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