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