mirror of https://github.com/halo-dev/halo
fix: breadcrumbs for hidden category can not be displayed (#6200)
#### What type of PR is this? /kind bug /area core /area theme /milestone 2.17.x #### What this PR does / why we need it: 修复获取隐藏分类的面包屑路径不正确的问题 #### Which issue(s) this PR fixes: Fixes #6197 #### Does this PR introduce a user-facing change? ```release-note 修复获取隐藏分类的面包屑路径不正确的问题 ```pull/6216/head
parent
80e1110da2
commit
4cafdb5a72
|
@ -17,6 +17,7 @@ import org.apache.commons.lang3.BooleanUtils;
|
|||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -88,12 +89,16 @@ public class CategoryFinderImpl implements CategoryFinder {
|
|||
|
||||
@Override
|
||||
public Flux<CategoryTreeVo> listAsTree() {
|
||||
return this.toCategoryTreeVoFlux(null);
|
||||
return listAll()
|
||||
.collectList()
|
||||
.flatMapMany(list -> Flux.fromIterable(listToTree(list, null)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<CategoryTreeVo> listAsTree(String name) {
|
||||
return this.toCategoryTreeVoFlux(name);
|
||||
return listAllFor(name)
|
||||
.collectList()
|
||||
.flatMapMany(list -> Flux.fromIterable(listToTree(list, name)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,43 +108,50 @@ public class CategoryFinderImpl implements CategoryFinder {
|
|||
.map(CategoryVo::from);
|
||||
}
|
||||
|
||||
Flux<CategoryVo> listAllFor(String parentName) {
|
||||
return categoryService.isCategoryHidden(parentName)
|
||||
private Flux<CategoryVo> listAllFor(String parentName) {
|
||||
return Mono.defer(
|
||||
() -> {
|
||||
if (StringUtils.isBlank(parentName)) {
|
||||
return Mono.just(false);
|
||||
}
|
||||
return categoryService.isCategoryHidden(parentName);
|
||||
})
|
||||
.flatMapMany(
|
||||
isHidden -> client.listAll(Category.class, new ListOptions(), defaultSort())
|
||||
.filter(category -> isHidden || !category.getSpec().isHideFromList())
|
||||
.filter(category -> {
|
||||
if (isHidden) {
|
||||
return true;
|
||||
}
|
||||
return !category.getSpec().isHideFromList();
|
||||
})
|
||||
.map(CategoryVo::from)
|
||||
);
|
||||
}
|
||||
|
||||
Flux<CategoryTreeVo> toCategoryTreeVoFlux(String name) {
|
||||
return listAllFor(name)
|
||||
.collectList()
|
||||
.flatMapIterable(categoryVos -> {
|
||||
Map<String, CategoryTreeVo> nameIdentityMap = categoryVos.stream()
|
||||
.map(CategoryTreeVo::from)
|
||||
.collect(Collectors.toMap(categoryVo -> categoryVo.getMetadata().getName(),
|
||||
Function.identity()));
|
||||
private List<CategoryTreeVo> listToTree(List<CategoryVo> categoryVos, @Nullable String name) {
|
||||
Map<String, CategoryTreeVo> nameIdentityMap = categoryVos.stream()
|
||||
.map(CategoryTreeVo::from)
|
||||
.collect(Collectors.toMap(categoryVo -> categoryVo.getMetadata().getName(),
|
||||
Function.identity()));
|
||||
|
||||
nameIdentityMap.forEach((nameKey, value) -> {
|
||||
List<String> children = value.getSpec().getChildren();
|
||||
if (children == null) {
|
||||
return;
|
||||
}
|
||||
for (String child : children) {
|
||||
CategoryTreeVo childNode = nameIdentityMap.get(child);
|
||||
if (childNode != null) {
|
||||
childNode.setParentName(nameKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
var tree = listToTree(nameIdentityMap.values(), name);
|
||||
recomputePostCount(tree);
|
||||
return tree;
|
||||
});
|
||||
nameIdentityMap.forEach((nameKey, value) -> {
|
||||
List<String> children = value.getSpec().getChildren();
|
||||
if (children == null) {
|
||||
return;
|
||||
}
|
||||
for (String child : children) {
|
||||
CategoryTreeVo childNode = nameIdentityMap.get(child);
|
||||
if (childNode != null) {
|
||||
childNode.setParentName(nameKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
var tree = listToTree(nameIdentityMap.values(), name);
|
||||
recomputePostCount(tree);
|
||||
return tree;
|
||||
}
|
||||
|
||||
static List<CategoryTreeVo> listToTree(Collection<CategoryTreeVo> list, String name) {
|
||||
private static List<CategoryTreeVo> listToTree(Collection<CategoryTreeVo> list, String name) {
|
||||
Map<String, List<CategoryTreeVo>> parentNameIdentityMap = list.stream()
|
||||
.filter(categoryTreeVo -> categoryTreeVo.getParentName() != null)
|
||||
.collect(Collectors.groupingBy(CategoryTreeVo::getParentName));
|
||||
|
@ -228,8 +240,9 @@ public class CategoryFinderImpl implements CategoryFinder {
|
|||
|
||||
@Override
|
||||
public Flux<CategoryVo> getBreadcrumbs(String name) {
|
||||
return listAsTree()
|
||||
return listAllFor(name)
|
||||
.collectList()
|
||||
.map(list -> listToTree(list, null))
|
||||
.flatMapMany(treeNodes -> {
|
||||
var rootNode = dummyVirtualRoot(treeNodes);
|
||||
var paths = new ArrayList<CategoryVo>();
|
||||
|
|
|
@ -13,6 +13,8 @@ import java.time.Instant;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
|
@ -190,13 +192,13 @@ class CategoryFinderImplTest {
|
|||
var json = Files.readString(file.toPath());
|
||||
categories = JsonUtils.jsonToObject(json, new TypeReference<>() {
|
||||
});
|
||||
when(client.listAll(eq(Category.class), any(ListOptions.class), any(Sort.class)))
|
||||
.thenReturn(Flux.fromIterable(categories));
|
||||
}
|
||||
|
||||
@Test
|
||||
void computePostCountFromTree() {
|
||||
var treeVos = categoryFinder.toCategoryTreeVoFlux("全部")
|
||||
when(client.listAll(eq(Category.class), any(ListOptions.class), any(Sort.class)))
|
||||
.thenReturn(Flux.fromIterable(categories));
|
||||
var treeVos = categoryFinder.listAsTree("全部")
|
||||
.collectList().block();
|
||||
assertThat(treeVos).hasSize(1);
|
||||
String s = visualizeTree(treeVos.get(0).getChildren());
|
||||
|
@ -232,6 +234,8 @@ class CategoryFinderImplTest {
|
|||
|
||||
@Test
|
||||
void getBreadcrumbsTest() {
|
||||
when(client.listAll(eq(Category.class), any(ListOptions.class), any(Sort.class)))
|
||||
.thenReturn(Flux.fromIterable(categories));
|
||||
// first level
|
||||
var breadcrumbs = categoryFinder.getBreadcrumbs("全部").collectList().block();
|
||||
assertThat(toNames(breadcrumbs)).containsSequence("全部");
|
||||
|
@ -259,6 +263,26 @@ class CategoryFinderImplTest {
|
|||
assertThat(toNames(breadcrumbs)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBreadcrumbsForHiddenTest() {
|
||||
Map<String, Category> categoryMap = categories.stream()
|
||||
.collect(
|
||||
Collectors.toMap(item -> item.getMetadata().getName(), Function.identity()));
|
||||
var category = categoryMap.get("IndependentNode");
|
||||
category.getSpec().setHideFromList(true);
|
||||
when(client.listAll(eq(Category.class), any(ListOptions.class), any(Sort.class)))
|
||||
.thenReturn(Flux.fromIterable(categoryMap.values()));
|
||||
|
||||
when(categoryService.isCategoryHidden(eq("IndependentChild4")))
|
||||
.thenReturn(Mono.just(true));
|
||||
|
||||
var breadcrumbs = categoryFinder.getBreadcrumbs("IndependentChild4")
|
||||
.collectList().block();
|
||||
assertThat(toNames(breadcrumbs)).containsSequence("全部", "FIT2CLOUD",
|
||||
"IndependentNode",
|
||||
"IndependentChild4");
|
||||
}
|
||||
|
||||
static List<String> toNames(List<CategoryVo> categories) {
|
||||
if (categories == null) {
|
||||
return List.of();
|
||||
|
|
Loading…
Reference in New Issue