xref: /plugin/struct/meta/AggregationCloud.php (revision be2ae900335f3589fa615e85ffb1f6a804f0aa99)
1fa04b28cSMichael Grosse<?php
2fa04b28cSMichael Grossenamespace dokuwiki\plugin\struct\meta;
3fa04b28cSMichael Grosseclass AggregationCloud {
4fa04b28cSMichael Grosse    /**
5fa04b28cSMichael Grosse     * @var string the page id of the page this is rendered to
6fa04b28cSMichael Grosse     */
7fa04b28cSMichael Grosse    protected $id;
8fa04b28cSMichael Grosse    /**
9fa04b28cSMichael Grosse     * @var string the Type of renderer used
10fa04b28cSMichael Grosse     */
11fa04b28cSMichael Grosse    protected $mode;
12fa04b28cSMichael Grosse    /**
13fa04b28cSMichael Grosse     * @var \Doku_Renderer the DokuWiki renderer used to create the output
14fa04b28cSMichael Grosse     */
15fa04b28cSMichael Grosse    protected $renderer;
16fa04b28cSMichael Grosse    /**
17fa04b28cSMichael Grosse     * @var SearchConfig the configured search - gives access to columns etc.
18fa04b28cSMichael Grosse     */
19fa04b28cSMichael Grosse    protected $searchConfig;
20fa04b28cSMichael Grosse    /**
21fa04b28cSMichael Grosse     * @var Column[] the list of columns to be displayed
22fa04b28cSMichael Grosse     */
23fa04b28cSMichael Grosse    protected $columns;
24fa04b28cSMichael Grosse    /**
25fa04b28cSMichael Grosse     * @var  Value[][] the search result
26fa04b28cSMichael Grosse     */
27fa04b28cSMichael Grosse    protected $result;
28fa04b28cSMichael Grosse    /**
29fa04b28cSMichael Grosse     * @var int number of all results
30fa04b28cSMichael Grosse     */
31fa04b28cSMichael Grosse    protected $resultCount;
32fa04b28cSMichael Grosse    /**
33fa04b28cSMichael Grosse     * @var string[] the result PIDs for each row
34fa04b28cSMichael Grosse     */
35fa04b28cSMichael Grosse    protected $resultPIDs;
36fa04b28cSMichael Grosse    /**
37fa04b28cSMichael Grosse     * @var array for summing up columns
38fa04b28cSMichael Grosse     */
39fa04b28cSMichael Grosse    protected $sums;
40fa04b28cSMichael Grosse    /**
41fa04b28cSMichael Grosse     * @var bool skip full table when no results found
42fa04b28cSMichael Grosse     */
43fa04b28cSMichael Grosse    protected $simplenone = true;
44fa04b28cSMichael Grosse    /**
45fa04b28cSMichael Grosse     * @todo we might be able to get rid of this helper and move this to SearchConfig
46fa04b28cSMichael Grosse     * @var \helper_plugin_struct_config
47fa04b28cSMichael Grosse     */
48fa04b28cSMichael Grosse    protected $helper;
49fa04b28cSMichael Grosse    /**
50fa04b28cSMichael Grosse     * Initialize the Aggregation renderer and executes the search
51fa04b28cSMichael Grosse     *
52fa04b28cSMichael Grosse     * You need to call @see render() on the resulting object.
53fa04b28cSMichael Grosse     *
54fa04b28cSMichael Grosse     * @param string $id
55fa04b28cSMichael Grosse     * @param string $mode
56fa04b28cSMichael Grosse     * @param \Doku_Renderer $renderer
57fa04b28cSMichael Grosse     * @param SearchConfig $searchConfig
58fa04b28cSMichael Grosse     */
590699ff47SMichael Grosse    public function __construct($id, $mode, \Doku_Renderer $renderer, SearchCloud $searchConfig) {
60fa04b28cSMichael Grosse        $this->id = $id;
61fa04b28cSMichael Grosse        $this->mode = $mode;
62fa04b28cSMichael Grosse        $this->renderer = $renderer;
63fa04b28cSMichael Grosse        $this->searchConfig = $searchConfig;
64fa04b28cSMichael Grosse        $this->data = $searchConfig->getConf();
65fa04b28cSMichael Grosse        $this->columns = $searchConfig->getColumns();
660699ff47SMichael Grosse        $this->result = $this->searchConfig->execute();
670699ff47SMichael Grosse        $this->resultCount = $this->searchConfig->getCount();
68fa04b28cSMichael Grosse        $this->helper = plugin_load('helper', 'struct_config');
69aafac1c1SMichael Grosse
70aafac1c1SMichael Grosse        $this->max = $this->result[0]['count'];
71aafac1c1SMichael Grosse        $this->min = end($this->result)['count'];
72fa04b28cSMichael Grosse    }
73fa04b28cSMichael Grosse
74fa04b28cSMichael Grosse    /**
75fa04b28cSMichael Grosse     * Create the table on the renderer
76fa04b28cSMichael Grosse     */
77fa04b28cSMichael Grosse    public function render() {
78fa04b28cSMichael Grosse        $this->startScope();
79fa04b28cSMichael Grosse        $this->renderer->doc .= '<ul>';
80fa04b28cSMichael Grosse        foreach ($this->result as $result) {
8133bd00e9SMichael Grosse            $this->renderTag($result);
82fa04b28cSMichael Grosse        }
83fa04b28cSMichael Grosse        $this->renderer->doc .= '</ul>';
84fa04b28cSMichael Grosse        $this->finishScope();
85fa04b28cSMichael Grosse        return;
86fa04b28cSMichael Grosse    }
87fa04b28cSMichael Grosse    /**
88fa04b28cSMichael Grosse     * Adds additional info to document and renderer in XHTML mode
89fa04b28cSMichael Grosse     *
90fa04b28cSMichael Grosse     * @see finishScope()
91fa04b28cSMichael Grosse     */
92fa04b28cSMichael Grosse    protected function startScope() {
93fa04b28cSMichael Grosse        // unique identifier for this aggregation
94fa04b28cSMichael Grosse        $this->renderer->info['struct_cloud_hash'] = md5(var_export($this->data, true));
95fa04b28cSMichael Grosse        // wrapping div
96fa04b28cSMichael Grosse        if($this->mode != 'xhtml') return;
97*be2ae900SMichael Grosse        $this->renderer->doc .= "<div class=\"structcloud\">";
98fa04b28cSMichael Grosse    }
99fa04b28cSMichael Grosse    /**
100fa04b28cSMichael Grosse     * Closes the table and anything opened in startScope()
101fa04b28cSMichael Grosse     *
102fa04b28cSMichael Grosse     * @see startScope()
103fa04b28cSMichael Grosse     */
104fa04b28cSMichael Grosse    protected function finishScope() {
105fa04b28cSMichael Grosse        // remove identifier from renderer again
106fa04b28cSMichael Grosse        if(isset($this->renderer->info['struct_cloud_hash'])) {
107fa04b28cSMichael Grosse            unset($this->renderer->info['struct_cloud_hash']);
108fa04b28cSMichael Grosse        }
109fa04b28cSMichael Grosse        // wrapping div
110fa04b28cSMichael Grosse        if($this->mode != 'xhtml') return;
111fa04b28cSMichael Grosse        $this->renderer->doc .= '</div>';
112fa04b28cSMichael Grosse    }
113aafac1c1SMichael Grosse
11433bd00e9SMichael Grosse    /**
11533bd00e9SMichael Grosse     * Render a tag of the cloud
11633bd00e9SMichael Grosse     *
11733bd00e9SMichael Grosse     * @param ['tag' => Value, 'count' => int] $result
11833bd00e9SMichael Grosse     */
11933bd00e9SMichael Grosse    protected function renderTag($result) {
120fa04b28cSMichael Grosse        /**
121fa04b28cSMichael Grosse         * @var Value $value
122fa04b28cSMichael Grosse         */
123fa04b28cSMichael Grosse        $value = $result['tag'];
124fa04b28cSMichael Grosse        $count = $result['count'];
125aafac1c1SMichael Grosse        $weight = $this->getWeight($count, $this->min, $this->max);
126aafac1c1SMichael Grosse        $type = strtolower($value->getColumn()->getType()->getClass());
127fa04b28cSMichael Grosse        if ($value->isEmpty()) {
128fa04b28cSMichael Grosse            return;
129fa04b28cSMichael Grosse        }
130fa04b28cSMichael Grosse
131ce8676aeSMichael Grosse        $tagValue = $value->getDisplayValue();
132ce8676aeSMichael Grosse        if (empty($tagValue)) {
133ce8676aeSMichael Grosse            $tagValue = $value->getRawValue();
134ce8676aeSMichael Grosse        }
135ce8676aeSMichael Grosse        if (is_array($tagValue)) {
136ce8676aeSMichael Grosse            $tagValue = $tagValue[0];
137fa04b28cSMichael Grosse        }
138fa04b28cSMichael Grosse        $schema = $this->data['schemas'][0][0];
139fa04b28cSMichael Grosse        $col = $value->getColumn()->getLabel();
140fa04b28cSMichael Grosse        $this->renderer->doc .= '<li><div class="li">';
1414c969d82SMichael Grosse        $this->renderer->doc .= "<div style='font-size:$weight%' data-count='$count' class='cloudtag $type'>";
1424c969d82SMichael Grosse
143ce8676aeSMichael Grosse        $this->renderer->internallink("?flt[$schema.$col*~]=" . urlencode($tagValue),$tagValue);
144fa04b28cSMichael Grosse        if ($column < $this->resultCount) {
145fa04b28cSMichael Grosse            $this->renderer->doc .= ' ';
146fa04b28cSMichael Grosse        }
147fa04b28cSMichael Grosse        $this->renderer->doc .= '</div>';
148fa04b28cSMichael Grosse        $this->renderer->doc .= '</div></li>';
149fa04b28cSMichael Grosse    }
150aafac1c1SMichael Grosse
151aafac1c1SMichael Grosse    /**
152aafac1c1SMichael Grosse     * This interpolates the weight between 70 and 150 based on $min, $max and $current
153aafac1c1SMichael Grosse     *
154aafac1c1SMichael Grosse     * @param int $current
155aafac1c1SMichael Grosse     * @param int $min
156aafac1c1SMichael Grosse     * @param int $max
157aafac1c1SMichael Grosse     * @return float|int
158aafac1c1SMichael Grosse     */
159aafac1c1SMichael Grosse    protected function getWeight($current, $min, $max) {
160aafac1c1SMichael Grosse        if ($min == $max) {
161aafac1c1SMichael Grosse            return 100;
162aafac1c1SMichael Grosse        }
163aafac1c1SMichael Grosse        return ($current - $min)/($max - $min) * 80 + 70;
164aafac1c1SMichael Grosse    }
165fa04b28cSMichael Grosse}
166