xref: /plugin/statistics/admin.php (revision 25b71d4bd2b8a0ffa2b5f33e8772d0fa67bbc89a)
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>'.$this->getLang('menu').'</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     * @param type $limit
132     * @param type $next
133     */
134    function html_pager($limit,$next){
135        echo '<div class="plg_stats_pager">';
136
137        if($this->start > 0){
138            $go = max($this->start - $limit, 0);
139            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">'.$this->getLang('prev').'</a>';
140        }
141
142        if($next){
143            $go = $this->start + $limit;
144            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">'.$this->getLang('next').'</a>';
145        }
146        echo '</div>';
147    }
148
149    /**
150     * Print the time selection menu
151     */
152    function html_timeselect(){
153        $today   = date('Y-m-d');
154        $last1   = date('Y-m-d',time()-(60*60*24));
155        $last7   = date('Y-m-d',time()-(60*60*24*7));
156        $last30  = date('Y-m-d',time()-(60*60*24*30));
157
158        echo '<div class="plg_stats_timeselect">';
159        echo '<span>'.$this->getLang('time_select').'</span> ';
160
161        echo '<form action="" method="get">';
162        echo '<input type="hidden" name="do" value="admin" />';
163        echo '<input type="hidden" name="page" value="statistics" />';
164        echo '<input type="hidden" name="opt" value="'.$this->opt.'" />';
165        echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />';
166        echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />';
167        echo '<input type="submit" value="go" class="button" />';
168        echo '</form>';
169
170        echo '<ul>';
171        foreach(array('today','last1','last7','last30') as $time){
172            echo '<li>';
173            echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$$time.'&amp;t='.$today.'">';
174            echo $this->getLang('time_'.$time);
175            echo '</a>';
176            echo '</li>';
177        }
178        echo '</ul>';
179
180        echo '</div>';
181    }
182
183
184    /**
185     * Print an introductionary screen
186     */
187    function html_dashboard(){
188        echo '<p>'.$this->getLang('intro_dashboard').'</p>';
189
190        // general info
191        echo '<div class="plg_stats_top">';
192        $result = $this->hlp->Query()->aggregate($this->tlimit);
193
194        echo '<ul class="left">';
195        foreach(array('pageviews','sessions','visitors','users','logins') as $name){
196            echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>';
197        }
198        echo '</ul>';
199
200        echo '<ul class="left">';
201        foreach(array('bouncerate','timespent','avgpages','newvisitors','registrations') as $name){
202            echo '<li><div class="li">'.sprintf($this->getLang('dash_'.$name),$result[$name]).'</div></li>';
203        }
204        echo '</ul>';
205
206        $this->html_graph('trend',700,280);
207        echo '</div>';
208
209
210        // top pages today
211        echo '<div>';
212        echo '<h2>'.$this->getLang('dash_mostpopular').'</h2>';
213        $result = $this->hlp->Query()->pages($this->tlimit,$this->start,15);
214        $this->html_resulttable($result);
215        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">'.$this->getLang('more').'</a>';
216        echo '</div>';
217
218        // top referer today
219        echo '<div>';
220        echo '<h2>'.$this->getLang('dash_newincoming').'</h2>';
221        $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,15);
222        $this->html_resulttable($result);
223        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">'.$this->getLang('more').'</a>';
224        echo '</div>';
225
226        // top searches today
227        echo '<div>';
228        echo '<h2>'.$this->getLang('dash_topsearch').'</h2>';
229        $result = $this->hlp->Query()->searchphrases($this->tlimit,$this->start,15);
230        $this->html_resulttable($result);
231        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">'.$this->getLang('more').'</a>';
232        echo '</div>';
233    }
234
235    function html_countries(){
236        echo '<p>'.$this->getLang('intro_countries').'</p>';
237        $this->html_graph('countries',400,200);
238        $result = $this->hlp->Query()->countries($this->tlimit,$this->start,150);
239        $this->html_resulttable($result,'',150);
240    }
241
242    function html_page(){
243        echo '<p>'.$this->getLang('intro_page').'</p>';
244        $result = $this->hlp->Query()->pages($this->tlimit,$this->start,150);
245        $this->html_resulttable($result,'',150);
246    }
247
248    function html_browsers(){
249        echo '<p>'.$this->getLang('intro_browsers').'</p>';
250        $this->html_graph('browsers',400,200);
251        $result = $this->hlp->Query()->browsers($this->tlimit,$this->start,150,true);
252        $this->html_resulttable($result,'',150);
253    }
254
255    function html_os(){
256        echo '<p>'.$this->getLang('intro_os').'</p>';
257        $this->html_graph('os',400,200);
258        $result = $this->hlp->Query()->os($this->tlimit,$this->start,150,true);
259        $this->html_resulttable($result,'',150);
260    }
261
262    function html_referer(){
263        $result = $this->hlp->Query()->aggregate($this->tlimit);
264
265        $all    = $result['search']+$result['external']+$result['direct'];
266
267        if($all){
268            printf('<p>'.$this->getLang('intro_referer').'</p>',
269                   $all,$result['direct'],(100*$result['direct']/$all),
270                   $result['search'],(100*$result['search']/$all),$result['external'],
271                   (100*$result['external']/$all));
272        }
273
274        $result = $this->hlp->Query()->referer($this->tlimit,$this->start,150);
275        $this->html_resulttable($result,'',150);
276    }
277
278    function html_newreferer(){
279        echo '<p>'.$this->getLang('intro_newreferer').'</p>';
280
281        $result = $this->hlp->Query()->newreferer($this->tlimit,$this->start,150);
282        $this->html_resulttable($result,'',150);
283    }
284
285    function html_outlinks(){
286        echo '<p>'.$this->getLang('intro_outlinks').'</p>';
287        $result = $this->hlp->Query()->outlinks($this->tlimit,$this->start,150);
288        $this->html_resulttable($result,'',150);
289    }
290
291    function html_searchphrases(){
292        echo '<p>'.$this->getLang('intro_searchphrases').'</p>';
293        $result = $this->hlp->Query()->searchphrases(true,$this->tlimit,$this->start,150);
294        $this->html_resulttable($result,'',150);
295    }
296
297    function html_searchwords(){
298        echo '<p>'.$this->getLang('intro_searchwords').'</p>';
299        $result = $this->hlp->Query()->searchwords(true,$this->tlimit,$this->start,150);
300        $this->html_resulttable($result,'',150);
301    }
302
303    function html_internalsearchphrases(){
304        echo '<p>'.$this->getLang('intro_internalsearchphrases').'</p>';
305        $result = $this->hlp->Query()->searchphrases(false,$this->tlimit,$this->start,150);
306        $this->html_resulttable($result,'',150);
307    }
308
309    function html_internalsearchwords(){
310        echo '<p>'.$this->getLang('intro_internalsearchwords').'</p>';
311        $result = $this->hlp->Query()->searchwords(false,$this->tlimit,$this->start,150);
312        $this->html_resulttable($result,'',150);
313    }
314
315    function html_searchengines(){
316        echo '<p>'.$this->getLang('intro_searchengines').'</p>';
317        $this->html_graph('searchengines',400,200);
318        $result = $this->hlp->Query()->searchengines($this->tlimit,$this->start,150);
319        $this->html_resulttable($result,'',150);
320    }
321
322    function html_resolution(){
323        echo '<p>'.$this->getLang('intro_resolution').'</p>';
324        $this->html_graph('resolution',650,490);
325        $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150);
326        $this->html_resulttable($result,'',150);
327    }
328
329    function html_viewport(){
330        echo '<p>'.$this->getLang('intro_viewport').'</p>';
331        $this->html_graph('viewport',650,490);
332        $result = $this->hlp->Query()->viewport($this->tlimit,$this->start,150);
333        $this->html_resulttable($result,'',150);
334    }
335
336
337    /**
338     * Display a result in a HTML table
339     */
340    function html_resulttable($result,$header='',$pager=0){
341        echo '<table>';
342        if(is_array($header)){
343            echo '<tr>';
344            foreach($header as $h){
345                echo '<th>'.hsc($h).'</th>';
346            }
347            echo '</tr>';
348        }
349
350        $count = 0;
351        if(is_array($result)) foreach($result as $row){
352            echo '<tr>';
353            foreach($row as $k => $v){
354                if($k == 'res_x') continue;
355                if($k == 'res_y') continue;
356
357                echo '<td class="plg_stats_X'.$k.'">';
358                if($k == 'page'){
359                    echo '<a href="'.wl($v).'" class="wikilink1">';
360                    echo hsc($v);
361                    echo '</a>';
362                }elseif($k == 'url'){
363                    $url = hsc($v);
364                    $url = preg_replace('/^https?:\/\/(www\.)?/','',$url);
365                    if(strlen($url) > 45){
366                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
367                    }
368                    echo '<a href="'.$v.'" class="urlextern">';
369                    echo $url;
370                    echo '</a>';
371                }elseif($k == 'ilookup'){
372                    echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>';
373                }elseif($k == 'lookup'){
374                    echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">';
375                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="Google" border="0" />';
376                    echo '</a> ';
377
378                    echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">';
379                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="Yahoo!" border="0" />';
380                    echo '</a> ';
381
382                    echo '<a href="http://www.bing.com/search?q='.rawurlencode($v).'">';
383                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/bing.png" alt="Bing" border="0" />';
384                    echo '</a> ';
385
386                }elseif($k == 'engine'){
387                    include_once(dirname(__FILE__).'/inc/searchengines.php');
388                    if(isset($SEARCHENGINEINFO[$v])){
389                        echo '<a href="'.$SEARCHENGINEINFO[$v][1].'">'.$SEARCHENGINEINFO[$v][0].'</a>';
390                    }else{
391                        echo hsc(ucwords($v));
392                    }
393                }elseif($k == 'eflag'){
394                    $this->html_icon('search',$v);
395                }elseif($k == 'bflag'){
396                    $this->html_icon('browser',$v);
397                }elseif($k == 'osflag'){
398                    $this->html_icon('os',$v);
399                }elseif($k == 'cflag'){
400                    $this->html_icon('flags',$v);
401                }elseif($k == 'html'){
402                    echo $v;
403                }else{
404                    echo hsc($v);
405                }
406                echo '</td>';
407            }
408            echo '</tr>';
409
410            if($pager && ($count == $pager)) break;
411            $count++;
412        }
413        echo '</table>';
414
415        if($pager) $this->html_pager($pager,count($result) > $pager);
416    }
417
418    function html_icon($type,$value){
419        $value = strtolower(preg_replace('/[^\w]+/','',$value));
420        $file  = 'lib/plugins/statistics/ico/'.$type.'/'.$value.'.png';
421        if(file_exists(DOKU_INC.$file)){
422            echo '<img src="'.DOKU_BASE.$file.'" alt="'.hsc($value).'" width="16" height="16" />';
423        }
424    }
425}
426