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