xref: /plugin/statistics/admin.php (revision f0a4ccee9985c9b288636fd60e7968a2d5af6789)
11878f16fSAndreas Gohr<?php
2a8acb244SAndreas Gohr
3a8acb244SAndreas Gohruse dokuwiki\Extension\AdminPlugin;
4a8acb244SAndreas Gohr
51878f16fSAndreas Gohr/**
61878f16fSAndreas Gohr * statistics plugin
71878f16fSAndreas Gohr *
81878f16fSAndreas Gohr * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
96b6f8822SAndreas Gohr * @author     Andreas Gohr <gohr@splitbrain.org>
101878f16fSAndreas Gohr */
11a8acb244SAndreas Gohrclass admin_plugin_statistics extends AdminPlugin
12a8acb244SAndreas Gohr{
1333a136e5SAndreas Gohr    /** @var string the currently selected page */
14a901d721SAndreas Gohr    protected $opt = '';
1533a136e5SAndreas Gohr
1633a136e5SAndreas Gohr    /** @var string from date in YYYY-MM-DD */
17a901d721SAndreas Gohr    protected $from = '';
1833a136e5SAndreas Gohr    /** @var string to date in YYYY-MM-DD */
19a901d721SAndreas Gohr    protected $to = '';
2033a136e5SAndreas Gohr    /** @var int Offset to use when displaying paged data */
2133a136e5SAndreas Gohr    protected $start = 0;
2233a136e5SAndreas Gohr
2333a136e5SAndreas Gohr    /** @var helper_plugin_statistics */
2433a136e5SAndreas Gohr    protected $hlp;
2533a136e5SAndreas Gohr
26a901d721SAndreas Gohr    /**
27a901d721SAndreas Gohr     * Available statistic pages
28a901d721SAndreas Gohr     */
29483101d3SAndreas Gohr    protected $pages = [
30483101d3SAndreas Gohr        'dashboard' => 1,
31483101d3SAndreas Gohr        'content' => ['page', 'edits', 'images', 'downloads', 'history'],
32483101d3SAndreas Gohr        'users' => ['topuser', 'topeditor', 'topgroup', 'topgroupedit', 'seenusers'],
33483101d3SAndreas Gohr        'links' => ['referer', 'newreferer', 'outlinks'],
34483101d3SAndreas Gohr        'search' => ['searchengines', 'searchphrases', 'searchwords', 'internalsearchphrases', 'internalsearchwords'],
35483101d3SAndreas Gohr        'technology' => ['browsers', 'os', 'countries', 'resolution', 'viewport']
36483101d3SAndreas Gohr    ];
371878f16fSAndreas Gohr
3881ff4c3aSAndreas Gohr    /** @var array keeps a list of all real content pages, generated from above array */
39a8acb244SAndreas Gohr    protected $allowedpages = [];
4081ff4c3aSAndreas Gohr
411878f16fSAndreas Gohr    /**
426b6f8822SAndreas Gohr     * Initialize the helper
436b6f8822SAndreas Gohr     */
44a8acb244SAndreas Gohr    public function __construct()
45a8acb244SAndreas Gohr    {
466b6f8822SAndreas Gohr        $this->hlp = plugin_load('helper', 'statistics');
4781ff4c3aSAndreas Gohr
4881ff4c3aSAndreas Gohr        // build a list of pages
4981ff4c3aSAndreas Gohr        foreach ($this->pages as $key => $val) {
5081ff4c3aSAndreas Gohr            if (is_array($val)) {
5181ff4c3aSAndreas Gohr                $this->allowedpages = array_merge($this->allowedpages, $val);
5281ff4c3aSAndreas Gohr            } else {
5381ff4c3aSAndreas Gohr                $this->allowedpages[] = $key;
5481ff4c3aSAndreas Gohr            }
5581ff4c3aSAndreas Gohr        }
566b6f8822SAndreas Gohr    }
576b6f8822SAndreas Gohr
586b6f8822SAndreas Gohr    /**
591878f16fSAndreas Gohr     * Access for managers allowed
601878f16fSAndreas Gohr     */
61a8acb244SAndreas Gohr    public function forAdminOnly()
62a8acb244SAndreas Gohr    {
631878f16fSAndreas Gohr        return false;
641878f16fSAndreas Gohr    }
651878f16fSAndreas Gohr
661878f16fSAndreas Gohr    /**
671878f16fSAndreas Gohr     * return sort order for position in admin menu
681878f16fSAndreas Gohr     */
69a8acb244SAndreas Gohr    public function getMenuSort()
70a8acb244SAndreas Gohr    {
716b6f8822SAndreas Gohr        return 350;
721878f16fSAndreas Gohr    }
731878f16fSAndreas Gohr
741878f16fSAndreas Gohr    /**
751878f16fSAndreas Gohr     * handle user request
761878f16fSAndreas Gohr     */
77a8acb244SAndreas Gohr    public function handle()
78a8acb244SAndreas Gohr    {
79483101d3SAndreas Gohr        global $INPUT;
80483101d3SAndreas Gohr        $this->opt = preg_replace('/[^a-z]+/', '', $INPUT->str('opt'));
8181ff4c3aSAndreas Gohr        if (!in_array($this->opt, $this->allowedpages)) $this->opt = 'dashboard';
82a901d721SAndreas Gohr
83483101d3SAndreas Gohr        $this->start = $INPUT->int('s');
84483101d3SAndreas Gohr        $this->setTimeframe($INPUT->str('f', date('Y-m-d')), $INPUT->str('t', date('Y-m-d')));
85e8699bceSAndreas Gohr    }
8695eb68e6SAndreas Gohr
87e8699bceSAndreas Gohr    /**
88e8699bceSAndreas Gohr     * set limit clause
89e8699bceSAndreas Gohr     */
90a8acb244SAndreas Gohr    public function setTimeframe($from, $to)
91a8acb244SAndreas Gohr    {
92047fcb0fSAndreas Gohr        // swap if wrong order
93a8acb244SAndreas Gohr        if ($from > $to) [$from, $to] = [$to, $from];
94047fcb0fSAndreas Gohr
957428e816SAndreas Gohr        $this->hlp->Query()->setTimeFrame($from, $to);
96e8699bceSAndreas Gohr        $this->from = $from;
97e8699bceSAndreas Gohr        $this->to = $to;
981878f16fSAndreas Gohr    }
991878f16fSAndreas Gohr
1001878f16fSAndreas Gohr    /**
10179b4a855SAndreas Gohr     * Output the Statistics
1021878f16fSAndreas Gohr     */
103a8acb244SAndreas Gohr    public function html()
104a8acb244SAndreas Gohr    {
105*f0a4cceeSAnna Dabrowska        // TODO package JS
106*f0a4cceeSAnna Dabrowska        echo '<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>';
107*f0a4cceeSAnna Dabrowska        echo '<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>';
108*f0a4cceeSAnna Dabrowska
1091d2d78ccSAndreas Gohr        echo '<div id="plugin__statistics">';
1100c3b1e44SAndreas Gohr        echo '<h1>' . $this->getLang('menu') . '</h1>';
111264f1744SAndreas Gohr        $this->html_timeselect();
112441bfb8eSAndreas Gohr        tpl_flush();
113264f1744SAndreas Gohr
11479b4a855SAndreas Gohr        $method = 'html_' . $this->opt;
11579b4a855SAndreas Gohr        if (method_exists($this, $method)) {
116a901d721SAndreas Gohr            echo '<div class="plg_stats_' . $this->opt . '">';
117a901d721SAndreas Gohr            echo '<h2>' . $this->getLang($this->opt) . '</h2>';
11879b4a855SAndreas Gohr            $this->$method();
119a901d721SAndreas Gohr            echo '</div>';
12014d99ec0SAndreas Gohr        }
1211d2d78ccSAndreas Gohr        echo '</div>';
12214d99ec0SAndreas Gohr    }
12314d99ec0SAndreas Gohr
1246b6f8822SAndreas Gohr    /**
1256b6f8822SAndreas Gohr     * Return the TOC
1266b6f8822SAndreas Gohr     *
1276b6f8822SAndreas Gohr     * @return array
1286b6f8822SAndreas Gohr     */
129a8acb244SAndreas Gohr    public function getTOC()
130a8acb244SAndreas Gohr    {
131a8acb244SAndreas Gohr        $toc = [];
13281ff4c3aSAndreas Gohr        foreach ($this->pages as $key => $info) {
13381ff4c3aSAndreas Gohr            if (is_array($info)) {
13481ff4c3aSAndreas Gohr                $toc[] = html_mktocitem(
13581ff4c3aSAndreas Gohr                    '',
13681ff4c3aSAndreas Gohr                    $this->getLang($key),
13781ff4c3aSAndreas Gohr                    1,
13881ff4c3aSAndreas Gohr                    ''
13947ffcf7dSAndreas Gohr                );
14081ff4c3aSAndreas Gohr
14181ff4c3aSAndreas Gohr                foreach ($info as $page) {
14281ff4c3aSAndreas Gohr                    $toc[] = html_mktocitem(
14381ff4c3aSAndreas Gohr                        '?do=admin&amp;page=statistics&amp;opt=' . $page . '&amp;f=' . $this->from . '&amp;t=' . $this->to,
14481ff4c3aSAndreas Gohr                        $this->getLang($page),
14581ff4c3aSAndreas Gohr                        2,
14681ff4c3aSAndreas Gohr                        ''
14781ff4c3aSAndreas Gohr                    );
14881ff4c3aSAndreas Gohr                }
14981ff4c3aSAndreas Gohr            } else {
15081ff4c3aSAndreas Gohr                $toc[] = html_mktocitem(
15181ff4c3aSAndreas Gohr                    '?do=admin&amp;page=statistics&amp;opt=' . $key . '&amp;f=' . $this->from . '&amp;t=' . $this->to,
15281ff4c3aSAndreas Gohr                    $this->getLang($key),
15381ff4c3aSAndreas Gohr                    1,
15481ff4c3aSAndreas Gohr                    ''
15581ff4c3aSAndreas Gohr                );
15681ff4c3aSAndreas Gohr            }
15747ffcf7dSAndreas Gohr        }
15847ffcf7dSAndreas Gohr        return $toc;
1599da6395dSAndreas Gohr    }
1609da6395dSAndreas Gohr
161a8acb244SAndreas Gohr    public function html_graph($name, $width, $height)
162a8acb244SAndreas Gohr    {
163*f0a4cceeSAnna Dabrowska        $this->hlp->Graph($this->from, $this->to, $width, $height)->$name();
164dc7b1e5eSAndreas Gohr    }
165dc7b1e5eSAndreas Gohr
1666b6f8822SAndreas Gohr    /**
1676b6f8822SAndreas Gohr     * Outputs pagination links
1686b6f8822SAndreas Gohr     *
16933a136e5SAndreas Gohr     * @param int $limit
17033a136e5SAndreas Gohr     * @param int $next
1716b6f8822SAndreas Gohr     */
172a8acb244SAndreas Gohr    public function html_pager($limit, $next)
173a8acb244SAndreas Gohr    {
1742507f8e0SAndreas Gohr        echo '<div class="plg_stats_pager">';
1752507f8e0SAndreas Gohr
1762507f8e0SAndreas Gohr        if ($this->start > 0) {
1772507f8e0SAndreas Gohr            $go = max($this->start - $limit, 0);
178d43cd6e0SAndreas Gohr            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 button">' . $this->getLang('prev') . '</a>';
1792507f8e0SAndreas Gohr        }
1802507f8e0SAndreas Gohr
1812507f8e0SAndreas Gohr        if ($next) {
1822507f8e0SAndreas Gohr            $go = $this->start + $limit;
183d43cd6e0SAndreas Gohr            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 button">' . $this->getLang('next') . '</a>';
1842507f8e0SAndreas Gohr        }
1852507f8e0SAndreas Gohr        echo '</div>';
1862507f8e0SAndreas Gohr    }
1872507f8e0SAndreas Gohr
188264f1744SAndreas Gohr    /**
189264f1744SAndreas Gohr     * Print the time selection menu
190264f1744SAndreas Gohr     */
191a8acb244SAndreas Gohr    public function html_timeselect()
192a8acb244SAndreas Gohr    {
193483101d3SAndreas Gohr        $quick = [
194483101d3SAndreas Gohr            'today' => date('Y-m-d'),
195483101d3SAndreas Gohr            'last1' => date('Y-m-d', time() - (60 * 60 * 24)),
196483101d3SAndreas Gohr            'last7' => date('Y-m-d', time() - (60 * 60 * 24 * 7)),
197483101d3SAndreas Gohr            'last30' => date('Y-m-d', time() - (60 * 60 * 24 * 30)),
198483101d3SAndreas Gohr        ];
199483101d3SAndreas Gohr
20014d99ec0SAndreas Gohr
201264f1744SAndreas Gohr        echo '<div class="plg_stats_timeselect">';
2026985b606SAndreas Gohr        echo '<span>' . $this->getLang('time_select') . '</span> ';
203264f1744SAndreas Gohr
204047fcb0fSAndreas Gohr        echo '<form action="' . DOKU_SCRIPT . '" method="get">';
205264f1744SAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
206264f1744SAndreas Gohr        echo '<input type="hidden" name="page" value="statistics" />';
207264f1744SAndreas Gohr        echo '<input type="hidden" name="opt" value="' . $this->opt . '" />';
208483101d3SAndreas Gohr        echo '<input type="date" name="f" value="' . $this->from . '" class="edit" />';
209483101d3SAndreas Gohr        echo '<input type="date" name="t" value="' . $this->to . '" class="edit" />';
210264f1744SAndreas Gohr        echo '<input type="submit" value="go" class="button" />';
21114d99ec0SAndreas Gohr        echo '</form>';
212264f1744SAndreas Gohr
2136985b606SAndreas Gohr        echo '<ul>';
214483101d3SAndreas Gohr        foreach ($quick as $name => $time) {
2156985b606SAndreas Gohr            echo '<li>';
216483101d3SAndreas Gohr            echo '<a href="?do=admin&amp;page=statistics&amp;opt=' . $this->opt . '&amp;f=' . $time . '&amp;t=' . $quick['today'] . '">';
217483101d3SAndreas Gohr            echo $this->getLang('time_' . $name);
2186985b606SAndreas Gohr            echo '</a>';
2196985b606SAndreas Gohr            echo '</li>';
2206985b606SAndreas Gohr        }
2216985b606SAndreas Gohr        echo '</ul>';
2226985b606SAndreas Gohr
223264f1744SAndreas Gohr        echo '</div>';
22414d99ec0SAndreas Gohr    }
22514d99ec0SAndreas Gohr
226f5f32cbfSAndreas Gohr    /**
227f5f32cbfSAndreas Gohr     * Print an introductionary screen
228f5f32cbfSAndreas Gohr     */
229a8acb244SAndreas Gohr    public function html_dashboard()
230a8acb244SAndreas Gohr    {
231878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_dashboard') . '</p>';
2322812a751SAndreas Gohr
2332812a751SAndreas Gohr        // general info
2342812a751SAndreas Gohr        echo '<div class="plg_stats_top">';
2357428e816SAndreas Gohr        $result = $this->hlp->Query()->aggregate();
2361d2d78ccSAndreas Gohr
2371d2d78ccSAndreas Gohr        echo '<ul class="left">';
238a8acb244SAndreas Gohr        foreach (['pageviews', 'sessions', 'visitors', 'users', 'logins', 'current'] as $name) {
239eabe0d07SAndreas Gohr            echo '<li><div class="li">' . sprintf($this->getLang('dash_' . $name), $result[$name]) . '</div></li>';
240eabe0d07SAndreas Gohr        }
2412812a751SAndreas Gohr        echo '</ul>';
2421d2d78ccSAndreas Gohr
2431d2d78ccSAndreas Gohr        echo '<ul class="left">';
244a8acb244SAndreas Gohr        foreach (['bouncerate', 'timespent', 'avgpages', 'newvisitors', 'registrations'] as $name) {
2451d2d78ccSAndreas Gohr            echo '<li><div class="li">' . sprintf($this->getLang('dash_' . $name), $result[$name]) . '</div></li>';
2461d2d78ccSAndreas Gohr        }
2471d2d78ccSAndreas Gohr        echo '</ul>';
2481d2d78ccSAndreas Gohr
24956f647ddSAndreas Gohr        echo '<br style="clear: left" />';
25056f647ddSAndreas Gohr
251259897e1SAndreas Gohr        $this->html_graph('dashboardviews', 700, 280);
252259897e1SAndreas Gohr        $this->html_graph('dashboardwiki', 700, 280);
2532812a751SAndreas Gohr        echo '</div>';
2542812a751SAndreas Gohr
25587d5e44bSAndreas Gohr        // top pages today
256264f1744SAndreas Gohr        echo '<div>';
257dc7b1e5eSAndreas Gohr        echo '<h2>' . $this->getLang('dash_mostpopular') . '</h2>';
2587428e816SAndreas Gohr        $result = $this->hlp->Query()->pages($this->start, 15);
2592812a751SAndreas Gohr        $this->html_resulttable($result);
260d43cd6e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f=' . $this->from . '&amp;t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>';
261264f1744SAndreas Gohr        echo '</div>';
26287d5e44bSAndreas Gohr
26387d5e44bSAndreas Gohr        // top referer today
264264f1744SAndreas Gohr        echo '<div>';
265dc7b1e5eSAndreas Gohr        echo '<h2>' . $this->getLang('dash_newincoming') . '</h2>';
2667428e816SAndreas Gohr        $result = $this->hlp->Query()->newreferer($this->start, 15);
2672812a751SAndreas Gohr        $this->html_resulttable($result);
268d43cd6e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f=' . $this->from . '&amp;t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>';
269264f1744SAndreas Gohr        echo '</div>';
27054f6c432SAndreas Gohr
27129dea504SAndreas Gohr        // top searches today
272264f1744SAndreas Gohr        echo '<div>';
273dc7b1e5eSAndreas Gohr        echo '<h2>' . $this->getLang('dash_topsearch') . '</h2>';
2747428e816SAndreas Gohr        $result = $this->hlp->Query()->searchphrases(true, $this->start, 15);
27529dea504SAndreas Gohr        $this->html_resulttable($result);
276d43cd6e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f=' . $this->from . '&amp;t=' . $this->to . '" class="more button">' . $this->getLang('more') . '</a>';
277264f1744SAndreas Gohr        echo '</div>';
27814d99ec0SAndreas Gohr    }
27914d99ec0SAndreas Gohr
280a8acb244SAndreas Gohr    public function html_history()
281a8acb244SAndreas Gohr    {
282cae4a1c5SAndreas Gohr        echo '<p>' . $this->getLang('intro_history') . '</p>';
283338987f5SAndreas Gohr        $this->html_graph('history_page_count', 600, 200);
284338987f5SAndreas Gohr        $this->html_graph('history_page_size', 600, 200);
285338987f5SAndreas Gohr        $this->html_graph('history_media_count', 600, 200);
286338987f5SAndreas Gohr        $this->html_graph('history_media_size', 600, 200);
287cae4a1c5SAndreas Gohr    }
288cae4a1c5SAndreas Gohr
289a8acb244SAndreas Gohr    public function html_countries()
290a8acb244SAndreas Gohr    {
291878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_countries') . '</p>';
292*f0a4cceeSAnna Dabrowska        $this->html_graph('countries', 200, 200);
293*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->countries();
2942507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
2959da6395dSAndreas Gohr    }
2969da6395dSAndreas Gohr
297a8acb244SAndreas Gohr    public function html_page()
298a8acb244SAndreas Gohr    {
299878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_page') . '</p>';
300*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->pages();
3012507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
3029da6395dSAndreas Gohr    }
3039da6395dSAndreas Gohr
304a8acb244SAndreas Gohr    public function html_edits()
305a8acb244SAndreas Gohr    {
3061664ba1dSAndreas Gohr        echo '<p>' . $this->getLang('intro_edits') . '</p>';
307*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->edits();
3081664ba1dSAndreas Gohr        $this->html_resulttable($result, '', 150);
3091664ba1dSAndreas Gohr    }
3101664ba1dSAndreas Gohr
311a8acb244SAndreas Gohr    public function html_images()
312a8acb244SAndreas Gohr    {
3131664ba1dSAndreas Gohr        echo '<p>' . $this->getLang('intro_images') . '</p>';
314616c1e8bSAndreas Gohr
3157428e816SAndreas Gohr        $result = $this->hlp->Query()->imagessum();
316616c1e8bSAndreas Gohr        echo '<p>';
317616c1e8bSAndreas Gohr        echo sprintf($this->getLang('trafficsum'), $result[0]['cnt'], filesize_h($result[0]['filesize']));
318616c1e8bSAndreas Gohr        echo '</p>';
319616c1e8bSAndreas Gohr
320*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->images();
3211664ba1dSAndreas Gohr        $this->html_resulttable($result, '', 150);
3221664ba1dSAndreas Gohr    }
3231664ba1dSAndreas Gohr
324a8acb244SAndreas Gohr    public function html_downloads()
325a8acb244SAndreas Gohr    {
3261664ba1dSAndreas Gohr        echo '<p>' . $this->getLang('intro_downloads') . '</p>';
327616c1e8bSAndreas Gohr
3287428e816SAndreas Gohr        $result = $this->hlp->Query()->downloadssum();
329616c1e8bSAndreas Gohr        echo '<p>';
330616c1e8bSAndreas Gohr        echo sprintf($this->getLang('trafficsum'), $result[0]['cnt'], filesize_h($result[0]['filesize']));
331616c1e8bSAndreas Gohr        echo '</p>';
332616c1e8bSAndreas Gohr
333*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->downloads();
3341664ba1dSAndreas Gohr        $this->html_resulttable($result, '', 150);
3351664ba1dSAndreas Gohr    }
3361664ba1dSAndreas Gohr
337a8acb244SAndreas Gohr    public function html_browsers()
338a8acb244SAndreas Gohr    {
339878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_browsers') . '</p>';
340*f0a4cceeSAnna Dabrowska        $this->html_graph('browsers', 200, 200);
341*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->browsers(false);
3422507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
34375fa767dSAndreas Gohr    }
34475fa767dSAndreas Gohr
345a8acb244SAndreas Gohr    public function html_topuser()
346a8acb244SAndreas Gohr    {
34781ff4c3aSAndreas Gohr        echo '<p>' . $this->getLang('intro_topuser') . '</p>';
348*f0a4cceeSAnna Dabrowska        $this->html_graph('topuser', 200, 200);
349*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->topuser();
35081ff4c3aSAndreas Gohr        $this->html_resulttable($result, '', 150);
35181ff4c3aSAndreas Gohr    }
35281ff4c3aSAndreas Gohr
353a8acb244SAndreas Gohr    public function html_topeditor()
354a8acb244SAndreas Gohr    {
35581ff4c3aSAndreas Gohr        echo '<p>' . $this->getLang('intro_topeditor') . '</p>';
356*f0a4cceeSAnna Dabrowska        $this->html_graph('topeditor', 200, 200);
357*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->topeditor();
35881ff4c3aSAndreas Gohr        $this->html_resulttable($result, '', 150);
35981ff4c3aSAndreas Gohr    }
36081ff4c3aSAndreas Gohr
361a8acb244SAndreas Gohr    public function html_topgroup()
362a8acb244SAndreas Gohr    {
36381ff4c3aSAndreas Gohr        echo '<p>' . $this->getLang('intro_topgroup') . '</p>';
364*f0a4cceeSAnna Dabrowska        $this->html_graph('topgroup', 200, 200);
365*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->topgroup();
36681ff4c3aSAndreas Gohr        $this->html_resulttable($result, '', 150);
36781ff4c3aSAndreas Gohr    }
36881ff4c3aSAndreas Gohr
369a8acb244SAndreas Gohr    public function html_topgroupedit()
370a8acb244SAndreas Gohr    {
37181ff4c3aSAndreas Gohr        echo '<p>' . $this->getLang('intro_topgroupedit') . '</p>';
372*f0a4cceeSAnna Dabrowska        $this->html_graph('topgroupedit', 200, 200);
373*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->topgroupedit();
37481ff4c3aSAndreas Gohr        $this->html_resulttable($result, '', 150);
37581ff4c3aSAndreas Gohr    }
37681ff4c3aSAndreas Gohr
377a8acb244SAndreas Gohr    public function html_os()
378a8acb244SAndreas Gohr    {
379878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_os') . '</p>';
380*f0a4cceeSAnna Dabrowska        $this->html_graph('os', 200, 200);
381*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->os();
3822507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
383bd4217d3SAndreas Gohr    }
384bd4217d3SAndreas Gohr
385a8acb244SAndreas Gohr    public function html_referer()
386a8acb244SAndreas Gohr    {
3877428e816SAndreas Gohr        $result = $this->hlp->Query()->aggregate();
3882812a751SAndreas Gohr
3892812a751SAndreas Gohr        $all = $result['search'] + $result['external'] + $result['direct'];
3902812a751SAndreas Gohr
39194023548SAndreas Gohr        if ($all) {
3920863c19cSAndreas Gohr            printf(
3930863c19cSAndreas Gohr                '<p>' . $this->getLang('intro_referer') . '</p>',
394a8acb244SAndreas Gohr                $all,
395a8acb244SAndreas Gohr                $result['direct'],
396a8acb244SAndreas Gohr                (100 * $result['direct'] / $all),
397a8acb244SAndreas Gohr                $result['search'],
398a8acb244SAndreas Gohr                (100 * $result['search'] / $all),
399a8acb244SAndreas Gohr                $result['external'],
4000863c19cSAndreas Gohr                (100 * $result['external'] / $all)
4010863c19cSAndreas Gohr            );
40294023548SAndreas Gohr        }
4032812a751SAndreas Gohr
404*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->referer();
4052507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
4069da6395dSAndreas Gohr    }
4079da6395dSAndreas Gohr
408a8acb244SAndreas Gohr    public function html_newreferer()
409a8acb244SAndreas Gohr    {
410878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_newreferer') . '</p>';
411e7a2f1e0SAndreas Gohr
412*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->newreferer();
4132507f8e0SAndreas Gohr        $this->html_resulttable($result, '', 150);
414e7a2f1e0SAndreas Gohr    }
415e7a2f1e0SAndreas Gohr
416a8acb244SAndreas Gohr    public function html_outlinks()
417a8acb244SAndreas Gohr    {
418878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_outlinks') . '</p>';
419*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->outlinks();
420e25286daSAndreas Gohr        $this->html_resulttable($result, '', 150);
421e25286daSAndreas Gohr    }
422e25286daSAndreas Gohr
423a8acb244SAndreas Gohr    public function html_searchphrases()
424a8acb244SAndreas Gohr    {
425878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_searchphrases') . '</p>';
426*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->searchphrases(true);
42712dcdeccSAndreas Gohr        $this->html_resulttable($result, '', 150);
42812dcdeccSAndreas Gohr    }
42912dcdeccSAndreas Gohr
430a8acb244SAndreas Gohr    public function html_searchwords()
431a8acb244SAndreas Gohr    {
432878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_searchwords') . '</p>';
433*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->searchwords(true);
4345bccfe87SAndreas Gohr        $this->html_resulttable($result, '', 150);
4355bccfe87SAndreas Gohr    }
4365bccfe87SAndreas Gohr
437a8acb244SAndreas Gohr    public function html_internalsearchphrases()
438a8acb244SAndreas Gohr    {
439878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_internalsearchphrases') . '</p>';
440*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->searchphrases(false);
4415bccfe87SAndreas Gohr        $this->html_resulttable($result, '', 150);
4425bccfe87SAndreas Gohr    }
4435bccfe87SAndreas Gohr
444a8acb244SAndreas Gohr    public function html_internalsearchwords()
445a8acb244SAndreas Gohr    {
446878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_internalsearchwords') . '</p>';
447*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->searchwords(false);
44812dcdeccSAndreas Gohr        $this->html_resulttable($result, '', 150);
44912dcdeccSAndreas Gohr    }
45012dcdeccSAndreas Gohr
451a8acb244SAndreas Gohr    public function html_searchengines()
452a8acb244SAndreas Gohr    {
453878be5c9SAndreas Gohr        echo '<p>' . $this->getLang('intro_searchengines') . '</p>';
45425b71d4bSAndreas Gohr        $this->html_graph('searchengines', 400, 200);
455*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->searchengines();
45612dcdeccSAndreas Gohr        $this->html_resulttable($result, '', 150);
45712dcdeccSAndreas Gohr    }
45812dcdeccSAndreas Gohr
459a8acb244SAndreas Gohr    public function html_resolution()
460a8acb244SAndreas Gohr    {
46125446aa2SAndreas Gohr        echo '<p>' . $this->getLang('intro_resolution') . '</p>';
46225446aa2SAndreas Gohr        $this->html_graph('resolution', 650, 490);
463*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->resolution();
464307baf3fSAndreas Gohr        $this->html_resulttable($result, '', 150);
46525446aa2SAndreas Gohr    }
466307baf3fSAndreas Gohr
467a8acb244SAndreas Gohr    public function html_viewport()
468a8acb244SAndreas Gohr    {
46925446aa2SAndreas Gohr        echo '<p>' . $this->getLang('intro_viewport') . '</p>';
47025446aa2SAndreas Gohr        $this->html_graph('viewport', 650, 490);
471*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->viewport();
47225446aa2SAndreas Gohr        $this->html_resulttable($result, '', 150);
473c73e16f1SAndreas Gohr    }
4749da6395dSAndreas Gohr
475a8acb244SAndreas Gohr    public function html_seenusers()
476a8acb244SAndreas Gohr    {
47733a136e5SAndreas Gohr        echo '<p>' . $this->getLang('intro_seenusers') . '</p>';
478*f0a4cceeSAnna Dabrowska        $result = $this->hlp->Query()->seenusers();
47933a136e5SAndreas Gohr        $this->html_resulttable($result, '', 150);
48033a136e5SAndreas Gohr    }
48133a136e5SAndreas Gohr
48214d99ec0SAndreas Gohr    /**
48314d99ec0SAndreas Gohr     * Display a result in a HTML table
48414d99ec0SAndreas Gohr     */
485a8acb244SAndreas Gohr    public function html_resulttable($result, $header = '', $pager = 0)
486a8acb244SAndreas Gohr    {
48756f647ddSAndreas Gohr        echo '<table class="inline">';
4882812a751SAndreas Gohr        if (is_array($header)) {
48914d99ec0SAndreas Gohr            echo '<tr>';
49014d99ec0SAndreas Gohr            foreach ($header as $h) {
49114d99ec0SAndreas Gohr                echo '<th>' . hsc($h) . '</th>';
49214d99ec0SAndreas Gohr            }
49314d99ec0SAndreas Gohr            echo '</tr>';
4942812a751SAndreas Gohr        }
49514d99ec0SAndreas Gohr
4962507f8e0SAndreas Gohr        $count = 0;
4972ee939eeSAndreas Gohr        if (is_array($result)) foreach ($result as $row) {
49814d99ec0SAndreas Gohr            echo '<tr>';
49914d99ec0SAndreas Gohr            foreach ($row as $k => $v) {
500f3818071SAndreas Gohr                if ($k == 'res_x') continue;
501f3818071SAndreas Gohr                if ($k == 'res_y') continue;
502f3818071SAndreas Gohr
5032812a751SAndreas Gohr                echo '<td class="plg_stats_X' . $k . '">';
50414d99ec0SAndreas Gohr                if ($k == 'page') {
50514d99ec0SAndreas Gohr                    echo '<a href="' . wl($v) . '" class="wikilink1">';
50614d99ec0SAndreas Gohr                    echo hsc($v);
50714d99ec0SAndreas Gohr                    echo '</a>';
5081664ba1dSAndreas Gohr                } elseif ($k == 'media') {
5091664ba1dSAndreas Gohr                    echo '<a href="' . ml($v) . '" class="wikilink1">';
5101664ba1dSAndreas Gohr                    echo hsc($v);
5111664ba1dSAndreas Gohr                    echo '</a>';
5121664ba1dSAndreas Gohr                } elseif ($k == 'filesize') {
5131664ba1dSAndreas Gohr                    echo filesize_h($v);
51414d99ec0SAndreas Gohr                } elseif ($k == 'url') {
51554f6c432SAndreas Gohr                    $url = hsc($v);
51683b63546SAndreas Gohr                    $url = preg_replace('/^https?:\/\/(www\.)?/', '', $url);
5172812a751SAndreas Gohr                    if (strlen($url) > 45) {
5182812a751SAndreas Gohr                        $url = substr($url, 0, 30) . ' &hellip; ' . substr($url, -15);
51954f6c432SAndreas Gohr                    }
52014d99ec0SAndreas Gohr                    echo '<a href="' . $v . '" class="urlextern">';
52154f6c432SAndreas Gohr                    echo $url;
52214d99ec0SAndreas Gohr                    echo '</a>';
5235bccfe87SAndreas Gohr                } elseif ($k == 'ilookup') {
524a8acb244SAndreas Gohr                    echo '<a href="' . wl('', ['id' => $v, 'do' => 'search']) . '">Search</a>';
52529dea504SAndreas Gohr                } elseif ($k == 'lookup') {
52629dea504SAndreas Gohr                    echo '<a href="http://www.google.com/search?q=' . rawurlencode($v) . '">';
52713a86c14SAndreas Gohr                    echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/google.png" alt="Google" border="0" />';
52829dea504SAndreas Gohr                    echo '</a> ';
52929dea504SAndreas Gohr
53029dea504SAndreas Gohr                    echo '<a href="http://search.yahoo.com/search?p=' . rawurlencode($v) . '">';
53113a86c14SAndreas Gohr                    echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/yahoo.png" alt="Yahoo!" border="0" />';
53229dea504SAndreas Gohr                    echo '</a> ';
53329dea504SAndreas Gohr
53413a86c14SAndreas Gohr                    echo '<a href="http://www.bing.com/search?q=' . rawurlencode($v) . '">';
53513a86c14SAndreas Gohr                    echo '<img src="' . DOKU_BASE . 'lib/plugins/statistics/ico/search/bing.png" alt="Bing" border="0" />';
53629dea504SAndreas Gohr                    echo '</a> ';
53712dcdeccSAndreas Gohr                } elseif ($k == 'engine') {
538a8acb244SAndreas Gohr                    include_once(__DIR__ . '/inc/searchengines.php');
53913a86c14SAndreas Gohr                    if (isset($SEARCHENGINEINFO[$v])) {
54013a86c14SAndreas Gohr                        echo '<a href="' . $SEARCHENGINEINFO[$v][1] . '">' . $SEARCHENGINEINFO[$v][0] . '</a>';
54113a86c14SAndreas Gohr                    } else {
54213a86c14SAndreas Gohr                        echo hsc(ucwords($v));
54313a86c14SAndreas Gohr                    }
54413a86c14SAndreas Gohr                } elseif ($k == 'eflag') {
54513a86c14SAndreas Gohr                    $this->html_icon('search', $v);
54675fa767dSAndreas Gohr                } elseif ($k == 'bflag') {
54713a86c14SAndreas Gohr                    $this->html_icon('browser', $v);
548bd4217d3SAndreas Gohr                } elseif ($k == 'osflag') {
54913a86c14SAndreas Gohr                    $this->html_icon('os', $v);
55075fa767dSAndreas Gohr                } elseif ($k == 'cflag') {
55113a86c14SAndreas Gohr                    $this->html_icon('flags', $v);
55214d99ec0SAndreas Gohr                } elseif ($k == 'html') {
55314d99ec0SAndreas Gohr                    echo $v;
55414d99ec0SAndreas Gohr                } else {
55514d99ec0SAndreas Gohr                    echo hsc($v);
55614d99ec0SAndreas Gohr                }
55714d99ec0SAndreas Gohr                echo '</td>';
55814d99ec0SAndreas Gohr            }
55914d99ec0SAndreas Gohr            echo '</tr>';
5602507f8e0SAndreas Gohr
5612507f8e0SAndreas Gohr            if ($pager && ($count == $pager)) break;
5622507f8e0SAndreas Gohr            $count++;
56314d99ec0SAndreas Gohr        }
56414d99ec0SAndreas Gohr        echo '</table>';
5652507f8e0SAndreas Gohr
5662507f8e0SAndreas Gohr        if ($pager) $this->html_pager($pager, count($result) > $pager);
5671878f16fSAndreas Gohr    }
5681878f16fSAndreas Gohr
569a8acb244SAndreas Gohr    public function html_icon($type, $value)
570a8acb244SAndreas Gohr    {
57113a86c14SAndreas Gohr        $value = strtolower(preg_replace('/[^\w]+/', '', $value));
5729bb008afSAndreas Gohr        $value = str_replace(' ', '_', $value);
573a8acb244SAndreas Gohr
57413a86c14SAndreas Gohr        $file = 'lib/plugins/statistics/ico/' . $type . '/' . $value . '.png';
575dffb869bSAndreas Gohr        if ($type == 'flags') {
576dffb869bSAndreas Gohr            $w = 18;
577dffb869bSAndreas Gohr            $h = 12;
578dffb869bSAndreas Gohr        } else {
579dffb869bSAndreas Gohr            $w = 16;
580dffb869bSAndreas Gohr            $h = 16;
581dffb869bSAndreas Gohr        }
58213a86c14SAndreas Gohr        if (file_exists(DOKU_INC . $file)) {
583dffb869bSAndreas Gohr            echo '<img src="' . DOKU_BASE . $file . '" alt="' . hsc($value) . '" width="' . $w . '" height="' . $h . '" />';
58413a86c14SAndreas Gohr        }
58513a86c14SAndreas Gohr    }
5861878f16fSAndreas Gohr}
587