xref: /plugin/statistics/admin.php (revision 25446aa269781e5bd0b6c4c4fb33b41e1c4d5a48)
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','viewport');
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    function html_resolution(){
324        echo '<p>'.$this->getLang('intro_resolution').'</p>';
325        $this->html_graph('resolution',650,490);
326        $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150);
327        $this->html_resulttable($result,'',150);
328    }
329
330    function html_viewport(){
331        echo '<p>'.$this->getLang('intro_viewport').'</p>';
332        $this->html_graph('viewport',650,490);
333        $result = $this->hlp->Query()->viewport($this->tlimit,$this->start,150);
334        $this->html_resulttable($result,'',150);
335    }
336
337
338    /**
339     * Display a result in a HTML table
340     */
341    function html_resulttable($result,$header='',$pager=0){
342        echo '<table>';
343        if(is_array($header)){
344            echo '<tr>';
345            foreach($header as $h){
346                echo '<th>'.hsc($h).'</th>';
347            }
348            echo '</tr>';
349        }
350
351        $count = 0;
352        if(is_array($result)) foreach($result as $row){
353            echo '<tr>';
354            foreach($row as $k => $v){
355                echo '<td class="plg_stats_X'.$k.'">';
356                if($k == 'page'){
357                    echo '<a href="'.wl($v).'" class="wikilink1">';
358                    echo hsc($v);
359                    echo '</a>';
360                }elseif($k == 'url'){
361                    $url = hsc($v);
362                    $url = preg_replace('/^https?:\/\/(www\.)?/','',$url);
363                    if(strlen($url) > 45){
364                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
365                    }
366                    echo '<a href="'.$v.'" class="urlextern">';
367                    echo $url;
368                    echo '</a>';
369                }elseif($k == 'ilookup'){
370                    echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>';
371                }elseif($k == 'lookup'){
372                    echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">';
373                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />';
374                    echo '</a> ';
375
376                    echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">';
377                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />';
378                    echo '</a> ';
379
380                    echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">';
381                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />';
382                    echo '</a> ';
383
384                }elseif($k == 'engine'){
385                    include_once(dirname(__FILE__).'/inc/search_engines.php');
386                    echo $SearchEnginesHashLib[$v];
387                }elseif($k == 'bflag'){
388                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
389                }elseif($k == 'osflag'){
390                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
391                }elseif($k == 'cflag'){
392                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
393                }elseif($k == 'html'){
394                    echo $v;
395                }else{
396                    echo hsc($v);
397                }
398                echo '</td>';
399            }
400            echo '</tr>';
401
402            if($pager && ($count == $pager)) break;
403            $count++;
404        }
405        echo '</table>';
406
407        if($pager) $this->html_pager($pager,count($result) > $pager);
408    }
409
410}
411