/// <summary> /// This constructor should be called when a Node is updated, passing the NodeID and it's parent. This is a starting point /// </summary> /// <param name="ParentNodeID">The Parent Node id, this will be the primary root of the NodeItem Build</param> /// <param name="Settings">The Node Item Builder Settings</param> /// <param name="UseCurrentVersion">If the current version of the document should be used, should only be true if doing a Conflict check and not saving.</param> public NodeItem(int PageNodeID, NodeItemBuilderSettings Settings, bool UseCurrentVersion = false) { if (Settings.BuildSiblings) { // Start with Parent and build children, and children of the PageNodeID NodeID = DocumentHelper.GetDocuments().WhereEquals("NodeID", PageNodeID).CombineWithAnyCulture().FirstOrDefault().NodeParentID; if (NodeID <= 0) { NodeID = PageNodeID; } } else { // Start with the node, and only build itself and it's children children. NodeID = PageNodeID; } TreeNode Node = DocumentHelper.GetDocuments().WhereEquals("NodeID", NodeID).CombineWithAnyCulture().FirstOrDefault(); Parent = null; UrlSlugs = new List <NodeUrlSlug>(); IsContainer = Node.IsCoupled; ClassName = Node.ClassName; Children = new List <NodeItem>(); ChildrenBuilt = true; this.Settings = Settings; // Builds the slugs for itself BuildUrlSlugs(UseCurrentVersion); // This will possibly be something other than -1 only on the initial node based on settings. AlsoBuildNodeID = Settings.BuildSiblings ? PageNodeID : -1; }
/// <summary> /// Rebuilds the Routes for the given Node, optionally allows for settings to be passed /// </summary> /// <param name="NodeID">The NodeID</param> /// <param name="Settings">The Node Item Build Settings, if null will create settings based on the Node itself.</param> private static void RebuildRoutesByNode(int NodeID, NodeItemBuilderSettings Settings = null) { // If settings are not set, then get settings based on the given Node if (Settings == null) { // Get Site from Node TreeNode Page = DocumentHelper.GetDocuments() .WhereEquals("NodeID", NodeID) .Columns("NodeSiteID") .FirstOrDefault(); // Get Settings based on the Page itself Settings = GetNodeItemBuilderSettings(Page.NodeAliasPath, GetSite(Page.NodeSiteID).SiteName, true, false); } // Build and save NodeItem GivenNodeItem = new NodeItem(NodeID, Settings); if (ErrorOnConflict()) { // If error on conflict, everything MUST be done syncly. GivenNodeItem.BuildChildren(); if (GivenNodeItem.ConflictsExist()) { throw new UrlSlugCollisionException("Conflict Exists, aborting save"); } // Save changes GivenNodeItem.SaveChanges(); } else { // Do rest asyncly. QueueUpUrlSlugGeneration(GivenNodeItem); } }
/// <summary> /// Rebuilds all URL Routes for nodes which use this class across all sites. /// </summary> /// <param name="ClassName">The Class Name</param> public static void RebuildRoutesByClass(string ClassName) { DataClassInfo Class = GetClass(ClassName); foreach (string SiteName in SiteInfoProvider.GetSites().Select(x => x.SiteName)) { // Get NodeItemBuilderSettings NodeItemBuilderSettings BuilderSettings = GetNodeItemBuilderSettings(SiteName, true, true, true, true, true); // Build all, gather nodes of any Node that is of this type of class, check for updates. List <int> NodeIDs = DocumentHelper.GetDocuments() .WhereEquals("NodeClassID", Class.ClassID) .OnSite(new SiteInfoIdentifier(SiteName)) .CombineWithDefaultCulture() .Distinct() .Columns("NodeID") .OrderBy("NodeLevel, NodeOrder") .Select(x => x.NodeID) .ToList(); // Check all parent nodes for changes foreach (int NodeID in NodeIDs) { RebuildRoutesByNode(NodeID, BuilderSettings); } } }
/// <summary> /// Rebuilds all URL Routes on the given Site /// </summary> /// <param name="SiteName">The Site name</param> public static void RebuildRoutesBySite(string SiteName) { //EventLogProvider.LogInformation("DynamicRouteTesting", "SyncBuildStart", eventDescription: DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString()); // Get NodeItemBuilderSettings NodeItemBuilderSettings BuilderSettings = GetNodeItemBuilderSettings(SiteName, true, true, true, true, true); // Get root NodeID TreeNode RootNode = DocumentHelper.GetDocument(new NodeSelectionParameters() { AliasPath = "/", SiteName = SiteName }, new TreeProvider()); // Rebuild NodeItem tree structure, this will only affect the initial node syncly. NodeItem RootNodeItem = new NodeItem(RootNode.NodeID, BuilderSettings); if (ErrorOnConflict()) { // If error on conflict, everything MUST be done syncly. RootNodeItem.BuildChildren(); if (RootNodeItem.ConflictsExist()) { throw new UrlSlugCollisionException("Conflict Exists, aborting save"); } // Save changes RootNodeItem.SaveChanges(); } else { // Do rest asyncly. QueueUpUrlSlugGeneration(RootNodeItem); } //EventLogProvider.LogInformation("DynamicRouteTesting", "SyncBuildEnd", eventDescription: DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString()); }
/// <summary> /// Rebuilds all URL Routes for nodes which use this class across all sites. /// </summary> /// <param name="ClassName">The Class Name</param> public static void RebuildRoutesByClass(string ClassName) { DataClassInfo Class = GetClass(ClassName); foreach (string SiteName in SiteInfoProvider.GetSites().Select(x => x.SiteName)) { // Get NodeItemBuilderSettings, will be searching all children in case of changes. NodeItemBuilderSettings BuilderSettings = GetNodeItemBuilderSettings(SiteName, true, true, true, true, true); BuilderSettings.CheckQueueImmediately = false; // Build all, gather nodes of any Node that is of this type of class, check for updates. List <string> NodeAliasPathsToRemove = new List <string>(); List <string> NodeAliasPaths = DocumentHelper.GetDocuments() .WhereEquals("NodeClassID", Class.ClassID) .OnSite(new SiteInfoIdentifier(SiteName)) .CombineWithDefaultCulture() .Distinct() .PublishedVersion() .Columns("NodeAliasPath, NodeLevel, NodeOrder") .OrderBy("NodeLevel, NodeOrder") .Result.Tables[0].Rows.Cast <DataRow>().Select(x => (string)x["NodeAliasPath"]).ToList(); // Remove any NodeAliasPaths that are a descendent of a parent item, as they will be ran when the parent is checked. NodeAliasPaths.ForEach(x => { NodeAliasPathsToRemove.AddRange(NodeAliasPaths.Where(y => y.Contains(x) && x != y)); }); NodeAliasPaths = NodeAliasPaths.Except(NodeAliasPathsToRemove).ToList(); // Now convert NodeAliasPaths into NodeIDs List <int> NodeIDs = DocumentHelper.GetDocuments() .WhereEquals("NodeClassID", Class.ClassID) .WhereIn("NodeAliasPath", NodeAliasPaths) .OnSite(new SiteInfoIdentifier(SiteName)) .CombineWithDefaultCulture() .Distinct() .PublishedVersion() .Columns("NodeID, NodeLevel, NodeOrder") .OrderBy("NodeLevel, NodeOrder") .Result.Tables[0].Rows.Cast <DataRow>().Select(x => (int)x["NodeID"]).ToList(); // Check all parent nodes for changes foreach (int NodeID in NodeIDs) { RebuildRoutesByNode(NodeID, BuilderSettings); } // Now check queue to run tasks CheckUrlSlugGenerationQueue(); } }
/// <summary> /// Rebuilds the Routes for the given Node, optionally allows for settings to be passed /// </summary> /// <param name="NodeID">The NodeID</param> /// <param name="Settings">The Node Item Build Settings, if null will create settings based on the Node itself.</param> private static void RebuildRoutesByNode(int NodeID, NodeItemBuilderSettings Settings = null, bool CheckConflictOnly = false) { // If settings are not set, then get settings based on the given Node string NodeAliasPath = ""; if (Settings == null) { // Get Site from Node TreeNode Page = DocumentHelper.GetDocuments() .WhereEquals("NodeID", NodeID) .Columns("NodeSiteID, NodeAliasPath") .CombineWithAnyCulture() .FirstOrDefault(); NodeAliasPath = Page.NodeAliasPath; // Get Settings based on the Page itself Settings = GetNodeItemBuilderSettings(Page.NodeAliasPath, GetSite(Page.NodeSiteID).SiteName, true, false); } // Build and save NodeItem GivenNodeItem = new NodeItem(NodeID, Settings, CheckConflictOnly); if (ErrorOnConflict() || CheckConflictOnly) { // If error on conflict, everything MUST be done syncly. GivenNodeItem.BuildChildren(); if (GivenNodeItem.ConflictsExist()) { string Error = $"Could not save document at {NodeAliasPath} due to a conflict in the generated route:\n\r {string.Join("\n\r", GivenNodeItem.GetConflictItems())}"; EventLogProvider.LogEvent("E", "DynamicRouting", "Conflict Exists", eventDescription: Error); throw new UrlSlugCollisionException($"{Error} aborting save"); } // Save changes if not only checking conflict if (CheckConflictOnly) { return; } GivenNodeItem.SaveChanges(); } else { // Save main one GivenNodeItem.SaveChanges(false); // Do rest asyncly. QueueUpUrlSlugGeneration(GivenNodeItem, Settings.CheckQueueImmediately); } }
/// <summary> /// Rebuilds the node and all child node /// </summary> /// <param name="NodeID">The Node ID</param> public static void RebuildSubtreeRoutesByNode(int NodeID) { // Set up settings // Get Site from Node TreeNode Page = DocumentHelper.GetDocuments() .WhereEquals("NodeID", NodeID) .Columns("NodeSiteID") .FirstOrDefault(); // Get Settings based on the Page itself NodeItemBuilderSettings Settings = GetNodeItemBuilderSettings(Page.NodeAliasPath, GetSite(Page.NodeSiteID).SiteName, true, false); // Check all descendents Settings.BuildDescendents = true; Settings.CheckingForUpdates = false; RebuildRoutesByNode(NodeID, Settings); }
public NodeItem(NodeItem parent, TreeNode Node, NodeItemBuilderSettings Settings, bool BuildChildren = false) { NodeID = Node.NodeID; Parent = parent; UrlSlugs = new List <NodeUrlSlug>(); Children = new List <NodeItem>(); IsContainer = Node.IsCoupled; ClassName = Node.ClassName; this.Settings = Settings; // Build it's slugs BuildUrlSlugs(); // If build children, or settings to build descendents, or if an update was found, build children if (BuildChildren || Settings.BuildDescendents || HasUpdates) { this.BuildChildren(); } }
/// <summary> /// Rebuilds all URL Routes on the given Site /// </summary> /// <param name="SiteName">The Site name</param> public static void RebuildRoutesBySite(string SiteName) { //EventLogProvider.LogInformation("DynamicRouteTesting", "SyncBuildStart", eventDescription: DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString()); // Get NodeItemBuilderSettings NodeItemBuilderSettings BuilderSettings = GetNodeItemBuilderSettings(SiteName, true, true, true, true, true); // Get root NodeID TreeNode RootNode = DocumentHelper.GetDocuments() .Path("/", PathTypeEnum.Single) .OnSite(SiteName) .CombineWithAnyCulture() .FirstOrDefault(); // Rebuild NodeItem tree structure, this will only affect the initial node syncly. NodeItem RootNodeItem = new NodeItem(RootNode.NodeID, BuilderSettings); if (ErrorOnConflict()) { // If error on conflict, everything MUST be done syncly. RootNodeItem.BuildChildren(); if (RootNodeItem.ConflictsExist()) { EventLogProvider.LogEvent("E", "DynamicRouting", "Conflict Exists", eventDescription: $"Could not rebuild the site {SiteName}'s routes due to a conflict in the generated routes."); throw new UrlSlugCollisionException("Conflict Exists, aborting save"); } // Save changes RootNodeItem.SaveChanges(); } else { // Save itself and then queue up rest RootNodeItem.SaveChanges(false); // Do rest asyncly. QueueUpUrlSlugGeneration(RootNodeItem, BuilderSettings.CheckQueueImmediately); } //EventLogProvider.LogInformation("DynamicRouteTesting", "SyncBuildEnd", eventDescription: DateTime.Now.ToString() + " " + DateTime.Now.Millisecond.ToString()); }