Example #1
0
 private void LogTask_Before(object sender, StagingLogTaskEventArgs e)
 {
     if (e.Task.TaskTitle.IndexOf("Update Url Slug", StringComparison.InvariantCultureIgnoreCase) == 0)
     {
         // Update the TItle
         UrlSlugInfo UrlSlug  = (UrlSlugInfo)e.Object;
         var         DocQuery = DocumentHelper.GetDocuments()
                                .WhereEquals("nodeID", UrlSlug.UrlSlugNodeID)
                                .Columns("NodeAlias, DocumentCulture");
         if (!string.IsNullOrWhiteSpace(UrlSlug.UrlSlugCultureCode))
         {
             DocQuery.Culture(UrlSlug.UrlSlugCultureCode);
         }
         else
         {
             DocQuery.CombineWithDefaultCulture();
             DocQuery.CombineWithAnyCulture();
         }
         var Node = DocQuery.FirstOrDefault();
         if (UrlSlug.UrlSlugIsCustom)
         {
             e.Task.TaskTitle = $"Add Custom Url Slug '{UrlSlug.UrlSlug}' for page {Node.NodeAlias} [{Node.DocumentCulture}]";
         }
         else
         {
             e.Task.TaskTitle = $"Restore Url Slug for page {Node.NodeAlias} [{Node.DocumentCulture}] to default";
         }
     }
 }
Example #2
0
        private void UrlSlug_Insert_After(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo UrlSlug = (UrlSlugInfo)e.Object;

            // Staging task should not be created, add entry so this task won't be generated
            UrlSlugStagingTaskIgnoreInfoProvider.SetUrlSlugStagingTaskIgnoreInfo(new UrlSlugStagingTaskIgnoreInfo()
            {
                UrlSlugStagingTaskIgnoreUrlSlugID = UrlSlug.UrlSlugID
            });
        }
        private void UrlSlug_Update_Before_IsCustomRebuild(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo UrlSlug = (UrlSlugInfo)e.Object;

            // If the Url Slug is custom or was custom, then need to rebuild after.
            if (UrlSlug.UrlSlugIsCustom || ValidationHelper.GetBoolean(UrlSlug.GetOriginalValue("UrlSlugIsCustom"), UrlSlug.UrlSlugIsCustom))
            {
                // Add hook so the Url Slug will be re-rendered after it's updated
                RecursionControl Trigger = new RecursionControl("UrlSlugNoLongerCustom_" + UrlSlug.UrlSlugGuid);
                var Triggered            = Trigger.Continue;
            }
        }
Example #4
0
        private void UrlSlug_Update_Before(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo UrlSlug = (UrlSlugInfo)e.Object;
            // save previous Url to 301 redirects
            // Get DocumentID
            var Document = DocumentHelper.GetDocuments()
                           .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                           .CombineWithDefaultCulture()
                           .CombineWithAnyCulture()
                           .Culture(UrlSlug.UrlSlugCultureCode)
                           .FirstOrDefault();
            var AlternativeUrl = AlternativeUrlInfoProvider.GetAlternativeUrls()
                                 .WhereEquals("AlternativeUrlUrl", UrlSlug.UrlSlug)
                                 .FirstOrDefault();

            if (AlternativeUrl != null)
            {
                if (AlternativeUrl.AlternativeUrlDocumentID != Document.DocumentID)
                {
                    // If Same NodeID, then replace the DocumentID with the current one as now the document has the culture code.
                    var AlternativeUrlDocument = DocumentHelper.GetDocument(AlternativeUrl.AlternativeUrlDocumentID, new TreeProvider());
                    if (AlternativeUrlDocument.NodeID == UrlSlug.UrlSlugNodeID)
                    {
                        AlternativeUrl.AlternativeUrlDocumentID = Document.DocumentID;
                        AlternativeUrlInfoProvider.SetAlternativeUrlInfo(AlternativeUrl);
                    }
                    else
                    {
                        // Log
                        EventLogProvider.LogEvent("W", "DynamicRouting", "AlternativeUrlConflict", eventDescription: string.Format("Could not create Alternative Url '{0}' for Document {1} [{2}] because it already exists as an Alternative Url for Document {3} [{4}]",
                                                                                                                                   AlternativeUrl.AlternativeUrlUrl,
                                                                                                                                   Document.NodeAliasPath,
                                                                                                                                   Document.DocumentCulture,
                                                                                                                                   AlternativeUrlDocument.NodeAliasPath,
                                                                                                                                   AlternativeUrlDocument.DocumentCulture
                                                                                                                                   ));
                    }
                }
            }
            else
            {
                // Create new one
                AlternativeUrl = new AlternativeUrlInfo()
                {
                    AlternativeUrlDocumentID = Document.DocumentID,
                    AlternativeUrlSiteID     = Document.NodeSiteID,
                };
                AlternativeUrl.SetValue("AlternativeUrlUrl", UrlSlug.UrlSlug);
                AlternativeUrlInfoProvider.SetAlternativeUrlInfo(AlternativeUrl);
            }
        }
Example #5
0
        private void StagingTask_ProcessTask_Before(object sender, StagingSynchronizationEventArgs e)
        {
            if (e.ObjectType.Equals(UrlSlugInfo.OBJECT_TYPE, StringComparison.InvariantCultureIgnoreCase))
            {
                // Get the URL slug itself
                UrlSlugInfo UrlSlug   = new UrlSlugInfo(e.TaskData.Tables[0].Rows[0]);
                int         NewNodeID = TranslateBindingTranslateID(UrlSlug.UrlSlugNodeID, e.TaskData, "cms.node");
                // Get the Site's current Url Slug
                UrlSlugInfo CurrentUrlSlug = UrlSlugInfoProvider.GetUrlSlugs()
                                             .WhereEquals("UrlSlugNodeID", NewNodeID)
                                             .WhereEquals("UrlSlugCultureCode", UrlSlug.UrlSlugCultureCode)
                                             .FirstOrDefault();

                bool UpdateCurrentUrlSlug = false;
                if (UrlSlug.UrlSlugIsCustom)
                {
                    if (!CurrentUrlSlug.UrlSlugIsCustom)
                    {
                        CurrentUrlSlug.UrlSlugIsCustom = true;
                        UpdateCurrentUrlSlug           = true;
                    }
                    if (CurrentUrlSlug.UrlSlug != UrlSlug.UrlSlug)
                    {
                        CurrentUrlSlug.UrlSlug = UrlSlug.UrlSlug;
                        UpdateCurrentUrlSlug   = true;
                    }
                }
                else
                {
                    if (CurrentUrlSlug.UrlSlugIsCustom)
                    {
                        CurrentUrlSlug.UrlSlugIsCustom = false;
                        UpdateCurrentUrlSlug           = true;
                    }
                }
                if (UpdateCurrentUrlSlug)
                {
                    UrlSlugInfoProvider.SetUrlSlugInfo(CurrentUrlSlug);
                }
                e.TaskHandled = true;
            }
        }
        public static object ParentUrl(EvaluationContext context, params object[] parameters)
        {
            // Based on the Macro Resolver which has the TreeNode Data, return the ParentUrl
            int    NodeID         = ValidationHelper.GetInteger(context.Resolver.ResolveMacros("{% NodeID %}"), 0);
            int    NodeParentID   = ValidationHelper.GetInteger(context.Resolver.ResolveMacros("{% NodeParentID %}"), 0);
            string Culture        = ValidationHelper.GetString(context.Resolver.ResolveMacros("{% DocumentCulture %}"), "en-US");
            string DefaultCulture = DynamicRouteInternalHelper.SiteContextSafe().DefaultVisitorCulture;

            return(CacheHelper.Cache(cs =>
            {
                UrlSlugInfo Slug = UrlSlugInfoProvider.GetUrlSlugs()
                                   .WhereEquals("UrlSlugNodeID", NodeParentID)
                                   .OrderBy($"case when UrlSlugCultureCode = '{Culture}' then 0 else 1 end, case when UrlSlugCultureCode = '{DefaultCulture}' then 0 else 1 end")
                                   .Columns("UrlSlug")
                                   .FirstOrDefault();
                if (cs.Cached)
                {
                    cs.CacheDependency = CacheHelper.GetCacheDependency("dynamicrouting.urlslug|all");
                }
                return Slug != null ? Slug.UrlSlug : "";
            }, new CacheSettings(1440, "GetUrlSlug", NodeParentID, Culture, DefaultCulture)));
        }
        private void UrlSlug_Update_After_IsCustomRebuild(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo      UrlSlug = (UrlSlugInfo)e.Object;
            RecursionControl Trigger = new RecursionControl("UrlSlugNoLongerCustom_" + UrlSlug.UrlSlugGuid);

            if (!Trigger.Continue)
            {
                try
                {
                    // If Continue is false, then the Before update shows this needs to be rebuilt.
                    DynamicRouteInternalHelper.RebuildRoutesByNode(UrlSlug.UrlSlugNodeID);
                }
                catch (UrlSlugCollisionException ex)
                {
                    LogErrorsInSeparateThread(ex, "DynamicRouting", "UrlSlugConflict", $"Occurred on Url Slug {UrlSlug.UrlSlugID}");
                    e.Cancel();
                }
                catch (Exception ex)
                {
                    LogErrorsInSeparateThread(ex, "DynamicRouting", "Error", $"Occurred on Url Slug {UrlSlug.UrlSlugID}");
                }
            }
        }
        private void UrlSlug_Update_Before_301Redirect(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo UrlSlug = (UrlSlugInfo)e.Object;

            #region "Create Alternative Url of Previous Url"
            try
            {
                // Alternative Urls don't have the slash at the beginning
                string OriginalUrlSlugNoTrim = ValidationHelper.GetString(UrlSlug.GetOriginalValue("UrlSlug"), UrlSlug.UrlSlug);
                string OriginalUrlSlug       = OriginalUrlSlugNoTrim.Trim('/');

                // save previous Url to 301 redirects
                // Get DocumentID
                var Document = DocumentHelper.GetDocuments()
                               .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                               .CombineWithDefaultCulture()
                               .CombineWithAnyCulture()
                               .Culture(UrlSlug.UrlSlugCultureCode)
                               .FirstOrDefault();
                var AlternativeUrl = AlternativeUrlInfoProvider.GetAlternativeUrls()
                                     .WhereEquals("AlternativeUrlUrl", OriginalUrlSlug)
                                     .FirstOrDefault();

                SiteInfo Site           = SiteInfoProvider.GetSiteInfo(Document.NodeSiteID);
                string   DefaultCulture = SettingsKeyInfoProvider.GetValue("CMSDefaultCultureCode", new SiteInfoIdentifier(Site.SiteName));

                UrlSlugInfo CultureSiblingUrlSlug = UrlSlugInfoProvider.GetUrlSlugs()
                                                    .WhereEquals("UrlSlug", OriginalUrlSlugNoTrim)
                                                    .WhereEquals("UrlSlugNodeID", UrlSlug.UrlSlugNodeID)
                                                    .WhereNotEquals("UrlSlugCultureCode", UrlSlug.UrlSlugCultureCode)
                                                    .FirstOrDefault();

                if (AlternativeUrl != null)
                {
                    if (AlternativeUrl.AlternativeUrlDocumentID != Document.DocumentID)
                    {
                        // If Same NodeID, then make sure the DocumentID is of the one that is the DefaultCulture, if no DefaultCulture
                        // Exists, then just ignore
                        var AlternativeUrlDocument = DocumentHelper.GetDocument(AlternativeUrl.AlternativeUrlDocumentID, new TreeProvider());

                        // Log a warning
                        if (AlternativeUrlDocument.NodeID != UrlSlug.UrlSlugNodeID)
                        {
                            EventLogProvider.LogEvent("W", "DynamicRouting", "AlternativeUrlConflict", eventDescription: string.Format("Conflict between Alternative Url '{0}' exists for Document {1} [{2}] which already exists as an Alternative Url for Document {3} [{4}].",
                                                                                                                                       AlternativeUrl.AlternativeUrlUrl,
                                                                                                                                       Document.NodeAliasPath,
                                                                                                                                       Document.DocumentCulture,
                                                                                                                                       AlternativeUrlDocument.NodeAliasPath,
                                                                                                                                       AlternativeUrlDocument.DocumentCulture
                                                                                                                                       ));
                        }
                        TreeNode DefaultLanguage = DocumentHelper.GetDocuments()
                                                   .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                                                   .Culture(DefaultCulture)
                                                   .CombineWithDefaultCulture()
                                                   .FirstOrDefault();

                        // Save only if there is no default language, or it is the default language, or if there is a default language adn it isn't it, that the Url doesn't match
                        // Any of the default languages urls, as this often happens when you clone from an existing language and then save a new url.
                        bool DefaultLanguageExists = DefaultLanguage != null;
                        bool IsNotDefaultLanguage  = DefaultLanguageExists && AlternativeUrl.AlternativeUrlDocumentID != DefaultLanguage.DocumentID;
                        bool MatchesDefaultLang    = false;
                        if (DefaultLanguageExists && IsNotDefaultLanguage)
                        {
                            // See if the OriginalUrlSlug matches the default document, or one of it's alternates
                            var DefaultLangUrlSlug = UrlSlugInfoProvider.GetUrlSlugs()
                                                     .WhereEquals("UrlSlugNodeID", UrlSlug.UrlSlugNodeID)
                                                     .WhereEquals("UrlSlugCultureCode", DefaultLanguage.DocumentCulture)
                                                     .WhereEquals("UrlSlug", "/" + OriginalUrlSlug)
                                                     .FirstOrDefault();
                            var DefaultLangAltUrl = AlternativeUrlInfoProvider.GetAlternativeUrls()
                                                    .WhereEquals("AlternativeUrlDocumentID", DefaultLanguage.DocumentID)
                                                    .WhereEquals("AlternativeUrlUrl", OriginalUrlSlug)
                                                    .FirstOrDefault();
                            MatchesDefaultLang = DefaultLangUrlSlug != null || DefaultLangAltUrl != null;
                        }

                        if (!DefaultLanguageExists || !IsNotDefaultLanguage || (DefaultLanguageExists && IsNotDefaultLanguage && !MatchesDefaultLang))
                        {
                            AlternativeUrl.AlternativeUrlDocumentID = DefaultLanguage.DocumentID;
                            AlternativeUrlInfoProvider.SetAlternativeUrlInfo(AlternativeUrl);
                        }
                    }
                }
                // Create new one if there are no other Url Slugs with the same pattern for that node
                else if (CultureSiblingUrlSlug == null)
                {
                    AlternativeUrl = new AlternativeUrlInfo()
                    {
                        AlternativeUrlDocumentID = Document.DocumentID,
                        AlternativeUrlSiteID     = Document.NodeSiteID,
                    };
                    AlternativeUrl.SetValue("AlternativeUrlUrl", OriginalUrlSlug);

                    // Save only if there is no default language, or it is the default language, or if there is a default language adn it isn't it, that the Url doesn't match
                    // Any of the default languages urls, as this often happens when you clone from an existing language and then save a new url.
                    TreeNode DefaultLanguage = DocumentHelper.GetDocuments()
                                               .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                                               .Culture(DefaultCulture)
                                               .FirstOrDefault();
                    bool DefaultLanguageExists = DefaultLanguage != null;
                    bool IsNotDefaultLanguage  = DefaultLanguageExists && AlternativeUrl.AlternativeUrlDocumentID != DefaultLanguage.DocumentID;
                    bool MatchesDefaultLang    = false;
                    if (DefaultLanguageExists && IsNotDefaultLanguage)
                    {
                        // See if the OriginalUrlSlug matches the default document, or one of it's alternates
                        var DefaultLangUrlSlug = UrlSlugInfoProvider.GetUrlSlugs()
                                                 .WhereEquals("UrlSlugNodeID", UrlSlug.UrlSlugNodeID)
                                                 .WhereEquals("UrlSlugCultureCode", DefaultLanguage.DocumentCulture)
                                                 .WhereEquals("UrlSlug", "/" + OriginalUrlSlug)
                                                 .FirstOrDefault();
                        var DefaultLangAltUrl = AlternativeUrlInfoProvider.GetAlternativeUrls()
                                                .WhereEquals("AlternativeUrlDocumentID", DefaultLanguage.DocumentID)
                                                .WhereEquals("AlternativeUrlUrl", OriginalUrlSlug)
                                                .FirstOrDefault();
                        MatchesDefaultLang = DefaultLangUrlSlug != null || DefaultLangAltUrl != null;
                    }
                    if (!DefaultLanguageExists || !IsNotDefaultLanguage || (DefaultLanguageExists && IsNotDefaultLanguage && !MatchesDefaultLang))
                    {
                        try
                        {
                            AlternativeUrlInfoProvider.SetAlternativeUrlInfo(AlternativeUrl);
                        }
                        catch (InvalidAlternativeUrlException ex)
                        {
                            // Figure out what to do, it doesn't match the pattern constraints.
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogErrorsInSeparateThread(ex, "DynamicRouting", "AlternateUrlError", $"Occurred on Url Slug Update for Url Slug {UrlSlug.UrlSlug} {UrlSlug.UrlSlugCultureCode}");
            }
            #endregion

            #region "Remove any Alternative Url of the new Url for this node"
            try
            {
                // Alternative Urls don't have the slash at the beginning
                string NewUrlSlug = UrlSlug.UrlSlug.Trim('/');

                // Check for any Alternative Urls for this node that match and remove
                // Get DocumentID
                var Document = DocumentHelper.GetDocuments()
                               .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                               .CombineWithDefaultCulture()
                               .CombineWithAnyCulture()
                               .Culture(UrlSlug.UrlSlugCultureCode)
                               .FirstOrDefault();
                var AllDocumentIDs = DocumentHelper.GetDocuments()
                                     .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                                     .AllCultures()
                                     .Columns("DocumentID")
                                     .Select(x => x.DocumentID).ToList();

                // Delete any Alternate Urls for any of the culture variations of this node that match the new Url Slug, this is to prevent infinite redirect loops
                AlternativeUrlInfoProvider.GetAlternativeUrls()
                .WhereEquals("AlternativeUrlUrl", NewUrlSlug)
                .WhereIn("AlternativeUrlDocumentID", AllDocumentIDs)
                .ForEachObject(x => x.Delete());

                SiteInfo Site           = SiteInfoProvider.GetSiteInfo(Document.NodeSiteID);
                string   DefaultCulture = SettingsKeyInfoProvider.GetValue("CMSDefaultCultureCode", new SiteInfoIdentifier(Site.SiteName));

                var AltUrlsOnOtherNodes = AlternativeUrlInfoProvider.GetAlternativeUrls()
                                          .WhereEquals("AlternativeUrlUrl", NewUrlSlug)
                                          .WhereNotIn("AlternativeUrlDocumentID", AllDocumentIDs)
                                          .ToList();

                // Add warning about conflict.
                if (AltUrlsOnOtherNodes.Count > 0)
                {
                    EventLogProvider.LogEvent("W", "DynamicRouting", "AlternateUrlConflict", $"Another page with an alternate Url matching {UrlSlug.UrlSlug} was found, please adjust and correct.");
                }
            }
            catch (Exception ex)
            {
                LogErrorsInSeparateThread(ex, "DynamicRouting", "AlternateUrlError", $"Occurred on Url Slug Update for Url Slug {UrlSlug.UrlSlug} {UrlSlug.UrlSlugCultureCode}");
            }

            #endregion
        }
Example #9
0
        private void UrlSlug_Update_Before_IsCustomRebuild(object sender, ObjectEventArgs e)
        {
            UrlSlugInfo UrlSlug = (UrlSlugInfo)e.Object;
            TreeNode    Node    = new DocumentQuery()
                                  .WhereEquals("NodeID", UrlSlug.UrlSlugNodeID)
                                  .Columns("NodeSiteID, NodeAliasPath, NodeGuid, NodeAlias")
                                  .FirstOrDefault();

            // First check if there is already a custom URL slug, if so cancel
            if (UrlSlug.UrlSlugIsCustom)
            {
                var ExistingMatchingSlug = UrlSlugInfoProvider.GetUrlSlugs()
                                           .WhereNotEquals("UrlSlugNodeID", UrlSlug.UrlSlugNodeID)
                                           .WhereEquals("UrlSlug", UrlSlug.UrlSlug)
                                           .Where($"UrlSlugNodeID in (Select NodeID from CMS_Tree where NodeSiteID = {Node.NodeSiteID})")
                                           .Columns("UrlSlugNodeID")
                                           .FirstOrDefault();
                if (ExistingMatchingSlug != null)
                {
                    TreeNode ConflictNode = new DocumentQuery()
                                            .WhereEquals("NodeID", ExistingMatchingSlug.UrlSlugNodeID)
                                            .Columns("NodeSiteID, NodeAliasPath")
                                            .FirstOrDefault();
                    var Error = new NotSupportedException($"This custom URL Slug '{UrlSlug.UrlSlug}' on {Node.NodeAliasPath} is already the pattern of an existing document ({ConflictNode.NodeAliasPath}).  Operation aborted.");
                    EventLogProvider.LogException("DynamicRouting", "CustomUrlSlugConflict", Error, Node.NodeSiteID);
                    throw Error;
                }
            }


            // This prevents the recursive url slug updates from the first update from removing the "Ignore" on this item.
            RecursionControl AlreadyDeterminedIfShouldIgnore = new RecursionControl("AlreadyDeterminedIfShouldIgnore_" + UrlSlug.UrlSlugGuid);

            if (CMSActionContext.CurrentLogSynchronization && AlreadyDeterminedIfShouldIgnore.Continue)
            {
                // Delete existing ignore records
                DynamicRouteInternalHelper.RemoveIgnoreStagingTaskOfUrlSlug(UrlSlug.UrlSlugID);
                // If the staging task Should be created
                if (
                    (UrlSlug.UrlSlugIsCustom && !ValidationHelper.GetBoolean(UrlSlug.GetOriginalValue("UrlSlugIsCustom"), true))
                    ||
                    (!UrlSlug.UrlSlugIsCustom && ValidationHelper.GetBoolean(UrlSlug.GetOriginalValue("UrlSlugIsCustom"), false))
                    ||
                    (UrlSlug.UrlSlugIsCustom && ValidationHelper.GetBoolean(UrlSlug.GetOriginalValue("UrlSlugIsCustom"), false) && UrlSlug.UrlSlug != ValidationHelper.GetString(UrlSlug.GetOriginalValue("UrlSlug"), UrlSlug.UrlSlug))
                    )
                {
                    // Staging task should be created, so proceed as normal
                }
                else
                {
                    // Staging task should not be created, add entry so this task won't be generated
                    UrlSlugStagingTaskIgnoreInfoProvider.SetUrlSlugStagingTaskIgnoreInfo(new UrlSlugStagingTaskIgnoreInfo()
                    {
                        UrlSlugStagingTaskIgnoreUrlSlugID = UrlSlug.UrlSlugID
                    });
                }
            }

            // If the Url Slug is custom or was custom, then need to rebuild after.
            if (UrlSlug.UrlSlugIsCustom || ValidationHelper.GetBoolean(UrlSlug.GetOriginalValue("UrlSlugIsCustom"), UrlSlug.UrlSlugIsCustom))
            {
                // Add hook so the Url Slug will be re-rendered after it's updated
                RecursionControl Trigger = new RecursionControl("UrlSlugNoLongerCustom_" + UrlSlug.UrlSlugGuid);
                var Triggered            = Trigger.Continue;
            }
        }