public async Task <PostEntity> UpdateAsync(EditPostRequest request) { var post = await _postRepository.GetAsync(request.Id); if (null == post) { throw new InvalidOperationException($"Post {request.Id} is not found."); } post.CommentEnabled = request.EnableComment; post.PostContent = request.EditorContent; post.ContentAbstract = GetPostAbstract( request.EditorContent, AppSettings.PostAbstractWords, AppSettings.Editor == EditorChoice.Markdown); // Address #221: Do not allow published posts back to draft status // postModel.IsPublished = request.IsPublished; // Edit draft -> save and publish, ignore false case because #221 bool isNewPublish = false; if (request.IsPublished && !post.IsPublished) { post.IsPublished = true; post.PubDateUtc = DateTime.UtcNow; isNewPublish = true; } // #325: Allow changing publish date for published posts if (request.PublishDate != null && post.PubDateUtc.HasValue) { var tod = post.PubDateUtc.Value.TimeOfDay; var adjustedDate = _dateTimeResolver.ToUtc(request.PublishDate.Value); post.PubDateUtc = adjustedDate.AddTicks(tod.Ticks); } post.Slug = request.Slug; post.Title = request.Title; post.ExposedToSiteMap = request.ExposedToSiteMap; post.LastModifiedUtc = DateTime.UtcNow; post.IsFeedIncluded = request.IsFeedIncluded; post.ContentLanguageCode = request.ContentLanguageCode; // 1. Add new tags to tag lib foreach (var item in request.Tags.Where(item => !_tagRepository.Any(p => p.DisplayName == item))) { await _tagRepository.AddAsync(new TagEntity { DisplayName = item, NormalizedName = TagService.NormalizeTagName(item) }); await _blogAudit.AddAuditEntry(EventType.Content, AuditEventId.TagCreated, $"Tag '{item}' created."); } // 2. update tags post.PostTag.Clear(); if (request.Tags.Any()) { foreach (var tagName in request.Tags) { if (!TagService.ValidateTagName(tagName)) { continue; } var tag = await _tagRepository.GetAsync(t => t.DisplayName == tagName); if (tag != null) { post.PostTag.Add(new PostTagEntity { PostId = post.Id, TagId = tag.Id }); } } } // 3. update categories post.PostCategory.Clear(); if (null != request.CategoryIds && request.CategoryIds.Length > 0) { foreach (var cid in request.CategoryIds) { if (_categoryRepository.Any(c => c.Id == cid)) { post.PostCategory.Add(new PostCategoryEntity { PostId = post.Id, CategoryId = cid }); } } } await _postRepository.UpdateAsync(post); await _blogAudit.AddAuditEntry( EventType.Content, isNewPublish?AuditEventId.PostPublished : AuditEventId.PostUpdated, $"Post updated, id: {post.Id}"); _cache.Remove(CacheDivision.Post, request.Id.ToString()); return(post); }
public async Task <PostEntity> CreateAsync(CreatePostRequest request) { var abs = GetPostAbstract( request.EditorContent, AppSettings.PostAbstractWords, AppSettings.Editor == EditorChoice.Markdown); var post = new PostEntity { CommentEnabled = request.EnableComment, Id = Guid.NewGuid(), PostContent = request.EditorContent, ContentAbstract = abs, CreateOnUtc = DateTime.UtcNow, Slug = request.Slug.ToLower().Trim(), Title = request.Title.Trim(), ContentLanguageCode = request.ContentLanguageCode, ExposedToSiteMap = request.ExposedToSiteMap, IsFeedIncluded = request.IsFeedIncluded, PubDateUtc = request.IsPublished ? DateTime.UtcNow : (DateTime?)null, IsDeleted = false, IsPublished = request.IsPublished, PostExtension = new PostExtensionEntity { Hits = 0, Likes = 0 } }; // check if exist same slug under the same day // linq to sql fix: // cannot write "p.PubDateUtc.GetValueOrDefault().Date == DateTime.UtcNow.Date" // it will not blow up, but can result in select ENTIRE posts and evaluated in memory!!! // - The LINQ expression 'where (Convert([p]?.PubDateUtc?.GetValueOrDefault(), DateTime).Date == DateTime.UtcNow.Date)' could not be translated and will be evaluated locally // Why EF Core this diao yang? if (_postRepository.Any(p => p.Slug == post.Slug && p.PubDateUtc != null && p.PubDateUtc.Value.Year == DateTime.UtcNow.Date.Year && p.PubDateUtc.Value.Month == DateTime.UtcNow.Date.Month && p.PubDateUtc.Value.Day == DateTime.UtcNow.Date.Day)) { var uid = Guid.NewGuid(); post.Slug += $"-{uid.ToString().ToLower().Substring(0, 8)}"; Logger.LogInformation($"Found conflict for post slug, generated new slug: {post.Slug}"); } // add categories if (null != request.CategoryIds && request.CategoryIds.Length > 0) { foreach (var cid in request.CategoryIds) { if (_categoryRepository.Any(c => c.Id == cid)) { post.PostCategory.Add(new PostCategoryEntity { CategoryId = cid, PostId = post.Id }); } } } // add tags if (null != request.Tags && request.Tags.Length > 0) { foreach (var item in request.Tags) { if (!TagService.ValidateTagName(item)) { continue; } var tag = await _tagRepository.GetAsync(q => q.DisplayName == item); if (null == tag) { var newTag = new TagEntity { DisplayName = item, NormalizedName = TagService.NormalizeTagName(item) }; tag = await _tagRepository.AddAsync(newTag); await _blogAudit.AddAuditEntry(EventType.Content, AuditEventId.TagCreated, $"Tag '{tag.NormalizedName}' created."); } post.PostTag.Add(new PostTagEntity { TagId = tag.Id, PostId = post.Id }); } } await _postRepository.AddAsync(post); await _blogAudit.AddAuditEntry(EventType.Content, AuditEventId.PostCreated, $"Post created, id: {post.Id}"); return(post); }