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 144*9fdd7e51SAndreas Gohr public function topdomain() 145*9fdd7e51SAndreas Gohr { 146*9fdd7e51SAndreas Gohr $this->sumUpPieChart('topdomain', 'domain'); 147*9fdd7e51SAndreas Gohr } 148*9fdd7e51SAndreas Gohr 14964ba7f66SAnna Dabrowska public function topuser() 15064ba7f66SAnna Dabrowska { 15164ba7f66SAnna Dabrowska $this->sumUpPieChart('topuser', 'user'); 15264ba7f66SAnna Dabrowska } 15364ba7f66SAnna Dabrowska 15464ba7f66SAnna Dabrowska public function topeditor() 15564ba7f66SAnna Dabrowska { 15664ba7f66SAnna Dabrowska $this->sumUpPieChart('topeditor', 'user'); 15764ba7f66SAnna Dabrowska } 15864ba7f66SAnna Dabrowska 15964ba7f66SAnna Dabrowska public function topgroup() 16064ba7f66SAnna Dabrowska { 16164ba7f66SAnna Dabrowska $this->sumUpPieChart('topgroup', 'group'); 16264ba7f66SAnna Dabrowska } 16364ba7f66SAnna Dabrowska 16464ba7f66SAnna Dabrowska public function topgroupedit() 16564ba7f66SAnna Dabrowska { 16664ba7f66SAnna Dabrowska $this->sumUpPieChart('topgroupedit', 'group'); 16764ba7f66SAnna Dabrowska } 16864ba7f66SAnna Dabrowska 16964ba7f66SAnna Dabrowska public function viewport() 17064ba7f66SAnna Dabrowska { 171211caa5dSAndreas Gohr $result = $this->hlp->getQuery()->viewport(); 17264ba7f66SAnna Dabrowska $data = []; 17364ba7f66SAnna Dabrowska 17464ba7f66SAnna Dabrowska foreach ($result as $row) { 17564ba7f66SAnna Dabrowska $data[] = [ 17664ba7f66SAnna Dabrowska 'x' => $row['res_x'], 17764ba7f66SAnna Dabrowska 'y' => $row['res_y'], 17864ba7f66SAnna Dabrowska 'r' => floor($row['cnt'] / 10), 17964ba7f66SAnna Dabrowska ]; 18064ba7f66SAnna Dabrowska } 18164ba7f66SAnna Dabrowska 18264ba7f66SAnna Dabrowska $data = [ 18364ba7f66SAnna Dabrowska 'datasets' => [ 18464ba7f66SAnna Dabrowska [ 18564ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('viewport'), 18664ba7f66SAnna Dabrowska 'data' => $data 18764ba7f66SAnna Dabrowska ] 18864ba7f66SAnna Dabrowska ], 18964ba7f66SAnna Dabrowska ]; 19064ba7f66SAnna Dabrowska 19164ba7f66SAnna Dabrowska $this->printGraph('viewport', 'bubble', $data); 19264ba7f66SAnna Dabrowska } 19364ba7f66SAnna Dabrowska 19464ba7f66SAnna Dabrowska public function resolution() 19564ba7f66SAnna Dabrowska { 196211caa5dSAndreas Gohr $result = $this->hlp->getQuery()->resolution(); 19764ba7f66SAnna Dabrowska $data = []; 19864ba7f66SAnna Dabrowska 19964ba7f66SAnna Dabrowska foreach ($result as $row) { 20064ba7f66SAnna Dabrowska $data[] = [ 20164ba7f66SAnna Dabrowska 'x' => $row['res_x'], 20264ba7f66SAnna Dabrowska 'y' => $row['res_y'], 20364ba7f66SAnna Dabrowska 'r' => floor($row['cnt'] / 10), 20464ba7f66SAnna Dabrowska ]; 20564ba7f66SAnna Dabrowska } 20664ba7f66SAnna Dabrowska 20764ba7f66SAnna Dabrowska $data = [ 20864ba7f66SAnna Dabrowska 'datasets' => [ 20964ba7f66SAnna Dabrowska [ 21064ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('resolution'), 21164ba7f66SAnna Dabrowska 'data' => $data 21264ba7f66SAnna Dabrowska ] 21364ba7f66SAnna Dabrowska ], 21464ba7f66SAnna Dabrowska ]; 21564ba7f66SAnna Dabrowska 21664ba7f66SAnna Dabrowska $this->printGraph('resolution', 'bubble', $data); 21764ba7f66SAnna Dabrowska } 21864ba7f66SAnna Dabrowska 21964ba7f66SAnna Dabrowska 22064ba7f66SAnna Dabrowska public function history_page_count() 22164ba7f66SAnna Dabrowska { 22264ba7f66SAnna Dabrowska $this->history('page_count'); 22364ba7f66SAnna Dabrowska } 22464ba7f66SAnna Dabrowska 22564ba7f66SAnna Dabrowska public function history_page_size() 22664ba7f66SAnna Dabrowska { 22764ba7f66SAnna Dabrowska $this->history('page_size'); 22864ba7f66SAnna Dabrowska } 22964ba7f66SAnna Dabrowska 23064ba7f66SAnna Dabrowska public function history_media_count() 23164ba7f66SAnna Dabrowska { 23264ba7f66SAnna Dabrowska $this->history('media_count'); 23364ba7f66SAnna Dabrowska } 23464ba7f66SAnna Dabrowska 23564ba7f66SAnna Dabrowska public function history_media_size() 23664ba7f66SAnna Dabrowska { 23764ba7f66SAnna Dabrowska $this->history('media_size'); 23864ba7f66SAnna Dabrowska } 23964ba7f66SAnna Dabrowska 24064ba7f66SAnna Dabrowska public function dashboardviews() 24164ba7f66SAnna Dabrowska { 24264ba7f66SAnna Dabrowska $hours = ($this->from == $this->to); 243211caa5dSAndreas Gohr $result = $this->hlp->getQuery()->dashboardviews($hours); 24464ba7f66SAnna Dabrowska $data1 = []; 24564ba7f66SAnna Dabrowska $data2 = []; 24664ba7f66SAnna Dabrowska $data3 = []; 24764ba7f66SAnna Dabrowska $times = []; 24864ba7f66SAnna Dabrowska 24964ba7f66SAnna Dabrowska foreach ($result as $time => $row) { 25064ba7f66SAnna Dabrowska $data1[] = (int) $row['pageviews']; 25164ba7f66SAnna Dabrowska $data2[] = (int) $row['sessions']; 25264ba7f66SAnna Dabrowska $data3[] = (int) $row['visitors']; 25364ba7f66SAnna Dabrowska $times[] = $time . ($hours ? 'h' : ''); 25464ba7f66SAnna Dabrowska } 25564ba7f66SAnna Dabrowska 25664ba7f66SAnna Dabrowska $data = [ 25764ba7f66SAnna Dabrowska 'datasets' => [ 25864ba7f66SAnna Dabrowska [ 25964ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_views'), 26064ba7f66SAnna Dabrowska 'data' => $data1, 26164ba7f66SAnna Dabrowska ], 26264ba7f66SAnna Dabrowska [ 26364ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_sessions'), 26464ba7f66SAnna Dabrowska 'data' => $data2, 26564ba7f66SAnna Dabrowska ], 26664ba7f66SAnna Dabrowska [ 26764ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_visitors'), 26864ba7f66SAnna Dabrowska 'data' => $data3, 26964ba7f66SAnna Dabrowska ], 27064ba7f66SAnna Dabrowska ], 27164ba7f66SAnna Dabrowska 'labels' => $times 27264ba7f66SAnna Dabrowska ]; 27364ba7f66SAnna Dabrowska 27464ba7f66SAnna Dabrowska $this->printGraph('dashboardviews', 'line', $data); 27564ba7f66SAnna Dabrowska } 27664ba7f66SAnna Dabrowska 27764ba7f66SAnna Dabrowska public function dashboardwiki($js = false) 27864ba7f66SAnna Dabrowska { 27964ba7f66SAnna Dabrowska $hours = ($this->from == $this->to); 280211caa5dSAndreas Gohr $result = $this->hlp->getQuery()->dashboardwiki($hours); 28164ba7f66SAnna Dabrowska $data1 = []; 28264ba7f66SAnna Dabrowska $data2 = []; 28364ba7f66SAnna Dabrowska $data3 = []; 28464ba7f66SAnna Dabrowska $times = []; 28564ba7f66SAnna Dabrowska 28664ba7f66SAnna Dabrowska foreach ($result as $time => $row) { 2872a30f557SAndreas Gohr $data1[] = (int) ($row['E'] ?? 0); 2882a30f557SAndreas Gohr $data2[] = (int) ($row['C'] ?? 0); 2892a30f557SAndreas Gohr $data3[] = (int) ($row['D'] ?? 0); 29064ba7f66SAnna Dabrowska $times[] = $time . ($hours ? 'h' : ''); 29164ba7f66SAnna Dabrowska } 29264ba7f66SAnna Dabrowska $data = [ 29364ba7f66SAnna Dabrowska 'datasets' => [ 29464ba7f66SAnna Dabrowska [ 29564ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_edits'), 29664ba7f66SAnna Dabrowska 'data' => $data1, 29764ba7f66SAnna Dabrowska ], 29864ba7f66SAnna Dabrowska [ 29964ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_creates'), 30064ba7f66SAnna Dabrowska 'data' => $data2, 30164ba7f66SAnna Dabrowska ], 30264ba7f66SAnna Dabrowska [ 30364ba7f66SAnna Dabrowska 'label' => $this->hlp->getLang('graph_deletions'), 30464ba7f66SAnna Dabrowska 'data' => $data3, 30564ba7f66SAnna Dabrowska ], 30664ba7f66SAnna Dabrowska ], 30764ba7f66SAnna Dabrowska 'labels' => $times 30864ba7f66SAnna Dabrowska ]; 30964ba7f66SAnna Dabrowska 31064ba7f66SAnna Dabrowska $this->printGraph('dashboardwiki', 'line', $data); 31164ba7f66SAnna Dabrowska } 31264ba7f66SAnna Dabrowska 31364ba7f66SAnna Dabrowska /** 31464ba7f66SAnna Dabrowska * @param string $name 31564ba7f66SAnna Dabrowska * @param string $type 31664ba7f66SAnna Dabrowska * @param array $data 31764ba7f66SAnna Dabrowska * @return void 31864ba7f66SAnna Dabrowska */ 31964ba7f66SAnna Dabrowska protected function printGraph(string $name, string $type, array $data) 32064ba7f66SAnna Dabrowska { 32164ba7f66SAnna Dabrowska $json = htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8'); 322b92383f5SAndreas Gohr $tpl = ' 32364ba7f66SAnna Dabrowska <chart-component 324b92383f5SAndreas Gohr width="%d" 325b92383f5SAndreas Gohr height="%d" 32664ba7f66SAnna Dabrowska name="%s" 32764ba7f66SAnna Dabrowska type="%s" 32864ba7f66SAnna Dabrowska data="%s"></chart-component> 329b92383f5SAndreas Gohr '; 33064ba7f66SAnna Dabrowska 331b92383f5SAndreas Gohr echo sprintf($tpl, $this->width, $this->height, $name, $type, $json); 33264ba7f66SAnna Dabrowska } 33364ba7f66SAnna Dabrowska 33464ba7f66SAnna Dabrowska #endregion Graphbuilding functions 33564ba7f66SAnna Dabrowska} 336