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