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