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('dashboardviews',700,280); 207 $this->html_graph('dashboardwiki',700,280); 208 echo '</div>'; 209 210 211 // top pages today 212 echo '<div>'; 213 echo '<h2>'.$this->getLang('dash_mostpopular').'</h2>'; 214 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15); 215 $this->html_resulttable($result); 216 echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">'.$this->getLang('more').'</a>'; 217 echo '</div>'; 218 219 // top referer today 220 echo '<div>'; 221 echo '<h2>'.$this->getLang('dash_newincoming').'</h2>'; 222 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15); 223 $this->html_resulttable($result); 224 echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">'.$this->getLang('more').'</a>'; 225 echo '</div>'; 226 227 // top searches today 228 echo '<div>'; 229 echo '<h2>'.$this->getLang('dash_topsearch').'</h2>'; 230 $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15); 231 $this->html_resulttable($result); 232 echo '<a href="?do=admin&page=statistics&opt=searchphrases&f='.$this->from.'&t='.$this->to.'" class="more">'.$this->getLang('more').'</a>'; 233 echo '</div>'; 234 } 235 236 function html_countries(){ 237 echo '<p>'.$this->getLang('intro_countries').'</p>'; 238 $this->html_graph('countries',400,200); 239 $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150); 240 $this->html_resulttable($result,'',150); 241 } 242 243 function html_page(){ 244 echo '<p>'.$this->getLang('intro_page').'</p>'; 245 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,150); 246 $this->html_resulttable($result,'',150); 247 } 248 249 function html_browsers(){ 250 echo '<p>'.$this->getLang('intro_browsers').'</p>'; 251 $this->html_graph('browsers',400,200); 252 $result = $this->hlp->Query()->browsers($this->tlimit,$this->start,150,true); 253 $this->html_resulttable($result,'',150); 254 } 255 256 function html_os(){ 257 echo '<p>'.$this->getLang('intro_os').'</p>'; 258 $this->html_graph('os',400,200); 259 $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true); 260 $this->html_resulttable($result,'',150); 261 } 262 263 function html_referer(){ 264 $result = $this->hlp->Query()->aggregate($this->tlimit); 265 266 $all = $result['search']+$result['external']+$result['direct']; 267 268 if($all){ 269 printf('<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 $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150); 276 $this->html_resulttable($result,'',150); 277 } 278 279 function html_newreferer(){ 280 echo '<p>'.$this->getLang('intro_newreferer').'</p>'; 281 282 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,150); 283 $this->html_resulttable($result,'',150); 284 } 285 286 function html_outlinks(){ 287 echo '<p>'.$this->getLang('intro_outlinks').'</p>'; 288 $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150); 289 $this->html_resulttable($result,'',150); 290 } 291 292 function html_searchphrases(){ 293 echo '<p>'.$this->getLang('intro_searchphrases').'</p>'; 294 $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150); 295 $this->html_resulttable($result,'',150); 296 } 297 298 function html_searchwords(){ 299 echo '<p>'.$this->getLang('intro_searchwords').'</p>'; 300 $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150); 301 $this->html_resulttable($result,'',150); 302 } 303 304 function html_internalsearchphrases(){ 305 echo '<p>'.$this->getLang('intro_internalsearchphrases').'</p>'; 306 $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150); 307 $this->html_resulttable($result,'',150); 308 } 309 310 function html_internalsearchwords(){ 311 echo '<p>'.$this->getLang('intro_internalsearchwords').'</p>'; 312 $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150); 313 $this->html_resulttable($result,'',150); 314 } 315 316 function html_searchengines(){ 317 echo '<p>'.$this->getLang('intro_searchengines').'</p>'; 318 $this->html_graph('searchengines',400,200); 319 $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150); 320 $this->html_resulttable($result,'',150); 321 } 322 323 function html_resolution(){ 324 echo '<p>'.$this->getLang('intro_resolution').'</p>'; 325 $this->html_graph('resolution',650,490); 326 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 327 $this->html_resulttable($result,'',150); 328 } 329 330 function html_viewport(){ 331 echo '<p>'.$this->getLang('intro_viewport').'</p>'; 332 $this->html_graph('viewport',650,490); 333 $result = $this->hlp->Query()->viewport($this->tlimit,$this->start,150); 334 $this->html_resulttable($result,'',150); 335 } 336 337 338 /** 339 * Display a result in a HTML table 340 */ 341 function html_resulttable($result,$header='',$pager=0){ 342 echo '<table>'; 343 if(is_array($header)){ 344 echo '<tr>'; 345 foreach($header as $h){ 346 echo '<th>'.hsc($h).'</th>'; 347 } 348 echo '</tr>'; 349 } 350 351 $count = 0; 352 if(is_array($result)) foreach($result as $row){ 353 echo '<tr>'; 354 foreach($row as $k => $v){ 355 if($k == 'res_x') continue; 356 if($k == 'res_y') continue; 357 358 echo '<td class="plg_stats_X'.$k.'">'; 359 if($k == 'page'){ 360 echo '<a href="'.wl($v).'" class="wikilink1">'; 361 echo hsc($v); 362 echo '</a>'; 363 }elseif($k == 'url'){ 364 $url = hsc($v); 365 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 366 if(strlen($url) > 45){ 367 $url = substr($url,0,30).' … '.substr($url,-15); 368 } 369 echo '<a href="'.$v.'" class="urlextern">'; 370 echo $url; 371 echo '</a>'; 372 }elseif($k == 'ilookup'){ 373 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 374 }elseif($k == 'lookup'){ 375 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 376 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="Google" border="0" />'; 377 echo '</a> '; 378 379 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 380 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="Yahoo!" border="0" />'; 381 echo '</a> '; 382 383 echo '<a href="http://www.bing.com/search?q='.rawurlencode($v).'">'; 384 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/bing.png" alt="Bing" border="0" />'; 385 echo '</a> '; 386 387 }elseif($k == 'engine'){ 388 include_once(dirname(__FILE__).'/inc/searchengines.php'); 389 if(isset($SEARCHENGINEINFO[$v])){ 390 echo '<a href="'.$SEARCHENGINEINFO[$v][1].'">'.$SEARCHENGINEINFO[$v][0].'</a>'; 391 }else{ 392 echo hsc(ucwords($v)); 393 } 394 }elseif($k == 'eflag'){ 395 $this->html_icon('search',$v); 396 }elseif($k == 'bflag'){ 397 $this->html_icon('browser',$v); 398 }elseif($k == 'osflag'){ 399 $this->html_icon('os',$v); 400 }elseif($k == 'cflag'){ 401 $this->html_icon('flags',$v); 402 }elseif($k == 'html'){ 403 echo $v; 404 }else{ 405 echo hsc($v); 406 } 407 echo '</td>'; 408 } 409 echo '</tr>'; 410 411 if($pager && ($count == $pager)) break; 412 $count++; 413 } 414 echo '</table>'; 415 416 if($pager) $this->html_pager($pager,count($result) > $pager); 417 } 418 419 function html_icon($type,$value){ 420 $value = strtolower(preg_replace('/[^\w]+/','',$value)); 421 $file = 'lib/plugins/statistics/ico/'.$type.'/'.$value.'.png'; 422 if(file_exists(DOKU_INC.$file)){ 423 echo '<img src="'.DOKU_BASE.$file.'" alt="'.hsc($value).'" width="16" height="16" />'; 424 } 425 } 426} 427