xref: /plugin/statistics/StatisticsGraph.php (revision b92383f54ffbdf0b3964d0a7fe188dbd1ac6a513)
164ba7f66SAnna Dabrowska<?php
264ba7f66SAnna Dabrowska
3211caa5dSAndreas Gohr// phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
464ba7f66SAnna Dabrowskanamespace dokuwiki\plugin\statistics;
564ba7f66SAnna Dabrowska
6211caa5dSAndreas Gohr/**
7211caa5dSAndreas Gohr * Create the data for graph visualization
8211caa5dSAndreas Gohr */
964ba7f66SAnna Dabrowskaclass StatisticsGraph
1064ba7f66SAnna Dabrowska{
1164ba7f66SAnna Dabrowska    private \helper_plugin_statistics $hlp;
1264ba7f66SAnna Dabrowska    private string $from;
1364ba7f66SAnna Dabrowska    private string $to;
1464ba7f66SAnna Dabrowska    private int $width;
1564ba7f66SAnna Dabrowska    private int $height;
1664ba7f66SAnna Dabrowska
17211caa5dSAndreas Gohr    /**
18211caa5dSAndreas Gohr     * Initialize a new Graph
19211caa5dSAndreas Gohr     *
20211caa5dSAndreas Gohr     * @param \helper_plugin_statistics $hlp
21211caa5dSAndreas Gohr     * @param string $from From date
22211caa5dSAndreas Gohr     * @param string $to To date
23211caa5dSAndreas Gohr     * @param int $width width of the graph in pixels
24211caa5dSAndreas Gohr     * @param int $height height of the graph in pixels
25211caa5dSAndreas Gohr     */
2664ba7f66SAnna Dabrowska    public function __construct(\helper_plugin_statistics $hlp, $from, $to, $width, $height)
2764ba7f66SAnna Dabrowska    {
2864ba7f66SAnna Dabrowska        $this->hlp = $hlp;
2964ba7f66SAnna Dabrowska        $this->from = $from;
3064ba7f66SAnna Dabrowska        $this->to = $to;
3164ba7f66SAnna Dabrowska        $this->width = $width;
3264ba7f66SAnna Dabrowska        $this->height = $height;
3364ba7f66SAnna Dabrowska    }
3464ba7f66SAnna Dabrowska
3564ba7f66SAnna Dabrowska    /**
3664ba7f66SAnna Dabrowska     * Create a PieChart
3764ba7f66SAnna Dabrowska     *
3864ba7f66SAnna Dabrowska     * @param array $data associative array contianing label and values
3964ba7f66SAnna Dabrowska     */
40211caa5dSAndreas Gohr    protected function pieChart($data)
4164ba7f66SAnna Dabrowska    {
4264ba7f66SAnna Dabrowska        $data = [
4364ba7f66SAnna Dabrowska            'datasets' => [
4464ba7f66SAnna Dabrowska                [
4564ba7f66SAnna Dabrowska                    'data' => array_values($data),
4664ba7f66SAnna Dabrowska                ],
4764ba7f66SAnna Dabrowska            ],
4864ba7f66SAnna Dabrowska            'labels' => array_keys($data)
4964ba7f66SAnna Dabrowska
5064ba7f66SAnna Dabrowska        ];
5164ba7f66SAnna Dabrowska
5264ba7f66SAnna Dabrowska        $this->printGraph('countries', 'pie', $data);
5364ba7f66SAnna Dabrowska    }
5464ba7f66SAnna Dabrowska
5564ba7f66SAnna Dabrowska    /**
5664ba7f66SAnna Dabrowska     * Build a PieChart with only the top data shown and all other summarized
5764ba7f66SAnna Dabrowska     *
5864ba7f66SAnna Dabrowska     * @param string $query The function to call on the Query object to get the data
5964ba7f66SAnna Dabrowska     * @param string $key The key containing the label
6064ba7f66SAnna Dabrowska     * @param int $max How many discrete values to show before summarizing under "other"
6164ba7f66SAnna Dabrowska     */
6264ba7f66SAnna Dabrowska    protected function sumUpPieChart($query, $key, $max = 4)
6364ba7f66SAnna Dabrowska    {
64211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->$query();
6564ba7f66SAnna Dabrowska        $data   = [];
6664ba7f66SAnna Dabrowska        $top    = 0;
6764ba7f66SAnna Dabrowska        foreach ($result as $row) {
6864ba7f66SAnna Dabrowska            if ($top < $max) {
6964ba7f66SAnna Dabrowska                $data[$row[$key]] = $row['cnt'];
7064ba7f66SAnna Dabrowska            } else {
7164ba7f66SAnna Dabrowska                $data['other'] += $row['cnt'];
7264ba7f66SAnna Dabrowska            }
7364ba7f66SAnna Dabrowska            $top++;
7464ba7f66SAnna Dabrowska        }
75211caa5dSAndreas Gohr        $this->pieChart($data);
7664ba7f66SAnna Dabrowska    }
7764ba7f66SAnna Dabrowska
7864ba7f66SAnna Dabrowska    /**
7964ba7f66SAnna Dabrowska     * Create a history graph for the given info type
8064ba7f66SAnna Dabrowska     *
8164ba7f66SAnna Dabrowska     * @param $info
8264ba7f66SAnna Dabrowska     */
8364ba7f66SAnna Dabrowska    protected function history($info)
8464ba7f66SAnna Dabrowska    {
8564ba7f66SAnna Dabrowska        $diff = abs(strtotime($this->from) - strtotime($this->to));
8664ba7f66SAnna Dabrowska        $days = floor($diff / (60 * 60 * 24));
8764ba7f66SAnna Dabrowska        if ($days > 365) {
8864ba7f66SAnna Dabrowska            $interval = 'months';
8964ba7f66SAnna Dabrowska        } elseif ($days > 56) {
9064ba7f66SAnna Dabrowska            $interval = 'weeks';
9164ba7f66SAnna Dabrowska        } else {
9264ba7f66SAnna Dabrowska            $interval = 'days';
9364ba7f66SAnna Dabrowska        }
9464ba7f66SAnna Dabrowska
95211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->history($info, $interval);
9664ba7f66SAnna Dabrowska
9764ba7f66SAnna Dabrowska        $data = [];
9864ba7f66SAnna Dabrowska        $times = [];
9964ba7f66SAnna Dabrowska        foreach ($result as $row) {
10064ba7f66SAnna Dabrowska            $data[] = $row['cnt'];
10164ba7f66SAnna Dabrowska            if ($interval == 'months') {
10264ba7f66SAnna Dabrowska                $times[] = substr($row['time'], 0, 4) . '-' . substr($row['time'], 4, 2);
10364ba7f66SAnna Dabrowska            } elseif ($interval == 'weeks') {
10464ba7f66SAnna Dabrowska                $times[] = $row['EXTRACT(YEAR FROM dt)'] . '-' . $row['time']; // FIXME
10564ba7f66SAnna Dabrowska            } else {
10664ba7f66SAnna Dabrowska                $times[] = substr($row['time'], -5); // FIXME
10764ba7f66SAnna Dabrowska            }
10864ba7f66SAnna Dabrowska        }
10964ba7f66SAnna Dabrowska
11064ba7f66SAnna Dabrowska        $data = [
11164ba7f66SAnna Dabrowska            'datasets' => [
11264ba7f66SAnna Dabrowska                [
11364ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_' . $info),
11464ba7f66SAnna Dabrowska                    'data' => $data,
11564ba7f66SAnna Dabrowska                ],
11664ba7f66SAnna Dabrowska            ],
11764ba7f66SAnna Dabrowska            'labels' => $times
11864ba7f66SAnna Dabrowska        ];
11964ba7f66SAnna Dabrowska
12064ba7f66SAnna Dabrowska        $this->printGraph("history_$info", 'line', $data);
12164ba7f66SAnna Dabrowska    }
12264ba7f66SAnna Dabrowska    #region Graphbuilding functions
12364ba7f66SAnna Dabrowska
12464ba7f66SAnna Dabrowska    public function countries()
12564ba7f66SAnna Dabrowska    {
12664ba7f66SAnna Dabrowska        $this->sumUpPieChart('countries', 'country');
12764ba7f66SAnna Dabrowska    }
12864ba7f66SAnna Dabrowska
12964ba7f66SAnna Dabrowska    public function searchengines()
13064ba7f66SAnna Dabrowska    {
13164ba7f66SAnna Dabrowska        $this->sumUpPieChart('searchengines', 'engine', 3);
13264ba7f66SAnna Dabrowska    }
13364ba7f66SAnna Dabrowska
13464ba7f66SAnna Dabrowska    public function browsers()
13564ba7f66SAnna Dabrowska    {
13664ba7f66SAnna Dabrowska        $this->sumUpPieChart('browsers', 'browser');
13764ba7f66SAnna Dabrowska    }
13864ba7f66SAnna Dabrowska
13964ba7f66SAnna Dabrowska    public function os()
14064ba7f66SAnna Dabrowska    {
14164ba7f66SAnna Dabrowska        $this->sumUpPieChart('os', 'os');
14264ba7f66SAnna Dabrowska    }
14364ba7f66SAnna Dabrowska
14464ba7f66SAnna Dabrowska    public function topuser()
14564ba7f66SAnna Dabrowska    {
14664ba7f66SAnna Dabrowska        $this->sumUpPieChart('topuser', 'user');
14764ba7f66SAnna Dabrowska    }
14864ba7f66SAnna Dabrowska
14964ba7f66SAnna Dabrowska    public function topeditor()
15064ba7f66SAnna Dabrowska    {
15164ba7f66SAnna Dabrowska        $this->sumUpPieChart('topeditor', 'user');
15264ba7f66SAnna Dabrowska    }
15364ba7f66SAnna Dabrowska
15464ba7f66SAnna Dabrowska    public function topgroup()
15564ba7f66SAnna Dabrowska    {
15664ba7f66SAnna Dabrowska        $this->sumUpPieChart('topgroup', 'group');
15764ba7f66SAnna Dabrowska    }
15864ba7f66SAnna Dabrowska
15964ba7f66SAnna Dabrowska    public function topgroupedit()
16064ba7f66SAnna Dabrowska    {
16164ba7f66SAnna Dabrowska        $this->sumUpPieChart('topgroupedit', 'group');
16264ba7f66SAnna Dabrowska    }
16364ba7f66SAnna Dabrowska
16464ba7f66SAnna Dabrowska    public function viewport()
16564ba7f66SAnna Dabrowska    {
166211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->viewport();
16764ba7f66SAnna Dabrowska        $data = [];
16864ba7f66SAnna Dabrowska
16964ba7f66SAnna Dabrowska        foreach ($result as $row) {
17064ba7f66SAnna Dabrowska            $data[] = [
17164ba7f66SAnna Dabrowska                'x' => $row['res_x'],
17264ba7f66SAnna Dabrowska                'y' => $row['res_y'],
17364ba7f66SAnna Dabrowska                'r' => floor($row['cnt'] / 10),
17464ba7f66SAnna Dabrowska            ];
17564ba7f66SAnna Dabrowska        }
17664ba7f66SAnna Dabrowska
17764ba7f66SAnna Dabrowska        $data = [
17864ba7f66SAnna Dabrowska            'datasets' => [
17964ba7f66SAnna Dabrowska                [
18064ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('viewport'),
18164ba7f66SAnna Dabrowska                    'data' => $data
18264ba7f66SAnna Dabrowska                ]
18364ba7f66SAnna Dabrowska            ],
18464ba7f66SAnna Dabrowska        ];
18564ba7f66SAnna Dabrowska
18664ba7f66SAnna Dabrowska        $this->printGraph('viewport', 'bubble', $data);
18764ba7f66SAnna Dabrowska    }
18864ba7f66SAnna Dabrowska
18964ba7f66SAnna Dabrowska    public function resolution()
19064ba7f66SAnna Dabrowska    {
191211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->resolution();
19264ba7f66SAnna Dabrowska        $data = [];
19364ba7f66SAnna Dabrowska
19464ba7f66SAnna Dabrowska        foreach ($result as $row) {
19564ba7f66SAnna Dabrowska            $data[] = [
19664ba7f66SAnna Dabrowska                'x' => $row['res_x'],
19764ba7f66SAnna Dabrowska                'y' => $row['res_y'],
19864ba7f66SAnna Dabrowska                'r' => floor($row['cnt'] / 10),
19964ba7f66SAnna Dabrowska            ];
20064ba7f66SAnna Dabrowska        }
20164ba7f66SAnna Dabrowska
20264ba7f66SAnna Dabrowska        $data = [
20364ba7f66SAnna Dabrowska            'datasets' => [
20464ba7f66SAnna Dabrowska                [
20564ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('resolution'),
20664ba7f66SAnna Dabrowska                    'data' => $data
20764ba7f66SAnna Dabrowska                ]
20864ba7f66SAnna Dabrowska            ],
20964ba7f66SAnna Dabrowska        ];
21064ba7f66SAnna Dabrowska
21164ba7f66SAnna Dabrowska        $this->printGraph('resolution', 'bubble', $data);
21264ba7f66SAnna Dabrowska    }
21364ba7f66SAnna Dabrowska
21464ba7f66SAnna Dabrowska
21564ba7f66SAnna Dabrowska    public function history_page_count()
21664ba7f66SAnna Dabrowska    {
21764ba7f66SAnna Dabrowska        $this->history('page_count');
21864ba7f66SAnna Dabrowska    }
21964ba7f66SAnna Dabrowska
22064ba7f66SAnna Dabrowska    public function history_page_size()
22164ba7f66SAnna Dabrowska    {
22264ba7f66SAnna Dabrowska        $this->history('page_size');
22364ba7f66SAnna Dabrowska    }
22464ba7f66SAnna Dabrowska
22564ba7f66SAnna Dabrowska    public function history_media_count()
22664ba7f66SAnna Dabrowska    {
22764ba7f66SAnna Dabrowska        $this->history('media_count');
22864ba7f66SAnna Dabrowska    }
22964ba7f66SAnna Dabrowska
23064ba7f66SAnna Dabrowska    public function history_media_size()
23164ba7f66SAnna Dabrowska    {
23264ba7f66SAnna Dabrowska        $this->history('media_size');
23364ba7f66SAnna Dabrowska    }
23464ba7f66SAnna Dabrowska
23564ba7f66SAnna Dabrowska    public function dashboardviews()
23664ba7f66SAnna Dabrowska    {
23764ba7f66SAnna Dabrowska        $hours  = ($this->from == $this->to);
238211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->dashboardviews($hours);
23964ba7f66SAnna Dabrowska        $data1  = [];
24064ba7f66SAnna Dabrowska        $data2  = [];
24164ba7f66SAnna Dabrowska        $data3  = [];
24264ba7f66SAnna Dabrowska        $times  = [];
24364ba7f66SAnna Dabrowska
24464ba7f66SAnna Dabrowska        foreach ($result as $time => $row) {
24564ba7f66SAnna Dabrowska            $data1[] = (int) $row['pageviews'];
24664ba7f66SAnna Dabrowska            $data2[] = (int) $row['sessions'];
24764ba7f66SAnna Dabrowska            $data3[] = (int) $row['visitors'];
24864ba7f66SAnna Dabrowska            $times[] = $time . ($hours ? 'h' : '');
24964ba7f66SAnna Dabrowska        }
25064ba7f66SAnna Dabrowska
25164ba7f66SAnna Dabrowska        $data = [
25264ba7f66SAnna Dabrowska            'datasets' => [
25364ba7f66SAnna Dabrowska                [
25464ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_views'),
25564ba7f66SAnna Dabrowska                    'data' => $data1,
25664ba7f66SAnna Dabrowska                ],
25764ba7f66SAnna Dabrowska                [
25864ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_sessions'),
25964ba7f66SAnna Dabrowska                    'data' => $data2,
26064ba7f66SAnna Dabrowska                ],
26164ba7f66SAnna Dabrowska                [
26264ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_visitors'),
26364ba7f66SAnna Dabrowska                    'data' => $data3,
26464ba7f66SAnna Dabrowska                ],
26564ba7f66SAnna Dabrowska            ],
26664ba7f66SAnna Dabrowska            'labels' => $times
26764ba7f66SAnna Dabrowska        ];
26864ba7f66SAnna Dabrowska
26964ba7f66SAnna Dabrowska        $this->printGraph('dashboardviews', 'line', $data);
27064ba7f66SAnna Dabrowska    }
27164ba7f66SAnna Dabrowska
27264ba7f66SAnna Dabrowska    public function dashboardwiki($js = false)
27364ba7f66SAnna Dabrowska    {
27464ba7f66SAnna Dabrowska        $hours  = ($this->from == $this->to);
275211caa5dSAndreas Gohr        $result = $this->hlp->getQuery()->dashboardwiki($hours);
27664ba7f66SAnna Dabrowska        $data1  = [];
27764ba7f66SAnna Dabrowska        $data2  = [];
27864ba7f66SAnna Dabrowska        $data3  = [];
27964ba7f66SAnna Dabrowska        $times  = [];
28064ba7f66SAnna Dabrowska
28164ba7f66SAnna Dabrowska        foreach ($result as $time => $row) {
28264ba7f66SAnna Dabrowska            $data1[] = (int) $row['E'];
28364ba7f66SAnna Dabrowska            $data2[] = (int) $row['C'];
28464ba7f66SAnna Dabrowska            $data3[] = (int) $row['D'];
28564ba7f66SAnna Dabrowska            $times[] = $time . ($hours ? 'h' : '');
28664ba7f66SAnna Dabrowska        }
28764ba7f66SAnna Dabrowska        $data = [
28864ba7f66SAnna Dabrowska            'datasets' => [
28964ba7f66SAnna Dabrowska                [
29064ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_edits'),
29164ba7f66SAnna Dabrowska                    'data' => $data1,
29264ba7f66SAnna Dabrowska                ],
29364ba7f66SAnna Dabrowska                [
29464ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_creates'),
29564ba7f66SAnna Dabrowska                    'data' => $data2,
29664ba7f66SAnna Dabrowska                ],
29764ba7f66SAnna Dabrowska                [
29864ba7f66SAnna Dabrowska                    'label' => $this->hlp->getLang('graph_deletions'),
29964ba7f66SAnna Dabrowska                    'data' => $data3,
30064ba7f66SAnna Dabrowska                ],
30164ba7f66SAnna Dabrowska            ],
30264ba7f66SAnna Dabrowska            'labels' => $times
30364ba7f66SAnna Dabrowska        ];
30464ba7f66SAnna Dabrowska
30564ba7f66SAnna Dabrowska        $this->printGraph('dashboardwiki', 'line', $data);
30664ba7f66SAnna Dabrowska    }
30764ba7f66SAnna Dabrowska
30864ba7f66SAnna Dabrowska    /**
30964ba7f66SAnna Dabrowska     * @param string $name
31064ba7f66SAnna Dabrowska     * @param string $type
31164ba7f66SAnna Dabrowska     * @param array $data
31264ba7f66SAnna Dabrowska     * @return void
31364ba7f66SAnna Dabrowska     */
31464ba7f66SAnna Dabrowska    protected function printGraph(string $name, string $type, array $data)
31564ba7f66SAnna Dabrowska    {
31664ba7f66SAnna Dabrowska        $json = htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8');
317*b92383f5SAndreas Gohr        $tpl = '
31864ba7f66SAnna Dabrowska        <chart-component
319*b92383f5SAndreas Gohr            width="%d"
320*b92383f5SAndreas Gohr            height="%d"
32164ba7f66SAnna Dabrowska            name="%s"
32264ba7f66SAnna Dabrowska            type="%s"
32364ba7f66SAnna Dabrowska            data="%s"></chart-component>
324*b92383f5SAndreas Gohr        ';
32564ba7f66SAnna Dabrowska
326*b92383f5SAndreas Gohr        echo sprintf($tpl, $this->width, $this->height, $name, $type, $json);
32764ba7f66SAnna Dabrowska    }
32864ba7f66SAnna Dabrowska
32964ba7f66SAnna Dabrowska    #endregion Graphbuilding functions
33064ba7f66SAnna Dabrowska}
331