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