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