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 echo '<li><span>'.$result['pageviews'].'</span> page views </li>'; 205 echo '<li><span>'.$result['sessions'].'</span> visits (sessions) </li>'; 206 echo '<li><span>'.$result['visitors'].'</span> unique visitors </li>'; 207 echo '<li><span>'.$result['users'].'</span> logged in users</li>'; 208 209 echo '</ul>'; 210 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&f='.$this->from.'&t='.$this->to.'" />'; 211 echo '</div>'; 212 213 214 // top pages today 215 echo '<div>'; 216 echo '<h2>Most popular pages</h2>'; 217 $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15); 218 $this->html_resulttable($result); 219 echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 220 echo '</div>'; 221 222 // top referer today 223 echo '<div>'; 224 echo '<h2>Newest incoming links</h2>'; 225 $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15); 226 $this->html_resulttable($result); 227 echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 228 echo '</div>'; 229 230 // top searches today 231 echo '<div>'; 232 echo '<h2>Top search phrases</h2>'; 233 $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15); 234 $this->html_resulttable($result); 235 echo '<a href="?do=admin&page=statistics&opt=searchphrases&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 236 echo '</div>'; 237 } 238 239 function html_countries(){ 240 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=countries&f='.$this->from.'&t='.$this->to.'" />'; 241 $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150); 242 $this->html_resulttable($result,'',150); 243 } 244 245 function html_page(){ 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 '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browsers&f='.$this->from.'&t='.$this->to.'" />'; 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 $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true); 258 $this->html_resulttable($result,'',150); 259 } 260 261 function html_referer(){ 262 $result = $this->hlp->Query()->aggregate($this->tlimit); 263 264 $all = $result['search']+$result['external']+$result['direct']; 265 266 if($all){ 267 printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses, 268 %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through 269 links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all), 270 $result['search'],(100*$result['search']/$all),$result['external'], 271 (100*$result['external']/$all)); 272 } 273 274 $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150); 275 $this->html_resulttable($result,'',150); 276 } 277 278 function html_newreferer(){ 279 echo '<p>The following incoming links where first logged in the selected time frame, 280 and have never been seen before.</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 $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150); 288 $this->html_resulttable($result,'',150); 289 } 290 291 function html_searchphrases(){ 292 $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150); 293 $this->html_resulttable($result,'',150); 294 } 295 296 function html_searchwords(){ 297 $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150); 298 $this->html_resulttable($result,'',150); 299 } 300 301 function html_internalsearchphrases(){ 302 $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150); 303 $this->html_resulttable($result,'',150); 304 } 305 306 function html_internalsearchwords(){ 307 $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150); 308 $this->html_resulttable($result,'',150); 309 } 310 311 function html_searchengines(){ 312 $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150); 313 $this->html_resulttable($result,'',150); 314 } 315 316 317 function html_resolution(){ 318 $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150); 319 $this->html_resulttable($result,'',150); 320 321 echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 322 much about about the real size of their browser windows. The graphic below shows the size distribution of 323 the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 324 in all browsers. Because users may resize their browser window while browsing your site the statistics may 325 be flawed. Take it with a grain of salt.</p>'; 326 327 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&f='.$this->from.'&t='.$this->to.'" />'; 328 } 329 330 331 /** 332 * Display a result in a HTML table 333 */ 334 function html_resulttable($result,$header='',$pager=0){ 335 echo '<table>'; 336 if(is_array($header)){ 337 echo '<tr>'; 338 foreach($header as $h){ 339 echo '<th>'.hsc($h).'</th>'; 340 } 341 echo '</tr>'; 342 } 343 344 $count = 0; 345 if(is_array($result)) foreach($result as $row){ 346 echo '<tr>'; 347 foreach($row as $k => $v){ 348 echo '<td class="plg_stats_X'.$k.'">'; 349 if($k == 'page'){ 350 echo '<a href="'.wl($v).'" class="wikilink1">'; 351 echo hsc($v); 352 echo '</a>'; 353 }elseif($k == 'url'){ 354 $url = hsc($v); 355 $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 356 if(strlen($url) > 45){ 357 $url = substr($url,0,30).' … '.substr($url,-15); 358 } 359 echo '<a href="'.$v.'" class="urlextern">'; 360 echo $url; 361 echo '</a>'; 362 }elseif($k == 'ilookup'){ 363 echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>'; 364 }elseif($k == 'lookup'){ 365 echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; 366 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />'; 367 echo '</a> '; 368 369 echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; 370 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />'; 371 echo '</a> '; 372 373 echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; 374 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; 375 echo '</a> '; 376 377 }elseif($k == 'engine'){ 378 include_once(dirname(__FILE__).'/inc/search_engines.php'); 379 echo $SearchEnginesHashLib[$v]; 380 }elseif($k == 'bflag'){ 381 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 382 }elseif($k == 'osflag'){ 383 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />'; 384 }elseif($k == 'cflag'){ 385 echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 386 }elseif($k == 'html'){ 387 echo $v; 388 }else{ 389 echo hsc($v); 390 } 391 echo '</td>'; 392 } 393 echo '</tr>'; 394 395 if($pager && ($count == $pager)) break; 396 $count++; 397 } 398 echo '</table>'; 399 400 if($pager) $this->html_pager($pager,count($result) > $pager); 401 } 402 403} 404