xref: /plugin/statistics/StatisticsGraph.php (revision b92383f54ffbdf0b3964d0a7fe188dbd1ac6a513)
1<?php
2
3// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
4namespace dokuwiki\plugin\statistics;
5
6/**
7 * Create the data for graph visualization
8 */
9class StatisticsGraph
10{
11    private \helper_plugin_statistics $hlp;
12    private string $from;
13    private string $to;
14    private int $width;
15    private int $height;
16
17    /**
18     * Initialize a new Graph
19     *
20     * @param \helper_plugin_statistics $hlp
21     * @param string $from From date
22     * @param string $to To date
23     * @param int $width width of the graph in pixels
24     * @param int $height height of the graph in pixels
25     */
26    public function __construct(\helper_plugin_statistics $hlp, $from, $to, $width, $height)
27    {
28        $this->hlp = $hlp;
29        $this->from = $from;
30        $this->to = $to;
31        $this->width = $width;
32        $this->height = $height;
33    }
34
35    /**
36     * Create a PieChart
37     *
38     * @param array $data associative array contianing label and values
39     */
40    protected function pieChart($data)
41    {
42        $data = [
43            'datasets' => [
44                [
45                    'data' => array_values($data),
46                ],
47            ],
48            'labels' => array_keys($data)
49
50        ];
51
52        $this->printGraph('countries', 'pie', $data);
53    }
54
55    /**
56     * Build a PieChart with only the top data shown and all other summarized
57     *
58     * @param string $query The function to call on the Query object to get the data
59     * @param string $key The key containing the label
60     * @param int $max How many discrete values to show before summarizing under "other"
61     */
62    protected function sumUpPieChart($query, $key, $max = 4)
63    {
64        $result = $this->hlp->getQuery()->$query();
65        $data   = [];
66        $top    = 0;
67        foreach ($result as $row) {
68            if ($top < $max) {
69                $data[$row[$key]] = $row['cnt'];
70            } else {
71                $data['other'] += $row['cnt'];
72            }
73            $top++;
74        }
75        $this->pieChart($data);
76    }
77
78    /**
79     * Create a history graph for the given info type
80     *
81     * @param $info
82     */
83    protected function history($info)
84    {
85        $diff = abs(strtotime($this->from) - strtotime($this->to));
86        $days = floor($diff / (60 * 60 * 24));
87        if ($days > 365) {
88            $interval = 'months';
89        } elseif ($days > 56) {
90            $interval = 'weeks';
91        } else {
92            $interval = 'days';
93        }
94
95        $result = $this->hlp->getQuery()->history($info, $interval);
96
97        $data = [];
98        $times = [];
99        foreach ($result as $row) {
100            $data[] = $row['cnt'];
101            if ($interval == 'months') {
102                $times[] = substr($row['time'], 0, 4) . '-' . substr($row['time'], 4, 2);
103            } elseif ($interval == 'weeks') {
104                $times[] = $row['EXTRACT(YEAR FROM dt)'] . '-' . $row['time']; // FIXME
105            } else {
106                $times[] = substr($row['time'], -5); // FIXME
107            }
108        }
109
110        $data = [
111            'datasets' => [
112                [
113                    'label' => $this->hlp->getLang('graph_' . $info),
114                    'data' => $data,
115                ],
116            ],
117            'labels' => $times
118        ];
119
120        $this->printGraph("history_$info", 'line', $data);
121    }
122    #region Graphbuilding functions
123
124    public function countries()
125    {
126        $this->sumUpPieChart('countries', 'country');
127    }
128
129    public function searchengines()
130    {
131        $this->sumUpPieChart('searchengines', 'engine', 3);
132    }
133
134    public function browsers()
135    {
136        $this->sumUpPieChart('browsers', 'browser');
137    }
138
139    public function os()
140    {
141        $this->sumUpPieChart('os', 'os');
142    }
143
144    public function topuser()
145    {
146        $this->sumUpPieChart('topuser', 'user');
147    }
148
149    public function topeditor()
150    {
151        $this->sumUpPieChart('topeditor', 'user');
152    }
153
154    public function topgroup()
155    {
156        $this->sumUpPieChart('topgroup', 'group');
157    }
158
159    public function topgroupedit()
160    {
161        $this->sumUpPieChart('topgroupedit', 'group');
162    }
163
164    public function viewport()
165    {
166        $result = $this->hlp->getQuery()->viewport();
167        $data = [];
168
169        foreach ($result as $row) {
170            $data[] = [
171                'x' => $row['res_x'],
172                'y' => $row['res_y'],
173                'r' => floor($row['cnt'] / 10),
174            ];
175        }
176
177        $data = [
178            'datasets' => [
179                [
180                    'label' => $this->hlp->getLang('viewport'),
181                    'data' => $data
182                ]
183            ],
184        ];
185
186        $this->printGraph('viewport', 'bubble', $data);
187    }
188
189    public function resolution()
190    {
191        $result = $this->hlp->getQuery()->resolution();
192        $data = [];
193
194        foreach ($result as $row) {
195            $data[] = [
196                'x' => $row['res_x'],
197                'y' => $row['res_y'],
198                'r' => floor($row['cnt'] / 10),
199            ];
200        }
201
202        $data = [
203            'datasets' => [
204                [
205                    'label' => $this->hlp->getLang('resolution'),
206                    'data' => $data
207                ]
208            ],
209        ];
210
211        $this->printGraph('resolution', 'bubble', $data);
212    }
213
214
215    public function history_page_count()
216    {
217        $this->history('page_count');
218    }
219
220    public function history_page_size()
221    {
222        $this->history('page_size');
223    }
224
225    public function history_media_count()
226    {
227        $this->history('media_count');
228    }
229
230    public function history_media_size()
231    {
232        $this->history('media_size');
233    }
234
235    public function dashboardviews()
236    {
237        $hours  = ($this->from == $this->to);
238        $result = $this->hlp->getQuery()->dashboardviews($hours);
239        $data1  = [];
240        $data2  = [];
241        $data3  = [];
242        $times  = [];
243
244        foreach ($result as $time => $row) {
245            $data1[] = (int) $row['pageviews'];
246            $data2[] = (int) $row['sessions'];
247            $data3[] = (int) $row['visitors'];
248            $times[] = $time . ($hours ? 'h' : '');
249        }
250
251        $data = [
252            'datasets' => [
253                [
254                    'label' => $this->hlp->getLang('graph_views'),
255                    'data' => $data1,
256                ],
257                [
258                    'label' => $this->hlp->getLang('graph_sessions'),
259                    'data' => $data2,
260                ],
261                [
262                    'label' => $this->hlp->getLang('graph_visitors'),
263                    'data' => $data3,
264                ],
265            ],
266            'labels' => $times
267        ];
268
269        $this->printGraph('dashboardviews', 'line', $data);
270    }
271
272    public function dashboardwiki($js = false)
273    {
274        $hours  = ($this->from == $this->to);
275        $result = $this->hlp->getQuery()->dashboardwiki($hours);
276        $data1  = [];
277        $data2  = [];
278        $data3  = [];
279        $times  = [];
280
281        foreach ($result as $time => $row) {
282            $data1[] = (int) $row['E'];
283            $data2[] = (int) $row['C'];
284            $data3[] = (int) $row['D'];
285            $times[] = $time . ($hours ? 'h' : '');
286        }
287        $data = [
288            'datasets' => [
289                [
290                    'label' => $this->hlp->getLang('graph_edits'),
291                    'data' => $data1,
292                ],
293                [
294                    'label' => $this->hlp->getLang('graph_creates'),
295                    'data' => $data2,
296                ],
297                [
298                    'label' => $this->hlp->getLang('graph_deletions'),
299                    'data' => $data3,
300                ],
301            ],
302            'labels' => $times
303        ];
304
305        $this->printGraph('dashboardwiki', 'line', $data);
306    }
307
308    /**
309     * @param string $name
310     * @param string $type
311     * @param array $data
312     * @return void
313     */
314    protected function printGraph(string $name, string $type, array $data)
315    {
316        $json = htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
317        $tpl = '
318        <chart-component
319            width="%d"
320            height="%d"
321            name="%s"
322            type="%s"
323            data="%s"></chart-component>
324        ';
325
326        echo sprintf($tpl, $this->width, $this->height, $name, $type, $json);
327    }
328
329    #endregion Graphbuilding functions
330}
331