Ceci est une ancienne révision du document !


A PCRE internal error occured. This might be caused by a faulty plugin

======Dokuwiki statistics plugin : multi-language support====== Mofification of Dokuwiki [[http://www.dokuwiki.org/plugin:statistics|plugin:statistics]]. =====Multi-language support===== To add multi-language support, change the **admin.php** file by : <code php admin.php> <?php /** * statistics plugin * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Andreas Gohr <gohr@cosmocode.de> */ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); require_once(DOKU_PLUGIN.'admin.php'); /** * All DokuWiki plugins to extend the admin function * need to inherit from this class */ class admin_plugin_statistics extends DokuWiki_Admin_Plugin { var $dblink = null; var $opt = ''; var $from = ''; var $to = ''; var $start = ''; var $tlimit = ''; /** * Access for managers allowed */ function forAdminOnly(){ return false; } /** * return sort order for position in admin menu */ function getMenuSort() { return 150; } /** * handle user request */ function handle() { $this->opt = preg_replace('/[^a-z]+/','',$_REQUEST['opt']); $this->start = (int) $_REQUEST['s']; $this->setTimeframe($_REQUEST['f'],$_REQUEST['t']); } /** * set limit clause */ function setTimeframe($from,$to){ // fixme add better sanity checking here: $from = preg_replace('/[^\d\-]+/','',$from); $to = preg_replace('/[^\d\-]+/','',$to); if(!$from) $from = date('Y-m-d'); if(!$to) $to = date('Y-m-d'); //setup limit clause $tlimit = "A.dt >= '$from 00:00:00' AND A.dt <= '$to 23:59:59'"; $this->tlimit = $tlimit; $this->from = $from; $this->to = $to; } /** * fixme build statistics here */ function html() { $this->html_toc(); echo '<h1>'.$this->getLang('menu').'</h1>'; $this->html_timeselect(); switch($this->opt){ case 'country': $this->html_country(); break; case 'page': $this->html_page(); break; case 'browser': $this->html_browser(); break; case 'os': $this->html_os(); break; case 'referer': $this->html_referer(); break; case 'newreferer': $this->html_newreferer(); break; case 'outlinks': $this->html_outlinks(); break; case 'resolution': $this->html_resolution(); break; case 'searchphrases': $this->html_searchphrases(); break; case 'searchwords': $this->html_searchwords(); break; case 'searchengines': $this->html_searchengines(); break; default: $this->html_dashboard(); } } function html_toc(){ echo '<div class="toc">'; echo '<div class="tocheader toctoggle" id="toc__header">'; echo $this->getLang('toc'); echo '</div>'; echo '<div id="toc__inside">'; echo '<ul class="toc">'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('dashboard').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('popular').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=referer&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('in_links').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('new_in_links').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=outlinks&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('out_links').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('search').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchwords&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('search_words').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchengines&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('search_engines').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=browser&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('browsers').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=os&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('os').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('countries').'</a>'; echo '</div></li>'; echo '<li><div class="li">'; echo '<a href="?do=admin&amp;page=statistics&amp;opt=resolution&amp;f='.$this->from.'&amp;t='.$this->to.'">'.$this->getLang('resolutions').'</a>'; echo '</div></li>'; echo '</ul>'; echo '</div>'; echo '</div>'; } function html_pager($limit,$next){ echo '<div class="plg_stats_pager">'; if($this->start > 0){ $go = max($this->start - $limit, 0); echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$go.'" class="prev">previous page</a>'; } if($next){ $go = $this->start + $limit; echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$go.'" class="next">next page</a>'; } echo '</div>'; } /** * Print the time selection menu */ function html_timeselect(){ $now = date('Y-m-d'); $yday = date('Y-m-d',time()-(60*60*24)); $week = date('Y-m-d',time()-(60*60*24*7)); $month = date('Y-m-d',time()-(60*60*24*30)); echo '<div class="plg_stats_timeselect">'; echo '<ul>'; echo '<li>'; echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$now.'&amp;t='.$now.'">'; echo $this->getLang('today'); echo '</a>'; echo '</li>'; echo '<li>'; echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$yday.'&amp;t='.$yday.'">'; echo $this->getLang('yesterday'); echo '</a>'; echo '</li>'; echo '<li>'; echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$week.'&amp;t='.$now.'">'; echo $this->getLang('last_7'); echo '</a>'; echo '</li>'; echo '<li>'; echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$month.'&amp;t='.$now.'">'; echo $this->getLang('last_30'); echo '</a>'; echo '</li>'; echo '</ul>'; echo'<br/><br/>'; echo '<form action="" method="get">'; echo '<input type="hidden" name="do" value="admin" />'; echo '<input type="hidden" name="page" value="statistics" />'; echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; echo '<input type="submit" value="go" class="button" />'; echo '</form>'; echo '</div>'; } /** * Print an introductionary screen */ function html_dashboard(){ echo '<p>'.$this->getLang('dashboard_intro').'</p>'; echo '<div class="plg_stats_dashboard">'; // general info echo '<div class="plg_stats_top">'; $result = $this->sql_aggregate($this->tlimit); echo '<ul>'; echo '<li><span>'.$result['pageviews'].' </span>'.$this->getLang('page_views').'</li>'; echo '<li><span>'.$result['sessions'].' </span>'.$this->getLang('sessions').'</li>'; echo '<li><span>'.$result['visitors'].' </span>'.$this->getLang('visitors').'</li>'; echo '<li><span>'.$result['users'].' </span>'.$this->getLang('users').'</li>'; echo '</ul>'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&amp;f='.$this->from.'&amp;t='.$this->to.'" />'; echo '</div>'; // top pages today echo '<div>'; echo '<h2>'.$this->getLang('popular_most').'</h2>'; $result = $this->sql_pages($this->tlimit,$this->start,15); $this->html_resulttable($result); echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>'; echo '</div>'; // top referer today echo '<div>'; echo '<h2>'.$this->getLang('new_in_links').'</h2>'; $result = $this->sql_newreferer($this->tlimit,$this->start,15); $this->html_resulttable($result); echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>'; echo '</div>'; // top searches today echo '<div>'; echo '<h2>'.$this->getLang('search_top').'</h2>'; $result = $this->sql_searchphrases($this->tlimit,$this->start,15); $this->html_resulttable($result); echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>'; echo '</div>'; echo '</div>'; } function html_country(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('countries').'</h2>'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />'; $result = $this->sql_countries($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_page(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('popular').'</h2>'; $result = $this->sql_pages($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_browser(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('browsers').'</h2>'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&amp;f='.$this->from.'&amp;t='.$this->to.'" />'; $result = $this->sql_browsers($this->tlimit,$this->start,150,true); $this->html_resulttable($result,'',150); echo '</div>'; } function html_os(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('os').'</h2>'; $result = $this->sql_os($this->tlimit,$this->start,150,true); $this->html_resulttable($result,'',150); echo '</div>'; } function html_referer(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('in_links').'</h2>'; $result = $this->sql_aggregate($this->tlimit); $all = $result['search']+$result['external']+$result['direct']; if($all){ printf('<p>'.$this->getLang('in_links_intro').'</p>',$all,$result['direct'],(100*$result['direct']/$all), $result['search'],(100*$result['search']/$all),$result['external'], (100*$result['external']/$all)); } $result = $this->sql_referer($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_newreferer(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('new_in_links').'</h2>'; echo '<p>'.$this->getLang('new_in_links_intro').'</p>'; $result = $this->sql_newreferer($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_outlinks(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('out_links').'</h2>'; $result = $this->sql_outlinks($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_searchphrases(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('search').'</h2>'; $result = $this->sql_searchphrases($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_searchwords(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('search_words').'</h2>'; $result = $this->sql_searchwords($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_searchengines(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('search_engines').'</h2>'; $result = $this->sql_searchengines($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '</div>'; } function html_resolution(){ echo '<div class="plg_stats_full">'; echo '<h2>'.$this->getLang('resolutions').'</h2>'; $result = $this->sql_resolution($this->tlimit,$this->start,150); $this->html_resulttable($result,'',150); echo '<p>'.$this->getLang('resolutions_intro').'</p>'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&amp;f='.$this->from.'&amp;t='.$this->to.'" />'; echo '</div>'; } /** * Display a result in a HTML table */ function html_resulttable($result,$header='',$pager=0){ echo '<table>'; if(is_array($header)){ echo '<tr>'; foreach($header as $h){ echo '<th>'.hsc($h).'</th>'; } echo '</tr>'; } $count = 0; if(is_array($result)) foreach($result as $row){ echo '<tr>'; foreach($row as $k => $v){ echo '<td class="plg_stats_X'.$k.'">'; if($k == 'page'){ echo '<a href="'.wl($v).'" class="wikilink1">'; echo hsc($v); echo '</a>'; }elseif($k == 'url'){ $url = hsc($v); $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); if(strlen($url) > 45){ $url = substr($url,0,30).' &hellip; '.substr($url,-15); } echo '<a href="'.$v.'" class="urlextern">'; echo $url; echo '</a>'; }elseif($k == 'lookup'){ echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />'; echo '</a> '; echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />'; echo '</a> '; echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">'; echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />'; echo '</a> '; }elseif($k == 'engine'){ include_once(dirname(__FILE__).'/inc/search_engines.php'); echo $SearchEnginesHashLib[$v]; }elseif($k == 'browser'){ include_once(dirname(__FILE__).'/inc/browsers.php'); echo $BrowsersHashIDLib[$v]; }elseif($k == 'bflag'){ include_once(dirname(__FILE__).'/inc/browsers.php'); echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />'; }elseif($k == 'os'){ if(empty($v)){ echo 'unknown'; }else{ include_once(dirname(__FILE__).'/inc/operating_systems.php'); echo $OSHashLib[$v]; } }elseif($k == 'osflag'){ echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />'; }elseif($k == 'cflag'){ echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; }elseif($k == 'html'){ echo $v; }else{ echo hsc($v); } echo '</td>'; } echo '</tr>'; if($pager && ($count == $pager)) break; $count++; } echo '</table>'; if($pager) $this->html_pager($pager,count($result) > $pager); } /** * Create an image */ function img_build($img){ include(dirname(__FILE__).'/inc/AGC.class.php'); switch($img){ case 'country': // build top countries + other $result = $this->sql_countries($this->tlimit,$this->start,0); $data = array(); $top = 0; foreach($result as $row){ if($top < 7){ $data[$row['country']] = $row['cnt']; }else{ $data['other'] += $row['cnt']; } $top++; } $pie = new AGC(300, 200); $pie->setProp("showkey",true); $pie->setProp("showval",false); $pie->setProp("showgrid",false); $pie->setProp("type","pie"); $pie->setProp("keyinfo",1); $pie->setProp("keysize",8); $pie->setProp("keywidspc",-50); $pie->setProp("key",array_keys($data)); $pie->addBulkPoints(array_values($data)); @$pie->graph(); $pie->showGraph(); break; case 'browser': // build top browsers + other include_once(dirname(__FILE__).'/inc/browsers.php'); $result = $this->sql_browsers($this->tlimit,$this->start,0,false); $data = array(); $top = 0; foreach($result as $row){ if($top < 5){ $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt']; }else{ $data['other'] += $row['cnt']; } $top++; } $pie = new AGC(300, 200); $pie->setProp("showkey",true); $pie->setProp("showval",false); $pie->setProp("showgrid",false); $pie->setProp("type","pie"); $pie->setProp("keyinfo",1); $pie->setProp("keysize",8); $pie->setProp("keywidspc",-50); $pie->setProp("key",array_keys($data)); $pie->addBulkPoints(array_values($data)); @$pie->graph(); $pie->showGraph(); break; case 'view': $graph = new AGC(400, 200); $graph->setColor('color',0,'blue'); $graph->setColor('color',1,'red'); $graph->setProp("showkey",true); $graph->setProp("key",'view port width',0); $graph->setProp("key",'view port height',1); $result = $this->sql_viewport($this->tlimit,0,0,true); foreach($result as $row){ $graph->addPoint($row['cnt'],$row['res_x'],0); } $result = $this->sql_viewport($this->tlimit,0,0,false); foreach($result as $row){ $graph->addPoint($row['cnt'],$row['res_y'],1); } @$graph->graph(); $graph->showGraph(); break; case 'trend': $hours = ($this->from == $this->to); $result = $this->sql_trend($this->tlimit,$hours); $data1 = array(); $data2 = array(); $graph = new AGC(400, 150); $graph->setProp("type","bar"); $graph->setProp("showgrid",false); $graph->setProp("barwidth",.8); $graph->setColor('color',0,'blue'); $graph->setColor('color',1,'red'); $graph->setColor('color',2,'yellow'); if($hours){ //preset $hours for($i=0;$i<24;$i++){ $data1[$i] = 0; $data2[$i] = 0; $data3[$i] = 0; $graph->setProp("scale",array(' 0h',' 4h',' 8h',' 12h',' 16h',' 20h',' 24h')); } }else{ $graph->setProp("scale",array(next(array_keys($data1)),$this->to)); } foreach($result as $row){ $data1[$row['time']] = $row['pageviews']; $data2[$row['time']] = $row['sessions']; $data3[$row['time']] = $row['visitors']; } foreach($data1 as $key => $val){ $graph->addPoint($val,$key,0); } foreach($data2 as $key => $val){ $graph->addPoint($val,$key,1); } foreach($data3 as $key => $val){ $graph->addPoint($val,$key,2); } @$graph->graph(); $graph->showGraph(); default: $this->sendGIF(); } } /** * Return some aggregated statistics */ function sql_aggregate($tlimit){ $data = array(); $sql = "SELECT ref_type, COUNT(*) as cnt FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY ref_type"; $result = $this->runSQL($sql); if(is_array($result)) foreach($result as $row){ if($row['ref_type'] == 'search') $data['search'] = $row['cnt']; if($row['ref_type'] == 'external') $data['external'] = $row['cnt']; if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt']; if($row['ref_type'] == '') $data['direct'] = $row['cnt']; } $sql = "SELECT COUNT(DISTINCT session) as sessions, COUNT(session) as views, COUNT(DISTINCT user) as users, COUNT(DISTINCT uid) as visitors FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser'"; $result = $this->runSQL($sql); $data['users'] = max($result[0]['users'] - 1,0); // subtract empty user $data['sessions'] = $result[0]['sessions']; $data['pageviews'] = $result[0]['views']; $data['visitors'] = $result[0]['visitors']; $sql = "SELECT COUNT(id) as robots FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'robot'"; $result = $this->runSQL($sql); $data['robots'] = $result[0]['robots']; return $data; } /** * standard statistics follow, only accesses made by browsers are counted * for general stats like browser or OS only visitors not pageviews are counted */ function sql_trend($tlimit,$hours=false){ if($hours){ $sql = "SELECT HOUR(dt) as time, COUNT(DISTINCT session) as sessions, COUNT(session) as pageviews, COUNT(DISTINCT uid) as visitors FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY HOUR(dt) ORDER BY time"; }else{ $sql = "SELECT DATE(dt) as time, COUNT(DISTINCT session) as sessions, COUNT(session) as pageviews, COUNT(DISTINCT uid) as visitors FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY DATE(dt) ORDER BY time"; } return $this->runSQL($sql); } function sql_searchengines($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, engine FROM ".$this->getConf('db_prefix')."search as A WHERE $tlimit GROUP BY engine ORDER BY cnt DESC, engine". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_searchphrases($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, query, query as lookup FROM ".$this->getConf('db_prefix')."search as A WHERE $tlimit GROUP BY query ORDER BY cnt DESC, query". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_searchwords($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, word, word as lookup FROM ".$this->getConf('db_prefix')."search as A, ".$this->getConf('db_prefix')."searchwords as B WHERE $tlimit AND A.id = B.sid GROUP BY word ORDER BY cnt DESC, word". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_outlinks($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, link as url FROM ".$this->getConf('db_prefix')."outlinks as A WHERE $tlimit GROUP BY link ORDER BY cnt DESC, link". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_pages($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, page FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY page ORDER BY cnt DESC, page". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_referer($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, ref as url FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' AND ref_type = 'external' GROUP BY ref_md5 ORDER BY cnt DESC, url". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_newreferer($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(*) as cnt, ref as url FROM ".$this->getConf('db_prefix')."access as B, ".$this->getConf('db_prefix')."refseen as A WHERE $tlimit AND ua_type = 'browser' AND ref_type = 'external' AND A.ref_md5 = B.ref_md5 GROUP BY A.ref_md5 ORDER BY cnt DESC, url". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_countries($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country FROM ".$this->getConf('db_prefix')."access as A, ".$this->getConf('db_prefix')."iplocation as B WHERE $tlimit AND A.ip = B.ip GROUP BY B.country ORDER BY cnt DESC, B.country". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){ if($ext){ $sel = 'ua_info as bflag, ua_info as browser, ua_ver'; $grp = 'ua_info, ua_ver'; }else{ $grp = 'ua_info'; $sel = 'ua_info'; } $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY $grp ORDER BY cnt DESC, ua_info". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_os($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY os ORDER BY cnt DESC, os". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_resolution($tlimit,$start=0,$limit=20){ $sql = "SELECT COUNT(DISTINCT session) as cnt, CONCAT(screen_x,'x',screen_y) as res FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' AND screen_x != 0 GROUP BY screen_x, screen_y ORDER BY cnt DESC, screen_x". $this->sql_limit($start,$limit); return $this->runSQL($sql); } function sql_viewport($tlimit,$start=0,$limit=20,$x=true){ if($x){ $col = 'view_x'; $res = 'res_x'; }else{ $col = 'view_y'; $res = 'res_y'; } $sql = "SELECT COUNT(*) as cnt, ROUND($col/10)*10 as $res FROM ".$this->getConf('db_prefix')."access as A WHERE $tlimit AND ua_type = 'browser' AND $col != 0 GROUP BY $res ORDER BY cnt DESC, $res". $this->sql_limit($start,$limit); return $this->runSQL($sql); } /** * Builds a limit clause */ function sql_limit($start,$limit){ $start = (int) $start; $limit = (int) $limit; if($limit){ $limit += 1; return " LIMIT $start,$limit"; }elseif($start){ return " OFFSET $start"; } return ''; } /** * Return a link to the DB, opening the connection if needed */ function dbLink(){ // connect to DB if needed if(!$this->dblink){ $this->dblink = mysql_connect($this->getConf('db_server'), $this->getConf('db_user'), $this->getConf('db_password')); if(!$this->dblink){ msg('DB Error: connection failed',-1); return null; } // set utf-8 if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); return null; } } return $this->dblink; } /** * Simple function to run a DB query */ function runSQL($sql_string) { $link = $this->dbLink(); $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); if(!$result){ msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1); return null; } $resultarray = array(); //mysql_db_query returns 1 on a insert statement -> no need to ask for results if ($result != 1) { for($i=0; $i< mysql_num_rows($result); $i++) { $temparray = mysql_fetch_assoc($result); $resultarray[]=$temparray; } mysql_free_result($result); } if (mysql_insert_id($link)) { $resultarray = mysql_insert_id($link); //give back ID on insert } return $resultarray; } /** * Returns a short name for a User Agent and sets type, version and os info */ function ua_info($ua,&$type,&$ver,&$os){ $ua = strtr($ua,' +','__'); $ua = strtolower($ua); // common browsers $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; $regvernetscape = '/netscape.?\/([\d\.]*)/i'; $regverfirefox = '/firefox\/([\d\.]*)/i'; $regversvn = '/svn\/([\d\.]*)/i'; $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; $regnotie = '/webtv|omniweb|opera/i'; $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; $name = ''; # IE ? if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ $type = 'browser'; $ver = $m[2]; $name = 'msie'; } # Firefox ? elseif (preg_match($regverfirefox,$ua,$m)){ $type = 'browser'; $ver = $m[1]; $name = 'firefox'; } # Subversion ? elseif (preg_match($regversvn,$ua,$m)){ $type = 'rcs'; $ver = $m[1]; $name = 'svn'; } # Netscape 6.x, 7.x ... ? elseif (preg_match($regvernetscape,$ua,$m)){ $type = 'browser'; $ver = $m[1]; $name = 'netscape'; } # Netscape 3.x, 4.x ... ? elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ $type = 'browser'; $ver = $m[2]; $name = 'netscape'; }else{ include(dirname(__FILE__).'/inc/browsers.php'); foreach($BrowsersSearchIDOrder as $regex){ if(preg_match('/'.$regex.'/',$ua)){ // it's a browser! $type = 'browser'; $name = strtolower($regex); break; } } } // check versions for Safari and Opera if($name == 'safari'){ if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){ $ver = $BrowsersSafariBuildToVersionHash[$match[1]]; } }elseif($name == 'opera'){ if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){ $ver = $match[1]; } } // check OS for browsers if($type == 'browser'){ include(dirname(__FILE__).'/inc/operating_systems.php'); foreach($OSSearchIDOrder as $regex){ if(preg_match('/'.$regex.'/',$ua)){ $os = $OSHashID[$regex]; break; } } } // are we done now? if($name) return $name; include(dirname(__FILE__).'/inc/robots.php'); foreach($RobotsSearchIDOrder as $regex){ if(preg_match('/'.$regex.'/',$ua)){ // it's a robot! $type = 'robot'; return strtolower($regex); } } // dunno return ''; } /** * Log search queries */ function log_search($referer,&$type){ $referer = strtolower($referer); $ref = strtr($referer,' +','__'); include(dirname(__FILE__).'/inc/search_engines.php'); foreach($SearchEnginesSearchIDOrder as $regex){ if(preg_match('/'.$regex.'/',$ref)){ if(!$NotSearchEnginesKeys[$regex] || !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$ref)){ // it's a search engine! $type = 'search'; break; } } } if($type != 'search') return; // we're done here // extract query $engine = $SearchEnginesHashID[$regex]; $param = $SearchEnginesKnownUrl[$engine]; if($param && preg_match('/'.$param.'(.*?)[&$]/',$referer,$match)){ $query = array_pop($match); }elseif(preg_match('/'.$WordsToExtractSearchUrl.'(.*?)[&$]/',$referer,$match)){ $query = array_pop($match); } if(!$query) return; // we failed // clean the query $query = preg_replace('/^(cache|related):[^\+]+/','',$query); // non-search queries $query = preg_replace('/%0[ad]/',' ',$query); // LF CR $query = preg_replace('/%2[02789abc]/',' ',$query); // space " ' ( ) * + , $query = preg_replace('/%3a/',' ',$query); // : $query = strtr($query,'+\'()"*,:',' '); // badly encoded $query = preg_replace('/ +/',' ',$query); // ws compact $query = trim($query); $query = urldecode($query); if(!utf8_check($query)) $query = utf8_encode($query); // assume latin1 if not utf8 $query = utf8_strtolower($query); // log it! $page = addslashes($_REQUEST['p']); $query = addslashes($query); $sql = "INSERT INTO ".$this->getConf('db_prefix')."search SET dt = NOW(), page = '$page', query = '$query', engine = '$engine'"; $id = $this->runSQL($sql); if(is_null($id)){ global $MSG; print_r($MSG); return; } // log single keywords $words = explode(' ',utf8_stripspecials($query,' ','\._\-:\*')); foreach($words as $word){ if(!$word) continue; $word = addslashes($word); $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."searchwords SET sid = $id, word = '$word'"; $ok = $this->runSQL($sql); if(is_null($ok)){ global $MSG; print_r($MSG); } } } /** * Resolve IP to country/city */ function log_ip($ip){ // check if IP already known and up-to-date $sql = "SELECT ip FROM ".$this->getConf('db_prefix')."iplocation WHERE ip ='".addslashes($ip)."' AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; $result = $this->runSQL($sql); if($result[0]['ip']) return; $http = new DokuHTTPClient(); $http->timeout = 10; $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ $country = addslashes(trim($match[1])); $code = addslashes(strtolower(trim($match[2]))); $city = addslashes(trim($match[3])); $host = addslashes(gethostbyaddr($ip)); $ip = addslashes($ip); $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation SET ip = '$ip', country = '$country', code = '$code', city = '$city', host = '$host'"; $this->runSQL($sql); } } /** * log a click on an external link * * called from log.php */ function log_outgoing(){ if(!$_REQUEST['ol']) return; $link_md5 = md5($link); $link = addslashes($_REQUEST['ol']); $session = addslashes(session_id()); $page = addslashes($_REQUEST['p']); $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."outlinks SET dt = NOW(), session = '$session', page = '$page', link_md5 = '$link_md5', link = '$link'"; $ok = $this->runSQL($sql); if(is_null($ok)){ global $MSG; print_r($MSG); } } /** * log a page access * * called from log.php */ function log_access(){ if(!$_REQUEST['p']) return; # FIXME check referer against blacklist and drop logging for bad boys // handle referer $referer = trim($_REQUEST['r']); if($referer){ $ref = addslashes($referer); $ref_md5 = ($ref) ? md5($referer) : ''; if(strpos($referer,DOKU_URL) === 0){ $ref_type = 'internal'; }else{ $ref_type = 'external'; $this->log_search($referer,$ref_type); } }else{ $ref = ''; $ref_md5 = ''; $ref_type = ''; } // handle user agent $agent = trim($_SERVER['HTTP_USER_AGENT']); $ua = addslashes($agent); $ua_type = ''; $ua_ver = ''; $os = ''; $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); $page = addslashes($_REQUEST['p']); $ip = addslashes($_SERVER['REMOTE_ADDR']); $sx = (int) $_REQUEST['sx']; $sy = (int) $_REQUEST['sy']; $vx = (int) $_REQUEST['vx']; $vy = (int) $_REQUEST['vy']; $js = (int) $_REQUEST['js']; $uid = addslashes($_REQUEST['uid']); $user = addslashes($_SERVER['REMOTE_USER']); $session = addslashes(session_id()); if(!$uid) $uid = $session; $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access SET dt = NOW(), page = '$page', ip = '$ip', ua = '$ua', ua_info = '$ua_info', ua_type = '$ua_type', ua_ver = '$ua_ver', os = '$os', ref = '$ref', ref_md5 = '$ref_md5', ref_type = '$ref_type', screen_x = '$sx', screen_y = '$sy', view_x = '$vx', view_y = '$vy', js = '$js', user = '$user', session = '$session', uid = '$uid'"; $ok = $this->runSQL($sql); if(is_null($ok)){ global $MSG; print_r($MSG); } $sql = "INSERT DELAYED IGNORE INTO ".$this->getConf('db_prefix')."refseen SET ref_md5 = '$ref_md5', dt = NOW()"; $ok = $this->runSQL($sql); if(is_null($ok)){ global $MSG; print_r($MSG); } // resolve the IP $this->log_ip($_SERVER['REMOTE_ADDR']); } /** * Just send a 1x1 pixel blank gif to the browser * * @called from log.php * * @author Andreas Gohr <andi@splitbrain.org> * @author Harry Fuecks <fuecks@gmail.com> */ function sendGIF(){ $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); header('Content-Type: image/gif'); header('Content-Length: '.strlen($img)); header('Connection: Close'); print $img; flush(); // Browser should drop connection after this // Thinks it's got the whole image } } </code> =====Languages===== ====English==== Put the following file into **statistics/lang/en/** (create path folders if necessary) : <code php lang.php> <?php /** * english language file */ // settings must be present and set appropriately for the language $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; // for admin plugins, the menu prompt to be displayed in the admin menu // if set here, the plugin doesn't need to override the getMenuText() method $lang['menu'] = 'Access Statistics'; // custom language strings for the plugin $lang['percent'] = 'Percent'; $lang['count'] = 'Count'; $lang['reason'] = 'Reason'; //Setup VIM: ex: et ts=4 enc=utf-8 : // timeframe $lang['timeselect'] = 'Select the timeframe :'; $lang['today'] = 'today'; $lang['yesterday'] = 'yesterday'; $lang['last_7'] = 'last 7 days'; $lang['last_30'] = 'last 30 days'; // menu, generals $lang['toc'] = 'Detailed statistics'; $lang['dashboard'] = 'Dashboard'; $lang['popular'] = 'Popular pages'; $lang['popular_most'] = 'Most popular pages'; $lang['in_links'] = 'Incoming links'; $lang['new_in_links'] = 'New incoming links'; $lang['out_links'] = 'Outgoing links'; $lang['search'] = 'Search phrases'; $lang['search_top'] = 'Top search phrases'; $lang['search_words'] = 'Search words'; $lang['search_engines'] = 'Search engines'; $lang['browsers'] = 'Browsers'; $lang['os'] = 'Operating systems'; $lang['countries'] = 'Countries'; $lang['resolutions'] = 'Resolutions'; // dashboard overview $lang['page_views'] = 'page views'; $lang['sessions'] = 'visits (sessions)'; $lang['visitors'] = 'unique visitors'; $lang['users'] = 'logged in users'; // introduction texts $lang['dashboard_intro'] = 'This page gives you a quick overview on what is happening in your Wiki. For detailed lists choose a topic from the list.'; $lang['in_links_intro'] = 'Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses, %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through links from other pages.'; $lang['new_in_links_intro'] = 'The following incoming links where first logged in the selected time frame, and have never been seen before.'; $lang['resolutions_intro'] = 'While the data above gives you some info about the resolution your visitors use, it does not tell you much about about the real size of their browser windows. The graphic below shows the size distribution of the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged in all browsers. Because users may resize their browser window while browsing your site the statistics may be flawed. Take it with a grain of salt.'; ?> </code> ====Français==== Placez le fichier suivant à l'adresse **statistics/lang/fr/** (créez les dossiers du chemin si nécessaire) : <code php lang.php> <?php /** * french language file */ // settings must be present and set appropriately for the language $lang['encoding'] = 'utf-8'; $lang['direction'] = 'ltr'; // for admin plugins, the menu prompt to be displayed in the admin menu // if set here, the plugin doesn't need to override the getMenuText() method $lang['menu'] = 'Statistiques'; // custom language strings for the plugin $lang['percent'] = 'Pourcent'; $lang['count'] = 'Count'; $lang['reason'] = 'Reason'; //Setup VIM: ex: et ts=4 enc=utf-8 : // timeframe $lang['timeselect'] = 'S&eacute;lectionnez la dur&eacute;e :'; $lang['today'] = 'aujourd\'hui'; $lang['yesterday'] = 'hier'; $lang['last_7'] = '7 derniers jours'; $lang['last_30'] = '30 derniers jours'; // menu, generals $lang['toc'] = 'Statistiques d&eacute;taill&eacute;es'; $lang['dashboard'] = 'Tableau de bord'; $lang['popular'] = 'Pages populaires'; $lang['popular_most'] = 'Pages les plus populaires'; $lang['in_links'] = 'Liens entrants'; $lang['new_in_links'] = 'Nouveaux liens entrants'; $lang['out_links'] = 'Liens sortants'; $lang['search'] = 'Recherches'; $lang['search_top'] = 'Recherches les plus courantes'; $lang['search_words'] = 'Mots recherch&eacute;s'; $lang['search_engines'] = 'Moteurs de recherche'; $lang['browsers'] = 'Navigateurs'; $lang['os'] = 'Syst&egrave;mes d\'exploitation'; $lang['countries'] = 'Pays'; $lang['resolutions'] = 'R&eacute;solutions'; // dashboard overview $lang['page_views'] = 'pages vues'; $lang['sessions'] = 'visites (sessions)'; $lang['visitors'] = 'visiteurs uniques'; $lang['users'] = 'visiteurs enregistr&eacute;s'; // introduction texts $lang['dashboard_intro'] = 'Cette page vous donne un aper&ccedil;u de ce qui se passe dans votre Wiki. Pour des informations d&eacute;taill&eacute;es choisissez un sujet dans le menu.'; $lang['in_links_intro'] = 'Sur les %d visites, %d (%.1f%%) viennent d\'acc&egrave;s directs (marque- pages), %d (%.1f%%) viennent d\'un moteur de recherche et %d (%.1f%%) viennent d\'autres pages. Seuls les derniers sont list&eacute;s ci-dessous.'; $lang['new_in_links_intro'] = 'Les liens entrants suivant sont apparus dans la dur&eacute;e s&eacute;lection&eacute;e et n\'avaient jamais &eacute;t&eacute; vus auparavant.'; $lang['resolutions_intro'] = 'Bien que les donn&eacute;es ci-dessous donnent un peu d\'infos sur la r&eacute;solution que vos visiteurs utilisent, il ne vous dit pas grand-chose sur la taille r&eacute;elle de la fen&ecirc;tres de leur navigateur. Le graphique ci-dessous montre la distribution de la taille de la fen&ecirc;tre (zone du document) des navigateurs de vos visiteurs. Veuillez noter que ces donn&eacute;es ne peuvent pas &ecirc;tre enregistr&eacute;es pour tous les navigateurs. Vu que les utilisateurs peuvent redimensionner la fen&ecirc;tre de leur navigateur pendant qu\'ils naviguent sur votre site, ces statistiques peuvent &ecirc;tre erron&eacute;es. Prenez tout &ccedil;a avec des pincettes.'; ?> </code> ~~DISCUSSION~~