Complete post update api

pull/137/head
johnniang 2019-03-21 23:09:24 +08:00
parent f27f4f8833
commit 7853bd679c
8 changed files with 134 additions and 30 deletions

View File

@ -66,8 +66,28 @@ public class PostParam implements InputConverter<Post> {
Post post = InputConverter.super.convertTo(); Post post = InputConverter.super.convertTo();
// Crypt password // Crypt password
post.setPassword(BCrypt.hashpw(password, BCrypt.gensalt())); if (StringUtils.isNotBlank(password)) {
post.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
}
return post; return post;
} }
@Override
public void update(Post post) {
if (StringUtils.isBlank(url)) {
url = HaloUtils.normalizeUrl(title);
} else {
url = HaloUtils.normalizeUrl(url);
}
url = HaloUtils.initializeUrlIfBlank(url);
InputConverter.super.update(post);
// Crypt password
if (StringUtils.isNotBlank(password)) {
post.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
}
}
} }

View File

@ -47,12 +47,12 @@ public interface PostCategoryService extends CrudService<PostCategory, Integer>
List<Post> listPostBy(@NonNull Integer categoryId); List<Post> listPostBy(@NonNull Integer categoryId);
/** /**
* Creates post categories by post id and category id set. * Merges or creates post categories by post id and category id set if absent.
* *
* @param postId post id must not be null * @param postId post id must not be null
* @param categoryIds category id set * @param categoryIds category id set
* @return a list of post category * @return a list of post category
*/ */
@NonNull @NonNull
List<PostCategory> createBy(@NonNull Integer postId, Set<Integer> categoryIds); List<PostCategory> mergeOrCreateByIfAbsent(@NonNull Integer postId, Set<Integer> categoryIds);
} }

View File

@ -126,6 +126,18 @@ public interface PostService extends CrudService<Post, Integer> {
@Transactional @Transactional
Post createBy(@NonNull Post post, Set<Integer> tagIds, Set<Integer> categoryIds); Post createBy(@NonNull Post post, Set<Integer> tagIds, Set<Integer> categoryIds);
/**
* Updates post by post, tag id set and category id set.
*
* @param postToUpdate post to update must not be null
* @param tagIds tag id set
* @param categoryIds category id set
* @return updated post
*/
@NonNull
@Transactional
Post updateBy(@NonNull Post postToUpdate, Set<Integer> tagIds, Set<Integer> categoryIds);
/** /**
* Get post by url. * Get post by url.
* *

View File

@ -58,12 +58,12 @@ public interface PostTagService extends CrudService<PostTag, Integer> {
List<Post> listPostsBy(@NonNull Integer tagId); List<Post> listPostsBy(@NonNull Integer tagId);
/** /**
* Creates post tags by post id and tag id set. * Merges or creates post tags by post id and tag id set if absent.
* *
* @param postId post id must not be null * @param postId post id must not be null
* @param tagIds tag id set * @param tagIds tag id set
* @return a list of post tag * @return a list of post tag
*/ */
@NonNull @NonNull
List<PostTag> createBy(@NonNull Integer postId, Set<Integer> tagIds); List<PostTag> mergeOrCreateByIfAbsent(@NonNull Integer postId, Set<Integer> tagIds);
} }

View File

@ -88,7 +88,7 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
} }
@Override @Override
public List<PostCategory> createBy(Integer postId, Set<Integer> categoryIds) { public List<PostCategory> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> categoryIds) {
Assert.notNull(postId, "Post id must not be null"); Assert.notNull(postId, "Post id must not be null");
if (CollectionUtils.isEmpty(categoryIds)) { if (CollectionUtils.isEmpty(categoryIds)) {
@ -96,17 +96,41 @@ public class PostCategoryServiceImpl extends AbstractCrudService<PostCategory, I
} }
// Build post categories // Build post categories
Set<PostCategory> postCategories = categoryIds.stream().map(categoryId -> { List<PostCategory> postCategoriesStaging = categoryIds.stream().map(categoryId -> {
PostCategory postCategory = new PostCategory(); PostCategory postCategory = new PostCategory();
postCategory.setPostId(postId); postCategory.setPostId(postId);
postCategory.setCategoryId(categoryId); postCategory.setCategoryId(categoryId);
return postCategory; return postCategory;
}).collect(Collectors.toSet()); }).collect(Collectors.toList());
// List all post categories and remove them List<PostCategory> postCategoriesToCreate = new LinkedList<>();
postCategories.removeAll(postCategoryRepository.findAllByPostId(postId)); List<PostCategory> postCategoriesToRemove = new LinkedList<>();
// Find all exist post categories
List<PostCategory> postCategories = postCategoryRepository.findAllByPostId(postId);
postCategories.forEach(postCategory -> {
if (!postCategoriesStaging.contains(postCategory)) {
postCategoriesToRemove.add(postCategory);
}
});
postCategoriesStaging.forEach(postCategoryStaging -> {
if (!postCategories.contains(postCategoryStaging)) {
postCategoriesToCreate.add(postCategoryStaging);
}
});
// Remove post categories
removeAll(postCategoriesToRemove);
// Remove all post categories need to remove
postCategories.removeAll(postCategoriesToRemove);
// Add all created post categories
postCategories.addAll(createInBatch(postCategoriesToCreate));
// Create them // Create them
return createInBatch(postCategories); return postCategories;
} }
} }

View File

@ -20,12 +20,14 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -166,10 +168,20 @@ public class PostServiceImpl extends AbstractCrudService<Post, Integer> implemen
} }
@Override @Override
public Post createBy(Post post, Set<Integer> tagIds, Set<Integer> categoryIds) { public Post createBy(Post postToCreate, Set<Integer> tagIds, Set<Integer> categoryIds) {
Assert.notNull(post, "Post param must not be null"); return createOrUpdate(postToCreate, tagIds, categoryIds, this::create);
}
// TODO Check url @Override
public Post updateBy(Post postToUpdate, Set<Integer> tagIds, Set<Integer> categoryIds) {
return createOrUpdate(postToUpdate, tagIds, categoryIds, this::update);
}
private Post createOrUpdate(@NonNull Post post, Set<Integer> tagIds, Set<Integer> categoryIds, @NonNull Function<Post, Post> postOperation) {
Assert.notNull(post, "Post param must not be null");
Assert.notNull(postOperation, "Post operation must not be null");
// Check url
long count = postRepository.countByUrl(post.getUrl()); long count = postRepository.countByUrl(post.getUrl());
if (count > 0) { if (count > 0) {
@ -179,10 +191,8 @@ public class PostServiceImpl extends AbstractCrudService<Post, Integer> implemen
// Render content // Render content
post.setFormatContent(MarkdownUtils.renderMarkdown(post.getOriginalContent())); post.setFormatContent(MarkdownUtils.renderMarkdown(post.getOriginalContent()));
// TODO Handle thumbnail // Update post
post = postOperation.apply(post);
// Create post
create(post);
// List all tags // List all tags
List<Tag> tags = tagService.listAllByIds(tagIds); List<Tag> tags = tagService.listAllByIds(tagIds);
@ -191,12 +201,12 @@ public class PostServiceImpl extends AbstractCrudService<Post, Integer> implemen
List<Category> categories = categoryService.listAllByIds(categoryIds); List<Category> categories = categoryService.listAllByIds(categoryIds);
// Create post tags // Create post tags
List<PostTag> postTags = postTagService.createBy(post.getId(), ServiceUtils.fetchProperty(tags, Tag::getId)); List<PostTag> postTags = postTagService.mergeOrCreateByIfAbsent(post.getId(), ServiceUtils.fetchProperty(tags, Tag::getId));
log.debug("Created post tags: [{}]", postTags); log.debug("Created post tags: [{}]", postTags);
// Create post categories // Create post categories
List<PostCategory> postCategories = postCategoryService.createBy(post.getId(), ServiceUtils.fetchProperty(categories, Category::getId)); List<PostCategory> postCategories = postCategoryService.mergeOrCreateByIfAbsent(post.getId(), ServiceUtils.fetchProperty(categories, Category::getId));
log.debug("Created post categories: [{}]", postCategories); log.debug("Created post categories: [{}]", postCategories);
@ -212,6 +222,6 @@ public class PostServiceImpl extends AbstractCrudService<Post, Integer> implemen
*/ */
@Override @Override
public Post getByUrl(String url, PostType type) { public Post getByUrl(String url, PostType type) {
return postRepository.getByUrlAndType(url, type).orElseThrow(()->new NotFoundException("The post does not exist").setErrorData(url)); return postRepository.getByUrlAndType(url, type).orElseThrow(() -> new NotFoundException("The post does not exist").setErrorData(url));
} }
} }

View File

@ -104,7 +104,7 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
} }
@Override @Override
public List<PostTag> createBy(Integer postId, Set<Integer> tagIds) { public List<PostTag> mergeOrCreateByIfAbsent(Integer postId, Set<Integer> tagIds) {
Assert.notNull(postId, "Post id must not be null"); Assert.notNull(postId, "Post id must not be null");
if (CollectionUtils.isEmpty(tagIds)) { if (CollectionUtils.isEmpty(tagIds)) {
@ -112,18 +112,41 @@ public class PostTagServiceImpl extends AbstractCrudService<PostTag, Integer> im
} }
// Create post tags // Create post tags
Set<PostTag> postTags = tagIds.stream().map(tagId -> { List<PostTag> postTagsStaging = tagIds.stream().map(tagId -> {
// Build post tag // Build post tag
PostTag postTag = new PostTag(); PostTag postTag = new PostTag();
postTag.setPostId(postId); postTag.setPostId(postId);
postTag.setTagId(tagId); postTag.setTagId(tagId);
return postTag; return postTag;
}).collect(Collectors.toSet()); }).collect(Collectors.toList());
// Get post tag exist and remove them List<PostTag> postTagsToRemove = new LinkedList<>();
postTags.removeAll(postTagRepository.findAllByPostId(postId)); List<PostTag> postTagsToCreate = new LinkedList<>();
// Create in batch List<PostTag> postTags = postTagRepository.findAllByPostId(postId);
return createInBatch(postTags);
postTags.forEach(postTag -> {
if (!postTagsStaging.contains(postTag)) {
postTagsToRemove.add(postTag);
}
});
postTagsStaging.forEach(postTagStaging -> {
if (!postTags.contains(postTagStaging)) {
postTagsToCreate.add(postTagStaging);
}
});
// Remove post tags
removeAll(postTagsToRemove);
// Remove all post tags need to remove
postTags.removeAll(postTagsToRemove);
// Add all created post tags
postTags.addAll(createInBatch(postTagsToCreate));
// Return post tags
return postTags;
} }
} }

View File

@ -7,7 +7,7 @@ import cc.ryanc.halo.model.entity.Post;
import cc.ryanc.halo.model.enums.PostStatus; import cc.ryanc.halo.model.enums.PostStatus;
import cc.ryanc.halo.model.enums.PostType; import cc.ryanc.halo.model.enums.PostType;
import cc.ryanc.halo.model.params.PostParam; import cc.ryanc.halo.model.params.PostParam;
import cc.ryanc.halo.service.*; import cc.ryanc.halo.service.PostService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@ -53,7 +53,22 @@ public class PostController {
// Convert to // Convert to
Post post = postParam.convertTo(); Post post = postParam.convertTo();
return new PostDetailOutputDTO().convertFrom(postService.createBy(post, postParam.getTagIds(), postParam.getCategoryIds())); Post createdPost = postService.createBy(post, postParam.getTagIds(), postParam.getCategoryIds());
return new PostDetailOutputDTO().convertFrom(createdPost);
}
@PutMapping("{postId:\\d+}")
public PostDetailOutputDTO updateBy(@Valid @RequestBody PostParam postParam,
@PathVariable("postId") Integer postId) {
// Get the post info
Post postToUpdate = postService.getById(postId);
postParam.update(postToUpdate);
Post updatedPost = postService.updateBy(postToUpdate, postParam.getTagIds(), postParam.getCategoryIds());
return new PostDetailOutputDTO().convertFrom(updatedPost);
} }
} }