xref: /plugin/statistics/admin.php (revision 441bfb8ee3582ca9d573b9b5250f86e11c783c41)
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        tpl_flush();
91
92        $method = 'html_'.$this->opt;
93        if(method_exists($this,$method)){
94            echo '<div class="plg_stats_'.$this->opt.'">';
95            echo '<h2>'.$this->getLang($this->opt).'</h2>';
96            $this->$method();
97            echo '</div>';
98        }
99        echo '</div>';
100    }
101
102    /**
103     * Return the TOC
104     *
105     * @return array
106     */
107    function getTOC(){
108        $toc = array();
109        foreach($this->pages as $page){
110            $toc[] = array(
111                    'link'  => '?do=admin&amp;page=statistics&amp;opt='.$page.'&amp;f='.$this->from.'&amp;t='.$this->to,
112                    'title' => $this->getLang($page),
113                    'level' => 1,
114                    'type'  => 'ul'
115            );
116        }
117        return $toc;
118    }
119
120
121    function html_graph($name,$width,$height){
122        $url = DOKU_BASE.'lib/plugins/statistics/img.php?img='.$name.
123               '&amp;f='.$this->from.'&amp;t='.$this->to;
124        echo '<img src="'.$url.'" class="graph" width="'.$width.'" height="'.$height.'"/>';
125    }
126
127
128    /**
129     * Outputs pagination links
130     *
131     * @fixme does this still work?
132     *
133     * @param type $limit
134     * @param type $next
135     */
136    function html_pager($limit,$next){
137        echo '<div class="plg_stats_pager">';
138
139        if($this->start > 0){
140            $go = max($this->start - $limit, 0);
141            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>';
142        }
143
144        if($next){
145            $go = $this->start + $limit;
146            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>';
147        }
148        echo '</div>';
149    }
150
151    /**
152     * Print the time selection menu
153     */
154    function html_timeselect(){
155        $today   = date('Y-m-d');
156        $last1   = date('Y-m-d',time()-(60*60*24));
157        $last7   = date('Y-m-d',time()-(60*60*24*7));
158        $last30  = date('Y-m-d',time()-(60*60*24*30));
159
160        echo '<div class="plg_stats_timeselect">';
161        echo '<span>'.$this->getLang('time_select').'</span> ';
162
163        echo '<form action="" method="get">';
164        echo '<input type="hidden" name="do" value="admin" />';
165        echo '<input type="hidden" name="page" value="statistics" />';
166        echo '<input type="hidden" name="opt" value="'.$this->opt.'" />';
167        echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />';
168        echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />';
169        echo '<input type="submit" value="go" class="button" />';
170        echo '</form>';
171
172        echo '<ul>';
173        foreach(array('today','last1','last7','last30') as $time){
174            echo '<li>';
175            echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$$time.'&amp;t='.$today.'">';
176            echo $this->getLang('time_'.$time);
177            echo '</a>';
178            echo '</li>';
179        }
180        echo '</ul>';
181
182        echo '</div>';
183    }
184
185
186    /**
187     * Print an introductionary screen
188     */
189    function html_dashboard(){
190        echo '<p>'.$this->getLang('intro_dashboard').'</p>';
191
192        // general info
193        echo '<div class="plg_stats_top">';
194        $result = $this->hlp->Query()->aggregate($this->tlimit);
195
196        echo '<ul class="left">';
197        foreach(array('pageviews','sessions','visitors','users','logins') as $name){
198            echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>';
199        }
200        echo '</ul>';
201
202        echo '<ul class="left">';
203        foreach(array('bouncerate','timespent','avgpages','newvisitors','registrations') as $name){
204            echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>';
205        }
206        echo '</ul>';
207
208        $this->html_graph('trend',700,280);
209        echo '</div>';
210
211
212        // top pages today
213        echo '<div>';
214        echo '<h2>'.$this->getLang('dash_mostpopular').'</h2>';
215        $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15);
216        $this->html_resulttable($result);
217        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
218        echo '</div>';
219
220        // top referer today
221        echo '<div>';
222        echo '<h2>'.$this->getLang('dash_newincoming').'</h2>';
223        $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15);
224        $this->html_resulttable($result);
225        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
226        echo '</div>';
227
228        // top searches today
229        echo '<div>';
230        echo '<h2>'.$this->getLang('dash_topsearch').'</h2>';
231        $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15);
232        $this->html_resulttable($result);
233        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
234        echo '</div>';
235    }
236
237    function html_countries(){
238        echo '<p>'.$this->getLang('intro_countries').'</p>';
239        $this->html_graph('countries',400,200);
240        $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150);
241        $this->html_resulttable($result,'',150);
242    }
243
244    function html_page(){
245        echo '<p>'.$this->getLang('intro_page').'</p>';
246        $result = $this->hlp->Query()->pages($this->tlimit,$this->start,150);
247        $this->html_resulttable($result,'',150);
248    }
249
250    function html_browsers(){
251        echo '<p>'.$this->getLang('intro_browsers').'</p>';
252        $this->html_graph('browsers',400,200);
253        $result = $this->hlp->Query()->browsers($this->tlimit,$this->start,150,true);
254        $this->html_resulttable($result,'',150);
255    }
256
257    function html_os(){
258        echo '<p>'.$this->getLang('intro_os').'</p>';
259        $this->html_graph('os',400,200);
260        $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true);
261        $this->html_resulttable($result,'',150);
262    }
263
264    function html_referer(){
265        $result = $this->hlp->Query()->aggregate($this->tlimit);
266
267        $all    = $result['search']+$result['external']+$result['direct'];
268
269        if($all){
270            printf('<p>'.$this->getLang('intro_referer').'</p>',
271                   $all,$result['direct'],(100*$result['direct']/$all),
272                   $result['search'],(100*$result['search']/$all),$result['external'],
273                   (100*$result['external']/$all));
274        }
275
276        $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150);
277        $this->html_resulttable($result,'',150);
278    }
279
280    function html_newreferer(){
281        echo '<p>'.$this->getLang('intro_newreferer').'</p>';
282
283        $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,150);
284        $this->html_resulttable($result,'',150);
285    }
286
287    function html_outlinks(){
288        echo '<p>'.$this->getLang('intro_outlinks').'</p>';
289        $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150);
290        $this->html_resulttable($result,'',150);
291    }
292
293    function html_searchphrases(){
294        echo '<p>'.$this->getLang('intro_searchphrases').'</p>';
295        $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150);
296        $this->html_resulttable($result,'',150);
297    }
298
299    function html_searchwords(){
300        echo '<p>'.$this->getLang('intro_searchwords').'</p>';
301        $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150);
302        $this->html_resulttable($result,'',150);
303    }
304
305    function html_internalsearchphrases(){
306        echo '<p>'.$this->getLang('intro_internalsearchphrases').'</p>';
307        $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150);
308        $this->html_resulttable($result,'',150);
309    }
310
311    function html_internalsearchwords(){
312        echo '<p>'.$this->getLang('intro_internalsearchwords').'</p>';
313        $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150);
314        $this->html_resulttable($result,'',150);
315    }
316
317    function html_searchengines(){
318        echo '<p>'.$this->getLang('intro_searchengines').'</p>';
319        $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150);
320        $this->html_resulttable($result,'',150);
321    }
322
323
324    function html_resolution(){
325
326        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=resolution&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
327
328        echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you
329              much about about the real size of their browser windows. The graphic below shows the size distribution of
330              the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged
331              in all browsers. Because users may resize their browser window while browsing your site the statistics may
332              be flawed. Take it with a grain of salt.</p>';
333
334        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=viewport&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
335
336        $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150);
337        $this->html_resulttable($result,'',150);
338
339
340    }
341
342
343    /**
344     * Display a result in a HTML table
345     */
346    function html_resulttable($result,$header='',$pager=0){
347        echo '<table>';
348        if(is_array($header)){
349            echo '<tr>';
350            foreach($header as $h){
351                echo '<th>'.hsc($h).'</th>';
352            }
353            echo '</tr>';
354        }
355
356        $count = 0;
357        if(is_array($result)) foreach($result as $row){
358            echo '<tr>';
359            foreach($row as $k => $v){
360                echo '<td class="plg_stats_X'.$k.'">';
361                if($k == 'page'){
362                    echo '<a href="'.wl($v).'" class="wikilink1">';
363                    echo hsc($v);
364                    echo '</a>';
365                }elseif($k == 'url'){
366                    $url = hsc($v);
367                    $url = preg_replace('/^https?:\/\/(www\.)?/','',$url);
368                    if(strlen($url) > 45){
369                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
370                    }
371                    echo '<a href="'.$v.'" class="urlextern">';
372                    echo $url;
373                    echo '</a>';
374                }elseif($k == 'ilookup'){
375                    echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>';
376                }elseif($k == 'lookup'){
377                    echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">';
378                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />';
379                    echo '</a> ';
380
381                    echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">';
382                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />';
383                    echo '</a> ';
384
385                    echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">';
386                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />';
387                    echo '</a> ';
388
389                }elseif($k == 'engine'){
390                    include_once(dirname(__FILE__).'/inc/search_engines.php');
391                    echo $SearchEnginesHashLib[$v];
392                }elseif($k == 'bflag'){
393                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
394                }elseif($k == 'osflag'){
395                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
396                }elseif($k == 'cflag'){
397                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
398                }elseif($k == 'html'){
399                    echo $v;
400                }else{
401                    echo hsc($v);
402                }
403                echo '</td>';
404            }
405            echo '</tr>';
406
407            if($pager && ($count == $pager)) break;
408            $count++;
409        }
410        echo '</table>';
411
412        if($pager) $this->html_pager($pager,count($result) > $pager);
413    }
414
415}
416