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