public DeleteBlogPostPropertiesResponse Delete(DeleteBlogPostPropertiesRequest request) { var model = new DeletePageViewModel { PageId = request.Id, Version = request.Data.Version }; var result = pageService.DeletePage(model, securityService.GetCurrentPrincipal()); return new DeleteBlogPostPropertiesResponse { Data = result }; }
/// <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); }); } } } } } }
public ActionResult DeletePage(DeletePageViewModel model) { if (GetCommand<DeletePageCommand>().ExecuteCommand(model)) { Messages.AddSuccess(PagesGlobalization.DeletePage_DeletedSuccessfully_Message); return Json(new WireJson { Success = true }); } return Json(new WireJson { Success = false }); }
/// <summary> /// Deletes the page. /// </summary> /// <param name="model">The model.</param> /// <param name="principal">The principal.</param> /// <param name="messages">The messages.</param> /// <returns> /// Delete result /// </returns> /// <exception cref="ConcurrentDataException"></exception> /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"> /// </exception> public bool DeletePage(DeletePageViewModel model, IPrincipal principal, IMessagesIndicator messages = null) { var languagesFuture = repository.AsQueryable<Language>().ToFuture(); var page = repository.AsQueryable<PageProperties>(p => p.Id == model.PageId) .FetchMany(p => p.PageContents) .ThenFetch(pc => pc.Content) .ToFuture() .ToList() .FirstOne(); // Unidentified problem where in some cases proxy is returned. if (page is INHibernateProxy) { page = repository.UnProxy(page); } if (model.Version > 0 && page.Version != model.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); } var isRedirectInternal = false; if (!string.IsNullOrWhiteSpace(model.RedirectUrl)) { isRedirectInternal = urlService.ValidateInternalUrl(model.RedirectUrl); if (!isRedirectInternal && urlService.ValidateInternalUrl(urlService.FixUrl(model.RedirectUrl))) { isRedirectInternal = true; } if (isRedirectInternal) { model.RedirectUrl = urlService.FixUrl(model.RedirectUrl); } } if (model.UpdateSitemap) { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent); } var sitemaps = new Dictionary<Sitemap, bool>(); var sitemapNodes = sitemapService.GetNodesByPage(page); if (model.UpdateSitemap) { sitemapNodes.Select(node => node.Sitemap) .Distinct() .ToList() .ForEach( sitemap => sitemaps.Add( sitemap, !cmsConfiguration.Security.AccessControlEnabled || accessControlService.GetAccessLevel(sitemap, 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(); // Update sitemap nodes IList<SitemapNode> updatedNodes = new List<SitemapNode>(); IList<SitemapNode> deletedNodes = new List<SitemapNode>(); UpdateSitemapNodes(model, page, sitemapNodes, sitemaps, languagesFuture.ToList(), updatedNodes, deletedNodes); Redirect redirect; if (!string.IsNullOrWhiteSpace(model.RedirectUrl)) { if (string.Equals(page.PageUrl, model.RedirectUrl, StringComparison.OrdinalIgnoreCase)) { var logMessage = string.Format("Circular redirect loop from url {0} to url {0}.", model.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_SameUrlPath_Message, logMessage); } // Validate url if (!urlService.ValidateExternalUrl(model.RedirectUrl)) { var logMessage = string.Format("Invalid redirect url {0}.", model.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_InvalidUrlPath_Message, logMessage); } string patternsValidationMessage; if (isRedirectInternal && !urlService.ValidateUrlPatterns(model.RedirectUrl, out patternsValidationMessage, PagesGlobalization.DeletePage_RedirectUrl_Name)) { var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, model.RedirectUrl); throw new ValidationException(() => patternsValidationMessage, logMessage); } redirect = redirectService.GetPageRedirect(page.PageUrl); if (redirect != null) { redirect.RedirectUrl = model.RedirectUrl; } else { redirect = redirectService.CreateRedirectEntity(page.PageUrl, model.RedirectUrl); } if (redirect != null) { repository.Save(redirect); } } else { redirect = null; } // Delete child entities. if (page.PageTags != null) { foreach (var pageTag in page.PageTags) { repository.Delete(pageTag); } } var deletedPageContents = new List<PageContent>(); var htmlContentsToDelete = new List<HtmlContent>(); if (page.PageContents != null) { foreach (var pageContent in page.PageContents) { // If content is HTML content, delete HTML content var htmlContent = pageContent.Content as HtmlContent; if (htmlContent != null) { var draft = pageContent.Content.History != null ? pageContent.Content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) : null; if (draft != null) { repository.Delete(draft); } repository.Delete(htmlContent); htmlContentsToDelete.Add(htmlContent); } repository.Delete(pageContent); deletedPageContents.Add(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>(page); // Commit unitOfWork.Commit(); var updatedSitemaps = new List<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 about redirect created if (redirect != null) { Events.PageEvents.Instance.OnRedirectCreated(redirect); } // Notify about deleted page contents foreach (var deletedPageContent in deletedPageContents) { Events.PageEvents.Instance.OnPageContentDeleted(deletedPageContent); } // Notify about deleted html contents foreach (var htmlContent in htmlContentsToDelete) { Events.PageEvents.Instance.OnHtmlContentDeleted(htmlContent); } // Notifying, that page is deleted. Events.PageEvents.Instance.OnPageDeleted(page); if (sitemaps.Any(tuple => !tuple.Value) && messages != null) { // Some sitemaps where skipped, because user has no permission to edit. messages.AddSuccess(PagesGlobalization.DeletePage_SitemapSkipped_Message); } return true; }
/// <summary> /// Deletes the page. /// </summary> /// <param name="model">The model.</param> /// <param name="principal">The principal.</param> /// <param name="messages">The messages.</param> /// <returns> /// Delete result /// </returns> /// <exception cref="ConcurrentDataException"></exception> /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"> /// </exception> public bool DeletePage(DeletePageViewModel model, IPrincipal principal, IMessagesIndicator messages = null) { var page = repository.First<PageProperties>(model.PageId); if (model.Version > 0 && page.Version != model.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); } var isRedirectInternal = false; if (!string.IsNullOrWhiteSpace(model.RedirectUrl)) { isRedirectInternal = urlService.ValidateInternalUrl(model.RedirectUrl); if (!isRedirectInternal && urlService.ValidateInternalUrl(urlService.FixUrl(model.RedirectUrl))) { isRedirectInternal = true; } if (isRedirectInternal) { model.RedirectUrl = urlService.FixUrl(model.RedirectUrl); } } if (model.UpdateSitemap) { accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent); } var sitemaps = new Dictionary<Sitemap, bool>(); var sitemapNodes = sitemapService.GetNodesByPage(page); if (model.UpdateSitemap) { sitemapNodes.Select(node => node.Sitemap) .Distinct() .ToList() .ForEach( sitemap => sitemaps.Add( sitemap, !cmsConfiguration.Security.AccessControlEnabled || accessControlService.GetAccessLevel(sitemap, 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 (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); } } } } } Redirect redirect; if (!string.IsNullOrWhiteSpace(model.RedirectUrl)) { if (string.Equals(page.PageUrl, model.RedirectUrl, StringComparison.OrdinalIgnoreCase)) { var logMessage = string.Format("Circular redirect loop from url {0} to url {0}.", model.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_SameUrlPath_Message, logMessage); } // Validate url if (!urlService.ValidateExternalUrl(model.RedirectUrl)) { var logMessage = string.Format("Invalid redirect url {0}.", model.RedirectUrl); throw new ValidationException(() => PagesGlobalization.ValidatePageUrlCommand_InvalidUrlPath_Message, logMessage); } string patternsValidationMessage; if (isRedirectInternal && !urlService.ValidateUrlPatterns(model.RedirectUrl, out patternsValidationMessage, PagesGlobalization.DeletePage_RedirectUrl_Name)) { var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, model.RedirectUrl); throw new ValidationException(() => patternsValidationMessage, logMessage); } redirect = redirectService.GetPageRedirect(page.PageUrl); if (redirect != null) { redirect.RedirectUrl = model.RedirectUrl; } else { redirect = redirectService.CreateRedirectEntity(page.PageUrl, model.RedirectUrl); } if (redirect != null) { repository.Save(redirect); } } else { redirect = null; } // Delete child entities. if (page.PageTags != null) { foreach (var pageTag in page.PageTags) { repository.Delete(pageTag); } } var deletedPageContents = new List<PageContent>(); if (page.PageContents != null) { foreach (var pageContent in page.PageContents) { repository.Delete(pageContent); deletedPageContents.Add(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>(page); // Commit unitOfWork.Commit(); var updatedSitemaps = new List<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 about redirect created if (redirect != null) { Events.PageEvents.Instance.OnRedirectCreated(redirect); } // Notify about deleted page contents foreach (var deletedPageContent in deletedPageContents) { Events.PageEvents.Instance.OnPageContentDeleted(deletedPageContent); } // Notifying, that page is deleted. Events.PageEvents.Instance.OnPageDeleted(page); if (sitemaps.Any(tuple => !tuple.Value) && messages != null) { // Some sitemaps where skipped, because user has no permission to edit. messages.AddSuccess(PagesGlobalization.DeletePage_SitemapSkipped_Message); } return true; }