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>Access Statistics</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 * @fixme does this still work? 132 * 133 * @param type $limit 134 * @param type $next 135 */ 136 function html_pager($limit,$next){ 137 echo '<div class="plg_stats_pager">'; 138 139 if($this->start > 0){ 140 $go = max($this->start - $limit, 0); 141 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">previous page</a>'; 142 } 143 144 if($next){ 145 $go = $this->start + $limit; 146 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="next">next page</a>'; 147 } 148 echo '</div>'; 149 } 150 151 /** 152 * Print the time selection menu 153 */ 154 function html_timeselect(){ 155 $today = date('Y-m-d'); 156 $last1 = date('Y-m-d',time()-(60*60*24)); 157 $last7 = date('Y-m-d',time()-(60*60*24*7)); 158 $last30 = date('Y-m-d',time()-(60*60*24*30)); 159 160 echo '<div class="plg_stats_timeselect">'; 161 echo '<span>'.$this->getLang('time_select').'</span> '; 162 163 echo '<form action="" method="get">'; 164 echo '<input type="hidden" name="do" value="admin" />'; 165 echo '<input type="hidden" name="page" value="statistics" />'; 166 echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 167 echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 168 echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 169 echo '<input type="submit" value="go" class="button" />'; 170 echo '</form>'; 171 172 echo '<ul>'; 173 foreach(array('today','last1','last7','last30') as $time){ 174 echo '<li>'; 175 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$$time.'&t='.$today.'">'; 176 echo $this->getLang('time_'.$time); 177 echo '</a>'; 178 echo '</li>'; 179 } 180 echo '</ul>'; 181 182 echo '</div>'; 183 } 184 185 186 /** 187 * Print an introductionary screen 188 */ 189 function html_dashboard(){ 190 echo '<p>'.$this->getLang('intro_dashboard').'</p>'; 191 192 // general info 193 echo '<div class="plg_stats_top">'; 194 $result = $this->hlp->Query()->aggregate($this->tlimit); 195 196 echo '<ul class="left">'; 197 foreach(array('pageviews','sessions','visitors','users','logins') as $name){ 198 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 199 } 200 echo '</ul>'; 201 202 echo '<ul class="left">'; 203 foreach(array('bouncerate','timespent','avgpages','newvisitors','registrations') as $name){ 204 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 205 } 206 echo '</ul>'; 207 208 $this->html_graph('trend',700,280); 209 echo '</div>'; 210 211 212 // top pages today 213 echo '<div>'; 214 echo '<h2>'.$this->getLang('dash_mostpopular').'</h2>'; 215 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15); 216 $this->html_resulttable($result); 217 echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 218 echo '</div>'; 219 220 // top referer today 221 echo '<div>'; 222 echo '<h2>'.$this->getLang('dash_newincoming').'</h2>'; 223 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15); 224 $this->html_resulttable($result); 225 echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 226 echo '</div>'; 227 228 // top searches today 229 echo '<div>'; 230 echo '<h2>'.$this->getLang('dash_topsearch').'</h2>'; 231 $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15); 232 $this->html_resulttable($result); 233 echo '<a href="?do=admin&page=statistics&opt=searchphrases&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 234 echo '</div>'; 235 } 236 237 function html_countries(){ 238 echo '<p>'.$this->getLang('intro_countries').'</p>'; 239 $this->html_graph('countries',400,200); 240 $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150); 241 $this->html_resulttable($result,'',150); 242 } 243 244 function html_page(){ 245 echo '<p>'.$this->getLang('intro_page').'</p>'; 246 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,150); 247 $this->html_resulttable($result,'',150); 248 } 249 250 function html_browsers(){ 251 echo '<p>'.$this->getLang('intro_browsers').'</p>'; 252 $this->html_graph('browsers',400,200); 253 $result = $this->hlp->Query()->browsers($this->tlimit,$this->start,150,true); 254 $this->html_resulttable($result,'',150); 255 } 256 257 function html_os(){ 258 echo '<p>'.$this->getLang('intro_os').'</p>'; 259 $this->html_graph('os',400,200); 260 $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true); 261 $this->html_resulttable($result,'',150); 262 } 263 264 function html_referer(){ 265 $result = $this->hlp->Query()->aggregate($this->tlimit); 266 267 $all = $result['search']+$result['external']+$result['direct']; 268 269 if($all){ 270 printf('<p>'.$this->getLang('intro_referer').'</p>', 271 $all,$result['direct'],(100*$result['direct']/$all), 272 $result['search'],(100*$result['search']/$all),$result['external'], 273 (100*$result['external']/$all)); 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 $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="lookup in 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="lookup in Yahoo" border="0" />'; 381 echo '</a> '; 382 383 echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; 384 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; 385 echo '</a> '; 386 387 }elseif($k == 'engine'){ 388 include_once(dirname(__FILE__).'/inc/search_engines.php'); 389 echo $SearchEnginesHashLib[$v]; 390 }elseif($k == 'bflag'){ 391 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 392 }elseif($k == 'osflag'){ 393 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 394 }elseif($k == 'cflag'){ 395 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 396 }elseif($k == 'html'){ 397 echo $v; 398 }else{ 399 echo hsc($v); 400 } 401 echo '</td>'; 402 } 403 echo '</tr>'; 404 405 if($pager && ($count == $pager)) break; 406 $count++; 407 } 408 echo '</table>'; 409 410 if($pager) $this->html_pager($pager,count($result) > $pager); 411 } 412 413} 414