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 91 $method = 'html_'.$this->opt; 92 if(method_exists($this,$method)){ 93 echo '<div class="plg_stats_'.$this->opt.'">'; 94 echo '<h2>'.$this->getLang($this->opt).'</h2>'; 95 $this->$method(); 96 echo '</div>'; 97 } 98 echo '</div>'; 99 } 100 101 /** 102 * Return the TOC 103 * 104 * @return array 105 */ 106 function getTOC(){ 107 $toc = array(); 108 foreach($this->pages as $page){ 109 $toc[] = array( 110 'link' => '?do=admin&page=statistics&opt='.$page.'&f='.$this->from.'&t='.$this->to, 111 'title' => $this->getLang($page), 112 'level' => 1, 113 'type' => 'ul' 114 ); 115 } 116 return $toc; 117 } 118 119 /** 120 * Outputs pagination links 121 * 122 * @fixme does this still work? 123 * 124 * @param type $limit 125 * @param type $next 126 */ 127 function html_pager($limit,$next){ 128 echo '<div class="plg_stats_pager">'; 129 130 if($this->start > 0){ 131 $go = max($this->start - $limit, 0); 132 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">previous page</a>'; 133 } 134 135 if($next){ 136 $go = $this->start + $limit; 137 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="next">next page</a>'; 138 } 139 echo '</div>'; 140 } 141 142 /** 143 * Print the time selection menu 144 */ 145 function html_timeselect(){ 146 $now = date('Y-m-d'); 147 $yday = date('Y-m-d',time()-(60*60*24)); 148 $week = date('Y-m-d',time()-(60*60*24*7)); 149 $month = date('Y-m-d',time()-(60*60*24*30)); 150 151 echo '<div class="plg_stats_timeselect">'; 152 echo '<span>Select the timeframe:</span>'; 153 echo '<ul>'; 154 155 echo '<li>'; 156 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$now.'&t='.$now.'">'; 157 echo 'today'; 158 echo '</a>'; 159 echo '</li>'; 160 161 echo '<li>'; 162 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$yday.'&t='.$yday.'">'; 163 echo 'yesterday'; 164 echo '</a>'; 165 echo '</li>'; 166 167 echo '<li>'; 168 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$week.'&t='.$now.'">'; 169 echo 'last 7 days'; 170 echo '</a>'; 171 echo '</li>'; 172 173 echo '<li>'; 174 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$month.'&t='.$now.'">'; 175 echo 'last 30 days'; 176 echo '</a>'; 177 echo '</li>'; 178 179 echo '</ul>'; 180 181 182 echo '<form action="" method="get">'; 183 echo '<input type="hidden" name="do" value="admin" />'; 184 echo '<input type="hidden" name="page" value="statistics" />'; 185 echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 186 echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 187 echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 188 echo '<input type="submit" value="go" class="button" />'; 189 echo '</form>'; 190 191 echo '</div>'; 192 } 193 194 195 /** 196 * Print an introductionary screen 197 */ 198 function html_dashboard(){ 199 echo '<p>This page gives you a quick overview on what is happening in your Wiki. For detailed lists 200 choose a topic from the list.</p>'; 201 202 // general info 203 echo '<div class="plg_stats_top">'; 204 $result = $this->hlp->Query()->aggregate($this->tlimit); 205 206 echo '<ul class="left">'; 207 foreach(array('pageviews','sessions','visitors','users','logins') as $name){ 208 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 209 } 210 echo '</ul>'; 211 212 echo '<ul class="left">'; 213 foreach(array('bouncerate','timespent','avgpages','newvisitors','registrations') as $name){ 214 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 215 } 216 echo '</ul>'; 217 218 219 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&f='.$this->from.'&t='.$this->to.'" />'; 220 echo '</div>'; 221 222 223 // top pages today 224 echo '<div>'; 225 echo '<h2>Most popular pages</h2>'; 226 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15); 227 $this->html_resulttable($result); 228 echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 229 echo '</div>'; 230 231 // top referer today 232 echo '<div>'; 233 echo '<h2>Newest incoming links</h2>'; 234 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15); 235 $this->html_resulttable($result); 236 echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 237 echo '</div>'; 238 239 // top searches today 240 echo '<div>'; 241 echo '<h2>Top search phrases</h2>'; 242 $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15); 243 $this->html_resulttable($result); 244 echo '<a href="?do=admin&page=statistics&opt=searchphrases&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 245 echo '</div>'; 246 } 247 248 function html_countries(){ 249 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=countries&f='.$this->from.'&t='.$this->to.'" />'; 250 $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150); 251 $this->html_resulttable($result,'',150); 252 } 253 254 function html_page(){ 255 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,150); 256 $this->html_resulttable($result,'',150); 257 } 258 259 function html_browsers(){ 260 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browsers&f='.$this->from.'&t='.$this->to.'" />'; 261 $result = $this->hlp->Query()->browsers($this->tlimit,$this->start,150,true); 262 $this->html_resulttable($result,'',150); 263 } 264 265 function html_os(){ 266 $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true); 267 $this->html_resulttable($result,'',150); 268 } 269 270 function html_referer(){ 271 $result = $this->hlp->Query()->aggregate($this->tlimit); 272 273 $all = $result['search']+$result['external']+$result['direct']; 274 275 if($all){ 276 printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses, 277 %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through 278 links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all), 279 $result['search'],(100*$result['search']/$all),$result['external'], 280 (100*$result['external']/$all)); 281 } 282 283 $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150); 284 $this->html_resulttable($result,'',150); 285 } 286 287 function html_newreferer(){ 288 echo '<p>The following incoming links where first logged in the selected time frame, 289 and have never been seen before.</p>'; 290 291 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,150); 292 $this->html_resulttable($result,'',150); 293 } 294 295 function html_outlinks(){ 296 $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150); 297 $this->html_resulttable($result,'',150); 298 } 299 300 function html_searchphrases(){ 301 $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150); 302 $this->html_resulttable($result,'',150); 303 } 304 305 function html_searchwords(){ 306 $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150); 307 $this->html_resulttable($result,'',150); 308 } 309 310 function html_internalsearchphrases(){ 311 $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150); 312 $this->html_resulttable($result,'',150); 313 } 314 315 function html_internalsearchwords(){ 316 $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150); 317 $this->html_resulttable($result,'',150); 318 } 319 320 function html_searchengines(){ 321 $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150); 322 $this->html_resulttable($result,'',150); 323 } 324 325 326 function html_resolution(){ 327 328 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=resolution&f='.$this->from.'&t='.$this->to.'" />'; 329 330 echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 331 much about about the real size of their browser windows. The graphic below shows the size distribution of 332 the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 333 in all browsers. Because users may resize their browser window while browsing your site the statistics may 334 be flawed. Take it with a grain of salt.</p>'; 335 336 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=viewport&f='.$this->from.'&t='.$this->to.'" />'; 337 338 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 339 $this->html_resulttable($result,'',150); 340 341 342 } 343 344 345 /** 346 * Display a result in a HTML table 347 */ 348 function html_resulttable($result,$header='',$pager=0){ 349 echo '<table>'; 350 if(is_array($header)){ 351 echo '<tr>'; 352 foreach($header as $h){ 353 echo '<th>'.hsc($h).'</th>'; 354 } 355 echo '</tr>'; 356 } 357 358 $count = 0; 359 if(is_array($result)) foreach($result as $row){ 360 echo '<tr>'; 361 foreach($row as $k => $v){ 362 echo '<td class="plg_stats_X'.$k.'">'; 363 if($k == 'page'){ 364 echo '<a href="'.wl($v).'" class="wikilink1">'; 365 echo hsc($v); 366 echo '</a>'; 367 }elseif($k == 'url'){ 368 $url = hsc($v); 369 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 370 if(strlen($url) > 45){ 371 $url = substr($url,0,30).' … '.substr($url,-15); 372 } 373 echo '<a href="'.$v.'" class="urlextern">'; 374 echo $url; 375 echo '</a>'; 376 }elseif($k == 'ilookup'){ 377 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 378 }elseif($k == 'lookup'){ 379 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 380 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />'; 381 echo '</a> '; 382 383 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 384 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />'; 385 echo '</a> '; 386 387 echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; 388 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; 389 echo '</a> '; 390 391 }elseif($k == 'engine'){ 392 include_once(dirname(__FILE__).'/inc/search_engines.php'); 393 echo $SearchEnginesHashLib[$v]; 394 }elseif($k == 'bflag'){ 395 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 396 }elseif($k == 'osflag'){ 397 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 398 }elseif($k == 'cflag'){ 399 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 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} 418