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