/// <summary> /// Updates page sitemap nodes. /// </summary> private void UpdateSitemapNodes(DeletePageViewModel model, PageProperties page, IList <SitemapNode> sitemapNodes, Dictionary <Sitemap, bool> sitemaps, List <Language> languages, IList <SitemapNode> updatedNodes, IList <SitemapNode> deletedNodes) { if (sitemapNodes != null) { // Archive sitemaps before update. sitemaps.Select(pair => pair.Key).ToList().ForEach(sitemap => sitemapService.ArchiveSitemap(sitemap.Id)); foreach (var node in sitemapNodes) { if (!node.IsDeleted) { if (model.UpdateSitemap && sitemaps[node.Sitemap]) { // Delete sitemap node. sitemapService.DeleteNode(node, ref deletedNodes); } else { // Unlink sitemap node. if (node.Page != null && node.Page.Id == page.Id) { node.Page = null; node.Title = node.UsePageTitleAsNodeTitle ? page.Title : node.Title; node.Url = page.PageUrl; node.UrlHash = page.PageUrlHash; repository.Save(node); updatedNodes.Add(node); IEnumerable <PageTranslationViewModel> pageTranslations; if (page.LanguageGroupIdentifier.HasValue && !page.LanguageGroupIdentifier.Value.HasDefaultValue()) { pageTranslations = GetPageTranslations(page.LanguageGroupIdentifier.Value); } else { pageTranslations = new PageTranslationViewModel[0]; } // Assigned node URL and title is taken from default language, if such exists. var defaultPageTranslation = pageTranslations.FirstOrDefault(p => !p.LanguageId.HasValue); if (defaultPageTranslation != null) { node.Url = defaultPageTranslation.PageUrl; node.UrlHash = defaultPageTranslation.PageUrlHash; if (node.UsePageTitleAsNodeTitle) { node.Title = defaultPageTranslation.Title; } } // Update sitemap node translations. if (node.Translations == null) { node.Translations = new List <SitemapNodeTranslation>(); } node.Translations.ForEach( t => { var pageTranslation = GetPageTranslation(pageTranslations, t.Language.Id, node, page); if (t.UsePageTitleAsNodeTitle) { t.Title = pageTranslation.Title; } t.UsePageTitleAsNodeTitle = false; t.Url = pageTranslation.PageUrl; t.UrlHash = pageTranslation.PageUrlHash; }); // Create non-existing node translations for each language. languages.Where(language => node.Translations.All(nt => nt.Language.Id != language.Id)) .ForEach(language => { var pageTranslation = GetPageTranslation(pageTranslations, language.Id, node, page); var nodeTranslation = new SitemapNodeTranslation { Language = language, Node = node, UsePageTitleAsNodeTitle = false, Title = pageTranslation.Title, Url = pageTranslation.PageUrl, UrlHash = pageTranslation.PageUrlHash }; node.Translations.Add(nodeTranslation); }); } } } } } }
/// <summary> /// Executes the specified request. /// </summary> /// <param name="request">The request.</param> /// <returns></returns> /// <exception cref="ConcurrentDataException"></exception> /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"> /// </exception> public virtual bool Execute(DeletePageViewModel request) { var page = Repository.First <PageProperties>(request.PageId); if (page.Version != request.Version) { throw new ConcurrentDataException(page); } if (page.IsMasterPage && Repository.AsQueryable <MasterPage>(mp => mp.Master == page).Any()) { var message = PagesGlobalization.DeletePageCommand_MasterPageHasChildren_Message; var logMessage = string.Format("Failed to delete page. Page is selected as master page. Id: {0} Url: {1}", page.Id, page.PageUrl); throw new ValidationException(() => message, logMessage); } request.RedirectUrl = urlService.FixUrl(request.RedirectUrl); if (request.UpdateSitemap) { AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent); } var sitemaps = new Dictionary <Models.Sitemap, bool>(); var sitemapNodes = sitemapService.GetNodesByPage(page); if (request.UpdateSitemap) { sitemapNodes.Select(node => node.Sitemap) .Distinct() .ToList() .ForEach( sitemap => sitemaps.Add( sitemap, !cmsConfiguration.Security.AccessControlEnabled || AccessControlService.GetAccessLevel(sitemap, Context.Principal) == AccessLevel.ReadWrite)); foreach (var node in sitemapNodes) { if (sitemaps[node.Sitemap] && node.ChildNodes.Count > 0) { var logMessage = string.Format("In {0} sitemap node {1} has {2} child nodes.", node.Sitemap.Id, node.Id, node.ChildNodes.Count); throw new ValidationException(() => PagesGlobalization.DeletePageCommand_SitemapNodeHasChildNodes_Message, logMessage); } } } UnitOfWork.BeginTransaction(); IList <SitemapNode> updatedNodes = new List <SitemapNode>(); IList <SitemapNode> deletedNodes = new List <SitemapNode>(); if (sitemapNodes != null) { // Archive sitemaps before update. sitemaps.Select(pair => pair.Key).ToList().ForEach(sitemap => sitemapService.ArchiveSitemap(sitemap.Id)); foreach (var node in sitemapNodes) { if (!node.IsDeleted) { if (request.UpdateSitemap && sitemaps[node.Sitemap]) { // Delete sitemap node. sitemapService.DeleteNode(node, ref deletedNodes); } else { // Unlink sitemap node. if (node.Page != null && node.Page.Id == page.Id) { node.Page = null; node.Url = page.PageUrl; node.UrlHash = page.PageUrlHash; Repository.Save(node); updatedNodes.Add(node); } } } } } if (!string.IsNullOrWhiteSpace(request.RedirectUrl)) { if (string.Equals(page.PageUrl, request.RedirectUrl, StringComparison.OrdinalIgnoreCase)) { var logMessage = string.Format("Circular redirect loop from url {0} to url {0}.", request.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_SameUrlPath_Message, logMessage); } // Validate url if (!urlService.ValidateUrl(request.RedirectUrl)) { var logMessage = string.Format("Invalid redirect url {0}.", request.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_InvalidUrlPath_Message, logMessage); } string patternsValidationMessage; if (!urlService.ValidateUrlPatterns(request.RedirectUrl, out patternsValidationMessage, PagesGlobalization.DeletePage_RedirectUrl_Name)) { var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, request.RedirectUrl); throw new ValidationException(() => patternsValidationMessage, logMessage); } var redirect = redirectService.GetPageRedirect(page.PageUrl); if (redirect != null) { redirect.RedirectUrl = request.RedirectUrl; } else { redirect = redirectService.CreateRedirectEntity(page.PageUrl, request.RedirectUrl); } if (redirect != null) { Repository.Save(redirect); } } // Delete child entities. if (page.PageTags != null) { foreach (var pageTag in page.PageTags) { Repository.Delete(pageTag); } } if (page.PageContents != null) { foreach (var pageContent in page.PageContents) { Repository.Delete(pageContent); } } if (page.Options != null) { foreach (var option in page.Options) { Repository.Delete(option); } } if (page.AccessRules != null) { var rules = page.AccessRules.ToList(); rules.ForEach(page.RemoveRule); } if (page.MasterPages != null) { foreach (var master in page.MasterPages) { Repository.Delete(master); } } // Delete page Repository.Delete <Root.Models.Page>(request.PageId, request.Version); // Commit UnitOfWork.Commit(); var updatedSitemaps = new List <Models.Sitemap>(); foreach (var node in updatedNodes) { Events.SitemapEvents.Instance.OnSitemapNodeUpdated(node); if (!updatedSitemaps.Contains(node.Sitemap)) { updatedSitemaps.Add(node.Sitemap); } } foreach (var node in deletedNodes) { Events.SitemapEvents.Instance.OnSitemapNodeDeleted(node); if (!updatedSitemaps.Contains(node.Sitemap)) { updatedSitemaps.Add(node.Sitemap); } } foreach (var updatedSitemap in updatedSitemaps) { Events.SitemapEvents.Instance.OnSitemapUpdated(updatedSitemap); } // Notifying, that page is deleted. Events.PageEvents.Instance.OnPageDeleted(page); if (sitemaps.Any(tuple => !tuple.Value)) { // Some sitemaps where skipped, because user has no permission to edit. Context.Messages.AddSuccess(PagesGlobalization.DeletePage_SitemapSkipped_Message); } return(true); }