xref: /plugin/statistics/Query.php (revision f9e60319e80aa3da7ac39dc9a7a1e018c34337df)
1b6632b6eSAndreas Gohr<?php
2b6632b6eSAndreas Gohr
3b6632b6eSAndreas Gohrnamespace dokuwiki\plugin\statistics;
4b6632b6eSAndreas Gohr
5*f9e60319SAndreas Gohr
6*f9e60319SAndreas Gohruse dokuwiki\plugin\sqlite\SQLiteDB;
7b6632b6eSAndreas Gohruse helper_plugin_statistics;
8b6632b6eSAndreas Gohr
9*f9e60319SAndreas Gohr/**
10*f9e60319SAndreas Gohr * This class defines a bunch of SQL queries to fetch various statistics from the database
11*f9e60319SAndreas Gohr */
12b6632b6eSAndreas Gohrclass Query
13b6632b6eSAndreas Gohr{
14*f9e60319SAndreas Gohr    protected helper_plugin_statistics $hlp;
15*f9e60319SAndreas Gohr    protected SQLiteDB $db;
16*f9e60319SAndreas Gohr    protected string $from;
17*f9e60319SAndreas Gohr    protected string $to;
18*f9e60319SAndreas Gohr    protected string $limit = '';
19b6632b6eSAndreas Gohr
20*f9e60319SAndreas Gohr    /**
21*f9e60319SAndreas Gohr     * @param helper_plugin_statistics $hlp
22*f9e60319SAndreas Gohr     */
23b6632b6eSAndreas Gohr    public function __construct(helper_plugin_statistics $hlp)
24b6632b6eSAndreas Gohr    {
25b6632b6eSAndreas Gohr        $this->hlp = $hlp;
26*f9e60319SAndreas Gohr        $this->db = $hlp->getDB();
277428e816SAndreas Gohr        $today = date('Y-m-d');
287428e816SAndreas Gohr        $this->setTimeFrame($today, $today);
29*f9e60319SAndreas Gohr        $this->setPagination(0, 20);
307428e816SAndreas Gohr    }
317428e816SAndreas Gohr
327428e816SAndreas Gohr    /**
337428e816SAndreas Gohr     * Set the time frame for all queries
34*f9e60319SAndreas Gohr     *
35*f9e60319SAndreas Gohr     * @param string $from The start date as YYYY-MM-DD
36*f9e60319SAndreas Gohr     * @param string $to The end date as YYYY-MM-DD
377428e816SAndreas Gohr     */
38*f9e60319SAndreas Gohr    public function setTimeFrame(string $from, string $to): void
397428e816SAndreas Gohr    {
40*f9e60319SAndreas Gohr        try {
41*f9e60319SAndreas Gohr            $from = new \DateTime($from);
42*f9e60319SAndreas Gohr            $to = new \DateTime($to);
43*f9e60319SAndreas Gohr        } catch (\Exception $e) {
44*f9e60319SAndreas Gohr            $from = new \DateTime();
45*f9e60319SAndreas Gohr            $to = new \DateTime();
46*f9e60319SAndreas Gohr        }
47*f9e60319SAndreas Gohr        $from->setTime(0, 0);
48*f9e60319SAndreas Gohr        $to->setTime(23, 59, 59);
497428e816SAndreas Gohr
50*f9e60319SAndreas Gohr        $this->from = $from->format('Y-m-d H:i:s');
51*f9e60319SAndreas Gohr        $this->to = $to->format('Y-m-d H:i:s');
52*f9e60319SAndreas Gohr    }
53*f9e60319SAndreas Gohr
54*f9e60319SAndreas Gohr    /**
55*f9e60319SAndreas Gohr     * Set the pagination settings for some queries
56*f9e60319SAndreas Gohr     *
57*f9e60319SAndreas Gohr     * @param int $start The start offset
58*f9e60319SAndreas Gohr     * @param int $limit The number of results. If one more is returned, there is another page
59*f9e60319SAndreas Gohr     * @return void
60*f9e60319SAndreas Gohr     */
61*f9e60319SAndreas Gohr    public function setPagination(int $start, int $limit)
62*f9e60319SAndreas Gohr    {
63*f9e60319SAndreas Gohr        // when a limit is set, one more is fetched to indicate when a next page exists
64*f9e60319SAndreas Gohr        if ($limit) $limit += 1;
65*f9e60319SAndreas Gohr
66*f9e60319SAndreas Gohr        if ($limit) {
67*f9e60319SAndreas Gohr            $this->limit = " LIMIT $start,$limit";
68*f9e60319SAndreas Gohr        } elseif ($start) {
69*f9e60319SAndreas Gohr            $this->limit = " OFFSET $start";
70*f9e60319SAndreas Gohr        }
71b6632b6eSAndreas Gohr    }
72b6632b6eSAndreas Gohr
73b6632b6eSAndreas Gohr    /**
74b6632b6eSAndreas Gohr     * Return some aggregated statistics
75b6632b6eSAndreas Gohr     */
76*f9e60319SAndreas Gohr    public function aggregate(): array
77b6632b6eSAndreas Gohr    {
78b6632b6eSAndreas Gohr        $data = [];
79b6632b6eSAndreas Gohr
80b6632b6eSAndreas Gohr        $sql = "SELECT ref_type, COUNT(*) as cnt
817428e816SAndreas Gohr                  FROM access as A
827428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
837428e816SAndreas Gohr                   AND ua_type = ?
84b6632b6eSAndreas Gohr              GROUP BY ref_type";
85*f9e60319SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->from, $this->to, 'browser']);
86b6632b6eSAndreas Gohr
87*f9e60319SAndreas Gohr        foreach ($result as $row) {
88b6632b6eSAndreas Gohr            if ($row['ref_type'] == 'search') $data['search'] = $row['cnt'];
89b6632b6eSAndreas Gohr            if ($row['ref_type'] == 'external') $data['external'] = $row['cnt'];
90b6632b6eSAndreas Gohr            if ($row['ref_type'] == 'internal') $data['internal'] = $row['cnt'];
91b6632b6eSAndreas Gohr            if ($row['ref_type'] == '') $data['direct'] = $row['cnt'];
92b6632b6eSAndreas Gohr        }
93b6632b6eSAndreas Gohr
94b6632b6eSAndreas Gohr        // general user and session info
95b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as sessions,
96b6632b6eSAndreas Gohr                       COUNT(session) as views,
97b6632b6eSAndreas Gohr                       COUNT(DISTINCT user) as users,
98b6632b6eSAndreas Gohr                       COUNT(DISTINCT uid) as visitors
997428e816SAndreas Gohr                  FROM access as A
1007428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
1017428e816SAndreas Gohr                   AND ua_type = ?";
102*f9e60319SAndreas Gohr        $result = $this->db->queryRecord($sql, [$this->from, $this->to, 'browser']);
103b6632b6eSAndreas Gohr
104*f9e60319SAndreas Gohr        $data['users'] = max($result['users'] - 1, 0); // subtract empty user
105*f9e60319SAndreas Gohr        $data['sessions'] = $result['sessions'];
106*f9e60319SAndreas Gohr        $data['pageviews'] = $result['views'];
107*f9e60319SAndreas Gohr        $data['visitors'] = $result['visitors'];
108b6632b6eSAndreas Gohr
109b6632b6eSAndreas Gohr        // calculate bounce rate
110b6632b6eSAndreas Gohr        if ($data['sessions']) {
111b6632b6eSAndreas Gohr            $sql = "SELECT COUNT(*) as cnt
1127428e816SAndreas Gohr                      FROM session as A
1137428e816SAndreas Gohr                     WHERE A.dt >= ? AND A.dt <= ?
1147428e816SAndreas Gohr                       AND views = ?";
115*f9e60319SAndreas Gohr            $count = $this->db->queryValue($sql, [$this->from, $this->to, 1]);
116*f9e60319SAndreas Gohr            $data['bouncerate'] = $count * 100 / $data['sessions'];
117*f9e60319SAndreas Gohr            $data['newvisitors'] = $count * 100 / $data['sessions'];
118b6632b6eSAndreas Gohr        }
119b6632b6eSAndreas Gohr
120b6632b6eSAndreas Gohr        // calculate avg. number of views per session
121b6632b6eSAndreas Gohr        $sql = "SELECT AVG(views) as cnt
1227428e816SAndreas Gohr                  FROM session as A
1237428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?";
124*f9e60319SAndreas Gohr        $data['avgpages'] = $this->db->queryValue($sql, [$this->from, $this->to]);
125b6632b6eSAndreas Gohr
126b6632b6eSAndreas Gohr        // average time spent on the site
127b6632b6eSAndreas Gohr        $sql = "SELECT AVG(end - dt)/60 as time
1287428e816SAndreas Gohr                  FROM session as A
1297428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
130b6632b6eSAndreas Gohr                   AND dt != end
131b6632b6eSAndreas Gohr                   AND DATE(dt) = DATE(end)";
132*f9e60319SAndreas Gohr        $data['timespent'] = $this->db->queryValue($sql, [$this->from, $this->to]);
133b6632b6eSAndreas Gohr
134b6632b6eSAndreas Gohr        // logins
135b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as logins
1367428e816SAndreas Gohr                  FROM logins as A
1377428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
1387428e816SAndreas Gohr                   AND (type = ? OR type = ?)";
139*f9e60319SAndreas Gohr        $data['logins'] = $this->db->queryValue($sql, [$this->from, $this->to, 'l', 'p']);
140b6632b6eSAndreas Gohr
141b6632b6eSAndreas Gohr        // registrations
142b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as registrations
1437428e816SAndreas Gohr                  FROM logins as A
1447428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
1457428e816SAndreas Gohr                   AND type = ?";
146*f9e60319SAndreas Gohr        $data['registrations'] = $this->db->queryValue($sql, [$this->from, $this->to, 'C']);
147b6632b6eSAndreas Gohr
148b6632b6eSAndreas Gohr        // current users
149b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as current
1507428e816SAndreas Gohr                  FROM lastseen
1517428e816SAndreas Gohr                 WHERE dt >= datetime('now', '-10 minutes')";
152*f9e60319SAndreas Gohr        $data['current'] = $this->db->queryValue($sql);
153b6632b6eSAndreas Gohr
154b6632b6eSAndreas Gohr        return $data;
155b6632b6eSAndreas Gohr    }
156b6632b6eSAndreas Gohr
157b6632b6eSAndreas Gohr
158b6632b6eSAndreas Gohr    /**
159b6632b6eSAndreas Gohr     * Return some trend data about visits and edits in the wiki
160*f9e60319SAndreas Gohr     *
161*f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
162*f9e60319SAndreas Gohr     * @return array
163b6632b6eSAndreas Gohr     */
164*f9e60319SAndreas Gohr    public function dashboardviews(bool $hours = false): array
165b6632b6eSAndreas Gohr    {
166b6632b6eSAndreas Gohr        if ($hours) {
1677428e816SAndreas Gohr            $TIME = 'strftime(\'%H\', dt)';
168b6632b6eSAndreas Gohr        } else {
169b6632b6eSAndreas Gohr            $TIME = 'DATE(dt)';
170b6632b6eSAndreas Gohr        }
171b6632b6eSAndreas Gohr
172b6632b6eSAndreas Gohr        $data = [];
173b6632b6eSAndreas Gohr
174b6632b6eSAndreas Gohr        // access trends
175b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
176b6632b6eSAndreas Gohr                       COUNT(DISTINCT session) as sessions,
177b6632b6eSAndreas Gohr                       COUNT(session) as pageviews,
178b6632b6eSAndreas Gohr                       COUNT(DISTINCT uid) as visitors
1797428e816SAndreas Gohr                  FROM access as A
1807428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
1817428e816SAndreas Gohr                   AND ua_type = ?
182b6632b6eSAndreas Gohr              GROUP BY $TIME
183b6632b6eSAndreas Gohr              ORDER BY time";
184*f9e60319SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->from, $this->to, 'browser']);
185b6632b6eSAndreas Gohr        foreach ($result as $row) {
186b6632b6eSAndreas Gohr            $data[$row['time']]['sessions'] = $row['sessions'];
187b6632b6eSAndreas Gohr            $data[$row['time']]['pageviews'] = $row['pageviews'];
188b6632b6eSAndreas Gohr            $data[$row['time']]['visitors'] = $row['visitors'];
189b6632b6eSAndreas Gohr        }
190b6632b6eSAndreas Gohr        return $data;
191b6632b6eSAndreas Gohr    }
192b6632b6eSAndreas Gohr
193*f9e60319SAndreas Gohr    /**
194*f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
195*f9e60319SAndreas Gohr     * @return array
196*f9e60319SAndreas Gohr     */
197*f9e60319SAndreas Gohr    public function dashboardwiki(bool $hours = false): array
198b6632b6eSAndreas Gohr    {
199b6632b6eSAndreas Gohr        if ($hours) {
2007428e816SAndreas Gohr            $TIME = 'strftime(\'%H\', dt)';
201b6632b6eSAndreas Gohr        } else {
202b6632b6eSAndreas Gohr            $TIME = 'DATE(dt)';
203b6632b6eSAndreas Gohr        }
204b6632b6eSAndreas Gohr
205b6632b6eSAndreas Gohr        $data = [];
206b6632b6eSAndreas Gohr
207b6632b6eSAndreas Gohr        // edit trends
208b6632b6eSAndreas Gohr        foreach (['E', 'C', 'D'] as $type) {
209b6632b6eSAndreas Gohr            $sql = "SELECT $TIME as time,
210b6632b6eSAndreas Gohr                           COUNT(*) as cnt
2117428e816SAndreas Gohr                      FROM edits as A
2127428e816SAndreas Gohr                     WHERE A.dt >= ? AND A.dt <= ?
2137428e816SAndreas Gohr                       AND type = ?
214b6632b6eSAndreas Gohr                  GROUP BY $TIME
215b6632b6eSAndreas Gohr                  ORDER BY time";
216*f9e60319SAndreas Gohr            $result = $this->db->queryAll($sql, [$this->from, $this->to, $type]);
217b6632b6eSAndreas Gohr            foreach ($result as $row) {
218b6632b6eSAndreas Gohr                $data[$row['time']][$type] = $row['cnt'];
219b6632b6eSAndreas Gohr            }
220b6632b6eSAndreas Gohr        }
221b6632b6eSAndreas Gohr        ksort($data);
222b6632b6eSAndreas Gohr        return $data;
223b6632b6eSAndreas Gohr    }
224b6632b6eSAndreas Gohr
225*f9e60319SAndreas Gohr    /**
226*f9e60319SAndreas Gohr     * @param string $info Which type of history to select (FIXME which ones are there?)
227*f9e60319SAndreas Gohr     * @param string $interval Group data by this interval (days, weeks, months)
228*f9e60319SAndreas Gohr     * @return array
229*f9e60319SAndreas Gohr     */
230*f9e60319SAndreas Gohr    public function history(string $info, string $interval = 'day'): array
231b6632b6eSAndreas Gohr    {
232b6632b6eSAndreas Gohr        if ($interval == 'weeks') {
2337428e816SAndreas Gohr            $TIME = 'strftime(\'%Y\', dt), strftime(\'%W\', dt)';
234b6632b6eSAndreas Gohr        } elseif ($interval == 'months') {
2357428e816SAndreas Gohr            $TIME = 'strftime(\'%Y-%m\', dt)';
236b6632b6eSAndreas Gohr        } else {
237b6632b6eSAndreas Gohr            $TIME = 'dt';
238b6632b6eSAndreas Gohr        }
239b6632b6eSAndreas Gohr
240b6632b6eSAndreas Gohr        $mod = 1;
241b6632b6eSAndreas Gohr        if ($info == 'media_size' || $info == 'page_size') {
242b6632b6eSAndreas Gohr            $mod = 1024 * 1024;
243b6632b6eSAndreas Gohr        }
244b6632b6eSAndreas Gohr
245b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
2467428e816SAndreas Gohr                       AVG(value)/$mod as cnt
2477428e816SAndreas Gohr                  FROM history as A
2487428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
2497428e816SAndreas Gohr                   AND info = ?
250b6632b6eSAndreas Gohr                  GROUP BY $TIME
251b6632b6eSAndreas Gohr                  ORDER BY $TIME";
252*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, $info]);
253b6632b6eSAndreas Gohr    }
254b6632b6eSAndreas Gohr
255*f9e60319SAndreas Gohr    /**
256*f9e60319SAndreas Gohr     * @return array
257*f9e60319SAndreas Gohr     */
258*f9e60319SAndreas Gohr    public function searchengines(): array
259b6632b6eSAndreas Gohr    {
260b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, engine as eflag, engine
2617428e816SAndreas Gohr                  FROM search as A
2627428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
263b6632b6eSAndreas Gohr              GROUP BY engine
264b6632b6eSAndreas Gohr              ORDER BY cnt DESC, engine" .
265*f9e60319SAndreas Gohr            $this->limit;
266*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to]);
267b6632b6eSAndreas Gohr    }
268b6632b6eSAndreas Gohr
269*f9e60319SAndreas Gohr    /**
270*f9e60319SAndreas Gohr     * @param bool $extern Limit results to external search engine (true) or dokuwiki (false)
271*f9e60319SAndreas Gohr     * @return array
272*f9e60319SAndreas Gohr     */
273*f9e60319SAndreas Gohr    public function searchphrases(bool $extern): array
274b6632b6eSAndreas Gohr    {
275b6632b6eSAndreas Gohr        if ($extern) {
2767428e816SAndreas Gohr            $WHERE = "engine != ?";
2777428e816SAndreas Gohr            $engineParam = 'dokuwiki';
278b6632b6eSAndreas Gohr            $I = '';
279b6632b6eSAndreas Gohr        } else {
2807428e816SAndreas Gohr            $WHERE = "engine = ?";
2817428e816SAndreas Gohr            $engineParam = 'dokuwiki';
282b6632b6eSAndreas Gohr            $I = 'i';
283b6632b6eSAndreas Gohr        }
284b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, query, query as ${I}lookup
2857428e816SAndreas Gohr                  FROM search as A
2867428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
287b6632b6eSAndreas Gohr                   AND $WHERE
288b6632b6eSAndreas Gohr              GROUP BY query
289b6632b6eSAndreas Gohr              ORDER BY cnt DESC, query" .
290*f9e60319SAndreas Gohr            $this->limit;
291*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, $engineParam]);
292b6632b6eSAndreas Gohr    }
293b6632b6eSAndreas Gohr
294*f9e60319SAndreas Gohr    /**
295*f9e60319SAndreas Gohr     * @param bool $extern Limit results to external search engine (true) or dokuwiki (false)
296*f9e60319SAndreas Gohr     * @return array
297*f9e60319SAndreas Gohr     */
298*f9e60319SAndreas Gohr    public function searchwords(bool $extern): array
299b6632b6eSAndreas Gohr    {
300b6632b6eSAndreas Gohr        if ($extern) {
3017428e816SAndreas Gohr            $WHERE = "engine != ?";
3027428e816SAndreas Gohr            $engineParam = 'dokuwiki';
303b6632b6eSAndreas Gohr            $I = '';
304b6632b6eSAndreas Gohr        } else {
3057428e816SAndreas Gohr            $WHERE = "engine = ?";
3067428e816SAndreas Gohr            $engineParam = 'dokuwiki';
307b6632b6eSAndreas Gohr            $I = 'i';
308b6632b6eSAndreas Gohr        }
309b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, word, word as ${I}lookup
3107428e816SAndreas Gohr                  FROM search as A,
3117428e816SAndreas Gohr                       searchwords as B
3127428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
313b6632b6eSAndreas Gohr                   AND A.id = B.sid
314b6632b6eSAndreas Gohr                   AND $WHERE
315b6632b6eSAndreas Gohr              GROUP BY word
316b6632b6eSAndreas Gohr              ORDER BY cnt DESC, word" .
317*f9e60319SAndreas Gohr            $this->limit;
318*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, $engineParam]);
319b6632b6eSAndreas Gohr    }
320b6632b6eSAndreas Gohr
321*f9e60319SAndreas Gohr    /**
322*f9e60319SAndreas Gohr     * @return array
323*f9e60319SAndreas Gohr     */
324*f9e60319SAndreas Gohr    public function outlinks(): array
325b6632b6eSAndreas Gohr    {
326b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, link as url
3277428e816SAndreas Gohr                  FROM outlinks as A
3287428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
329b6632b6eSAndreas Gohr              GROUP BY link
330b6632b6eSAndreas Gohr              ORDER BY cnt DESC, link" .
331*f9e60319SAndreas Gohr            $this->limit;
332*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to]);
333b6632b6eSAndreas Gohr    }
334b6632b6eSAndreas Gohr
335*f9e60319SAndreas Gohr    /**
336*f9e60319SAndreas Gohr     * @return array
337*f9e60319SAndreas Gohr     */
338*f9e60319SAndreas Gohr    public function pages(): array
339b6632b6eSAndreas Gohr    {
340b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
3417428e816SAndreas Gohr                  FROM access as A
3427428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
3437428e816SAndreas Gohr                   AND ua_type = ?
344b6632b6eSAndreas Gohr              GROUP BY page
345b6632b6eSAndreas Gohr              ORDER BY cnt DESC, page" .
346*f9e60319SAndreas Gohr            $this->limit;
347*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser']);
348b6632b6eSAndreas Gohr    }
349b6632b6eSAndreas Gohr
350*f9e60319SAndreas Gohr    /**
351*f9e60319SAndreas Gohr     * @return array
352*f9e60319SAndreas Gohr     */
353*f9e60319SAndreas Gohr    public function edits(): array
354b6632b6eSAndreas Gohr    {
355b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
3567428e816SAndreas Gohr                  FROM edits as A
3577428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
358b6632b6eSAndreas Gohr              GROUP BY page
359b6632b6eSAndreas Gohr              ORDER BY cnt DESC, page" .
360*f9e60319SAndreas Gohr            $this->limit;
361*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to]);
362b6632b6eSAndreas Gohr    }
363b6632b6eSAndreas Gohr
364*f9e60319SAndreas Gohr    /**
365*f9e60319SAndreas Gohr     * @return array
366*f9e60319SAndreas Gohr     */
367*f9e60319SAndreas Gohr    public function images(): array
368b6632b6eSAndreas Gohr    {
369b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
3707428e816SAndreas Gohr                  FROM media as A
3717428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
3727428e816SAndreas Gohr                   AND mime1 = ?
373b6632b6eSAndreas Gohr              GROUP BY media
374b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
375*f9e60319SAndreas Gohr            $this->limit;
376*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'image']);
377b6632b6eSAndreas Gohr    }
378b6632b6eSAndreas Gohr
379*f9e60319SAndreas Gohr    /**
380*f9e60319SAndreas Gohr     * @return array
381*f9e60319SAndreas Gohr     */
382*f9e60319SAndreas Gohr    public function imagessum(): array
383b6632b6eSAndreas Gohr    {
384b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
3857428e816SAndreas Gohr                  FROM media as A
3867428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
3877428e816SAndreas Gohr                   AND mime1 = ?";
388*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'image']);
389b6632b6eSAndreas Gohr    }
390b6632b6eSAndreas Gohr
391*f9e60319SAndreas Gohr    /**
392*f9e60319SAndreas Gohr     * @return array
393*f9e60319SAndreas Gohr     */
394*f9e60319SAndreas Gohr    public function downloads(): array
395b6632b6eSAndreas Gohr    {
396b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
3977428e816SAndreas Gohr                  FROM media as A
3987428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
3997428e816SAndreas Gohr                   AND mime1 != ?
400b6632b6eSAndreas Gohr              GROUP BY media
401b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
402*f9e60319SAndreas Gohr            $this->limit;
403*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'image']);
404b6632b6eSAndreas Gohr    }
405b6632b6eSAndreas Gohr
406*f9e60319SAndreas Gohr    /**
407*f9e60319SAndreas Gohr     * @return array
408*f9e60319SAndreas Gohr     */
409*f9e60319SAndreas Gohr    public function downloadssum(): array
410b6632b6eSAndreas Gohr    {
411b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
4127428e816SAndreas Gohr                  FROM media as A
4137428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
4147428e816SAndreas Gohr                   AND mime1 != ?";
415*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'image']);
416b6632b6eSAndreas Gohr    }
417b6632b6eSAndreas Gohr
418*f9e60319SAndreas Gohr    /**
419*f9e60319SAndreas Gohr     * @return array
420*f9e60319SAndreas Gohr     */
421*f9e60319SAndreas Gohr    public function referer(): array
422b6632b6eSAndreas Gohr    {
423b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
4247428e816SAndreas Gohr                  FROM access as A
4257428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
4267428e816SAndreas Gohr                   AND ua_type = ?
4277428e816SAndreas Gohr                   AND ref_type = ?
428b6632b6eSAndreas Gohr              GROUP BY ref_md5
429b6632b6eSAndreas Gohr              ORDER BY cnt DESC, url" .
430*f9e60319SAndreas Gohr            $this->limit;
431*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser', 'external']);
432b6632b6eSAndreas Gohr    }
433b6632b6eSAndreas Gohr
434*f9e60319SAndreas Gohr    /**
435*f9e60319SAndreas Gohr     * @return array
436*f9e60319SAndreas Gohr     */
437*f9e60319SAndreas Gohr    public function newreferer(): array
438b6632b6eSAndreas Gohr    {
439b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
4407428e816SAndreas Gohr                  FROM access as B,
4417428e816SAndreas Gohr                       refseen as A
4427428e816SAndreas Gohr                 WHERE B.dt >= ? AND B.dt <= ?
4437428e816SAndreas Gohr                   AND ua_type = ?
4447428e816SAndreas Gohr                   AND ref_type = ?
445b6632b6eSAndreas Gohr                   AND A.ref_md5 = B.ref_md5
446b6632b6eSAndreas Gohr              GROUP BY A.ref_md5
447b6632b6eSAndreas Gohr              ORDER BY cnt DESC, url" .
448*f9e60319SAndreas Gohr            $this->limit;
449*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser', 'external']);
450b6632b6eSAndreas Gohr    }
451b6632b6eSAndreas Gohr
452*f9e60319SAndreas Gohr    /**
453*f9e60319SAndreas Gohr     * @return array
454*f9e60319SAndreas Gohr     */
455*f9e60319SAndreas Gohr    public function countries(): array
456b6632b6eSAndreas Gohr    {
457b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country
4587428e816SAndreas Gohr                  FROM access as A,
4597428e816SAndreas Gohr                       iplocation as B
4607428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
461b6632b6eSAndreas Gohr                   AND A.ip = B.ip
462b6632b6eSAndreas Gohr              GROUP BY B.code
463b6632b6eSAndreas Gohr              ORDER BY cnt DESC, B.country" .
464*f9e60319SAndreas Gohr            $this->limit;
465*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to]);
466b6632b6eSAndreas Gohr    }
467b6632b6eSAndreas Gohr
468*f9e60319SAndreas Gohr    /**
469*f9e60319SAndreas Gohr     * @param bool $ext return extended information
470*f9e60319SAndreas Gohr     * @return array
471*f9e60319SAndreas Gohr     */
472*f9e60319SAndreas Gohr    public function browsers(bool $ext = true): array
473b6632b6eSAndreas Gohr    {
474b6632b6eSAndreas Gohr        if ($ext) {
475b6632b6eSAndreas Gohr            $sel = 'ua_info as bflag, ua_info as browser, ua_ver';
476b6632b6eSAndreas Gohr            $grp = 'ua_info, ua_ver';
477b6632b6eSAndreas Gohr        } else {
478b6632b6eSAndreas Gohr            $grp = 'ua_info';
479b6632b6eSAndreas Gohr            $sel = 'ua_info';
480b6632b6eSAndreas Gohr        }
481b6632b6eSAndreas Gohr
482b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel
4837428e816SAndreas Gohr                  FROM access as A
4847428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
4857428e816SAndreas Gohr                   AND ua_type = ?
486b6632b6eSAndreas Gohr              GROUP BY $grp
487b6632b6eSAndreas Gohr              ORDER BY cnt DESC, ua_info" .
488*f9e60319SAndreas Gohr            $this->limit;
489*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser']);
490b6632b6eSAndreas Gohr    }
491b6632b6eSAndreas Gohr
492*f9e60319SAndreas Gohr    /**
493*f9e60319SAndreas Gohr     * @return array
494*f9e60319SAndreas Gohr     */
495*f9e60319SAndreas Gohr    public function os(): array
496b6632b6eSAndreas Gohr    {
497b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os
4987428e816SAndreas Gohr                  FROM access as A
4997428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5007428e816SAndreas Gohr                   AND ua_type = ?
501b6632b6eSAndreas Gohr              GROUP BY os
502b6632b6eSAndreas Gohr              ORDER BY cnt DESC, os" .
503*f9e60319SAndreas Gohr            $this->limit;
504*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser']);
505b6632b6eSAndreas Gohr    }
506b6632b6eSAndreas Gohr
507*f9e60319SAndreas Gohr    /**
508*f9e60319SAndreas Gohr     * @return array
509*f9e60319SAndreas Gohr     */
510*f9e60319SAndreas Gohr    public function topuser(): array
511b6632b6eSAndreas Gohr    {
512b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, user
5137428e816SAndreas Gohr                  FROM access as A
5147428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5157428e816SAndreas Gohr                   AND ua_type = ?
5167428e816SAndreas Gohr                   AND user != ?
517b6632b6eSAndreas Gohr              GROUP BY user
518b6632b6eSAndreas Gohr              ORDER BY cnt DESC, user" .
519*f9e60319SAndreas Gohr            $this->limit;
520*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser', '']);
521b6632b6eSAndreas Gohr    }
522b6632b6eSAndreas Gohr
523*f9e60319SAndreas Gohr    /**
524*f9e60319SAndreas Gohr     * @return array
525*f9e60319SAndreas Gohr     */
526*f9e60319SAndreas Gohr    public function topeditor(): array
527b6632b6eSAndreas Gohr    {
528b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, user
5297428e816SAndreas Gohr                  FROM edits as A
5307428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5317428e816SAndreas Gohr                   AND user != ?
532b6632b6eSAndreas Gohr              GROUP BY user
533b6632b6eSAndreas Gohr              ORDER BY cnt DESC, user" .
534*f9e60319SAndreas Gohr            $this->limit;
535*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, '']);
536b6632b6eSAndreas Gohr    }
537b6632b6eSAndreas Gohr
538*f9e60319SAndreas Gohr    /**
539*f9e60319SAndreas Gohr     * @return array
540*f9e60319SAndreas Gohr     */
541*f9e60319SAndreas Gohr    public function topgroup(): array
542b6632b6eSAndreas Gohr    {
543b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, `group`
5447428e816SAndreas Gohr                  FROM groups as A
5457428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5467428e816SAndreas Gohr                   AND `type` = ?
547b6632b6eSAndreas Gohr              GROUP BY `group`
548b6632b6eSAndreas Gohr              ORDER BY cnt DESC, `group`" .
549*f9e60319SAndreas Gohr            $this->limit;
550*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'view']);
551b6632b6eSAndreas Gohr    }
552b6632b6eSAndreas Gohr
553*f9e60319SAndreas Gohr    /**
554*f9e60319SAndreas Gohr     * @return array
555*f9e60319SAndreas Gohr     */
556*f9e60319SAndreas Gohr    public function topgroupedit(): array
557b6632b6eSAndreas Gohr    {
558b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, `group`
5597428e816SAndreas Gohr                  FROM groups as A
5607428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5617428e816SAndreas Gohr                   AND `type` = ?
562b6632b6eSAndreas Gohr              GROUP BY `group`
563b6632b6eSAndreas Gohr              ORDER BY cnt DESC, `group`" .
564*f9e60319SAndreas Gohr            $this->limit;
565*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'edit']);
566b6632b6eSAndreas Gohr    }
567b6632b6eSAndreas Gohr
568b6632b6eSAndreas Gohr
569*f9e60319SAndreas Gohr    /**
570*f9e60319SAndreas Gohr     * @return array
571*f9e60319SAndreas Gohr     */
572*f9e60319SAndreas Gohr    public function resolution(): array
573b6632b6eSAndreas Gohr    {
574b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT uid) as cnt,
575b6632b6eSAndreas Gohr                       ROUND(screen_x/100)*100 as res_x,
576b6632b6eSAndreas Gohr                       ROUND(screen_y/100)*100 as res_y,
5777428e816SAndreas Gohr                       (ROUND(screen_x/100)*100 || 'x' || ROUND(screen_y/100)*100) as resolution
5787428e816SAndreas Gohr                  FROM access as A
5797428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
5807428e816SAndreas Gohr                   AND ua_type  = ?
5817428e816SAndreas Gohr                   AND screen_x != ?
5827428e816SAndreas Gohr                   AND screen_y != ?
583b6632b6eSAndreas Gohr              GROUP BY resolution
584b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
585*f9e60319SAndreas Gohr            $this->limit;
586*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser', 0, 0]);
587b6632b6eSAndreas Gohr    }
588b6632b6eSAndreas Gohr
589*f9e60319SAndreas Gohr    /**
590*f9e60319SAndreas Gohr     * @return array
591*f9e60319SAndreas Gohr     */
592*f9e60319SAndreas Gohr    public function viewport(): array
593b6632b6eSAndreas Gohr    {
594b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT uid) as cnt,
595b6632b6eSAndreas Gohr                       ROUND(view_x/100)*100 as res_x,
596b6632b6eSAndreas Gohr                       ROUND(view_y/100)*100 as res_y,
5977428e816SAndreas Gohr                       (ROUND(view_x/100)*100 || 'x' || ROUND(view_y/100)*100) as resolution
5987428e816SAndreas Gohr                  FROM access as A
5997428e816SAndreas Gohr                 WHERE A.dt >= ? AND A.dt <= ?
6007428e816SAndreas Gohr                   AND ua_type  = ?
6017428e816SAndreas Gohr                   AND view_x != ?
6027428e816SAndreas Gohr                   AND view_y != ?
603b6632b6eSAndreas Gohr              GROUP BY resolution
604b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
605*f9e60319SAndreas Gohr            $this->limit;
606b6632b6eSAndreas Gohr
607*f9e60319SAndreas Gohr        return $this->db->queryAll($sql, [$this->from, $this->to, 'browser', 0, 0]);
608b6632b6eSAndreas Gohr    }
609b6632b6eSAndreas Gohr
610*f9e60319SAndreas Gohr    /**
611*f9e60319SAndreas Gohr     * @return array
612*f9e60319SAndreas Gohr     */
613*f9e60319SAndreas Gohr    public function seenusers(): array
614b6632b6eSAndreas Gohr    {
615b6632b6eSAndreas Gohr        $sql = "SELECT `user`, `dt`
616b6632b6eSAndreas Gohr                  FROM " . $this->hlp->prefix . "lastseen as A
617b6632b6eSAndreas Gohr              ORDER BY `dt` DESC" .
618*f9e60319SAndreas Gohr            $this->limit;
619b6632b6eSAndreas Gohr
620*f9e60319SAndreas Gohr        return $this->db->queryAll($sql);
621b6632b6eSAndreas Gohr    }
622b6632b6eSAndreas Gohr
623b6632b6eSAndreas Gohr}
624