]>
Commit | Line | Data |
---|---|---|
c266a89d A |
1 | <?php |
2 | ||
3 | declare(strict_types=1); | |
4 | ||
2899ebb5 | 5 | namespace Shaarli\Front\Controller\Visitor; |
c266a89d A |
6 | |
7 | use Slim\Http\Request; | |
8 | use Slim\Http\Response; | |
9 | ||
10 | /** | |
11 | * Class TagCloud | |
12 | * | |
60ae2412 | 13 | * Slim controller used to render the tag cloud and tag list pages. |
c266a89d | 14 | */ |
2899ebb5 | 15 | class TagCloudController extends ShaarliVisitorController |
c266a89d | 16 | { |
60ae2412 A |
17 | protected const TYPE_CLOUD = 'cloud'; |
18 | protected const TYPE_LIST = 'list'; | |
19 | ||
3772298e A |
20 | /** |
21 | * Display the tag cloud through the template engine. | |
22 | * This controller a few filters: | |
23 | * - Visibility stored in the session for logged in users | |
24 | * - `searchtags` query parameter: will return tags associated with filter in at least one bookmark | |
25 | */ | |
26 | public function cloud(Request $request, Response $response): Response | |
60ae2412 A |
27 | { |
28 | return $this->processRequest(static::TYPE_CLOUD, $request, $response); | |
29 | } | |
30 | ||
31 | /** | |
32 | * Display the tag list through the template engine. | |
33 | * This controller a few filters: | |
34 | * - Visibility stored in the session for logged in users | |
35 | * - `searchtags` query parameter: will return tags associated with filter in at least one bookmark | |
36 | * - `sort` query parameters: | |
37 | * + `usage` (default): most used tags first | |
38 | * + `alpha`: alphabetical order | |
39 | */ | |
40 | public function list(Request $request, Response $response): Response | |
41 | { | |
42 | return $this->processRequest(static::TYPE_LIST, $request, $response); | |
43 | } | |
44 | ||
45 | /** | |
46 | * Process the request for both tag cloud and tag list endpoints. | |
47 | */ | |
48 | protected function processRequest(string $type, Request $request, Response $response): Response | |
c266a89d A |
49 | { |
50 | if ($this->container->loginManager->isLoggedIn() === true) { | |
51 | $visibility = $this->container->sessionManager->getSessionParameter('visibility'); | |
52 | } | |
53 | ||
60ae2412 | 54 | $sort = $request->getQueryParam('sort'); |
c266a89d A |
55 | $searchTags = $request->getQueryParam('searchtags'); |
56 | $filteringTags = $searchTags !== null ? explode(' ', $searchTags) : []; | |
57 | ||
58 | $tags = $this->container->bookmarkService->bookmarksCountPerTag($filteringTags, $visibility ?? null); | |
59 | ||
60ae2412 A |
60 | if (static::TYPE_CLOUD === $type || 'alpha' === $sort) { |
61 | // TODO: the sorting should be handled by bookmarkService instead of the controller | |
62 | alphabetical_sort($tags, false, true); | |
63 | } | |
c266a89d | 64 | |
60ae2412 A |
65 | if (static::TYPE_CLOUD === $type) { |
66 | $tags = $this->formatTagsForCloud($tags); | |
67 | } | |
c266a89d A |
68 | |
69 | $searchTags = implode(' ', escape($filteringTags)); | |
70 | $data = [ | |
71 | 'search_tags' => $searchTags, | |
60ae2412 | 72 | 'tags' => $tags, |
c266a89d | 73 | ]; |
9fbc4229 A |
74 | $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type); |
75 | $this->assignAllView($data); | |
c266a89d A |
76 | |
77 | $searchTags = !empty($searchTags) ? $searchTags .' - ' : ''; | |
78 | $this->assignView( | |
79 | 'pagetitle', | |
60ae2412 | 80 | $searchTags . t('Tag '. $type) .' - '. $this->container->conf->get('general.title', 'Shaarli') |
c266a89d A |
81 | ); |
82 | ||
9fbc4229 | 83 | return $response->write($this->render('tag.' . $type)); |
c266a89d A |
84 | } |
85 | ||
60ae2412 A |
86 | /** |
87 | * Format the tags array for the tag cloud template. | |
88 | * | |
89 | * @param array<string, int> $tags List of tags as key with count as value | |
90 | * | |
91 | * @return mixed[] List of tags as key, with count and expected font size in a subarray | |
92 | */ | |
3772298e A |
93 | protected function formatTagsForCloud(array $tags): array |
94 | { | |
95 | // We sort tags alphabetically, then choose a font size according to count. | |
96 | // First, find max value. | |
97 | $maxCount = count($tags) > 0 ? max($tags) : 0; | |
98 | $logMaxCount = $maxCount > 1 ? log($maxCount, 30) : 1; | |
99 | $tagList = []; | |
100 | foreach ($tags as $key => $value) { | |
101 | // Tag font size scaling: | |
102 | // default 15 and 30 logarithm bases affect scaling, | |
103 | // 2.2 and 0.8 are arbitrary font sizes in em. | |
104 | $size = log($value, 15) / $logMaxCount * 2.2 + 0.8; | |
105 | $tagList[$key] = [ | |
106 | 'count' => $value, | |
107 | 'size' => number_format($size, 2, '.', ''), | |
108 | ]; | |
109 | } | |
110 | ||
111 | return $tagList; | |
112 | } | |
c266a89d | 113 | } |