1<?php 2/** 3 * statistics plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <gohr@splitbrain.org> 7 */ 8 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11 12/** 13 * All DokuWiki plugins to extend the admin function 14 * need to inherit from this class 15 */ 16class admin_plugin_statistics extends DokuWiki_Admin_Plugin { 17 /** @var string the currently selected page */ 18 protected $opt = ''; 19 20 /** @var string from date in YYYY-MM-DD */ 21 protected $from = ''; 22 /** @var string to date in YYYY-MM-DD */ 23 protected $to = ''; 24 /** @var int Offset to use when displaying paged data */ 25 protected $start = 0; 26 27 /** @var string MySQL timelimit statement */ 28 protected $tlimit = ''; 29 30 /** @var helper_plugin_statistics */ 31 protected $hlp; 32 33 /** 34 * Available statistic pages 35 */ 36 protected $pages = array( 37 'dashboard', 'page', 'referer', 'newreferer', 38 'outlinks', 'searchengines', 'searchphrases', 39 'searchwords', 'internalsearchphrases', 40 'internalsearchwords', 'browsers', 'os', 41 'countries', 'resolution', 'viewport', 42 'seenusers' 43 ); 44 45 /** 46 * Initialize the helper 47 */ 48 public function __construct() { 49 $this->hlp = plugin_load('helper', 'statistics'); 50 } 51 52 /** 53 * Access for managers allowed 54 */ 55 public function forAdminOnly() { 56 return false; 57 } 58 59 /** 60 * return sort order for position in admin menu 61 */ 62 public function getMenuSort() { 63 return 350; 64 } 65 66 /** 67 * handle user request 68 */ 69 public function handle() { 70 $this->opt = preg_replace('/[^a-z]+/', '', $_REQUEST['opt']); 71 if(!in_array($this->opt, $this->pages)) $this->opt = 'dashboard'; 72 73 $this->start = (int) $_REQUEST['s']; 74 $this->setTimeframe($_REQUEST['f'], $_REQUEST['t']); 75 } 76 77 /** 78 * set limit clause 79 */ 80 public function setTimeframe($from, $to) { 81 $this->tlimit = $this->hlp->Query()->mktlimit($from, $to); 82 $this->from = $from; 83 $this->to = $to; 84 } 85 86 /** 87 * Output the Statistics 88 */ 89 function html() { 90 echo '<div id="plugin__statistics">'; 91 echo '<h1>' . $this->getLang('menu') . '</h1>'; 92 $this->html_timeselect(); 93 tpl_flush(); 94 95 $method = 'html_' . $this->opt; 96 if(method_exists($this, $method)) { 97 echo '<div class="plg_stats_' . $this->opt . '">'; 98 echo '<h2>' . $this->getLang($this->opt) . '</h2>'; 99 $this->$method(); 100 echo '</div>'; 101 } 102 echo '</div>'; 103 } 104 105 /** 106 * Return the TOC 107 * 108 * @return array 109 */ 110 function getTOC() { 111 $toc = array(); 112 foreach($this->pages as $page) { 113 $toc[] = array( 114 'link' => '?do=admin&page=statistics&opt=' . $page . '&f=' . $this->from . '&t=' . $this->to, 115 'title' => $this->getLang($page), 116 'level' => 1, 117 'type' => 'ul' 118 ); 119 } 120 return $toc; 121 } 122 123 function html_graph($name, $width, $height) { 124 $url = DOKU_BASE . 'lib/plugins/statistics/img.php?img=' . $name . 125 '&f=' . $this->from . '&t=' . $this->to; 126 echo '<img src="' . $url . '" class="graph" width="' . $width . '" height="' . $height . '"/>'; 127 } 128 129 /** 130 * Outputs pagination links 131 * 132 * @param int $limit 133 * @param int $next 134 */ 135 function html_pager($limit, $next) { 136 echo '<div class="plg_stats_pager">'; 137 138 if($this->start > 0) { 139 $go = max($this->start - $limit, 0); 140 echo '<a href="?do=admin&page=statistics&opt=' . $this->opt . '&f=' . $this->from . '&t=' . $this->to . '&s=' . $go . '" class="prev button">' . $this->getLang('prev') . '</a>'; 141 } 142 143 if($next) { 144 $go = $this->start + $limit; 145 echo '<a href="?do=admin&page=statistics&opt=' . $this->opt . '&f=' . $this->from . '&t=' . $this->to . '&s=' . $go . '" class="next button">' . $this->getLang('next') . '</a>'; 146 } 147 echo '</div>'; 148 } 149 150 /** 151 * Print the time selection menu 152 */ 153 function html_timeselect() { 154 $today = date('Y-m-d'); 155 $last1 = date('Y-m-d', time() - (60 * 60 * 24)); 156 $last7 = date('Y-m-d', time() - (60 * 60 * 24 * 7)); 157 $last30 = date('Y-m-d', time() - (60 * 60 * 24 * 30)); 158 159 echo '<div class="plg_stats_timeselect">'; 160 echo '<span>' . $this->getLang('time_select') . '</span> '; 161 162 echo '<form action="" method="get">'; 163 echo '<input type="hidden" name="do" value="admin" />'; 164 echo '<input type="hidden" name="page" value="statistics" />'; 165 echo '<input type="hidden" name="opt" value="' . $this->opt . '" />'; 166 echo '<input type="text" name="f" value="' . $this->from . '" class="edit" />'; 167 echo '<input type="text" name="t" value="' . $this->to . '" class="edit" />'; 168 echo '<input type="submit" value="go" class="button" />'; 169 echo '</form>'; 170 171 echo '<ul>'; 172 foreach(array('today', 'last1', 'last7', 'last30') as $time) { 173 echo '<li>'; 174 echo '<a href="?do=admin&page=statistics&opt=' . $this->opt . '&f=' . $$time . '&t=' . $today . '">'; 175 echo $this->getLang('time_' . $time); 176 echo '</a>'; 177 echo '</li>'; 178 } 179 echo '</ul>'; 180 181 echo '</div>'; 182 } 183 184 /** 185 * Print an introductionary screen 186 */ 187 function html_dashboard() { 188 echo '<p>' . $this->getLang('intro_dashboard') . '</p>'; 189 190 // general info 191 echo '<div class="plg_stats_top">'; 192 $result = $this->hlp->Query()->aggregate($this->tlimit); 193 194 echo '<ul class="left">'; 195 foreach(array('pageviews', 'sessions', 'visitors', 'users', 'logins', 'current') as $name) { 196 echo '<li><div class="li">' . sprintf($this->getLang('dash_' . $name), $result[$name]) . '</div></li>'; 197 } 198 echo '</ul>'; 199 200 echo '<ul class="left">'; 201 foreach(array('bouncerate', 'timespent', 'avgpages', 'newvisitors', 'registrations') as $name) { 202 echo '<li><div class="li">' . sprintf($this->getLang('dash_' . $name), $result[$name]) . '</div></li>'; 203 } 204 echo '</ul>'; 205 206 $this->html_graph('dashboardviews', 700, 280); 207 $this->html_graph('dashboardwiki', 700, 280); 208 echo '</div>'; 209 210 // top pages today 211 echo '<div>'; 212 echo '<h2>' . $this->getLang('dash_mostpopular') . '</h2>'; 213 $result = $this->hlp->Query()->pages($this->tlimit, $this->start, 15); 214 $this->html_resulttable($result); 215 echo '<a href="?do=admin&page=statistics&opt=page&f=' . $this->from . '&t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>'; 216 echo '</div>'; 217 218 // top referer today 219 echo '<div>'; 220 echo '<h2>' . $this->getLang('dash_newincoming') . '</h2>'; 221 $result = $this->hlp->Query()->newreferer($this->tlimit, $this->start, 15); 222 $this->html_resulttable($result); 223 echo '<a href="?do=admin&page=statistics&opt=newreferer&f=' . $this->from . '&t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>'; 224 echo '</div>'; 225 226 // top searches today 227 echo '<div>'; 228 echo '<h2>' . $this->getLang('dash_topsearch') . '</h2>'; 229 $result = $this->hlp->Query()->searchphrases(true, $this->tlimit, $this->start, 15); 230 $this->html_resulttable($result); 231 echo '<a href="?do=admin&page=statistics&opt=searchphrases&f=' . $this->from . '&t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>'; 232 echo '</div>'; 233 } 234 235 function html_countries() { 236 echo '<p>' . $this->getLang('intro_countries') . '</p>'; 237 $this->html_graph('countries', 400, 200); 238 $result = $this->hlp->Query()->countries($this->tlimit, $this->start, 150); 239 $this->html_resulttable($result, '', 150); 240 } 241 242 function html_page() { 243 echo '<p>' . $this->getLang('intro_page') . '</p>'; 244 $result = $this->hlp->Query()->pages($this->tlimit, $this->start, 150); 245 $this->html_resulttable($result, '', 150); 246 } 247 248 function html_browsers() { 249 echo '<p>' . $this->getLang('intro_browsers') . '</p>'; 250 $this->html_graph('browsers', 400, 200); 251 $result = $this->hlp->Query()->browsers($this->tlimit, $this->start, 150, true); 252 $this->html_resulttable($result, '', 150); 253 } 254 255 function html_os() { 256 echo '<p>' . $this->getLang('intro_os') . '</p>'; 257 $this->html_graph('os', 400, 200); 258 $result = $this->hlp->Query()->os($this->tlimit, $this->start, 150, true); 259 $this->html_resulttable($result, '', 150); 260 } 261 262 function html_referer() { 263 $result = $this->hlp->Query()->aggregate($this->tlimit); 264 265 $all = $result['search'] + $result['external'] + $result['direct']; 266 267 if($all) { 268 printf( 269 '<p>' . $this->getLang('intro_referer') . '</p>', 270 $all, $result['direct'], (100 * $result['direct'] / $all), 271 $result['search'], (100 * $result['search'] / $all), $result['external'], 272 (100 * $result['external'] / $all) 273 ); 274 } 275 276 $result = $this->hlp->Query()->referer($this->tlimit, $this->start, 150); 277 $this->html_resulttable($result, '', 150); 278 } 279 280 function html_newreferer() { 281 echo '<p>' . $this->getLang('intro_newreferer') . '</p>'; 282 283 $result = $this->hlp->Query()->newreferer($this->tlimit, $this->start, 150); 284 $this->html_resulttable($result, '', 150); 285 } 286 287 function html_outlinks() { 288 echo '<p>' . $this->getLang('intro_outlinks') . '</p>'; 289 $result = $this->hlp->Query()->outlinks($this->tlimit, $this->start, 150); 290 $this->html_resulttable($result, '', 150); 291 } 292 293 function html_searchphrases() { 294 echo '<p>' . $this->getLang('intro_searchphrases') . '</p>'; 295 $result = $this->hlp->Query()->searchphrases(true, $this->tlimit, $this->start, 150); 296 $this->html_resulttable($result, '', 150); 297 } 298 299 function html_searchwords() { 300 echo '<p>' . $this->getLang('intro_searchwords') . '</p>'; 301 $result = $this->hlp->Query()->searchwords(true, $this->tlimit, $this->start, 150); 302 $this->html_resulttable($result, '', 150); 303 } 304 305 function html_internalsearchphrases() { 306 echo '<p>' . $this->getLang('intro_internalsearchphrases') . '</p>'; 307 $result = $this->hlp->Query()->searchphrases(false, $this->tlimit, $this->start, 150); 308 $this->html_resulttable($result, '', 150); 309 } 310 311 function html_internalsearchwords() { 312 echo '<p>' . $this->getLang('intro_internalsearchwords') . '</p>'; 313 $result = $this->hlp->Query()->searchwords(false, $this->tlimit, $this->start, 150); 314 $this->html_resulttable($result, '', 150); 315 } 316 317 function html_searchengines() { 318 echo '<p>' . $this->getLang('intro_searchengines') . '</p>'; 319 $this->html_graph('searchengines', 400, 200); 320 $result = $this->hlp->Query()->searchengines($this->tlimit, $this->start, 150); 321 $this->html_resulttable($result, '', 150); 322 } 323 324 function html_resolution() { 325 echo '<p>' . $this->getLang('intro_resolution') . '</p>'; 326 $this->html_graph('resolution', 650, 490); 327 $result = $this->hlp->Query()->resolution($this->tlimit, $this->start, 150); 328 $this->html_resulttable($result, '', 150); 329 } 330 331 function html_viewport() { 332 echo '<p>' . $this->getLang('intro_viewport') . '</p>'; 333 $this->html_graph('viewport', 650, 490); 334 $result = $this->hlp->Query()->viewport($this->tlimit, $this->start, 150); 335 $this->html_resulttable($result, '', 150); 336 } 337 338 function html_seenusers() { 339 echo '<p>' . $this->getLang('intro_seenusers') . '</p>'; 340 $result = $this->hlp->Query()->seenusers($this->tlimit, $this->start, 150); 341 $this->html_resulttable($result, '', 150); 342 } 343 344 /** 345 * Display a result in a HTML table 346 */ 347 function html_resulttable($result, $header = '', $pager = 0) { 348 echo '<table>'; 349 if(is_array($header)) { 350 echo '<tr>'; 351 foreach($header as $h) { 352 echo '<th>' . hsc($h) . '</th>'; 353 } 354 echo '</tr>'; 355 } 356 357 $count = 0; 358 if(is_array($result)) foreach($result as $row) { 359 echo '<tr>'; 360 foreach($row as $k => $v) { 361 if($k == 'res_x') continue; 362 if($k == 'res_y') continue; 363 364 echo '<td class="plg_stats_X' . $k . '">'; 365 if($k == 'page') { 366 echo '<a href="' . wl($v) . '" class="wikilink1">'; 367 echo hsc($v); 368 echo '</a>'; 369 } elseif($k == 'url') { 370 $url = hsc($v); 371 $url = preg_replace('/^https?:\/\/(www\.)?/', '', $url); 372 if(strlen($url) > 45) { 373 $url = substr($url, 0, 30) . ' … ' . substr($url, -15); 374 } 375 echo '<a href="' . $v . '" class="urlextern">'; 376 echo $url; 377 echo '</a>'; 378 } elseif($k == 'ilookup') { 379 echo '<a href="' . wl('', array('id' => $v, 'do' => 'search')) . '">Search</a>'; 380 } elseif($k == 'lookup') { 381 echo '<a href="http://www.google.com/search?q=' . rawurlencode($v) . '">'; 382 echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/google.png" alt="Google" border="0" />'; 383 echo '</a> '; 384 385 echo '<a href="http://search.yahoo.com/search?p=' . rawurlencode($v) . '">'; 386 echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/yahoo.png" alt="Yahoo!" border="0" />'; 387 echo '</a> '; 388 389 echo '<a href="http://www.bing.com/search?q=' . rawurlencode($v) . '">'; 390 echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/bing.png" alt="Bing" border="0" />'; 391 echo '</a> '; 392 393 } elseif($k == 'engine') { 394 include_once(dirname(__FILE__) . '/inc/searchengines.php'); 395 if(isset($SEARCHENGINEINFO[$v])) { 396 echo '<a href="' . $SEARCHENGINEINFO[$v][1] . '">' . $SEARCHENGINEINFO[$v][0] . '</a>'; 397 } else { 398 echo hsc(ucwords($v)); 399 } 400 } elseif($k == 'eflag') { 401 $this->html_icon('search', $v); 402 } elseif($k == 'bflag') { 403 $this->html_icon('browser', $v); 404 } elseif($k == 'osflag') { 405 $this->html_icon('os', $v); 406 } elseif($k == 'cflag') { 407 $this->html_icon('flags', $v); 408 } elseif($k == 'html') { 409 echo $v; 410 } else { 411 echo hsc($v); 412 } 413 echo '</td>'; 414 } 415 echo '</tr>'; 416 417 if($pager && ($count == $pager)) break; 418 $count++; 419 } 420 echo '</table>'; 421 422 if($pager) $this->html_pager($pager, count($result) > $pager); 423 } 424 425 function html_icon($type, $value) { 426 $value = strtolower(preg_replace('/[^\w]+/', '', $value)); 427 $value = str_replace(' ', '_', $value); 428 $file = 'lib/plugins/statistics/ico/' . $type . '/' . $value . '.png'; 429 if($type == 'flags') { 430 $w = 18; 431 $h = 12; 432 } else { 433 $w = 16; 434 $h = 16; 435 } 436 if(file_exists(DOKU_INC . $file)) { 437 echo '<img src="' . DOKU_BASE . $file . '" alt="' . hsc($value) . '" width="' . $w . '" height="' . $h . '" />'; 438 } 439 } 440} 441