Support querying sub-categories of any level (#2995)

What type of PR is this?

/kind feature
/kind api-change

What this PR does / why we need it:

添加一个方法可以根据分类树的任意一层级的名称查询子树

Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/2960

Special notes for your reviewer:

None

Does this PR introduce a user-facing change?

```release-note
CategoryFinder 添加根据分类查询子分类树结构的方法
```
pull/3031/head
chengfeiyue 2022-12-22 11:56:29 +08:00 committed by GitHub
parent 77da761a13
commit a7da2c0d76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 5 deletions

View File

@ -26,4 +26,6 @@ public interface CategoryFinder {
Flux<CategoryVo> listAll();
Flux<CategoryTreeVo> listAsTree();
Flux<CategoryTreeVo> listAsTree(String name);
}

View File

@ -10,6 +10,7 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Category;
@ -72,6 +73,15 @@ public class CategoryFinderImpl implements CategoryFinder {
@Override
public Flux<CategoryTreeVo> listAsTree() {
return this.toCategoryTreeVoFlux(null);
}
@Override
public Flux<CategoryTreeVo> listAsTree(String name) {
return this.toCategoryTreeVoFlux(name);
}
Flux<CategoryTreeVo> toCategoryTreeVoFlux(String name) {
return listAll()
.collectList()
.flatMapIterable(categoryVos -> {
@ -80,7 +90,7 @@ public class CategoryFinderImpl implements CategoryFinder {
.collect(Collectors.toMap(categoryVo -> categoryVo.getMetadata().getName(),
Function.identity()));
nameIdentityMap.forEach((name, value) -> {
nameIdentityMap.forEach((nameKey, value) -> {
List<String> children = value.getSpec().getChildren();
if (children == null) {
return;
@ -88,15 +98,15 @@ public class CategoryFinderImpl implements CategoryFinder {
for (String child : children) {
CategoryTreeVo childNode = nameIdentityMap.get(child);
if (childNode != null) {
childNode.setParentName(name);
childNode.setParentName(nameKey);
}
}
});
return listToTree(nameIdentityMap.values());
return listToTree(nameIdentityMap.values(), name);
});
}
static List<CategoryTreeVo> listToTree(Collection<CategoryTreeVo> list) {
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));
@ -111,7 +121,8 @@ public class CategoryFinderImpl implements CategoryFinder {
node.setChildren(children);
});
return list.stream()
.filter(v -> v.getParentName() == null)
.filter(v -> StringUtils.isEmpty(name) ? v.getParentName() == null
: StringUtils.equals(v.getMetadata().getName(), name))
.sorted(defaultTreeNodeComparator())
.collect(Collectors.toList());
}

View File

@ -101,6 +101,17 @@ class CategoryFinderImplTest {
assertThat(treeVos).hasSize(1);
}
@Test
void listSubTreeByName() {
when(client.list(eq(Category.class), eq(null), any()))
.thenReturn(Flux.fromIterable(categoriesForTree()));
List<CategoryTreeVo> treeVos = categoryFinder.listAsTree("E").collectList().block();
assertThat(treeVos.get(0).getMetadata().getName()).isEqualTo("E");
assertThat(treeVos.get(0).getChildren()).hasSize(2);
assertThat(treeVos.get(0).getChildren().get(0).getMetadata().getName()).isEqualTo("A");
assertThat(treeVos.get(0).getChildren().get(1).getMetadata().getName()).isEqualTo("C");
}
/**
* Test for {@link CategoryFinderImpl#listAsTree()}.
*