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