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