Пример #1
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The page view model.</param>
        /// <returns>Created page</returns>
        public virtual SavePageResponse Execute(AddNewPageViewModel request)
        {
            // Create / fix page url
            var pageUrl       = request.PageUrl;
            var createPageUrl = (pageUrl == null);

            if (createPageUrl && !string.IsNullOrWhiteSpace(request.PageTitle))
            {
                pageUrl = pageService.CreatePagePermalink(request.PageTitle, request.ParentPageUrl);
            }
            else
            {
                pageUrl = urlService.FixUrl(pageUrl);

                // Validate Url
                pageService.ValidatePageUrl(pageUrl);
            }

            var page = new PageProperties
            {
                PageUrl  = pageUrl,
                Title    = request.PageTitle,
                Layout   = Repository.First <Root.Models.Layout>(request.TemplateId),
                IsPublic = true,
                Status   = PageStatus.Unpublished
            };

            Repository.Save(page);
            UnitOfWork.Commit();

            // Notifying, that page is created
            PagesApiContext.Events.OnPageCreated(page);

            return(new SavePageResponse(page));
        }
Пример #2
0
        private string TryValidateOldUrl(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return(null);
            }

            url = urlService.FixUrl(url);
            if (!urlService.ValidateInternalUrl(url))
            {
                var serverPath = httpContextAccessor.MapPublicPath("/").TrimEnd('/');
                if (url.StartsWith(serverPath) && serverPath != url)
                {
                    url = url.Substring(serverPath.Length, url.Length - serverPath.Length);
                    if (!urlService.ValidateInternalUrl(url))
                    {
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }

            return(url);
        }
Пример #3
0
        /// <summary>
        /// Saves SEO information.
        /// </summary>
        /// <param name="model">The SEO information model.</param>
        /// <returns>
        /// true if SEO information saved successfully; false otherwise.
        /// </returns>
        public virtual EditSeoViewModel Execute(EditSeoViewModel model)
        {
            var page = Repository.First <PageProperties>(model.PageId);

            bool initialHasSeo = page.HasSEO;

            Models.Redirect newRedirect = null;

            page.Version = model.Version;
            page.Title   = model.PageTitle;

            model.ChangedUrlPath = urlService.FixUrl(model.ChangedUrlPath);

            if (!string.Equals(model.PageUrlPath, model.ChangedUrlPath))
            {
                pageService.ValidatePageUrl(model.ChangedUrlPath, model.PageId);

                if (model.CreatePermanentRedirect)
                {
                    var redirect = redirectService.CreateRedirectEntity(model.PageUrlPath, model.ChangedUrlPath);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        newRedirect = redirect;
                    }
                }

                page.NodeCountInSitemap = model.UpdateSitemap
                    ? sitemapService.ChangeUrl(page.PageUrl, model.ChangedUrlPath)
                    : sitemapService.NodesWithUrl(model.ChangedUrlPath);

                page.PageUrl = model.ChangedUrlPath;
            }

            page.PageUrlHash     = page.PageUrl.UrlHash();
            page.MetaTitle       = model.MetaTitle;
            page.MetaKeywords    = model.MetaKeywords;
            page.MetaDescription = model.MetaDescription;
            page.UseCanonicalUrl = model.UseCanonicalUrl;

            Repository.Save(page);
            UnitOfWork.Commit();

            // Notify about SEO change.
            if (page.HasSEO != initialHasSeo)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new redirect creation.
            if (newRedirect != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(newRedirect);
            }

            return(new EditSeoViewModel {
                PageUrlPath = page.PageUrl
            });
        }
Пример #4
0
        /// <summary>
        /// Gets the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns><c>GetPageResponse</c> with page properties.</returns>
        public GetPageResponse Get(GetPageRequest request)
        {
            var query = repository.AsQueryable <PageProperties>();

            if (request.PageId.HasValue)
            {
                query = query.Where(page => page.Id == request.PageId.Value);
            }
            else
            {
                var url = urlService.FixUrl(request.PageUrl);
                query = query.Where(page => page.PageUrlHash == url.UrlHash());
            }

            var model = query
                        .Select(page => new PageModel
            {
                Id             = page.Id,
                Version        = page.Version,
                CreatedBy      = page.CreatedByUser,
                CreatedOn      = page.CreatedOn,
                LastModifiedBy = page.ModifiedByUser,
                LastModifiedOn = page.ModifiedOn,

                PageUrl                 = page.PageUrl,
                Title                   = page.Title,
                Description             = page.Description,
                IsPublished             = page.Status == PageStatus.Published,
                PublishedOn             = page.PublishedOn,
                LayoutId                = page.Layout != null && !page.Layout.IsDeleted ? page.Layout.Id : (Guid?)null,
                MasterPageId            = page.MasterPage != null && !page.MasterPage.IsDeleted ? page.MasterPage.Id : (Guid?)null,
                CategoryId              = page.Category != null && !page.Category.IsDeleted ? page.Category.Id : (Guid?)null,
                CategoryName            = page.Category != null && !page.Category.IsDeleted ? page.Category.Name : null,
                MainImageId             = page.Image != null && !page.Image.IsDeleted ? page.Image.Id : (Guid?)null,
                MainImageUrl            = page.Image != null && !page.Image.IsDeleted ? page.Image.PublicUrl : null,
                MainImageThumbnauilUrl  = page.Image != null && !page.Image.IsDeleted ? page.Image.PublicThumbnailUrl : null,
                MainImageThumbnailUrl   = page.Image != null && !page.Image.IsDeleted ? page.Image.PublicThumbnailUrl : null,
                MainImageCaption        = page.Image != null && !page.Image.IsDeleted ? page.Image.Caption : null,
                IsArchived              = page.IsArchived,
                IsMasterPage            = page.IsMasterPage,
                LanguageId              = page.Language != null ? page.Language.Id : (Guid?)null,
                LanguageCode            = page.Language != null ? page.Language.Code : null,
                LanguageGroupIdentifier = page.LanguageGroupIdentifier
            })
                        .FirstOne();

            model.MainImageUrl           = fileUrlResolver.EnsureFullPathUrl(model.MainImageUrl);
            model.MainImageThumbnauilUrl = fileUrlResolver.EnsureFullPathUrl(model.MainImageThumbnauilUrl);
            model.MainImageThumbnailUrl  = fileUrlResolver.EnsureFullPathUrl(model.MainImageThumbnailUrl);

            return(new GetPageResponse {
                Data = model
            });
        }
Пример #5
0
        private string FixUrl(string url)
        {
            foreach (var ending in new[] { ".asp", ".aspx", ".php", ".htm", ".html" })
            {
                if (url.EndsWith(ending))
                {
                    url = url.Substring(0, url.LastIndexOf(ending, StringComparison.InvariantCulture));
                }
            }
            url = urlService.FixUrl(url);

            return(url);
        }
Пример #6
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The page view model.</param>
        /// <returns>Created page</returns>
        public virtual SavePageResponse Execute(AddNewPageViewModel request)
        {
            // Create / fix page url
            var pageUrl       = request.PageUrl;
            var createPageUrl = (pageUrl == null);

            if (createPageUrl && !string.IsNullOrWhiteSpace(request.PageTitle))
            {
                pageUrl = pageService.CreatePagePermalink(request.PageTitle, request.ParentPageUrl);
            }
            else
            {
                pageUrl = urlService.FixUrl(pageUrl);

                // Validate Url
                pageService.ValidatePageUrl(pageUrl);
            }

            var page = new PageProperties
            {
                PageUrl             = pageUrl,
                PageUrlLowerTrimmed = pageUrl.LowerTrimmedUrl(),
                Title     = request.PageTitle,
                MetaTitle = request.PageTitle,
                Layout    = Repository.First <Root.Models.Layout>(request.TemplateId),
                Status    = PageStatus.Unpublished
            };

            var parentOptions = Repository
                                .AsQueryable <LayoutOption>(o => o.Layout.Id == request.TemplateId)
                                .ToList();

            optionService.SaveOptionValues(request.OptionValues, null, parentOptions, () => new PageOption {
                Page = page
            });

            Repository.Save(page);

            // Update access control if enabled:
            if (cmsConfiguration.AccessControlEnabled)
            {
                accessControlService.UpdateAccessControl(request.UserAccessList, page.Id);
            }

            UnitOfWork.Commit();

            // Notifying, that page is created
            Events.PageEvents.Instance.OnPageCreated(page);

            return(new SavePageResponse(page));
        }
Пример #7
0
        private System.Guid?GetPageLanguageGroupIdentifier(GetPageTranslationsRequest request)
        {
            // Get page language group identifier
            var query = repository.AsQueryable <Module.Pages.Models.PageProperties>();

            if (request.PageId.HasValue)
            {
                query = query.Where(p => p.Id == request.PageId.Value);
            }
            else
            {
                var url = urlService.FixUrl(request.PageUrl);
                query = query.Where(p => p.PageUrl == url);
            }

            return(query.Select(p => p.LanguageGroupIdentifier).FirstOrDefault());
        }
Пример #8
0
        public PageExistsResponse Get(PageExistsRequest request)
        {
            var url = urlService.FixUrl(request.PageUrl);

            var id = repository
                     .AsQueryable <Module.Root.Models.Page>(p => p.PageUrlHash == url.UrlHash())
                     .Select(p => p.Id)
                     .FirstOrDefault();

            return(new PageExistsResponse
            {
                Data = new PageModel
                {
                    Exists = !id.HasDefaultValue(),
                    PageId = !id.HasDefaultValue() ? id : (System.Guid?)null
                }
            });
        }
Пример #9
0
        public GetPageResponse Get(GetPageRequest request)
        {
            var query = repository.AsQueryable <Module.Pages.Models.PageProperties>();

            if (request.PageId.HasValue)
            {
                query = query.Where(page => page.Id == request.PageId.Value);
            }
            else
            {
                var url = urlService.FixUrl(request.PageUrl);
                query = query.Where(page => page.PageUrl == url);
            }

            var model = query
                        .Select(page => new PageModel
            {
                Id             = page.Id,
                Version        = page.Version,
                CreatedBy      = page.CreatedByUser,
                CreatedOn      = page.CreatedOn,
                LastModifiedBy = page.ModifiedByUser,
                LastModifiedOn = page.ModifiedOn,

                PageUrl                = page.PageUrl,
                Title                  = page.Title,
                Description            = page.Description,
                IsPublished            = page.Status == PageStatus.Published,
                PublishedOn            = page.PublishedOn,
                LayoutId               = page.Layout.Id,
                CategoryId             = page.Category.Id,
                CategoryName           = page.Category.Name,
                MainImageId            = page.Image.Id,
                MainImageUrl           = page.Image.PublicUrl,
                MainImageThumbnauilUrl = page.Image.PublicThumbnailUrl,
                MainImageCaption       = page.Image.Caption,
                IsArchived             = page.IsArchived
            })
                        .FirstOne();

            return(new GetPageResponse {
                Data = model
            });
        }
Пример #10
0
        /// <summary>
        /// Finds the redirect.
        /// </summary>
        /// <param name="source">The source url.</param>
        /// <returns>
        /// Destination url
        /// </returns>
        public string FindRedirect(string source)
        {
            string redirectDestinationUrl = null;
            var    useCache = cmsConfiguration.Cache.Enabled;

            if (urlService.ValidateInternalUrl(source))
            {
                source = urlService.FixUrl(source);
            }
            if (useCache)
            {
                var redirects = cacheService.Get(cacheKey, cmsConfiguration.Cache.Timeout, () => redirectService.GetAllRedirects());
                redirectDestinationUrl = redirects.Where(x => x.PageUrl.Equals(source, StringComparison.InvariantCultureIgnoreCase)).Select(x => x.RedirectUrl).FirstOrDefault();
            }
            else
            {
                return(redirectService.GetRedirect(source));
            }

            return(redirectDestinationUrl);
        }
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Save response.</returns>
        /// <exception cref="CmsException">Failed to save page properties.</exception>
        public SavePageResponse Execute(EditPagePropertiesViewModel request)
        {
            var isMultilanguageEnabled = cmsConfiguration.EnableMultilanguage;

            ValidateRequest(request, isMultilanguageEnabled);

            var pageQuery =
                Repository.AsQueryable <PageProperties>(p => p.Id == request.Id)
                .FetchMany(p => p.Options)
                .Fetch(p => p.Layout)
                .ThenFetchMany(l => l.LayoutOptions)
                .FetchMany(p => p.MasterPages)
                .AsQueryable();

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                pageQuery = pageQuery.FetchMany(f => f.AccessRules);
            }

            var page         = pageQuery.ToList().FirstOne();
            var beforeChange = new UpdatingPagePropertiesModel(page);

            var roles = page.IsMasterPage
                            ? new[]
            {
                RootModuleConstants.UserRoles.EditContent, RootModuleConstants.UserRoles.PublishContent, RootModuleConstants.UserRoles.Administration
            }
                            : new[] { RootModuleConstants.UserRoles.EditContent, RootModuleConstants.UserRoles.PublishContent };

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                AccessControlService.DemandAccess(page, Context.Principal, AccessLevel.ReadWrite, roles);
            }
            else
            {
                AccessControlService.DemandAccess(Context.Principal, roles);
            }

            var canEdit = page.IsMasterPage
                              ? SecurityService.IsAuthorized(
                Context.Principal,
                RootModuleConstants.UserRoles.MultipleRoles(RootModuleConstants.UserRoles.EditContent, RootModuleConstants.UserRoles.Administration))
                              : SecurityService.IsAuthorized(Context.Principal, RootModuleConstants.UserRoles.EditContent);

            IList <PageProperties> translations = null;

            if (canEdit && isMultilanguageEnabled && !page.IsMasterPage)
            {
                translations = LoadAndValidateTranslations(page, request);
            }

            // Load master pages for updating page's master path and page's children master path
            IList <Guid>       newMasterIds;
            IList <Guid>       oldMasterIds;
            IList <Guid>       childrenPageIds;
            IList <MasterPage> existingChildrenMasterPages;

            masterPageService.PrepareForUpdateChildrenMasterPages(page, request.MasterPageId, out newMasterIds, out oldMasterIds, out childrenPageIds, out existingChildrenMasterPages);

            IList <SitemapNode> updatedNodes = null;

            // Start transaction, only when everything is already loaded
            UnitOfWork.BeginTransaction();

            Models.Redirect redirectCreated  = null;
            var             initialSeoStatus = page.HasSEO;

            request.PageUrl = urlService.FixUrl(request.PageUrl);

            if (canEdit && !string.Equals(page.PageUrl, request.PageUrl))
            {
                pageService.ValidatePageUrl(request.PageUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(page.PageUrl, request.PageUrl);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                if (request.UpdateSitemap)
                {
                    updatedNodes = sitemapService.ChangeUrlsInAllSitemapsNodes(page.PageUrl, request.PageUrl);
                }

                page.PageUrl = request.PageUrl;
            }

            List <PageProperties> updatePageTranslations = null;

            if (canEdit)
            {
                page.PageUrlHash         = page.PageUrl.UrlHash();
                page.ForceAccessProtocol = request.ForceAccessProtocol;

                categoryService.CombineEntityCategories <PageProperties, PageCategory>(page, request.Categories);

                page.Title     = request.PageName;
                page.CustomCss = request.PageCSS;
                page.CustomJS  = request.PageJavascript;

                masterPageService.SetMasterOrLayout(page, request.MasterPageId, request.TemplateId);

                if (isMultilanguageEnabled && !page.IsMasterPage)
                {
                    updatePageTranslations = UpdatePageTranslations(page, translations, request);
                }
            }

            var publishDraftContent = false;

            if (request.CanPublishPage && !page.IsMasterPage)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent);

                if (request.IsPagePublished)
                {
                    if (page.Status != PageStatus.Published)
                    {
                        page.Status         = PageStatus.Published;
                        page.PublishedOn    = DateTime.Now;
                        publishDraftContent = true;
                    }
                }
                else
                {
                    page.Status = PageStatus.Unpublished;
                }
            }

            IList <PageOption> pageOptions = page.Options.Distinct().ToList();

            if (canEdit)
            {
                if (!page.IsMasterPage)
                {
                    page.UseNoFollow = request.UseNoFollow;
                    page.UseNoIndex  = request.UseNoIndex;
                    page.IsArchived  = request.IsArchived;
                }

                page.UseCanonicalUrl = request.UseCanonicalUrl;
                page.Version         = request.Version;

                page.Image          = request.Image != null && request.Image.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                page.SecondaryImage = request.SecondaryImage != null && request.SecondaryImage.ImageId.HasValue
                                          ? Repository.AsProxy <MediaImage>(request.SecondaryImage.ImageId.Value)
                                          : null;
                page.FeaturedImage = request.FeaturedImage != null && request.FeaturedImage.ImageId.HasValue
                                         ? Repository.AsProxy <MediaImage>(request.FeaturedImage.ImageId.Value)
                                         : null;

                pageOptions = optionService.SaveOptionValues(request.OptionValues, pageOptions, () => new PageOption {
                    Page = page
                });

                if (cmsConfiguration.Security.AccessControlEnabled)
                {
                    page.AccessRules.RemoveDuplicateEntities();

                    var accessRules = request.UserAccessList != null?request.UserAccessList.Cast <IAccessRule>().ToList() : null;

                    accessControlService.UpdateAccessControl(page, accessRules);
                }
            }

            // Notify about page properties changing.
            var cancelEventArgs = Events.PageEvents.Instance.OnPagePropertiesChanging(beforeChange, new UpdatingPagePropertiesModel(page));

            if (cancelEventArgs.Cancel)
            {
                Context.Messages.AddError(cancelEventArgs.CancellationErrorMessages.ToArray());
                return(null);
            }

            Repository.Save(page);

            IList <Tag> newTags = null;

            if (canEdit)
            {
                masterPageService.UpdateChildrenMasterPages(existingChildrenMasterPages, oldMasterIds, newMasterIds, childrenPageIds);
                tagService.SavePageTags(page, request.Tags, out newTags);
            }

            if (publishDraftContent)
            {
                contentService.PublishDraftContent(page.Id);
            }

            UnitOfWork.Commit();

            // Notify about page properties change.
            page.Options = pageOptions;
            Events.PageEvents.Instance.OnPagePropertiesChanged(page);

            // Notify about translation properties changed
            if (updatePageTranslations != null)
            {
                updatePageTranslations.ForEach(Events.PageEvents.Instance.OnPagePropertiesChanged);
            }

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            // Notify about SEO status change.
            if (initialSeoStatus != page.HasSEO)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about updated sitemap nodes.
            if (updatedNodes != null)
            {
                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 updatedSitemap in updatedSitemaps)
                {
                    Events.SitemapEvents.Instance.OnSitemapUpdated(updatedSitemap);
                }
            }

            return(new SavePageResponse(page));
        }
Пример #12
0
        /// <summary>
        /// Saves SEO information.
        /// </summary>
        /// <param name="model">The SEO information model.</param>
        /// <returns>
        /// true if SEO information saved successfully; false otherwise.
        /// </returns>
        public virtual EditSeoViewModel Execute(EditSeoViewModel model)
        {
            var page = Repository.First <PageProperties>(model.PageId);

            bool initialHasSeo = page.HasSEO;

            Models.Redirect newRedirect = null;

            page.Version = model.Version;
            page.Title   = model.PageTitle;

            model.ChangedUrlPath = urlService.FixUrl(model.ChangedUrlPath);

            IList <SitemapNode> updatedNodes = null;

            if (!string.Equals(model.PageUrlPath, model.ChangedUrlPath))
            {
                pageService.ValidatePageUrl(model.ChangedUrlPath, model.PageId);

                if (model.CreatePermanentRedirect)
                {
                    var redirect = redirectService.CreateRedirectEntity(model.PageUrlPath, model.ChangedUrlPath);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        newRedirect = redirect;
                    }
                }

                if (model.UpdateSitemap)
                {
                    updatedNodes = sitemapService.ChangeUrlsInAllSitemapsNodes(page.PageUrl, model.ChangedUrlPath);
                }

                page.PageUrl = model.ChangedUrlPath;
            }

            page.PageUrlHash     = page.PageUrl.UrlHash();
            page.MetaTitle       = model.MetaTitle;
            page.MetaKeywords    = model.MetaKeywords;
            page.MetaDescription = model.MetaDescription;
            page.UseCanonicalUrl = model.UseCanonicalUrl;

            Repository.Save(page);
            UnitOfWork.Commit();

            // Notify about SEO change.
            if (page.HasSEO != initialHasSeo)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new redirect creation.
            if (newRedirect != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(newRedirect);
            }

            // Notify about updated sitemap nodes.
            if (updatedNodes != null)
            {
                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 updatedSitemap in updatedSitemaps)
                {
                    Events.SitemapEvents.Instance.OnSitemapUpdated(updatedSitemap);
                }
            }

            return(new EditSeoViewModel {
                PageUrlPath = page.PageUrl
            });
        }
Пример #13
0
        /// <summary>
        /// Saves SEO information.
        /// </summary>
        /// <param name="model">The SEO information model.</param>
        /// <returns>
        /// true if SEO information saved successfully; false otherwise.
        /// </returns>
        public virtual EditSeoViewModel Execute(EditSeoViewModel model)
        {
            var pageQuery =
                Repository.AsQueryable <PageProperties>(p => p.Id == model.PageId)
                .FetchMany(p => p.Options)
                .Fetch(p => p.Layout)
                .ThenFetchMany(l => l.LayoutOptions)
                .FetchMany(p => p.MasterPages)
                .AsQueryable();

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                pageQuery = pageQuery.FetchMany(f => f.AccessRules);
            }

            var page         = pageQuery.ToList().FirstOne();
            var beforeChange = new UpdatingPagePropertiesModel(page);

            var roles = new[] { RootModuleConstants.UserRoles.EditContent };

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                AccessControlService.DemandAccess(page, Context.Principal, AccessLevel.ReadWrite, roles);
            }
            else
            {
                AccessControlService.DemandAccess(Context.Principal, roles);
            }

            bool initialHasSeo = page.HasSEO;

            Models.Redirect newRedirect = null;

            page.Version = model.Version;
            page.Title   = model.PageTitle;

            model.ChangedUrlPath = urlService.FixUrl(model.ChangedUrlPath);

            IList <SitemapNode> updatedNodes = null;

            if (!string.Equals(model.PageUrlPath, model.ChangedUrlPath))
            {
                pageService.ValidatePageUrl(model.ChangedUrlPath, model.PageId);

                if (model.CreatePermanentRedirect)
                {
                    var redirect = redirectService.CreateRedirectEntity(model.PageUrlPath, model.ChangedUrlPath);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        newRedirect = redirect;
                    }
                }

                if (model.UpdateSitemap)
                {
                    updatedNodes = sitemapService.ChangeUrlsInAllSitemapsNodes(page.PageUrl, model.ChangedUrlPath);
                }

                page.PageUrl = model.ChangedUrlPath;
            }

            page.PageUrlHash     = page.PageUrl.UrlHash();
            page.MetaTitle       = model.MetaTitle;
            page.MetaKeywords    = model.MetaKeywords;
            page.MetaDescription = model.MetaDescription;
            page.UseCanonicalUrl = model.UseCanonicalUrl;

            // Notify about page properties changing.
            var cancelEventArgs = Events.PageEvents.Instance.OnPagePropertiesChanging(beforeChange, new UpdatingPagePropertiesModel(page));

            if (cancelEventArgs.Cancel)
            {
                Context.Messages.AddError(cancelEventArgs.CancellationErrorMessages.ToArray());
                return(null);
            }

            Repository.Save(page);
            UnitOfWork.Commit();

            Events.PageEvents.Instance.OnPagePropertiesChanged(page);

            // Notify about SEO change.
            if (page.HasSEO != initialHasSeo)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new redirect creation.
            if (newRedirect != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(newRedirect);
            }

            // Notify about updated sitemap nodes.
            if (updatedNodes != null)
            {
                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 updatedSitemap in updatedSitemaps)
                {
                    Events.SitemapEvents.Instance.OnSitemapUpdated(updatedSitemap);
                }
            }

            return(new EditSeoViewModel {
                PageUrlPath = page.PageUrl
            });
        }
Пример #14
0
        /// <summary>
        /// Executes a command to save a redirect.
        /// </summary>
        /// <param name="request">The redirect view model.</param>
        /// <returns>
        /// Saved redirect view model.
        /// </returns>
        public SiteSettingRedirectViewModel Execute(SiteSettingRedirectViewModel request)
        {
            Models.Redirect redirect;

            request.PageUrl     = urlService.FixUrl(request.PageUrl);
            request.RedirectUrl = urlService.FixUrl(request.RedirectUrl);

            // Validate request
            if (!urlService.ValidateUrl(request.PageUrl))
            {
                var message    = PagesGlobalization.SaveRedirect_InvalidPageUrl_Message;
                var logMessage = string.Format("Invalid page url {0}.", request.PageUrl);
                throw new ValidationException(() => message, logMessage);
            }
            if (!urlService.ValidateUrl(request.RedirectUrl))
            {
                var message    = PagesGlobalization.SaveRedirect_InvalidRedirectUrl_Message;
                var logMessage = string.Format("Invalid redirect url {0}.", request.RedirectUrl);
                throw new ValidationException(() => message, logMessage);
            }

            // Validate for url patterns
            string patternsValidationMessage;

            if (!urlService.ValidateUrlPatterns(request.PageUrl, out patternsValidationMessage))
            {
                var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, request.PageUrl);
                throw new ValidationException(() => patternsValidationMessage, logMessage);
            }
            if (!urlService.ValidateUrlPatterns(request.RedirectUrl, out patternsValidationMessage, PagesGlobalization.SaveRedirect_RedirectUrl_Name))
            {
                var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, request.PageUrl);
                throw new ValidationException(() => patternsValidationMessage, logMessage);
            }

            redirectService.ValidateRedirectExists(request.PageUrl, request.Id);
            redirectService.ValidateForCircularLoop(request.PageUrl, request.RedirectUrl, request.Id);

            if (request.Id.HasDefaultValue())
            {
                redirect = new Models.Redirect();
            }
            else
            {
                redirect = Repository.First <Models.Redirect>(request.Id);
            }

            redirect.Version     = request.Version;
            redirect.PageUrl     = request.PageUrl;
            redirect.RedirectUrl = request.RedirectUrl;

            Repository.Save(redirect);
            UnitOfWork.Commit();

            // Notify.
            if (request.Id.HasDefaultValue())
            {
                PagesApiContext.Events.OnRedirectCreated(redirect);
            }
            else
            {
                PagesApiContext.Events.OnRedirectUpdated(redirect);
            }

            return(new SiteSettingRedirectViewModel
            {
                Id = redirect.Id,
                Version = redirect.Version,
                PageUrl = redirect.PageUrl,
                RedirectUrl = redirect.RedirectUrl
            });
        }
Пример #15
0
        /// <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()
                       .FirstOne();

            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);
        }
Пример #16
0
        /// <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);
        }
Пример #17
0
        public GetPagePropertiesResponse Get(GetPagePropertiesRequest request)
        {
            var query = repository.AsQueryable <Module.Pages.Models.PageProperties>();

            if (request.PageId.HasValue)
            {
                query = query.Where(page => page.Id == request.PageId.Value);
            }
            else
            {
                var url = urlService.FixUrl(request.PageUrl);
                query = query.Where(page => page.PageUrlHash == url.UrlHash());
            }

            var response = query
                           .Select(page => new GetPagePropertiesResponse
            {
                Data = new PagePropertiesModel
                {
                    Id             = page.Id,
                    Version        = page.Version,
                    CreatedBy      = page.CreatedByUser,
                    CreatedOn      = page.CreatedOn,
                    LastModifiedBy = page.ModifiedByUser,
                    LastModifiedOn = page.ModifiedOn,

                    PageUrl                 = page.PageUrl,
                    Title                   = page.Title,
                    Description             = page.Description,
                    IsPublished             = page.Status == PageStatus.Published,
                    PublishedOn             = page.PublishedOn,
                    LayoutId                = page.Layout != null && !page.Layout.IsDeleted ? page.Layout.Id : Guid.Empty,
                    CategoryId              = page.Category != null && !page.Category.IsDeleted ? page.Category.Id : (Guid?)null,
                    IsArchived              = page.IsArchived,
                    IsMasterPage            = page.IsMasterPage,
                    LanguageGroupIdentifier = page.LanguageGroupIdentifier,
                    LanguageId              = page.Language != null ? page.Language.Id : (Guid?)null,
                    MainImageId             = page.Image != null && !page.Image.IsDeleted ? page.Image.Id : (Guid?)null,
                    FeaturedImageId         = page.FeaturedImage != null && !page.FeaturedImage.IsDeleted ?  page.FeaturedImage.Id : (Guid?)null,
                    SecondaryImageId        = page.SecondaryImage != null && !page.SecondaryImage.IsDeleted ? page.SecondaryImage.Id : (Guid?)null,
                    CustomCss               = page.CustomCss,
                    CustomJavaScript        = page.CustomJS,
                    UseCanonicalUrl         = page.UseCanonicalUrl,
                    UseNoFollow             = page.UseNoFollow,
                    UseNoIndex              = page.UseNoIndex
                },
                MetaData = request.Data.IncludeMetaData
                            ? new MetadataModel
                {
                    MetaTitle       = page.MetaTitle,
                    MetaDescription = page.MetaDescription,
                    MetaKeywords    = page.MetaKeywords
                }
                            : null,
                Category = page.Category != null && !page.Category.IsDeleted && request.Data.IncludeCategory
                            ? new CategoryModel
                {
                    Id             = page.Category.Id,
                    Version        = page.Category.Version,
                    CreatedBy      = page.Category.CreatedByUser,
                    CreatedOn      = page.Category.CreatedOn,
                    LastModifiedBy = page.Category.ModifiedByUser,
                    LastModifiedOn = page.Category.ModifiedOn,
                    Name           = page.Category.Name
                } : null,
                Layout = request.Data.IncludeLayout && !page.Layout.IsDeleted
                            ? new LayoutModel
                {
                    Id             = page.Layout.Id,
                    Version        = page.Layout.Version,
                    CreatedBy      = page.Layout.CreatedByUser,
                    CreatedOn      = page.Layout.CreatedOn,
                    LastModifiedBy = page.Layout.ModifiedByUser,
                    LastModifiedOn = page.Layout.ModifiedOn,

                    Name       = page.Layout.Name,
                    LayoutPath = page.Layout.LayoutPath,
                    PreviewUrl = page.Layout.PreviewUrl
                }
                            : null,
                MainImage = page.Image != null && !page.Image.IsDeleted && request.Data.IncludeImages
                            ? new ImageModel
                {
                    Id             = page.Image.Id,
                    Version        = page.Image.Version,
                    CreatedBy      = page.Image.CreatedByUser,
                    CreatedOn      = page.Image.CreatedOn,
                    LastModifiedBy = page.Image.ModifiedByUser,
                    LastModifiedOn = page.Image.ModifiedOn,

                    Title        = page.Image.Title,
                    Caption      = page.Image.Caption,
                    Url          = fileUrlResolver.EnsureFullPathUrl(page.Image.PublicUrl),
                    ThumbnailUrl = fileUrlResolver.EnsureFullPathUrl(page.Image.PublicThumbnailUrl)
                }
                            : null,
                FeaturedImage = page.FeaturedImage != null && !page.FeaturedImage.IsDeleted && request.Data.IncludeImages
                            ? new ImageModel
                {
                    Id             = page.FeaturedImage.Id,
                    Version        = page.FeaturedImage.Version,
                    CreatedBy      = page.FeaturedImage.CreatedByUser,
                    CreatedOn      = page.FeaturedImage.CreatedOn,
                    LastModifiedBy = page.FeaturedImage.ModifiedByUser,
                    LastModifiedOn = page.FeaturedImage.ModifiedOn,

                    Title        = page.FeaturedImage.Title,
                    Caption      = page.FeaturedImage.Caption,
                    Url          = fileUrlResolver.EnsureFullPathUrl(page.FeaturedImage.PublicUrl),
                    ThumbnailUrl = fileUrlResolver.EnsureFullPathUrl(page.FeaturedImage.PublicThumbnailUrl)
                }
                            : null,
                SecondaryImage = page.SecondaryImage != null && !page.SecondaryImage.IsDeleted && request.Data.IncludeImages
                            ? new ImageModel
                {
                    Id             = page.SecondaryImage.Id,
                    Version        = page.SecondaryImage.Version,
                    CreatedBy      = page.SecondaryImage.CreatedByUser,
                    CreatedOn      = page.SecondaryImage.CreatedOn,
                    LastModifiedBy = page.SecondaryImage.ModifiedByUser,
                    LastModifiedOn = page.SecondaryImage.ModifiedOn,

                    Title        = page.SecondaryImage.Title,
                    Caption      = page.SecondaryImage.Caption,
                    Url          = fileUrlResolver.EnsureFullPathUrl(page.SecondaryImage.PublicUrl),
                    ThumbnailUrl = fileUrlResolver.EnsureFullPathUrl(page.SecondaryImage.PublicThumbnailUrl)
                }
                            : null,
                Language = page.Language != null && !page.Language.IsDeleted && request.Data.IncludeLanguage
                            ? new LanguageModel
                {
                    Id             = page.Language.Id,
                    Version        = page.Language.Version,
                    CreatedBy      = page.Language.CreatedByUser,
                    CreatedOn      = page.Language.CreatedOn,
                    LastModifiedBy = page.Language.ModifiedByUser,
                    LastModifiedOn = page.Language.ModifiedOn,

                    Name = page.Language.Name,
                    Code = page.Language.Code,
                } : null,
            })
                           .FirstOne();

            if (request.Data.IncludeTags)
            {
                response.Tags = LoadTags(response.Data.Id);
            }

            if (request.Data.IncludePageContents)
            {
                response.PageContents = LoadPageContents(response.Data.Id);
            }

            if (request.Data.IncludePageOptions)
            {
                // Get layout options, page options and merge them
                var layoutOptions = repository
                                    .AsQueryable <LayoutOption>(lo => lo.Layout.Id == response.Data.LayoutId).ToList();
                var pageOptions = repository
                                  .AsQueryable <PageOption>(p => p.Page.Id == response.Data.Id)
                                  .ToList();

                response.PageOptions = optionService
                                       .GetMergedOptionValuesForEdit(layoutOptions, pageOptions)
                                       .Select(o => new OptionModel
                {
                    Key          = o.OptionKey,
                    Value        = o.OptionValue,
                    DefaultValue = o.OptionDefaultValue,
                    Type         = ((Root.OptionType)(int) o.Type)
                })
                                       .ToList();
            }

            if (request.Data.IncludePageTranslations &&
                response.Data.LanguageGroupIdentifier.HasValue)
            {
                // Get layout options, page options and merge them
                response.PageTranslations = repository
                                            .AsQueryable <Module.Pages.Models.PageProperties>()
                                            .Where(p => p.LanguageGroupIdentifier == response.Data.LanguageGroupIdentifier)
                                            .OrderBy(p => p.Title)
                                            .Select(p => new PageTranslationModel
                {
                    Id           = p.Id,
                    Title        = p.Title,
                    PageUrl      = p.PageUrl,
                    LanguageId   = p.Language != null ? p.Language.Id: (Guid?)null,
                    LanguageCode = p.Language != null ? p.Language.Code : null,
                })
                                            .ToList();
            }

            return(response);
        }
Пример #18
0
        private PageProperties ClonePage(System.Guid pageId, string pageTitle, string pageUrl,
                                         IEnumerable <IAccessRule> userAccessList, bool cloneAsMasterPage, System.Guid?languageId, System.Guid?languageGroupIdentifier)
        {
            var principal = securityService.GetCurrentPrincipal();

            if (cloneAsMasterPage)
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.Administration);
            }
            else
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent);
            }

            // Create / fix page url
            if (pageUrl == null && !string.IsNullOrWhiteSpace(pageTitle))
            {
                pageUrl = pageService.CreatePagePermalink(pageTitle, null, pageId, languageId);
            }
            else
            {
                pageUrl = urlService.FixUrl(pageUrl);
                pageService.ValidatePageUrl(pageUrl);
            }

            var page = repository
                       .AsQueryable <PageProperties>()
                       .Where(f => f.Id == pageId)
                       .FetchMany(f => f.Options)
                       .FetchMany(f => f.Categories).ThenFetch(c => c.Category).ThenFetch(c => c.CategoryTree)
                       .FetchMany(f => f.PageContents).ThenFetch(f => f.Region)
                       .FetchMany(f => f.PageContents).ThenFetch(f => f.Content)
                       .FetchMany(f => f.PageContents).ThenFetchMany(f => f.Options)
                       .FetchMany(f => f.PageTags).ThenFetch(f => f.Tag)
                       .FetchMany(f => f.MasterPages).ThenFetch(f => f.Master)
                       .ToList().FirstOne();

            ValidateCloningPage(page, languageId, languageGroupIdentifier);

            unitOfWork.BeginTransaction();

            // Detach page to avoid duplicate saving.
            repository.Detach(page);
            repository.Detach(page.MasterPage);
            page.MasterPages.ForEach(mp => repository.Detach(mp.Master));
            page.PageContents.ForEach(repository.Detach);
            page.PageTags.ForEach(repository.Detach);
            page.Options.ForEach(repository.Detach);
            page.Categories.ForEach(repository.Detach);
            page.SaveUnsecured = true;

            var pageContents   = page.PageContents.Distinct().ToList();
            var pageTags       = page.PageTags.Distinct().ToList();
            var pageOptions    = page.Options.Distinct().ToList();
            var pageCategories = page.Categories.Distinct().ToList();

            var masterPages = page.MasterPages != null?page.MasterPages.Distinct().ToList() : new List <MasterPage>();

            // Clone page with security
            var newPage = ClonePageOnly(page, userAccessList, pageTitle, pageUrl, cloneAsMasterPage);

            if (languageId.HasValue)
            {
                if (languageId.Value.HasDefaultValue())
                {
                    newPage.Language = null;
                }
                else
                {
                    newPage.Language = repository.AsProxy <Language>(languageId.Value);
                }
            }
            if (languageGroupIdentifier.HasValue)
            {
                newPage.LanguageGroupIdentifier = languageGroupIdentifier.Value;
            }
            else
            {
                newPage.LanguageGroupIdentifier = null;
            }

            repository.Save(newPage);

            // Clone contents.
            var createdContents             = new List <Root.Models.Content>();
            var createdPageContents         = new List <PageContent>();
            var clonedPageContentReferences = new Dictionary <PageContent, PageContent>(pageContents.Count);

            pageContents.ForEach(pageContent => ClonePageContent(pageContent, newPage, createdContents, createdPageContents, clonedPageContentReferences));
            UpdateParentPageContents(pageContents, clonedPageContentReferences);

            // Clone tags.
            pageTags.ForEach(pageTag => ClonePageTags(pageTag, newPage));

            // Clone options.
            pageOptions.ForEach(pageOption => ClonePageOption(pageOption, newPage));

            // Clone master pages
            masterPages.ForEach(masterPage => CloneMasterPages(masterPage, newPage));

            // Clone categories pages
            pageCategories.ForEach(category => CloneCategories(category, newPage));

            // Set language identifier for parent page, if it hasn't and child is cloned from the parent.
            var parentChanged = false;

            if (languageGroupIdentifier.HasValue && !page.LanguageGroupIdentifier.HasValue)
            {
                page.LanguageGroupIdentifier = languageGroupIdentifier.Value;
                parentChanged = true;
                repository.Save(page);
            }

            unitOfWork.Commit();

            // Fire events. (NOTE: do not change event order!!!)
            Events.PageEvents.Instance.OnPageCloned(newPage);
            createdContents.Where(c => c is HtmlContent).ForEach(c => Events.PageEvents.Instance.OnHtmlContentCreated((HtmlContent)c));
            createdPageContents.ForEach(Events.PageEvents.Instance.OnPageContentInserted);

            // Fire event about parent page changes
            if (parentChanged)
            {
                Events.PageEvents.Instance.OnPagePropertiesChanged(page);
            }

            return(newPage);
        }
Пример #19
0
        /// <summary>
        /// Saves the blog post.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="principal">The principal.</param>
        /// <returns>
        /// Saved blog post entity
        /// </returns>
        public BlogPost SaveBlogPost(BlogPostViewModel request, IPrincipal principal)
        {
            string[] roles;
            if (request.DesirableStatus == ContentStatus.Published)
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent);
                roles = new[] { RootModuleConstants.UserRoles.PublishContent };
            }
            else
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent);
                roles = new[] { RootModuleConstants.UserRoles.EditContent };
            }

            Layout layout;
            Page   masterPage;

            LoadLayout(out layout, out masterPage);

            if (masterPage != null)
            {
                var level = accessControlService.GetAccessLevel(masterPage, principal);
                if (level < AccessLevel.Read)
                {
                    var          message    = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage;
                    const string logMessage = "Failed to save blog post. Selected master page for page layout is inaccessible.";
                    throw new ValidationException(() => message, logMessage);
                }
            }

            var region      = LoadRegion(layout, masterPage);
            var isNew       = request.Id.HasDefaultValue();
            var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent);

            // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception.

            BlogPost        blogPost;
            BlogPostContent content     = null;
            PageContent     pageContent = null;

            Pages.Models.Redirect redirectCreated = null;

            // Loading blog post and it's content, or creating new, if such not exists
            if (!isNew)
            {
                var blogPostFuture = repository
                                     .AsQueryable <BlogPost>(b => b.Id == request.Id)
                                     .ToFuture();

                content = repository
                          .AsQueryable <BlogPostContent>(c => c.PageContents.Any(x => x.Page.Id == request.Id && !x.IsDeleted))
                          .ToFuture()
                          .FirstOrDefault();

                blogPost = blogPostFuture.FirstOne();

                if (cmsConfiguration.Security.AccessControlEnabled)
                {
                    accessControlService.DemandAccess(blogPost, principal, AccessLevel.ReadWrite, roles);
                }

                if (content != null)
                {
                    // Check if user has confirmed the deletion of content
                    if (!request.IsUserConfirmed && blogPost.IsMasterPage)
                    {
                        var hasAnyChildren = contentService.CheckIfContentHasDeletingChildren(blogPost.Id, content.Id, request.Content);
                        if (hasAnyChildren)
                        {
                            var message    = PagesGlobalization.SaveContent_ContentHasChildrenContents_RegionDeleteConfirmationMessage;
                            var logMessage = string.Format("User is trying to delete content regions which has children contents. Confirmation is required. ContentId: {0}, PageId: {1}",
                                                           content.Id, blogPost.Id);
                            throw new ConfirmationRequestException(() => message, logMessage);
                        }
                    }

                    pageContent = repository.FirstOrDefault <PageContent>(c => c.Page == blogPost && !c.IsDeleted && c.Content == content);
                }

                if (userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && request.BlogUrl != null)
                {
                    request.BlogUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(request.BlogUrl, request.Id);
                    if (request.RedirectFromOldUrl)
                    {
                        var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl);
                        if (redirect != null)
                        {
                            repository.Save(redirect);
                            redirectCreated = redirect;
                        }
                    }

                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                }
            }
            else
            {
                blogPost = new BlogPost();
            }

            if (pageContent == null)
            {
                pageContent = new PageContent {
                    Region = region, Page = blogPost
                };
            }

            // Push to change modified data each time.
            blogPost.ModifiedOn = DateTime.Now;
            blogPost.Version    = request.Version;

            if (userCanEdit)
            {
                blogPost.Title       = request.Title;
                blogPost.Description = request.IntroText;
                blogPost.Author      = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null;
                blogPost.Category    = request.CategoryId.HasValue ? repository.AsProxy <Category>(request.CategoryId.Value) : null;
                blogPost.Image       = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                if (isNew || request.DesirableStatus == ContentStatus.Published)
                {
                    blogPost.ActivationDate = request.LiveFromDate;
                    blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate);
                }
            }

            if (isNew)
            {
                if (!string.IsNullOrWhiteSpace(request.BlogUrl))
                {
                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(blogPost.PageUrl);
                }
                else
                {
                    blogPost.PageUrl = CreateBlogPermalink(request.Title);
                }

                blogPost.MetaTitle = request.MetaTitle ?? request.Title;
                if (masterPage != null)
                {
                    blogPost.MasterPage = masterPage;
                    masterPageService.SetPageMasterPages(blogPost, masterPage.Id);
                }
                else
                {
                    blogPost.Layout = layout;
                }
                UpdateStatus(blogPost, request.DesirableStatus);
                AddDefaultAccessRules(blogPost, principal, masterPage);
            }
            else if (request.DesirableStatus == ContentStatus.Published ||
                     blogPost.Status == PageStatus.Preview)
            {
                // Update only if publishing or current status is preview.
                // Else do not change, because it may change from published to draft status
                UpdateStatus(blogPost, request.DesirableStatus);
            }

            // Create content.
            var newContent = new BlogPostContent
            {
                Id               = content != null ? content.Id : Guid.Empty,
                Name             = request.Title,
                Html             = request.Content ?? string.Empty,
                EditInSourceMode = request.EditInSourceMode,
                ActivationDate   = request.LiveFromDate,
                ExpirationDate   = TimeHelper.FormatEndDate(request.LiveToDate)
            };

            // Preserve content if user is not authorized to change it.
            if (!userCanEdit)
            {
                if (content == null)
                {
                    throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content.
                }

                var contentToPublish = (BlogPostContent)(content.History != null
                    ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content
                    : content);

                newContent.Name = contentToPublish.Name;
                newContent.Html = contentToPublish.Html;
            }

            content             = (BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus);
            pageContent.Content = content;

            blogPost.PageUrlHash     = blogPost.PageUrl.UrlHash();
            blogPost.UseCanonicalUrl = request.UseCanonicalUrl;

            repository.Save(blogPost);
            repository.Save(content);
            repository.Save(pageContent);

            pageContent.Content   = content;
            blogPost.PageContents = new [] { pageContent };

            IList <Tag> newTags = null;

            if (userCanEdit)
            {
                tagService.SavePageTags(blogPost, request.Tags, out newTags);
            }

            // Commit
            unitOfWork.Commit();

            // Notify about new or updated blog post.
            if (isNew)
            {
                Events.BlogEvents.Instance.OnBlogCreated(blogPost);
            }
            else
            {
                Events.BlogEvents.Instance.OnBlogUpdated(blogPost);
            }

            // Notify about new created tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            return(blogPost);
        }
Пример #20
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Save response.</returns>
        /// <exception cref="CmsException">Failed to save page properties.</exception>
        public SavePageResponse Execute(EditPagePropertiesViewModel request)
        {
            UnitOfWork.BeginTransaction();

            var page = Repository.First <PageProperties>(request.Id);

            Models.Redirect redirectCreated  = null;
            bool            initialSeoStatus = page.HasSEO;

            request.PageUrl = urlService.FixUrl(request.PageUrl);

            if (!string.Equals(page.PageUrl, request.PageUrl, StringComparison.OrdinalIgnoreCase))
            {
                pageService.ValidatePageUrl(request.PageUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(page.PageUrl, request.PageUrl);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                page.NodeCountInSitemap = request.UpdateSitemap
                    ? sitemapService.ChangeUrl(page.PageUrl, request.PageUrl)
                    : sitemapService.NodesWithUrl(request.PageUrl);

                page.PageUrl = request.PageUrl;
            }

            page.Layout      = Repository.AsProxy <Root.Models.Layout>(request.TemplateId);
            page.Category    = request.CategoryId.HasValue ? Repository.AsProxy <Category>(request.CategoryId.Value) : null;
            page.Title       = request.PageName;
            page.CustomCss   = request.PageCSS;
            page.CustomJS    = request.PageJavascript;
            page.IsPublic    = request.IsVisibleToEveryone;
            page.UseNoFollow = request.UseNoFollow;
            page.UseNoIndex  = request.UseNoIndex;
            page.Version     = request.Version;

            if (request.Image != null && request.Image.ImageId.HasValue)
            {
                page.Image = Repository.AsProxy <MediaImage>(request.Image.ImageId.Value);
            }
            else
            {
                page.Image = null;
            }

            Repository.Save(page);

            // Save tags
            IList <Root.Models.Tag> newTags;

            tagService.SavePageTags(page, request.Tags, out newTags);

            UnitOfWork.Commit();

            // Notify about page properties change.
            PagesApiContext.Events.OnPagePropertiesChanged(page);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                PagesApiContext.Events.OnRedirectCreated(redirectCreated);
            }

            // Notify about SEO status change.
            if (initialSeoStatus != page.HasSEO)
            {
                PagesApiContext.Events.OnPageSeoStatusChanged(page);
            }

            // Notify about new tags.
            PagesApiContext.Events.OnTagCreated(newTags);

            return(new SavePageResponse(page));
        }
Пример #21
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Save response.</returns>
        /// <exception cref="CmsException">Failed to save page properties.</exception>
        public SavePageResponse Execute(EditPagePropertiesViewModel request)
        {
            UnitOfWork.BeginTransaction();

            var page = Repository
                       .AsQueryable <PageProperties>(p => p.Id == request.Id)
                       .FetchMany(p => p.Options)
                       .Fetch(p => p.Layout).ThenFetchMany(l => l.LayoutOptions)
                       .ToList()
                       .FirstOrDefault();

            Models.Redirect redirectCreated  = null;
            bool            initialSeoStatus = page.HasSEO;

            request.PageUrl = urlService.FixUrl(request.PageUrl);

            if (!string.Equals(page.PageUrl, request.PageUrl))
            {
                pageService.ValidatePageUrl(request.PageUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(page.PageUrl, request.PageUrl);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                page.NodeCountInSitemap = request.UpdateSitemap
                    ? sitemapService.ChangeUrl(page.PageUrl, request.PageUrl)
                    : sitemapService.NodesWithUrl(request.PageUrl);

                page.PageUrl = request.PageUrl;
            }

            page.PageUrlLowerTrimmed = page.PageUrl.LowerTrimmedUrl();
            page.Layout    = Repository.AsProxy <Root.Models.Layout>(request.TemplateId);
            page.Category  = request.CategoryId.HasValue ? Repository.AsProxy <CategoryEntity>(request.CategoryId.Value) : null;
            page.Title     = request.PageName;
            page.CustomCss = request.PageCSS;
            page.CustomJS  = request.PageJavascript;

            if (request.IsVisibleToEveryone)
            {
                page.Status      = PageStatus.Published;
                page.PublishedOn = DateTime.Now;
            }
            else
            {
                page.Status = PageStatus.Unpublished;
            }

            page.UseNoFollow     = request.UseNoFollow;
            page.UseNoIndex      = request.UseNoIndex;
            page.UseCanonicalUrl = request.UseCanonicalUrl;
            page.IsArchived      = request.IsArchived;
            page.Version         = request.Version;

            page.Image          = request.Image != null && request.Image.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
            page.SecondaryImage = request.SecondaryImage != null && request.SecondaryImage.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.SecondaryImage.ImageId.Value) : null;
            page.FeaturedImage  = request.FeaturedImage != null && request.FeaturedImage.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.FeaturedImage.ImageId.Value) : null;

            var optionValues  = page.Options.Distinct();
            var parentOptions = page.Layout.LayoutOptions.Distinct();

            optionService.SaveOptionValues(request.OptionValues, optionValues, parentOptions, () => new Root.Models.PageOption {
                Page = page
            });

            if (cmsConfiguration.AccessControlEnabled)
            {
                accessControlService.UpdateAccessControl(request.UserAccessList, request.Id);
            }

            Repository.Save(page);

            // Save tags
            IList <Root.Models.Tag> newTags;

            tagService.SavePageTags(page, request.Tags, out newTags);

            UnitOfWork.Commit();

            // Notify about page properties change.
            Events.PageEvents.Instance.OnPagePropertiesChanged(page);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            // Notify about SEO status change.
            if (initialSeoStatus != page.HasSEO)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            return(new SavePageResponse(page));
        }
Пример #22
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Save response.</returns>
        /// <exception cref="CmsException">Failed to save page properties.</exception>
        public SavePageResponse Execute(EditPagePropertiesViewModel request)
        {
            UnitOfWork.BeginTransaction();

            var pageQuery = Repository
                            .AsQueryable <PageProperties>(p => p.Id == request.Id)
                            .FetchMany(p => p.Options)
                            .Fetch(p => p.Layout).ThenFetchMany(l => l.LayoutOptions)
                            .AsQueryable();

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                pageQuery = pageQuery.FetchMany(f => f.AccessRules);
            }

            var page = pageQuery.ToList().FirstOne();

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                AccessControlService.DemandAccess(page, Context.Principal, AccessLevel.ReadWrite, RootModuleConstants.UserRoles.EditContent, RootModuleConstants.UserRoles.PublishContent);
            }
            else
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent, RootModuleConstants.UserRoles.PublishContent);
            }

            Models.Redirect redirectCreated  = null;
            bool            initialSeoStatus = page.HasSEO;

            request.PageUrl = urlService.FixUrl(request.PageUrl);

            if (!string.Equals(page.PageUrl, request.PageUrl))
            {
                pageService.ValidatePageUrl(request.PageUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(page.PageUrl, request.PageUrl);
                    if (redirect != null)
                    {
                        Repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                page.NodeCountInSitemap = request.UpdateSitemap
                    ? sitemapService.ChangeUrl(page.PageUrl, request.PageUrl)
                    : sitemapService.NodesWithUrl(request.PageUrl);

                page.PageUrl = request.PageUrl;
            }

            page.PageUrlHash = page.PageUrl.UrlHash();
            page.Layout      = Repository.AsProxy <Root.Models.Layout>(request.TemplateId);
            page.Category    = request.CategoryId.HasValue ? Repository.AsProxy <CategoryEntity>(request.CategoryId.Value) : null;
            page.Title       = request.PageName;
            page.CustomCss   = request.PageCSS;
            page.CustomJS    = request.PageJavascript;

            var publishDraftContent = false;

            if (request.CanPublishPage)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent);

                if (request.IsPagePublished)
                {
                    if (page.Status != PageStatus.Published)
                    {
                        page.Status         = PageStatus.Published;
                        page.PublishedOn    = DateTime.Now;
                        publishDraftContent = true;
                    }
                }
                else
                {
                    page.Status = PageStatus.Unpublished;
                }
            }

            page.UseNoFollow     = request.UseNoFollow;
            page.UseNoIndex      = request.UseNoIndex;
            page.UseCanonicalUrl = request.UseCanonicalUrl;
            page.IsArchived      = request.IsArchived;
            page.Version         = request.Version;

            page.Image          = request.Image != null && request.Image.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
            page.SecondaryImage = request.SecondaryImage != null && request.SecondaryImage.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.SecondaryImage.ImageId.Value) : null;
            page.FeaturedImage  = request.FeaturedImage != null && request.FeaturedImage.ImageId.HasValue ? Repository.AsProxy <MediaImage>(request.FeaturedImage.ImageId.Value) : null;

            var optionValues  = page.Options.Distinct();
            var parentOptions = page.Layout.LayoutOptions.Distinct();

            optionService.SaveOptionValues(request.OptionValues, optionValues, parentOptions, () => new PageOption {
                Page = page
            });

            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                page.AccessRules.RemoveDuplicateEntities();

                var accessRules = request.UserAccessList != null?request.UserAccessList.Cast <IAccessRule>().ToList() : null;

                accessControlService.UpdateAccessControl(page, accessRules);
            }

            Repository.Save(page);

            // Save tags
            IList <Tag> newTags;

            tagService.SavePageTags(page, request.Tags, out newTags);

            if (publishDraftContent)
            {
                contentService.PublishDraftContent(page.Id);
            }

            UnitOfWork.Commit();

            // Notify about page properties change.
            Events.PageEvents.Instance.OnPagePropertiesChanged(page);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            // Notify about SEO status change.
            if (initialSeoStatus != page.HasSEO)
            {
                Events.PageEvents.Instance.OnPageSeoStatusChanged(page);
            }

            // Notify about new tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            return(new SavePageResponse(page));
        }
Пример #23
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns>Blog post view model</returns>
        public SaveBlogPostCommandResponse Execute(BlogPostViewModel request)
        {
            if (request.DesirableStatus == ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.PublishContent);
            }

            var layout      = LoadLayout();
            var region      = LoadRegion();
            var isNew       = request.Id.HasDefaultValue();
            var userCanEdit = false;

            if (isNew || request.DesirableStatus != ContentStatus.Published)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent);
                userCanEdit = true;
            }
            else
            {
                userCanEdit = SecurityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent);
            }

            // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception.

            BlogPost        blogPost;
            BlogPostContent content     = null;
            PageContent     pageContent = null;

            Pages.Models.Redirect redirectCreated = null;

            // Loading blog post and it's content, or creating new, if such not exists
            if (!isNew)
            {
                blogPost = Repository.First <BlogPost>(request.Id);
                content  = Repository.FirstOrDefault <BlogPostContent>(c => c.PageContents.Any(x => x.Page == blogPost && x.Region == region && !x.IsDeleted));
                if (content != null)
                {
                    pageContent = Repository.FirstOrDefault <PageContent>(c => c.Page == blogPost && c.Region == region && !c.IsDeleted && c.Content == content);
                }

                if (userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && request.BlogUrl != null)
                {
                    request.BlogUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(request.BlogUrl, request.Id);
                    if (request.RedirectFromOldUrl)
                    {
                        var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl);
                        if (redirect != null)
                        {
                            Repository.Save(redirect);
                            redirectCreated = redirect;
                        }
                    }

                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                }
            }
            else
            {
                blogPost = new BlogPost();

                AddDefaultAccessRules(blogPost);
            }

            if (pageContent == null)
            {
                pageContent = new PageContent {
                    Region = region, Page = blogPost
                };
            }

            // Push to change modified data each time.
            blogPost.ModifiedOn = DateTime.Now;
            blogPost.Version    = request.Version;

            if (userCanEdit)
            {
                blogPost.Title       = request.Title;
                blogPost.Description = request.IntroText;
                blogPost.Author      = request.AuthorId.HasValue ? Repository.AsProxy <Author>(request.AuthorId.Value) : null;
                blogPost.Category    = request.CategoryId.HasValue ? Repository.AsProxy <Category>(request.CategoryId.Value) : null;
                blogPost.Image       = (request.Image != null && request.Image.ImageId.HasValue) ? Repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                if (isNew || request.DesirableStatus == ContentStatus.Published)
                {
                    blogPost.ActivationDate = request.LiveFromDate;
                    blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate);
                }
            }

            if (isNew)
            {
                if (!string.IsNullOrWhiteSpace(request.BlogUrl))
                {
                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(blogPost.PageUrl);
                }
                else
                {
                    blogPost.PageUrl = blogService.CreateBlogPermalink(request.Title);
                }

                blogPost.MetaTitle = request.Title;
                blogPost.Layout    = layout;
                UpdateStatus(blogPost, request.DesirableStatus);
            }
            else if (request.DesirableStatus == ContentStatus.Published)
            {
                UpdateStatus(blogPost, request.DesirableStatus);
            }

            // Create content.
            var newContent = new BlogPostContent
            {
                Id               = content != null ? content.Id : Guid.Empty,
                Name             = request.Title,
                Html             = request.Content ?? string.Empty,
                EditInSourceMode = request.EditInSourceMode,
                ActivationDate   = request.LiveFromDate,
                ExpirationDate   = TimeHelper.FormatEndDate(request.LiveToDate)
            };

            // Preserve content if user is not authorized to change it.
            if (!userCanEdit)
            {
                if (content == null)
                {
                    throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content.
                }

                var contentToPublish = (BlogPostContent)(content.History != null
                    ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content
                    : content);

                newContent.Name = contentToPublish.Name;
                newContent.Html = contentToPublish.Html;
            }

            content             = (BlogPostContent)contentService.SaveContentWithStatusUpdate(newContent, request.DesirableStatus);
            pageContent.Content = content;

            blogPost.PageUrlHash     = blogPost.PageUrl.UrlHash();
            blogPost.UseCanonicalUrl = request.UseCanonicalUrl;
            Repository.Save(blogPost);
            Repository.Save(content);
            Repository.Save(pageContent);

            // Save tags if user has edit right.
            IList <Tag> newTags = null;

            if (userCanEdit)
            {
                tagService.SavePageTags(blogPost, request.Tags, out newTags);
            }

            // Commit
            UnitOfWork.Commit();

            // Notify about new or updated blog post.
            if (isNew)
            {
                Events.BlogEvents.Instance.OnBlogCreated(blogPost);
            }
            else
            {
                Events.BlogEvents.Instance.OnBlogUpdated(blogPost);
            }

            // Notify about new created tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            return(new SaveBlogPostCommandResponse
            {
                Id = blogPost.Id,
                Version = blogPost.Version,
                Title = blogPost.Title,
                PageUrl = blogPost.PageUrl,
                ModifiedByUser = blogPost.ModifiedByUser,
                ModifiedOn = blogPost.ModifiedOn.ToFormattedDateString(),
                CreatedOn = blogPost.CreatedOn.ToFormattedDateString(),
                PageStatus = blogPost.Status,
                DesirableStatus = request.DesirableStatus,
                PageContentId = pageContent.Id
            });
        }
Пример #24
0
        public Redirect SaveRedirect(ViewModels.SiteSettings.SiteSettingRedirectViewModel model, bool createIfNotExists = false)
        {
            var isRedirectInternal = urlService.ValidateInternalUrl(model.RedirectUrl);

            if (!isRedirectInternal && urlService.ValidateInternalUrl(urlService.FixUrl(model.RedirectUrl)))
            {
                isRedirectInternal = true;
            }

            model.PageUrl = urlService.FixUrl(model.PageUrl);
            if (isRedirectInternal)
            {
                model.RedirectUrl = urlService.FixUrl(model.RedirectUrl);
            }

            // Validate request
            if (!urlService.ValidateInternalUrl(model.PageUrl))
            {
                var message    = PagesGlobalization.SaveRedirect_InvalidPageUrl_Message;
                var logMessage = string.Format("Invalid page url {0}.", model.PageUrl);
                throw new ValidationException(() => message, logMessage);
            }
            if (!urlService.ValidateExternalUrl(model.RedirectUrl))
            {
                var message    = PagesGlobalization.SaveRedirect_InvalidRedirectUrl_Message;
                var logMessage = string.Format("Invalid redirect url {0}.", model.RedirectUrl);
                throw new ValidationException(() => message, logMessage);
            }

            // Validate for url patterns
            string patternsValidationMessage;

            if (!urlService.ValidateUrlPatterns(model.PageUrl, out patternsValidationMessage))
            {
                var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, model.PageUrl);
                throw new ValidationException(() => patternsValidationMessage, logMessage);
            }
            if (isRedirectInternal && !urlService.ValidateUrlPatterns(model.RedirectUrl, out patternsValidationMessage, PagesGlobalization.SaveRedirect_RedirectUrl_Name))
            {
                var logMessage = string.Format("{0}. URL: {1}.", patternsValidationMessage, model.PageUrl);
                throw new ValidationException(() => patternsValidationMessage, logMessage);
            }

            ValidateRedirectExists(model.PageUrl, model.Id);
            ValidateForCircularLoop(model.PageUrl, model.RedirectUrl, model.Id);

            Redirect redirect = null;
            var      isNew    = model.Id.HasDefaultValue();

            if (!isNew)
            {
                redirect = repository.FirstOrDefault <Redirect>(model.Id);
                isNew    = redirect == null;

                if (isNew && !createIfNotExists)
                {
                    throw new EntityNotFoundException(typeof(Redirect), model.Id);
                }
            }

            if (isNew)
            {
                redirect = new Redirect {
                    Id = model.Id
                };
            }

            if (model.Version > 0)
            {
                redirect.Version = model.Version;
            }
            redirect.PageUrl     = model.PageUrl;
            redirect.RedirectUrl = model.RedirectUrl;

            repository.Save(redirect);
            unitOfWork.Commit();

            // Notify.
            if (isNew)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirect);
            }
            else
            {
                Events.PageEvents.Instance.OnRedirectUpdated(redirect);
            }

            return(redirect);
        }
        /// <summary>
        /// Saves the blog post.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="childContentOptionValues">The child content option values.</param>
        /// <param name="principal">The principal.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns>
        /// Saved blog post entity
        /// </returns>
        /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"></exception>
        /// <exception cref="SecurityException">Forbidden: Access is denied.</exception>
        public BlogPost SaveBlogPost(BlogPostViewModel request, IList <ContentOptionValuesViewModel> childContentOptionValues, IPrincipal principal, out string[] errorMessages)
        {
            errorMessages = new string[0];
            string[] roles;
            if (request.DesirableStatus == ContentStatus.Published)
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.PublishContent);
                roles = new[] { RootModuleConstants.UserRoles.PublishContent };
            }
            else
            {
                accessControlService.DemandAccess(principal, RootModuleConstants.UserRoles.EditContent);
                roles = new[] { RootModuleConstants.UserRoles.EditContent };
            }

            var isNew       = request.Id.HasDefaultValue();
            var userCanEdit = securityService.IsAuthorized(RootModuleConstants.UserRoles.EditContent);

            ValidateData(isNew, request);

            BlogPost        blogPost;
            BlogPostContent content;
            PageContent     pageContent;

            GetBlogPostAndContentEntities(request, principal, roles, ref isNew, out content, out pageContent, out blogPost);
            var beforeChange = new UpdatingBlogModel(blogPost);

            // Master page / layout
            Layout layout;
            Page   masterPage;
            Region region;

            LoadDefaultLayoutAndRegion(out layout, out masterPage, out region);

            if (masterPage != null)
            {
                var level = accessControlService.GetAccessLevel(masterPage, principal);
                if (level < AccessLevel.Read)
                {
                    var          message    = BlogGlobalization.SaveBlogPost_FailedToSave_InaccessibleMasterPage;
                    const string logMessage = "Failed to save blog post. Selected master page for page layout is inaccessible.";
                    throw new ValidationException(() => message, logMessage);
                }
            }

            if (pageContent.Region == null)
            {
                pageContent.Region = region;
            }

            // Load master pages for updating page's master path and page's children master path
            IList <Guid>       newMasterIds;
            IList <Guid>       oldMasterIds;
            IList <Guid>       childrenPageIds;
            IList <MasterPage> existingChildrenMasterPages;

            PrepareForUpdateChildrenMasterPages(isNew, blogPost, request, out newMasterIds, out oldMasterIds, out childrenPageIds, out existingChildrenMasterPages);

            // TODO: TEST AND TRY TO FIX IT: TRANSACTION HERE IS REQUIRED!
            // UnitOfWork.BeginTransaction(); // NOTE: this causes concurrent data exception.

            Redirect redirectCreated = null;

            if (!isNew && userCanEdit && !string.Equals(blogPost.PageUrl, request.BlogUrl) && !string.IsNullOrWhiteSpace(request.BlogUrl))
            {
                request.BlogUrl = urlService.FixUrl(request.BlogUrl);
                pageService.ValidatePageUrl(request.BlogUrl, request.Id);
                if (request.RedirectFromOldUrl)
                {
                    var redirect = redirectService.CreateRedirectEntity(blogPost.PageUrl, request.BlogUrl);
                    if (redirect != null)
                    {
                        repository.Save(redirect);
                        redirectCreated = redirect;
                    }
                }

                blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
            }

            // Push to change modified data each time.
            blogPost.ModifiedOn = DateTime.Now;

            if (userCanEdit)
            {
                blogPost.Title       = request.Title;
                blogPost.Description = request.IntroText;
                blogPost.Author      = request.AuthorId.HasValue ? repository.AsProxy <Author>(request.AuthorId.Value) : null;
                blogPost.Category    = request.CategoryId.HasValue ? repository.AsProxy <Category>(request.CategoryId.Value) : null;
                blogPost.Image       = (request.Image != null && request.Image.ImageId.HasValue) ? repository.AsProxy <MediaImage>(request.Image.ImageId.Value) : null;
                if (isNew || request.DesirableStatus == ContentStatus.Published)
                {
                    blogPost.ActivationDate = request.LiveFromDate;
                    blogPost.ExpirationDate = TimeHelper.FormatEndDate(request.LiveToDate);
                }
            }

            if (isNew)
            {
                if (!string.IsNullOrWhiteSpace(request.BlogUrl))
                {
                    blogPost.PageUrl = urlService.FixUrl(request.BlogUrl);
                    pageService.ValidatePageUrl(blogPost.PageUrl);
                }
                else
                {
                    blogPost.PageUrl = CreateBlogPermalink(request.Title, null, blogPost.Category != null ? (Guid?)blogPost.Category.Id : null);
                }

                blogPost.MetaTitle = request.MetaTitle ?? request.Title;
                if (masterPage != null)
                {
                    blogPost.MasterPage = masterPage;
                    masterPageService.SetPageMasterPages(blogPost, masterPage.Id);
                }
                else
                {
                    blogPost.Layout = layout;
                }
                UpdateStatus(blogPost, request.DesirableStatus);
                AddDefaultAccessRules(blogPost, principal, masterPage);
            }
            else if (request.DesirableStatus == ContentStatus.Published ||
                     blogPost.Status == PageStatus.Preview)
            {
                // Update only if publishing or current status is preview.
                // Else do not change, because it may change from published to draft status
                UpdateStatus(blogPost, request.DesirableStatus);
            }

            // Create content.
            var newContent = new BlogPostContent
            {
                Id               = content != null ? content.Id : Guid.Empty,
                Name             = request.Title,
                Html             = request.Content ?? string.Empty,
                EditInSourceMode = request.EditInSourceMode,
                ActivationDate   = request.LiveFromDate,
                ExpirationDate   = TimeHelper.FormatEndDate(request.LiveToDate)
            };

            // Preserve content if user is not authorized to change it.
            if (!userCanEdit)
            {
                if (content == null)
                {
                    throw new SecurityException("Forbidden: Access is denied."); // User has no rights to create new content.
                }

                var contentToPublish = (BlogPostContent)(content.History != null
                    ? content.History.FirstOrDefault(c => c.Status == ContentStatus.Draft) ?? content
                    : content);

                newContent.Name = contentToPublish.Name;
                newContent.Html = contentToPublish.Html;
            }

            content             = SaveContentWithStatusUpdate(isNew, newContent, request, principal);
            pageContent.Content = content;
            optionService.SaveChildContentOptions(content, childContentOptionValues, request.DesirableStatus);

            blogPost.PageUrlHash     = blogPost.PageUrl.UrlHash();
            blogPost.UseCanonicalUrl = request.UseCanonicalUrl;

            MapExtraProperties(isNew, blogPost, content, pageContent, request, principal);

            // Notify about page properties changing.
            var cancelEventArgs = Events.BlogEvents.Instance.OnBlogChanging(beforeChange, new UpdatingBlogModel(blogPost));

            if (cancelEventArgs.Cancel)
            {
                errorMessages = cancelEventArgs.CancellationErrorMessages.ToArray();
                return(null);
            }

            repository.Save(blogPost);
            repository.Save(content);
            repository.Save(pageContent);

            masterPageService.UpdateChildrenMasterPages(existingChildrenMasterPages, oldMasterIds, newMasterIds, childrenPageIds);

            pageContent.Content   = content;
            blogPost.PageContents = new [] { pageContent };



            IList <Tag> newTags = null;

            if (userCanEdit)
            {
                newTags = SaveTags(blogPost, request);
            }

            // Commit
            unitOfWork.Commit();

            // Notify about new created tags.
            Events.RootEvents.Instance.OnTagCreated(newTags);

            // Notify about new or updated blog post.
            if (isNew)
            {
                Events.BlogEvents.Instance.OnBlogCreated(blogPost);
            }
            else
            {
                Events.BlogEvents.Instance.OnBlogUpdated(blogPost);
            }

            // Notify about redirect creation.
            if (redirectCreated != null)
            {
                Events.PageEvents.Instance.OnRedirectCreated(redirectCreated);
            }

            return(blogPost);
        }
Пример #26
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The page view model.</param>
        /// <returns>Created page</returns>
        public virtual SavePageResponse Execute(AddNewPageViewModel request)
        {
            if (request.CreateMasterPage)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.Administration);
            }
            else
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent);
            }

            if (!request.MasterPageId.HasValue && !request.TemplateId.HasValue)
            {
                var message = RootGlobalization.MasterPage_Or_Layout_ShouldBeSelected_ValidationMessage;
                throw new ValidationException(() => message, message);
            }
            if (request.MasterPageId.HasValue && request.TemplateId.HasValue)
            {
                var logMessage = string.Format("Only one of master page and layout can be selected. LayoutId: {0}, MasterPageId: {1}", request.MasterPageId, request.TemplateId);
                var message    = RootGlobalization.MasterPage_Or_Layout_OnlyOne_ShouldBeSelected_ValidationMessage;
                throw new ValidationException(() => message, logMessage);
            }

            // Create / fix page url.
            var pageUrl       = request.PageUrl;
            var createPageUrl = pageUrl == null;

            if (createPageUrl && !string.IsNullOrWhiteSpace(request.PageTitle))
            {
                pageUrl = pageService.CreatePagePermalink(request.PageTitle, request.ParentPageUrl, null, request.LanguageId);
            }
            else
            {
                pageUrl = urlService.FixUrl(pageUrl);

                // Validate Url
                pageService.ValidatePageUrl(pageUrl);
            }

            var page = new PageProperties
            {
                PageUrl      = pageUrl,
                PageUrlHash  = pageUrl.UrlHash(),
                Title        = request.PageTitle,
                MetaTitle    = request.PageTitle,
                Status       = request.CreateMasterPage ? PageStatus.Published : PageStatus.Unpublished,
                IsMasterPage = request.CreateMasterPage
            };

            if (request.MasterPageId.HasValue)
            {
                page.MasterPage = Repository.AsProxy <Root.Models.Page>(request.MasterPageId.Value);

                masterPageService.SetPageMasterPages(page, request.MasterPageId.Value);
            }
            else
            {
                page.Layout = Repository.AsProxy <Root.Models.Layout>(request.TemplateId.Value);
            }

            if (cmsConfiguration.EnableMultilanguage)
            {
                if (request.LanguageId.HasValue && !request.LanguageId.Value.HasDefaultValue())
                {
                    page.Language = Repository.AsProxy <Language>(request.LanguageId.Value);
                }
            }

            page.Options = optionService.SaveOptionValues(request.OptionValues, null, () => new PageOption {
                Page = page
            });

            Repository.Save(page);

            // Update access control if enabled:
            if (cmsConfiguration.Security.AccessControlEnabled)
            {
                AccessControlService.UpdateAccessControl(page, request.UserAccessList != null ? request.UserAccessList.Cast <IAccessRule>().ToList() : null);
            }

            UnitOfWork.Commit();

            // Notifying, that page is created
            Events.PageEvents.Instance.OnPageCreated(page);

            var response = new SavePageResponse(page)
            {
                IsSitemapActionEnabled = ConfigurationHelper.IsSitemapActionEnabledAfterAddingNewPage(cmsConfiguration)
            };

            return(response);
        }
Пример #27
0
        /// <summary>
        /// Executes the specified request.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <returns></returns>
        public virtual bool Execute(DeletePageViewModel request)
        {
            var page = Repository.First <PageProperties>(request.PageId);

            if (page.Version != request.Version)
            {
                throw new ConcurrentDataException(page);
            }

            request.RedirectUrl = urlService.FixUrl(request.RedirectUrl);

            IList <SitemapNode> sitemapNodes = null;

            if (request.UpdateSitemap)
            {
                AccessControlService.DemandAccess(Context.Principal, RootModuleConstants.UserRoles.EditContent);
            }

            if (request.UpdateSitemap && page.NodeCountInSitemap > 0)
            {
                sitemapNodes = sitemapService.GetNodesByUrl(page.PageUrl);
                foreach (var node in sitemapNodes)
                {
                    if (node.ChildNodes.Count > 0)
                    {
                        var logMessage = string.Format("Sitemap node {0} has {1} child nodes.", node.Id, node.ChildNodes.Count);
                        throw new ValidationException(() => PagesGlobalization.DeletePageCommand_SitemapNodeHasChildNodes_Message, logMessage);
                    }
                }
            }

            UnitOfWork.BeginTransaction();

            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);
            }

            // Delete sitemapNodes.
            if (sitemapNodes != null)
            {
                foreach (var node in sitemapNodes)
                {
                    sitemapService.DeleteNodeWithoutPageUpdate(node);
                }

                page.NodeCountInSitemap -= sitemapNodes.Count;
                Repository.Save(page);
            }

            // Delete page
            Repository.Delete <Root.Models.Page>(request.PageId, request.Version);

            // Commit
            UnitOfWork.Commit();

            if (sitemapNodes != null && sitemapNodes.Count > 0)
            {
                foreach (var node in sitemapNodes)
                {
                    Events.SitemapEvents.Instance.OnSitemapNodeUpdated(node);
                }
                Events.SitemapEvents.Instance.OnSitemapUpdated();
            }

            // Notifying, that page is deleted.
            Events.PageEvents.Instance.OnPageDeleted(page);

            return(true);
        }