1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5class AggregationCloud extends Aggregation
6{
7    /** @var int */
8    protected $max;
9
10    /** @var int */
11    protected $min;
12
13    /** @inheritdoc */
14    public function render($showNotFound = false)
15    {
16
17        if ($this->mode !== 'xhtml') return;
18
19        $rows = $this->searchConfig->getRows();
20        $this->max = $rows[0]['count'];
21        $this->min = end($rows)['count'];
22
23        $this->sortResults($rows);
24        $this->startList();
25        foreach ($rows as $result) {
26            $this->renderTag($result);
27        }
28        $this->finishList();
29    }
30
31    /**
32     * Render a tag of the cloud
33     *
34     * @param ['tag' => Value, 'count' => int] $result
35     */
36    protected function renderTag($result)
37    {
38        /**
39         * @var Value $value
40         */
41        $value = $result['tag'];
42        $count = $result['count'];
43        if ($value->isEmpty()) {
44            return;
45        }
46
47        $type = strtolower($value->getColumn()->getType()->getClass());
48        $weight = $this->getWeight($count, $this->min, $this->max);
49
50        if (!empty($this->data['target'])) {
51            $target = $this->data['target'];
52        } else {
53            global $INFO;
54            $target = $INFO['id'];
55        }
56
57        $tagValue = $value->getDisplayValue();
58        if (is_array($tagValue)) {
59            $tagValue = $tagValue[0];
60        }
61        $key = $value->getColumn()->getFullQualifiedLabel() . '=';
62        $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue);
63
64        $this->renderer->listitem_open(1);
65        $this->renderer->listcontent_open();
66
67        if ($this->mode == 'xhtml') {
68            $this->renderer->doc .=
69                "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>";
70        }
71
72        $showCount = $this->searchConfig->getConf()['summarize'] ? $count : 0;
73        $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight, $showCount);
74
75        if ($this->mode == 'xhtml') {
76            $this->renderer->doc .= '</div>';
77        }
78
79        $this->renderer->listcontent_close();
80        $this->renderer->listitem_close();
81    }
82
83    /**
84     * This interpolates the weight between 70 and 150 based on $min, $max and $current
85     *
86     * @param int $current
87     * @param int $min
88     * @param int $max
89     * @return int
90     */
91    protected function getWeight($current, $min, $max)
92    {
93        if ($min == $max) {
94            return 100;
95        }
96        return round(($current - $min) / ($max - $min) * 80 + 70);
97    }
98
99    /**
100     * Sort the list of results
101     */
102    protected function sortResults(&$rows)
103    {
104        usort($rows, function ($a, $b) {
105            $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']);
106            $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']);
107            if ($asort < $bsort) {
108                return -1;
109            }
110            if ($asort > $bsort) {
111                return 1;
112            }
113            return 0;
114        });
115    }
116
117    protected function startList()
118    {
119        $this->renderer->listu_open();
120    }
121
122    protected function finishList()
123    {
124        $this->renderer->listu_close();
125    }
126}
127