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/** 14 * All DokuWiki plugins to extend the admin function 15 * need to inherit from this class 16 */ 17class admin_plugin_statistics extends DokuWiki_Admin_Plugin { 18 public $dblink = null; 19 protected $opt = ''; 20 protected $from = ''; 21 protected $to = ''; 22 protected $start = ''; 23 protected $tlimit = ''; 24 25 /** 26 * Available statistic pages 27 */ 28 protected $pages = array('dashboard','page','referer','newreferer', 29 'outlinks','searchengines','searchphrases', 30 'searchwords', 'internalsearchphrases', 31 'internalsearchwords','browsers','os', 32 'countries','resolution','viewport'); 33 34 /** 35 * Initialize the helper 36 */ 37 public function __construct() { 38 $this->hlp = plugin_load('helper','statistics'); 39 } 40 41 /** 42 * Access for managers allowed 43 */ 44 public function forAdminOnly(){ 45 return false; 46 } 47 48 /** 49 * return sort order for position in admin menu 50 */ 51 public function getMenuSort() { 52 return 350; 53 } 54 55 /** 56 * handle user request 57 */ 58 public function handle() { 59 $this->opt = preg_replace('/[^a-z]+/','',$_REQUEST['opt']); 60 if(!in_array($this->opt,$this->pages)) $this->opt = 'dashboard'; 61 62 $this->start = (int) $_REQUEST['s']; 63 $this->setTimeframe($_REQUEST['f'],$_REQUEST['t']); 64 } 65 66 /** 67 * set limit clause 68 */ 69 public function setTimeframe($from,$to){ 70 // fixme add better sanity checking here: 71 $from = preg_replace('/[^\d\-]+/','',$from); 72 $to = preg_replace('/[^\d\-]+/','',$to); 73 if(!$from) $from = date('Y-m-d'); 74 if(!$to) $to = date('Y-m-d'); 75 76 //setup limit clause 77 $tlimit = "A.dt >= '$from 00:00:00' AND A.dt <= '$to 23:59:59'"; 78 $this->tlimit = $tlimit; 79 $this->from = $from; 80 $this->to = $to; 81 } 82 83 /** 84 * Output the Statistics 85 */ 86 function html() { 87 echo '<div id="plugin__statistics">'; 88 echo '<h1>'.$this->getLang('menu').'</h1>'; 89 $this->html_timeselect(); 90 tpl_flush(); 91 92 $method = 'html_'.$this->opt; 93 if(method_exists($this,$method)){ 94 echo '<div class="plg_stats_'.$this->opt.'">'; 95 echo '<h2>'.$this->getLang($this->opt).'</h2>'; 96 $this->$method(); 97 echo '</div>'; 98 } 99 echo '</div>'; 100 } 101 102 /** 103 * Return the TOC 104 * 105 * @return array 106 */ 107 function getTOC(){ 108 $toc = array(); 109 foreach($this->pages as $page){ 110 $toc[] = array( 111 'link' => '?do=admin&page=statistics&opt='.$page.'&f='.$this->from.'&t='.$this->to, 112 'title' => $this->getLang($page), 113 'level' => 1, 114 'type' => 'ul' 115 ); 116 } 117 return $toc; 118 } 119 120 121 function html_graph($name,$width,$height){ 122 $url = DOKU_BASE.'lib/plugins/statistics/img.php?img='.$name. 123 '&f='.$this->from.'&t='.$this->to; 124 echo '<img src="'.$url.'" class="graph" width="'.$width.'" height="'.$height.'"/>'; 125 } 126 127 128 /** 129 * Outputs pagination links 130 * 131 * @param type $limit 132 * @param type $next 133 */ 134 function html_pager($limit,$next){ 135 echo '<div class="plg_stats_pager">'; 136 137 if($this->start > 0){ 138 $go = max($this->start - $limit, 0); 139 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">'.$this->getLang('prev').'</a>'; 140 } 141 142 if($next){ 143 $go = $this->start + $limit; 144 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="next">'.$this->getLang('next').'</a>'; 145 } 146 echo '</div>'; 147 } 148 149 /** 150 * Print the time selection menu 151 */ 152 function html_timeselect(){ 153 $today = date('Y-m-d'); 154 $last1 = date('Y-m-d',time()-(60*60*24)); 155 $last7 = date('Y-m-d',time()-(60*60*24*7)); 156 $last30 = date('Y-m-d',time()-(60*60*24*30)); 157 158 echo '<div class="plg_stats_timeselect">'; 159 echo '<span>'.$this->getLang('time_select').'</span> '; 160 161 echo '<form action="" method="get">'; 162 echo '<input type="hidden" name="do" value="admin" />'; 163 echo '<input type="hidden" name="page" value="statistics" />'; 164 echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 165 echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 166 echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 167 echo '<input type="submit" value="go" class="button" />'; 168 echo '</form>'; 169 170 echo '<ul>'; 171 foreach(array('today','last1','last7','last30') as $time){ 172 echo '<li>'; 173 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$$time.'&t='.$today.'">'; 174 echo $this->getLang('time_'.$time); 175 echo '</a>'; 176 echo '</li>'; 177 } 178 echo '</ul>'; 179 180 echo '</div>'; 181 } 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') 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('trend',700,280); 207 echo '</div>'; 208 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">'.$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">'.$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($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">'.$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('<p>'.$this->getLang('intro_referer').'</p>', 269 $all,$result['direct'],(100*$result['direct']/$all), 270 $result['search'],(100*$result['search']/$all),$result['external'], 271 (100*$result['external']/$all)); 272 } 273 274 $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150); 275 $this->html_resulttable($result,'',150); 276 } 277 278 function html_newreferer(){ 279 echo '<p>'.$this->getLang('intro_newreferer').'</p>'; 280 281 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,150); 282 $this->html_resulttable($result,'',150); 283 } 284 285 function html_outlinks(){ 286 echo '<p>'.$this->getLang('intro_outlinks').'</p>'; 287 $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150); 288 $this->html_resulttable($result,'',150); 289 } 290 291 function html_searchphrases(){ 292 echo '<p>'.$this->getLang('intro_searchphrases').'</p>'; 293 $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150); 294 $this->html_resulttable($result,'',150); 295 } 296 297 function html_searchwords(){ 298 echo '<p>'.$this->getLang('intro_searchwords').'</p>'; 299 $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150); 300 $this->html_resulttable($result,'',150); 301 } 302 303 function html_internalsearchphrases(){ 304 echo '<p>'.$this->getLang('intro_internalsearchphrases').'</p>'; 305 $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150); 306 $this->html_resulttable($result,'',150); 307 } 308 309 function html_internalsearchwords(){ 310 echo '<p>'.$this->getLang('intro_internalsearchwords').'</p>'; 311 $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150); 312 $this->html_resulttable($result,'',150); 313 } 314 315 function html_searchengines(){ 316 echo '<p>'.$this->getLang('intro_searchengines').'</p>'; 317 $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150); 318 $this->html_resulttable($result,'',150); 319 } 320 321 function html_resolution(){ 322 echo '<p>'.$this->getLang('intro_resolution').'</p>'; 323 $this->html_graph('resolution',650,490); 324 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 325 $this->html_resulttable($result,'',150); 326 } 327 328 function html_viewport(){ 329 echo '<p>'.$this->getLang('intro_viewport').'</p>'; 330 $this->html_graph('viewport',650,490); 331 $result = $this->hlp->Query()->viewport($this->tlimit,$this->start,150); 332 $this->html_resulttable($result,'',150); 333 } 334 335 336 /** 337 * Display a result in a HTML table 338 */ 339 function html_resulttable($result,$header='',$pager=0){ 340 echo '<table>'; 341 if(is_array($header)){ 342 echo '<tr>'; 343 foreach($header as $h){ 344 echo '<th>'.hsc($h).'</th>'; 345 } 346 echo '</tr>'; 347 } 348 349 $count = 0; 350 if(is_array($result)) foreach($result as $row){ 351 echo '<tr>'; 352 foreach($row as $k => $v){ 353 if($k == 'res_x') continue; 354 if($k == 'res_y') continue; 355 356 echo '<td class="plg_stats_X'.$k.'">'; 357 if($k == 'page'){ 358 echo '<a href="'.wl($v).'" class="wikilink1">'; 359 echo hsc($v); 360 echo '</a>'; 361 }elseif($k == 'url'){ 362 $url = hsc($v); 363 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 364 if(strlen($url) > 45){ 365 $url = substr($url,0,30).' … '.substr($url,-15); 366 } 367 echo '<a href="'.$v.'" class="urlextern">'; 368 echo $url; 369 echo '</a>'; 370 }elseif($k == 'ilookup'){ 371 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 372 }elseif($k == 'lookup'){ 373 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 374 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="Google" border="0" />'; 375 echo '</a> '; 376 377 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 378 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="Yahoo!" border="0" />'; 379 echo '</a> '; 380 381 echo '<a href="http://www.bing.com/search?q='.rawurlencode($v).'">'; 382 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/bing.png" alt="Bing" border="0" />'; 383 echo '</a> '; 384 385 }elseif($k == 'engine'){ 386 include_once(dirname(__FILE__).'/inc/searchengines.php'); 387 if(isset($SEARCHENGINEINFO[$v])){ 388 echo '<a href="'.$SEARCHENGINEINFO[$v][1].'">'.$SEARCHENGINEINFO[$v][0].'</a>'; 389 }else{ 390 echo hsc(ucwords($v)); 391 } 392 }elseif($k == 'eflag'){ 393 $this->html_icon('search',$v); 394 }elseif($k == 'bflag'){ 395 $this->html_icon('browser',$v); 396 }elseif($k == 'osflag'){ 397 $this->html_icon('os',$v); 398 }elseif($k == 'cflag'){ 399 $this->html_icon('flags',$v); 400 }elseif($k == 'html'){ 401 echo $v; 402 }else{ 403 echo hsc($v); 404 } 405 echo '</td>'; 406 } 407 echo '</tr>'; 408 409 if($pager && ($count == $pager)) break; 410 $count++; 411 } 412 echo '</table>'; 413 414 if($pager) $this->html_pager($pager,count($result) > $pager); 415 } 416 417 function html_icon($type,$value){ 418 $value = strtolower(preg_replace('/[^\w]+/','',$value)); 419 $file = 'lib/plugins/statistics/ico/'.$type.'/'.$value.'.png'; 420 if(file_exists(DOKU_INC.$file)){ 421 echo '<img src="'.DOKU_BASE.$file.'" alt="'.hsc($value).'" width="16" height="16" />'; 422 } 423 } 424} 425