diff --git a/src/main/java/run/halo/app/controller/content/api/PostController.java b/src/main/java/run/halo/app/controller/content/api/PostController.java index e3f647a5f..b615f64ea 100644 --- a/src/main/java/run/halo/app/controller/content/api/PostController.java +++ b/src/main/java/run/halo/app/controller/content/api/PostController.java @@ -13,6 +13,7 @@ import run.halo.app.model.dto.BaseCommentDTO; import run.halo.app.model.dto.post.BasePostDetailDTO; import run.halo.app.model.dto.post.BasePostSimpleDTO; import run.halo.app.model.entity.Post; +import run.halo.app.model.entity.PostComment; import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.PostStatus; import run.halo.app.model.params.PostCommentParam; @@ -88,9 +89,12 @@ public class PostController { @GetMapping("{postId:\\d+}/comments/{commentParentId:\\d+}/children") public List listChildrenBy(@PathVariable("postId") Integer postId, - @PathVariable("commentParentId") Integer commentParentId, + @PathVariable("commentParentId") Long commentParentId, @SortDefault(sort = "createTime", direction = DESC) Sort sort) { - return postCommentService.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort); + // Find all children comments + List postComments = postCommentService.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort); + // Convert to base comment dto + return postCommentService.convertTo(postComments); } diff --git a/src/main/java/run/halo/app/repository/base/BaseCommentRepository.java b/src/main/java/run/halo/app/repository/base/BaseCommentRepository.java index 6385adc7b..524508f01 100644 --- a/src/main/java/run/halo/app/repository/base/BaseCommentRepository.java +++ b/src/main/java/run/halo/app/repository/base/BaseCommentRepository.java @@ -94,6 +94,27 @@ public interface BaseCommentRepository extends Base @NonNull Page findAllByPostIdAndStatus(Integer postId, CommentStatus status, Pageable pageable); + /** + * Finds comments by post id, comment status and parent id. + * + * @param postId post id must not be null + * @param status comment status must not be null + * @param parentId comment parent id must not be null + * @return a list of comment + */ + @NonNull + List findAllByPostIdAndStatusAndParentId(Integer postId, CommentStatus status, Long parentId); + + /** + * Finds all comments by status and parent id collection. + * + * @param status comment status must not be null + * @param parentIds parent id collection must not be null + * @return a list of comment + */ + @NonNull + List findAllByStatusAndParentIdIn(@NonNull CommentStatus status, @NonNull Iterable parentIds); + /** * Finds comments by post id, comment status and parent id. * @@ -106,6 +127,7 @@ public interface BaseCommentRepository extends Base @NonNull Page findAllByPostIdAndStatusAndParentId(Integer postId, CommentStatus status, Long parentId, Pageable pageable); + @Query("select new run.halo.app.model.projection.CommentChildrenCountProjection(count(comment.id), comment.parentId) " + "from BaseComment comment " + "where comment.parentId in ?1 " + diff --git a/src/main/java/run/halo/app/service/base/BaseCommentService.java b/src/main/java/run/halo/app/service/base/BaseCommentService.java index d31a1843d..87c2a0043 100644 --- a/src/main/java/run/halo/app/service/base/BaseCommentService.java +++ b/src/main/java/run/halo/app/service/base/BaseCommentService.java @@ -213,5 +213,5 @@ public interface BaseCommentService extends CrudSer * @return a list of children comment */ @NonNull - List listChildrenBy(@NonNull Integer targetId, @NonNull Integer commentParentId, @NonNull CommentStatus status, @NonNull Sort sort); + List listChildrenBy(@NonNull Integer targetId, @NonNull Long commentParentId, @NonNull CommentStatus status, @NonNull Sort sort); } diff --git a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java index 1b28d73ba..bbcac107b 100644 --- a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java @@ -445,12 +445,55 @@ public abstract class BaseCommentServiceImpl extend } @Override - public List listChildrenBy(Integer targetId, Integer commentParentId, CommentStatus status, Sort sort) { + public List listChildrenBy(Integer targetId, Long commentParentId, CommentStatus status, Sort sort) { Assert.notNull(targetId, "Target id must not be null"); Assert.notNull(commentParentId, "Comment parent id must not be null"); Assert.notNull(sort, "Sort info must not be null"); - return null; + // Get comments recursively + + // Get direct children + List directChildren = baseCommentRepository.findAllByPostIdAndStatusAndParentId(targetId, status, commentParentId); + + // Create result container + Set children = new HashSet<>(); + + // Get children comments + getChildrenRecursively(directChildren, status, children); + + // Sort children + List childrenList = new ArrayList<>(children); + childrenList.sort(Comparator.comparing(BaseComment::getId)); + + return childrenList; + } + + /** + * Get children comments recursively. + * + * @param topComments top comment list + * @param status comment status must not be null + * @param children children result must not be null + */ + private void getChildrenRecursively(@Nullable List topComments, @NonNull CommentStatus status, @NonNull Set children) { + Assert.notNull(status, "Comment status must not be null"); + Assert.notNull(children, "Children comment set must not be null"); + + if (CollectionUtils.isEmpty(topComments)) { + return; + } + + // Convert comment id set + Set commentIds = ServiceUtils.fetchProperty(topComments, COMMENT::getId); + + // Get direct children + List directChildren = baseCommentRepository.findAllByStatusAndParentIdIn(status, commentIds); + + // Recursively invoke + getChildrenRecursively(directChildren, status, children); + + // Add direct children to children result + children.addAll(topComments); } /** diff --git a/src/main/java/run/halo/app/utils/ServiceUtils.java b/src/main/java/run/halo/app/utils/ServiceUtils.java index 7cf80a0f6..a03bec409 100644 --- a/src/main/java/run/halo/app/utils/ServiceUtils.java +++ b/src/main/java/run/halo/app/utils/ServiceUtils.java @@ -31,6 +31,7 @@ public class ServiceUtils { * @param data type * @return a set of id */ + @NonNull public static Set fetchProperty(final Collection datas, Function mappingFunction) { return CollectionUtils.isEmpty(datas) ? Collections.emptySet() : @@ -47,6 +48,7 @@ public class ServiceUtils { * @param data type * @return a map which key is in ids and value containing in list */ + @NonNull public static Map> convertToListMap(Collection ids, Collection list, Function mappingFunction) { Assert.notNull(mappingFunction, "mapping function must not be null"); @@ -72,6 +74,7 @@ public class ServiceUtils { * @param data type * @return a map which key from list data and value is data */ + @NonNull public static Map convertToMap(Collection list, Function mappingFunction) { Assert.notNull(mappingFunction, "mapping function must not be null"); @@ -97,6 +100,7 @@ public class ServiceUtils { * @param value type * @return a map which key from list data and value is data */ + @NonNull public static Map convertToMap(Collection list, Function keyFunction, Function valueFunction) { Assert.notNull(keyFunction, "mapping function must not be null");