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)); } }
private ContentFilterResult FilterHtmlForList(IPost post, IProjectSettings settings, bool useTeaser) { var result = new ContentFilterResult(); if (useTeaser) { TeaserResult teaserResult = null; string teaser = null; if (!string.IsNullOrWhiteSpace(post.TeaserOverride)) { if (post.ContentType == "markdown") { teaser = MapImageUrlsToCdn( ConvertMarkdownToHtml(post.TeaserOverride), settings.CdnUrl, settings.LocalMediaVirtualPath); } else { teaser = MapImageUrlsToCdn( post.TeaserOverride, settings.CdnUrl, settings.LocalMediaVirtualPath); } result.FilteredContent = teaser; result.IsFullContent = false; } else if (!string.IsNullOrWhiteSpace(post.AutoTeaser)) // as of 2018-08-20 this gets populated on save { teaser = MapImageUrlsToCdn( post.AutoTeaser, settings.CdnUrl, settings.LocalMediaVirtualPath); result.FilteredContent = teaser; result.IsFullContent = false; } else { // need to generate teaser if (post.ContentType == "markdown") { var html = MapImageUrlsToCdn( ConvertMarkdownToHtml(post.CoalesceContentToDraftContent()), settings.CdnUrl, settings.LocalMediaVirtualPath); teaserResult = _teaserService.GenerateTeaser( settings.TeaserTruncationMode, settings.TeaserTruncationLength, html, post.Id, post.Slug, settings.LanguageCode ); } else { var html = MapImageUrlsToCdn( post.CoalesceContentToDraftContent(), settings.CdnUrl, settings.LocalMediaVirtualPath); teaserResult = _teaserService.GenerateTeaser( settings.TeaserTruncationMode, settings.TeaserTruncationLength, html, post.Id, post.Slug, settings.LanguageCode ); } result.FilteredContent = teaserResult.Content; result.IsFullContent = !teaserResult.DidTruncate; } } else { // using full content if (post.ContentType == "markdown") { result.FilteredContent = MapImageUrlsToCdn( ConvertMarkdownToHtml(post.CoalesceContentToDraftContent()), settings.CdnUrl, settings.LocalMediaVirtualPath); } else { result.FilteredContent = MapImageUrlsToCdn( post.CoalesceContentToDraftContent(), settings.CdnUrl, settings.LocalMediaVirtualPath); } result.IsFullContent = true; } return(result); }
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)); } }