public async Task PublishReadyDrafts(CancellationToken cancellationToken = default(CancellationToken)) { await EnsureBlogSettings(); var drafts = await _postQueries.GetPostsReadyForPublish(_settings.Id, cancellationToken); foreach (var post in drafts) { post.Content = post.DraftContent; post.Author = post.DraftAuthor; post.PubDate = post.DraftPubDate.Value; post.SerializedModel = post.DraftSerializedModel; post.IsPublished = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftSerializedModel = null; post.DraftPubDate = null; await Update(post); await _eventHandlers.HandlePublished(_settings.Id, post).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(_settings.Id, post.Id).ConfigureAwait(false); _log.LogDebug($"auto published draft for post {post.Title}"); } }
public async Task PublishReadyDrafts(CancellationToken cancellationToken = default(CancellationToken)) { var settings = await _projectService.GetCurrentProjectSettings().ConfigureAwait(false); var drafts = await _pageQueries.GetPagesReadyForPublish(settings.Id, cancellationToken); foreach (var page in drafts) { page.Content = page.DraftContent; page.Author = page.DraftAuthor; page.PubDate = page.DraftPubDate.Value; page.SerializedModel = page.DraftSerializedModel; page.IsPublished = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftSerializedModel = null; page.DraftPubDate = null; await Update(page, settings); await _eventHandlers.HandlePublished(page.ProjectId, page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(page.ProjectId, page.Id).ConfigureAwait(false); await _navigationCache.ClearTreeCache(); _log.LogDebug($"auto published draft for page {page.Title}"); } }
public async Task <CommandResult <IPage> > Handle(UpdateTemplatedPageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var page = request.Page; var history = page.CreateHistory(request.UserName); var project = await _projectService.GetProjectSettings(request.ProjectId); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(page.DraftSerializedModel)) { pageModelString = page.DraftSerializedModel; } else { pageModelString = page.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != page.Slug) { var slugIsAvailable = await _pageService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { errors.Add(_localizer["The page slug was not changed because the requested slug is already in use."]); request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); page.Title = request.ViewModel.Title; page.CorrelationKey = request.ViewModel.CorrelationKey; page.LastModified = DateTime.UtcNow; page.LastModifiedByUser = request.UserName; page.MenuFilters = request.ViewModel.MenuFilters; page.MetaDescription = request.ViewModel.MetaDescription; page.PageOrder = request.ViewModel.PageOrder; page.ShowHeading = request.ViewModel.ShowHeading; page.ShowMenu = request.ViewModel.ShowMenu; page.ShowComments = request.ViewModel.ShowComments; page.MenuFilters = request.ViewModel.MenuFilters; page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { page.Slug = request.ViewModel.Slug; } page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ParentSlug == project.DefaultPageSlug) { _log.LogWarning($"{request.UserName} tried to explicitely set the default page slug as the parent slug which is not allowed since all root pages are already children of the default page"); page.ParentSlug = string.Empty; page.ParentId = "0"; } var shouldFirePublishEvent = false; switch (request.ViewModel.SaveMode) { case SaveMode.SaveDraft: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishLater: page.DraftSerializedModel = modelString; page.DraftContent = renderedModel; page.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); page.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishNow: page.Author = request.ViewModel.Author; page.Content = renderedModel; page.SerializedModel = modelString; page.PubDate = DateTime.UtcNow; page.IsPublished = true; shouldFirePublishEvent = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftPubDate = null; page.DraftSerializedModel = null; break; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _pageService.Update(page); if (shouldFirePublishEvent) { await _pageService.FirePublishEvent(page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, page.Id).ConfigureAwait(false); } await _navigationCache.ClearTreeCache(); } return(new CommandResult <IPage>(page, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page from a content template failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public async Task <CommandResult <IPost> > Handle(CreateOrUpdatePostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); try { bool isNew = false; var project = await _projectService.GetProjectSettings(request.ProjectId); var post = request.Post; ContentHistory history = null; if (post == null) { isNew = true; post = new Post() { BlogId = request.ProjectId, Title = request.ViewModel.Title, MetaDescription = request.ViewModel.MetaDescription, Slug = ContentUtils.CreateSlug(request.ViewModel.Title), CreatedByUser = request.UserName }; } else { history = post.CreateHistory(request.UserName); } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != post.Slug) { var slugIsAvailable = await _blogService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { post.Title = request.ViewModel.Title; post.CorrelationKey = request.ViewModel.CorrelationKey; post.ImageUrl = request.ViewModel.ImageUrl; post.ThumbnailUrl = request.ViewModel.ThumbnailUrl; post.IsFeatured = request.ViewModel.IsFeatured; post.ContentType = request.ViewModel.ContentType; post.TeaserOverride = request.ViewModel.TeaserOverride; post.SuppressTeaser = request.ViewModel.SuppressTeaser; post.LastModified = DateTime.UtcNow; post.LastModifiedByUser = request.UserName; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { post.Slug = request.ViewModel.Slug; } var categories = new List <string>(); if (!string.IsNullOrEmpty(request.ViewModel.Categories)) { if (_editOptions.ForceLowerCaseCategories) { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } post.Categories = categories; var shouldFirePublishEvent = false; switch (request.ViewModel.SaveMode) { case SaveMode.SaveDraft: post.DraftContent = request.ViewModel.Content; post.DraftAuthor = request.ViewModel.Author; break; case SaveMode.PublishLater: post.DraftContent = request.ViewModel.Content; post.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); post.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishNow: post.Content = request.ViewModel.Content; post.Author = request.ViewModel.Author; if (!post.PubDate.HasValue) { post.PubDate = DateTime.UtcNow; } else if (post.PubDate > DateTime.UtcNow) { post.PubDate = DateTime.UtcNow; } post.IsPublished = true; shouldFirePublishEvent = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftPubDate = null; break; } if (project.TeaserMode != TeaserMode.Off) { // need to generate the teaser on save string html = null; if (post.ContentType == "markdown") { var mdPipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); html = Markdown.ToHtml(post.Content, mdPipeline); } else { html = post.Content; } var teaserResult = _teaserService.GenerateTeaser( project.TeaserTruncationMode, project.TeaserTruncationLength, html, Guid.NewGuid().ToString(),//cache key post.Slug, project.LanguageCode, false //logWarnings ); post.AutoTeaser = teaserResult.Content; } if (history != null) { await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); } if (isNew) { await _blogService.Create(post); } else { await _blogService.Update(post); } if (shouldFirePublishEvent) { await _blogService.FirePublishEvent(post); await _historyCommands.DeleteDraftHistory(request.ProjectId, post.Id).ConfigureAwait(false); } } return(new CommandResult <IPost>(post, request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task <CommandResult <IPage> > Handle(CreateOrUpdatePageRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); try { bool isNew = false; var project = await _projectService.GetProjectSettings(request.ProjectId); var page = request.Page; ContentHistory history = null; if (page == null) { isNew = true; page = new Page() { ProjectId = request.ProjectId, ParentId = "0", CreatedByUser = request.UserName, Slug = ContentUtils.CreateSlug(request.ViewModel.Title), ContentType = request.ViewModel.ContentType }; } else { history = page.CreateHistory(request.UserName); } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != page.Slug) { var slugIsAvailable = await _pageService.SlugIsAvailable(request.ViewModel.Slug); if (!slugIsAvailable) { errors.Add(_localizer["The page slug was invalid because the requested slug is already in use."]); request.ModelState.AddModelError("Slug", _localizer["The page slug was not changed because the requested slug is already in use."]); } } } if (request.ModelState.IsValid) { page.Title = request.ViewModel.Title; page.CorrelationKey = request.ViewModel.CorrelationKey; page.LastModified = DateTime.UtcNow; page.LastModifiedByUser = request.UserName; page.MenuFilters = request.ViewModel.MenuFilters; page.MetaDescription = request.ViewModel.MetaDescription; page.PageOrder = request.ViewModel.PageOrder; page.ShowHeading = request.ViewModel.ShowHeading; page.ShowMenu = request.ViewModel.ShowMenu; page.MenuOnly = request.ViewModel.MenuOnly; page.DisableEditor = request.ViewModel.DisableEditor; page.ShowComments = request.ViewModel.ShowComments; page.MenuFilters = request.ViewModel.MenuFilters; page.ExternalUrl = request.ViewModel.ExternalUrl; page.ViewRoles = request.ViewModel.ViewRoles; if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { page.Slug = request.ViewModel.Slug; } if (!string.IsNullOrEmpty(request.ViewModel.ParentSlug)) { var parentPage = await _pageService.GetPageBySlug(request.ViewModel.ParentSlug); if (parentPage != null) { if (parentPage.Id != page.ParentId) { page.ParentId = parentPage.Id; page.ParentSlug = parentPage.Slug; } } } else { // empty means root level page.ParentSlug = string.Empty; page.ParentId = "0"; } if (page.ParentSlug == project.DefaultPageSlug) { _log.LogWarning($"{request.UserName} tried to explicitely set the default page slug as the parent slug which is not allowed since all root pages are already children of the default page"); page.ParentSlug = string.Empty; page.ParentId = "0"; } var shouldFirePublishEvent = false; //var shouldFireUnPublishEvent = false; switch (request.ViewModel.SaveMode) { //case SaveMode.UnPublish: // page.DraftContent = request.ViewModel.Content; // page.DraftAuthor = request.ViewModel.Author; // page.DraftPubDate = null; // page.IsPublished = false; // page.PubDate = null; // shouldFireUnPublishEvent = true; // break; case SaveMode.SaveDraft: page.DraftContent = request.ViewModel.Content; page.DraftAuthor = request.ViewModel.Author; // should we clear the draft pub date if save draft clicked? //page.DraftPubDate = null; if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishLater: page.DraftContent = request.ViewModel.Content; page.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); page.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!page.PubDate.HasValue) { page.IsPublished = false; } break; case SaveMode.PublishNow: page.Content = request.ViewModel.Content; page.Author = request.ViewModel.Author; page.PubDate = DateTime.UtcNow; page.IsPublished = true; shouldFirePublishEvent = true; page.DraftAuthor = null; page.DraftContent = null; page.DraftPubDate = null; break; } if (history != null) { await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); } if (isNew) { await _pageService.Create(page); } else { await _pageService.Update(page); } if (shouldFirePublishEvent) { await _pageService.FirePublishEvent(page).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, page.Id).ConfigureAwait(false); } //if (shouldFireUnPublishEvent) //{ // await _pageService.FireUnPublishEvent(page).ConfigureAwait(false); //} _pageService.ClearNavigationCache(); } return(new CommandResult <IPage>(page, request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a page failed. An error has been logged."]); return(new CommandResult <IPage>(null, false, errors)); } }
public async Task <CommandResult <IPost> > Handle(UpdateTemplatedPostRequest request, CancellationToken cancellationToken = default(CancellationToken)) { var errors = new List <string>(); var customModelIsValid = true; try { var post = request.Post; var history = post.CreateHistory(request.UserName); var project = await _projectService.GetCurrentProjectSettings(); var serializer = GetSerializer(request.Template.SerializerName); var parser = GetFormParser(request.Template.FormParserName); var validator = GetValidator(request.Template.ValidatorName); var type = Type.GetType(request.Template.ModelType); var model = parser.ParseModel(request.Template.ModelType, request.Form); if (model == null) { errors.Add(_localizer["Failed to parse custom template model from form."]); customModelIsValid = false; //failed to parse model from form // at least return the original model before changes string pageModelString; if (!string.IsNullOrWhiteSpace(post.DraftSerializedModel)) { pageModelString = post.DraftSerializedModel; } else { pageModelString = post.SerializedModel; } if (!string.IsNullOrWhiteSpace(pageModelString)) { request.ViewModel.TemplateModel = serializer.Deserialize(request.Template.ModelType, pageModelString); } } if (customModelIsValid) { // we are going to return the parsed model either way request.ViewModel.TemplateModel = model; var validationContext = new ValidationContext(model, serviceProvider: null, items: null); var validationResults = new List <ValidationResult>(); customModelIsValid = validator.IsValid(model, validationContext, validationResults); if (!customModelIsValid) { foreach (var item in validationResults) { foreach (var memberName in item.MemberNames) { request.ModelState.AddModelError(memberName, item.ErrorMessage); } } } } if (!string.IsNullOrEmpty(request.ViewModel.Slug)) { // remove any bad characters request.ViewModel.Slug = ContentUtils.CreateSlug(request.ViewModel.Slug); if (request.ViewModel.Slug != post.Slug) { var slug = request.ViewModel.Slug; var slugIsAvailable = await _blogService.SlugIsAvailable(slug); while (!slugIsAvailable) { slug += "-"; slugIsAvailable = await _blogService.SlugIsAvailable(slug); } if (slugIsAvailable) { post.Slug = slug; } } } if (request.ModelState.IsValid) { var modelString = serializer.Serialize(request.Template.ModelType, model); var renderedModel = await _viewRenderer.RenderViewAsString(request.Template.RenderView, model).ConfigureAwait(false); post.Title = request.ViewModel.Title; post.CorrelationKey = request.ViewModel.CorrelationKey; post.ImageUrl = request.ViewModel.ImageUrl; post.ThumbnailUrl = request.ViewModel.ThumbnailUrl; post.IsFeatured = request.ViewModel.IsFeatured; post.TeaserOverride = request.ViewModel.TeaserOverride; post.SuppressTeaser = request.ViewModel.SuppressTeaser; post.ShowComments = request.ViewModel.ShowComments; post.LastModified = DateTime.UtcNow; post.LastModifiedByUser = request.UserName; post.MetaDescription = request.ViewModel.MetaDescription; var categories = new List <string>(); if (!string.IsNullOrEmpty(request.ViewModel.Categories)) { if (_editOptions.ForceLowerCaseCategories) { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim().ToLower()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } else { categories = request.ViewModel.Categories.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x) && x != "," ) .Distinct() .ToList(); } } post.Categories = categories; var tzId = await _timeZoneIdResolver.GetUserTimeZoneId(CancellationToken.None); var shouldFirePublishEvent = false; var saveMode = request.ViewModel.SaveMode; if (saveMode == SaveMode.PublishLater) { if (request.ViewModel.NewPubDate.HasValue) { var newPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); if (newPubDate < DateTime.UtcNow) { saveMode = SaveMode.PublishNow; post.PubDate = newPubDate; } } } switch (saveMode) { case SaveMode.SaveDraft: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishLater: post.DraftSerializedModel = modelString; post.DraftContent = renderedModel; post.DraftAuthor = request.ViewModel.Author; if (request.ViewModel.NewPubDate.HasValue) { post.DraftPubDate = _timeZoneHelper.ConvertToUtc(request.ViewModel.NewPubDate.Value, tzId); } if (!post.PubDate.HasValue) { post.IsPublished = false; } break; case SaveMode.PublishNow: post.Author = request.ViewModel.Author; post.Content = renderedModel; post.SerializedModel = modelString; if (!post.PubDate.HasValue) { post.PubDate = DateTime.UtcNow; } post.IsPublished = true; shouldFirePublishEvent = true; post.DraftAuthor = null; post.DraftContent = null; post.DraftPubDate = null; post.DraftSerializedModel = null; break; } if (project.TeaserMode != TeaserMode.Off) { // need to generate the teaser on save var teaserResult = _teaserService.GenerateTeaser( project.TeaserTruncationMode, project.TeaserTruncationLength, post.Content, Guid.NewGuid().ToString(),//cache key post.Slug, project.LanguageCode, false //logWarnings ); post.AutoTeaser = teaserResult.Content; } await _historyCommands.Create(request.ProjectId, history).ConfigureAwait(false); await _blogService.Update(post); if (shouldFirePublishEvent) { await _blogService.FirePublishEvent(post).ConfigureAwait(false); await _historyCommands.DeleteDraftHistory(project.Id, post.Id).ConfigureAwait(false); } } return(new CommandResult <IPost>(post, customModelIsValid && request.ModelState.IsValid, errors)); } catch (Exception ex) { _log.LogError($"{ex.Message}:{ex.StackTrace}"); errors.Add(_localizer["Updating a post from a content template failed. An error has been logged."]); return(new CommandResult <IPost>(null, false, errors)); } }
public async Task <bool> EditPost( string blogId, string postId, string userName, string password, PostStruct post, bool publish) { var permission = await _security.ValidatePermissions( blogId, userName, password, CancellationToken.None ).ConfigureAwait(false); if (!permission.CanEditPosts) { _log.LogWarning($"rejecting new post because user {userName} cannot edit posts"); return(false); } var existing = await _blogService.GetPost(postId).ConfigureAwait(false); if (existing == null) { _log.LogError($"post not found for id {postId}"); return(false); } if (!string.IsNullOrWhiteSpace(existing.TemplateKey)) { _log.LogError($"post {postId} uses a content template and cannot be edited via metaweblog api"); return(false); } if (existing.ContentType != ProjectConstants.HtmlContentType) { _log.LogError($"post {postId} uses a content type {existing.ContentType} and cannot be edited via metaweblog api"); return(false); } var history = existing.CreateHistory(userName); var update = _mapper.GetPostFromStruct(post); existing.Title = update.Title; existing.MetaDescription = update.MetaDescription; existing.LastModified = DateTime.UtcNow; existing.LastModifiedByUser = permission.DisplayName; if (!string.Equals(existing.Slug, update.Slug, StringComparison.OrdinalIgnoreCase)) { // slug changed make sure the new slug is available var requestedSlug = ContentUtils.CreateSlug(update.Slug); var available = await _blogService.SlugIsAvailable(blogId, requestedSlug).ConfigureAwait(false); if (available) { existing.Slug = requestedSlug; } } existing.Categories = update.Categories; if (publish) { existing.Content = update.Content; existing.IsPublished = true; if (!existing.PubDate.HasValue) { existing.PubDate = DateTime.UtcNow; } existing.DraftAuthor = null; existing.DraftContent = null; existing.DraftPubDate = null; } else { existing.DraftContent = update.Content; } var convertToRelativeUrls = true; await _blogService.Update(existing, convertToRelativeUrls).ConfigureAwait(false); await _contentHistoryCommands.Create(blogId, history); if (publish) { await _blogService.FirePublishEvent(existing); await _contentHistoryCommands.DeleteDraftHistory(blogId, history.ContentId); } return(true); }