/// <summary> /// Constructs an section. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties">The descriptor of this section.</param> /// <param name="expression">The expressio of this section.</param> public Section(IMansionContext context, IPropertyBag properties, IExpressionScript expression) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (properties == null) throw new ArgumentNullException("properties"); if (expression == null) throw new ArgumentNullException("expression"); // set values Properties = properties; Expression = expression; Id = Guid.NewGuid().ToString(); Name = Properties.Get<string>(context, "name"); ShouldBeRenderedOnce = !Properties.Get(context, "repeatable", true); TargetField = Properties.Get(context, "field", Name); // check if there is a requires property string requiresExpressionString; if (Properties.TryGet(context, "requires", out requiresExpressionString)) { // assemble the expression var expressionService = context.Nucleus.ResolveSingle<IExpressionScriptService>(); var requiresExpression = expressionService.Parse(context, new LiteralResource(requiresExpressionString)); // execute the expression areRequirementsSatisfied = requiresExpression.Execute<bool>; } else areRequirementsSatisfied = mansionContext => true; }
/// <summary> /// Initializes the given <paramref name="column"/>. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="column">The <see cref="PropertyColumn"/> which to initialze.</param> /// <param name="properties">The properties.</param> /// <exception cref="ArgumentNullException">Thrown if one of the parameters is null.</exception> protected static void Initialize(IMansionContext context, PropertyColumn column, IPropertyBag properties) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (column == null) throw new ArgumentNullException("column"); if (properties == null) throw new ArgumentNullException("properties"); // get the allow null flag column.AllowNullValue = properties.Get(context, "allowNullValue", false); // check if there is an expression string expressionString; if (properties.TryGet(context, "expression", out expressionString)) { var expressionService = context.Nucleus.ResolveSingle<IExpressionScriptService>(); column.HasExpression = true; column.Expression = expressionService.Parse(context, new LiteralResource(expressionString)); } // get the default value string defaultValue; if (properties.TryGet(context, "defaultValue", out defaultValue)) { var expressionService = context.Nucleus.ResolveSingle<IExpressionScriptService>(); var defaultValueExpression = expressionService.Parse(context, new LiteralResource(defaultValue)); column.DefaultValue = defaultValueExpression.Execute<object>(context); column.HasDefaultValue = true; } }
/// <summary> /// Populates the fullText property. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="modifiedProperties">The modified <see cref="IPropertyBag"/>.</param> /// <param name="originalProperties">The original <see cref="IPropertyBag"/>.</param> /// <exception cref="ArgumentNullException">Thrown if one of the parameters is null.</exception> public void Populate(IMansionContext context, IPropertyBag modifiedProperties, IPropertyBag originalProperties) { //validate arguments if (context == null) throw new ArgumentNullException("context"); if (modifiedProperties == null) throw new ArgumentNullException("modifiedProperties"); if (originalProperties == null) throw new ArgumentNullException("originalProperties"); // get all the properties over which to loop var properties = Properties.Get<string>(context, "properties").Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(property => property.Trim()); // assemble the content var buffer = new StringBuilder(); foreach (var property in properties) { // get the content for the given property String content; if (!modifiedProperties.TryGet(context, property, out content)) { if (!originalProperties.TryGet(context, property, out content)) continue; } // strip the HTML content = content.StripHtml(); // add it to the buffer buffer.AppendLine(content); } // if there is full-text content, add it to the full-text property, otherwise set it to null modifiedProperties.Set("fullText", buffer.Length > 0 ? buffer.ToString() : null); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // check if the property is not modified int newOrder; if (!modifiedProperties.TryGet(context, PropertyName, out newOrder)) return; // check if the record contains a pointer NodePointer pointer; if (!record.TryGet(context, "pointer", out pointer)) throw new InvalidOperationException("Could not update this record because it did not contain a pointer"); // don't update order for root nodes if (pointer.Depth == 1) return; // do not allow values smaller than 1 if (newOrder < 1) throw new InvalidOperationException("Can not set orders smaller than 1"); // assemble parameter var newOrderParameterName = queryBuilder.AddParameter("newOrder", newOrder, DbType.Int32); var oldOrderParameterName = queryBuilder.AddParameter("oldOrder", record.Get<int>(context, PropertyName), DbType.Int32); var parentIdParameterName = queryBuilder.AddParameter("parentId", pointer.Parent.Id, DbType.Int32); // update the orders before updating the order of the current node queryBuilder.PrependQuery(string.Format("UPDATE [Nodes] SET [order] = [order] + 1 WHERE (parentId = {0}) AND ([order] < {1} AND [order] >= {2})", parentIdParameterName, oldOrderParameterName, newOrderParameterName)); queryBuilder.PrependQuery(string.Format("UPDATE [Nodes] SET [order] = [order] - 1 WHERE (parentId = {0}) AND ([order] > {1} AND [order] <= {2})", parentIdParameterName, oldOrderParameterName, newOrderParameterName)); // update the column queryBuilder.AddColumnValue(PropertyName, newOrderParameterName); }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="node">The node which will be modified.</param> /// <param name="modifiedProperties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Node node, IPropertyBag modifiedProperties) { // if the name has not changed we are not interested string newName; if (!modifiedProperties.TryGet(context, "name", out newName)) return; // if the name has not changed after normalization we are not interested newName = TagUtilities.Normalize(newName); if (node.Pointer.Name.Equals(newName)) { modifiedProperties.Remove("name"); return; } modifiedProperties.Set("name", newName); // if the tag is renamed to another already existing tag, move all content to that existing tag and delete this one Node existingTag; var tagIndexNode = TagUtilities.RetrieveTagIndexNode(context); if (TagUtilities.TryRetrieveTagNode(context, tagIndexNode, newName, out existingTag)) { // TODO: move all content to the existing tag // TODO: delete this tag } }
/// <summary> /// Creates a filled nodeset. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties"></param> /// <param name="records"></param> public RecordSet(IMansionContext context, IPropertyBag properties, IEnumerable<Record> records) : base(properties) { // validate arguments if (records == null) throw new ArgumentNullException("records"); if (properties == null) throw new ArgumentNullException("properties"); // set values foreach (var node in records) RowCollection.Add(node); Set("count", RowCollection.Count); // check for paging var totalRowCount = properties.Get(context, "totalCount", -1); var pageNumber = properties.Get(context, "pageNumber", -1); var rowsPerPage = properties.Get(context, "pageSize", -1); if (totalRowCount != -1 && pageNumber != -1 && rowsPerPage != -1) SetPaging(totalRowCount, pageNumber, rowsPerPage); // check for sort string sortString; if (properties.TryGet(context, "sort", out sortString)) { foreach (var sort in Collections.Sort.Parse(sortString)) AddSort(sort); } }
/// <summary> /// Tries to revive the user based on the revival properties. /// </summary> /// <param name="context">The security context.</param> /// <param name="revivalProperties">The revival properties.</param> /// <returns>Returns the revived <see cref="UserState"/> or null.</returns> public override UserState ReviveUser(IMansionContext context, IPropertyBag revivalProperties) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (revivalProperties == null) throw new ArgumentNullException("revivalProperties"); // get the id of the from the revival properties Guid id; if (!revivalProperties.TryGet(context, "id", out id)) return null; // retrieve the user by guid var userNode = context.Repository.RetrieveSingleNode(context, new PropertyBag { {"baseType", "User"}, {"guid", id}, {"status", "any"}, {"bypassAuthorization", true}, {"cache", false}, {StorageOnlyQueryComponent.PropertyKey, true} }); if (userNode == null) return null; // create and return the user state return CreateUserState(context, userNode); }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { // get the variables string currentTheme; var hasCurrentTheme = record.TryGet(context, "theme", out currentTheme) && !string.IsNullOrEmpty(currentTheme); string newTheme; var hasNewTheme = properties.TryGet(context, "theme", out newTheme) && !string.IsNullOrEmpty(newTheme); // do nothing when the page does not have a theme yet if (!hasCurrentTheme) return; // retrieve the schema of the current theme var currentThemeSchema = ColumnSchema.GetSchema(context, currentTheme); // retrieve the blocks of this page var repository = context.Repository; var blockNodeset = repository.RetrieveNodeset(context, new PropertyBag { {"baseType", "Block"}, {"parentSource", record} }); // check if a new theme is selected if (hasNewTheme) { // retrieve the schema of the new theme var newThemeSchema = ColumnSchema.GetSchema(context, newTheme); // loop through the blocks to find obsolete ones foreach (var blockNode in blockNodeset.Nodes) { // get the column of this block var column = blockNode.Get<string>(context, "column"); // check if this block lived in the old theme if (!currentThemeSchema.ContainsColumn(column)) continue; // check if the column exists in the new theme as well if (newThemeSchema.ContainsColumn(column)) continue; // block is obsolete delete it repository.DeleteNode(context, blockNode); } } else { // theme is removed, delete all the theme blocks foreach (var blockNode in blockNodeset.Nodes.Where(candidate => currentThemeSchema.ContainsColumn(candidate.Get<string>(context, "column")))) repository.DeleteNode(context, blockNode); } base.DoBeforeUpdate(context, record, properties); }
/// <summary> /// Gets the row. /// </summary> /// <param name="context">The request context.</param> /// <param name="attributes">The attributes of this tag.</param> /// <returns>Returns the result.</returns> protected override IPropertyBag Get(IMansionContext context, IPropertyBag attributes) { // get the url Url url; if (!attributes.TryGet(context, "url", out url)) url = context.Cast<IMansionWebContext>().Request.RequestUrl; // return the property bag representation return url.ToPropertyBag(); }
/// <summary> /// This method is called just before a node is created by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties">The new properties of the node.</param> protected override void DoBeforeCreate(IMansionContext context, IPropertyBag properties) { // check if the layout is set string layout; if (properties.TryGet(context, "layout", out layout)) return; // set the layout properties.TrySet("layout", layout); }
/// <summary> /// This method is called just before a node is created by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="parent">The parent node to which the new child will be added.</param> /// <param name="newProperties">The new properties of the node.</param> protected override void DoBeforeCreate(IMansionContext context, Node parent, IPropertyBag newProperties) { // check if the layout is set string layout; if (newProperties.TryGet(context, "layout", out layout)) return; if (!parent.TryGet(context, "layout", out layout)) layout = "OneColumnLayout"; // set the layout newProperties.TrySet("layout", layout); }
/// <summary> /// Gets a value from the script stack. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="propertyBag">The <see cref="IPropertyBag"/> from which to get the property.</param> /// <param name="propertyName">The name of the property from which to get the value.</param> /// <param name="defaultValue">The default value which to return in case the <paramref name="propertyBag"/> does not contain <paramref name="propertyName"/>.</param> /// <returns>Returns the value of the specified property.</returns> public object Evaluate(IMansionContext context, IPropertyBag propertyBag, string propertyName, object defaultValue) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (propertyBag == null) throw new ArgumentNullException("propertyBag"); if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName"); // get the property object obj; return !propertyBag.TryGet(context, propertyName, out obj) ? defaultValue : obj; }
public bool TryGet(string name, out Jint.Native.Descriptor descriptor) { if (lastAccessed != null && lastAccessed.Name == name) { descriptor = lastAccessed; return(true); } bool result = bag.TryGet(name, out descriptor); if (result) { lastAccessed = descriptor; } return(result); }
/// <summary> /// Gets a value from the given propertybag. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="propertyBag">The <see cref="IPropertyBag"/> from which to get the property.</param> /// <param name="propertyName">The name of the property from which to get the value.</param> /// <returns>Returns the value of the specified property.</returns> public object Evaluate(IMansionContext context, IPropertyBag propertyBag, string propertyName) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (propertyBag == null) throw new ArgumentNullException("propertyBag"); if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName"); // get the property object obj; if (!propertyBag.TryGet(context, propertyName, out obj)) throw new InvalidOperationException(string.Format("Does not contain property '{0}'", propertyName)); return obj; }
/// <summary> /// Builds and executes the query. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="arguments">The arguments from which to build the query.</param> /// <param name="repository">The <see cref="IRepository"/>.</param> /// <param name="parser">The <see cref="IQueryParser"/>.</param> /// <returns>Returns the result.</returns> protected override Record Retrieve(IMansionContext context, IPropertyBag arguments, IRepository repository, IQueryParser parser) { // get the url Url url; if (!arguments.TryGet(context, "url", out url)) url = context.Cast<IMansionWebContext>().Request.RequestUrl; // parse the query var query = parser.Parse(context, new PropertyBag { {"baseType", "Site"}, {"hostHeaders", url.HostName} }); // execute the query return repository.RetrieveSingleNode(context, query); }
/// <summary> /// Builds and executes the query. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="arguments">The arguments from which to build the query.</param> /// <param name="repository">The <see cref="IRepository"/>.</param> /// <param name="parser">The <see cref="IQueryParser"/>.</param> /// <returns>Returns the result.</returns> protected override Record Retrieve(IMansionContext context, IPropertyBag arguments, IRepository repository, IQueryParser parser) { // get the url Url url; if (!arguments.TryGet(context, "url", out url)) url = context.Cast<IMansionWebContext>().Request.RequestUrl; // parse the URL for identifiers IPropertyBag queryAttributes; if (!nodeUrlService.TryExtractQueryParameters(context.Cast<IMansionWebContext>(), url, out queryAttributes)) return null; // parse the query var query = parser.Parse(context, queryAttributes); // execute the query return repository.RetrieveSingleNode(context, query); }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { base.DoBeforeUpdate(context, record, properties); // check if the identifier was updated string identifier; if (!properties.TryGet(context, "identifier", out identifier)) return; identifier = identifier.Trim().ToLower(); properties.Set("identifier", identifier); // only update the name with the identifier if the previous name was also derived from the identifier if (record.Get(context, "name", string.Empty).Equals(record.Get(context, "identifier", string.Empty))) { var name = properties.Get(context, "name", identifier).Trim().ToLower(); properties.Set("name", name); } }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="node">The node which will be modified.</param> /// <param name="modifiedProperties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Node node, IPropertyBag modifiedProperties) { // check if the layout was not modified string newLayoutName; if (!modifiedProperties.TryGet(context, "layout", out newLayoutName)) return; // check if there was no old layout string oldLayoutName; if (!node.TryGet(context, "layout", out oldLayoutName)) return; // get the schemas var newColumnSchema = ColumnSchema.GetSchema(context, newLayoutName); var oldColumnSchema = ColumnSchema.GetSchema(context, oldLayoutName); // retrieve the blocks of this page var repository = context.Repository; var blockNodeset = repository.Retrieve(context, repository.ParseQuery(context, new PropertyBag { {"baseType", "Block"}, {"parentSource", node} })); // loop through all the nodes foreach (var blockNode in blockNodeset.Nodes) { // check if this block was not in a column of the old schema so it wont have to move to the new schema var columnName = blockNode.Get<string>(context, "column"); if (!oldColumnSchema.ContainsColumn(columnName)) continue; // check if the column is in the new schema as well so it wont have to move if (newColumnSchema.ContainsColumn(columnName)) continue; // move the block to the default column repository.Update(context, blockNode, new PropertyBag { {"column", newColumnSchema.DefaultColumn} }); } }
/// <summary> /// This method is called just before a node is updated by the repository. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record"> </param> /// <param name="properties">The updated properties of the node.</param> protected override void DoBeforeUpdate(IMansionContext context, Record record, IPropertyBag properties) { base.DoBeforeUpdate(context, record, properties); // check if the preferred term has changed Guid newPreferredTermGuid; if (!properties.TryGet(context, "preferredTermGuid", out newPreferredTermGuid)) return; // delete the old link if it exists var recordGuidString = record.Get<string>(context, "guid"); Guid currentPreferredTermGuid; if (record.TryGet(context, "preferredTermGuid", out currentPreferredTermGuid) && currentPreferredTermGuid != Guid.Empty) { // retrieve the old record var currentPreferredTermNode = context.Repository.RetrieveSingleNode(context, currentPreferredTermGuid); // remove the link, if the target was found if (currentPreferredTermNode != null) { // store the guid in the synonymGuids field context.Repository.UpdateNode(context, currentPreferredTermNode, new PropertyBag { {"synonymGuids", currentPreferredTermNode.Get(context, "synonymGuids", string.Empty).RemoveNeedle(recordGuidString)} }); } } // check if there is no new synonym if (newPreferredTermGuid == Guid.Empty) return; // retrieve the preferredTermNode var newPreferredTermNode = context.Repository.RetrieveSingleNode(context, newPreferredTermGuid); if (newPreferredTermNode == null) return; // store the guid in the synonymGuids field context.Repository.UpdateNode(context, newPreferredTermNode, new PropertyBag { {"synonymGuids", newPreferredTermNode.Get(context, "synonymGuids", string.Empty).AppendNeedle(recordGuidString)} }); }
/// <summary> /// Renders the specified <paramref name="blockProperties"/> to the output pipe. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="blockProperties">The <see cref="IPropertyBag"/> of the block which to render.</param> /// <param name="targetField">The name of the field to which to render.</param> protected override void DoRender(IMansionContext context, IPropertyBag blockProperties, string targetField) { // first retrieve the block node to display Guid displayedBlockGuid; if (!blockProperties.TryGet(context, "blockGuid", out displayedBlockGuid)) throw new InvalidOperationException("Block guid not found for shared block display"); var displayedBlockNode = context.Repository.RetrieveSingleNode(context, new PropertyBag { {"guid", displayedBlockGuid} }); if (displayedBlockNode == null) throw new InvalidOperationException(string.Format("Could not find block with guid '{0}'", displayedBlockGuid)); // second, merge the two block properties together var mergedBlockProperties = new PropertyBag(); mergedBlockProperties.Merge(blockProperties); mergedBlockProperties.Merge(displayedBlockNode); mergedBlockProperties.Set("id", blockProperties.Get<int>(context, "id")); // finally re-render the combined block using the portal service PortalService.RenderBlock(context, mergedBlockProperties, targetField); }
/// <summary> /// Retrieves the properties as a dictionary. /// </summary> /// <param name="propertyBag">The property bag.</param> /// <returns>A dictionary containing all of the properties in the bag.</returns> /// <remarks> /// <para> /// The types of the individual entries will either be .NET primitive types (e.g. int, string, etc) or further /// <see cref="IPropertyBag"/>s. Any arrays in the source <see cref="IPropertyBag"/> will be added to the /// dictionary as arrays of <see cref="object"/>, with array elements being further .NET primitive types of /// <see cref="IPropertyBag"/>s. /// </para> /// </remarks> public static IReadOnlyDictionary <string, object> AsDictionary(this IPropertyBag propertyBag) { if (propertyBag is not IEnumerable <(string Key, PropertyBagEntryType Type)> items) { throw new ArgumentException($"Only property bags that implement {nameof(IEnumerable<(string Key, PropertyBagEntryType Type)>)} can be converted to dictionaries"); } var dictionary = new Dictionary <string, object>(); // Now for each item in the dictionary we need to check that it's either // 1. A scalar type // 2. An IPropertyBag // 3. An array of 1. or 2. // The initial call to properties.ToObject<T>() will have given us a dictionary containing either scalars // or JTokens. We need to look for the JTokens and process them appropriately. foreach ((string key, PropertyBagEntryType type) in items) { T RequireItem <T>(string key) => propertyBag.TryGet <T>(key, out T result) ? result : throw new InvalidOperationException($"Property bag advertised entry {key} of type {typeof(T).Name} during enumeration, but TryGet for that entry failed"); object value = type switch { PropertyBagEntryType.Null => throw new ArgumentException("Cannot return a dictionary with non-null value type when the bag contains null values"), PropertyBagEntryType.String => RequireItem <string>(key), PropertyBagEntryType.Boolean => RequireItem <bool>(key), PropertyBagEntryType.Integer => RequireItem <long>(key), PropertyBagEntryType.Decimal => RequireItem <double>(key), PropertyBagEntryType.Array => RequireItem <object[]>(key), PropertyBagEntryType.Object => RequireItem <IPropertyBag>(key), _ => throw new InvalidOperationException($"Bag reported entry of unrecognized type: {type}"), }; dictionary.Add(key, value); } return(dictionary); }
public virtual bool HasOwnProperty(string key) { Descriptor desc; return(properties.TryGet(key, out desc)); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // allow update of relational column on special cases, most likely used when fixing the repository integrity if (modifiedProperties.Get(context, "_allowRelationPropertiesUpdate", false)) { string name; if (modifiedProperties.TryGet(context, "name", out name)) queryBuilder.AddColumnValue("name", name, DbType.String); string type; if (modifiedProperties.TryGet(context, "type", out type)) queryBuilder.AddColumnValue("type", type, DbType.String); int depth; if (modifiedProperties.TryGet(context, "depth", out depth)) queryBuilder.AddColumnValue("depth", depth, DbType.Int32); int parentId; if (modifiedProperties.TryGet(context, "parentId", out parentId)) queryBuilder.AddColumnValue("parentId", parentId, DbType.Int32); string parentPointer; if (modifiedProperties.TryGet(context, "parentPointer", out parentPointer)) queryBuilder.AddColumnValue("parentPointer", parentPointer, DbType.String); string parentPath; if (modifiedProperties.TryGet(context, "parentPath", out parentPath)) queryBuilder.AddColumnValue("parentPath", parentPath, DbType.String); string parentStructure; if (modifiedProperties.TryGet(context, "parentStructure", out parentStructure)) queryBuilder.AddColumnValue("parentStructure", parentStructure, DbType.String); return; } // make sure the relational intgrety is not comprimised if (modifiedProperties.Names.Intersect(ReservedPropertyName, StringComparer.OrdinalIgnoreCase).Any()) throw new InvalidOperationException("The relational properties can not be changed"); // get the pointer NodePointer pointer; if (!record.TryGet(context, "pointer", out pointer)) throw new InvalidOperationException("Could not update this record because it did not contain a pointer"); // add the id an pointer parameters var idParameterName = queryBuilder.AddParameter("id", pointer.Id, DbType.Int32); var pointerParameterName = queryBuilder.AddParameter("pointer", pointer.PointerString + "-%", DbType.String); // check if the name changed string newName; if (modifiedProperties.TryGetAndRemove(context, "name", out newName)) { newName = newName.Trim(); if (string.IsNullOrEmpty(newName)) throw new InvalidOperationException("Can not update column name with empty string"); if (newName.Contains(NodePointer.PathSeparator)) throw new InvalidOperationException(string.Format("Name '{0}' contains invalid characters", newName)); if (!pointer.Name.Equals(newName)) { // add the name column modification queryBuilder.AddColumnValue("name", newName, DbType.String); // update the paths var oldPathLengthParameterName = queryBuilder.AddParameter("oldPathLength", pointer.PathString.Length + 1, DbType.String); var newPathParameterName = queryBuilder.AddParameter("newPath", NodePointer.Rename(pointer, newName).PathString + NodePointer.PathSeparator, DbType.String); queryBuilder.AppendQuery(string.Format(@" UPDATE [Nodes] SET [parentPath] = {0} + RIGHT( [parentPath], LEN( [parentPath] ) - {1} ) WHERE ( [parentId] = {2} OR [parentPointer] LIKE {3} )", newPathParameterName, oldPathLengthParameterName, idParameterName, pointerParameterName)); } } // check if the type changed string newType; if (modifiedProperties.TryGetAndRemove(context, "type", out newType)) { newType = newType.Trim(); if (string.IsNullOrEmpty(newType)) throw new InvalidOperationException("Can not update column type with empty string"); if (newType.Contains(NodePointer.StructureSeparator)) throw new InvalidOperationException(string.Format("Type '{0}' contains invalid characters", newType)); if (!string.IsNullOrEmpty(newType) && !pointer.Type.Equals(newType, StringComparison.OrdinalIgnoreCase)) { // add the name column modification queryBuilder.AddColumnValue("type", newType, DbType.String); // update the structures var newStructureParameterName = queryBuilder.AddParameter("newStructure", NodePointer.ChangeType(pointer, newType).StructureString + NodePointer.StructureSeparator, DbType.String); var oldStructureLengthParameterName = queryBuilder.AddParameter("oldStructureLength", pointer.StructureString.Length + 1, DbType.Int32); queryBuilder.AppendQuery(string.Format("UPDATE [Nodes] SET [parentStructure] = {0} + RIGHT( [parentStructure], LEN( [parentStructure] ) - {1} ) WHERE ( [parentId] = {2} OR [parentPointer] LIKE {3} )", newStructureParameterName, oldStructureLengthParameterName, idParameterName, pointerParameterName)); } } }
/// <summary> /// Manages the tags. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties">The new properties.</param> /// <returns>A CSV of all the tag names.</returns> public static string ToNames(IMansionContext context, IPropertyBag properties) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (properties == null) throw new ArgumentNullException("properties"); var tagNames = string.Empty; // retrieve the guids string tagGuids; if (properties.TryGet(context, "tagGuids", out tagGuids) && !string.IsNullOrEmpty(tagGuids)) { // retrieve the tag index node var tagIndexNode = RetrieveTagIndexNode(context); // retrieve the tags by their guid var tagNodes = context.Repository.RetrieveNodeset(context, new PropertyBag { {"parentSource", tagIndexNode}, {"guid", tagGuids} }); // assemble the tag names tagNames = string.Join(", ", tagNodes.Nodes.Select(x => x.Pointer.Name)); } return tagNames; }
/// <summary> /// Writes <paramref name="values"/> to the output. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="values">The <see cref="IPropertyBag"/> containing the values which to write.</param> public void Write(IMansionContext context, IPropertyBag values) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (values == null) throw new ArgumentNullException("values"); CheckDisposed(); // write out the values for (var index = 0; index < format.ColumnProperties.Length; index++) { // write out the current value when there is one string value; if (values.TryGet(context, format.ColumnProperties[index], out value)) { outputPipe.Writer.Write(format.TextQualifier); outputPipe.Writer.Write(value); outputPipe.Writer.Write(format.TextQualifier); } // write out the column or row delimitor outputPipe.Writer.Write(index == (format.ColumnProperties.Length - 1) ? format.RowDelimitor : format.ColumnDelimitor); } }
/// <summary> /// Requests this voter to cast a vote. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="subject">The subject.</param> /// <returns>Returns the result of the vote.</returns> protected override VoteResult DoVote(IMansionContext context, IPropertyBag subject) { // check if a path is specified string type; return subject.TryGet(context, "type", out type) ? VoteResult.MediumInterest : VoteResult.Refrain; }
/// <summary> /// Gets the row. /// </summary> /// <param name="context">The request context.</param> /// <param name="attributes">The attributes of this tag.</param> /// <returns>Returns the result.</returns> protected override IPropertyBag Get(IMansionContext context, IPropertyBag attributes) { // get the web request context var webRequest = context.Cast<IMansionWebContext>(); // get the url Url url; if (!attributes.TryGet(context, "url", out url)) url = webRequest.Request.RequestUrl; // get the area prefix var routeProperties = new PropertyBag(); // if the request was forwarded from a 404, do not parse the route string forwardedFrom404; if (webRequest.Request.Headers.TryGetValue(Constants.ForwardedFrom404HeaderKey, out forwardedFrom404)) { routeProperties.Set("controller", "404"); routeProperties.Set("action", "NotFound"); return routeProperties; } // get the route index var routeUrlIndex = Array.FindIndex(url.PathSegments, x => x.Equals(Constants.RouteUrlPrefix, StringComparison.OrdinalIgnoreCase)); // check if this is no route url if (routeUrlIndex == -1) { // this is no route URL, default controller and action routeProperties.Set("area", GetAttribute<string>(context, "defaultArea")); routeProperties.Set("controller", GetAttribute<string>(context, "defaultController")); routeProperties.Set("action", GetAttribute<string>(context, "defaultAction")); return routeProperties; } // determine the number of route url parts var parameterRouteUrlIndex = Array.FindIndex(url.PathSegments, x => x.Equals(Constants.RouteParameterPrefix, StringComparison.OrdinalIgnoreCase)); var routeUrlPartLength = (parameterRouteUrlIndex != -1 ? parameterRouteUrlIndex : url.PathSegments.Length) - routeUrlIndex; // parse the route parts if (routeUrlIndex != -1 && routeUrlPartLength == 4) { // route url with area routeProperties.Set("area", GetSegment(url, routeUrlIndex + 1)); routeProperties.Set("controller", GetSegment(url, routeUrlIndex + 2)); routeProperties.Set("action", GetSegment(url, routeUrlIndex + 3)); } else if (routeUrlIndex != -1 && routeUrlPartLength == 3) { // route url without area routeProperties.Set("controller", GetSegment(url, routeUrlIndex + 1)); routeProperties.Set("action", GetSegment(url, routeUrlIndex + 2)); } else { // unknown route type throw new InvalidOperationException(string.Format("'{0}' is an invalid route url", url)); } // parse parameters if any if (parameterRouteUrlIndex > -1) { // set all the parameters for (var paremeterIndex = parameterRouteUrlIndex + 1; paremeterIndex < url.PathSegments.Length; paremeterIndex++) routeProperties.Set("routeParameter" + ((paremeterIndex - parameterRouteUrlIndex) - 1), GetSegment(url, paremeterIndex)); } // return the route return routeProperties; }
/// <summary> /// Generates the update statement for this table. /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // create identity parameter var idParameterName = queryBuilder.AddParameter("id", record.Id, DbType.Int32); // loop through all the properties foreach (var propertyName in Columns.Select(column => column.PropertyName)) { // check if the property is modified string rawModifiedValue; if (!modifiedProperties.TryGet(context, propertyName, out rawModifiedValue)) continue; // get the current values var currentValues = GetCurrentValues(queryBuilder.Command, record, propertyName).ToList(); // check if there are new properties var modifiedValues = (rawModifiedValue ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToArray(); // get the deleted values var deletedValues = currentValues.Except(modifiedValues, StringComparer.OrdinalIgnoreCase); var newValues = modifiedValues.Except(currentValues, StringComparer.OrdinalIgnoreCase); // create property parameter var propertyParameterName = queryBuilder.AddParameter(propertyName, propertyName, DbType.String); // generate the delete statements foreach (var deletedValue in deletedValues) { // build the query var valueModificationQuery = new ModificationQueryBuilder(queryBuilder); // build clause var valueParameterName = valueModificationQuery.AddParameter("value", deletedValue, DbType.String); valueModificationQuery.AppendWhereClause("[id] = " + idParameterName + " AND [name] = " + propertyParameterName + " AND [value] = " + valueParameterName); // append the query queryBuilder.AppendQuery(valueModificationQuery.ToDeleteStatement(Name)); } // generate the insert statements foreach (var newValue in newValues) { // build the query var valueModificationQuery = new ModificationQueryBuilder(queryBuilder); // set column values valueModificationQuery.AddColumnValue("id", idParameterName); valueModificationQuery.AddColumnValue("name", propertyParameterName); valueModificationQuery.AddColumnValue("value", newValue, DbType.String); // append the query queryBuilder.AppendQuery(valueModificationQuery.ToInsertStatement(Name)); } } }
/// <summary> /// Gets the <see cref="RecordListener"/>s for type <paramref name="record"/>. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="record">The <see cref="Record"/> for which to get the type.</param> /// <param name="overrideProperties">The overriding properties, might be null.</param> /// <returns>Returns the listeners for this <paramref name="record"/>.</returns> private List<RecordListener> GetListeners(IMansionContext context, Record record, IPropertyBag overrideProperties = null) { // retrieve the record type var recordListeners = GetListeners(context, record.Type); // retrieve the type override, if any ITypeDefinition overrideType; if (overrideProperties == null || !overrideProperties.TryGet(context, "type", out overrideType)) return recordListeners.ToList(); // retrieve the override listeners var overrideListeners = GetListeners(overrideType); // merge the listeners return recordListeners.Union(overrideListeners).ToList(); }
/// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="queryBuilder"></param> /// <param name="record"> </param> /// <param name="modifiedProperties"></param> protected override void DoToUpdateStatement(IMansionContext context, ModificationQueryBuilder queryBuilder, Record record, IPropertyBag modifiedProperties) { // check if the property is not modified object input; if (!modifiedProperties.TryGet(context, PropertyName, out input)) return; // determine the value var value = GetValue(context, input); // add the parameter var parameterName = queryBuilder.AddParameter(ColumnName, value); // set the column value queryBuilder.AddColumnValue(ColumnName, parameterName); }
/// <summary> /// Parses the <paramref name="properties"/> into a <see cref="IResourcePath"/>. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties">The properties which to parse.</param> /// <returns>Returns the parsed <see cref="IResourcePath"/>.</returns> public IResourcePath ParsePath(IMansionContext context, IPropertyBag properties) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (properties == null) throw new ArgumentNullException("properties"); // get the resource base path var categoryBasePath = properties.Get(context, "category", "Temp"); // check if it is an existing resource string relativePath; if (properties.TryGet(context, "relativePath", out relativePath)) return new ContentResourcePath(relativePath); // check if it is a new file name string fileName; if (properties.TryGet(context, "fileName", out fileName)) { // get the current date var today = DateTime.Today; // get the file base name and extension var fileBaseName = Path.GetFileNameWithoutExtension(fileName); var fileExtension = Path.GetExtension(fileName); // make sure the file name is unique var index = 0; while (File.Exists(ResourceUtils.Combine(physicalBasePath, relativeBasePath, categoryBasePath, today.Year.ToString(CultureInfo.InvariantCulture), today.Month.ToString(CultureInfo.InvariantCulture), fileBaseName + index + fileExtension))) index++; // create the resource path return new ContentResourcePath(ResourceUtils.Combine(categoryBasePath, today.Year.ToString(CultureInfo.InvariantCulture), today.Month.ToString(CultureInfo.InvariantCulture), fileBaseName + index + fileExtension)); } // unkonwn type throw new InvalidOperationException("Could not identify resource path"); }
/// <summary> /// Manages the tags. /// </summary> /// <param name="context">The <see cref="IMansionContext"/>.</param> /// <param name="properties">The new properties.</param> public static void ToGuids(IMansionContext context, IPropertyBag properties) { // validate arguments if (context == null) throw new ArgumentNullException("context"); if (properties == null) throw new ArgumentNullException("properties"); // get the tag name string string tagNameString; if (!properties.TryGet(context, "_tags", out tagNameString)) return; // normalize the tag names var tagNames = NormalizeNames(tagNameString).ToList(); // retrieve the tag index node var tagIndexNode = RetrieveTagIndexNode(context); // loop over all the tag names var tagNodes = tagNames.Select(tagName => RetrieveTagNode(context, tagIndexNode, tagName)); // set the new tag guids properties.Set("tagGuids", string.Join(",", tagNodes.Select(x => x.PermanentId))); properties.Remove("_tags"); }