xref: /plugin/statistics/Query.php (revision c9de78bb5a9fc166eaa547a9847b9db132048b2e)
1b6632b6eSAndreas Gohr<?php
2b6632b6eSAndreas Gohr
3b6632b6eSAndreas Gohrnamespace dokuwiki\plugin\statistics;
4b6632b6eSAndreas Gohr
5*c9de78bbSsplitbrainuse dokuwiki\Logger;
6f9e60319SAndreas Gohruse dokuwiki\plugin\sqlite\SQLiteDB;
7b6632b6eSAndreas Gohruse helper_plugin_statistics;
8b6632b6eSAndreas Gohr
9f9e60319SAndreas Gohr/**
10f9e60319SAndreas Gohr * This class defines a bunch of SQL queries to fetch various statistics from the database
11f9e60319SAndreas Gohr */
12b6632b6eSAndreas Gohrclass Query
13b6632b6eSAndreas Gohr{
14f9e60319SAndreas Gohr    protected helper_plugin_statistics $hlp;
15f9e60319SAndreas Gohr    protected SQLiteDB $db;
16f9e60319SAndreas Gohr    protected string $from;
17f9e60319SAndreas Gohr    protected string $to;
18f9e60319SAndreas Gohr    protected string $limit = '';
1944f81330SAndreas Gohr    protected string $tz = 'localtime';
20b6632b6eSAndreas Gohr
21f9e60319SAndreas Gohr    /**
22f9e60319SAndreas Gohr     * @param helper_plugin_statistics $hlp
23f9e60319SAndreas Gohr     */
24b6632b6eSAndreas Gohr    public function __construct(helper_plugin_statistics $hlp)
25b6632b6eSAndreas Gohr    {
26b6632b6eSAndreas Gohr        $this->hlp = $hlp;
27f9e60319SAndreas Gohr        $this->db = $hlp->getDB();
287428e816SAndreas Gohr        $today = date('Y-m-d');
297428e816SAndreas Gohr        $this->setTimeFrame($today, $today);
30f9e60319SAndreas Gohr        $this->setPagination(0, 20);
317428e816SAndreas Gohr    }
327428e816SAndreas Gohr
337428e816SAndreas Gohr    /**
347428e816SAndreas Gohr     * Set the time frame for all queries
35f9e60319SAndreas Gohr     *
36f9e60319SAndreas Gohr     * @param string $from The start date as YYYY-MM-DD
37f9e60319SAndreas Gohr     * @param string $to The end date as YYYY-MM-DD
387428e816SAndreas Gohr     */
39f9e60319SAndreas Gohr    public function setTimeFrame(string $from, string $to): void
407428e816SAndreas Gohr    {
41f9e60319SAndreas Gohr        try {
42f9e60319SAndreas Gohr            $from = new \DateTime($from);
43f9e60319SAndreas Gohr            $to = new \DateTime($to);
44f9e60319SAndreas Gohr        } catch (\Exception $e) {
45f9e60319SAndreas Gohr            $from = new \DateTime();
46f9e60319SAndreas Gohr            $to = new \DateTime();
47f9e60319SAndreas Gohr        }
48f9e60319SAndreas Gohr        $from->setTime(0, 0);
49f9e60319SAndreas Gohr        $to->setTime(23, 59, 59);
507428e816SAndreas Gohr
51f9e60319SAndreas Gohr        $this->from = $from->format('Y-m-d H:i:s');
52f9e60319SAndreas Gohr        $this->to = $to->format('Y-m-d H:i:s');
5357819987SAnna Dabrowska
5457819987SAnna Dabrowska        $this->setTimezone();
5557819987SAnna Dabrowska    }
5657819987SAnna Dabrowska
5757819987SAnna Dabrowska    /**
5857819987SAnna Dabrowska     * Force configured timezone.
5957819987SAnna Dabrowska     * This is useful if you cannot set localtime on the server.
6057819987SAnna Dabrowska     *
6157819987SAnna Dabrowska     * @return void
6257819987SAnna Dabrowska     */
6357819987SAnna Dabrowska    public function setTimezone()
6457819987SAnna Dabrowska    {
6557819987SAnna Dabrowska        $timezoneId = $this->hlp->getConf('timezone');
6657819987SAnna Dabrowska        if (!$timezoneId || !in_array($timezoneId, \DateTimeZone::listIdentifiers())) return;
6757819987SAnna Dabrowska
6857819987SAnna Dabrowska        try {
6957819987SAnna Dabrowska            $dateTime = new \DateTime($this->from, new \DateTimeZone($timezoneId));
7057819987SAnna Dabrowska            $this->tz = $dateTime->format('P');
7157819987SAnna Dabrowska        } catch (\Exception $e) {
72*c9de78bbSsplitbrain            Logger::error($e->getMessage());
7357819987SAnna Dabrowska        }
74f9e60319SAndreas Gohr    }
75f9e60319SAndreas Gohr
76f9e60319SAndreas Gohr    /**
77f9e60319SAndreas Gohr     * Set the pagination settings for some queries
78f9e60319SAndreas Gohr     *
79f9e60319SAndreas Gohr     * @param int $start The start offset
80f9e60319SAndreas Gohr     * @param int $limit The number of results. If one more is returned, there is another page
81f9e60319SAndreas Gohr     * @return void
82f9e60319SAndreas Gohr     */
83f9e60319SAndreas Gohr    public function setPagination(int $start, int $limit)
84f9e60319SAndreas Gohr    {
85f9e60319SAndreas Gohr        // when a limit is set, one more is fetched to indicate when a next page exists
86f9e60319SAndreas Gohr        if ($limit) $limit += 1;
87f9e60319SAndreas Gohr
88f9e60319SAndreas Gohr        if ($limit) {
89f9e60319SAndreas Gohr            $this->limit = " LIMIT $start,$limit";
90f9e60319SAndreas Gohr        } elseif ($start) {
91f9e60319SAndreas Gohr            $this->limit = " OFFSET $start";
92f9e60319SAndreas Gohr        }
93b6632b6eSAndreas Gohr    }
94b6632b6eSAndreas Gohr
95b6632b6eSAndreas Gohr    /**
96b6632b6eSAndreas Gohr     * Return some aggregated statistics
97b6632b6eSAndreas Gohr     */
98f9e60319SAndreas Gohr    public function aggregate(): array
99b6632b6eSAndreas Gohr    {
1002a30f557SAndreas Gohr        // init some values that might not be set
1012a30f557SAndreas Gohr        $data = [
1022a30f557SAndreas Gohr            'referers' => 0, // total number of (external) referrers
1032a30f557SAndreas Gohr            'external' => 0, // external referrers
1042a30f557SAndreas Gohr            'search' => 0, // search engine referrers
1052a30f557SAndreas Gohr            'direct' => 0, // direct referrers
1062a30f557SAndreas Gohr            'internal' => 0, // internal referrers
1072a30f557SAndreas Gohr            'bouncerate' => 0,
1082a30f557SAndreas Gohr            'newvisitors' => 0,
1092a30f557SAndreas Gohr        ];
110b6632b6eSAndreas Gohr
11110dcb86fSAndreas Gohr        // Count referrer types by joining with referers table
11210dcb86fSAndreas Gohr        $sql = "SELECT
11310dcb86fSAndreas Gohr                    CASE
11410dcb86fSAndreas Gohr                        WHEN R.engine IS NOT NULL THEN 'search'
1152a30f557SAndreas Gohr                        WHEN R.url = '' THEN 'direct'
1162a30f557SAndreas Gohr                        WHEN R.url IS NOT NULL THEN 'external'
1172a30f557SAndreas Gohr                        ELSE 'internal'
11810dcb86fSAndreas Gohr                    END as ref_type,
11910dcb86fSAndreas Gohr                    COUNT(*) as cnt
12010dcb86fSAndreas Gohr                  FROM pageviews as P
12110dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
12210dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
12344f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
12430cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
125b6632b6eSAndreas Gohr              GROUP BY ref_type";
12644f81330SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
127b6632b6eSAndreas Gohr
128f9e60319SAndreas Gohr        foreach ($result as $row) {
1292a30f557SAndreas Gohr            if ($row['ref_type'] == 'search') {
1302a30f557SAndreas Gohr                $data['search'] = $row['cnt'];
1312a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1322a30f557SAndreas Gohr            }
1332a30f557SAndreas Gohr            if ($row['ref_type'] == 'direct') {
1342a30f557SAndreas Gohr                $data['direct'] = $row['cnt'];
1352a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1362a30f557SAndreas Gohr            }
1372a30f557SAndreas Gohr            if ($row['ref_type'] == 'external') {
1382a30f557SAndreas Gohr                $data['external'] = $row['cnt'];
1392a30f557SAndreas Gohr                $data['referers'] += $row['cnt'];
1402a30f557SAndreas Gohr            }
1412a30f557SAndreas Gohr            if ($row['ref_type'] == 'internal') {
1422a30f557SAndreas Gohr                $data['internal'] = $row['cnt'];
1432a30f557SAndreas Gohr            }
144b6632b6eSAndreas Gohr        }
145b6632b6eSAndreas Gohr
146b6632b6eSAndreas Gohr        // general user and session info
14710dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT P.session) as sessions,
14810dcb86fSAndreas Gohr                       COUNT(P.session) as views,
14910dcb86fSAndreas Gohr                       COUNT(DISTINCT S.user) as users,
15044f81330SAndreas Gohr                       COUNT(DISTINCT S.uid) as visitors,
15144f81330SAndreas Gohr                       DATETIME(MAX(P.dt), ?) as last
15210dcb86fSAndreas Gohr                  FROM pageviews as P
15310dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
15444f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
15530cf9434SAndreas Gohr                   AND S.ua_type = 'browser'";
15644f81330SAndreas Gohr        $result = $this->db->queryRecord($sql, [$this->tz, $this->tz, $this->from, $this->tz, $this->to]);
157b6632b6eSAndreas Gohr
15810dcb86fSAndreas Gohr        $data['users'] = $result['users'];
159f9e60319SAndreas Gohr        $data['sessions'] = $result['sessions'];
160f9e60319SAndreas Gohr        $data['pageviews'] = $result['views'];
161f9e60319SAndreas Gohr        $data['visitors'] = $result['visitors'];
16244f81330SAndreas Gohr        $data['last'] = $result['last'];
163b6632b6eSAndreas Gohr
16410dcb86fSAndreas Gohr        // calculate bounce rate (sessions with only 1 page view)
165b6632b6eSAndreas Gohr        if ($data['sessions']) {
166b6632b6eSAndreas Gohr            $sql = "SELECT COUNT(*) as cnt
16710dcb86fSAndreas Gohr                      FROM (
16810dcb86fSAndreas Gohr                          SELECT P.session, COUNT(*) as views
16910dcb86fSAndreas Gohr                            FROM pageviews as P
17010dcb86fSAndreas Gohr                            LEFT JOIN sessions as S ON P.session = S.session
17144f81330SAndreas Gohr                           WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
17230cf9434SAndreas Gohr                             AND S.ua_type = 'browser'
17310dcb86fSAndreas Gohr                        GROUP BY P.session
17410dcb86fSAndreas Gohr                          HAVING views = 1
17510dcb86fSAndreas Gohr                      )";
17644f81330SAndreas Gohr            $count = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
177f9e60319SAndreas Gohr            $data['bouncerate'] = $count * 100 / $data['sessions'];
178f9e60319SAndreas Gohr            $data['newvisitors'] = $count * 100 / $data['sessions'];
179b6632b6eSAndreas Gohr        }
180b6632b6eSAndreas Gohr
181b6632b6eSAndreas Gohr        // calculate avg. number of views per session
182b6632b6eSAndreas Gohr        $sql = "SELECT AVG(views) as cnt
18310dcb86fSAndreas Gohr                  FROM (
18410dcb86fSAndreas Gohr                      SELECT P.session, COUNT(*) as views
18510dcb86fSAndreas Gohr                        FROM pageviews as P
18610dcb86fSAndreas Gohr                        LEFT JOIN sessions as S ON P.session = S.session
18744f81330SAndreas Gohr                       WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
18830cf9434SAndreas Gohr                         AND S.ua_type = 'browser'
18910dcb86fSAndreas Gohr                    GROUP BY P.session
19010dcb86fSAndreas Gohr                  )";
19144f81330SAndreas Gohr        $data['avgpages'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
192b6632b6eSAndreas Gohr
193b6632b6eSAndreas Gohr        // average time spent on the site
194115ede90SAndreas Gohr        $sql = "SELECT AVG((unixepoch(end) - unixepoch(dt)) / 60) as time
19510dcb86fSAndreas Gohr                  FROM sessions as S
196115ede90SAndreas Gohr                 WHERE S.dt != S.end
19744f81330SAndreas Gohr                   AND DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
19830cf9434SAndreas Gohr                   AND S.ua_type = 'browser'";
19944f81330SAndreas Gohr        $data['timespent'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
200b6632b6eSAndreas Gohr
201b6632b6eSAndreas Gohr        // logins
202b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as logins
2037428e816SAndreas Gohr                  FROM logins as A
20444f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
20530cf9434SAndreas Gohr                   AND (type = 'l' OR type = 'p')";
20644f81330SAndreas Gohr        $data['logins'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
207b6632b6eSAndreas Gohr
208b6632b6eSAndreas Gohr        // registrations
209b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as registrations
2107428e816SAndreas Gohr                  FROM logins as A
21144f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
21230cf9434SAndreas Gohr                   AND type = 'C'";
21344f81330SAndreas Gohr        $data['registrations'] = $this->db->queryValue($sql, [$this->tz, $this->from, $this->tz, $this->to]);
214b6632b6eSAndreas Gohr
21510dcb86fSAndreas Gohr        // current users (based on recent sessions)
21610dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT uid) as current
21710dcb86fSAndreas Gohr                  FROM sessions
21810dcb86fSAndreas Gohr                 WHERE end >= datetime('now', '-10 minutes')";
219f9e60319SAndreas Gohr        $data['current'] = $this->db->queryValue($sql);
220b6632b6eSAndreas Gohr
221b6632b6eSAndreas Gohr        return $data;
222b6632b6eSAndreas Gohr    }
223b6632b6eSAndreas Gohr
224b6632b6eSAndreas Gohr
225b6632b6eSAndreas Gohr    /**
226b6632b6eSAndreas Gohr     * Return some trend data about visits and edits in the wiki
227f9e60319SAndreas Gohr     *
228f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
229f9e60319SAndreas Gohr     * @return array
230b6632b6eSAndreas Gohr     */
231f9e60319SAndreas Gohr    public function dashboardviews(bool $hours = false): array
232b6632b6eSAndreas Gohr    {
233b6632b6eSAndreas Gohr        if ($hours) {
23444f81330SAndreas Gohr            $TIME = "strftime('%H', DATETIME(P.dt, '$this->tz'))";
235b6632b6eSAndreas Gohr        } else {
23644f81330SAndreas Gohr            $TIME = "DATE(DATETIME(P.dt, '$this->tz'))";
237b6632b6eSAndreas Gohr        }
238b6632b6eSAndreas Gohr
239b6632b6eSAndreas Gohr        $data = [];
240b6632b6eSAndreas Gohr
241b6632b6eSAndreas Gohr        // access trends
242b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
24310dcb86fSAndreas Gohr                       COUNT(DISTINCT P.session) as sessions,
24410dcb86fSAndreas Gohr                       COUNT(P.session) as pageviews,
24510dcb86fSAndreas Gohr                       COUNT(DISTINCT S.uid) as visitors
24610dcb86fSAndreas Gohr                  FROM pageviews as P
24710dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
24844f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
24930cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
250b6632b6eSAndreas Gohr              GROUP BY $TIME
251b6632b6eSAndreas Gohr              ORDER BY time";
25244f81330SAndreas Gohr        $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
253b6632b6eSAndreas Gohr        foreach ($result as $row) {
254b6632b6eSAndreas Gohr            $data[$row['time']]['sessions'] = $row['sessions'];
255b6632b6eSAndreas Gohr            $data[$row['time']]['pageviews'] = $row['pageviews'];
256b6632b6eSAndreas Gohr            $data[$row['time']]['visitors'] = $row['visitors'];
257b6632b6eSAndreas Gohr        }
258b6632b6eSAndreas Gohr        return $data;
259b6632b6eSAndreas Gohr    }
260b6632b6eSAndreas Gohr
261f9e60319SAndreas Gohr    /**
262f9e60319SAndreas Gohr     * @param bool $hours Use hour resolution rather than days
263f9e60319SAndreas Gohr     * @return array
264f9e60319SAndreas Gohr     */
265f9e60319SAndreas Gohr    public function dashboardwiki(bool $hours = false): array
266b6632b6eSAndreas Gohr    {
267b6632b6eSAndreas Gohr        if ($hours) {
26844f81330SAndreas Gohr            $TIME = "strftime('%H', DATETIME(dt, '$this->tz'))";
269b6632b6eSAndreas Gohr        } else {
27044f81330SAndreas Gohr            $TIME = "DATE(DATETIME(dt, '$this->tz'))";
271b6632b6eSAndreas Gohr        }
272b6632b6eSAndreas Gohr
273b6632b6eSAndreas Gohr        $data = [];
274b6632b6eSAndreas Gohr
275b6632b6eSAndreas Gohr        // edit trends
276b6632b6eSAndreas Gohr        foreach (['E', 'C', 'D'] as $type) {
277b6632b6eSAndreas Gohr            $sql = "SELECT $TIME as time,
278b6632b6eSAndreas Gohr                           COUNT(*) as cnt
2797428e816SAndreas Gohr                      FROM edits as A
28044f81330SAndreas Gohr                     WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
28130cf9434SAndreas Gohr                       AND type = '$type'
282b6632b6eSAndreas Gohr                  GROUP BY $TIME
283b6632b6eSAndreas Gohr                  ORDER BY time";
28444f81330SAndreas Gohr            $result = $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
285b6632b6eSAndreas Gohr            foreach ($result as $row) {
286b6632b6eSAndreas Gohr                $data[$row['time']][$type] = $row['cnt'];
287b6632b6eSAndreas Gohr            }
288b6632b6eSAndreas Gohr        }
289b6632b6eSAndreas Gohr        ksort($data);
290b6632b6eSAndreas Gohr        return $data;
291b6632b6eSAndreas Gohr    }
292b6632b6eSAndreas Gohr
293f9e60319SAndreas Gohr    /**
294f9e60319SAndreas Gohr     * @param string $info Which type of history to select (FIXME which ones are there?)
295f9e60319SAndreas Gohr     * @param string $interval Group data by this interval (days, weeks, months)
296f9e60319SAndreas Gohr     * @return array
297f9e60319SAndreas Gohr     */
298f9e60319SAndreas Gohr    public function history(string $info, string $interval = 'day'): array
299b6632b6eSAndreas Gohr    {
300b6632b6eSAndreas Gohr        if ($interval == 'weeks') {
30144f81330SAndreas Gohr            $TIME = "strftime('%Y', DATETIME(dt, '$this->tz')), strftime('%W', DATETIME(dt, '$this->tz'))";
302b6632b6eSAndreas Gohr        } elseif ($interval == 'months') {
30344f81330SAndreas Gohr            $TIME = "strftime('%Y-%m', DATETIME(dt, '$this->tz'))";
304b6632b6eSAndreas Gohr        } else {
30544f81330SAndreas Gohr            $TIME = "strftime('%d-%m', DATETIME(dt, '$this->tz'))";
306b6632b6eSAndreas Gohr        }
307b6632b6eSAndreas Gohr
308b6632b6eSAndreas Gohr        $mod = 1;
309b6632b6eSAndreas Gohr        if ($info == 'media_size' || $info == 'page_size') {
310b6632b6eSAndreas Gohr            $mod = 1024 * 1024;
311b6632b6eSAndreas Gohr        }
312b6632b6eSAndreas Gohr
313b6632b6eSAndreas Gohr        $sql = "SELECT $TIME as time,
3147428e816SAndreas Gohr                       AVG(value)/$mod as cnt
3157428e816SAndreas Gohr                  FROM history as A
31644f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
3177428e816SAndreas Gohr                   AND info = ?
318b6632b6eSAndreas Gohr                  GROUP BY $TIME
319b6632b6eSAndreas Gohr                  ORDER BY $TIME";
32044f81330SAndreas Gohr
32144f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to, $info]);
322b6632b6eSAndreas Gohr    }
323b6632b6eSAndreas Gohr
324f9e60319SAndreas Gohr    /**
325f9e60319SAndreas Gohr     * @return array
326f9e60319SAndreas Gohr     */
327f9e60319SAndreas Gohr    public function searchengines(): array
328b6632b6eSAndreas Gohr    {
32910dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.engine
3306f2bdce1SAndreas Gohr                  FROM pageviews as P,
3316f2bdce1SAndreas Gohr                       referers as R
33244f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
3336f2bdce1SAndreas Gohr                   AND P.ref_id = R.id
33410dcb86fSAndreas Gohr                   AND R.engine != ''
33510dcb86fSAndreas Gohr              GROUP BY R.engine
33610dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.engine" .
337f9e60319SAndreas Gohr            $this->limit;
33844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
339b6632b6eSAndreas Gohr    }
340b6632b6eSAndreas Gohr
341f9e60319SAndreas Gohr    /**
342f9e60319SAndreas Gohr     * @return array
343f9e60319SAndreas Gohr     */
344444fcd22SAndreas Gohr    public function internalsearchphrases(): array
345b6632b6eSAndreas Gohr    {
3462a30f557SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, query, query as ilookup
3472a30f557SAndreas Gohr                  FROM search
34844f81330SAndreas Gohr                 WHERE DATETIME(dt, ?) >= ? AND DATETIME(dt, ?) <= ?
3492a30f557SAndreas Gohr              GROUP BY query
3502a30f557SAndreas Gohr              ORDER BY cnt DESC, query" .
351f9e60319SAndreas Gohr            $this->limit;
35244f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
353b6632b6eSAndreas Gohr    }
354b6632b6eSAndreas Gohr
355f9e60319SAndreas Gohr    /**
356f9e60319SAndreas Gohr     * @return array
357f9e60319SAndreas Gohr     */
358444fcd22SAndreas Gohr    public function internalsearchwords(): array
359b6632b6eSAndreas Gohr    {
3602a30f557SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SW.word, SW.word as ilookup
3612a30f557SAndreas Gohr                  FROM search as S,
3622a30f557SAndreas Gohr                       searchwords as SW
36344f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
3642a30f557SAndreas Gohr                   AND S.id = SW.sid
36510dcb86fSAndreas Gohr              GROUP BY SW.word
36610dcb86fSAndreas Gohr              ORDER BY cnt DESC, SW.word" .
367f9e60319SAndreas Gohr            $this->limit;
36844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
369b6632b6eSAndreas Gohr    }
370b6632b6eSAndreas Gohr
371f9e60319SAndreas Gohr    /**
372f9e60319SAndreas Gohr     * @return array
373f9e60319SAndreas Gohr     */
374f9e60319SAndreas Gohr    public function outlinks(): array
375b6632b6eSAndreas Gohr    {
376b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, link as url
3777428e816SAndreas Gohr                  FROM outlinks as A
37844f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
379b6632b6eSAndreas Gohr              GROUP BY link
380b6632b6eSAndreas Gohr              ORDER BY cnt DESC, link" .
381f9e60319SAndreas Gohr            $this->limit;
38244f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
383b6632b6eSAndreas Gohr    }
384b6632b6eSAndreas Gohr
385f9e60319SAndreas Gohr    /**
386f9e60319SAndreas Gohr     * @return array
387f9e60319SAndreas Gohr     */
388f9e60319SAndreas Gohr    public function pages(): array
389b6632b6eSAndreas Gohr    {
39010dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, P.page
3916f2bdce1SAndreas Gohr                  FROM pageviews as P,
3926f2bdce1SAndreas Gohr                       sessions as S
39344f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
3946f2bdce1SAndreas Gohr                   AND P.session = S.session
39530cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
39610dcb86fSAndreas Gohr              GROUP BY P.page
39710dcb86fSAndreas Gohr              ORDER BY cnt DESC, P.page" .
398f9e60319SAndreas Gohr            $this->limit;
39944f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
400b6632b6eSAndreas Gohr    }
401b6632b6eSAndreas Gohr
402f9e60319SAndreas Gohr    /**
403f9e60319SAndreas Gohr     * @return array
404f9e60319SAndreas Gohr     */
405f9e60319SAndreas Gohr    public function edits(): array
406b6632b6eSAndreas Gohr    {
407b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
4087428e816SAndreas Gohr                  FROM edits as A
40944f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
410b6632b6eSAndreas Gohr              GROUP BY page
411b6632b6eSAndreas Gohr              ORDER BY cnt DESC, page" .
412f9e60319SAndreas Gohr            $this->limit;
41344f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
414b6632b6eSAndreas Gohr    }
415b6632b6eSAndreas Gohr
416f9e60319SAndreas Gohr    /**
417f9e60319SAndreas Gohr     * @return array
418f9e60319SAndreas Gohr     */
419f9e60319SAndreas Gohr    public function images(): array
420b6632b6eSAndreas Gohr    {
421b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
4227428e816SAndreas Gohr                  FROM media as A
42344f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
42430cf9434SAndreas Gohr                   AND mime1 = 'image'
425b6632b6eSAndreas Gohr              GROUP BY media
426b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
427f9e60319SAndreas Gohr            $this->limit;
42844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
429b6632b6eSAndreas Gohr    }
430b6632b6eSAndreas Gohr
431f9e60319SAndreas Gohr    /**
432f9e60319SAndreas Gohr     * @return array
433f9e60319SAndreas Gohr     */
434f9e60319SAndreas Gohr    public function imagessum(): array
435b6632b6eSAndreas Gohr    {
436b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
4377428e816SAndreas Gohr                  FROM media as A
43844f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
43930cf9434SAndreas Gohr                   AND mime1 = 'image'";
44044f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
441b6632b6eSAndreas Gohr    }
442b6632b6eSAndreas Gohr
443f9e60319SAndreas Gohr    /**
444f9e60319SAndreas Gohr     * @return array
445f9e60319SAndreas Gohr     */
446f9e60319SAndreas Gohr    public function downloads(): array
447b6632b6eSAndreas Gohr    {
448b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize
4497428e816SAndreas Gohr                  FROM media as A
45044f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
45130cf9434SAndreas Gohr                   AND mime1 != 'image'
452b6632b6eSAndreas Gohr              GROUP BY media
453b6632b6eSAndreas Gohr              ORDER BY cnt DESC, media" .
454f9e60319SAndreas Gohr            $this->limit;
45544f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
456b6632b6eSAndreas Gohr    }
457b6632b6eSAndreas Gohr
458f9e60319SAndreas Gohr    /**
459f9e60319SAndreas Gohr     * @return array
460f9e60319SAndreas Gohr     */
461f9e60319SAndreas Gohr    public function downloadssum(): array
462b6632b6eSAndreas Gohr    {
463b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize
4647428e816SAndreas Gohr                  FROM media as A
46544f81330SAndreas Gohr                 WHERE DATETIME(A.dt, ?) >= ? AND DATETIME(A.dt, ?) <= ?
46630cf9434SAndreas Gohr                   AND mime1 != 'image'";
46744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
468b6632b6eSAndreas Gohr    }
469b6632b6eSAndreas Gohr
470f9e60319SAndreas Gohr    /**
471f9e60319SAndreas Gohr     * @return array
472f9e60319SAndreas Gohr     */
473f9e60319SAndreas Gohr    public function referer(): array
474b6632b6eSAndreas Gohr    {
47510dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.url
47610dcb86fSAndreas Gohr                  FROM pageviews as P
47710dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
47810dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
47944f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
48030cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
48110dcb86fSAndreas Gohr                   AND R.url IS NOT NULL
48210dcb86fSAndreas Gohr                   AND R.url != ''
48310dcb86fSAndreas Gohr                   AND R.engine IS NULL
48410dcb86fSAndreas Gohr              GROUP BY R.url
48510dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.url" .
486f9e60319SAndreas Gohr            $this->limit;
48744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
488b6632b6eSAndreas Gohr    }
489b6632b6eSAndreas Gohr
490f9e60319SAndreas Gohr    /**
491f9e60319SAndreas Gohr     * @return array
492f9e60319SAndreas Gohr     */
493f9e60319SAndreas Gohr    public function newreferer(): array
494b6632b6eSAndreas Gohr    {
49510dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, R.url
49610dcb86fSAndreas Gohr                  FROM pageviews as P
49710dcb86fSAndreas Gohr                  LEFT JOIN sessions as S ON P.session = S.session
49810dcb86fSAndreas Gohr                  LEFT JOIN referers as R ON P.ref_id = R.id
49944f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
50030cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
50110dcb86fSAndreas Gohr                   AND R.url IS NOT NULL
50210dcb86fSAndreas Gohr                   AND R.url != ''
50310dcb86fSAndreas Gohr                   AND R.engine IS NULL
50444f81330SAndreas Gohr                   AND DATETIME(R.dt, ?) >= ?
50510dcb86fSAndreas Gohr              GROUP BY R.url
50610dcb86fSAndreas Gohr              ORDER BY cnt DESC, R.url" .
507f9e60319SAndreas Gohr            $this->limit;
50844f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to, $this->tz, $this->from]);
509b6632b6eSAndreas Gohr    }
510b6632b6eSAndreas Gohr
511f9e60319SAndreas Gohr    /**
512f9e60319SAndreas Gohr     * @return array
513f9e60319SAndreas Gohr     */
514f666296fSAndreas Gohr    public function campaigns(): array
515f666296fSAndreas Gohr    {
516f666296fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign
517f666296fSAndreas Gohr                  FROM campaigns as C,
518f666296fSAndreas Gohr                       sessions as S
519f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
520f666296fSAndreas Gohr                   AND S.session = C.session
521f666296fSAndreas Gohr              GROUP BY C.campaign
522f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
523f666296fSAndreas Gohr            $this->limit;
524f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
525f666296fSAndreas Gohr    }
526f666296fSAndreas Gohr
527f666296fSAndreas Gohr    /**
528f666296fSAndreas Gohr     * @return array
529f666296fSAndreas Gohr     */
530f666296fSAndreas Gohr    public function source(): array
531f666296fSAndreas Gohr    {
53259a64057SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign || ' ' || C.source AS campaign
533f666296fSAndreas Gohr                  FROM campaigns as C,
534f666296fSAndreas Gohr                       sessions as S
535f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
536f666296fSAndreas Gohr                   AND S.session = C.session
537f666296fSAndreas Gohr                   AND C.source IS NOT NULL
538f666296fSAndreas Gohr              GROUP BY C.campaign, C.source
539f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
540f666296fSAndreas Gohr            $this->limit;
541f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
542f666296fSAndreas Gohr    }
543f666296fSAndreas Gohr
544f666296fSAndreas Gohr    /**
545f666296fSAndreas Gohr     * @return array
546f666296fSAndreas Gohr     */
547f666296fSAndreas Gohr    public function medium(): array
548f666296fSAndreas Gohr    {
54959a64057SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, C.campaign || ' ' || C.medium AS campaign
550f666296fSAndreas Gohr                  FROM campaigns as C,
551f666296fSAndreas Gohr                       sessions as S
552f666296fSAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
553f666296fSAndreas Gohr                   AND S.session = C.session
554f666296fSAndreas Gohr                   AND C.medium IS NOT NULL
555f666296fSAndreas Gohr              GROUP BY C.campaign, C.medium
556f666296fSAndreas Gohr              ORDER BY cnt DESC, C.campaign" .
557f666296fSAndreas Gohr            $this->limit;
558f666296fSAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
559f666296fSAndreas Gohr    }
560f666296fSAndreas Gohr
561f666296fSAndreas Gohr
562f666296fSAndreas Gohr    /**
563f666296fSAndreas Gohr     * @return array
564f666296fSAndreas Gohr     */
565f9e60319SAndreas Gohr    public function countries(): array
566b6632b6eSAndreas Gohr    {
56710dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT P.session) as cnt, I.country
5686f2bdce1SAndreas Gohr                  FROM pageviews as P,
5696f2bdce1SAndreas Gohr                       iplocation as I
57044f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
5716f2bdce1SAndreas Gohr                   AND P.ip = I.ip
57210dcb86fSAndreas Gohr                   AND I.country != ''
57310dcb86fSAndreas Gohr              GROUP BY I.code
57410dcb86fSAndreas Gohr              ORDER BY cnt DESC, I.country" .
575f9e60319SAndreas Gohr            $this->limit;
57644f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
577b6632b6eSAndreas Gohr    }
578b6632b6eSAndreas Gohr
579f9e60319SAndreas Gohr    /**
580f9e60319SAndreas Gohr     * @param bool $ext return extended information
581f9e60319SAndreas Gohr     * @return array
582f9e60319SAndreas Gohr     */
5832a30f557SAndreas Gohr    public function browsers(bool $ext = false): array
584b6632b6eSAndreas Gohr    {
585b6632b6eSAndreas Gohr        if ($ext) {
58610dcb86fSAndreas Gohr            $sel = 'S.ua_info as browser, S.ua_ver';
58710dcb86fSAndreas Gohr            $grp = 'S.ua_info, S.ua_ver';
588b6632b6eSAndreas Gohr        } else {
5892a30f557SAndreas Gohr            $sel = 'S.ua_info as browser';
59010dcb86fSAndreas Gohr            $grp = 'S.ua_info';
591b6632b6eSAndreas Gohr        }
592b6632b6eSAndreas Gohr
59310dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.session) as cnt, $sel
59410dcb86fSAndreas Gohr                  FROM sessions as S
59544f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
59630cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
597b6632b6eSAndreas Gohr              GROUP BY $grp
59810dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.ua_info" .
599f9e60319SAndreas Gohr            $this->limit;
60044f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
601b6632b6eSAndreas Gohr    }
602b6632b6eSAndreas Gohr
603f9e60319SAndreas Gohr    /**
604f9e60319SAndreas Gohr     * @return array
605f9e60319SAndreas Gohr     */
606f9e60319SAndreas Gohr    public function os(): array
607b6632b6eSAndreas Gohr    {
60810dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.session) as cnt, S.os
60910dcb86fSAndreas Gohr                  FROM sessions as S
61044f81330SAndreas Gohr                 WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ?
61130cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
61210dcb86fSAndreas Gohr              GROUP BY S.os
61310dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.os" .
614f9e60319SAndreas Gohr            $this->limit;
61544f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
616b6632b6eSAndreas Gohr    }
617b6632b6eSAndreas Gohr
618f9e60319SAndreas Gohr    /**
619f9e60319SAndreas Gohr     * @return array
620f9e60319SAndreas Gohr     */
6219fdd7e51SAndreas Gohr    public function topdomain(): array
6229fdd7e51SAndreas Gohr    {
6239fdd7e51SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, U.domain
6249fdd7e51SAndreas Gohr                  FROM pageviews as P,
6259fdd7e51SAndreas Gohr                       sessions as S,
6269fdd7e51SAndreas Gohr                       users as U
62744f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6289fdd7e51SAndreas Gohr                   AND P.session = S.session
6299fdd7e51SAndreas Gohr                   AND S.user = U.user
63030cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
6319fdd7e51SAndreas Gohr                   AND S.user IS NOT NULL
6329fdd7e51SAndreas Gohr              GROUP BY U.domain
6339fdd7e51SAndreas Gohr              ORDER BY cnt DESC, U.domain" .
6349fdd7e51SAndreas Gohr            $this->limit;
63544f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
6369fdd7e51SAndreas Gohr    }
6379fdd7e51SAndreas Gohr
6389fdd7e51SAndreas Gohr    /**
6399fdd7e51SAndreas Gohr     * @return array
6409fdd7e51SAndreas Gohr     */
641f9e60319SAndreas Gohr    public function topuser(): array
642b6632b6eSAndreas Gohr    {
64310dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, S.user
6446f2bdce1SAndreas Gohr                  FROM pageviews as P,
6456f2bdce1SAndreas Gohr                       sessions as S
64644f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6476f2bdce1SAndreas Gohr                   AND P.session = S.session
64830cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
649b7091bfdSAndreas Gohr                   AND S.user IS NOT NULL
65010dcb86fSAndreas Gohr              GROUP BY S.user
65110dcb86fSAndreas Gohr              ORDER BY cnt DESC, S.user" .
652f9e60319SAndreas Gohr            $this->limit;
65344f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
654b6632b6eSAndreas Gohr    }
655b6632b6eSAndreas Gohr
656f9e60319SAndreas Gohr    /**
657f9e60319SAndreas Gohr     * @return array
658f9e60319SAndreas Gohr     */
659f9e60319SAndreas Gohr    public function topeditor(): array
660b6632b6eSAndreas Gohr    {
661b6632b6eSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, user
6626f2bdce1SAndreas Gohr                  FROM edits as E,
6636f2bdce1SAndreas Gohr                       sessions as S
66444f81330SAndreas Gohr                 WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ?
6656f2bdce1SAndreas Gohr                   AND E.session = S.session
666b7091bfdSAndreas Gohr                   AND S.user IS NOT NULL
667b6632b6eSAndreas Gohr              GROUP BY user
668b6632b6eSAndreas Gohr              ORDER BY cnt DESC, user" .
669f9e60319SAndreas Gohr            $this->limit;
67044f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
671b6632b6eSAndreas Gohr    }
672b6632b6eSAndreas Gohr
673f9e60319SAndreas Gohr    /**
674f9e60319SAndreas Gohr     * @return array
675f9e60319SAndreas Gohr     */
676f9e60319SAndreas Gohr    public function topgroup(): array
677b6632b6eSAndreas Gohr    {
67810dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, G.`group`
6796f2bdce1SAndreas Gohr                  FROM pageviews as P,
6806f2bdce1SAndreas Gohr                       sessions as S,
6816f2bdce1SAndreas Gohr                       groups as G
68244f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
6836f2bdce1SAndreas Gohr                   AND P.session = S.session
6846f2bdce1SAndreas Gohr                   AND S.user = G.user
68530cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
68610dcb86fSAndreas Gohr              GROUP BY G.`group`
68710dcb86fSAndreas Gohr              ORDER BY cnt DESC, G.`group`" .
688f9e60319SAndreas Gohr            $this->limit;
68944f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
690b6632b6eSAndreas Gohr    }
691b6632b6eSAndreas Gohr
692f9e60319SAndreas Gohr    /**
693f9e60319SAndreas Gohr     * @return array
694f9e60319SAndreas Gohr     */
695f9e60319SAndreas Gohr    public function topgroupedit(): array
696b6632b6eSAndreas Gohr    {
69710dcb86fSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, G.`group`
6986f2bdce1SAndreas Gohr                  FROM edits as E,
6996f2bdce1SAndreas Gohr                       sessions as S,
7006f2bdce1SAndreas Gohr                       groups as G
70144f81330SAndreas Gohr                 WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ?
7026f2bdce1SAndreas Gohr                   AND E.session = S.session
7036f2bdce1SAndreas Gohr                   AND S.user = G.user
70410dcb86fSAndreas Gohr              GROUP BY G.`group`
70510dcb86fSAndreas Gohr              ORDER BY cnt DESC, G.`group`" .
706f9e60319SAndreas Gohr            $this->limit;
70744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
708b6632b6eSAndreas Gohr    }
709b6632b6eSAndreas Gohr
710b6632b6eSAndreas Gohr
711f9e60319SAndreas Gohr    /**
712f9e60319SAndreas Gohr     * @return array
713f9e60319SAndreas Gohr     */
714f9e60319SAndreas Gohr    public function resolution(): array
715b6632b6eSAndreas Gohr    {
71610dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.uid) as cnt,
71710dcb86fSAndreas Gohr                       ROUND(P.screen_x/100)*100 as res_x,
71810dcb86fSAndreas Gohr                       ROUND(P.screen_y/100)*100 as res_y,
719bd514593SAndreas Gohr                       CAST(ROUND(P.screen_x/100)*100 AS int)
720bd514593SAndreas Gohr                           || 'x' ||
721bd514593SAndreas Gohr                       CAST(ROUND(P.screen_y/100)*100 AS int) as resolution
7226f2bdce1SAndreas Gohr                  FROM pageviews as P,
7236f2bdce1SAndreas Gohr                       sessions as S
72444f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
7256f2bdce1SAndreas Gohr                   AND P.session = S.session
72630cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
72730cf9434SAndreas Gohr                   AND P.screen_x != 0
72830cf9434SAndreas Gohr                   AND P.screen_y != 0
729b6632b6eSAndreas Gohr              GROUP BY resolution
730b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
731f9e60319SAndreas Gohr            $this->limit;
73244f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
733b6632b6eSAndreas Gohr    }
734b6632b6eSAndreas Gohr
735f9e60319SAndreas Gohr    /**
736f9e60319SAndreas Gohr     * @return array
737f9e60319SAndreas Gohr     */
738f9e60319SAndreas Gohr    public function viewport(): array
739b6632b6eSAndreas Gohr    {
74010dcb86fSAndreas Gohr        $sql = "SELECT COUNT(DISTINCT S.uid) as cnt,
74110dcb86fSAndreas Gohr                       ROUND(P.view_x/100)*100 as res_x,
74210dcb86fSAndreas Gohr                       ROUND(P.view_y/100)*100 as res_y,
743bd514593SAndreas Gohr                       CAST(ROUND(P.view_x/100)*100 AS int)
744bd514593SAndreas Gohr                           || 'x' ||
745bd514593SAndreas Gohr                       CAST(ROUND(P.view_y/100)*100 AS int) as resolution
7466f2bdce1SAndreas Gohr                  FROM pageviews as P,
7476f2bdce1SAndreas Gohr                       sessions as S
74844f81330SAndreas Gohr                 WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ?
7496f2bdce1SAndreas Gohr                   AND P.session = S.session
75030cf9434SAndreas Gohr                   AND S.ua_type = 'browser'
75130cf9434SAndreas Gohr                   AND P.view_x != 0
75230cf9434SAndreas Gohr                   AND P.view_y != 0
753b6632b6eSAndreas Gohr              GROUP BY resolution
754b6632b6eSAndreas Gohr              ORDER BY cnt DESC" .
755f9e60319SAndreas Gohr            $this->limit;
756b6632b6eSAndreas Gohr
75744f81330SAndreas Gohr        return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]);
758b6632b6eSAndreas Gohr    }
759b6632b6eSAndreas Gohr
760f9e60319SAndreas Gohr    /**
761f9e60319SAndreas Gohr     * @return array
762f9e60319SAndreas Gohr     */
763f9e60319SAndreas Gohr    public function seenusers(): array
764b6632b6eSAndreas Gohr    {
76510dcb86fSAndreas Gohr        $sql = "SELECT `user`, MAX(`dt`) as dt
76610dcb86fSAndreas Gohr                  FROM users
76710dcb86fSAndreas Gohr                 WHERE `user` IS NOT NULL
76810dcb86fSAndreas Gohr                   AND `user` != ''
76910dcb86fSAndreas Gohr              GROUP BY `user`
770b6632b6eSAndreas Gohr              ORDER BY `dt` DESC" .
771f9e60319SAndreas Gohr            $this->limit;
772b6632b6eSAndreas Gohr
773f9e60319SAndreas Gohr        return $this->db->queryAll($sql);
774b6632b6eSAndreas Gohr    }
775b6632b6eSAndreas Gohr}
776