xref: /plugin/struct/meta/AggregationCloud.php (revision d6d97f6064c3b0f90310be8341edc9585520ee54)
1fa04b28cSMichael Grosse<?php
25282d027SMichael Grosse
3fa04b28cSMichael Grossenamespace dokuwiki\plugin\struct\meta;
45282d027SMichael Grosse
5*d6d97f60SAnna Dabrowskaclass AggregationCloud
6*d6d97f60SAnna Dabrowska{
75282d027SMichael Grosse
8fa04b28cSMichael Grosse    /**
9fa04b28cSMichael Grosse     * @var string the page id of the page this is rendered to
10fa04b28cSMichael Grosse     */
11fa04b28cSMichael Grosse    protected $id;
125282d027SMichael Grosse
13fa04b28cSMichael Grosse    /**
14fa04b28cSMichael Grosse     * @var string the Type of renderer used
15fa04b28cSMichael Grosse     */
16fa04b28cSMichael Grosse    protected $mode;
175282d027SMichael Grosse
18fa04b28cSMichael Grosse    /**
19fa04b28cSMichael Grosse     * @var \Doku_Renderer the DokuWiki renderer used to create the output
20fa04b28cSMichael Grosse     */
21fa04b28cSMichael Grosse    protected $renderer;
225282d027SMichael Grosse
23fa04b28cSMichael Grosse    /**
24fa04b28cSMichael Grosse     * @var SearchConfig the configured search - gives access to columns etc.
25fa04b28cSMichael Grosse     */
26fa04b28cSMichael Grosse    protected $searchConfig;
275282d027SMichael Grosse
28fa04b28cSMichael Grosse    /**
29fa04b28cSMichael Grosse     * @var Column[] the list of columns to be displayed
30fa04b28cSMichael Grosse     */
31fa04b28cSMichael Grosse    protected $columns;
325282d027SMichael Grosse
33fa04b28cSMichael Grosse    /**
34fa04b28cSMichael Grosse     * @var  Value[][] the search result
35fa04b28cSMichael Grosse     */
36fa04b28cSMichael Grosse    protected $result;
375282d027SMichael Grosse
38fa04b28cSMichael Grosse    /**
39fa04b28cSMichael Grosse     * @var int number of all results
40fa04b28cSMichael Grosse     */
41fa04b28cSMichael Grosse    protected $resultCount;
425282d027SMichael Grosse
43fa04b28cSMichael Grosse    /**
44fa04b28cSMichael Grosse     * Initialize the Aggregation renderer and executes the search
45fa04b28cSMichael Grosse     *
46fa04b28cSMichael Grosse     * You need to call @see render() on the resulting object.
47fa04b28cSMichael Grosse     *
48fa04b28cSMichael Grosse     * @param string $id
49fa04b28cSMichael Grosse     * @param string $mode
50fa04b28cSMichael Grosse     * @param \Doku_Renderer $renderer
51fa04b28cSMichael Grosse     * @param SearchConfig $searchConfig
52fa04b28cSMichael Grosse     */
53*d6d97f60SAnna Dabrowska    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig)
54*d6d97f60SAnna Dabrowska    {
55fa04b28cSMichael Grosse        $this->id = $id;
56fa04b28cSMichael Grosse        $this->mode = $mode;
57fa04b28cSMichael Grosse        $this->renderer = $renderer;
58fa04b28cSMichael Grosse        $this->searchConfig = $searchConfig;
59fa04b28cSMichael Grosse        $this->data = $searchConfig->getConf();
60fa04b28cSMichael Grosse        $this->columns = $searchConfig->getColumns();
610699ff47SMichael Grosse        $this->result = $this->searchConfig->execute();
620699ff47SMichael Grosse        $this->resultCount = $this->searchConfig->getCount();
63aafac1c1SMichael Grosse
64aafac1c1SMichael Grosse        $this->max = $this->result[0]['count'];
65aafac1c1SMichael Grosse        $this->min = end($this->result)['count'];
66fa04b28cSMichael Grosse    }
67fa04b28cSMichael Grosse
68fa04b28cSMichael Grosse    /**
699e7e1786SMichael Grosse     * Create the cloud on the renderer
70fa04b28cSMichael Grosse     */
71*d6d97f60SAnna Dabrowska    public function render()
72*d6d97f60SAnna Dabrowska    {
738b4531cfSMichael Grosse
748b4531cfSMichael Grosse        $this->sortResults();
758b4531cfSMichael Grosse
76fa04b28cSMichael Grosse        $this->startScope();
77c7dd6b6aSMichael Grosse        $this->startList();
78fa04b28cSMichael Grosse        foreach ($this->result as $result) {
7933bd00e9SMichael Grosse            $this->renderTag($result);
80fa04b28cSMichael Grosse        }
81c7dd6b6aSMichael Grosse        $this->finishList();
82fa04b28cSMichael Grosse        $this->finishScope();
83fa04b28cSMichael Grosse        return;
84fa04b28cSMichael Grosse    }
855282d027SMichael Grosse
86fa04b28cSMichael Grosse    /**
87fa04b28cSMichael Grosse     * Adds additional info to document and renderer in XHTML mode
88fa04b28cSMichael Grosse     *
89fa04b28cSMichael Grosse     * @see finishScope()
90fa04b28cSMichael Grosse     */
91*d6d97f60SAnna Dabrowska    protected function startScope()
92*d6d97f60SAnna Dabrowska    {
93fa04b28cSMichael Grosse        // wrapping div
94fa04b28cSMichael Grosse        if ($this->mode != 'xhtml') return;
95be2ae900SMichael Grosse        $this->renderer->doc .= "<div class=\"structcloud\">";
96fa04b28cSMichael Grosse    }
975282d027SMichael Grosse
98fa04b28cSMichael Grosse    /**
99fa04b28cSMichael Grosse     * Closes the table and anything opened in startScope()
100fa04b28cSMichael Grosse     *
101fa04b28cSMichael Grosse     * @see startScope()
102fa04b28cSMichael Grosse     */
103*d6d97f60SAnna Dabrowska    protected function finishScope()
104*d6d97f60SAnna Dabrowska    {
105fa04b28cSMichael Grosse        // wrapping div
106fa04b28cSMichael Grosse        if ($this->mode != 'xhtml') return;
107fa04b28cSMichael Grosse        $this->renderer->doc .= '</div>';
108fa04b28cSMichael Grosse    }
109aafac1c1SMichael Grosse
11033bd00e9SMichael Grosse    /**
11133bd00e9SMichael Grosse     * Render a tag of the cloud
11233bd00e9SMichael Grosse     *
11333bd00e9SMichael Grosse     * @param ['tag' => Value, 'count' => int] $result
11433bd00e9SMichael Grosse     */
115*d6d97f60SAnna Dabrowska    protected function renderTag($result)
116*d6d97f60SAnna Dabrowska    {
117fa04b28cSMichael Grosse        /**
118fa04b28cSMichael Grosse         * @var Value $value
119fa04b28cSMichael Grosse         */
120fa04b28cSMichael Grosse        $value = $result['tag'];
121fa04b28cSMichael Grosse        $count = $result['count'];
122fa04b28cSMichael Grosse        if ($value->isEmpty()) {
123fa04b28cSMichael Grosse            return;
124fa04b28cSMichael Grosse        }
125fa04b28cSMichael Grosse
126c7dd6b6aSMichael Grosse        $type = strtolower($value->getColumn()->getType()->getClass());
127c7dd6b6aSMichael Grosse        $weight = $this->getWeight($count, $this->min, $this->max);
1288e54e6f4SMichael Grosse
12985edf4f2SMichael Grosse        if (!empty($this->data['target'])) {
13085edf4f2SMichael Grosse            $target = $this->data['target'];
13185edf4f2SMichael Grosse        } else {
13285edf4f2SMichael Grosse            global $INFO;
13385edf4f2SMichael Grosse            $target = $INFO['id'];
13485edf4f2SMichael Grosse        }
1358e54e6f4SMichael Grosse
136ce8676aeSMichael Grosse        $tagValue = $value->getDisplayValue();
137ce8676aeSMichael Grosse        if (is_array($tagValue)) {
138ce8676aeSMichael Grosse            $tagValue = $tagValue[0];
139fa04b28cSMichael Grosse        }
14057775e30SSzymon Olewniczak        $key = $value->getColumn()->getFullQualifiedLabel() . '=';
14143d76406SSzymon Olewniczak        $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue);
142c7dd6b6aSMichael Grosse
143da11327aSMichael Grosse        $this->renderer->listitem_open(1);
144da11327aSMichael Grosse        $this->renderer->listcontent_open();
145da11327aSMichael Grosse
146262c0fc6SMichael Grosse        if ($this->mode == 'xhtml') {
147c7dd6b6aSMichael Grosse            $this->renderer->doc .= "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>";
1488e54e6f4SMichael Grosse        }
1498e54e6f4SMichael Grosse
150262c0fc6SMichael Grosse        $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight);
151262c0fc6SMichael Grosse
152262c0fc6SMichael Grosse        if ($this->mode == 'xhtml') {
153c7dd6b6aSMichael Grosse            $this->renderer->doc .= '</div>';
154fa04b28cSMichael Grosse        }
155da11327aSMichael Grosse
156da11327aSMichael Grosse        $this->renderer->listcontent_close();
157da11327aSMichael Grosse        $this->renderer->listitem_close();
158262c0fc6SMichael Grosse    }
159aafac1c1SMichael Grosse
160aafac1c1SMichael Grosse    /**
161aafac1c1SMichael Grosse     * This interpolates the weight between 70 and 150 based on $min, $max and $current
162aafac1c1SMichael Grosse     *
163aafac1c1SMichael Grosse     * @param int $current
164aafac1c1SMichael Grosse     * @param int $min
165aafac1c1SMichael Grosse     * @param int $max
1668e54e6f4SMichael Grosse     * @return int
167aafac1c1SMichael Grosse     */
168*d6d97f60SAnna Dabrowska    protected function getWeight($current, $min, $max)
169*d6d97f60SAnna Dabrowska    {
170aafac1c1SMichael Grosse        if ($min == $max) {
171aafac1c1SMichael Grosse            return 100;
172aafac1c1SMichael Grosse        }
1738e54e6f4SMichael Grosse        return round(($current - $min) / ($max - $min) * 80 + 70);
174aafac1c1SMichael Grosse    }
1758b4531cfSMichael Grosse
1768b4531cfSMichael Grosse    /**
1778b4531cfSMichael Grosse     * Sort the list of results
1788b4531cfSMichael Grosse     */
179*d6d97f60SAnna Dabrowska    protected function sortResults()
180*d6d97f60SAnna Dabrowska    {
1818b4531cfSMichael Grosse        usort($this->result, function ($a, $b) {
182d560ea13SMichael Grosse            $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']);
183d560ea13SMichael Grosse            $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']);
184d560ea13SMichael Grosse            if ($asort < $bsort) {
1858b4531cfSMichael Grosse                return -1;
1868b4531cfSMichael Grosse            }
187d560ea13SMichael Grosse            if ($asort > $bsort) {
1888b4531cfSMichael Grosse                return 1;
1898b4531cfSMichael Grosse            }
1908b4531cfSMichael Grosse            return 0;
1918b4531cfSMichael Grosse        });
1928b4531cfSMichael Grosse    }
1938b4531cfSMichael Grosse
194*d6d97f60SAnna Dabrowska    protected function startList()
195*d6d97f60SAnna Dabrowska    {
196c7dd6b6aSMichael Grosse        $this->renderer->listu_open();
197c7dd6b6aSMichael Grosse    }
198c7dd6b6aSMichael Grosse
199*d6d97f60SAnna Dabrowska    protected function finishList()
200*d6d97f60SAnna Dabrowska    {
201c7dd6b6aSMichael Grosse        $this->renderer->listu_close();
202c7dd6b6aSMichael Grosse    }
203fa04b28cSMichael Grosse}
204