forked from modstart/ModStartBlog
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBlogCategoryUtil.php
More file actions
207 lines (179 loc) · 6.01 KB
/
Copy pathBlogCategoryUtil.php
File metadata and controls
207 lines (179 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<?php
namespace Module\Blog\Util;
use Illuminate\Support\Facades\Cache;
use ModStart\Core\Assets\AssetsUtil;
use ModStart\Core\Dao\ModelUtil;
use ModStart\Core\Util\TreeUtil;
use Module\Blog\Model\Blog;
use Module\Blog\Model\BlogCategory;
class BlogCategoryUtil
{
public static function clearCache()
{
Cache::forget('Blog:Categories');
// 同时清理二级分类标签缓存
self::clearSubcategoryTagsCache();
}
public static function all()
{
return Cache::rememberForever('Blog:Categories', function () {
$records = ModelUtil::all(BlogCategory::class, [], ['*'], ['sort', 'asc']);
AssetsUtil::recordsFixFullOrDefault($records, 'cover', 'asset/image/none.png');
foreach ($records as $k => $v) {
$records[$k]['_url'] = UrlUtil::category($v);
}
return $records;
});
}
public static function categoryTree()
{
$nodes = self::all();
return TreeUtil::nodesToTree($nodes);
}
public static function categoryTreeFlat()
{
$tree = self::categoryTree();
$nodes = TreeUtil::treeToListWithLevel($tree);
foreach ($nodes as $i => $v) {
$chain = TreeUtil::nodesChain($nodes, $v['id']);
$nodes[$i]['_fullTitle'] = join('-', array_map(function ($item) {
return $item['title'];
}, $chain));
}
return $nodes;
}
public static function categoryChainWithItems($categoryId)
{
$records = self::all();
return TreeUtil::nodesChainWithItems($records, $categoryId);
}
public static function get($id)
{
foreach (self::all() as $one) {
if ($one['id'] == $id) {
return $one;
}
}
return null;
}
public static function listChildCategories($categoryId)
{
$records = self::all();
$records = array_filter($records, function ($item) use ($categoryId) {
return $item['pid'] == $categoryId;
});
return array_values($records);
}
public static function childrenIds($categoryId)
{
if ($categoryId <= 0) {
return [];
}
$nodes = self::all();
return array_merge([$categoryId], TreeUtil::nodesChildrenIds($nodes, $categoryId));
}
public static function updateCount($categoryIds)
{
if (!is_array($categoryIds)) {
$categoryIds = [$categoryIds];
}
$categoryIds = array_unique($categoryIds);
foreach ($categoryIds as $catId) {
$chapter = self::get($catId);
if (empty($chapter)) {
continue;
}
$tree = self::categoryTree();
$chain = TreeUtil::treeChain($tree, $catId);
foreach ($chain as $item) {
$ids = TreeUtil::treeNodeChildrenIds($tree, $item['id']);
if (empty($ids)) {
$blogCount = 0;
} else {
$blogCount = Blog::published()->whereIn('categoryId', $ids)->count();
}
ModelUtil::update(BlogCategory::class, $item['id'], [
'blogCount' => $blogCount,
]);
}
}
self::clearCache();
}
/**
* 获取所有二级分类的默认标签
* @param int $limit 限制数量,0为不限制
* @return array 标签→数量映射
*/
public static function getSubcategoryTags($limit = 0)
{
$tagCounts = Cache::rememberForever('Blog:SubcategoryTags', function () {
// 获取所有二级分类(pid > 0)
$subcategories = BlogCategory::where('pid', '>', 0)->get(['id', 'title', 'default_tags'])->toArray();
$tagCounts = [];
foreach ($subcategories as $category) {
if (empty($category['default_tags'])) {
continue;
}
// 解析标签(支持JSON和逗号分隔两种格式)
$tags = self::parseTagsString($category['default_tags']);
foreach ($tags as $tag) {
$tag = trim($tag);
if (empty($tag)) {
continue;
}
// 统计每个标签对应的博客数量
if (!isset($tagCounts[$tag])) {
$tagCounts[$tag] = self::getTagBlogCount($tag);
}
}
}
// 按博客数量降序排序
arsort($tagCounts);
return $tagCounts;
});
// 应用限制
if ($limit > 0) {
$tagCounts = array_slice($tagCounts, 0, $limit, true);
}
return $tagCounts;
}
/**
* 解析标签字符串,支持JSON和逗号分隔两种格式
* @param string $tagsString
* @return array
*/
private static function parseTagsString($tagsString)
{
if (empty($tagsString)) {
return [];
}
// 尝试解析JSON格式
if (strpos($tagsString, '[') === 0 || strpos($tagsString, '["') === 0) {
$decoded = json_decode($tagsString, true);
if (is_array($decoded)) {
return array_filter(array_map('trim', $decoded));
}
}
// 按逗号分隔
return array_filter(array_map('trim', explode(',', $tagsString)));
}
/**
* 获取标签对应的博客数量
* @param string $tag
* @return int
*/
private static function getTagBlogCount($tag)
{
// 查询包含该标签的博客数量
return Blog::published()
->where('tag', 'like', '%' . $tag . '%')
->count();
}
/**
* 清除二级分类标签缓存
*/
public static function clearSubcategoryTagsCache()
{
Cache::forget('Blog:SubcategoryTags');
}
}