xref: /plugin/struct/meta/AggregationCloud.php (revision 0549dcc5bc88d4f9d923acdd09931d8d51be7097)
1fa04b28cSMichael Grosse<?php
25282d027SMichael Grosse
3fa04b28cSMichael Grossenamespace dokuwiki\plugin\struct\meta;
45282d027SMichael Grosse
5d6d97f60SAnna Dabrowskaclass AggregationCloud
6d6d97f60SAnna Dabrowska{
7fa04b28cSMichael Grosse    /**
8fa04b28cSMichael Grosse     * @var string the page id of the page this is rendered to
9fa04b28cSMichael Grosse     */
10fa04b28cSMichael Grosse    protected $id;
115282d027SMichael Grosse
12fa04b28cSMichael Grosse    /**
13fa04b28cSMichael Grosse     * @var string the Type of renderer used
14fa04b28cSMichael Grosse     */
15fa04b28cSMichael Grosse    protected $mode;
165282d027SMichael Grosse
17fa04b28cSMichael Grosse    /**
18fa04b28cSMichael Grosse     * @var \Doku_Renderer the DokuWiki renderer used to create the output
19fa04b28cSMichael Grosse     */
20fa04b28cSMichael Grosse    protected $renderer;
215282d027SMichael Grosse
22fa04b28cSMichael Grosse    /**
23fa04b28cSMichael Grosse     * @var SearchConfig the configured search - gives access to columns etc.
24fa04b28cSMichael Grosse     */
25fa04b28cSMichael Grosse    protected $searchConfig;
265282d027SMichael Grosse
27fa04b28cSMichael Grosse    /**
28fa04b28cSMichael Grosse     * @var Column[] the list of columns to be displayed
29fa04b28cSMichael Grosse     */
30fa04b28cSMichael Grosse    protected $columns;
315282d027SMichael Grosse
32fa04b28cSMichael Grosse    /**
33fa04b28cSMichael Grosse     * @var  Value[][] the search result
34fa04b28cSMichael Grosse     */
35fa04b28cSMichael Grosse    protected $result;
365282d027SMichael Grosse
37fa04b28cSMichael Grosse    /**
38fa04b28cSMichael Grosse     * @var int number of all results
39fa04b28cSMichael Grosse     */
40fa04b28cSMichael Grosse    protected $resultCount;
415282d027SMichael Grosse
42fa04b28cSMichael Grosse    /**
43fa04b28cSMichael Grosse     * Initialize the Aggregation renderer and executes the search
44fa04b28cSMichael Grosse     *
45*0549dcc5SAndreas Gohr     * You need to call @param string $id
46fa04b28cSMichael Grosse     * @param string $mode
47fa04b28cSMichael Grosse     * @param \Doku_Renderer $renderer
48fa04b28cSMichael Grosse     * @param SearchConfig $searchConfig
49*0549dcc5SAndreas Gohr     * @see render() on the resulting object.
50*0549dcc5SAndreas Gohr     *
51fa04b28cSMichael Grosse     */
52d6d97f60SAnna Dabrowska    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig)
53d6d97f60SAnna Dabrowska    {
54fa04b28cSMichael Grosse        $this->id = $id;
55fa04b28cSMichael Grosse        $this->mode = $mode;
56fa04b28cSMichael Grosse        $this->renderer = $renderer;
57fa04b28cSMichael Grosse        $this->searchConfig = $searchConfig;
58fa04b28cSMichael Grosse        $this->data = $searchConfig->getConf();
59fa04b28cSMichael Grosse        $this->columns = $searchConfig->getColumns();
600699ff47SMichael Grosse        $this->result = $this->searchConfig->execute();
610699ff47SMichael Grosse        $this->resultCount = $this->searchConfig->getCount();
62aafac1c1SMichael Grosse
63aafac1c1SMichael Grosse        $this->max = $this->result[0]['count'];
64aafac1c1SMichael Grosse        $this->min = end($this->result)['count'];
65fa04b28cSMichael Grosse    }
66fa04b28cSMichael Grosse
67fa04b28cSMichael Grosse    /**
689e7e1786SMichael Grosse     * Create the cloud on the renderer
69fa04b28cSMichael Grosse     */
70d6d97f60SAnna Dabrowska    public function render()
71d6d97f60SAnna Dabrowska    {
728b4531cfSMichael Grosse
738b4531cfSMichael Grosse        $this->sortResults();
748b4531cfSMichael Grosse
75fa04b28cSMichael Grosse        $this->startScope();
76c7dd6b6aSMichael Grosse        $this->startList();
77fa04b28cSMichael Grosse        foreach ($this->result as $result) {
7833bd00e9SMichael Grosse            $this->renderTag($result);
79fa04b28cSMichael Grosse        }
80c7dd6b6aSMichael Grosse        $this->finishList();
81fa04b28cSMichael Grosse        $this->finishScope();
82fa04b28cSMichael Grosse        return;
83fa04b28cSMichael Grosse    }
845282d027SMichael Grosse
85fa04b28cSMichael Grosse    /**
86fa04b28cSMichael Grosse     * Adds additional info to document and renderer in XHTML mode
87fa04b28cSMichael Grosse     *
88fa04b28cSMichael Grosse     * @see finishScope()
89fa04b28cSMichael Grosse     */
90d6d97f60SAnna Dabrowska    protected function startScope()
91d6d97f60SAnna Dabrowska    {
92fa04b28cSMichael Grosse        // wrapping div
93fa04b28cSMichael Grosse        if ($this->mode != 'xhtml') return;
94be2ae900SMichael Grosse        $this->renderer->doc .= "<div class=\"structcloud\">";
95fa04b28cSMichael Grosse    }
965282d027SMichael Grosse
97fa04b28cSMichael Grosse    /**
98fa04b28cSMichael Grosse     * Closes the table and anything opened in startScope()
99fa04b28cSMichael Grosse     *
100fa04b28cSMichael Grosse     * @see startScope()
101fa04b28cSMichael Grosse     */
102d6d97f60SAnna Dabrowska    protected function finishScope()
103d6d97f60SAnna Dabrowska    {
104fa04b28cSMichael Grosse        // wrapping div
105fa04b28cSMichael Grosse        if ($this->mode != 'xhtml') return;
106fa04b28cSMichael Grosse        $this->renderer->doc .= '</div>';
107fa04b28cSMichael Grosse    }
108aafac1c1SMichael Grosse
10933bd00e9SMichael Grosse    /**
11033bd00e9SMichael Grosse     * Render a tag of the cloud
11133bd00e9SMichael Grosse     *
11233bd00e9SMichael Grosse     * @param ['tag' => Value, 'count' => int] $result
11333bd00e9SMichael Grosse     */
114d6d97f60SAnna Dabrowska    protected function renderTag($result)
115d6d97f60SAnna Dabrowska    {
116fa04b28cSMichael Grosse        /**
117fa04b28cSMichael Grosse         * @var Value $value
118fa04b28cSMichael Grosse         */
119fa04b28cSMichael Grosse        $value = $result['tag'];
120fa04b28cSMichael Grosse        $count = $result['count'];
121fa04b28cSMichael Grosse        if ($value->isEmpty()) {
122fa04b28cSMichael Grosse            return;
123fa04b28cSMichael Grosse        }
124fa04b28cSMichael Grosse
125c7dd6b6aSMichael Grosse        $type = strtolower($value->getColumn()->getType()->getClass());
126c7dd6b6aSMichael Grosse        $weight = $this->getWeight($count, $this->min, $this->max);
1278e54e6f4SMichael Grosse
12885edf4f2SMichael Grosse        if (!empty($this->data['target'])) {
12985edf4f2SMichael Grosse            $target = $this->data['target'];
13085edf4f2SMichael Grosse        } else {
13185edf4f2SMichael Grosse            global $INFO;
13285edf4f2SMichael Grosse            $target = $INFO['id'];
13385edf4f2SMichael Grosse        }
1348e54e6f4SMichael Grosse
135ce8676aeSMichael Grosse        $tagValue = $value->getDisplayValue();
136ce8676aeSMichael Grosse        if (is_array($tagValue)) {
137ce8676aeSMichael Grosse            $tagValue = $tagValue[0];
138fa04b28cSMichael Grosse        }
13957775e30SSzymon Olewniczak        $key = $value->getColumn()->getFullQualifiedLabel() . '=';
14043d76406SSzymon Olewniczak        $filter = SearchConfigParameters::$PARAM_FILTER . '[' . urlencode($key) . ']=' . urlencode($tagValue);
141c7dd6b6aSMichael Grosse
142da11327aSMichael Grosse        $this->renderer->listitem_open(1);
143da11327aSMichael Grosse        $this->renderer->listcontent_open();
144da11327aSMichael Grosse
145262c0fc6SMichael Grosse        if ($this->mode == 'xhtml') {
146c7dd6b6aSMichael Grosse            $this->renderer->doc .= "<div style='font-size:$weight%' data-count='$count' class='cloudtag struct_$type'>";
1478e54e6f4SMichael Grosse        }
1488e54e6f4SMichael Grosse
149262c0fc6SMichael Grosse        $value->renderAsTagCloudLink($this->renderer, $this->mode, $target, $filter, $weight);
150262c0fc6SMichael Grosse
151262c0fc6SMichael Grosse        if ($this->mode == 'xhtml') {
152c7dd6b6aSMichael Grosse            $this->renderer->doc .= '</div>';
153fa04b28cSMichael Grosse        }
154da11327aSMichael Grosse
155da11327aSMichael Grosse        $this->renderer->listcontent_close();
156da11327aSMichael Grosse        $this->renderer->listitem_close();
157262c0fc6SMichael Grosse    }
158aafac1c1SMichael Grosse
159aafac1c1SMichael Grosse    /**
160aafac1c1SMichael Grosse     * This interpolates the weight between 70 and 150 based on $min, $max and $current
161aafac1c1SMichael Grosse     *
162aafac1c1SMichael Grosse     * @param int $current
163aafac1c1SMichael Grosse     * @param int $min
164aafac1c1SMichael Grosse     * @param int $max
1658e54e6f4SMichael Grosse     * @return int
166aafac1c1SMichael Grosse     */
167d6d97f60SAnna Dabrowska    protected function getWeight($current, $min, $max)
168d6d97f60SAnna Dabrowska    {
169aafac1c1SMichael Grosse        if ($min == $max) {
170aafac1c1SMichael Grosse            return 100;
171aafac1c1SMichael Grosse        }
1728e54e6f4SMichael Grosse        return round(($current - $min) / ($max - $min) * 80 + 70);
173aafac1c1SMichael Grosse    }
1748b4531cfSMichael Grosse
1758b4531cfSMichael Grosse    /**
1768b4531cfSMichael Grosse     * Sort the list of results
1778b4531cfSMichael Grosse     */
178d6d97f60SAnna Dabrowska    protected function sortResults()
179d6d97f60SAnna Dabrowska    {
1808b4531cfSMichael Grosse        usort($this->result, function ($a, $b) {
181d560ea13SMichael Grosse            $asort = $a['tag']->getColumn()->getType()->getSortString($a['tag']);
182d560ea13SMichael Grosse            $bsort = $b['tag']->getColumn()->getType()->getSortString($b['tag']);
183d560ea13SMichael Grosse            if ($asort < $bsort) {
1848b4531cfSMichael Grosse                return -1;
1858b4531cfSMichael Grosse            }
186d560ea13SMichael Grosse            if ($asort > $bsort) {
1878b4531cfSMichael Grosse                return 1;
1888b4531cfSMichael Grosse            }
1898b4531cfSMichael Grosse            return 0;
1908b4531cfSMichael Grosse        });
1918b4531cfSMichael Grosse    }
1928b4531cfSMichael Grosse
193d6d97f60SAnna Dabrowska    protected function startList()
194d6d97f60SAnna Dabrowska    {
195c7dd6b6aSMichael Grosse        $this->renderer->listu_open();
196c7dd6b6aSMichael Grosse    }
197c7dd6b6aSMichael Grosse
198d6d97f60SAnna Dabrowska    protected function finishList()
199d6d97f60SAnna Dabrowska    {
200c7dd6b6aSMichael Grosse        $this->renderer->listu_close();
201c7dd6b6aSMichael Grosse    }
202fa04b28cSMichael Grosse}
203