You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sonic/service/assembler/post.go

340 lines
10 KiB
Go

package assembler
import (
"context"
"sort"
"time"
"github.com/go-sonic/sonic/consts"
"github.com/go-sonic/sonic/model/dto"
"github.com/go-sonic/sonic/model/entity"
"github.com/go-sonic/sonic/model/vo"
"github.com/go-sonic/sonic/service"
)
type PostAssembler interface {
BasePostAssembler
ConvertToListVO(ctx context.Context, posts []*entity.Post) ([]*vo.Post, error)
ConvertToDetailVO(ctx context.Context, post *entity.Post) (*vo.PostDetailVO, error)
ConvertToDetailVOs(ctx context.Context, posts []*entity.Post) ([]*vo.PostDetailVO, error)
ConvertToArchiveYearVOs(ctx context.Context, posts []*entity.Post) ([]*vo.ArchiveYear, error)
ConvertTOArchiveMonthVOs(ctx context.Context, posts []*entity.Post) ([]*vo.ArchiveMonth, error)
}
func NewPostAssembler(basePostService service.BasePostService,
baseCommentService service.BaseCommentService,
postTagService service.PostTagService,
postCategoryService service.PostCategoryService,
tagService service.TagService,
categoryService service.CategoryService,
postCommentService service.PostCommentService,
metaService service.MetaService,
basePostAssembler BasePostAssembler,
) PostAssembler {
return &postAssembler{
BasePostAssembler: basePostAssembler,
BasePostService: basePostService,
BaseCommentService: baseCommentService,
PostTagService: postTagService,
PostCommentService: postCommentService,
PostCategoryService: postCategoryService,
TagService: tagService,
CategoryService: categoryService,
MetaService: metaService,
}
}
type postAssembler struct {
BasePostAssembler
BasePostService service.BasePostService
BaseCommentService service.BaseCommentService
PostTagService service.PostTagService
PostCategoryService service.PostCategoryService
TagService service.TagService
CategoryService service.CategoryService
PostCommentService service.PostCommentService
MetaService service.MetaService
}
func (p *postAssembler) ConvertToListVO(ctx context.Context, posts []*entity.Post) ([]*vo.Post, error) {
postVOs := make([]*vo.Post, 0)
postIDs := make([]int32, 0)
for _, post := range posts {
postIDs = append(postIDs, post.ID)
}
postTagMap, err := p.PostTagService.ListTagMapByPostID(ctx, postIDs)
if err != nil {
return nil, err
}
tagDTOMap := make(map[int32]*dto.Tag)
for _, tags := range postTagMap {
for _, tag := range tags {
if _, ok := tagDTOMap[tag.ID]; !ok {
tagDTO, err := p.TagService.ConvertToDTO(ctx, tag)
if err != nil {
return nil, err
}
tagDTOMap[tag.ID] = tagDTO
}
}
}
categoryMap, err := p.PostCategoryService.ListCategoryMapByPostID(ctx, postIDs)
if err != nil {
return nil, err
}
categoryDTOMap := make(map[int32]*dto.CategoryDTO, 0)
for _, categories := range categoryMap {
for _, category := range categories {
if _, ok := categoryDTOMap[category.ID]; !ok {
categoryDTO, err := p.CategoryService.ConvertToCategoryDTO(ctx, category)
if err != nil {
return nil, err
}
categoryDTOMap[category.ID] = categoryDTO
}
}
}
commentCountMap, err := p.PostCommentService.CountByStatusAndContentIDs(ctx, consts.CommentStatusPublished, postIDs)
if err != nil {
return nil, err
}
postMetaMap, err := p.MetaService.GetPostsMeta(ctx, postIDs)
if err != nil {
return nil, err
}
for _, post := range posts {
postVO := &vo.Post{}
if commentCount, ok := commentCountMap[post.ID]; ok {
postVO.CommentCount = commentCount
}
if categories, ok := categoryMap[post.ID]; ok {
categoryDTOs := make([]*dto.CategoryDTO, 0)
for _, category := range categories {
if categoryDTO, ok := categoryDTOMap[category.ID]; ok {
categoryDTOs = append(categoryDTOs, categoryDTO)
}
}
postVO.Categories = categoryDTOs
}
if tags, ok := postTagMap[post.ID]; ok {
tagDTOs := make([]*dto.Tag, 0)
for _, tag := range tags {
if tagDTO, ok := tagDTOMap[tag.ID]; ok {
tagDTOs = append(tagDTOs, tagDTO)
}
}
postVO.Tags = tagDTOs
}
if metas, ok := postMetaMap[post.ID]; ok {
metaMap := make(map[string]interface{})
for _, meta := range metas {
metaMap[meta.MetaKey] = meta
}
postVO.Metas = metaMap
}
postDTO, err := p.ConvertToSimpleDTO(ctx, post)
if err != nil {
return nil, err
}
postVO.Post = *postDTO
postVOs = append(postVOs, postVO)
}
return postVOs, nil
}
func (p *postAssembler) ConvertToDetailVO(ctx context.Context, post *entity.Post) (*vo.PostDetailVO, error) {
if post == nil {
return nil, nil
}
postDetailVO := &vo.PostDetailVO{}
postDetailDTO, err := p.ConvertToDetailDTO(ctx, post)
if err != nil {
return nil, err
}
postDetailVO.PostDetail = *postDetailDTO
tags, err := p.PostTagService.ListTagByPostID(ctx, post.ID)
if err != nil {
return nil, err
}
tagIDs := make([]int32, 0)
tagDTOs := make([]*dto.Tag, 0)
for _, tag := range tags {
tagIDs = append(tagIDs, tag.ID)
tagDTO, err := p.TagService.ConvertToDTO(ctx, tag)
if err != nil {
return nil, err
}
tagDTOs = append(tagDTOs, tagDTO)
}
postDetailVO.TagIDs = tagIDs
postDetailVO.Tags = tagDTOs
categories, err := p.PostCategoryService.ListCategoryByPostID(ctx, post.ID)
if err != nil {
return nil, err
}
categoryDTOs := make([]*dto.CategoryDTO, 0, len(categories))
categoryIDs := make([]int32, 0)
for _, category := range categories {
categoryDTO, err := p.CategoryService.ConvertToCategoryDTO(ctx, category)
if err != nil {
return nil, err
}
categoryDTOs = append(categoryDTOs, categoryDTO)
categoryIDs = append(categoryIDs, category.ID)
}
postDetailVO.CategoryIDs = categoryIDs
postDetailVO.Categories = categoryDTOs
postMetas, err := p.MetaService.GetPostMeta(ctx, post.ID)
if err != nil {
return nil, err
}
metaDTOs := make([]*dto.Meta, 0, len(postMetas))
metaIDs := make([]int32, 0, len(postMetas))
for _, meta := range postMetas {
metaDTOs = append(metaDTOs, p.MetaService.ConvertToMetaDTO(meta))
metaIDs = append(metaIDs, meta.ID)
}
postDetailVO.MetaIDs = metaIDs
postDetailVO.Metas = metaDTOs
return postDetailVO, nil
}
func (p *postAssembler) ConvertToDetailVOs(ctx context.Context, posts []*entity.Post) ([]*vo.PostDetailVO, error) {
postDetailVOs := make([]*vo.PostDetailVO, 0)
postIDs := make([]int32, 0)
for _, post := range posts {
postIDs = append(postIDs, post.ID)
}
postTagMap, err := p.PostTagService.ListTagMapByPostID(ctx, postIDs)
if err != nil {
return nil, err
}
tagDTOMap := make(map[int32]*dto.Tag)
for _, tags := range postTagMap {
for _, tag := range tags {
if _, ok := tagDTOMap[tag.ID]; !ok {
tagDTO, err := p.TagService.ConvertToDTO(ctx, tag)
if err != nil {
return nil, err
}
tagDTOMap[tag.ID] = tagDTO
}
}
}
categoryMap, err := p.PostCategoryService.ListCategoryMapByPostID(ctx, postIDs)
if err != nil {
return nil, err
}
categoryDTOMap := make(map[int32]*dto.CategoryDTO, 0)
for _, categories := range categoryMap {
for _, category := range categories {
if _, ok := categoryDTOMap[category.ID]; !ok {
categoryDTO, err := p.CategoryService.ConvertToCategoryDTO(ctx, category)
if err != nil {
return nil, err
}
categoryDTOMap[category.ID] = categoryDTO
}
}
}
postMetaMap, err := p.MetaService.GetPostsMeta(ctx, postIDs)
if err != nil {
return nil, err
}
for _, post := range posts {
postDetailVO := &vo.PostDetailVO{}
if categories, ok := categoryMap[post.ID]; ok {
categoryDTOs := make([]*dto.CategoryDTO, 0)
categoryIDs := make([]int32, 0)
for _, category := range categories {
if categoryDTO, ok := categoryDTOMap[category.ID]; ok {
categoryDTOs = append(categoryDTOs, categoryDTO)
categoryIDs = append(categoryIDs, categoryDTO.ID)
}
}
postDetailVO.Categories = categoryDTOs
postDetailVO.CategoryIDs = categoryIDs
}
if tags, ok := postTagMap[post.ID]; ok {
tagDTOs := make([]*dto.Tag, 0)
tagIDs := make([]int32, 0)
for _, tag := range tags {
if tagDTO, ok := tagDTOMap[tag.ID]; ok {
tagDTOs = append(tagDTOs, tagDTO)
tagIDs = append(tagIDs, tagDTO.ID)
}
}
postDetailVO.Tags = tagDTOs
postDetailVO.TagIDs = tagIDs
}
if metas, ok := postMetaMap[post.ID]; ok {
metaDTOs := make([]*dto.Meta, 0)
metaIDs := make([]int32, 0)
for _, meta := range metas {
metaDTOs = append(metaDTOs, p.MetaService.ConvertToMetaDTO(meta))
metaIDs = append(metaIDs, meta.ID)
}
postDetailVO.Metas = metaDTOs
postDetailVO.MetaIDs = metaIDs
}
postDetailDTO, err := p.ConvertToDetailDTO(ctx, post)
if err != nil {
return nil, err
}
postDetailVO.PostDetail = *postDetailDTO
postDetailVOs = append(postDetailVOs, postDetailVO)
}
return postDetailVOs, nil
}
func (p *postAssembler) ConvertToArchiveYearVOs(ctx context.Context, posts []*entity.Post) ([]*vo.ArchiveYear, error) {
postVos, err := p.ConvertToListVO(ctx, posts)
if err != nil {
return nil, err
}
archiveYearVos := make([]*vo.ArchiveYear, 0)
yearToPostMap := make(map[int][]*vo.Post)
for _, postVo := range postVos {
yearToPostMap[time.UnixMilli(postVo.CreateTime).Year()] = append(yearToPostMap[time.UnixMilli(postVo.CreateTime).Year()], postVo)
}
for year, postVos := range yearToPostMap {
sort.Slice(postVos, func(i, j int) bool {
return postVos[i].CreateTime >= postVos[j].CreateTime
})
archiveYearVos = append(archiveYearVos, &vo.ArchiveYear{Year: year, Posts: postVos})
}
sort.Slice(archiveYearVos, func(i, j int) bool {
return archiveYearVos[i].Year >= archiveYearVos[j].Year
})
return archiveYearVos, nil
}
func (p *postAssembler) ConvertTOArchiveMonthVOs(ctx context.Context, posts []*entity.Post) ([]*vo.ArchiveMonth, error) {
postVos, err := p.ConvertToListVO(ctx, posts)
if err != nil {
return nil, err
}
archiveMonthVos := make([]*vo.ArchiveMonth, 0)
monthToPostMap := make(map[int][]*vo.Post)
for _, postVo := range postVos {
monthToPostMap[int(time.UnixMilli(postVo.CreateTime).Month())] = append(monthToPostMap[int(time.UnixMilli(postVo.CreateTime).Month())], postVo)
}
for year, postVos := range monthToPostMap {
sort.Slice(postVos, func(i, j int) bool {
return postVos[i].CreateTime >= postVos[j].CreateTime
})
archiveMonthVos = append(archiveMonthVos, &vo.ArchiveMonth{Month: year, Posts: postVos})
}
sort.Slice(archiveMonthVos, func(i, j int) bool {
return archiveMonthVos[i].Month >= archiveMonthVos[j].Month
})
return archiveMonthVos, nil
}