]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - application/front/controller/visitor/TagCloudController.php
Merge pull request #1525 from ArthurHoaro/feature/rest-api-bookmark-dates
[github/shaarli/Shaarli.git] / application / front / controller / visitor / TagCloudController.php
CommitLineData
c266a89d
A
1<?php
2
3declare(strict_types=1);
4
2899ebb5 5namespace Shaarli\Front\Controller\Visitor;
c266a89d
A
6
7use Slim\Http\Request;
8use 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 15class 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 68
72fbbcd6
A
69 $tagsUrl = [];
70 foreach ($tags as $tag => $value) {
71 $tagsUrl[escape($tag)] = urlencode((string) $tag);
72 }
73
c266a89d 74 $searchTags = implode(' ', escape($filteringTags));
72fbbcd6 75 $searchTagsUrl = urlencode(implode(' ', $filteringTags));
c266a89d 76 $data = [
72fbbcd6
A
77 'search_tags' => escape($searchTags),
78 'search_tags_url' => $searchTagsUrl,
79 'tags' => escape($tags),
80 'tags_url' => $tagsUrl,
c266a89d 81 ];
9fbc4229
A
82 $this->executePageHooks('render_tag' . $type, $data, 'tag.' . $type);
83 $this->assignAllView($data);
c266a89d
A
84
85 $searchTags = !empty($searchTags) ? $searchTags .' - ' : '';
86 $this->assignView(
87 'pagetitle',
60ae2412 88 $searchTags . t('Tag '. $type) .' - '. $this->container->conf->get('general.title', 'Shaarli')
c266a89d
A
89 );
90
9fbc4229 91 return $response->write($this->render('tag.' . $type));
c266a89d
A
92 }
93
60ae2412
A
94 /**
95 * Format the tags array for the tag cloud template.
96 *
97 * @param array<string, int> $tags List of tags as key with count as value
98 *
99 * @return mixed[] List of tags as key, with count and expected font size in a subarray
100 */
3772298e
A
101 protected function formatTagsForCloud(array $tags): array
102 {
103 // We sort tags alphabetically, then choose a font size according to count.
104 // First, find max value.
105 $maxCount = count($tags) > 0 ? max($tags) : 0;
106 $logMaxCount = $maxCount > 1 ? log($maxCount, 30) : 1;
107 $tagList = [];
108 foreach ($tags as $key => $value) {
109 // Tag font size scaling:
110 // default 15 and 30 logarithm bases affect scaling,
111 // 2.2 and 0.8 are arbitrary font sizes in em.
112 $size = log($value, 15) / $logMaxCount * 2.2 + 0.8;
113 $tagList[$key] = [
114 'count' => $value,
115 'size' => number_format($size, 2, '.', ''),
116 ];
117 }
118
119 return $tagList;
120 }
c266a89d 121}