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