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