diff --git a/src/main/java/run/halo/app/model/entity/BaseComment.java b/src/main/java/run/halo/app/model/entity/BaseComment.java index 6dae167d6..74be80bdb 100644 --- a/src/main/java/run/halo/app/model/entity/BaseComment.java +++ b/src/main/java/run/halo/app/model/entity/BaseComment.java @@ -3,9 +3,8 @@ package run.halo.app.model.entity; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.Where; import run.halo.app.model.enums.CommentStatus; +import run.halo.app.utils.ServiceUtils; import javax.persistence.*; @@ -102,7 +101,11 @@ public class BaseComment extends BaseEntity { public void prePersist() { super.prePersist(); - if (parentId == null || parentId < 0) { + if (ServiceUtils.isEmptyId(id)) { + id = null; + } + + if (ServiceUtils.isEmptyId(parentId)) { parentId = 0L; } diff --git a/src/main/java/run/halo/app/repository/base/BaseRepository.java b/src/main/java/run/halo/app/repository/base/BaseRepository.java index 51775e5e7..91948a579 100644 --- a/src/main/java/run/halo/app/repository/base/BaseRepository.java +++ b/src/main/java/run/halo/app/repository/base/BaseRepository.java @@ -46,4 +46,5 @@ public interface BaseRepository extends JpaRepository { * @return number of rows affected */ long deleteByIdIn(@NonNull Iterable ids); + } diff --git a/src/main/java/run/halo/app/repository/base/BaseRepositoryImpl.java b/src/main/java/run/halo/app/repository/base/BaseRepositoryImpl.java index 231d9a304..021bfbc32 100644 --- a/src/main/java/run/halo/app/repository/base/BaseRepositoryImpl.java +++ b/src/main/java/run/halo/app/repository/base/BaseRepositoryImpl.java @@ -10,6 +10,7 @@ import org.springframework.data.jpa.repository.support.JpaEntityInformation; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.repository.support.PageableExecutionUtils; import org.springframework.lang.Nullable; +import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import javax.persistence.EntityManager; @@ -97,6 +98,7 @@ public class BaseRepositoryImpl extends SimpleJpaRepository ids) { log.debug("Customized deleteByIdIn method was invoked"); 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 7e4cb8788..ccb895f32 100644 --- a/src/main/java/run/halo/app/service/base/BaseCommentService.java +++ b/src/main/java/run/halo/app/service/base/BaseCommentService.java @@ -13,6 +13,7 @@ import run.halo.app.model.vo.BaseCommentVO; import run.halo.app.model.vo.BaseCommentWithParentVO; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; @@ -163,6 +164,15 @@ public interface BaseCommentService extends CrudSer @NonNull Page convertTo(@NonNull Page commentPage); + /** + * Converts to base comment vo tree. + * + * @param comments comments list could be null + * @param comparator comment comparator could be null + * @return a comment vo tree + */ + List convertToVo(@Nullable List comments, @Nullable Comparator comparator); + /** * Target must exist. * 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 1fade9883..2e26b1a4b 100644 --- a/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/BaseCommentServiceImpl.java @@ -219,9 +219,17 @@ public abstract class BaseCommentServiceImpl extend Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // Set some default values - comment.setIpAddress(ServletUtils.getRequestIp()); - comment.setUserAgent(ServletUtils.getHeaderIgnoreCase(HttpHeaders.USER_AGENT)); - comment.setGavatarMd5(DigestUtils.md5Hex(comment.getEmail())); + if (comment.getIpAddress() == null) { + comment.setIpAddress(ServletUtils.getRequestIp()); + } + + if (comment.getUserAgent() == null) { + comment.setUserAgent(ServletUtils.getHeaderIgnoreCase(HttpHeaders.USER_AGENT)); + } + + if (comment.getGavatarMd5() == null) { + comment.setGavatarMd5(DigestUtils.md5Hex(comment.getEmail())); + } if (authentication != null) { // Comment of blogger @@ -368,15 +376,8 @@ public abstract class BaseCommentServiceImpl extend }; } - /** - * Converts to base comment vo tree. - * - * @param comments comments list could be null - * @param comparator comment comparator could be null - * @return a comment vo tree - */ @NonNull - protected List convertToVo(@Nullable List comments, @Nullable Comparator comparator) { + public List convertToVo(@Nullable List comments, @Nullable Comparator comparator) { if (CollectionUtils.isEmpty(comments)) { return Collections.emptyList(); } @@ -408,32 +409,24 @@ public abstract class BaseCommentServiceImpl extend return; } - List children = new LinkedList<>(); + // Get children + List children = comments.stream() + .filter(comment -> Objects.equals(parentComment.getId(), comment.getParentId())) + .collect(Collectors.toList()); - comments.forEach(comment -> { - if (parentComment.getId().equals(comment.getParentId())) { - // Stage the child comment - children.add(comment); + // Add children + children.forEach(comment -> { + // Convert to comment vo + BaseCommentVO commentVO = new BaseCommentVO().convertFrom(comment); - // Convert to comment vo - BaseCommentVO commentVO = new BaseCommentVO().convertFrom(comment); - - // Add additional content - if (commentVO.getParentId() > 0) { - // TODO Provide an optional additional content - commentVO.setContent(String.format(COMMENT_TEMPLATE, parentComment.getId(), parentComment.getAuthor(), commentVO.getContent())); - } - - // Init children container - if (parentComment.getChildren() == null) { - parentComment.setChildren(new LinkedList<>()); - } - - parentComment.getChildren().add(commentVO); + if (parentComment.getChildren() == null) { + parentComment.setChildren(new LinkedList<>()); } + + parentComment.getChildren().add(commentVO); }); - // Remove all children + // Remove children comments.removeAll(children); if (!CollectionUtils.isEmpty(parentComment.getChildren())) { diff --git a/src/main/java/run/halo/app/service/impl/RecoveryServiceImpl.java b/src/main/java/run/halo/app/service/impl/RecoveryServiceImpl.java index f20a932ad..bf75af7c5 100644 --- a/src/main/java/run/halo/app/service/impl/RecoveryServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/RecoveryServiceImpl.java @@ -7,6 +7,7 @@ import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; import run.halo.app.exception.ServiceException; @@ -14,9 +15,12 @@ import run.halo.app.model.entity.*; import run.halo.app.model.enums.AttachmentType; import run.halo.app.model.enums.CommentStatus; import run.halo.app.model.enums.PostStatus; +import run.halo.app.repository.PostCommentRepository; +import run.halo.app.repository.SheetCommentRepository; import run.halo.app.service.*; import run.halo.app.utils.BeanUtils; import run.halo.app.utils.JsonUtils; +import run.halo.app.utils.ServiceUtils; import java.io.IOException; import java.io.InputStreamReader; @@ -49,8 +53,12 @@ public class RecoveryServiceImpl implements RecoveryService { private final PostCommentService postCommentService; + private final PostCommentRepository postCommentRepository; + private final SheetCommentService sheetCommentService; + private final SheetCommentRepository sheetCommentRepository; + private final SheetService sheetService; private final PhotoService photoService; @@ -62,7 +70,9 @@ public class RecoveryServiceImpl implements RecoveryService { CategoryService categoryService, TagService tagService, PostCommentService postCommentService, + PostCommentRepository postCommentRepository, SheetCommentService sheetCommentService, + SheetCommentRepository sheetCommentRepository, SheetService sheetService, PhotoService photoService) { this.attachmentService = attachmentService; @@ -72,7 +82,9 @@ public class RecoveryServiceImpl implements RecoveryService { this.categoryService = categoryService; this.tagService = tagService; this.postCommentService = postCommentService; + this.postCommentRepository = postCommentRepository; this.sheetCommentService = sheetCommentService; + this.sheetCommentRepository = sheetCommentRepository; this.sheetService = sheetService; this.photoService = photoService; } @@ -203,7 +215,7 @@ public class RecoveryServiceImpl implements RecoveryService { Post createdPost = postService.createOrUpdateBy(post); Object commentsObject = postMap.get("comments"); - // TODO Handle comments + // Handle comments List baseComments = handleComment(commentsObject, createdPost.getId()); List postComments = baseComments.stream() @@ -211,9 +223,11 @@ public class RecoveryServiceImpl implements RecoveryService { .collect(Collectors.toList()); try { + // Build virtual comment + PostComment virtualPostComment = new PostComment(); + virtualPostComment.setId(0L); // Create comments - // TODO Don't use createInBatch method - List createdPostComments = postCommentService.createInBatch(postComments); + createPostCommentRecursively(virtualPostComment, postComments); } catch (Exception e) { log.warn("Failed to create post comments for post with id " + createdPost.getId(), e); // Ignore this exception @@ -239,7 +253,11 @@ public class RecoveryServiceImpl implements RecoveryService { // Create comments try { - sheetCommentService.createInBatch(sheetComments); + // Build virtual comment + SheetComment virtualSheetComment = new SheetComment(); + virtualSheetComment.setId(0L); + // Create comments + createSheetCommentRecursively(virtualSheetComment, sheetComments); } catch (Exception e) { log.warn("Failed to create sheet comments for sheet with id " + createdSheet.getId(), e); // Ignore this exception @@ -248,6 +266,62 @@ public class RecoveryServiceImpl implements RecoveryService { return createdSheet; } + + private void createPostCommentRecursively(@NonNull final PostComment parentComment, List postComments) { + Long oldParentId = parentComment.getId(); + + // Create parent + if (!ServiceUtils.isEmptyId(parentComment.getId())) { + PostComment createdComment = postCommentRepository.save(parentComment); + log.debug("Created post comment: [{}]", createdComment); + parentComment.setId(createdComment.getId()); + } + + if (CollectionUtils.isEmpty(postComments)) { + return; + } + // Get all children + List children = postComments.stream() + .filter(postComment -> Objects.equals(oldParentId, postComment.getParentId())) + .collect(Collectors.toList()); + + + // Set parent id again + children.forEach(postComment -> postComment.setParentId(parentComment.getId())); + + // Remove children + postComments.removeAll(children); + + // Create children recursively + children.forEach(childComment -> createPostCommentRecursively(childComment, postComments)); + } + + private void createSheetCommentRecursively(@NonNull final SheetComment parentComment, List sheetComments) { + Long oldParentId = parentComment.getId(); + // Create parent + if (!ServiceUtils.isEmptyId(parentComment.getId())) { + SheetComment createComment = sheetCommentRepository.save(parentComment); + parentComment.setId(createComment.getId()); + } + + if (CollectionUtils.isEmpty(sheetComments)) { + return; + } + // Get all children + List children = sheetComments.stream() + .filter(sheetComment -> Objects.equals(oldParentId, sheetComment.getParentId())) + .collect(Collectors.toList()); + + // Set parent id again + children.forEach(postComment -> postComment.setParentId(parentComment.getId())); + + // Remove children + sheetComments.removeAll(children); + + // Create children recursively + children.forEach(childComment -> createSheetCommentRecursively(childComment, sheetComments)); + } + private List handleComment(@Nullable Object commentsObject, @NonNull Integer postId) { Assert.notNull(postId, "Post id must not be null"); @@ -279,6 +353,10 @@ public class RecoveryServiceImpl implements RecoveryService { baseComment.setPostId(postId); baseComment.setParentId(getLongOrDefault(commentMap.getOrDefault("commentParent", "").toString(), 0L)); + // Set create date + Long createTimestamp = getLongOrDefault(commentMap.getOrDefault("createDate", "").toString(), System.currentTimeMillis()); + baseComment.setCreateTime(new Date(createTimestamp)); + Integer commentStatus = getIntegerOrDefault(commentMap.getOrDefault("commentStatus", "").toString(), 1); if (commentStatus == 0) { baseComment.setStatus(CommentStatus.PUBLISHED);