protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        lblAltUrl.AssociatedControlClientID = txtAltUrl.TextBox.ClientID;
        txtAltUrl.PlaceholderText           = TextHelper.LimitLength(SitePresentationUrl, 45, CutTextEnum.Start);

        menu.ActionsList.Add(new SaveAction());
        menu.ActionsList.Add(new SaveAction()
        {
            ButtonStyle     = ButtonStyle.Default,
            Text            = GetString("content.ui.properties.saveandaddanotherlternativeurl"),
            CommandArgument = COMMAND_ARGUMENT_SAVE_ANOTHER
        });
        menu.ActionsList.Add(new HeaderAction
        {
            ButtonStyle   = ButtonStyle.Default,
            RedirectUrl   = GetListingUrl(),
            Text          = GetString("general.back"),
            OnClientClick = "if (CheckChanges && !CheckChanges()) {{ return false; }}"
        });

        // Register for action
        ComponentEvents.RequestEvents.RegisterForEvent(ComponentEvents.SAVE, btnOk_Click);

        // Ensure script which allows redirecting to conflicting page
        ScriptHelper.RegisterEditScript(Page, false);

        alternativeUrl = GetAlternativeUrlInfo();

        // Initializes page breadcrumbs
        PageBreadcrumbs.Items.Add(new BreadcrumbItem()
        {
            Text        = GetString("content.ui.propertiesurls"),
            RedirectUrl = GetListingUrl(),
            Target      = "propedit"
        });

        PageBreadcrumbs.Items.Add(new BreadcrumbItem()
        {
            Text = alternativeUrl.AlternativeUrlID > 0 ? TextHelper.LimitLength(alternativeUrl.AlternativeUrlUrl.ToString(), 100, cutLocation: CutTextEnum.Middle) : GetString("content.ui.properties.addalternativeurl")
        });

        if (alternativeUrl.AlternativeUrlID == 0)
        {
            // Do not include type as breadcrumbs suffix
            UIHelper.SetBreadcrumbsSuffix("");
        }

        if (!RequestHelper.IsPostBack())
        {
            // Automatically display changes saved text
            if (QueryHelper.GetBoolean("saved", false))
            {
                ShowChangesSaved();
            }

            txtAltUrl.Text = alternativeUrl.AlternativeUrlUrl.NormalizedUrl;
        }
    }
    private AlternativeUrlInfo GetAlternativeUrlInfo(string url, int altUrlId = 0)
    {
        AlternativeUrlInfo alternativeUrl;

        if (altUrlId > 0)
        {
            alternativeUrl = AlternativeUrlInfoProvider.GetAlternativeUrlInfo(altUrlId);
            if (alternativeUrl == null)
            {
                return(null);
            }
        }
        else
        {
            alternativeUrl = new AlternativeUrlInfo
            {
                AlternativeUrlDocumentID = EditedDocument.DocumentID,
                AlternativeUrlSiteID     = SiteContext.CurrentSiteID
            };
        }

        alternativeUrl.AlternativeUrlUrl = AlternativeUrlHelper.NormalizeAlternativeUrl(url);

        return(alternativeUrl);
    }
Exemplo n.º 3
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);
            }
        }
    /// <summary>
    /// Returns <see cref="String.Empty"/> when <paramref name="alternativeUrl"/> was saved.
    /// If error occurs during saving the <paramref name="alternativeUrl"/>, corresponding error message is returned.
    /// </summary>
    private string SaveData(AlternativeUrlInfo alternativeUrl)
    {
        if (String.IsNullOrWhiteSpace(alternativeUrl.AlternativeUrlUrl.NormalizedUrl))
        {
            return(GetString("general.requiresvalue"));
        }

        try
        {
            AlternativeUrlInfoProvider.SetInfoCheckForConflictingPage(alternativeUrl);
        }
        catch (InvalidAlternativeUrlException ex) when(ex.ConflictingPage != null)
        {
            return(String.Format(GetString("alternativeurl.isinconflictwithpage"), alternativeUrl.AlternativeUrlUrl, AlternativeUrlHelper.GetDocumentIdentification(ex.ConflictingPage.DocumentNamePath, ex.ConflictingPage.DocumentCulture)));
        }
        catch (InvalidAlternativeUrlException ex) when(ex.ConflictingAlternativeUrl != null)
        {
            var page = DocumentHelper.GetDocument(ex.ConflictingAlternativeUrl.AlternativeUrlDocumentID, new TreeProvider());

            return(String.Format(GetString("alternativeurl.isinconflictwithalternativeurl"), alternativeUrl.AlternativeUrlUrl, AlternativeUrlHelper.GetDocumentIdentification(page.DocumentNamePath, page.DocumentCulture)));
        }
        catch (InvalidAlternativeUrlException ex) when(!String.IsNullOrEmpty(ex.ExcludedUrl) || ex.AlternativeUrl != null)
        {
            var errorMessage = SettingsKeyInfoProvider.GetValue("CMSAlternativeURLsErrorMessage", SiteContext.CurrentSiteID);

            return(String.IsNullOrEmpty(errorMessage) ?
                   GetString("settingskey.cmsalternativeurlsfallbackerrormessage") :
                   ResHelper.LocalizeString(errorMessage));
        }
        catch (InvalidAlternativeUrlException)
        {
            return(String.Format(GetString("general.mustbeunique"), TypeHelper.GetNiceObjectTypeName(AlternativeUrlInfo.OBJECT_TYPE)));
        }
        catch (RegexMatchTimeoutException)
        {
            return(String.Format(GetString("settingskey.cmsalternativeurlstimeouterrormessage"), alternativeUrl.AlternativeUrlUrl));
        }

        DocumentManager.SaveDocument();

        return(String.Empty);
    }
        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
        }
    /// <summary>
    /// Returns <see cref="String.Empty"/> when <paramref name="alternativeUrl"/> was saved.
    /// If error occurs during saving the <paramref name="alternativeUrl"/>, corresponding error message is returned.
    /// </summary>
    private string SaveData(AlternativeUrlInfo alternativeUrl)
    {
        alternativeUrl.AlternativeUrlUrl = AlternativeUrlHelper.NormalizeAlternativeUrl(txtAltUrl.Text);

        if (String.IsNullOrWhiteSpace(alternativeUrl.AlternativeUrlUrl.NormalizedUrl))
        {
            return(GetString("general.requiresvalue"));
        }

        try
        {
            AlternativeUrlInfoProvider.SetInfoCheckForConflictingPage(alternativeUrl);
        }
        catch (InvalidAlternativeUrlException ex) when(ex.CollisionData != null)
        {
            var collisionData = ex.CollisionData;

            if (collisionData.CultureVersionExists)
            {
                var editDocumentLink = $"<a onclick=\"window.CMSContentManager.changed(false); EditDocument({collisionData.NodeID}, 'Properties.URLs', {ScriptHelper.GetString(collisionData.CultureCode)})\">{GetDocumentIdentification(collisionData.PageName, collisionData.CultureCode)}</a>";
                return(String.Format(GetString("alternativeurl.isinconflictwithpage"), alternativeUrl.AlternativeUrlUrl, editDocumentLink));
            }
            else
            {
                var editDocumentLink = $"<a onclick=\"window.CMSContentManager.changed(false); EditDocument({collisionData.NodeID}, 'Properties.URLs|{PageRoutingUIHelper.SLUGS_LIST_SUBTAB_NAME}', {ScriptHelper.GetString(collisionData.ExistingCultureCode)})\">{collisionData.PageName}</a>";
                return(String.Format(GetString("alternativeurl.isinconflictwithnottranslatedpage"), alternativeUrl.AlternativeUrlUrl, GetCultureShortName(collisionData.CultureCode), editDocumentLink));
            }
        }
        catch (InvalidAlternativeUrlException ex) when(ex.ConflictingAlternativeUrl != null)
        {
            var page             = DocumentHelper.GetDocument(ex.ConflictingAlternativeUrl.AlternativeUrlDocumentID, new TreeProvider());
            var editDocumentLink = $"<a onclick=\"window.CMSContentManager.changed(false); EditDocument({page.NodeID}, 'Properties.URLs', {ScriptHelper.GetString(page.DocumentCulture)})\">{GetDocumentIdentification(page)}</a>";

            return(String.Format(GetString("alternativeurl.isinconflictwithalternativeurl"), alternativeUrl.AlternativeUrlUrl, editDocumentLink));
        }
        catch (InvalidAlternativeUrlException ex) when(!String.IsNullOrEmpty(ex.ExcludedUrl) || ex.AlternativeUrl != null)
        {
            var errorMessage = SettingsKeyInfoProvider.GetValue("CMSAlternativeURLsErrorMessage", Node.NodeSiteID);

            return(String.IsNullOrEmpty(errorMessage) ?
                   GetString("settingskey.cmsalternativeurlsfallbackerrormessage") :
                   ResHelper.LocalizeString(errorMessage));
        }
        catch (InvalidAlternativeUrlException)
        {
            return(String.Format(GetString("general.mustbeunique"), TypeHelper.GetNiceObjectTypeName(AlternativeUrlInfo.OBJECT_TYPE)));
        }
        catch (RegexMatchTimeoutException)
        {
            return(String.Format(GetString("settingskey.cmsalternativeurlstimeouterrormessage"), alternativeUrl.AlternativeUrlUrl));
        }
        catch (Exception ex)
        {
            Service.Resolve <IEventLogService>().LogException("Alternative URLs", "EDIT", ex);
            return(GetString("alternativeurl.generalerror"));
        }

        DocumentManager.SaveDocument();

        txtAltUrl.Text = alternativeUrl.AlternativeUrlUrl.NormalizedUrl;

        return(String.Empty);
    }