xref: /plugin/statistics/StatisticsGraph.php (revision 9fdd7e51bafea206b2557d1421fa6965d460c57e)
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 topdomain()
145    {
146        $this->sumUpPieChart('topdomain', 'domain');
147    }
148
149    public function topuser()
150    {
151        $this->sumUpPieChart('topuser', 'user');
152    }
153
154    public function topeditor()
155    {
156        $this->sumUpPieChart('topeditor', 'user');
157    }
158
159    public function topgroup()
160    {
161        $this->sumUpPieChart('topgroup', 'group');
162    }
163
164    public function topgroupedit()
165    {
166        $this->sumUpPieChart('topgroupedit', 'group');
167    }
168
169    public function viewport()
170    {
171        $result = $this->hlp->getQuery()->viewport();
172        $data = [];
173
174        foreach ($result as $row) {
175            $data[] = [
176                'x' => $row['res_x'],
177                'y' => $row['res_y'],
178                'r' => floor($row['cnt'] / 10),
179            ];
180        }
181
182        $data = [
183            'datasets' => [
184                [
185                    'label' => $this->hlp->getLang('viewport'),
186                    'data' => $data
187                ]
188            ],
189        ];
190
191        $this->printGraph('viewport', 'bubble', $data);
192    }
193
194    public function resolution()
195    {
196        $result = $this->hlp->getQuery()->resolution();
197        $data = [];
198
199        foreach ($result as $row) {
200            $data[] = [
201                'x' => $row['res_x'],
202                'y' => $row['res_y'],
203                'r' => floor($row['cnt'] / 10),
204            ];
205        }
206
207        $data = [
208            'datasets' => [
209                [
210                    'label' => $this->hlp->getLang('resolution'),
211                    'data' => $data
212                ]
213            ],
214        ];
215
216        $this->printGraph('resolution', 'bubble', $data);
217    }
218
219
220    public function history_page_count()
221    {
222        $this->history('page_count');
223    }
224
225    public function history_page_size()
226    {
227        $this->history('page_size');
228    }
229
230    public function history_media_count()
231    {
232        $this->history('media_count');
233    }
234
235    public function history_media_size()
236    {
237        $this->history('media_size');
238    }
239
240    public function dashboardviews()
241    {
242        $hours  = ($this->from == $this->to);
243        $result = $this->hlp->getQuery()->dashboardviews($hours);
244        $data1  = [];
245        $data2  = [];
246        $data3  = [];
247        $times  = [];
248
249        foreach ($result as $time => $row) {
250            $data1[] = (int) $row['pageviews'];
251            $data2[] = (int) $row['sessions'];
252            $data3[] = (int) $row['visitors'];
253            $times[] = $time . ($hours ? 'h' : '');
254        }
255
256        $data = [
257            'datasets' => [
258                [
259                    'label' => $this->hlp->getLang('graph_views'),
260                    'data' => $data1,
261                ],
262                [
263                    'label' => $this->hlp->getLang('graph_sessions'),
264                    'data' => $data2,
265                ],
266                [
267                    'label' => $this->hlp->getLang('graph_visitors'),
268                    'data' => $data3,
269                ],
270            ],
271            'labels' => $times
272        ];
273
274        $this->printGraph('dashboardviews', 'line', $data);
275    }
276
277    public function dashboardwiki($js = false)
278    {
279        $hours  = ($this->from == $this->to);
280        $result = $this->hlp->getQuery()->dashboardwiki($hours);
281        $data1  = [];
282        $data2  = [];
283        $data3  = [];
284        $times  = [];
285
286        foreach ($result as $time => $row) {
287            $data1[] = (int) ($row['E'] ?? 0);
288            $data2[] = (int) ($row['C'] ?? 0);
289            $data3[] = (int) ($row['D'] ?? 0);
290            $times[] = $time . ($hours ? 'h' : '');
291        }
292        $data = [
293            'datasets' => [
294                [
295                    'label' => $this->hlp->getLang('graph_edits'),
296                    'data' => $data1,
297                ],
298                [
299                    'label' => $this->hlp->getLang('graph_creates'),
300                    'data' => $data2,
301                ],
302                [
303                    'label' => $this->hlp->getLang('graph_deletions'),
304                    'data' => $data3,
305                ],
306            ],
307            'labels' => $times
308        ];
309
310        $this->printGraph('dashboardwiki', 'line', $data);
311    }
312
313    /**
314     * @param string $name
315     * @param string $type
316     * @param array $data
317     * @return void
318     */
319    protected function printGraph(string $name, string $type, array $data)
320    {
321        $json = htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
322        $tpl = '
323        <chart-component
324            width="%d"
325            height="%d"
326            name="%s"
327            type="%s"
328            data="%s"></chart-component>
329        ';
330
331        echo sprintf($tpl, $this->width, $this->height, $name, $type, $json);
332    }
333
334    #endregion Graphbuilding functions
335}
336