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'); 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 324 function html_resolution(){ 325 326 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=resolution&f='.$this->from.'&t='.$this->to.'" />'; 327 328 echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 329 much about about the real size of their browser windows. The graphic below shows the size distribution of 330 the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 331 in all browsers. Because users may resize their browser window while browsing your site the statistics may 332 be flawed. Take it with a grain of salt.</p>'; 333 334 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=viewport&f='.$this->from.'&t='.$this->to.'" />'; 335 336 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 337 $this->html_resulttable($result,'',150); 338 339 340 } 341 342 343 /** 344 * Display a result in a HTML table 345 */ 346 function html_resulttable($result,$header='',$pager=0){ 347 echo '<table>'; 348 if(is_array($header)){ 349 echo '<tr>'; 350 foreach($header as $h){ 351 echo '<th>'.hsc($h).'</th>'; 352 } 353 echo '</tr>'; 354 } 355 356 $count = 0; 357 if(is_array($result)) foreach($result as $row){ 358 echo '<tr>'; 359 foreach($row as $k => $v){ 360 echo '<td class="plg_stats_X'.$k.'">'; 361 if($k == 'page'){ 362 echo '<a href="'.wl($v).'" class="wikilink1">'; 363 echo hsc($v); 364 echo '</a>'; 365 }elseif($k == 'url'){ 366 $url = hsc($v); 367 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 368 if(strlen($url) > 45){ 369 $url = substr($url,0,30).' … '.substr($url,-15); 370 } 371 echo '<a href="'.$v.'" class="urlextern">'; 372 echo $url; 373 echo '</a>'; 374 }elseif($k == 'ilookup'){ 375 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 376 }elseif($k == 'lookup'){ 377 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 378 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />'; 379 echo '</a> '; 380 381 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 382 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />'; 383 echo '</a> '; 384 385 echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; 386 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; 387 echo '</a> '; 388 389 }elseif($k == 'engine'){ 390 include_once(dirname(__FILE__).'/inc/search_engines.php'); 391 echo $SearchEnginesHashLib[$v]; 392 }elseif($k == 'bflag'){ 393 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 394 }elseif($k == 'osflag'){ 395 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 396 }elseif($k == 'cflag'){ 397 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 398 }elseif($k == 'html'){ 399 echo $v; 400 }else{ 401 echo hsc($v); 402 } 403 echo '</td>'; 404 } 405 echo '</tr>'; 406 407 if($pager && ($count == $pager)) break; 408 $count++; 409 } 410 echo '</table>'; 411 412 if($pager) $this->html_pager($pager,count($result) > $pager); 413 } 414 415} 416