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 */ 343*444fcd22SAndreas 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 */ 357*444fcd22SAndreas 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 */ 513f9e60319SAndreas Gohr public function countries(): array 514b6632b6eSAndreas Gohr { 51510dcb86fSAndreas Gohr $sql = "SELECT COUNT(DISTINCT P.session) as cnt, I.country 5166f2bdce1SAndreas Gohr FROM pageviews as P, 5176f2bdce1SAndreas Gohr iplocation as I 51844f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 5196f2bdce1SAndreas Gohr AND P.ip = I.ip 52010dcb86fSAndreas Gohr AND I.country != '' 52110dcb86fSAndreas Gohr GROUP BY I.code 52210dcb86fSAndreas Gohr ORDER BY cnt DESC, I.country" . 523f9e60319SAndreas Gohr $this->limit; 52444f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 525b6632b6eSAndreas Gohr } 526b6632b6eSAndreas Gohr 527f9e60319SAndreas Gohr /** 528f9e60319SAndreas Gohr * @param bool $ext return extended information 529f9e60319SAndreas Gohr * @return array 530f9e60319SAndreas Gohr */ 5312a30f557SAndreas Gohr public function browsers(bool $ext = false): array 532b6632b6eSAndreas Gohr { 533b6632b6eSAndreas Gohr if ($ext) { 53410dcb86fSAndreas Gohr $sel = 'S.ua_info as browser, S.ua_ver'; 53510dcb86fSAndreas Gohr $grp = 'S.ua_info, S.ua_ver'; 536b6632b6eSAndreas Gohr } else { 5372a30f557SAndreas Gohr $sel = 'S.ua_info as browser'; 53810dcb86fSAndreas Gohr $grp = 'S.ua_info'; 539b6632b6eSAndreas Gohr } 540b6632b6eSAndreas Gohr 54110dcb86fSAndreas Gohr $sql = "SELECT COUNT(DISTINCT S.session) as cnt, $sel 54210dcb86fSAndreas Gohr FROM sessions as S 54344f81330SAndreas Gohr WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ? 54430cf9434SAndreas Gohr AND S.ua_type = 'browser' 545b6632b6eSAndreas Gohr GROUP BY $grp 54610dcb86fSAndreas Gohr ORDER BY cnt DESC, S.ua_info" . 547f9e60319SAndreas Gohr $this->limit; 54844f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 549b6632b6eSAndreas Gohr } 550b6632b6eSAndreas Gohr 551f9e60319SAndreas Gohr /** 552f9e60319SAndreas Gohr * @return array 553f9e60319SAndreas Gohr */ 554f9e60319SAndreas Gohr public function os(): array 555b6632b6eSAndreas Gohr { 55610dcb86fSAndreas Gohr $sql = "SELECT COUNT(DISTINCT S.session) as cnt, S.os 55710dcb86fSAndreas Gohr FROM sessions as S 55844f81330SAndreas Gohr WHERE DATETIME(S.dt, ?) >= ? AND DATETIME(S.dt, ?) <= ? 55930cf9434SAndreas Gohr AND S.ua_type = 'browser' 56010dcb86fSAndreas Gohr GROUP BY S.os 56110dcb86fSAndreas Gohr ORDER BY cnt DESC, S.os" . 562f9e60319SAndreas Gohr $this->limit; 56344f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 564b6632b6eSAndreas Gohr } 565b6632b6eSAndreas Gohr 566f9e60319SAndreas Gohr /** 567f9e60319SAndreas Gohr * @return array 568f9e60319SAndreas Gohr */ 5699fdd7e51SAndreas Gohr public function topdomain(): array 5709fdd7e51SAndreas Gohr { 5719fdd7e51SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, U.domain 5729fdd7e51SAndreas Gohr FROM pageviews as P, 5739fdd7e51SAndreas Gohr sessions as S, 5749fdd7e51SAndreas Gohr users as U 57544f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 5769fdd7e51SAndreas Gohr AND P.session = S.session 5779fdd7e51SAndreas Gohr AND S.user = U.user 57830cf9434SAndreas Gohr AND S.ua_type = 'browser' 5799fdd7e51SAndreas Gohr AND S.user IS NOT NULL 5809fdd7e51SAndreas Gohr GROUP BY U.domain 5819fdd7e51SAndreas Gohr ORDER BY cnt DESC, U.domain" . 5829fdd7e51SAndreas Gohr $this->limit; 58344f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 5849fdd7e51SAndreas Gohr } 5859fdd7e51SAndreas Gohr 5869fdd7e51SAndreas Gohr /** 5879fdd7e51SAndreas Gohr * @return array 5889fdd7e51SAndreas Gohr */ 589f9e60319SAndreas Gohr public function topuser(): array 590b6632b6eSAndreas Gohr { 59110dcb86fSAndreas Gohr $sql = "SELECT COUNT(*) as cnt, S.user 5926f2bdce1SAndreas Gohr FROM pageviews as P, 5936f2bdce1SAndreas Gohr sessions as S 59444f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 5956f2bdce1SAndreas Gohr AND P.session = S.session 59630cf9434SAndreas Gohr AND S.ua_type = 'browser' 597b7091bfdSAndreas Gohr AND S.user IS NOT NULL 59810dcb86fSAndreas Gohr GROUP BY S.user 59910dcb86fSAndreas Gohr ORDER BY cnt DESC, S.user" . 600f9e60319SAndreas Gohr $this->limit; 60144f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 602b6632b6eSAndreas Gohr } 603b6632b6eSAndreas Gohr 604f9e60319SAndreas Gohr /** 605f9e60319SAndreas Gohr * @return array 606f9e60319SAndreas Gohr */ 607f9e60319SAndreas Gohr public function topeditor(): array 608b6632b6eSAndreas Gohr { 609b6632b6eSAndreas Gohr $sql = "SELECT COUNT(*) as cnt, user 6106f2bdce1SAndreas Gohr FROM edits as E, 6116f2bdce1SAndreas Gohr sessions as S 61244f81330SAndreas Gohr WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ? 6136f2bdce1SAndreas Gohr AND E.session = S.session 614b7091bfdSAndreas Gohr AND S.user IS NOT NULL 615b6632b6eSAndreas Gohr GROUP BY user 616b6632b6eSAndreas Gohr ORDER BY cnt DESC, user" . 617f9e60319SAndreas Gohr $this->limit; 61844f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 619b6632b6eSAndreas Gohr } 620b6632b6eSAndreas Gohr 621f9e60319SAndreas Gohr /** 622f9e60319SAndreas Gohr * @return array 623f9e60319SAndreas Gohr */ 624f9e60319SAndreas Gohr public function topgroup(): array 625b6632b6eSAndreas Gohr { 62610dcb86fSAndreas Gohr $sql = "SELECT COUNT(*) as cnt, G.`group` 6276f2bdce1SAndreas Gohr FROM pageviews as P, 6286f2bdce1SAndreas Gohr sessions as S, 6296f2bdce1SAndreas Gohr groups as G 63044f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 6316f2bdce1SAndreas Gohr AND P.session = S.session 6326f2bdce1SAndreas Gohr AND S.user = G.user 63330cf9434SAndreas Gohr AND S.ua_type = 'browser' 63410dcb86fSAndreas Gohr GROUP BY G.`group` 63510dcb86fSAndreas Gohr ORDER BY cnt DESC, G.`group`" . 636f9e60319SAndreas Gohr $this->limit; 63744f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 638b6632b6eSAndreas Gohr } 639b6632b6eSAndreas Gohr 640f9e60319SAndreas Gohr /** 641f9e60319SAndreas Gohr * @return array 642f9e60319SAndreas Gohr */ 643f9e60319SAndreas Gohr public function topgroupedit(): array 644b6632b6eSAndreas Gohr { 64510dcb86fSAndreas Gohr $sql = "SELECT COUNT(*) as cnt, G.`group` 6466f2bdce1SAndreas Gohr FROM edits as E, 6476f2bdce1SAndreas Gohr sessions as S, 6486f2bdce1SAndreas Gohr groups as G 64944f81330SAndreas Gohr WHERE DATETIME(E.dt, ?) >= ? AND DATETIME(E.dt, ?) <= ? 6506f2bdce1SAndreas Gohr AND E.session = S.session 6516f2bdce1SAndreas Gohr AND S.user = G.user 65210dcb86fSAndreas Gohr GROUP BY G.`group` 65310dcb86fSAndreas Gohr ORDER BY cnt DESC, G.`group`" . 654f9e60319SAndreas Gohr $this->limit; 65544f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 656b6632b6eSAndreas Gohr } 657b6632b6eSAndreas Gohr 658b6632b6eSAndreas Gohr 659f9e60319SAndreas Gohr /** 660f9e60319SAndreas Gohr * @return array 661f9e60319SAndreas Gohr */ 662f9e60319SAndreas Gohr public function resolution(): array 663b6632b6eSAndreas Gohr { 66410dcb86fSAndreas Gohr $sql = "SELECT COUNT(DISTINCT S.uid) as cnt, 66510dcb86fSAndreas Gohr ROUND(P.screen_x/100)*100 as res_x, 66610dcb86fSAndreas Gohr ROUND(P.screen_y/100)*100 as res_y, 667bd514593SAndreas Gohr CAST(ROUND(P.screen_x/100)*100 AS int) 668bd514593SAndreas Gohr || 'x' || 669bd514593SAndreas Gohr CAST(ROUND(P.screen_y/100)*100 AS int) as resolution 6706f2bdce1SAndreas Gohr FROM pageviews as P, 6716f2bdce1SAndreas Gohr sessions as S 67244f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 6736f2bdce1SAndreas Gohr AND P.session = S.session 67430cf9434SAndreas Gohr AND S.ua_type = 'browser' 67530cf9434SAndreas Gohr AND P.screen_x != 0 67630cf9434SAndreas Gohr AND P.screen_y != 0 677b6632b6eSAndreas Gohr GROUP BY resolution 678b6632b6eSAndreas Gohr ORDER BY cnt DESC" . 679f9e60319SAndreas Gohr $this->limit; 68044f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 681b6632b6eSAndreas Gohr } 682b6632b6eSAndreas Gohr 683f9e60319SAndreas Gohr /** 684f9e60319SAndreas Gohr * @return array 685f9e60319SAndreas Gohr */ 686f9e60319SAndreas Gohr public function viewport(): array 687b6632b6eSAndreas Gohr { 68810dcb86fSAndreas Gohr $sql = "SELECT COUNT(DISTINCT S.uid) as cnt, 68910dcb86fSAndreas Gohr ROUND(P.view_x/100)*100 as res_x, 69010dcb86fSAndreas Gohr ROUND(P.view_y/100)*100 as res_y, 691bd514593SAndreas Gohr CAST(ROUND(P.view_x/100)*100 AS int) 692bd514593SAndreas Gohr || 'x' || 693bd514593SAndreas Gohr CAST(ROUND(P.view_y/100)*100 AS int) as resolution 6946f2bdce1SAndreas Gohr FROM pageviews as P, 6956f2bdce1SAndreas Gohr sessions as S 69644f81330SAndreas Gohr WHERE DATETIME(P.dt, ?) >= ? AND DATETIME(P.dt, ?) <= ? 6976f2bdce1SAndreas Gohr AND P.session = S.session 69830cf9434SAndreas Gohr AND S.ua_type = 'browser' 69930cf9434SAndreas Gohr AND P.view_x != 0 70030cf9434SAndreas Gohr AND P.view_y != 0 701b6632b6eSAndreas Gohr GROUP BY resolution 702b6632b6eSAndreas Gohr ORDER BY cnt DESC" . 703f9e60319SAndreas Gohr $this->limit; 704b6632b6eSAndreas Gohr 70544f81330SAndreas Gohr return $this->db->queryAll($sql, [$this->tz, $this->from, $this->tz, $this->to]); 706b6632b6eSAndreas Gohr } 707b6632b6eSAndreas Gohr 708f9e60319SAndreas Gohr /** 709f9e60319SAndreas Gohr * @return array 710f9e60319SAndreas Gohr */ 711f9e60319SAndreas Gohr public function seenusers(): array 712b6632b6eSAndreas Gohr { 71310dcb86fSAndreas Gohr $sql = "SELECT `user`, MAX(`dt`) as dt 71410dcb86fSAndreas Gohr FROM users 71510dcb86fSAndreas Gohr WHERE `user` IS NOT NULL 71610dcb86fSAndreas Gohr AND `user` != '' 71710dcb86fSAndreas Gohr GROUP BY `user` 718b6632b6eSAndreas Gohr ORDER BY `dt` DESC" . 719f9e60319SAndreas Gohr $this->limit; 720b6632b6eSAndreas Gohr 721f9e60319SAndreas Gohr return $this->db->queryAll($sql); 722b6632b6eSAndreas Gohr } 723b6632b6eSAndreas Gohr} 724