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