Différences
Ci-dessous, les différences entre deux révisions de la page.
Dernière révision Les deux révisions suivantes | |||
articles:dokuwiki_statistics_lang [2010/09/27 19:45] nico créée |
articles:dokuwiki_statistics_lang [2010/09/27 19:48] nico |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | ======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&page=statistics&opt=&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('dashboard').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('popular').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=referer&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('in_links').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('new_in_links').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=outlinks&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('out_links').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=searchphrases&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('search').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=searchwords&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('search_words').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=searchengines&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('search_engines').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=browser&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('browsers').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=os&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('os').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=country&f='.$this->from.'&t='.$this->to.'">'.$this->getLang('countries').'</a>'; | ||
+ | echo '</div></li>'; | ||
+ | |||
+ | echo '<li><div class="li">'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt=resolution&f='.$this->from.'&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&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">previous page</a>'; | ||
+ | } | ||
+ | |||
+ | if($next){ | ||
+ | $go = $this->start + $limit; | ||
+ | echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&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&page=statistics&opt='.$this->opt.'&f='.$now.'&t='.$now.'">'; | ||
+ | echo $this->getLang('today'); | ||
+ | echo '</a>'; | ||
+ | echo '</li>'; | ||
+ | |||
+ | echo '<li>'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$yday.'&t='.$yday.'">'; | ||
+ | echo $this->getLang('yesterday'); | ||
+ | echo '</a>'; | ||
+ | echo '</li>'; | ||
+ | |||
+ | echo '<li>'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$week.'&t='.$now.'">'; | ||
+ | echo $this->getLang('last_7'); | ||
+ | echo '</a>'; | ||
+ | echo '</li>'; | ||
+ | |||
+ | echo '<li>'; | ||
+ | echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$month.'&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&f='.$this->from.'&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&page=statistics&opt=page&f='.$this->from.'&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&page=statistics&opt=newreferer&f='.$this->from.'&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&page=statistics&opt=searchphrases&f='.$this->from.'&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&f='.$this->from.'&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&f='.$this->from.'&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&f='.$this->from.'&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).' … '.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électionnez la duré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étaillé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és'; | ||
+ | $lang['search_engines'] = 'Moteurs de recherche'; | ||
+ | $lang['browsers'] = 'Navigateurs'; | ||
+ | $lang['os'] = 'Systèmes d\'exploitation'; | ||
+ | $lang['countries'] = 'Pays'; | ||
+ | $lang['resolutions'] = 'Résolutions'; | ||
+ | |||
+ | // dashboard overview | ||
+ | $lang['page_views'] = 'pages vues'; | ||
+ | $lang['sessions'] = 'visites (sessions)'; | ||
+ | $lang['visitors'] = 'visiteurs uniques'; | ||
+ | $lang['users'] = 'visiteurs enregistrés'; | ||
+ | |||
+ | // introduction texts | ||
+ | $lang['dashboard_intro'] = 'Cette page vous donne un aperçu de ce qui se passe dans votre Wiki. | ||
+ | Pour des informations détaillées choisissez un sujet dans le menu.'; | ||
+ | $lang['in_links_intro'] = 'Sur les %d visites, %d (%.1f%%) viennent d\'accès directs (marque- | ||
+ | pages), %d (%.1f%%) viennent d\'un moteur de recherche et %d (%.1f%%) viennent d\'autres pages. Seuls | ||
+ | les derniers sont listés ci-dessous.'; | ||
+ | $lang['new_in_links_intro'] = 'Les liens entrants suivant sont apparus dans la durée sélectionée | ||
+ | et n\'avaient jamais été vus auparavant.'; | ||
+ | $lang['resolutions_intro'] = 'Bien que les données ci-dessous donnent un peu d\'infos sur la | ||
+ | résolution que vos visiteurs utilisent, il ne vous dit pas grand-chose sur la taille réelle | ||
+ | de la fenêtres de leur navigateur. Le graphique ci-dessous montre la distribution de la taille | ||
+ | de la fenêtre (zone du document) des navigateurs de vos visiteurs. Veuillez noter que ces données | ||
+ | ne peuvent pas être enregistrées pour tous les navigateurs. Vu que les utilisateurs peuvent | ||
+ | redimensionner la fenêtre de leur navigateur pendant qu\'ils naviguent sur votre site, ces statistiques | ||
+ | peuvent être erronées. Prenez tout ça avec des pincettes.'; | ||
+ | ?> | ||
+ | </code> | ||
+ | |||
+ | ~~DISCUSSION~~ |