mirror of https://github.com/halo-dev/halo
Fix migration logical bug
parent
f2b9fc768d
commit
4c8d38ae07
|
@ -3,9 +3,8 @@ package run.halo.app.model.entity;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import org.hibernate.annotations.SQLDelete;
|
|
||||||
import org.hibernate.annotations.Where;
|
|
||||||
import run.halo.app.model.enums.CommentStatus;
|
import run.halo.app.model.enums.CommentStatus;
|
||||||
|
import run.halo.app.utils.ServiceUtils;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@ -102,7 +101,11 @@ public class BaseComment extends BaseEntity {
|
||||||
public void prePersist() {
|
public void prePersist() {
|
||||||
super.prePersist();
|
super.prePersist();
|
||||||
|
|
||||||
if (parentId == null || parentId < 0) {
|
if (ServiceUtils.isEmptyId(id)) {
|
||||||
|
id = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServiceUtils.isEmptyId(parentId)) {
|
||||||
parentId = 0L;
|
parentId = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,4 +46,5 @@ public interface BaseRepository<DOMAIN, ID> extends JpaRepository<DOMAIN, ID> {
|
||||||
* @return number of rows affected
|
* @return number of rows affected
|
||||||
*/
|
*/
|
||||||
long deleteByIdIn(@NonNull Iterable<ID> ids);
|
long deleteByIdIn(@NonNull Iterable<ID> ids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.data.jpa.repository.support.JpaEntityInformation;
|
||||||
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
|
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
|
||||||
import org.springframework.data.repository.support.PageableExecutionUtils;
|
import org.springframework.data.repository.support.PageableExecutionUtils;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
@ -97,6 +98,7 @@ public class BaseRepositoryImpl<DOMAIN, ID> extends SimpleJpaRepository<DOMAIN,
|
||||||
* @return number of rows affected
|
* @return number of rows affected
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public long deleteByIdIn(Iterable<ID> ids) {
|
public long deleteByIdIn(Iterable<ID> ids) {
|
||||||
|
|
||||||
log.debug("Customized deleteByIdIn method was invoked");
|
log.debug("Customized deleteByIdIn method was invoked");
|
||||||
|
|
|
@ -13,6 +13,7 @@ import run.halo.app.model.vo.BaseCommentVO;
|
||||||
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
import run.halo.app.model.vo.BaseCommentWithParentVO;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -163,6 +164,15 @@ public interface BaseCommentService<COMMENT extends BaseComment> extends CrudSer
|
||||||
@NonNull
|
@NonNull
|
||||||
Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> commentPage);
|
Page<BaseCommentDTO> convertTo(@NonNull Page<COMMENT> 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<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments, @Nullable Comparator<BaseCommentVO> comparator);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target must exist.
|
* Target must exist.
|
||||||
*
|
*
|
||||||
|
|
|
@ -219,9 +219,17 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
// Set some default values
|
// Set some default values
|
||||||
comment.setIpAddress(ServletUtils.getRequestIp());
|
if (comment.getIpAddress() == null) {
|
||||||
comment.setUserAgent(ServletUtils.getHeaderIgnoreCase(HttpHeaders.USER_AGENT));
|
comment.setIpAddress(ServletUtils.getRequestIp());
|
||||||
comment.setGavatarMd5(DigestUtils.md5Hex(comment.getEmail()));
|
}
|
||||||
|
|
||||||
|
if (comment.getUserAgent() == null) {
|
||||||
|
comment.setUserAgent(ServletUtils.getHeaderIgnoreCase(HttpHeaders.USER_AGENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment.getGavatarMd5() == null) {
|
||||||
|
comment.setGavatarMd5(DigestUtils.md5Hex(comment.getEmail()));
|
||||||
|
}
|
||||||
|
|
||||||
if (authentication != null) {
|
if (authentication != null) {
|
||||||
// Comment of blogger
|
// Comment of blogger
|
||||||
|
@ -368,15 +376,8 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> 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
|
@NonNull
|
||||||
protected List<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments, @Nullable Comparator<BaseCommentVO> comparator) {
|
public List<BaseCommentVO> convertToVo(@Nullable List<COMMENT> comments, @Nullable Comparator<BaseCommentVO> comparator) {
|
||||||
if (CollectionUtils.isEmpty(comments)) {
|
if (CollectionUtils.isEmpty(comments)) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -408,32 +409,24 @@ public abstract class BaseCommentServiceImpl<COMMENT extends BaseComment> extend
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<COMMENT> children = new LinkedList<>();
|
// Get children
|
||||||
|
List<COMMENT> children = comments.stream()
|
||||||
|
.filter(comment -> Objects.equals(parentComment.getId(), comment.getParentId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
comments.forEach(comment -> {
|
// Add children
|
||||||
if (parentComment.getId().equals(comment.getParentId())) {
|
children.forEach(comment -> {
|
||||||
// Stage the child comment
|
// Convert to comment vo
|
||||||
children.add(comment);
|
BaseCommentVO commentVO = new BaseCommentVO().convertFrom(comment);
|
||||||
|
|
||||||
// Convert to comment vo
|
if (parentComment.getChildren() == null) {
|
||||||
BaseCommentVO commentVO = new BaseCommentVO().convertFrom(comment);
|
parentComment.setChildren(new LinkedList<>());
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parentComment.getChildren().add(commentVO);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove all children
|
// Remove children
|
||||||
comments.removeAll(children);
|
comments.removeAll(children);
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(parentComment.getChildren())) {
|
if (!CollectionUtils.isEmpty(parentComment.getChildren())) {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.lang.NonNull;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import run.halo.app.exception.ServiceException;
|
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.AttachmentType;
|
||||||
import run.halo.app.model.enums.CommentStatus;
|
import run.halo.app.model.enums.CommentStatus;
|
||||||
import run.halo.app.model.enums.PostStatus;
|
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.service.*;
|
||||||
import run.halo.app.utils.BeanUtils;
|
import run.halo.app.utils.BeanUtils;
|
||||||
import run.halo.app.utils.JsonUtils;
|
import run.halo.app.utils.JsonUtils;
|
||||||
|
import run.halo.app.utils.ServiceUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
@ -49,8 +53,12 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
|
|
||||||
private final PostCommentService postCommentService;
|
private final PostCommentService postCommentService;
|
||||||
|
|
||||||
|
private final PostCommentRepository postCommentRepository;
|
||||||
|
|
||||||
private final SheetCommentService sheetCommentService;
|
private final SheetCommentService sheetCommentService;
|
||||||
|
|
||||||
|
private final SheetCommentRepository sheetCommentRepository;
|
||||||
|
|
||||||
private final SheetService sheetService;
|
private final SheetService sheetService;
|
||||||
|
|
||||||
private final PhotoService photoService;
|
private final PhotoService photoService;
|
||||||
|
@ -62,7 +70,9 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
CategoryService categoryService,
|
CategoryService categoryService,
|
||||||
TagService tagService,
|
TagService tagService,
|
||||||
PostCommentService postCommentService,
|
PostCommentService postCommentService,
|
||||||
|
PostCommentRepository postCommentRepository,
|
||||||
SheetCommentService sheetCommentService,
|
SheetCommentService sheetCommentService,
|
||||||
|
SheetCommentRepository sheetCommentRepository,
|
||||||
SheetService sheetService,
|
SheetService sheetService,
|
||||||
PhotoService photoService) {
|
PhotoService photoService) {
|
||||||
this.attachmentService = attachmentService;
|
this.attachmentService = attachmentService;
|
||||||
|
@ -72,7 +82,9 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
this.categoryService = categoryService;
|
this.categoryService = categoryService;
|
||||||
this.tagService = tagService;
|
this.tagService = tagService;
|
||||||
this.postCommentService = postCommentService;
|
this.postCommentService = postCommentService;
|
||||||
|
this.postCommentRepository = postCommentRepository;
|
||||||
this.sheetCommentService = sheetCommentService;
|
this.sheetCommentService = sheetCommentService;
|
||||||
|
this.sheetCommentRepository = sheetCommentRepository;
|
||||||
this.sheetService = sheetService;
|
this.sheetService = sheetService;
|
||||||
this.photoService = photoService;
|
this.photoService = photoService;
|
||||||
}
|
}
|
||||||
|
@ -203,7 +215,7 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
Post createdPost = postService.createOrUpdateBy(post);
|
Post createdPost = postService.createOrUpdateBy(post);
|
||||||
|
|
||||||
Object commentsObject = postMap.get("comments");
|
Object commentsObject = postMap.get("comments");
|
||||||
// TODO Handle comments
|
// Handle comments
|
||||||
List<BaseComment> baseComments = handleComment(commentsObject, createdPost.getId());
|
List<BaseComment> baseComments = handleComment(commentsObject, createdPost.getId());
|
||||||
|
|
||||||
List<PostComment> postComments = baseComments.stream()
|
List<PostComment> postComments = baseComments.stream()
|
||||||
|
@ -211,9 +223,11 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Build virtual comment
|
||||||
|
PostComment virtualPostComment = new PostComment();
|
||||||
|
virtualPostComment.setId(0L);
|
||||||
// Create comments
|
// Create comments
|
||||||
// TODO Don't use createInBatch method
|
createPostCommentRecursively(virtualPostComment, postComments);
|
||||||
List<PostComment> createdPostComments = postCommentService.createInBatch(postComments);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Failed to create post comments for post with id " + createdPost.getId(), e);
|
log.warn("Failed to create post comments for post with id " + createdPost.getId(), e);
|
||||||
// Ignore this exception
|
// Ignore this exception
|
||||||
|
@ -239,7 +253,11 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
|
|
||||||
// Create comments
|
// Create comments
|
||||||
try {
|
try {
|
||||||
sheetCommentService.createInBatch(sheetComments);
|
// Build virtual comment
|
||||||
|
SheetComment virtualSheetComment = new SheetComment();
|
||||||
|
virtualSheetComment.setId(0L);
|
||||||
|
// Create comments
|
||||||
|
createSheetCommentRecursively(virtualSheetComment, sheetComments);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Failed to create sheet comments for sheet with id " + createdSheet.getId(), e);
|
log.warn("Failed to create sheet comments for sheet with id " + createdSheet.getId(), e);
|
||||||
// Ignore this exception
|
// Ignore this exception
|
||||||
|
@ -248,6 +266,62 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
return createdSheet;
|
return createdSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createPostCommentRecursively(@NonNull final PostComment parentComment, List<PostComment> 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<PostComment> 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<SheetComment> 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<SheetComment> 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<BaseComment> handleComment(@Nullable Object commentsObject, @NonNull Integer postId) {
|
private List<BaseComment> handleComment(@Nullable Object commentsObject, @NonNull Integer postId) {
|
||||||
Assert.notNull(postId, "Post id must not be null");
|
Assert.notNull(postId, "Post id must not be null");
|
||||||
|
|
||||||
|
@ -279,6 +353,10 @@ public class RecoveryServiceImpl implements RecoveryService {
|
||||||
baseComment.setPostId(postId);
|
baseComment.setPostId(postId);
|
||||||
baseComment.setParentId(getLongOrDefault(commentMap.getOrDefault("commentParent", "").toString(), 0L));
|
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);
|
Integer commentStatus = getIntegerOrDefault(commentMap.getOrDefault("commentStatus", "").toString(), 1);
|
||||||
if (commentStatus == 0) {
|
if (commentStatus == 0) {
|
||||||
baseComment.setStatus(CommentStatus.PUBLISHED);
|
baseComment.setStatus(CommentStatus.PUBLISHED);
|
||||||
|
|
Loading…
Reference in New Issue