feat: Add comment assembler for theme render (#1729)

* feat: Add comment assembler for theme render

* fix: code style

* fix: page converter

* refactor: clear sensitive field value
pull/1730/head
guqing 2022-03-09 19:19:49 +08:00 committed by GitHub
parent 7d4075eb3a
commit d0ca7bd9d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 476 additions and 112 deletions

View File

@ -34,7 +34,7 @@ import run.halo.app.model.vo.CommentWithHasChildrenVO;
import run.halo.app.service.JournalCommentService;
import run.halo.app.service.JournalService;
import run.halo.app.service.OptionService;
import run.halo.app.service.assembler.comment.JournalCommentAssembler;
import run.halo.app.service.assembler.comment.JournalCommentRenderAssembler;
/**
* Content journal controller.
@ -49,18 +49,18 @@ public class JournalController {
private final JournalService journalService;
private final JournalCommentAssembler journalCommentAssembler;
private final JournalCommentRenderAssembler journalCommentRenderAssembler;
private final JournalCommentService journalCommentService;
private final OptionService optionService;
public JournalController(JournalService journalService,
JournalCommentAssembler journalCommentAssembler,
JournalCommentRenderAssembler journalCommentRenderAssembler,
JournalCommentService journalCommentService,
OptionService optionService) {
this.journalService = journalService;
this.journalCommentAssembler = journalCommentAssembler;
this.journalCommentRenderAssembler = journalCommentRenderAssembler;
this.journalCommentService = journalCommentService;
this.optionService = optionService;
}
@ -85,8 +85,11 @@ public class JournalController {
@PathVariable("journalId") Integer journalId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<CommentWithHasChildrenVO> comments =
journalCommentService.pageTopCommentsBy(journalId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.forEach(journalCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{journalId:\\d+}/comments/{commentParentId:\\d+}/children")
@ -97,7 +100,7 @@ public class JournalController {
List<JournalComment> postComments = journalCommentService
.listChildrenBy(journalId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return journalCommentAssembler.convertTo(postComments);
return journalCommentRenderAssembler.convertTo(postComments);
}
@GetMapping("{journalId:\\d+}/comments/tree_view")
@ -105,8 +108,10 @@ public class JournalController {
public Page<BaseCommentVO> listCommentsTree(@PathVariable("journalId") Integer journalId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return journalCommentService
Page<BaseCommentVO> comments = journalCommentService
.pageVosBy(journalId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(journalCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{journalId:\\d+}/comments/list_view")
@ -114,8 +119,11 @@ public class JournalController {
public Page<BaseCommentWithParentVO> listComments(@PathVariable("journalId") Integer journalId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return journalCommentService.pageWithParentVoBy(journalId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<BaseCommentWithParentVO> comments =
journalCommentService.pageWithParentVoBy(journalId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(journalCommentRenderAssembler::clearSensitiveField);
return comments;
}
@PostMapping("comments")
@ -126,7 +134,7 @@ public class JournalController {
// Escape content
journalCommentParam.setContent(HtmlUtils
.htmlEscape(journalCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return journalCommentAssembler.convertTo(
return journalCommentRenderAssembler.convertTo(
journalCommentService.createBy(journalCommentParam));
}

View File

@ -42,7 +42,7 @@ import run.halo.app.service.OptionService;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.PostService;
import run.halo.app.service.assembler.PostRenderAssembler;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
import run.halo.app.service.assembler.comment.PostCommentRenderAssembler;
/**
* Content post controller.
@ -58,7 +58,7 @@ public class PostController {
private final PostService postService;
private final PostCommentAssembler postCommentAssembler;
private final PostCommentRenderAssembler postCommentRenderAssembler;
private final PostCommentService postCommentService;
@ -69,12 +69,12 @@ public class PostController {
private final PostAuthentication postAuthentication;
public PostController(PostService postService,
PostCommentAssembler postCommentAssembler,
PostCommentRenderAssembler postCommentRenderAssembler,
PostCommentService postCommentService,
OptionService optionService, PostRenderAssembler postRenderAssembler,
PostAuthentication postAuthentication) {
this.postService = postService;
this.postCommentAssembler = postCommentAssembler;
this.postCommentRenderAssembler = postCommentRenderAssembler;
this.postCommentService = postCommentService;
this.optionService = optionService;
this.postRenderAssembler = postRenderAssembler;
@ -194,8 +194,11 @@ public class PostController {
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
checkAuthenticate(postId);
return postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<CommentWithHasChildrenVO> comments =
postCommentService.pageTopCommentsBy(postId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{postId:\\d+}/comments/{commentParentId:\\d+}/children")
@ -208,7 +211,7 @@ public class PostController {
.listChildrenBy(postId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return postCommentAssembler.convertTo(postComments);
return postCommentRenderAssembler.convertTo(postComments);
}
@GetMapping("{postId:\\d+}/comments/tree_view")
@ -217,8 +220,10 @@ public class PostController {
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
checkAuthenticate(postId);
return postCommentService
Page<BaseCommentVO> comments = postCommentService
.pageVosBy(postId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{postId:\\d+}/comments/list_view")
@ -227,8 +232,11 @@ public class PostController {
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
checkAuthenticate(postId);
return postCommentService.pageWithParentVoBy(postId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<BaseCommentWithParentVO> comments =
postCommentService.pageWithParentVoBy(postId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(postCommentRenderAssembler::clearSensitiveField);
return comments;
}
@PostMapping("comments")
@ -241,7 +249,7 @@ public class PostController {
// Escape content
postCommentParam.setContent(HtmlUtils
.htmlEscape(postCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return postCommentAssembler.convertTo(postCommentService.createBy(postCommentParam));
return postCommentRenderAssembler.convertTo(postCommentService.createBy(postCommentParam));
}
@PostMapping("{postId:\\d+}/likes")

View File

@ -35,7 +35,7 @@ import run.halo.app.service.OptionService;
import run.halo.app.service.SheetCommentService;
import run.halo.app.service.SheetService;
import run.halo.app.service.assembler.SheetRenderAssembler;
import run.halo.app.service.assembler.comment.SheetCommentAssembler;
import run.halo.app.service.assembler.comment.SheetCommentRenderAssembler;
/**
* Content sheet controller.
@ -48,7 +48,7 @@ import run.halo.app.service.assembler.comment.SheetCommentAssembler;
@RequestMapping("/api/content/sheets")
public class SheetController {
private final SheetCommentAssembler sheetCommentAssembler;
private final SheetCommentRenderAssembler sheetCommentRenderAssembler;
private final SheetService sheetService;
@ -59,12 +59,12 @@ public class SheetController {
private final OptionService optionService;
public SheetController(
SheetCommentAssembler sheetCommentAssembler,
SheetCommentRenderAssembler sheetCommentRenderAssembler,
SheetService sheetService,
SheetRenderAssembler sheetRenderAssembler,
SheetCommentService sheetCommentService,
OptionService optionService) {
this.sheetCommentAssembler = sheetCommentAssembler;
this.sheetCommentRenderAssembler = sheetCommentRenderAssembler;
this.sheetService = sheetService;
this.sheetRenderAssembler = sheetRenderAssembler;
this.sheetCommentService = sheetCommentService;
@ -134,8 +134,11 @@ public class SheetController {
public Page<CommentWithHasChildrenVO> listTopComments(@PathVariable("sheetId") Integer sheetId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<CommentWithHasChildrenVO> comments =
sheetCommentService.pageTopCommentsBy(sheetId, CommentStatus.PUBLISHED,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.forEach(sheetCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{sheetId:\\d+}/comments/{commentParentId:\\d+}/children")
@ -146,7 +149,7 @@ public class SheetController {
List<SheetComment> sheetComments = sheetCommentService
.listChildrenBy(sheetId, commentParentId, CommentStatus.PUBLISHED, sort);
// Convert to base comment dto
return sheetCommentAssembler.convertTo(sheetComments);
return sheetCommentRenderAssembler.convertTo(sheetComments);
}
@ -155,8 +158,10 @@ public class SheetController {
public Page<BaseCommentVO> listCommentsTree(@PathVariable("sheetId") Integer sheetId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return sheetCommentService
Page<BaseCommentVO> comments = sheetCommentService
.pageVosBy(sheetId, PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(sheetCommentRenderAssembler::clearSensitiveField);
return comments;
}
@GetMapping("{sheetId:\\d+}/comments/list_view")
@ -164,8 +169,11 @@ public class SheetController {
public Page<BaseCommentWithParentVO> listComments(@PathVariable("sheetId") Integer sheetId,
@RequestParam(name = "page", required = false, defaultValue = "0") int page,
@SortDefault(sort = "createTime", direction = DESC) Sort sort) {
return sheetCommentService.pageWithParentVoBy(sheetId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
Page<BaseCommentWithParentVO> comments =
sheetCommentService.pageWithParentVoBy(sheetId,
PageRequest.of(page, optionService.getCommentPageSize(), sort));
comments.getContent().forEach(sheetCommentRenderAssembler::clearSensitiveField);
return comments;
}
@PostMapping("comments")
@ -176,6 +184,7 @@ public class SheetController {
// Escape content
sheetCommentParam.setContent(HtmlUtils
.htmlEscape(sheetCommentParam.getContent(), StandardCharsets.UTF_8.displayName()));
return sheetCommentAssembler.convertTo(sheetCommentService.createBy(sheetCommentParam));
return sheetCommentRenderAssembler.convertTo(
sheetCommentService.createBy(sheetCommentParam));
}
}

View File

@ -15,12 +15,13 @@ import run.halo.app.model.entity.PostComment;
import run.halo.app.model.enums.CommentStatus;
import run.halo.app.model.support.HaloConst;
import run.halo.app.service.PostCommentService;
import run.halo.app.service.assembler.comment.PostCommentAssembler;
import run.halo.app.service.assembler.comment.PostCommentRenderAssembler;
/**
* Freemarker custom tag of comment.
*
* @author ryanwang
* @author guqing
* @date 2019-03-22
*/
@Component
@ -28,12 +29,12 @@ public class CommentTagDirective implements TemplateDirectiveModel {
private final PostCommentService postCommentService;
private final PostCommentAssembler postCommentAssembler;
private final PostCommentRenderAssembler postCommentRenderAssembler;
public CommentTagDirective(Configuration configuration, PostCommentService postCommentService,
PostCommentAssembler postCommentAssembler) {
PostCommentRenderAssembler postCommentRenderAssembler) {
this.postCommentService = postCommentService;
this.postCommentAssembler = postCommentAssembler;
this.postCommentRenderAssembler = postCommentRenderAssembler;
configuration.setSharedVariable("commentTag", this);
}
@ -52,7 +53,7 @@ public class CommentTagDirective implements TemplateDirectiveModel {
postCommentService.pageLatest(top, CommentStatus.PUBLISHED);
env.setVariable("comments",
builder.build()
.wrap(postCommentAssembler.convertToWithPostVo(postComments)));
.wrap(postCommentRenderAssembler.convertToWithPostVo(postComments)));
break;
case "count":
env.setVariable("count", builder.build().wrap(postCommentService.count()));

View File

@ -1,13 +1,18 @@
package run.halo.app.service.assembler.comment;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Queue;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@ -15,7 +20,9 @@ import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.BaseComment;
import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.support.CommentPage;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.model.vo.BaseCommentWithParentVO;
import run.halo.app.service.OptionService;
/**
@ -24,6 +31,7 @@ import run.halo.app.service.OptionService;
* @author guqing
* @date 2022-03-08
*/
@Slf4j
public abstract class BaseCommentAssembler<COMMENT extends BaseComment> {
private final OptionService optionService;
@ -102,6 +110,47 @@ public abstract class BaseCommentAssembler<COMMENT extends BaseComment> {
return topVirtualComment.getChildren();
}
/**
* Lists comment vos by list of COMMENT.
*
* @param comments comments must not be null
* @param pageable page info must not be null
* @return a page of comment vo
*/
@NonNull
public Page<BaseCommentVO> pageVosBy(@NonNull List<COMMENT> comments,
@NonNull Pageable pageable) {
Assert.notNull(comments, "Comments must not be null");
Assert.notNull(pageable, "Page info must not be null");
Comparator<BaseCommentVO> commentComparator =
buildCommentComparator(pageable.getSortOr(Sort.by(Sort.Direction.DESC, "createTime")));
// Convert to vo
List<BaseCommentVO> topComments = convertToVo(comments, commentComparator);
List<BaseCommentVO> pageContent;
// Calc the shear index
int startIndex = pageable.getPageNumber() * pageable.getPageSize();
if (startIndex >= topComments.size() || startIndex < 0) {
pageContent = Collections.emptyList();
} else {
int endIndex = startIndex + pageable.getPageSize();
if (endIndex > topComments.size()) {
endIndex = topComments.size();
}
log.debug("Top comments size: [{}]", topComments.size());
log.debug("Start index: [{}]", startIndex);
log.debug("End index: [{}]", endIndex);
pageContent = topComments.subList(startIndex, endIndex);
}
return new CommentPage<>(pageContent, pageable, topComments.size(), comments.size());
}
/**
* Concretes comment tree.
*
@ -165,4 +214,95 @@ public abstract class BaseCommentAssembler<COMMENT extends BaseComment> {
return gravatarSource + gravatarMd5 + "?s=256&d=" + gravatarDefault;
}
/**
* Builds a comment comparator.
*
* @param sort sort info
* @return comment comparator
*/
protected Comparator<BaseCommentVO> buildCommentComparator(Sort sort) {
return (currentComment, toCompareComment) -> {
Assert.notNull(currentComment, "Current comment must not be null");
Assert.notNull(toCompareComment, "Comment to compare must not be null");
// Get sort order
Sort.Order order = sort.filter(anOrder -> "id".equals(anOrder.getProperty()))
.get()
.findFirst()
.orElseGet(() -> Sort.Order.desc("id"));
// Init sign
int sign = order.getDirection().isAscending() ? 1 : -1;
// Compare id property
return sign * currentComment.getId().compareTo(toCompareComment.getId());
};
}
/**
* clear sensitive field value for theme render.
*
* @param comment comment
*/
public void clearSensitiveField(@Nullable COMMENT comment) {
if (comment == null) {
return;
}
comment.setIpAddress(null);
comment.setEmail(null);
}
/**
* clear sensitive field value for theme render.
*
* @param comment comment tree
*/
public void clearSensitiveField(@Nullable BaseCommentDTO comment) {
if (comment == null) {
return;
}
comment.setIpAddress(null);
comment.setEmail(null);
}
/**
* clear sensitive field value for theme render.
*
* @param commentTree comment tree
*/
public void clearSensitiveField(@Nullable BaseCommentVO commentTree) {
if (commentTree == null) {
return;
}
Queue<BaseCommentVO> queue = new ArrayDeque<>();
queue.add(commentTree);
while (!queue.isEmpty()) {
BaseCommentVO comment = queue.poll();
comment.setIpAddress(null);
comment.setEmail(null);
if (!CollectionUtils.isEmpty(comment.getChildren())) {
queue.addAll(comment.getChildren());
}
}
}
/**
* clear sensitive field value for theme render.
*
* @param comment comment
*/
public void clearSensitiveField(@Nullable BaseCommentWithParentVO comment) {
if (comment == null) {
return;
}
BaseCommentWithParentVO parent = comment.getParent();
if (parent != null) {
parent.setIpAddress(null);
parent.setEmail(null);
}
comment.setIpAddress(null);
comment.setEmail(null);
}
}

View File

@ -0,0 +1,85 @@
package run.halo.app.service.assembler.comment;
import java.util.Comparator;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.JournalComment;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.model.vo.JournalCommentWithJournalVO;
import run.halo.app.repository.JournalRepository;
import run.halo.app.service.OptionService;
/**
* Journal comment assembler for theme render.
*
* @author guqing
* @date 2022-03-09
*/
@Component
public class JournalCommentRenderAssembler extends JournalCommentAssembler {
public JournalCommentRenderAssembler(OptionService optionService,
JournalRepository journalRepository) {
super(optionService, journalRepository);
}
@NonNull
@Override
public BaseCommentDTO convertTo(@NonNull JournalComment comment) {
clearSensitiveField(comment);
return super.convertTo(comment);
}
@NonNull
@Override
public List<BaseCommentDTO> convertTo(List<JournalComment> journalComments) {
journalComments.forEach(this::clearSensitiveField);
return super.convertTo(journalComments);
}
@NonNull
@Override
public Page<BaseCommentDTO> convertTo(Page<JournalComment> journalComments) {
journalComments.getContent().forEach(this::clearSensitiveField);
return super.convertTo(journalComments);
}
@Override
public List<BaseCommentVO> convertToVo(List<JournalComment> journalComments,
Comparator<BaseCommentVO> comparator) {
if (!CollectionUtils.isEmpty(journalComments)) {
journalComments.forEach(this::clearSensitiveField);
}
return super.convertToVo(journalComments, comparator);
}
@NonNull
@Override
public List<JournalCommentWithJournalVO> convertToWithJournalVo(
List<JournalComment> journalComments) {
if (!CollectionUtils.isEmpty(journalComments)) {
journalComments.forEach(this::clearSensitiveField);
}
return super.convertToWithJournalVo(journalComments);
}
@NonNull
@Override
public Page<JournalCommentWithJournalVO> convertToWithJournalVo(
@NonNull Page<JournalComment> journalCommentPage) {
journalCommentPage.getContent().forEach(this::clearSensitiveField);
return super.convertToWithJournalVo(journalCommentPage);
}
@NonNull
@Override
public Page<BaseCommentVO> pageVosBy(@NonNull List<JournalComment> journalComments,
@NonNull Pageable pageable) {
journalComments.forEach(this::clearSensitiveField);
return super.pageVosBy(journalComments, pageable);
}
}

View File

@ -0,0 +1,91 @@
package run.halo.app.service.assembler.comment;
import java.util.Comparator;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.PostComment;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.model.vo.PostCommentWithPostVO;
import run.halo.app.repository.PostRepository;
import run.halo.app.service.OptionService;
/**
* Post comment assembler for theme render.
*
* @author guqing
* @date 2022-03-09
*/
@Component
public class PostCommentRenderAssembler extends PostCommentAssembler {
public PostCommentRenderAssembler(OptionService optionService,
PostRepository postRepository) {
super(optionService, postRepository);
}
@NonNull
@Override
public BaseCommentDTO convertTo(@NonNull PostComment comment) {
clearSensitiveField(comment);
return super.convertTo(comment);
}
@NonNull
@Override
public List<BaseCommentDTO> convertTo(@NonNull List<PostComment> postComments) {
postComments.forEach(this::clearSensitiveField);
return super.convertTo(postComments);
}
@NonNull
@Override
public Page<BaseCommentDTO> convertTo(@NonNull Page<PostComment> postComments) {
postComments.forEach(this::clearSensitiveField);
return super.convertTo(postComments);
}
@Override
public List<BaseCommentVO> convertToVo(List<PostComment> postComments,
Comparator<BaseCommentVO> comparator) {
if (!CollectionUtils.isEmpty(postComments)) {
postComments.forEach(this::clearSensitiveField);
}
return super.convertToVo(postComments, comparator);
}
@NonNull
@Override
public Page<PostCommentWithPostVO> convertToWithPostVo(@NonNull Page<PostComment> commentPage) {
commentPage.getContent().forEach(this::clearSensitiveField);
return super.convertToWithPostVo(commentPage);
}
@NonNull
@Override
public PostCommentWithPostVO convertToWithPostVo(@NonNull PostComment comment) {
this.clearSensitiveField(comment);
return super.convertToWithPostVo(comment);
}
@NonNull
@Override
public List<PostCommentWithPostVO> convertToWithPostVo(List<PostComment> postComments) {
if (!CollectionUtils.isEmpty(postComments)) {
postComments.forEach(this::clearSensitiveField);
}
return super.convertToWithPostVo(postComments);
}
@NonNull
@Override
public Page<BaseCommentVO> pageVosBy(@NonNull List<PostComment> postComments,
@NonNull Pageable pageable) {
postComments.forEach(this::clearSensitiveField);
return super.pageVosBy(postComments, pageable);
}
}

View File

@ -0,0 +1,93 @@
package run.halo.app.service.assembler.comment;
import java.util.Comparator;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import run.halo.app.model.dto.BaseCommentDTO;
import run.halo.app.model.entity.SheetComment;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.model.vo.SheetCommentWithSheetVO;
import run.halo.app.repository.SheetRepository;
import run.halo.app.service.OptionService;
/**
* Sheet comment assembler for theme render.
*
* @author guqing
* @date 2022-03-09
*/
@Component
public class SheetCommentRenderAssembler extends SheetCommentAssembler {
public SheetCommentRenderAssembler(OptionService optionService,
SheetRepository sheetRepository) {
super(optionService, sheetRepository);
}
@NonNull
@Override
public BaseCommentDTO convertTo(@NonNull SheetComment comment) {
clearSensitiveField(comment);
return super.convertTo(comment);
}
@NonNull
@Override
public List<BaseCommentDTO> convertTo(@NonNull List<SheetComment> sheetComments) {
sheetComments.forEach(this::clearSensitiveField);
return super.convertTo(sheetComments);
}
@NonNull
@Override
public Page<BaseCommentDTO> convertTo(@NonNull Page<SheetComment> sheetComments) {
sheetComments.getContent().forEach(this::clearSensitiveField);
return super.convertTo(sheetComments);
}
@Override
public List<BaseCommentVO> convertToVo(List<SheetComment> sheetComments,
Comparator<BaseCommentVO> comparator) {
if (!CollectionUtils.isEmpty(sheetComments)) {
sheetComments.forEach(this::clearSensitiveField);
}
return super.convertToVo(sheetComments, comparator);
}
@NonNull
@Override
public SheetCommentWithSheetVO convertToWithSheetVo(@NonNull SheetComment comment) {
clearSensitiveField(comment);
return super.convertToWithSheetVo(comment);
}
@NonNull
@Override
public List<SheetCommentWithSheetVO> convertToWithSheetVo(
List<SheetComment> sheetComments) {
if (!CollectionUtils.isEmpty(sheetComments)) {
sheetComments.forEach(this::clearSensitiveField);
}
return super.convertToWithSheetVo(sheetComments);
}
@NonNull
@Override
public Page<SheetCommentWithSheetVO> convertToWithSheetVo(
@NonNull Page<SheetComment> sheetCommentPage) {
sheetCommentPage.getContent().forEach(this::clearSensitiveField);
return super.convertToWithSheetVo(sheetCommentPage);
}
@NonNull
@Override
public Page<BaseCommentVO> pageVosBy(@NonNull List<SheetComment> sheetComments,
@NonNull Pageable pageable) {
sheetComments.forEach(this::clearSensitiveField);
return super.pageVosBy(sheetComments, pageable);
}
}

View File

@ -94,16 +94,6 @@ public interface BaseCommentService<COMMENT extends BaseComment>
@NonNull
Page<BaseCommentVO> pageVosBy(@NonNull Integer postId, @NonNull Pageable pageable);
/**
* Lists comment vos by list of COMMENT.
*
* @param comments comments must not be null
* @param pageable page info must not be null
* @return a page of comment vo
*/
@NonNull
Page<BaseCommentVO> pageVosBy(@NonNull List<COMMENT> comments, @NonNull Pageable pageable);
/**
* Lists comment with parent vo.
*

View File

@ -42,7 +42,6 @@ import run.halo.app.model.projection.CommentChildrenCountProjection;
import run.halo.app.model.projection.CommentCountProjection;
import run.halo.app.model.properties.BlogProperties;
import run.halo.app.model.properties.CommentProperties;
import run.halo.app.model.support.CommentPage;
import run.halo.app.model.vo.BaseCommentVO;
import run.halo.app.model.vo.BaseCommentWithParentVO;
import run.halo.app.model.vo.CommentWithHasChildrenVO;
@ -142,42 +141,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
// List all the top comments (Caution: This list will be cleared)
List<COMMENT> comments = baseCommentRepository.findAllByPostId(postId);
return pageVosBy(comments, pageable);
}
@Override
@NonNull
public Page<BaseCommentVO> pageVosBy(@NonNull List<COMMENT> comments,
@NonNull Pageable pageable) {
Assert.notNull(comments, "Comments must not be null");
Assert.notNull(pageable, "Page info must not be null");
Comparator<BaseCommentVO> commentComparator =
buildCommentComparator(pageable.getSortOr(Sort.by(Sort.Direction.DESC, "createTime")));
// Convert to vo
List<BaseCommentVO> topComments = commentAssembler.convertToVo(comments, commentComparator);
List<BaseCommentVO> pageContent;
// Calc the shear index
int startIndex = pageable.getPageNumber() * pageable.getPageSize();
if (startIndex >= topComments.size() || startIndex < 0) {
pageContent = Collections.emptyList();
} else {
int endIndex = startIndex + pageable.getPageSize();
if (endIndex > topComments.size()) {
endIndex = topComments.size();
}
log.debug("Top comments size: [{}]", topComments.size());
log.debug("Start index: [{}]", startIndex);
log.debug("End index: [{}]", endIndex);
pageContent = topComments.subList(startIndex, endIndex);
}
return new CommentPage<>(pageContent, pageable, topComments.size(), comments.size());
return commentAssembler.pageVosBy(comments, pageable);
}
@Override
@ -192,7 +156,7 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
List<COMMENT> comments =
baseCommentRepository.findAllByPostIdAndStatus(postId, CommentStatus.PUBLISHED);
return pageVosBy(comments, pageable);
return commentAssembler.pageVosBy(comments, pageable);
}
@Override
@ -501,31 +465,6 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment>
};
}
/**
* Builds a comment comparator.
*
* @param sort sort info
* @return comment comparator
*/
protected Comparator<BaseCommentVO> buildCommentComparator(Sort sort) {
return (currentComment, toCompareComment) -> {
Assert.notNull(currentComment, "Current comment must not be null");
Assert.notNull(toCompareComment, "Comment to compare must not be null");
// Get sort order
Sort.Order order = sort.filter(anOrder -> "id".equals(anOrder.getProperty()))
.get()
.findFirst()
.orElseGet(() -> Sort.Order.desc("id"));
// Init sign
int sign = order.getDirection().isAscending() ? 1 : -1;
// Compare id property
return sign * currentComment.getId().compareTo(toCompareComment.getId());
};
}
@Override
@NonNull
public Page<CommentWithHasChildrenVO> pageTopCommentsBy(@NonNull Integer targetId,

View File

@ -112,6 +112,6 @@ public class PostCommentApiTest extends BaseApiTest {
Assertions.assertEquals(HttpStatus.OK, result.getStatusCode());
Assertions.assertEquals(COMMENT_AUTHOR_TEST, comment.getAuthor());
Assertions.assertEquals(COMMENT_CONTENT_TEST, comment.getContent());
Assertions.assertEquals(COMMENT_VALID_EMAIL_TEST, comment.getEmail());
Assertions.assertNull(comment.getEmail());
}
}