Skip to content

Commit 59e3e61

Browse files
authored
Merge pull request #6256 from WoltLab/6.2-TagCloudCache-to-TolerantCache
Migrate `TagCache` and `TypedTagCache` to TolerantCache
2 parents 1451992 + 3b46770 commit 59e3e61

5 files changed

Lines changed: 154 additions & 18 deletions

File tree

wcfsetup/install/files/lib/system/cache/builder/TagCloudCacheBuilder.class.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* @author Marcel Werk
1515
* @copyright 2001-2019 WoltLab GmbH
1616
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
17+
*
18+
* @deprecated 6.2 use `TagCloudCache` instead
1719
*/
1820
class TagCloudCacheBuilder extends AbstractCacheBuilder
1921
{

wcfsetup/install/files/lib/system/cache/builder/TypedTagCloudCacheBuilder.class.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@
22

33
namespace wcf\system\cache\builder;
44

5+
use wcf\system\cache\tolerant\TagCloudCache;
6+
57
/**
68
* Caches the typed tag cloud.
79
*
810
* @author Marcel Werk
911
* @copyright 2001-2019 WoltLab GmbH
1012
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
13+
*
14+
* @deprecated 6.2 use `TagCloudCache` instead
1115
*/
12-
class TypedTagCloudCacheBuilder extends TagCloudCacheBuilder
16+
class TypedTagCloudCacheBuilder extends AbstractLegacyCacheBuilder
1317
{
14-
/**
15-
* @inheritDoc
16-
*/
17-
protected function rebuild(array $parameters)
18+
#[\Override]
19+
public function reset(array $parameters = [])
1820
{
19-
$this->objectTypeIDs = $parameters['objectTypeIDs'];
20-
$this->languageIDs = $parameters['languageIDs'];
21-
22-
// get tags
23-
$this->getTags();
21+
(new TagCloudCache($parameters["objectTypeIDs"], $parameters["languageIDs"]))->rebuild();
22+
}
2423

25-
return $this->tags;
24+
#[\Override]
25+
protected function rebuild(array $parameters): array
26+
{
27+
return (new TagCloudCache($parameters["objectTypeIDs"], $parameters["languageIDs"]))->getCache();
2628
}
2729
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace wcf\system\cache\tolerant;
4+
5+
use wcf\data\tag\Tag;
6+
use wcf\data\tag\TagCloudTag;
7+
use wcf\system\database\util\PreparedStatementConditionBuilder;
8+
use wcf\system\WCF;
9+
10+
/**
11+
* Caches the tag cloud.
12+
*
13+
* @author Olaf Braun
14+
* @copyright 2001-2025 WoltLab GmbH
15+
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16+
* @since 6.2
17+
*
18+
* @extends AbstractTolerantCache<array<string, TagCloudTag>>
19+
*/
20+
class TagCloudCache extends AbstractTolerantCache
21+
{
22+
public function __construct(
23+
/** @var int[] */
24+
public readonly array $objectTypeIDs,
25+
/** @var int[] */
26+
public readonly array $languageIDs = [],
27+
) {
28+
}
29+
30+
private static function sortTagsByCounter(TagCloudTag $tagA, TagCloudTag $tagB): int
31+
{
32+
return $tagB->counter <=> $tagA->counter;
33+
}
34+
35+
#[\Override]
36+
public function getLifetime(): int
37+
{
38+
return 3_600;
39+
}
40+
41+
#[\Override]
42+
protected function rebuildCacheData(): array
43+
{
44+
if ($this->objectTypeIDs === []) {
45+
return [];
46+
}
47+
48+
return $this->fetchTags($this->fetchTagIDs());
49+
}
50+
51+
/**
52+
* @param array<int, int> $tagIDs
53+
* @return array<string, TagCloudTag>
54+
*/
55+
protected function fetchTags(array $tagIDs): array
56+
{
57+
if ($tagIDs === []) {
58+
return [];
59+
}
60+
61+
$conditionBuilder = new PreparedStatementConditionBuilder();
62+
$conditionBuilder->add('tagID IN (?)', [\array_keys($tagIDs)]);
63+
$sql = "SELECT *
64+
FROM wcf1_tag
65+
" . $conditionBuilder;
66+
$statement = WCF::getDB()->prepare($sql);
67+
$statement->execute($conditionBuilder->getParameters());
68+
69+
$tags = [];
70+
while ($row = $statement->fetchArray()) {
71+
$row['counter'] = $tagIDs[$row['tagID']];
72+
$tags[$row['name']] = new TagCloudTag(new Tag(null, $row));
73+
}
74+
75+
\uasort($tags, self::sortTagsByCounter(...));
76+
77+
return $tags;
78+
}
79+
80+
/**
81+
* @return array<int, int>
82+
*/
83+
protected function fetchTagIDs(): array
84+
{
85+
$conditionBuilder = $this->getConditionBuilder();
86+
87+
$sql = "SELECT tag.tagID, COUNT(*) AS counter
88+
FROM wcf1_tag_to_object object
89+
INNER JOIN wcf1_tag tag
90+
ON tag.tagID = object.tagID
91+
" . $this->getJoin() . "
92+
" . $conditionBuilder . "
93+
GROUP BY tag.tagID
94+
ORDER BY counter DESC";
95+
$statement = WCF::getDB()->prepare($sql, $this->getLimit());
96+
$statement->execute($conditionBuilder->getParameters());
97+
98+
return $statement->fetchMap('tagID', 'counter');
99+
}
100+
101+
protected function getConditionBuilder(): PreparedStatementConditionBuilder
102+
{
103+
$conditionBuilder = new PreparedStatementConditionBuilder();
104+
$conditionBuilder->add('object.objectTypeID IN (?)', [$this->objectTypeIDs]);
105+
106+
if ($this->languageIDs !== []) {
107+
$conditionBuilder->add('tag.languageID IN (?)', [$this->languageIDs]);
108+
}
109+
110+
return $conditionBuilder;
111+
}
112+
113+
/**
114+
* Returns the extra join statement.
115+
*/
116+
protected function getJoin(): string
117+
{
118+
return "";
119+
}
120+
121+
/**
122+
* Returns the number of tags to fetch.
123+
*/
124+
protected function getLimit(): int
125+
{
126+
return 500;
127+
}
128+
}

wcfsetup/install/files/lib/system/tagging/TagCloud.class.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace wcf\system\tagging;
44

5+
use wcf\data\object\type\ObjectType;
6+
use wcf\data\object\type\ObjectTypeCache;
57
use wcf\data\tag\TagCloudTag;
6-
use wcf\system\cache\builder\TagCloudCacheBuilder;
8+
use wcf\system\cache\tolerant\TagCloudCache;
79
use wcf\system\language\LanguageFactory;
810

911
/**
@@ -62,7 +64,12 @@ public function __construct(array $languageIDs = [])
6264
*/
6365
protected function loadCache()
6466
{
65-
$this->tags = TagCloudCacheBuilder::getInstance()->getData($this->languageIDs);
67+
$objectTypeIDs = \array_map(
68+
static fn(ObjectType $objectType) => $objectType->objectTypeID,
69+
ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.tagging.taggableObject')
70+
);
71+
72+
$this->tags = (new TagCloudCache($objectTypeIDs, $this->languageIDs))->getCache();
6673
}
6774

6875
/**

wcfsetup/install/files/lib/system/tagging/TypedTagCloud.class.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace wcf\system\tagging;
44

55
use wcf\data\object\type\ObjectTypeCache;
6-
use wcf\system\cache\builder\TypedTagCloudCacheBuilder;
6+
use wcf\system\cache\tolerant\TagCloudCache;
77

88
/**
99
* This class provides the function to filter the tag cloud by object types.
@@ -42,9 +42,6 @@ public function __construct($objectType, array $languageIDs = [])
4242
*/
4343
protected function loadCache()
4444
{
45-
$this->tags = TypedTagCloudCacheBuilder::getInstance()->getData([
46-
'languageIDs' => $this->languageIDs,
47-
'objectTypeIDs' => $this->objectTypeIDs,
48-
]);
45+
$this->tags = (new TagCloudCache($this->objectTypeIDs, $this->languageIDs))->getCache();
4946
}
5047
}

0 commit comments

Comments
 (0)