|
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
|
|
|
using Volo.Abp.Caching;
|
|
|
|
|
using Volo.Abp.EventBus.Local;
|
|
|
|
|
using Volo.Blogging.Comments;
|
|
|
|
|
using Volo.Blogging.Tagging;
|
|
|
|
|
using Volo.Blogging.Tagging.Dtos;
|
|
|
|
@ -20,41 +21,92 @@ namespace Volo.Blogging.Posts
|
|
|
|
|
private readonly IPostRepository _postRepository;
|
|
|
|
|
private readonly ITagRepository _tagRepository;
|
|
|
|
|
private readonly ICommentRepository _commentRepository;
|
|
|
|
|
private readonly IDistributedCache<ListResultDto<PostWithDetailsDto>> _postsCache;
|
|
|
|
|
|
|
|
|
|
public PostAppService(IPostRepository postRepository, ITagRepository tagRepository, ICommentRepository commentRepository, IBlogUserLookupService userLookupService, IDistributedCache<ListResultDto<PostWithDetailsDto>> postsCache)
|
|
|
|
|
private readonly IDistributedCache<List<PostCacheItem>> _postsCache;
|
|
|
|
|
private readonly ILocalEventBus _localEventBus;
|
|
|
|
|
|
|
|
|
|
public PostAppService(
|
|
|
|
|
IPostRepository postRepository,
|
|
|
|
|
ITagRepository tagRepository,
|
|
|
|
|
ICommentRepository commentRepository,
|
|
|
|
|
IBlogUserLookupService userLookupService,
|
|
|
|
|
IDistributedCache<List<PostCacheItem>> postsCache,
|
|
|
|
|
ILocalEventBus localEventBus
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
UserLookupService = userLookupService;
|
|
|
|
|
_postRepository = postRepository;
|
|
|
|
|
_tagRepository = tagRepository;
|
|
|
|
|
_commentRepository = commentRepository;
|
|
|
|
|
_postsCache = postsCache;
|
|
|
|
|
_localEventBus = localEventBus;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<ListResultDto<PostWithDetailsDto>> GetListByBlogIdAndTagName(Guid id, string tagName)
|
|
|
|
|
{
|
|
|
|
|
var cacheKey = id.ToString() + "-" + tagName;
|
|
|
|
|
var posts = await _postRepository.GetPostsByBlogId(id);
|
|
|
|
|
var tag = tagName.IsNullOrWhiteSpace() ? null : await _tagRepository.FindByNameAsync(id, tagName);
|
|
|
|
|
var userDictionary = new Dictionary<Guid, BlogUserDto>();
|
|
|
|
|
var postDtos = new List<PostWithDetailsDto>(ObjectMapper.Map<List<Post>, List<PostWithDetailsDto>>(posts));
|
|
|
|
|
|
|
|
|
|
return await _postsCache.GetOrAddAsync(
|
|
|
|
|
cacheKey,
|
|
|
|
|
async () => await GetPostsByBlogIdAndTagName(id, tagName),
|
|
|
|
|
() => new DistributedCacheEntryOptions
|
|
|
|
|
foreach (var postDto in postDtos)
|
|
|
|
|
{
|
|
|
|
|
postDto.Tags = await GetTagsOfPost(postDto.Id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tag != null)
|
|
|
|
|
{
|
|
|
|
|
postDtos = await FilterPostsByTag(postDtos, tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var postDto in postDtos)
|
|
|
|
|
{
|
|
|
|
|
if (postDto.CreatorId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
AbsoluteExpiration = DateTimeOffset.Now.AddHours(6)
|
|
|
|
|
if (!userDictionary.ContainsKey(postDto.CreatorId.Value))
|
|
|
|
|
{
|
|
|
|
|
var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value);
|
|
|
|
|
if (creatorUser != null)
|
|
|
|
|
{
|
|
|
|
|
userDictionary[creatorUser.Id] = ObjectMapper.Map<BlogUser, BlogUserDto>(creatorUser);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userDictionary.ContainsKey(postDto.CreatorId.Value))
|
|
|
|
|
{
|
|
|
|
|
postDto.Writer = userDictionary[(Guid)postDto.CreatorId];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ListResultDto<PostWithDetailsDto>(postDtos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<ListResultDto<PostWithDetailsDto>> GetTimeOrderedListAsync(Guid blogId)
|
|
|
|
|
{
|
|
|
|
|
return await _postsCache.GetOrAddAsync(
|
|
|
|
|
var postCacheItems = await _postsCache.GetOrAddAsync(
|
|
|
|
|
blogId.ToString(),
|
|
|
|
|
async () => await GetTimeOrderedPostsAsync(blogId),
|
|
|
|
|
() => new DistributedCacheEntryOptions
|
|
|
|
|
{
|
|
|
|
|
AbsoluteExpiration = DateTimeOffset.Now.AddHours(6)
|
|
|
|
|
AbsoluteExpiration = DateTimeOffset.Now.AddHours(1)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var postsWithDetails = ObjectMapper.Map<List<PostCacheItem>, List<PostWithDetailsDto>>(postCacheItems);
|
|
|
|
|
|
|
|
|
|
foreach (var post in postsWithDetails)
|
|
|
|
|
{
|
|
|
|
|
if (post.CreatorId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
var creatorUser = await UserLookupService.FindByIdAsync(post.CreatorId.Value);
|
|
|
|
|
if (creatorUser != null)
|
|
|
|
|
{
|
|
|
|
|
post.Writer = ObjectMapper.Map<BlogUser, BlogUserDto>(creatorUser);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ListResultDto<PostWithDetailsDto>(postsWithDetails);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<PostWithDetailsDto> GetForReadingAsync(GetPostInput input)
|
|
|
|
@ -107,6 +159,7 @@ namespace Volo.Blogging.Posts
|
|
|
|
|
await _commentRepository.DeleteOfPost(id);
|
|
|
|
|
|
|
|
|
|
await _postRepository.DeleteAsync(id);
|
|
|
|
|
await PublishPostChangedEventAsync(post.BlogId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Authorize(BloggingPermissions.Posts.Update)]
|
|
|
|
@ -128,6 +181,7 @@ namespace Volo.Blogging.Posts
|
|
|
|
|
|
|
|
|
|
var tagList = SplitTags(input.Tags);
|
|
|
|
|
await SaveTags(tagList, post);
|
|
|
|
|
await PublishPostChangedEventAsync(post.BlogId);
|
|
|
|
|
|
|
|
|
|
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
|
|
|
|
|
}
|
|
|
|
@ -153,66 +207,16 @@ namespace Volo.Blogging.Posts
|
|
|
|
|
|
|
|
|
|
var tagList = SplitTags(input.Tags);
|
|
|
|
|
await SaveTags(tagList, post);
|
|
|
|
|
await PublishPostChangedEventAsync(post.BlogId);
|
|
|
|
|
|
|
|
|
|
return ObjectMapper.Map<Post, PostWithDetailsDto>(post);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<ListResultDto<PostWithDetailsDto>> GetPostsByBlogIdAndTagName(Guid id, string tagName)
|
|
|
|
|
{
|
|
|
|
|
var posts = await _postRepository.GetPostsByBlogId(id);
|
|
|
|
|
var tag = tagName.IsNullOrWhiteSpace() ? null : await _tagRepository.FindByNameAsync(id, tagName);
|
|
|
|
|
var userDictionary = new Dictionary<Guid, BlogUserDto>();
|
|
|
|
|
var postDtos = new List<PostWithDetailsDto>(ObjectMapper.Map<List<Post>, List<PostWithDetailsDto>>(posts));
|
|
|
|
|
|
|
|
|
|
foreach (var postDto in postDtos)
|
|
|
|
|
{
|
|
|
|
|
postDto.Tags = await GetTagsOfPost(postDto.Id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tag != null)
|
|
|
|
|
{
|
|
|
|
|
postDtos = await FilterPostsByTag(postDtos, tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var postDto in postDtos)
|
|
|
|
|
{
|
|
|
|
|
if (postDto.CreatorId.HasValue)
|
|
|
|
|
{
|
|
|
|
|
if (!userDictionary.ContainsKey(postDto.CreatorId.Value))
|
|
|
|
|
{
|
|
|
|
|
var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value);
|
|
|
|
|
if (creatorUser != null)
|
|
|
|
|
{
|
|
|
|
|
userDictionary[creatorUser.Id] = ObjectMapper.Map<BlogUser, BlogUserDto>(creatorUser);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userDictionary.ContainsKey(postDto.CreatorId.Value))
|
|
|
|
|
{
|
|
|
|
|
postDto.Writer = userDictionary[(Guid)postDto.CreatorId];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ListResultDto<PostWithDetailsDto>(postDtos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<ListResultDto<PostWithDetailsDto>> GetTimeOrderedPostsAsync(Guid blogId)
|
|
|
|
|
private async Task<List<PostCacheItem>> GetTimeOrderedPostsAsync(Guid blogId)
|
|
|
|
|
{
|
|
|
|
|
var posts = await _postRepository.GetOrderedList(blogId);
|
|
|
|
|
|
|
|
|
|
var postDtos = new List<PostWithDetailsDto>(ObjectMapper.Map<List<Post>, List<PostWithDetailsDto>>(posts));
|
|
|
|
|
|
|
|
|
|
foreach (var postDto in postDtos)
|
|
|
|
|
{
|
|
|
|
|
var creatorUser = await UserLookupService.FindByIdAsync(postDto.CreatorId.Value);
|
|
|
|
|
if (creatorUser != null)
|
|
|
|
|
{
|
|
|
|
|
postDto.Writer = ObjectMapper.Map<BlogUser, BlogUserDto>(creatorUser);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new ListResultDto<PostWithDetailsDto>(postDtos);
|
|
|
|
|
return ObjectMapper.Map<List<Post>, List<PostCacheItem>>(posts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task<string> RenameUrlIfItAlreadyExistAsync(Guid blogId, string url, Post existingPost = null)
|
|
|
|
@ -300,5 +304,14 @@ namespace Volo.Blogging.Posts
|
|
|
|
|
|
|
|
|
|
return Task.FromResult(filteredPostDtos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task PublishPostChangedEventAsync(Guid blogId)
|
|
|
|
|
{
|
|
|
|
|
await _localEventBus.PublishAsync(
|
|
|
|
|
new PostChangedEvent
|
|
|
|
|
{
|
|
|
|
|
BlogId = blogId
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|