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