feat: add site stats finder for theme-side (#2604)

#### What type of PR is this?
/kind feature
/area core
/milestone 2.0

#### What this PR does / why we need it:
提供主题端站点统计信息查询器
#### Which issue(s) this PR fixes:

Fixes #

#### Special notes for your reviewer:
how to test it?
在任意主题页面使用如下语法
```
<p th:text="${siteStatsFinder.getStats()}"></p>
```
/cc @halo-dev/sig-halo 
#### Does this PR introduce a user-facing change?

```release-note
提供主题端站点统计信息查询器
```
pull/2613/head^2
guqing 2022-10-20 22:34:23 +08:00 committed by GitHub
parent 6b2aea9301
commit 969c0d56f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 104 additions and 0 deletions

View File

@ -0,0 +1,14 @@
package run.halo.app.theme.finders;
import run.halo.app.theme.finders.vo.SiteStatsVo;
/**
* Site statistics finder.
*
* @author guqing
* @since 2.0.0
*/
public interface SiteStatsFinder {
SiteStatsVo getStats();
}

View File

@ -0,0 +1,55 @@
package run.halo.app.theme.finders.impl;
import lombok.AllArgsConstructor;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.Category;
import run.halo.app.core.extension.Counter;
import run.halo.app.core.extension.Post;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.theme.finders.Finder;
import run.halo.app.theme.finders.SiteStatsFinder;
import run.halo.app.theme.finders.vo.SiteStatsVo;
/**
* A default implementation of {@link SiteStatsFinder}.
*
* @author guqing
* @since 2.0.0
*/
@AllArgsConstructor
@Finder("siteStatsFinder")
public class SiteStatsFinderImpl implements SiteStatsFinder {
private final ReactiveExtensionClient client;
@Override
public SiteStatsVo getStats() {
return client.list(Counter.class, null, null)
.reduce(SiteStatsVo.empty(), (stats, counter) -> {
stats.setVisit(stats.getVisit() + counter.getVisit());
stats.setComment(stats.getComment() + counter.getApprovedComment());
stats.setUpvote(stats.getUpvote() + counter.getUpvote());
return stats;
})
.flatMap(siteStatsVo -> postCount()
.doOnNext(siteStatsVo::setPost)
.thenReturn(siteStatsVo)
)
.flatMap(siteStatsVo -> categoryCount()
.doOnNext(siteStatsVo::setCategory)
.thenReturn(siteStatsVo))
.block();
}
Mono<Integer> postCount() {
return client.list(Post.class, post -> !post.isDeleted() && post.isPublished(), null)
.count()
.map(Long::intValue);
}
Mono<Integer> categoryCount() {
return client.list(Category.class, null, null)
.count()
.map(Long::intValue);
}
}

View File

@ -0,0 +1,35 @@
package run.halo.app.theme.finders.vo;
import lombok.Builder;
import lombok.Data;
/**
* A value object for site stats.
*
* @author guqing
* @since 2.0.0
*/
@Data
@Builder
public class SiteStatsVo {
private Integer visit;
private Integer upvote;
private Integer comment;
private Integer post;
private Integer category;
public static SiteStatsVo empty() {
return SiteStatsVo.builder()
.visit(0)
.upvote(0)
.comment(0)
.post(0)
.category(0)
.build();
}
}