mirror of https://github.com/go-sonic/sonic.git
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.
788 lines
25 KiB
Go
788 lines
25 KiB
Go
package impl
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"gorm.io/gen/field"
|
|
|
|
"github.com/go-sonic/sonic/consts"
|
|
"github.com/go-sonic/sonic/dal"
|
|
"github.com/go-sonic/sonic/model/dto"
|
|
"github.com/go-sonic/sonic/model/entity"
|
|
"github.com/go-sonic/sonic/model/param"
|
|
"github.com/go-sonic/sonic/model/projection"
|
|
"github.com/go-sonic/sonic/model/property"
|
|
"github.com/go-sonic/sonic/model/vo"
|
|
"github.com/go-sonic/sonic/service"
|
|
"github.com/go-sonic/sonic/util"
|
|
"github.com/go-sonic/sonic/util/xerr"
|
|
)
|
|
|
|
type categoryServiceImpl struct {
|
|
OptionService service.OptionService
|
|
}
|
|
|
|
func NewCategoryService(optionService service.OptionService) service.CategoryService {
|
|
return &categoryServiceImpl{
|
|
OptionService: optionService,
|
|
}
|
|
}
|
|
|
|
func (c categoryServiceImpl) GetByID(ctx context.Context, id int32) (*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
category, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.Eq(id)).Take()
|
|
return category, WrapDBErr(err)
|
|
}
|
|
|
|
func (c categoryServiceImpl) GetBySlug(ctx context.Context, slug string) (*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
category, err := categoryDAL.WithContext(ctx).Where(categoryDAL.Slug.Eq(slug)).Take()
|
|
return category, WrapDBErr(err)
|
|
}
|
|
|
|
func (c categoryServiceImpl) GetByName(ctx context.Context, name string) (*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
category, err := categoryDAL.WithContext(ctx).Where(categoryDAL.Name.Eq(name)).Take()
|
|
return category, WrapDBErr(err)
|
|
}
|
|
|
|
func (c categoryServiceImpl) ListCategoryWithPostCountDTO(ctx context.Context, sort *param.Sort) ([]*dto.CategoryWithPostCount, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
categoryDO := categoryDAL.WithContext(ctx)
|
|
|
|
err := BuildSort(sort, &categoryDAL, &categoryDO)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
categories, err := categoryDO.Find()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
postCategoryDAL := dal.GetQueryByCtx(ctx).PostCategory
|
|
postCounts := make([]*projection.CategoryPostCountProjection, 0)
|
|
err = postCategoryDAL.WithContext(ctx).Select(postCategoryDAL.CategoryID, postCategoryDAL.PostID.Count().As("post_count")).Group(postCategoryDAL.CategoryID).Scan(&postCounts)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
postCountMap := make(map[int32]int32)
|
|
for _, postCount := range postCounts {
|
|
postCountMap[postCount.CategoryID] = postCount.PostCount
|
|
}
|
|
results := make([]*dto.CategoryWithPostCount, 0)
|
|
for _, category := range categories {
|
|
categoryDTO, err := c.ConvertToCategoryDTO(ctx, category)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
results = append(results, &dto.CategoryWithPostCount{
|
|
CategoryDTO: categoryDTO,
|
|
PostCount: postCountMap[category.ID],
|
|
})
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) ListAll(ctx context.Context, sort *param.Sort) ([]*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
categoryDO := categoryDAL.WithContext(ctx)
|
|
err := BuildSort(sort, &categoryDAL, &categoryDO)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
categories, err := categoryDO.Find()
|
|
return categories, err
|
|
}
|
|
|
|
func (c categoryServiceImpl) ListAsTree(ctx context.Context, sort *param.Sort, fillPassword bool) ([]*vo.CategoryVO, error) {
|
|
allCategory, err := c.ListAll(ctx, sort)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return c.buildTree(ctx, allCategory, fillPassword)
|
|
}
|
|
|
|
func (c categoryServiceImpl) buildTree(ctx context.Context, categories []*entity.Category, fillPassword bool) ([]*vo.CategoryVO, error) {
|
|
categoryTree := make([]*vo.CategoryVO, 0)
|
|
parentIDToCategoryMap := make(map[int32][]*vo.CategoryVO)
|
|
categoryDTOs, err := c.ConvertToCategoryDTOs(ctx, categories)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
categoryVOs := make([]*vo.CategoryVO, len(categories))
|
|
for i, categoryDTO := range categoryDTOs {
|
|
categoryVO := &vo.CategoryVO{
|
|
CategoryDTO: *categoryDTO,
|
|
}
|
|
if !fillPassword {
|
|
categoryVO.Password = ""
|
|
}
|
|
if categoryDTO.ParentID != 0 {
|
|
parentIDToCategoryMap[categoryDTO.ParentID] = append(parentIDToCategoryMap[categoryDTO.ParentID], categoryVO)
|
|
}
|
|
categoryVOs[i] = categoryVO
|
|
}
|
|
for _, categoryVO := range categoryVOs {
|
|
children, ok := parentIDToCategoryMap[categoryVO.ID]
|
|
if ok {
|
|
categoryVO.Children = children
|
|
}
|
|
if categoryVO.ParentID == 0 {
|
|
categoryTree = append(categoryTree, categoryVO)
|
|
}
|
|
}
|
|
return categoryTree, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) ConvertToCategoryDTO(ctx context.Context, e *entity.Category) (*dto.CategoryDTO, error) {
|
|
categoryDTO := &dto.CategoryDTO{}
|
|
categoryDTO.ID = e.ID
|
|
categoryDTO.Thumbnail = e.Thumbnail
|
|
categoryDTO.ParentID = e.ParentID
|
|
categoryDTO.Password = e.Password
|
|
categoryDTO.Name = e.Name
|
|
categoryDTO.CreateTime = e.CreateTime.UnixMilli()
|
|
categoryDTO.Description = e.Description
|
|
categoryDTO.Slug = e.Slug
|
|
categoryDTO.Priority = e.Priority
|
|
isEnabled, err := c.OptionService.IsEnabledAbsolutePath(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fullPath := strings.Builder{}
|
|
if isEnabled {
|
|
blogBaseURL, err := c.OptionService.GetBlogBaseURL(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fullPath.WriteString(blogBaseURL)
|
|
}
|
|
fullPath.WriteString("/")
|
|
categoryPrefix, err := c.OptionService.GetOrByDefaultWithErr(ctx, property.CategoriesPrefix, "categories")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fullPath.WriteString(categoryPrefix.(string))
|
|
fullPath.WriteString("/")
|
|
fullPath.WriteString(e.Slug)
|
|
pathSuffix, err := c.OptionService.GetPathSuffix(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fullPath.WriteString(pathSuffix)
|
|
categoryDTO.FullPath = fullPath.String()
|
|
return categoryDTO, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) ConvertToCategoryDTOs(ctx context.Context, categories []*entity.Category) ([]*dto.CategoryDTO, error) {
|
|
result := make([]*dto.CategoryDTO, len(categories))
|
|
isEnabled, err := c.OptionService.IsEnabledAbsolutePath(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blogBaseURL, err := c.OptionService.GetBlogBaseURL(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
categoryPrefix, err := c.OptionService.GetOrByDefaultWithErr(ctx, property.CategoriesPrefix, "categories")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pathSuffix, err := c.OptionService.GetPathSuffix(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i, category := range categories {
|
|
categoryDTO := &dto.CategoryDTO{}
|
|
categoryDTO.ID = category.ID
|
|
categoryDTO.Thumbnail = category.Thumbnail
|
|
categoryDTO.ParentID = category.ParentID
|
|
categoryDTO.Password = category.Password
|
|
categoryDTO.Name = category.Name
|
|
categoryDTO.CreateTime = category.CreateTime.UnixMilli()
|
|
categoryDTO.Description = category.Description
|
|
categoryDTO.Slug = category.Slug
|
|
categoryDTO.Priority = category.Priority
|
|
|
|
fullPath := strings.Builder{}
|
|
if isEnabled {
|
|
fullPath.WriteString(blogBaseURL)
|
|
}
|
|
fullPath.WriteString("/")
|
|
fullPath.WriteString(categoryPrefix.(string))
|
|
fullPath.WriteString("/")
|
|
fullPath.WriteString(category.Slug)
|
|
fullPath.WriteString(pathSuffix)
|
|
categoryDTO.FullPath = fullPath.String()
|
|
result[i] = categoryDTO
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) Create(ctx context.Context, categoryParam *param.Category) (*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
|
|
count, err := categoryDAL.WithContext(ctx).Where(categoryDAL.Name.Eq(categoryParam.Name)).Count()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if count > 0 {
|
|
return nil, xerr.BadParam.New("").WithMsg("Category has exist already").WithStatus(xerr.StatusBadRequest)
|
|
}
|
|
if categoryParam.Slug != "" {
|
|
slugCount, err := categoryDAL.WithContext(ctx).Where(categoryDAL.Slug.Eq(categoryParam.Slug)).Count()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if slugCount > 0 {
|
|
return nil, xerr.BadParam.New("").WithStatus(xerr.StatusBadRequest).WithMsg("category slug has exist already")
|
|
}
|
|
}
|
|
var parentCategory *entity.Category
|
|
if categoryParam.ParentID > 0 {
|
|
parentCategory, err = categoryDAL.WithContext(ctx).Where(categoryDAL.ID.Eq(categoryParam.ParentID)).Take()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
if parentCategory == nil {
|
|
return nil, xerr.BadParam.New("parentID=%d", categoryParam.ParentID).WithStatus(xerr.StatusBadRequest).WithMsg("Parent Category was not found")
|
|
}
|
|
}
|
|
if categoryParam.Password != "" {
|
|
categoryParam.Password = strings.TrimSpace(categoryParam.Password)
|
|
}
|
|
if categoryParam.Slug == "" {
|
|
categoryParam.Slug = util.Slug(categoryParam.Name)
|
|
} else {
|
|
categoryParam.Slug = util.Slug(categoryParam.Slug)
|
|
}
|
|
|
|
category := &entity.Category{
|
|
Name: categoryParam.Name,
|
|
Slug: categoryParam.Slug,
|
|
Description: categoryParam.Description,
|
|
Password: categoryParam.Password,
|
|
Thumbnail: categoryParam.Thumbnail,
|
|
ParentID: categoryParam.ParentID,
|
|
Priority: categoryParam.Priority,
|
|
Type: util.IfElse(categoryParam.Password == "", consts.CategoryTypeNormal, consts.CategoryTypeIntimate).(consts.CategoryType),
|
|
}
|
|
if parentCategory != nil && parentCategory.Type == consts.CategoryTypeIntimate {
|
|
category.Type = consts.CategoryTypeIntimate
|
|
}
|
|
err = categoryDAL.WithContext(ctx).Create(category)
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return category, nil
|
|
}
|
|
|
|
func (c *categoryServiceImpl) Update(ctx context.Context, categoryParam *param.Category) (*entity.Category, error) {
|
|
executor := newCategoryUpdateExecutor(ctx)
|
|
if err := executor.Update(ctx, categoryParam); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
category, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.Eq(categoryParam.ID)).First()
|
|
return category, WrapDBErr(err)
|
|
}
|
|
|
|
func (c categoryServiceImpl) UpdateBatch(ctx context.Context, categoryParams []*param.Category) ([]*entity.Category, error) {
|
|
executor := newCategoryUpdateExecutor(ctx)
|
|
if err := executor.UpdateBatch(ctx, categoryParams); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
categoryIDs := make([]int32, 0)
|
|
for _, category := range categoryParams {
|
|
categoryIDs = append(categoryIDs, category.ID)
|
|
}
|
|
categories, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(categoryIDs...)).Find()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return categories, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) Delete(ctx context.Context, categoryID int32) (err error) {
|
|
return newCategoryUpdateExecutor(ctx).Delete(ctx, categoryID)
|
|
}
|
|
|
|
func (c categoryServiceImpl) ListByIDs(ctx context.Context, categoryIDs []int32) ([]*entity.Category, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
categories, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(categoryIDs...)).Find()
|
|
if err != nil {
|
|
return nil, WrapDBErr(err)
|
|
}
|
|
return categories, nil
|
|
}
|
|
|
|
func (c categoryServiceImpl) IsCategoriesEncrypt(ctx context.Context, categoryIDs ...int32) (bool, error) {
|
|
if len(categoryIDs) == 0 {
|
|
return false, nil
|
|
}
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
count, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(categoryIDs...), categoryDAL.Type.Eq(consts.CategoryTypeIntimate)).Count()
|
|
return count > 0, WrapDBErr(err)
|
|
}
|
|
|
|
func (c categoryServiceImpl) Count(ctx context.Context) (int64, error) {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
count, err := categoryDAL.WithContext(ctx).Count()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return count, nil
|
|
}
|
|
|
|
func (c *categoryServiceImpl) GetChildCategory(ctx context.Context, parentCategoryID int32) ([]*entity.Category, error) {
|
|
allCategory, err := c.ListAll(ctx, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
allCategoryMap := make(map[int32]*entity.Category)
|
|
parentIDToChild := make(map[int32][]*entity.Category)
|
|
for _, category := range allCategory {
|
|
parentIDToChild[category.ParentID] = append(parentIDToChild[category.ParentID], category)
|
|
allCategoryMap[category.ID] = category
|
|
}
|
|
|
|
q := util.NewQueueCap[int32](len(allCategory))
|
|
|
|
for _, category := range parentIDToChild[parentCategoryID] {
|
|
q.Push(category.ID)
|
|
}
|
|
childs := make([]*entity.Category, 0)
|
|
for !q.IsEmpty() {
|
|
categoryID := q.Next()
|
|
childs = append(childs, allCategory[categoryID])
|
|
for _, category := range parentIDToChild[categoryID] {
|
|
q.Push(category.ID)
|
|
}
|
|
}
|
|
return childs, nil
|
|
}
|
|
|
|
type categoryUpdateExecutor struct {
|
|
AllCategory map[int32]*entity.Category
|
|
CategoryPosts map[int32][]*entity.Post
|
|
PostMap map[int32]*entity.Post
|
|
PostToCategory map[int32][]*entity.Category
|
|
}
|
|
|
|
func newCategoryUpdateExecutor(ctx context.Context) *categoryUpdateExecutor {
|
|
return &categoryUpdateExecutor{}
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) Update(ctx context.Context, categoryParam *param.Category) error {
|
|
if err := c.prepare(ctx, []*param.Category{categoryParam}); err != nil {
|
|
return err
|
|
}
|
|
|
|
parentCategory, ok := c.AllCategory[categoryParam.ParentID]
|
|
oldCategory := c.AllCategory[categoryParam.ID]
|
|
if categoryParam.ParentID > 0 && (!ok || parentCategory == nil) {
|
|
return xerr.BadParam.New("parentID=%d", categoryParam.ParentID).WithStatus(xerr.StatusBadRequest).WithMsg("Parent Category was not found")
|
|
}
|
|
|
|
category := c.convertParam(categoryParam)
|
|
if parentCategory != nil && parentCategory.Type == consts.CategoryTypeIntimate {
|
|
category.Type = consts.CategoryTypeIntimate
|
|
}
|
|
|
|
err := dal.Transaction(ctx, func(txCtx context.Context) error {
|
|
categoryDAL := dal.GetQueryByCtx(txCtx).Category
|
|
|
|
resultInfo, err := categoryDAL.WithContext(txCtx).Where(categoryDAL.ID.Eq(categoryParam.ID)).Select(field.Star).Omit(categoryDAL.CreateTime).Updates(category)
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
if resultInfo.RowsAffected != 1 {
|
|
return xerr.DB.New("").WithMsg("update failed")
|
|
}
|
|
|
|
if oldCategory.Type != category.Type {
|
|
c.AllCategory[category.ID].Type = category.Type
|
|
if err := c.refreshChildsType(txCtx, category.ID, category.Type); err != nil {
|
|
return err
|
|
}
|
|
if err := c.refreshPostStatus(txCtx); err != nil {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) UpdateBatch(ctx context.Context, categoryParams []*param.Category) error {
|
|
categories := make([]*entity.Category, 0)
|
|
for _, categoryParam := range categoryParams {
|
|
categories = append(categories, c.convertParam(categoryParam))
|
|
}
|
|
|
|
err := dal.Transaction(ctx, func(txCtx context.Context) error {
|
|
categoryDAL := dal.GetQueryByCtx(txCtx).Category
|
|
for _, category := range categories {
|
|
resultInfo, err := categoryDAL.WithContext(txCtx).Where(categoryDAL.ID.Eq(category.ID)).Select(field.Star).Omit(categoryDAL.CreateTime).Updates(category)
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
if resultInfo.RowsAffected != 1 {
|
|
return xerr.DB.New("").WithMsg("update failed")
|
|
}
|
|
}
|
|
|
|
if err := c.prepare(txCtx, categoryParams); err != nil {
|
|
return err
|
|
}
|
|
if err := c.refreshAllType(txCtx); err != nil {
|
|
return err
|
|
}
|
|
if err := c.refreshPostStatus(txCtx); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) Delete(ctx context.Context, categoryID int32) error {
|
|
if err := c.prepare(ctx, []*param.Category{{ID: categoryID}}); err != nil {
|
|
return err
|
|
}
|
|
curCategory, ok := c.AllCategory[categoryID]
|
|
if !ok || curCategory == nil {
|
|
return xerr.BadParam.New("category=%d", categoryID).WithStatus(xerr.StatusBadRequest).WithMsg("Category was not found")
|
|
}
|
|
|
|
parent, ok := c.AllCategory[curCategory.ParentID]
|
|
|
|
err := dal.Transaction(ctx, func(txCtx context.Context) error {
|
|
if ok && parent != nil {
|
|
if parent.Type == consts.CategoryTypeNormal && curCategory.Type == consts.CategoryTypeIntimate {
|
|
if err := c.refreshChildsType(txCtx, categoryID, consts.CategoryTypeNormal); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else if curCategory.Type == consts.CategoryTypeIntimate {
|
|
if err := c.refreshChildsType(txCtx, categoryID, consts.CategoryTypeNormal); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := c.removePostCategory(txCtx, categoryID); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := c.removeCategory(txCtx, categoryID); err != nil {
|
|
return err
|
|
}
|
|
if err := c.refreshPostStatus(txCtx); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
return err
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) prepare(ctx context.Context, categoryParams []*param.Category) error {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
categoryDO := categoryDAL.WithContext(ctx)
|
|
|
|
categories, err := categoryDO.Find()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
categoryMap := make(map[int32]*entity.Category)
|
|
|
|
for _, category := range categories {
|
|
categoryMap[category.ID] = category
|
|
}
|
|
c.AllCategory = categoryMap
|
|
|
|
categoryIDMap := make(map[int32]struct{})
|
|
for _, category := range categoryParams {
|
|
categoryIDMap[category.ID] = struct{}{}
|
|
childs := c.getChildCategory(category.ID)
|
|
for _, child := range childs {
|
|
categoryIDMap[child.ID] = struct{}{}
|
|
}
|
|
}
|
|
categoryIDs := util.MapKeyToArray(categoryIDMap)
|
|
|
|
postDAL := dal.GetQueryByCtx(ctx).Post
|
|
postCategoryDAL := dal.GetQueryByCtx(ctx).PostCategory
|
|
|
|
posts, err := postDAL.WithContext(ctx).Where(
|
|
postDAL.Password.Null()).Or(postDAL.Password.Zero()).Where(
|
|
postDAL.WithContext(ctx).Columns(postDAL.ID).In(
|
|
postCategoryDAL.WithContext(ctx).Select(postCategoryDAL.PostID).Where(postCategoryDAL.CategoryID.In(categoryIDs...)),
|
|
),
|
|
postDAL.Status.Neq(consts.PostStatusRecycle),
|
|
).Select(postDAL.Status, postDAL.Password, postDAL.ID).Find()
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
|
|
postMap := make(map[int32]*entity.Post)
|
|
for _, post := range posts {
|
|
postMap[post.ID] = post
|
|
}
|
|
c.PostMap = postMap
|
|
|
|
postIDs := make([]int32, 0)
|
|
for _, post := range posts {
|
|
postIDs = append(postIDs, post.ID)
|
|
}
|
|
postCategorys, err := postCategoryDAL.WithContext(ctx).Where(postCategoryDAL.PostID.In(postIDs...)).Find()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
postToCategory := make(map[int32][]*entity.Category, 0)
|
|
for _, postCategory := range postCategorys {
|
|
category := categoryMap[postCategory.CategoryID]
|
|
postToCategory[postCategory.PostID] = append(postToCategory[postCategory.PostID], category)
|
|
}
|
|
c.PostToCategory = postToCategory
|
|
return nil
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) getChildCategory(parentCategoryID int32) []*entity.Category {
|
|
parentIDToChild := make(map[int32][]*entity.Category)
|
|
for _, category := range c.AllCategory {
|
|
parentIDToChild[category.ParentID] = append(parentIDToChild[category.ParentID], category)
|
|
}
|
|
|
|
q := util.NewQueueCap[int32](len(c.AllCategory))
|
|
|
|
for _, category := range parentIDToChild[parentCategoryID] {
|
|
q.Push(category.ID)
|
|
}
|
|
childs := make([]*entity.Category, 0)
|
|
for !q.IsEmpty() {
|
|
categoryID := q.Next()
|
|
childs = append(childs, c.AllCategory[categoryID])
|
|
for _, category := range parentIDToChild[categoryID] {
|
|
q.Push(category.ID)
|
|
}
|
|
}
|
|
return childs
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) convertParam(categoryParam *param.Category) *entity.Category {
|
|
if categoryParam.Slug != "" {
|
|
categoryParam.Slug = util.Slug(categoryParam.Slug)
|
|
} else {
|
|
categoryParam.Slug = util.Slug(categoryParam.Name)
|
|
}
|
|
|
|
return &entity.Category{
|
|
ID: categoryParam.ID,
|
|
Name: categoryParam.Name,
|
|
Description: categoryParam.Description,
|
|
Thumbnail: categoryParam.Thumbnail,
|
|
ParentID: categoryParam.ParentID,
|
|
Password: strings.TrimSpace(categoryParam.Password),
|
|
Slug: categoryParam.Slug,
|
|
Priority: categoryParam.Priority,
|
|
Type: util.IfElse(categoryParam.Password == "", consts.CategoryTypeNormal, consts.CategoryTypeIntimate).(consts.CategoryType),
|
|
}
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) refreshChildsType(ctx context.Context, parentID int32, categoryType consts.CategoryType) error {
|
|
childs := c.getChildCategory(parentID)
|
|
for _, category := range childs {
|
|
category.Type = consts.CategoryTypeNormal
|
|
}
|
|
|
|
needEncryptMap := make(map[int32]struct{})
|
|
|
|
for _, child := range childs {
|
|
if categoryType == consts.CategoryTypeIntimate {
|
|
child.Type = consts.CategoryTypeIntimate
|
|
needEncryptMap[child.ID] = struct{}{}
|
|
continue
|
|
}
|
|
if child.Password != "" {
|
|
child.Type = consts.CategoryTypeIntimate
|
|
needEncryptMap[child.ID] = struct{}{}
|
|
childs := c.getChildCategory(child.ID)
|
|
for _, child := range childs {
|
|
child.Type = consts.CategoryTypeIntimate
|
|
needEncryptMap[child.ID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
needDecrypt := make([]int32, 0)
|
|
for _, child := range childs {
|
|
if _, ok := needEncryptMap[child.ID]; !ok {
|
|
needDecrypt = append(needDecrypt, child.ID)
|
|
child.Type = consts.CategoryTypeNormal
|
|
}
|
|
}
|
|
needEncrypt := util.MapKeyToArray(needEncryptMap)
|
|
if len(needEncrypt) > 0 {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(needEncrypt...)).UpdateColumnSimple(categoryDAL.Type.Value(consts.CategoryTypeIntimate))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
|
|
if len(needDecrypt) > 0 {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(needDecrypt...)).UpdateColumnSimple(categoryDAL.Type.Value(consts.CategoryTypeNormal))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) refreshAllType(ctx context.Context) error {
|
|
for _, category := range c.AllCategory {
|
|
category.Type = consts.CategoryTypeNormal
|
|
}
|
|
|
|
needEncryptMap := make(map[int32]struct{})
|
|
for _, category := range c.AllCategory {
|
|
if category.Password != "" {
|
|
category.Type = consts.CategoryTypeIntimate
|
|
needEncryptMap[category.ID] = struct{}{}
|
|
childs := c.getChildCategory(category.ID)
|
|
for _, child := range childs {
|
|
child.Type = consts.CategoryTypeIntimate
|
|
needEncryptMap[child.ID] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
needEncrypt := util.MapKeyToArray(needEncryptMap)
|
|
|
|
needDecrypt := make([]int32, 0)
|
|
for id, category := range c.AllCategory {
|
|
if _, ok := needEncryptMap[id]; !ok {
|
|
needDecrypt = append(needDecrypt, id)
|
|
category.Type = consts.CategoryTypeNormal
|
|
}
|
|
}
|
|
|
|
if len(needEncrypt) > 0 {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(needEncrypt...)).UpdateColumnSimple(categoryDAL.Type.Value(consts.CategoryTypeIntimate))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
|
|
if len(needDecrypt) > 0 {
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(needDecrypt...)).UpdateColumnSimple(categoryDAL.Type.Value(consts.CategoryTypeNormal))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) refreshPostStatus(ctx context.Context) error {
|
|
needEncryptPostID := make([]int32, 0)
|
|
needDecryptPostID := make([]int32, 0)
|
|
for id, post := range c.PostMap {
|
|
var status consts.PostStatus
|
|
for _, category := range c.PostToCategory[id] {
|
|
if category.Type == consts.CategoryTypeIntimate {
|
|
status = consts.PostStatusIntimate
|
|
break
|
|
}
|
|
}
|
|
if status == consts.PostStatusIntimate {
|
|
needEncryptPostID = append(needEncryptPostID, id)
|
|
} else if post.Status == consts.PostStatusIntimate && post.Password == "" {
|
|
needDecryptPostID = append(needDecryptPostID, id)
|
|
}
|
|
}
|
|
if len(needEncryptPostID) > 0 {
|
|
postDAL := dal.GetQueryByCtx(ctx).Post
|
|
_, err := postDAL.WithContext(ctx).Where(postDAL.ID.In(needEncryptPostID...), postDAL.Status.Neq(consts.PostStatusDraft)).UpdateColumnSimple(postDAL.Status.Value(consts.PostStatusIntimate))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
if len(needDecryptPostID) > 0 {
|
|
postDAL := dal.GetQueryByCtx(ctx).Post
|
|
_, err := postDAL.WithContext(ctx).Where(postDAL.ID.In(needDecryptPostID...), postDAL.Status.Neq(consts.PostStatusDraft)).UpdateColumnSimple(postDAL.Status.Value(consts.PostStatusPublished))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) removePostCategory(ctx context.Context, categoryID int32) error {
|
|
parent, ok := c.AllCategory[c.AllCategory[categoryID].ParentID]
|
|
postCategory := make([]*entity.PostCategory, 0)
|
|
for postID, categories := range c.PostToCategory {
|
|
if len(categories) == 1 && categories[0].ID == categoryID {
|
|
if ok && parent != nil {
|
|
postCategory = append(postCategory, &entity.PostCategory{
|
|
PostID: postID,
|
|
CategoryID: parent.ID,
|
|
})
|
|
c.PostToCategory[postID] = []*entity.Category{parent}
|
|
} else {
|
|
c.PostToCategory[postID] = nil
|
|
}
|
|
} else {
|
|
t := make([]*entity.Category, 0)
|
|
for _, category := range categories {
|
|
if category.ID == categoryID {
|
|
continue
|
|
}
|
|
t = append(t, category)
|
|
}
|
|
c.PostToCategory[postID] = t
|
|
}
|
|
}
|
|
postCategoryDAL := dal.GetQueryByCtx(ctx).PostCategory
|
|
err := postCategoryDAL.WithContext(ctx).Create(postCategory...)
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
_, err = postCategoryDAL.WithContext(ctx).Where(postCategoryDAL.CategoryID.Eq(categoryID)).Delete()
|
|
|
|
return WrapDBErr(err)
|
|
}
|
|
|
|
func (c *categoryUpdateExecutor) removeCategory(ctx context.Context, categoryID int32) error {
|
|
childs := c.getChildCategory(categoryID)
|
|
toUpdate := make([]int32, 0)
|
|
for _, child := range childs {
|
|
if child.ParentID == categoryID {
|
|
toUpdate = append(toUpdate, child.ID)
|
|
}
|
|
}
|
|
parent, ok := c.AllCategory[c.AllCategory[categoryID].ParentID]
|
|
parentID := 0
|
|
if ok && parent != nil {
|
|
parentID = int(parent.ID)
|
|
}
|
|
categoryDAL := dal.GetQueryByCtx(ctx).Category
|
|
if len(toUpdate) > 0 {
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.In(toUpdate...)).UpdateColumnSimple(categoryDAL.ParentID.Value(int32(parentID)))
|
|
if err != nil {
|
|
return WrapDBErr(err)
|
|
}
|
|
}
|
|
_, err := categoryDAL.WithContext(ctx).Where(categoryDAL.ID.Eq(categoryID)).Delete()
|
|
return WrapDBErr(err)
|
|
}
|