xref: /plugin/statistics/Query.php (revision f666296fd6eba2c9ce30baa6c98d904f07a52045)
1b6632b6eSAndreas Gohr<?php
2b6632b6eSAndreas Gohr
3b6632b6eSAndreas Gohrnamespace dokuwiki\plugin\statistics;
4b6632b6eSAndreas Gohr
5f9e60319SAndreas Gohruse dokuwiki\plugin\sqlite\SQLiteDB;
6b6632b6eSAndreas Gohruse helper_plugin_statistics;
7b6632b6eSAndreas Gohr
8f9e60319SAndreas Gohr/**
9f9e60319SAndreas Gohr * This class defines a bunch of SQL queries to fetch various statistics from the database
10f9e60319SAndreas Gohr */
11b6632b6eSAndreas Gohrclass Query
12b6632b6eSAndreas Gohr{
13f9e60319SAndreas Gohr    protected helper_plugin_statistics $hlp;
14f9e60319SAndreas Gohr    protected SQLiteDB $db;
15f9e60319SAndreas Gohr    protected string $from;
16f9e60319SAndreas Gohr    protected string $to;
17f9e60319SAndreas Gohr    protected string $limit = '';
1844f81330SAndreas Gohr    protected string $tz = 'localtime';
19b6632b6eSAndreas Gohr
20f9e60319SAndreas Gohr    /**
21f9e60319SAndreas Gohr     * @param helper_plugin_statistics $hlp
22f9e60319SAndreas Gohr     */
23b6632b6eSAndreas Gohr    public function __construct(helper_plugin_statistics $hlp)
24b6632b6eSAndreas Gohr    {
25b6632b6eSAndreas Gohr        $this->hlp = $hlp;
26f9e60319SAndreas Gohr        $this->db = $hlp->getDB();
277428e816SAndreas Gohr        $today = date('Y-m-d');
287428e816SAndreas Gohr        $this->setTimeFrame($today, $today);
29f9e60319SAndreas Gohr        $this->setPagination(0, 20);
307428e816SAndreas Gohr    }
317428e816SAndreas Gohr
327428e816SAndreas Gohr    /**
337428e816SAndreas Gohr     * Set the time frame for all queries
34f9e60319SAndreas Gohr     *
35f9e60319SAndreas Gohr     * @param string $from The start date as YYYY-MM-DD
36f9e60319SAndreas Gohr     * @param string $to The end date as YYYY-MM-DD
377428e816SAndreas Gohr     */
38f9e60319SAndreas Gohr    public function setTimeFrame(string $from, string $to): void
397428e816SAndreas Gohr    {
40f9e60319SAndreas Gohr        try {
41f9e60319SAndreas Gohr            $from = new \DateTime($from);
42f9e60319SAndreas Gohr            $to = new \DateTime($to);
43f9e60319SAndreas Gohr        } catch (\Exception $e) {
44f9e60319SAndreas Gohr            $from = new \DateTime();
45f9e60319SAndreas Gohr            $to = new \DateTime();
46f9e60319SAndreas Gohr        }
47f9e60319SAndreas Gohr        $from->setTime(0, 0);
48f9e60319SAndreas Gohr        $to->setTime(23, 59, 59);
497428e816SAndreas Gohr
50f9e60319SAndreas Gohr        $this->from = $from->format('Y-m-d H:i:s');
51f9e60319SAndreas Gohr        $this->to = $to->format('Y-m-d H:i:s');
5257819987SAnna Dabrowska
5357819987SAnna Dabrowska        $this->setTimezone();
5457819987SAnna Dabrowska    }
5557819987SAnna Dabrowska
5657819987SAnna Dabrowska    /**
5757819987SAnna Dabrowska     * Force configured timezone.
5857819987SAnna Dabrowska     * This is useful if you cannot set localtime on the server.
5957819987SAnna Dabrowska     *
6057819987SAnna Dabrowska     * @return void
6157819987SAnna Dabrowska     */
6257819987SAnna Dabrowska    public function setTimezone()
6357819987SAnna Dabrowska    {
6457819987SAnna Dabrowska        $timezoneId = $this->hlp->getConf('timezone');
6557819987SAnna Dabrowska        if (!$timezoneId || !in_array($timezoneId, \DateTimeZone::listIdentifiers())) return;
6657819987SAnna Dabrowska
6757819987SAnna Dabrowska        try {
6857819987SAnna Dabrowska            $dateTime = new \DateTime($this->from, new \DateTimeZone($timezoneId));
6957819987SAnna Dabrowska            $this->tz = $dateTime->format('P');
7057819987SAnna Dabrowska        } catch (\Exception $e) {
7157819987SAnna Dabrowska            \dokuwiki\Logger::error($e->getMessage());
7257819987SAnna Dabrowska        }
73f9e60319SAndreas Gohr    }
74f9e60319SAndreas Gohr
75f9e60319SAndreas Gohr    /**
76f9e60319SAndreas Gohr     * Set the pagination settings for some queries
77f9e60319SAndreas Gohr     *
78f9e60319SAndreas Gohr     * @param int $start The start offset
79f9e60319SAndreas Gohr     * @param int $limit The number of results. If one more is returned, there is another page
80f9e60319SAndreas Gohr     * @return void
81f9e60319SAndreas Gohr     */
82f9e60319SAndreas Gohr    public function setPagination(int $start, int $limit)
83f9e60319SAndreas Gohr    {
84f9e60319SAndreas Gohr        // when a limit is set, one more is fetched to indicate when a next page exists
85f9e60319SAndreas Gohr        if ($limit) $limit += 1;
86f9e60319SAndreas Gohr
87f9e60319SAndreas Gohr        if ($limit) {
88f9e60319SAndreas Gohr            $this->limit = " LIMIT $start,$limit";
89f9e60319SAndreas Gohr        } elseif ($start) {
90f9e60319SAndreas Gohr            $this->limit = " OFFSET $start";
91f9e60319SAndreas Gohr        }
92b6632b6eSAndreas Gohr    }
93b6632b6eSAndreas Gohr
94b6632b6eSAndreas Gohr    /**
95b6632b6eSAndreas Gohr     * Return some aggregated statistics
96b6632b6eSAndreas Gohr     */
97f9e60319SAndreas Gohr    public function aggregate(): array
98b6632b6eSAndreas Gohr    {
992a30f557SAndreas Gohr        // init some values that might not be set
1002a30f557SAndreas Gohr        $data = [
1012a30f557SAndreas Gohr            'referers' => 0, // total number of (external) referrers
1022a30f557SAndreas Gohr            'external' => 0, // external referrers
1032a30f557SAndreas Gohr            'search' => 0, // search engine referrers
1042a30f557SAndreas Gohr            'direct' => 0, // direct referrers
1052a30f557SAndreas Gohr            'internal' => 0, // internal referrers
1062a30f557SAndreas Gohr            'bouncerate' => 0,
1072a30f557SAndreas Gohr            'newvisitors' => 0,
1082a30f557SAndreas Gohr        ];
109b6632b6eSAndreas Gohr
11010dcb86fSAndreas Gohr        // Count referrer types by joining with referers table
11110dcb86fSAndreas Gohr        $sql = "SELECT
11210dcb86fSAndreas Gohr                    CASE
11310dcb86fSAndreas Gohr                        WHEN R.engine IS NOT NULL THEN 'search'
1142a30f557SAndreas Gohr                        WHEN R.url = '' THEN 'direct'
1152a30f557SAndreas Gohr                        WHEN R.url IS NOT NULL THEN 'external'
1162a30f557SAndreas Gohr                        ELSE 'internal'
11710dcb86fSAndreas Gohr                    END as ref_type,
11810dcb86fSAndreas Gohr                    COUNT(*) as cnt
11910dcb86fSAndreas Gohr                  FROM pageviews as P
12010dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
12110dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
12244f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
12330cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
124b6632b6eSAndreas Gohr              GROUP BY ref_type";
12544f81330SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
126b6632b6eSAndreas Gohr
127f9e60319SAndreas Gohr        foreach ($result as $row) {
1282a30f557SAndreas Gohr            if ($row['ref_type'] == 'search') {
1292a30f557SAndreas Gohr                $data['search'] = $row['cnt'];
1302a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1312a30f557SAndreas Gohr            }
1322a30f557SAndreas Gohr            if ($row['ref_type'] == 'direct') {
1332a30f557SAndreas Gohr                $data['direct'] = $row['cnt'];
1342a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1352a30f557SAndreas Gohr            }
1362a30f557SAndreas Gohr            if ($row['ref_type'] == 'external') {
1372a30f557SAndreas Gohr                $data['external'] = $row['cnt'];
1382a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1392a30f557SAndreas Gohr            }
1402a30f557SAndreas Gohr            if ($row['ref_type'] == 'internal') {
1412a30f557SAndreas Gohr                $data['internal'] = $row['cnt'];
1422a30f557SAndreas Gohr            }
143b6632b6eSAndreas Gohr        }
144b6632b6eSAndreas Gohr
145b6632b6eSAndreas Gohr        // general user and session info
14610dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT P.session) as sessions,
14710dcb86fSAndreas Gohr                       COUNT(P.session) as views,
14810dcb86fSAndreas Gohr                       COUNT(DISTINCT S.user) as users,
14944f81330SAndreas Gohr                       COUNT(DISTINCT S.uid) as visitors,
15044f81330SAndreas Gohr                       DATETIME(MAX(P.dt), ?) as last
15110dcb86fSAndreas Gohr                  FROM pageviews as P
15210dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
15344f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
15430cf9434SAndreas Gohr                   AND S.ua_type = 'browser'";
15544f81330SAndreas Gohr        $result = $this->db->queryRecord($sql, [$this->tz, $this->tz, $this->from, $this->tz, $this->to]);
156b6632b6eSAndreas Gohr
15710dcb86fSAndreas Gohr        $data['users'] = $result['users'];
158f9e60319SAndreas Gohr        $data['sessions'] = $result['sessions'];
159f9e60319SAndreas Gohr        $data['pageviews'] = $result['views'];
160f9e60319SAndreas Gohr        $data['visitors'] = $result['visitors'];
16144f81330SAndreas Gohr        $data['last'] = $result['last'];
162b6632b6eSAndreas Gohr
16310dcb86fSAndreas Gohr        // calculate bounce rate (sessions with only 1 page view)
164b6632b6eSAndreas Gohr        if ($data['sessions']) {
165b6632b6eSAndreas Gohr            $sql = "SELECT COUNT(*) as cnt
16610dcb86fSAndreas Gohr                      FROM (
16710dcb86fSAndreas Gohr                          SELECT P.session, COUNT(*) as views
16810dcb86fSAndreas Gohr                            FROM pageviews as P
16910dcb86fSAndreas Gohr                            LEFT JOIN sessions as S ON P.session = S.session
17044f81330SAndreas Gohr                           WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
17130cf9434SAndreas Gohr                             AND S.ua_type = 'browser'
17210dcb86fSAndreas Gohr                        GROUP BY P.session
17310dcb86fSAndreas Gohr                          HAVING views = 1
17410dcb86fSAndreas Gohr                      )";
17544f81330SAndreas Gohr            $count = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
176f9e60319SAndreas Gohr            $data['bouncerate'] = $count * 100 / $data['sessions'];
177f9e60319SAndreas Gohr            $data['newvisitors'] = $count * 100 / $data['sessions'];
178b6632b6eSAndreas Gohr        }
179b6632b6eSAndreas Gohr
180b6632b6eSAndreas Gohr        // calculate avg. number of views per session
181b6632b6eSAndreas Gohr        $sql = "SELECT AVG(views) as cnt
18210dcb86fSAndreas Gohr                  FROM (
18310dcb86fSAndreas Gohr                      SELECT P.session, COUNT(*) as views
18410dcb86fSAndreas Gohr                        FROM pageviews as P
18510dcb86fSAndreas Gohr                        LEFT JOIN sessions as S ON P.session = S.session
18644f81330SAndreas Gohr                       WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
18730cf9434SAndreas Gohr                         AND S.ua_type = 'browser'
18810dcb86fSAndreas Gohr                    GROUP BY P.session
18910dcb86fSAndreas Gohr                  )";
19044f81330SAndreas Gohr        $data['avgpages'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
191b6632b6eSAndreas Gohr
192b6632b6eSAndreas Gohr        // average time spent on the site
193115ede90SAndreas Gohr        $sql = "SELECT AVG((unixepoch(end) - unixepoch(dt)) / 60) as time
19410dcb86fSAndreas Gohr                  FROM sessions as S
195115ede90SAndreas Gohr                 WHERE S.dt != S.end
19644f81330SAndreas Gohr                   AND DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
19730cf9434SAndreas Gohr                   AND S.ua_type = 'browser'";
19844f81330SAndreas Gohr        $data['timespent'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
199b6632b6eSAndreas Gohr
200b6632b6eSAndreas Gohr        // logins
201b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as logins
2027428e816SAndreas Gohr                  FROM logins as A
20344f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
20430cf9434SAndreas Gohr                   AND (type = 'l' OR type = 'p')";
20544f81330SAndreas Gohr        $data['logins'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
206b6632b6eSAndreas Gohr
207b6632b6eSAndreas Gohr        // registrations
208b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as registrations
2097428e816SAndreas Gohr                  FROM logins as A
21044f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
21130cf9434SAndreas Gohr                   AND type = 'C'";
21244f81330SAndreas Gohr        $data['registrations'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
213b6632b6eSAndreas Gohr
21410dcb86fSAndreas Gohr        // current users (based on recent sessions)
21510dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT uid) as current
21610dcb86fSAndreas Gohr                  FROM sessions
21710dcb86fSAndreas Gohr                 WHERE end >= datetime('now', '-10 minutes')";
218f9e60319SAndreas Gohr        $data['current'] = $this->db->queryValue($sql);
219b6632b6eSAndreas Gohr
220b6632b6eSAndreas Gohr        return $data;
221b6632b6eSAndreas Gohr    }
222b6632b6eSAndreas Gohr
223b6632b6eSAndreas Gohr
224b6632b6eSAndreas Gohr    /**
225b6632b6eSAndreas Gohr     * Return some trend data about visits and edits in the wiki
226f9e60319SAndreas Gohr     *
227f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
228f9e60319SAndreas Gohr     * @return array
229b6632b6eSAndreas Gohr     */
230f9e60319SAndreas Gohr    public function dashboardviews(bool $hours = false): array
231b6632b6eSAndreas Gohr    {
232b6632b6eSAndreas Gohr        if ($hours) {
23344f81330SAndreas Gohr            $TIME = "strftime('%H', DATETIME(P.dt, '$this->tz'))";
234b6632b6eSAndreas Gohr        } else {
23544f81330SAndreas Gohr            $TIME = "DATE(DATETIME(P.dt, '$this->tz'))";
236b6632b6eSAndreas Gohr        }
237b6632b6eSAndreas Gohr
238b6632b6eSAndreas Gohr        $data = [];
239b6632b6eSAndreas Gohr
240b6632b6eSAndreas Gohr        // access trends
241b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
24210dcb86fSAndreas Gohr                       COUNT(DISTINCT P.session) as sessions,
24310dcb86fSAndreas Gohr                       COUNT(P.session) as pageviews,
24410dcb86fSAndreas Gohr                       COUNT(DISTINCT S.uid) as visitors
24510dcb86fSAndreas Gohr                  FROM pageviews as P
24610dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
24744f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
24830cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
249b6632b6eSAndreas Gohr              GROUP BY $TIME
250b6632b6eSAndreas Gohr              ORDER BY time";
25144f81330SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
252b6632b6eSAndreas Gohr        foreach ($result as $row) {
253b6632b6eSAndreas Gohr            $data[$row['time']]['sessions'] = $row['sessions'];
254b6632b6eSAndreas Gohr            $data[$row['time']]['pageviews'] = $row['pageviews'];
255b6632b6eSAndreas Gohr            $data[$row['time']]['visitors'] = $row['visitors'];
256b6632b6eSAndreas Gohr        }
257b6632b6eSAndreas Gohr        return $data;
258b6632b6eSAndreas Gohr    }
259b6632b6eSAndreas Gohr
260f9e60319SAndreas Gohr    /**
261f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
262f9e60319SAndreas Gohr     * @return array
263f9e60319SAndreas Gohr     */
264f9e60319SAndreas Gohr    public function dashboardwiki(bool $hours = false): array
265b6632b6eSAndreas Gohr    {
266b6632b6eSAndreas Gohr        if ($hours) {
26744f81330SAndreas Gohr            $TIME = "strftime('%H', DATETIME(dt, '$this->tz'))";
268b6632b6eSAndreas Gohr        } else {
26944f81330SAndreas Gohr            $TIME = "DATE(DATETIME(dt, '$this->tz'))";
270b6632b6eSAndreas Gohr        }
271b6632b6eSAndreas Gohr
272b6632b6eSAndreas Gohr        $data = [];
273b6632b6eSAndreas Gohr
274b6632b6eSAndreas Gohr        // edit trends
275b6632b6eSAndreas Gohr        foreach (['E', 'C', 'D'] as $type) {
276b6632b6eSAndreas Gohr            $sql = "SELECT $TIME as time,
277b6632b6eSAndreas Gohr                           COUNT(*) as cnt
2787428e816SAndreas Gohr                      FROM edits as A
27944f81330SAndreas Gohr                     WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
28030cf9434SAndreas Gohr                       AND type = '$type'
281b6632b6eSAndreas Gohr                  GROUP BY $TIME
282b6632b6eSAndreas Gohr                  ORDER BY time";
28344f81330SAndreas Gohr            $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
284b6632b6eSAndreas Gohr            foreach ($result as $row) {
285b6632b6eSAndreas Gohr                $data[$row['time']][$type] = $row['cnt'];
286b6632b6eSAndreas Gohr            }
287b6632b6eSAndreas Gohr        }
288b6632b6eSAndreas Gohr        ksort($data);
289b6632b6eSAndreas Gohr        return $data;
290b6632b6eSAndreas Gohr    }
291b6632b6eSAndreas Gohr
292f9e60319SAndreas Gohr    /**
293f9e60319SAndreas Gohr     * @param string $info Which type of history to select (FIXME which ones are there?)
294f9e60319SAndreas Gohr     * @param string $interval Group data by this interval (days, weeks, months)
295f9e60319SAndreas Gohr     * @return array
296f9e60319SAndreas Gohr     */
297f9e60319SAndreas Gohr    public function history(string $info, string $interval = 'day'): array
298b6632b6eSAndreas Gohr    {
299b6632b6eSAndreas Gohr        if ($interval == 'weeks') {
30044f81330SAndreas Gohr            $TIME = "strftime('%Y', DATETIME(dt, '$this->tz')), strftime('%W', DATETIME(dt, '$this->tz'))";
301b6632b6eSAndreas Gohr        } elseif ($interval == 'months') {
30244f81330SAndreas Gohr            $TIME = "strftime('%Y-%m', DATETIME(dt, '$this->tz'))";
303b6632b6eSAndreas Gohr        } else {
30444f81330SAndreas Gohr            $TIME = "strftime('%d-%m', DATETIME(dt, '$this->tz'))";
305b6632b6eSAndreas Gohr        }
306b6632b6eSAndreas Gohr
307b6632b6eSAndreas Gohr        $mod = 1;
308b6632b6eSAndreas Gohr        if ($info == 'media_size' || $info == 'page_size') {
309b6632b6eSAndreas Gohr            $mod = 1024 * 1024;
310b6632b6eSAndreas Gohr        }
311b6632b6eSAndreas Gohr
312b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
3137428e816SAndreas Gohr                       AVG(value)/$mod as cnt
3147428e816SAndreas Gohr                  FROM history as A
31544f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
3167428e816SAndreas Gohr                   AND info = ?
317b6632b6eSAndreas Gohr                  GROUP BY $TIME
318b6632b6eSAndreas Gohr                  ORDER BY $TIME";
31944f81330SAndreas Gohr
32044f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to, $info]);
321b6632b6eSAndreas Gohr    }
322b6632b6eSAndreas Gohr
323f9e60319SAndreas Gohr    /**
324f9e60319SAndreas Gohr     * @return array
325f9e60319SAndreas Gohr     */
326f9e60319SAndreas Gohr    public function searchengines(): array
327b6632b6eSAndreas Gohr    {
32810dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.engine
3296f2bdce1SAndreas Gohr                  FROM pageviews as P,
3306f2bdce1SAndreas Gohr                       referers as R
33144f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
3326f2bdce1SAndreas Gohr                   AND P.ref_id = R.id
33310dcb86fSAndreas Gohr                   AND R.engine != ''
33410dcb86fSAndreas Gohr              GROUP BY R.engine
33510dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.engine" .
336f9e60319SAndreas Gohr            $this->limit;
33744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
338b6632b6eSAndreas Gohr    }
339b6632b6eSAndreas Gohr
340f9e60319SAndreas Gohr    /**
341f9e60319SAndreas Gohr     * @return array
342f9e60319SAndreas Gohr     */
343444fcd22SAndreas Gohr    public function internalsearchphrases(): array
344b6632b6eSAndreas Gohr    {
3452a30f557SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, query, query as ilookup
3462a30f557SAndreas Gohr                  FROM search
34744f81330SAndreas Gohr                 WHERE DATETIME(dt, ?) >= ? AND DATETIME(dt, ?) <= ?
3482a30f557SAndreas Gohr              GROUP BY query
3492a30f557SAndreas Gohr              ORDER BY cnt DESC, query" .
350f9e60319SAndreas Gohr            $this->limit;
35144f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
352b6632b6eSAndreas Gohr    }
353b6632b6eSAndreas Gohr
354f9e60319SAndreas Gohr    /**
355f9e60319SAndreas Gohr     * @return array
356f9e60319SAndreas Gohr     */
357444fcd22SAndreas Gohr    public function internalsearchwords(): array
358b6632b6eSAndreas Gohr    {
3592a30f557SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SW.word, SW.word as ilookup
3602a30f557SAndreas Gohr                  FROM search as S,
3612a30f557SAndreas Gohr                       searchwords as SW
36244f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
3632a30f557SAndreas Gohr                   AND S.id = SW.sid
36410dcb86fSAndreas Gohr              GROUP BY SW.word
36510dcb86fSAndreas Gohr              ORDER BY cnt DESC, SW.word" .
366f9e60319SAndreas Gohr            $this->limit;
36744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
368b6632b6eSAndreas Gohr    }
369b6632b6eSAndreas Gohr
370f9e60319SAndreas Gohr    /**
371f9e60319SAndreas Gohr     * @return array
372f9e60319SAndreas Gohr     */
373f9e60319SAndreas Gohr    public function outlinks(): array
374b6632b6eSAndreas Gohr    {
375b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, link as url
3767428e816SAndreas Gohr                  FROM outlinks as A
37744f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
378b6632b6eSAndreas Gohr              GROUP BY link
379b6632b6eSAndreas Gohr              ORDER BY cnt DESC, link" .
380f9e60319SAndreas Gohr            $this->limit;
38144f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
382b6632b6eSAndreas Gohr    }
383b6632b6eSAndreas Gohr
384f9e60319SAndreas Gohr    /**
385f9e60319SAndreas Gohr     * @return array
386f9e60319SAndreas Gohr     */
387f9e60319SAndreas Gohr    public function pages(): array
388b6632b6eSAndreas Gohr    {
38910dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, P.page
3906f2bdce1SAndreas Gohr                  FROM pageviews as P,
3916f2bdce1SAndreas Gohr                       sessions as S
39244f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
3936f2bdce1SAndreas Gohr                   AND P.session = S.session
39430cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
39510dcb86fSAndreas Gohr              GROUP BY P.page
39610dcb86fSAndreas Gohr              ORDER BY cnt DESC, P.page" .
397f9e60319SAndreas Gohr            $this->limit;
39844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
399b6632b6eSAndreas Gohr    }
400b6632b6eSAndreas Gohr
401f9e60319SAndreas Gohr    /**
402f9e60319SAndreas Gohr     * @return array
403f9e60319SAndreas Gohr     */
404f9e60319SAndreas Gohr    public function edits(): array
405b6632b6eSAndreas Gohr    {
406b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
4077428e816SAndreas Gohr                  FROM edits as A
40844f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
409b6632b6eSAndreas Gohr              GROUP BY page
410b6632b6eSAndreas Gohr              ORDER BY cnt DESC, page" .
411f9e60319SAndreas Gohr            $this->limit;
41244f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
413b6632b6eSAndreas Gohr    }
414b6632b6eSAndreas Gohr
415f9e60319SAndreas Gohr    /**
416f9e60319SAndreas Gohr     * @return array
417f9e60319SAndreas Gohr     */
418f9e60319SAndreas Gohr    public function images(): array
419b6632b6eSAndreas Gohr    {
420b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
4217428e816SAndreas Gohr                  FROM media as A
42244f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
42330cf9434SAndreas Gohr                   AND mime1 = 'image'
424b6632b6eSAndreas Gohr              GROUP BY media
425b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
426f9e60319SAndreas Gohr            $this->limit;
42744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
428b6632b6eSAndreas Gohr    }
429b6632b6eSAndreas Gohr
430f9e60319SAndreas Gohr    /**
431f9e60319SAndreas Gohr     * @return array
432f9e60319SAndreas Gohr     */
433f9e60319SAndreas Gohr    public function imagessum(): array
434b6632b6eSAndreas Gohr    {
435b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
4367428e816SAndreas Gohr                  FROM media as A
43744f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
43830cf9434SAndreas Gohr                   AND mime1 = 'image'";
43944f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
440b6632b6eSAndreas Gohr    }
441b6632b6eSAndreas Gohr
442f9e60319SAndreas Gohr    /**
443f9e60319SAndreas Gohr     * @return array
444f9e60319SAndreas Gohr     */
445f9e60319SAndreas Gohr    public function downloads(): array
446b6632b6eSAndreas Gohr    {
447b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
4487428e816SAndreas Gohr                  FROM media as A
44944f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
45030cf9434SAndreas Gohr                   AND mime1 != 'image'
451b6632b6eSAndreas Gohr              GROUP BY media
452b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
453f9e60319SAndreas Gohr            $this->limit;
45444f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
455b6632b6eSAndreas Gohr    }
456b6632b6eSAndreas Gohr
457f9e60319SAndreas Gohr    /**
458f9e60319SAndreas Gohr     * @return array
459f9e60319SAndreas Gohr     */
460f9e60319SAndreas Gohr    public function downloadssum(): array
461b6632b6eSAndreas Gohr    {
462b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
4637428e816SAndreas Gohr                  FROM media as A
46444f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
46530cf9434SAndreas Gohr                   AND mime1 != 'image'";
46644f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
467b6632b6eSAndreas Gohr    }
468b6632b6eSAndreas Gohr
469f9e60319SAndreas Gohr    /**
470f9e60319SAndreas Gohr     * @return array
471f9e60319SAndreas Gohr     */
472f9e60319SAndreas Gohr    public function referer(): array
473b6632b6eSAndreas Gohr    {
47410dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.url
47510dcb86fSAndreas Gohr                  FROM pageviews as P
47610dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
47710dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
47844f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
47930cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
48010dcb86fSAndreas Gohr                   AND R.url IS NOT NULL
48110dcb86fSAndreas Gohr                   AND R.url != ''
48210dcb86fSAndreas Gohr                   AND R.engine IS NULL
48310dcb86fSAndreas Gohr              GROUP BY R.url
48410dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.url" .
485f9e60319SAndreas Gohr            $this->limit;
48644f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
487b6632b6eSAndreas Gohr    }
488b6632b6eSAndreas Gohr
489f9e60319SAndreas Gohr    /**
490f9e60319SAndreas Gohr     * @return array
491f9e60319SAndreas Gohr     */
492f9e60319SAndreas Gohr    public function newreferer(): array
493b6632b6eSAndreas Gohr    {
49410dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.url
49510dcb86fSAndreas Gohr                  FROM pageviews as P
49610dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
49710dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
49844f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
49930cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
50010dcb86fSAndreas Gohr                   AND R.url IS NOT NULL
50110dcb86fSAndreas Gohr                   AND R.url != ''
50210dcb86fSAndreas Gohr                   AND R.engine IS NULL
50344f81330SAndreas Gohr                   AND DATETIME(R.dt, ?) >= ?
50410dcb86fSAndreas Gohr              GROUP BY R.url
50510dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.url" .
506f9e60319SAndreas Gohr            $this->limit;
50744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to, $this->tz, $this->from]);
508b6632b6eSAndreas Gohr    }
509b6632b6eSAndreas Gohr
510f9e60319SAndreas Gohr    /**
511f9e60319SAndreas Gohr     * @return array
512f9e60319SAndreas Gohr     */
513*f666296fSAndreas Gohr    public function campaigns(): array
514*f666296fSAndreas Gohr    {
515*f666296fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign
516*f666296fSAndreas Gohr                  FROM campaigns as C,
517*f666296fSAndreas Gohr                       sessions as S
518*f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
519*f666296fSAndreas Gohr                   AND S.session = C.session
520*f666296fSAndreas Gohr              GROUP BY C.campaign
521*f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
522*f666296fSAndreas Gohr            $this->limit;
523*f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
524*f666296fSAndreas Gohr    }
525*f666296fSAndreas Gohr
526*f666296fSAndreas Gohr    /**
527*f666296fSAndreas Gohr     * @return array
528*f666296fSAndreas Gohr     */
529*f666296fSAndreas Gohr    public function source(): array
530*f666296fSAndreas Gohr    {
531*f666296fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign || ' - ' || C.source AS campaign
532*f666296fSAndreas Gohr                  FROM campaigns as C,
533*f666296fSAndreas Gohr                       sessions as S
534*f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
535*f666296fSAndreas Gohr                   AND S.session = C.session
536*f666296fSAndreas Gohr                   AND C.source IS NOT NULL
537*f666296fSAndreas Gohr              GROUP BY C.campaign, C.source
538*f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
539*f666296fSAndreas Gohr            $this->limit;
540*f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
541*f666296fSAndreas Gohr    }
542*f666296fSAndreas Gohr
543*f666296fSAndreas Gohr    /**
544*f666296fSAndreas Gohr     * @return array
545*f666296fSAndreas Gohr     */
546*f666296fSAndreas Gohr    public function medium(): array
547*f666296fSAndreas Gohr    {
548*f666296fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign || ' - ' || C.medium AS campaign
549*f666296fSAndreas Gohr                  FROM campaigns as C,
550*f666296fSAndreas Gohr                       sessions as S
551*f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
552*f666296fSAndreas Gohr                   AND S.session = C.session
553*f666296fSAndreas Gohr                   AND C.medium IS NOT NULL
554*f666296fSAndreas Gohr              GROUP BY C.campaign, C.medium
555*f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
556*f666296fSAndreas Gohr            $this->limit;
557*f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
558*f666296fSAndreas Gohr    }
559*f666296fSAndreas Gohr
560*f666296fSAndreas Gohr
561*f666296fSAndreas Gohr    /**
562*f666296fSAndreas Gohr     * @return array
563*f666296fSAndreas Gohr     */
564f9e60319SAndreas Gohr    public function countries(): array
565b6632b6eSAndreas Gohr    {
56610dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT P.session) as cnt, I.country
5676f2bdce1SAndreas Gohr                  FROM pageviews as P,
5686f2bdce1SAndreas Gohr                       iplocation as I
56944f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
5706f2bdce1SAndreas Gohr                   AND P.ip = I.ip
57110dcb86fSAndreas Gohr                   AND I.country != ''
57210dcb86fSAndreas Gohr              GROUP BY I.code
57310dcb86fSAndreas Gohr              ORDER BY cnt DESC, I.country" .
574f9e60319SAndreas Gohr            $this->limit;
57544f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
576b6632b6eSAndreas Gohr    }
577b6632b6eSAndreas Gohr
578f9e60319SAndreas Gohr    /**
579f9e60319SAndreas Gohr     * @param bool $ext return extended information
580f9e60319SAndreas Gohr     * @return array
581f9e60319SAndreas Gohr     */
5822a30f557SAndreas Gohr    public function browsers(bool $ext = false): array
583b6632b6eSAndreas Gohr    {
584b6632b6eSAndreas Gohr        if ($ext) {
58510dcb86fSAndreas Gohr            $sel = 'S.ua_info as browser, S.ua_ver';
58610dcb86fSAndreas Gohr            $grp = 'S.ua_info, S.ua_ver';
587b6632b6eSAndreas Gohr        } else {
5882a30f557SAndreas Gohr            $sel = 'S.ua_info as browser';
58910dcb86fSAndreas Gohr            $grp = 'S.ua_info';
590b6632b6eSAndreas Gohr        }
591b6632b6eSAndreas Gohr
59210dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.session) as cnt, $sel
59310dcb86fSAndreas Gohr                  FROM sessions as S
59444f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
59530cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
596b6632b6eSAndreas Gohr              GROUP BY $grp
59710dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.ua_info" .
598f9e60319SAndreas Gohr            $this->limit;
59944f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
600b6632b6eSAndreas Gohr    }
601b6632b6eSAndreas Gohr
602f9e60319SAndreas Gohr    /**
603f9e60319SAndreas Gohr     * @return array
604f9e60319SAndreas Gohr     */
605f9e60319SAndreas Gohr    public function os(): array
606b6632b6eSAndreas Gohr    {
60710dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.session) as cnt, S.os
60810dcb86fSAndreas Gohr                  FROM sessions as S
60944f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
61030cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
61110dcb86fSAndreas Gohr              GROUP BY S.os
61210dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.os" .
613f9e60319SAndreas Gohr            $this->limit;
61444f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
615b6632b6eSAndreas Gohr    }
616b6632b6eSAndreas Gohr
617f9e60319SAndreas Gohr    /**
618f9e60319SAndreas Gohr     * @return array
619f9e60319SAndreas Gohr     */
6209fdd7e51SAndreas Gohr    public function topdomain(): array
6219fdd7e51SAndreas Gohr    {
6229fdd7e51SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, U.domain
6239fdd7e51SAndreas Gohr                  FROM pageviews as P,
6249fdd7e51SAndreas Gohr                       sessions as S,
6259fdd7e51SAndreas Gohr                       users as U
62644f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6279fdd7e51SAndreas Gohr                   AND P.session = S.session
6289fdd7e51SAndreas Gohr                   AND S.user = U.user
62930cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
6309fdd7e51SAndreas Gohr                   AND S.user IS NOT NULL
6319fdd7e51SAndreas Gohr              GROUP BY U.domain
6329fdd7e51SAndreas Gohr              ORDER BY cnt DESC, U.domain" .
6339fdd7e51SAndreas Gohr            $this->limit;
63444f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
6359fdd7e51SAndreas Gohr    }
6369fdd7e51SAndreas Gohr
6379fdd7e51SAndreas Gohr    /**
6389fdd7e51SAndreas Gohr     * @return array
6399fdd7e51SAndreas Gohr     */
640f9e60319SAndreas Gohr    public function topuser(): array
641b6632b6eSAndreas Gohr    {
64210dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, S.user
6436f2bdce1SAndreas Gohr                  FROM pageviews as P,
6446f2bdce1SAndreas Gohr                       sessions as S
64544f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6466f2bdce1SAndreas Gohr                   AND P.session = S.session
64730cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
648b7091bfdSAndreas Gohr                   AND S.user IS NOT NULL
64910dcb86fSAndreas Gohr              GROUP BY S.user
65010dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.user" .
651f9e60319SAndreas Gohr            $this->limit;
65244f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
653b6632b6eSAndreas Gohr    }
654b6632b6eSAndreas Gohr
655f9e60319SAndreas Gohr    /**
656f9e60319SAndreas Gohr     * @return array
657f9e60319SAndreas Gohr     */
658f9e60319SAndreas Gohr    public function topeditor(): array
659b6632b6eSAndreas Gohr    {
660b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, user
6616f2bdce1SAndreas Gohr                  FROM edits as E,
6626f2bdce1SAndreas Gohr                       sessions as S
66344f81330SAndreas Gohr                 WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ?
6646f2bdce1SAndreas Gohr                   AND E.session = S.session
665b7091bfdSAndreas Gohr                   AND S.user IS NOT NULL
666b6632b6eSAndreas Gohr              GROUP BY user
667b6632b6eSAndreas Gohr              ORDER BY cnt DESC, user" .
668f9e60319SAndreas Gohr            $this->limit;
66944f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
670b6632b6eSAndreas Gohr    }
671b6632b6eSAndreas Gohr
672f9e60319SAndreas Gohr    /**
673f9e60319SAndreas Gohr     * @return array
674f9e60319SAndreas Gohr     */
675f9e60319SAndreas Gohr    public function topgroup(): array
676b6632b6eSAndreas Gohr    {
67710dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, G.`group`
6786f2bdce1SAndreas Gohr                  FROM pageviews as P,
6796f2bdce1SAndreas Gohr                       sessions as S,
6806f2bdce1SAndreas Gohr                       groups as G
68144f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6826f2bdce1SAndreas Gohr                   AND P.session = S.session
6836f2bdce1SAndreas Gohr                   AND S.user = G.user
68430cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
68510dcb86fSAndreas Gohr              GROUP BY G.`group`
68610dcb86fSAndreas Gohr              ORDER BY cnt DESC, G.`group`" .
687f9e60319SAndreas Gohr            $this->limit;
68844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
689b6632b6eSAndreas Gohr    }
690b6632b6eSAndreas Gohr
691f9e60319SAndreas Gohr    /**
692f9e60319SAndreas Gohr     * @return array
693f9e60319SAndreas Gohr     */
694f9e60319SAndreas Gohr    public function topgroupedit(): array
695b6632b6eSAndreas Gohr    {
69610dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, G.`group`
6976f2bdce1SAndreas Gohr                  FROM edits as E,
6986f2bdce1SAndreas Gohr                       sessions as S,
6996f2bdce1SAndreas Gohr                       groups as G
70044f81330SAndreas Gohr                 WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ?
7016f2bdce1SAndreas Gohr                   AND E.session = S.session
7026f2bdce1SAndreas Gohr                   AND S.user = G.user
70310dcb86fSAndreas Gohr              GROUP BY G.`group`
70410dcb86fSAndreas Gohr              ORDER BY cnt DESC, G.`group`" .
705f9e60319SAndreas Gohr            $this->limit;
70644f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
707b6632b6eSAndreas Gohr    }
708b6632b6eSAndreas Gohr
709b6632b6eSAndreas Gohr
710f9e60319SAndreas Gohr    /**
711f9e60319SAndreas Gohr     * @return array
712f9e60319SAndreas Gohr     */
713f9e60319SAndreas Gohr    public function resolution(): array
714b6632b6eSAndreas Gohr    {
71510dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.uid) as cnt,
71610dcb86fSAndreas Gohr                       ROUND(P.screen_x/100)*100 as res_x,
71710dcb86fSAndreas Gohr                       ROUND(P.screen_y/100)*100 as res_y,
718bd514593SAndreas Gohr                       CAST(ROUND(P.screen_x/100)*100 AS int)
719bd514593SAndreas Gohr                           || 'x' ||
720bd514593SAndreas Gohr                       CAST(ROUND(P.screen_y/100)*100 AS int) as resolution
7216f2bdce1SAndreas Gohr                  FROM pageviews as P,
7226f2bdce1SAndreas Gohr                       sessions as S
72344f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
7246f2bdce1SAndreas Gohr                   AND P.session = S.session
72530cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
72630cf9434SAndreas Gohr                   AND P.screen_x != 0
72730cf9434SAndreas Gohr                   AND P.screen_y != 0
728b6632b6eSAndreas Gohr              GROUP BY resolution
729b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
730f9e60319SAndreas Gohr            $this->limit;
73144f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
732b6632b6eSAndreas Gohr    }
733b6632b6eSAndreas Gohr
734f9e60319SAndreas Gohr    /**
735f9e60319SAndreas Gohr     * @return array
736f9e60319SAndreas Gohr     */
737f9e60319SAndreas Gohr    public function viewport(): array
738b6632b6eSAndreas Gohr    {
73910dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.uid) as cnt,
74010dcb86fSAndreas Gohr                       ROUND(P.view_x/100)*100 as res_x,
74110dcb86fSAndreas Gohr                       ROUND(P.view_y/100)*100 as res_y,
742bd514593SAndreas Gohr                       CAST(ROUND(P.view_x/100)*100 AS int)
743bd514593SAndreas Gohr                           || 'x' ||
744bd514593SAndreas Gohr                       CAST(ROUND(P.view_y/100)*100 AS int) as resolution
7456f2bdce1SAndreas Gohr                  FROM pageviews as P,
7466f2bdce1SAndreas Gohr                       sessions as S
74744f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
7486f2bdce1SAndreas Gohr                   AND P.session = S.session
74930cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
75030cf9434SAndreas Gohr                   AND P.view_x != 0
75130cf9434SAndreas Gohr                   AND P.view_y != 0
752b6632b6eSAndreas Gohr              GROUP BY resolution
753b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
754f9e60319SAndreas Gohr            $this->limit;
755b6632b6eSAndreas Gohr
75644f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
757b6632b6eSAndreas Gohr    }
758b6632b6eSAndreas Gohr
759f9e60319SAndreas Gohr    /**
760f9e60319SAndreas Gohr     * @return array
761f9e60319SAndreas Gohr     */
762f9e60319SAndreas Gohr    public function seenusers(): array
763b6632b6eSAndreas Gohr    {
76410dcb86fSAndreas Gohr        $sql = "SELECT `user`, MAX(`dt`) as dt
76510dcb86fSAndreas Gohr                  FROM users
76610dcb86fSAndreas Gohr                 WHERE `user` IS NOT NULL
76710dcb86fSAndreas Gohr                   AND `user` != ''
76810dcb86fSAndreas Gohr              GROUP BY `user`
769b6632b6eSAndreas Gohr              ORDER BY `dt` DESC" .
770f9e60319SAndreas Gohr            $this->limit;
771b6632b6eSAndreas Gohr
772f9e60319SAndreas Gohr        return $this->db->queryAll($sql);
773b6632b6eSAndreas Gohr    }
774b6632b6eSAndreas Gohr}
775