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