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