xref: /plugin/statistics/admin.php (revision eabe0d07c30a5b0d4bf51212b11c020f21d748b1)
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','timespent') 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        $result = $this->hlp->Query()->resolution($this->tlimit,$this->start,150);
317        $this->html_resulttable($result,'',150);
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=view&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
326    }
327
328
329    /**
330     * Display a result in a HTML table
331     */
332    function html_resulttable($result,$header='',$pager=0){
333        echo '<table>';
334        if(is_array($header)){
335            echo '<tr>';
336            foreach($header as $h){
337                echo '<th>'.hsc($h).'</th>';
338            }
339            echo '</tr>';
340        }
341
342        $count = 0;
343        if(is_array($result)) foreach($result as $row){
344            echo '<tr>';
345            foreach($row as $k => $v){
346                echo '<td class="plg_stats_X'.$k.'">';
347                if($k == 'page'){
348                    echo '<a href="'.wl($v).'" class="wikilink1">';
349                    echo hsc($v);
350                    echo '</a>';
351                }elseif($k == 'url'){
352                    $url = hsc($v);
353                    $url = preg_replace('/^https?:\/\/(www\.)?/','',$url);
354                    if(strlen($url) > 45){
355                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
356                    }
357                    echo '<a href="'.$v.'" class="urlextern">';
358                    echo $url;
359                    echo '</a>';
360                }elseif($k == 'ilookup'){
361                    echo '<a href="'.wl('',array('id'=>$v,'do'=>'search')).'">Search</a>';
362                }elseif($k == 'lookup'){
363                    echo '<a href="http://www.google.com/search?q='.rawurlencode($v).'">';
364                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/google.png" alt="lookup in Google" border="0" />';
365                    echo '</a> ';
366
367                    echo '<a href="http://search.yahoo.com/search?p='.rawurlencode($v).'">';
368                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/yahoo.png" alt="lookup in Yahoo" border="0" />';
369                    echo '</a> ';
370
371                    echo '<a href="http://search.msn.com/results.aspx?q='.rawurlencode($v).'">';
372                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/search/msn.png" alt="lookup in MSN Live" border="0" />';
373                    echo '</a> ';
374
375                }elseif($k == 'engine'){
376                    include_once(dirname(__FILE__).'/inc/search_engines.php');
377                    echo $SearchEnginesHashLib[$v];
378                }elseif($k == 'bflag'){
379                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
380                }elseif($k == 'osflag'){
381                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.strtolower(preg_replace('/[^\w]+/','',$v)).'.png" alt="'.hsc($v).'" />';
382                }elseif($k == 'cflag'){
383                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
384                }elseif($k == 'html'){
385                    echo $v;
386                }else{
387                    echo hsc($v);
388                }
389                echo '</td>';
390            }
391            echo '</tr>';
392
393            if($pager && ($count == $pager)) break;
394            $count++;
395        }
396        echo '</table>';
397
398        if($pager) $this->html_pager($pager,count($result) > $pager);
399    }
400
401}
402