xref: /plugin/struct/meta/AggregationCloud.php (revision d90aa848684950ae06490f12279278db183f4fa5)
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->startScope();
36        $this->startList();
37        foreach ($this->result as $result) {
38            $this->renderTag($result);
39        }
40        $this->finishList();
41        $this->finishScope();
42    }
43
44    /**
45     * Adds additional info to document and renderer in XHTML mode
46     *
47     * @see finishScope()
48     */
49    protected function startScope()
50    {
51        // wrapping div
52        if ($this->mode != 'xhtml') return;
53        $this->renderer->doc .= "<div class=\"structcloud\">";
54    }
55
56    /**
57     * Closes the table and anything opened in startScope()
58     *
59     * @see startScope()
60     */
61    protected function finishScope()
62    {
63        // wrapping div
64        if ($this->mode != 'xhtml') return;
65        $this->renderer->doc .= '</div>';
66    }
67
68    /**
69     * Render a tag of the cloud
70     *
71     * @param ['tag' => Value, 'count' => int] $result
72     */
73    protected function renderTag($result)
74    {
75        /**
76         * @var Value $value
77         */
78        $value = $result['tag'];
79        $count = $result['count'];
80        if ($value->isEmpty()) {
81            return;
82        }
83
84        $type = strtolower($value->getColumn()->getType()->getClass());
85        $weight = $this->getWeight($count, $this->min, $this->max);
86
87        if (!empty($this->data['target'])) {
88            $target = $this->data['target'];
89        } else {
90            global $INFO;
91            $target = $INFO['id'];
92        }
93
94        $tagValue = $value->getDisplayValue();
95        if (is_array($tagValue)) {
96            $tagValue = $tagValue[0];
97        }
98        $key = $value->getColumn()->getFullQualifiedLabel() . '=';
99        $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue);
100
101        $this->renderer->listitem_open(1);
102        $this->renderer->listcontent_open();
103
104        if ($this->mode == 'xhtml') {
105            $this->renderer->doc .=
106                "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>";
107        }
108
109        $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight);
110
111        if ($this->mode == 'xhtml') {
112            $this->renderer->doc .= '</div>';
113        }
114
115        $this->renderer->listcontent_close();
116        $this->renderer->listitem_close();
117    }
118
119    /**
120     * This interpolates the weight between 70 and 150 based on $min, $max and $current
121     *
122     * @param int $current
123     * @param int $min
124     * @param int $max
125     * @return int
126     */
127    protected function getWeight($current, $min, $max)
128    {
129        if ($min == $max) {
130            return 100;
131        }
132        return round(($current - $min) / ($max - $min) * 80 + 70);
133    }
134
135    /**
136     * Sort the list of results
137     */
138    protected function sortResults()
139    {
140        usort($this->result, function ($a, $b) {
141            $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']);
142            $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']);
143            if ($asort < $bsort) {
144                return -1;
145            }
146            if ($asort > $bsort) {
147                return 1;
148            }
149            return 0;
150        });
151    }
152
153    protected function startList()
154    {
155        $this->renderer->listu_open();
156    }
157
158    protected function finishList()
159    {
160        $this->renderer->listu_close();
161    }
162}
163