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 function html_graph($name,$width,$height){ 121 $url = DOKU_BASE.'lib/plugins/statistics/img.php?img='.$name. 122 '&f='.$this->from.'&t='.$this->to; 123 echo '<img src="'.$url.'" class="graph" width="'.$width.'" height="'.$height.'"/>'; 124 } 125 126 127 /** 128 * Outputs pagination links 129 * 130 * @fixme does this still work? 131 * 132 * @param type $limit 133 * @param type $next 134 */ 135 function html_pager($limit,$next){ 136 echo '<div class="plg_stats_pager">'; 137 138 if($this->start > 0){ 139 $go = max($this->start - $limit, 0); 140 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">previous page</a>'; 141 } 142 143 if($next){ 144 $go = $this->start + $limit; 145 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="next">next page</a>'; 146 } 147 echo '</div>'; 148 } 149 150 /** 151 * Print the time selection menu 152 */ 153 function html_timeselect(){ 154 $today = date('Y-m-d'); 155 $last1 = date('Y-m-d',time()-(60*60*24)); 156 $last7 = date('Y-m-d',time()-(60*60*24*7)); 157 $last30 = date('Y-m-d',time()-(60*60*24*30)); 158 159 echo '<div class="plg_stats_timeselect">'; 160 echo '<span>'.$this->getLang('time_select').'</span> '; 161 162 echo '<form action="" method="get">'; 163 echo '<input type="hidden" name="do" value="admin" />'; 164 echo '<input type="hidden" name="page" value="statistics" />'; 165 echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 166 echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 167 echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 168 echo '<input type="submit" value="go" class="button" />'; 169 echo '</form>'; 170 171 echo '<ul>'; 172 foreach(array('today','last1','last7','last30') as $time){ 173 echo '<li>'; 174 echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$$time.'&t='.$today.'">'; 175 echo $this->getLang('time_'.$time); 176 echo '</a>'; 177 echo '</li>'; 178 } 179 echo '</ul>'; 180 181 echo '</div>'; 182 } 183 184 185 /** 186 * Print an introductionary screen 187 */ 188 function html_dashboard(){ 189 echo '<p>'.$this->getLang('intro_dashboard').'</p>'; 190 191 // general info 192 echo '<div class="plg_stats_top">'; 193 $result = $this->hlp->Query()->aggregate($this->tlimit); 194 195 echo '<ul class="left">'; 196 foreach(array('pageviews','sessions','visitors','users','logins') as $name){ 197 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 198 } 199 echo '</ul>'; 200 201 echo '<ul class="left">'; 202 foreach(array('bouncerate','timespent','avgpages','newvisitors','registrations') as $name){ 203 echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>'; 204 } 205 echo '</ul>'; 206 207 $this->html_graph('trend',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">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">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">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 $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150); 319 $this->html_resulttable($result,'',150); 320 } 321 322 323 function html_resolution(){ 324 325 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=resolution&f='.$this->from.'&t='.$this->to.'" />'; 326 327 echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 328 much about about the real size of their browser windows. The graphic below shows the size distribution of 329 the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 330 in all browsers. Because users may resize their browser window while browsing your site the statistics may 331 be flawed. Take it with a grain of salt.</p>'; 332 333 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=viewport&f='.$this->from.'&t='.$this->to.'" />'; 334 335 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 336 $this->html_resulttable($result,'',150); 337 338 339 } 340 341 342 /** 343 * Display a result in a HTML table 344 */ 345 function html_resulttable($result,$header='',$pager=0){ 346 echo '<table>'; 347 if(is_array($header)){ 348 echo '<tr>'; 349 foreach($header as $h){ 350 echo '<th>'.hsc($h).'</th>'; 351 } 352 echo '</tr>'; 353 } 354 355 $count = 0; 356 if(is_array($result)) foreach($result as $row){ 357 echo '<tr>'; 358 foreach($row as $k => $v){ 359 echo '<td class="plg_stats_X'.$k.'">'; 360 if($k == 'page'){ 361 echo '<a href="'.wl($v).'" class="wikilink1">'; 362 echo hsc($v); 363 echo '</a>'; 364 }elseif($k == 'url'){ 365 $url = hsc($v); 366 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 367 if(strlen($url) > 45){ 368 $url = substr($url,0,30).' … '.substr($url,-15); 369 } 370 echo '<a href="'.$v.'" class="urlextern">'; 371 echo $url; 372 echo '</a>'; 373 }elseif($k == 'ilookup'){ 374 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 375 }elseif($k == 'lookup'){ 376 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 377 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />'; 378 echo '</a> '; 379 380 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 381 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />'; 382 echo '</a> '; 383 384 echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; 385 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; 386 echo '</a> '; 387 388 }elseif($k == 'engine'){ 389 include_once(dirname(__FILE__).'/inc/search_engines.php'); 390 echo $SearchEnginesHashLib[$v]; 391 }elseif($k == 'bflag'){ 392 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 393 }elseif($k == 'osflag'){ 394 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 395 }elseif($k == 'cflag'){ 396 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 397 }elseif($k == 'html'){ 398 echo $v; 399 }else{ 400 echo hsc($v); 401 } 402 echo '</td>'; 403 } 404 echo '</tr>'; 405 406 if($pager && ($count == $pager)) break; 407 $count++; 408 } 409 echo '</table>'; 410 411 if($pager) $this->html_pager($pager,count($result) > $pager); 412 } 413 414} 415