1<?php 2 3/** 4 * statdisplay plugin graph helper component 5 * 6 * @author Andreas Gohr <gohr@cosmocode.de> 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 */ 9class helper_plugin_statdisplay_graph extends DokuWiki_Plugin 10{ 11 /** @var helper_plugin_statdisplay_log */ 12 private $log = null; 13 14 /** 15 * Outputs a Graph image 16 * 17 * @param string $command 18 * @param string $from 19 * @param string $to 20 * @return void 21 */ 22 public function sendgraph($command, $from = '', $to = '') 23 { 24 require dirname(__FILE__) . '/../pchart/pData.php'; 25 require dirname(__FILE__) . '/../pchart/pChart.php'; 26 require dirname(__FILE__) . '/../pchart/GDCanvas.php'; 27 require dirname(__FILE__) . '/../pchart/PieChart.php'; 28 29 $this->log = plugin_load('helper', 'statdisplay_log'); 30 31 header('Content-Type: image/png'); 32 switch ($command) { 33 case 'all': 34 $this->summary(); 35 break; 36 case 'month by day': 37 $this->monthby('day', $from); 38 break; 39 case 'month by hour': 40 $this->monthby('hour', $from); 41 break; 42 case 'traffic by day': 43 $this->trafficby('day', $from); 44 break; 45 case 'traffic by hour': 46 $this->trafficby('hour', $from); 47 break; 48 case 'traffic by user': 49 $this->userdownloads($from); 50 break; 51 default: 52 $this->nograph('No such graph: ' . $command); 53 break; 54 } 55 } 56 57 /** 58 * Show all the access data 59 * 60 * @param string $from 61 * @param string $to 62 * @return void 63 */ 64 private function summary($from = '', $to = '') 65 { 66 $times = array(); 67 $hits = array(); 68 $pages = array(); 69 $media = array(); 70 $visitors = array(); 71 72 foreach ($this->log->logdata as $month => $data) { 73 if ($month[0] == '_') continue; 74 if ($from && $month < $from) continue; 75 if ($to && $month > $to) break; 76 77 $times[] = $month; 78 $pages[] = $data['page']['all']['count'] ?? 0; 79 $media[] = $data['media']['all']['count'] ?? 0; 80 $hits[] = $data['hits']['all']['count'] ?? 0; 81 $visitors[] = $data['hits']['all']['visitor'] ?? 0; 82 } 83 84 $title = $this->getLang('t_summary'); 85 86 $this->accessgraph( 87 $title, 88 $times, 89 array( 90 $this->getLang('hits'), 91 $this->getLang('pages'), 92 $this->getLang('media'), 93 $this->getLang('visitors'), 94 ), 95 array($hits, $pages, $media, $visitors) 96 ); 97 } 98 99 /** 100 * Show month access by day or hour 101 * 102 * @param string $by either day or hour 103 * @param string $date 104 */ 105 private function monthby($by, $date = '') 106 { 107 if (!$date) $date = date('Y-m'); 108 $data = $this->log->logdata[$date]; 109 110 $times = array(); 111 $hits = array(); 112 $pages = array(); 113 $media = array(); 114 $visitors = array(); 115 116 $keys = array_keys((array)$data['hits'][$by]); 117 sort($keys); 118 foreach ($keys as $idx) { 119 $times[] = $idx; 120 $pages[] = $data['page'][$by][$idx]['count']; 121 $media[] = $data['media'][$by][$idx]['count']; 122 $hits[] = $data['hits'][$by][$idx]['count']; 123 $visitors[] = $data['hits'][$by][$idx]['visitor']; 124 } 125 126 $title = sprintf($this->getLang('t_' . $by), $date); 127 128 $this->accessgraph( 129 $title, 130 $times, 131 array( 132 $this->getLang('hits'), 133 $this->getLang('pages'), 134 $this->getLang('media'), 135 $this->getLang('visitors'), 136 ), 137 array($hits, $pages, $media, $visitors) 138 ); 139 } 140 141 /** 142 * Show month traffic by day or hour 143 * 144 * @param string $by either day or hour 145 * @param string $date 146 */ 147 private function trafficby($by, $date = '') 148 { 149 if (!$date) $date = date('Y-m'); 150 $data = $this->log->logdata[$date]; 151 152 $times = array(); 153 $hits = array(); 154 $pages = array(); 155 $media = array(); 156 157 foreach (array_keys((array)$data['hits'][$by]) as $idx) { 158 $times[] = $idx; 159 $pages[] = $data['page'][$by][$idx]['bytes'] / 1024; 160 $media[] = $data['media'][$by][$idx]['bytes'] / 1024; 161 $hits[] = $data['hits'][$by][$idx]['bytes'] / 1024; 162 } 163 164 $title = 'Traffic'; 165 166 $this->accessgraph( 167 $title, 168 $times, 169 array( 170 $this->getLang('all'), 171 $this->getLang('pages'), 172 $this->getLang('media'), 173 ), 174 array($hits, $pages, $media) 175 ); 176 } 177 178 /** 179 * @param string $date month to display 180 */ 181 private function userdownloads($date) 182 { 183 $usertraffic = $this->log->usertraffic($date); 184 if (!$usertraffic) $this->nograph($this->getLang('t_usertraffic') . ': no data'); 185 186 $usertraffic = array_map(function ($in) { 187 return $in / 1024 / 1024; 188 }, $usertraffic); 189 190 // get work day average 191 if (count($usertraffic)) { 192 $avg = $this->log->avg($usertraffic); 193 // $avg = $avg / 7 *5; //work day average 194 } else { 195 $avg = 0; 196 } 197 arsort($usertraffic); // highest first 198 199 // limit number of users shown 200 $maxusers = 10; 201 if (count($usertraffic) > $maxusers + 1) { 202 $others = array_slice($usertraffic, $maxusers); 203 $usertraffic = array_slice($usertraffic, 0, $maxusers); 204 205 $other = 0; 206 foreach ($others as $user => $traffic) { 207 $other += $traffic; 208 } 209 210 $usertraffic[sprintf($this->getLang('others'), count($others))] = $other; 211 } 212 213 // prepare the graph datasets 214 $DataSet = new pData(); 215 $DataSet->addPoints(array_values($usertraffic), "traffic"); 216 217 // setup axis 218 $DataSet->AddPoints(array_keys($usertraffic), 'names'); 219 $DataSet->AddAllSeries(); 220 $DataSet->SetAbscissaLabelSeries('names'); 221 $DataSet->removeSeries('names'); 222 $DataSet->removeSeriesName('names'); 223 224 // create the bar graph 225 $Canvas = new GDCanvas(600, 300, false); 226 $Chart = new pChart(600, 300, $Canvas); 227 228 $Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 8); 229 $Chart->setGraphArea(50, 40, 600, 200); 230 $Chart->drawScale( 231 $DataSet, new ScaleStyle(SCALE_NORMAL, new Color(127)), 232 45, 1, true 233 ); 234 235 $Chart->drawBarGraph($DataSet->GetData(), $DataSet->GetDataDescription()); 236 //$Chart->drawLegend(500, 40, $DataSet->GetDataDescription(), new Color(250)); 237 238 $Chart->drawTreshold($avg, new Color(128, 0, 0)); 239 240 $Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 12); 241 $Chart->drawTitle(10, 10, $this->getLang('t_usertraffic') . ' (MB)', new Color(0), 590, 30); 242 243 $Chart->Render(null); 244 245 } 246 247 /** 248 * Draws a line or bargraph depending on the number of data points 249 * 250 * @param string $title the graph's title 251 * @param array $axis the axis points 252 * @param array $labels the labels for the datasets 253 * @param array $datasets any number of data arrays 254 */ 255 private function accessgraph($title, $axis, $labels, $datasets) 256 { 257 if (!count($axis)) { 258 $this->nograph($title . ': no data'); 259 return; 260 } 261 262 // add the data and labels 263 $DataSet = new pData(); 264 foreach ($datasets as $num => $set) { 265 $DataSet->AddPoints($set, "series$num"); 266 $DataSet->SetSeriesName($labels[$num], "series$num"); 267 } 268 269 // setup axis 270 $DataSet->AddPoints($axis, 'times'); 271 $DataSet->AddAllSeries(); 272 $DataSet->SetAbscissaLabelSeries('times'); 273 $DataSet->removeSeries('times'); 274 $DataSet->removeSeriesName('times'); 275 276 $Canvas = new GDCanvas(600, 300, false); 277 $Chart = new pChart(600, 300, $Canvas); 278 $usebargraph = (count($axis) < 10); 279 280 $Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 8); 281 $Chart->setGraphArea(50, 40, 500, 200); 282 $Chart->drawScale( 283 $DataSet, new ScaleStyle(SCALE_NORMAL, new Color(127)), 284 45, 1, $usebargraph 285 ); 286 287 if ($usebargraph) { 288 $Chart->drawBarGraph($DataSet->GetData(), $DataSet->GetDataDescription()); 289 } else { 290 $Chart->drawLineGraph($DataSet->GetData(), $DataSet->GetDataDescription()); 291 } 292 $Chart->drawLegend(500, 40, $DataSet->GetDataDescription(), new Color(250)); 293 294 $Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 12); 295 $Chart->drawTitle(10, 10, $title, new Color(0), 590, 30); 296 297 $Chart->Render(null); 298 } 299 300 /** 301 * Just creates a message 302 * 303 * @param $title 304 */ 305 private function nograph($title) 306 { 307 $Canvas = new GDCanvas(300, 40, false); 308 $Chart = new pChart(300, 40, $Canvas); 309 $Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 10); 310 $Chart->drawTitle(0, 0, $title, new Color(128, 0, 0), 300, 40); 311 $Chart->Render(null); 312 exit; 313 } 314} 315