hlp = $hlp; } /** * Return some aggregated statistics */ public function aggregate($tlimit) { $data = array(); $sql = "SELECT ref_type, COUNT(*) as cnt FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY ref_type"; $result = $this->hlp->runSQL($sql); if(is_array($result)) foreach($result as $row) { if($row['ref_type'] == 'search') $data['search'] = $row['cnt']; if($row['ref_type'] == 'external') $data['external'] = $row['cnt']; if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt']; if($row['ref_type'] == '') $data['direct'] = $row['cnt']; } // general user and session info $sql = "SELECT COUNT(DISTINCT session) as sessions, COUNT(session) as views, COUNT(DISTINCT user) as users, COUNT(DISTINCT uid) as visitors FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser'"; $result = $this->hlp->runSQL($sql); $data['users'] = max($result[0]['users'] - 1, 0); // subtract empty user $data['sessions'] = $result[0]['sessions']; $data['pageviews'] = $result[0]['views']; $data['visitors'] = $result[0]['visitors']; // calculate bounce rate if($data['sessions']) { $sql = "SELECT COUNT(*) as cnt FROM " . $this->hlp->prefix . "session as A WHERE $tlimit AND views = 1"; $result = $this->hlp->runSQL($sql); $data['bouncerate'] = $result[0]['cnt'] * 100 / $data['sessions']; // new visitors $result = "SELECT COUNT(*) as cnt FROM " . $this->hlp->prefix . "session as A WHERE $tlimit AND NOT EXISTS ( SELECT * FROM stats_session B WHERE A.session <> B.session AND B.uid = B.uid )"; $result = $this->hlp->runSQL($sql); $data['newvisitors'] = $result[0]['cnt'] * 100 / $data['sessions']; } // calculate avg. number of views per session $sql = "SELECT AVG(views) as cnt FROM " . $this->hlp->prefix . "session as A WHERE $tlimit"; $result = $this->hlp->runSQL($sql); $data['avgpages'] = $result[0]['cnt']; /* not used currently $sql = "SELECT COUNT(id) as robots FROM ".$this->hlp->prefix."access as A WHERE $tlimit AND ua_type = 'robot'"; $result = $this->hlp->runSQL($sql); $data['robots'] = $result[0]['robots']; */ // average time spent on the site $sql = "SELECT AVG(end - dt)/60 as time FROM " . $this->hlp->prefix . "session as A WHERE $tlimit AND dt != end AND DATE(dt) = DATE(end)"; $result = $this->hlp->runSQL($sql); $data['timespent'] = $result[0]['time']; // logins $sql = "SELECT COUNT(*) as logins FROM " . $this->hlp->prefix . "logins as A WHERE $tlimit AND (type = 'l' OR type = 'p')"; $result = $this->hlp->runSQL($sql); $data['logins'] = $result[0]['logins']; // registrations $sql = "SELECT COUNT(*) as registrations FROM " . $this->hlp->prefix . "logins as A WHERE $tlimit AND type = 'C'"; $result = $this->hlp->runSQL($sql); $data['registrations'] = $result[0]['registrations']; // current users $sql = "SELECT COUNT(*) as current FROM ". $this->hlp->prefix . "lastseen WHERE `dt` >= NOW() - INTERVAL 10 MINUTE"; $result = $this->hlp->runSQL($sql); $data['current'] = $result[0]['current']; return $data; } /** * standard statistics follow, only accesses made by browsers are counted * for general stats like browser or OS only visitors not pageviews are counted */ /** * Return some trend data about visits and edits in the wiki */ public function dashboardviews($tlimit, $hours = false) { if($hours) { $TIME = 'HOUR(dt)'; } else { $TIME = 'DATE(dt)'; } $data = array(); // access trends $sql = "SELECT $TIME as time, COUNT(DISTINCT session) as sessions, COUNT(session) as pageviews, COUNT(DISTINCT uid) as visitors FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY $TIME ORDER BY time"; $result = $this->hlp->runSQL($sql); foreach($result as $row) { $data[$row['time']]['sessions'] = $row['sessions']; $data[$row['time']]['pageviews'] = $row['pageviews']; $data[$row['time']]['visitors'] = $row['visitors']; } return $data; } public function dashboardwiki($tlimit, $hours = false) { if($hours) { $TIME = 'HOUR(dt)'; } else { $TIME = 'DATE(dt)'; } $data = array(); // edit trends foreach(array('E', 'C', 'D') as $type) { $sql = "SELECT $TIME as time, COUNT(*) as cnt FROM " . $this->hlp->prefix . "edits as A WHERE $tlimit AND type = '$type' GROUP BY $TIME ORDER BY time"; $result = $this->hlp->runSQL($sql); foreach($result as $row) { $data[$row['time']][$type] = $row['cnt']; } } ksort($data); return $data; } public function history($tlimit, $info, $interval = false) { if($interval == 'weeks') { $TIME = 'EXTRACT(YEAR FROM dt), EXTRACT(WEEK FROM dt)'; } elseif ($interval == 'months') { $TIME = 'EXTRACT(YEAR_MONTH FROM dt)'; } else { $TIME = 'dt'; } $mod = 1; if($info == 'media_size' || $info == 'page_size') { $mod = 1024*1024; } $sql = "SELECT $TIME as time, AVG(`value`)/$mod as cnt FROM " . $this->hlp->prefix . "history as A WHERE $tlimit AND info = '$info' GROUP BY $TIME ORDER BY $TIME"; return $this->hlp->runSQL($sql); } public function searchengines($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, engine as eflag, engine FROM " . $this->hlp->prefix . "search as A WHERE $tlimit GROUP BY engine ORDER BY cnt DESC, engine" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function searchphrases($extern, $tlimit, $start = 0, $limit = 20) { if($extern) { $WHERE = "engine != 'dokuwiki'"; $I = ''; } else { $WHERE = "engine = 'dokuwiki'"; $I = 'i'; } $sql = "SELECT COUNT(*) as cnt, query, query as ${I}lookup FROM " . $this->hlp->prefix . "search as A WHERE $tlimit AND $WHERE GROUP BY query ORDER BY cnt DESC, query" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function searchwords($extern, $tlimit, $start = 0, $limit = 20) { if($extern) { $WHERE = "engine != 'dokuwiki'"; $I = ''; } else { $WHERE = "engine = 'dokuwiki'"; $I = 'i'; } $sql = "SELECT COUNT(*) as cnt, word, word as ${I}lookup FROM " . $this->hlp->prefix . "search as A, " . $this->hlp->prefix . "searchwords as B WHERE $tlimit AND A.id = B.sid AND $WHERE GROUP BY word ORDER BY cnt DESC, word" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function outlinks($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, link as url FROM " . $this->hlp->prefix . "outlinks as A WHERE $tlimit GROUP BY link ORDER BY cnt DESC, link" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function pages($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, page FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY page ORDER BY cnt DESC, page" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function edits($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, page FROM " . $this->hlp->prefix . "edits as A WHERE $tlimit GROUP BY page ORDER BY cnt DESC, page" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function images($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize FROM " . $this->hlp->prefix . "media as A WHERE $tlimit AND mime1 = 'image' GROUP BY media ORDER BY cnt DESC, media" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function imagessum($tlimit) { $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize FROM " . $this->hlp->prefix . "media as A WHERE $tlimit AND mime1 = 'image'"; return $this->hlp->runSQL($sql); } public function downloads($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, media, SUM(size) as filesize FROM " . $this->hlp->prefix . "media as A WHERE $tlimit AND mime1 != 'image' GROUP BY media ORDER BY cnt DESC, media" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function downloadssum($tlimit) { $sql = "SELECT COUNT(*) as cnt, SUM(size) as filesize FROM " . $this->hlp->prefix . "media as A WHERE $tlimit AND mime1 != 'image'"; return $this->hlp->runSQL($sql); } public function referer($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, ref as url FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' AND ref_type = 'external' GROUP BY ref_md5 ORDER BY cnt DESC, url" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function newreferer($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, ref as url FROM " . $this->hlp->prefix . "access as B, " . $this->hlp->prefix . "refseen as A WHERE $tlimit AND ua_type = 'browser' AND ref_type = 'external' AND A.ref_md5 = B.ref_md5 GROUP BY A.ref_md5 ORDER BY cnt DESC, url" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function countries($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country FROM " . $this->hlp->prefix . "access as A, " . $this->hlp->prefix . "iplocation as B WHERE $tlimit AND A.ip = B.ip GROUP BY B.code ORDER BY cnt DESC, B.country" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function browsers($tlimit, $start = 0, $limit = 20, $ext = true) { if($ext) { $sel = 'ua_info as bflag, ua_info as browser, ua_ver'; $grp = 'ua_info, ua_ver'; } else { $grp = 'ua_info'; $sel = 'ua_info'; } $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY $grp ORDER BY cnt DESC, ua_info" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function os($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' GROUP BY os ORDER BY cnt DESC, os" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function topuser($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, user FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' AND user != '' GROUP BY user ORDER BY cnt DESC, user" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function topeditor($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, user FROM " . $this->hlp->prefix . "edits as A WHERE $tlimit AND user != '' GROUP BY user ORDER BY cnt DESC, user" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function topgroup($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, `group` FROM " . $this->hlp->prefix . "groups as A WHERE $tlimit AND `type` = 'view' GROUP BY `group` ORDER BY cnt DESC, `group`" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function topgroupedit($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(*) as cnt, `group` FROM " . $this->hlp->prefix . "groups as A WHERE $tlimit AND `type` = 'edit' GROUP BY `group` ORDER BY cnt DESC, `group`" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function resolution($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(DISTINCT uid) as cnt, ROUND(screen_x/100)*100 as res_x, ROUND(screen_y/100)*100 as res_y, CONCAT(ROUND(screen_x/100)*100,'x',ROUND(screen_y/100)*100) as resolution FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' AND screen_x != 0 AND screen_y != 0 GROUP BY resolution ORDER BY cnt DESC" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function viewport($tlimit, $start = 0, $limit = 20) { $sql = "SELECT COUNT(DISTINCT uid) as cnt, ROUND(view_x/100)*100 as res_x, ROUND(view_y/100)*100 as res_y, CONCAT(ROUND(view_x/100)*100,'x',ROUND(view_y/100)*100) as resolution FROM " . $this->hlp->prefix . "access as A WHERE $tlimit AND ua_type = 'browser' AND view_x != 0 AND view_y != 0 GROUP BY resolution ORDER BY cnt DESC" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } public function seenusers($tlimit, $start = 0, $limit = 20) { $sql = "SELECT `user`, `dt` FROM " . $this->hlp->prefix . "lastseen as A ORDER BY `dt` DESC" . $this->mklimit($start, $limit); return $this->hlp->runSQL($sql); } /** * Builds a limit clause */ public function mklimit($start, $limit) { $start = (int) $start; $limit = (int) $limit; if($limit) { $limit += 1; return " LIMIT $start,$limit"; } elseif($start) { return " OFFSET $start"; } return ''; } /** * Create a time limit for use in SQL */ public function mktlimit(&$from, &$to) { // fixme add better sanity checking here: $from = preg_replace('/[^\d\-]+/', '', $from); $to = preg_replace('/[^\d\-]+/', '', $to); if(!$from) $from = date('Y-m-d'); if(!$to) $to = date('Y-m-d'); return "A.dt >= '$from 00:00:00' AND A.dt <= '$to 23:59:59'"; } }