diff --git a/src/main/java/run/halo/app/event/category/CategoryUpdatedEvent.java b/src/main/java/run/halo/app/event/category/CategoryUpdatedEvent.java index 698bf5a3c2..e809401976 100644 --- a/src/main/java/run/halo/app/event/category/CategoryUpdatedEvent.java +++ b/src/main/java/run/halo/app/event/category/CategoryUpdatedEvent.java @@ -1,5 +1,6 @@ package run.halo.app.event.category; +import java.util.Set; import org.springframework.context.ApplicationEvent; import org.springframework.lang.Nullable; import run.halo.app.model.entity.Category; @@ -15,13 +16,15 @@ public class CategoryUpdatedEvent extends ApplicationEvent { private final Category beforeUpdated; private final Category category; private final boolean beforeIsPrivate; + private final Set postIds; public CategoryUpdatedEvent(Object source, Category category, - Category beforeUpdated, boolean beforeIsPrivate) { + Category beforeUpdated, boolean beforeIsPrivate, Set postIds) { super(source); this.category = category; this.beforeUpdated = beforeUpdated; this.beforeIsPrivate = beforeIsPrivate; + this.postIds = postIds; } @Nullable @@ -37,4 +40,8 @@ public Category getBeforeUpdated() { public boolean isBeforeIsPrivate() { return beforeIsPrivate; } + + public Set getPostIds() { + return postIds; + } } diff --git a/src/main/java/run/halo/app/listener/post/PostRefreshStatusListener.java b/src/main/java/run/halo/app/listener/post/PostRefreshStatusListener.java index b395c58b76..15e553123b 100644 --- a/src/main/java/run/halo/app/listener/post/PostRefreshStatusListener.java +++ b/src/main/java/run/halo/app/listener/post/PostRefreshStatusListener.java @@ -1,24 +1,19 @@ package run.halo.app.listener.post; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.springframework.context.event.EventListener; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import run.halo.app.event.category.CategoryUpdatedEvent; import run.halo.app.event.post.PostUpdatedEvent; import run.halo.app.model.entity.Category; import run.halo.app.model.entity.Post; -import run.halo.app.model.entity.PostCategory; import run.halo.app.model.enums.PostStatus; import run.halo.app.service.CategoryService; import run.halo.app.service.PostCategoryService; import run.halo.app.service.PostService; -import run.halo.app.utils.ServiceUtils; /** * Post status management. @@ -53,45 +48,55 @@ public void categoryUpdatedListener(CategoryUpdatedEvent event) { Category beforeUpdated = event.getBeforeUpdated(); boolean beforeIsPrivate = event.isBeforeIsPrivate(); RecordState recordState = determineRecordState(beforeUpdated, category); + + List posts = postService.listAllByIds(event.getPostIds()); + + // handle delete action if (RecordState.DELETED.equals(recordState) || category == null) { + if (beforeUpdated == null || !beforeIsPrivate) { + return; + } + // Cancel the encryption status of the posts + changeStatusToPublishIfNecessary(posts, beforeUpdated.getId()); return; } // now boolean isPrivate = categoryService.isPrivate(category.getId()); - List posts = findPostsByCategoryIdRecursively(category.getId()); if (isPrivate) { + List postsToUpdate = new ArrayList<>(); posts.forEach(post -> { if (post.getStatus() == PostStatus.PUBLISHED) { post.setStatus(PostStatus.INTIMATE); + postsToUpdate.add(post); } }); - } else { - if (RecordState.UPDATED.equals(recordState)) { - Set encryptedCategories = - pickUpEncryptedFromUpdatedRecord(category.getId()); - for (Post post : posts) { - boolean belongsToEncryptedCategory = - postBelongsToEncryptedCategory(post.getId(), encryptedCategories); - if (!belongsToEncryptedCategory && StringUtils.isBlank(post.getPassword()) - && beforeIsPrivate - && post.getStatus() == PostStatus.INTIMATE) { - post.setStatus(PostStatus.PUBLISHED); - } - } + postService.updateInBatch(postsToUpdate); + } else if (beforeIsPrivate && RecordState.UPDATED.equals(recordState)) { + // Cancel the encryption status of the posts + changeStatusToPublishIfNecessary(posts, category.getId()); + } + } + + private void changeStatusToPublishIfNecessary(List posts, Integer categoryId) { + List postsToUpdate = new ArrayList<>(); + for (Post post : posts) { + boolean belongsToEncryptedCategory = postBelongsToEncryptedCategory(post.getId()); + if (!belongsToEncryptedCategory && StringUtils.isBlank(post.getPassword()) + && post.getStatus() == PostStatus.INTIMATE) { + post.setStatus(PostStatus.PUBLISHED); + postsToUpdate.add(post); } } - postService.updateInBatch(posts); + postService.updateInBatch(postsToUpdate); } - private boolean postBelongsToEncryptedCategory(Integer postId, - Set encryptedCategories) { - Set categoryIds = - postCategoryService.listCategoryIdsByPostId(postId); + private boolean postBelongsToEncryptedCategory(Integer postId) { + Set categoryIds = postCategoryService.listCategoryIdsByPostId(postId); boolean encrypted = false; for (Integer categoryId : categoryIds) { - if (encryptedCategories.contains(categoryId)) { + if (categoryService.isPrivate(categoryId)) { encrypted = true; break; } @@ -99,40 +104,6 @@ private boolean postBelongsToEncryptedCategory(Integer postId, return encrypted; } - private Set pickUpEncryptedFromUpdatedRecord(Integer categoryId) { - Set privateCategories = new HashSet<>(); - - List categories = categoryService.listAllByParentId(categoryId); - Map categoryMap = - ServiceUtils.convertToMap(categories, Category::getId); - categories.forEach(category -> { - boolean privateBy = isPrivateBy(category.getId(), categoryMap); - if (privateBy) { - privateCategories.add(category.getId()); - } - }); - return privateCategories; - } - - private boolean isPrivateBy(Integer categoryId, Map categoryMap) { - return findFirstEncryptedCategoryBy(categoryMap, categoryId) != null; - } - - private Category findFirstEncryptedCategoryBy(Map idToCategoryMap, - Integer categoryId) { - Category category = idToCategoryMap.get(categoryId); - - if (categoryId == 0 || category == null) { - return null; - } - - if (StringUtils.isNotBlank(category.getPassword())) { - return category; - } - - return findFirstEncryptedCategoryBy(idToCategoryMap, category.getParentId()); - } - private RecordState determineRecordState(Category before, Category updated) { if (before == null) { if (updated != null) { @@ -153,27 +124,16 @@ private RecordState determineRecordState(Category before, Category updated) { } } - /** - * effective state for database record. - */ enum RecordState { + /** + * effective state for database record. + */ CREATED, UPDATED, DELETED, UNCHANGED } - @NonNull - private List findPostsByCategoryIdRecursively(Integer categoryId) { - Set categoryIds = - ServiceUtils.fetchProperty(categoryService.listAllByParentId(categoryId), - Category::getId); - List postCategories = - postCategoryService.listByCategoryIdList(new ArrayList<>(categoryIds)); - Set postIds = ServiceUtils.fetchProperty(postCategories, PostCategory::getPostId); - return postService.listAllByIds(postIds); - } - /** * If the post belongs to any encryption category, set the status to INTIMATE. * diff --git a/src/main/java/run/halo/app/service/CategoryService.java b/src/main/java/run/halo/app/service/CategoryService.java index 95876421cd..33646c5f64 100755 --- a/src/main/java/run/halo/app/service/CategoryService.java +++ b/src/main/java/run/halo/app/service/CategoryService.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.Optional; +import java.util.Set; import org.springframework.data.domain.Sort; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; @@ -133,4 +134,13 @@ public interface CategoryService extends CrudService { * @return a tree of category. */ List listToTree(List categories); + + /** + * Recursively query the associated post ids according to the category id. + * + * @param categoryId category id + * @return a collection of post ids + */ + @NonNull + Set listPostIdsByCategoryIdRecursively(@NonNull Integer categoryId); } diff --git a/src/main/java/run/halo/app/service/impl/CategoryServiceImpl.java b/src/main/java/run/halo/app/service/impl/CategoryServiceImpl.java index da2cd1c0db..6e575c497b 100644 --- a/src/main/java/run/halo/app/service/impl/CategoryServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/CategoryServiceImpl.java @@ -3,6 +3,7 @@ import static run.halo.app.model.support.HaloConst.URL_SEPARATOR; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; @@ -28,6 +29,7 @@ import run.halo.app.exception.NotFoundException; import run.halo.app.model.dto.CategoryDTO; import run.halo.app.model.entity.Category; +import run.halo.app.model.entity.PostCategory; import run.halo.app.model.vo.CategoryVO; import run.halo.app.repository.CategoryRepository; import run.halo.app.service.CategoryService; @@ -111,8 +113,10 @@ public Category update(Category category) { boolean beforeIsPrivate = isPrivate(category.getId()); Category updated = super.update(category); + + Set postIds = listPostIdsByCategoryIdRecursively(category.getId()); applicationContext.publishEvent( - new CategoryUpdatedEvent(this, category, beforeUpdated, beforeIsPrivate)); + new CategoryUpdatedEvent(this, category, beforeUpdated, beforeIsPrivate, postIds)); return updated; } @@ -183,8 +187,10 @@ public Category getByName(String name) { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void removeCategoryAndPostCategoryBy(Integer categoryId) { + final boolean beforeIsPrivate = isPrivate(categoryId); + final Set postIds = listPostIdsByCategoryIdRecursively(categoryId); List categories = listByParentId(categoryId); if (null != categories && categories.size() > 0) { categories.forEach(category -> { @@ -198,7 +204,8 @@ public void removeCategoryAndPostCategoryBy(Integer categoryId) { // Remove post categories postCategoryService.removeByCategoryId(categoryId); - applicationContext.publishEvent(new CategoryUpdatedEvent(this, null, category, false)); + applicationContext.publishEvent( + new CategoryUpdatedEvent(this, null, category, beforeIsPrivate, postIds)); } @Override @@ -371,12 +378,26 @@ public List updateInBatch(Collection categories) { Category categoryParam = idCategoryParamMap.get(categoryToUpdate.getId()); BeanUtils.updateProperties(categoryParam, categoryToUpdate); Category categoryUpdated = update(categoryToUpdate); + + Set postIds = listPostIdsByCategoryIdRecursively(categoryUpdated.getId()); applicationContext.publishEvent(new CategoryUpdatedEvent(this, - categoryUpdated, categoryBefore, beforeIsPrivate)); + categoryUpdated, categoryBefore, beforeIsPrivate, postIds)); return categoryUpdated; }) .collect(Collectors.toList()); } + @NonNull + @Override + public Set listPostIdsByCategoryIdRecursively(@NonNull Integer categoryId) { + Set categoryIds = ServiceUtils.fetchProperty(listAllByParentId(categoryId), + Category::getId); + if (CollectionUtils.isEmpty(categoryIds)) { + return Collections.emptySet(); + } + List postCategories = + postCategoryService.listByCategoryIdList(new ArrayList<>(categoryIds)); + return ServiceUtils.fetchProperty(postCategories, PostCategory::getPostId); + } }