1<?php
2/**
3 * XOOPS Kernel Class
4 *
5 * You may not change or alter any portion of this comment or credits
6 * of supporting developers from this source code or any supporting source code
7 * which is considered copyrighted (c) material of the original comment or credit authors.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
13 * @license             GNU GPL 2 (http://www.gnu.org/licenses/gpl-2.0.html)
14 * @package             kernel
15 * @since               2.0.0
16 * @author              Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
17 */
18defined('XOOPS_ROOT_PATH') || exit('Restricted access');
19
20/**
21 * A handler for "Who is Online?" information
22 *
23 * @package             kernel
24 *
25 * @author              Kazumi Ono    <onokazu@xoops.org>
26 * @copyright       (c) 2000-2016 XOOPS Project (www.xoops.org)
27 */
28class XoopsOnlineHandler
29{
30    /**
31     * Database connection
32     *
33     * @var object
34     * @access    private
35     */
36    public $db;
37
38    /**
39     * This should be here, since this really should be a XoopsPersistableObjectHandler
40     * Here, we fake it for future compatibility
41     *
42     * @var string table name
43     */
44    public $table;
45
46    /**
47     * Constructor
48     *
49     * @param XoopsDatabase $db {@link XoopsHandlerFactory}
50     */
51    public function __construct(XoopsDatabase $db)
52    {
53        $this->db = $db;
54        $this->table = $this->db->prefix('online');
55    }
56
57    /**
58     * Write online information to the database
59     *
60     * @param int    $uid    UID of the active user
61     * @param string $uname  Username
62     * @param int    $time   Timestamp
63     * @param int    $module Current module id
64     * @param string $ip     User's IP address
65     *
66     * @internal param string $timestamp
67     * @return bool TRUE on success
68     */
69    public function write($uid, $uname, $time, $module, $ip)
70    {
71        $uid = (int) $uid;
72        $uname = $this->db->quote($uname);
73        $time = (int) $time;
74        $module = (int) $module;
75        $ip = $this->db->quote($ip);
76
77        if ($uid > 0) {
78            $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('online') . " WHERE online_uid={$uid}";
79        } else {
80            $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('online')
81                   . " WHERE online_uid={$uid} AND online_ip={$ip}";
82        }
83        list($count) = $this->db->fetchRow($this->db->queryF($sql));
84        if ($count > 0) {
85            $sql = 'UPDATE ' . $this->db->prefix('online')
86                   . " SET online_updated = {$time}, online_module = {$module} WHERE online_uid = {$uid}";
87            if ($uid === 0) {
88                $sql .= " AND online_ip={$ip}";
89            }
90        } else {
91            $sql = sprintf(
92                'INSERT INTO %s (online_uid, online_uname, online_updated, online_ip, online_module)'
93                . ' VALUES (%u, %s, %u, %s, %u)',
94                $this->db->prefix('online'),
95                $uid,
96                $uname,
97                $time,
98                $ip,
99                $module
100            );
101        }
102        if (!$this->db->queryF($sql)) {
103            return false;
104        }
105
106        return true;
107    }
108
109    /**
110     * Delete online information for a user
111     *
112     * @param int $uid UID
113     *
114     * @return bool TRUE on success
115     */
116    public function destroy($uid)
117    {
118        $sql = sprintf('DELETE FROM %s WHERE online_uid = %u', $this->db->prefix('online'), $uid);
119        if (!$result = $this->db->queryF($sql)) {
120            return false;
121        }
122
123        return true;
124    }
125
126    /**
127     * Garbage Collection
128     *
129     * Delete all online information that has not been updated for a certain time
130     *
131     * @param int $expire Expiration time in seconds
132     */
133    public function gc($expire)
134    {
135        $sql = sprintf(
136            'DELETE FROM %s WHERE online_updated < %u',
137            $this->db->prefix('online'),
138            time() - (int)$expire
139        );
140        $this->db->queryF($sql);
141    }
142
143    /**
144     * Get an array of online information
145     *
146     * @param  CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
147     * @return array  Array of associative arrays of online information
148     */
149    public function getAll(CriteriaElement $criteria = null)
150    {
151        $ret   = array();
152        $limit = $start = 0;
153        $sql   = 'SELECT * FROM ' . $this->db->prefix('online');
154        if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
155            $sql .= ' ' . $criteria->renderWhere();
156            $limit = $criteria->getLimit();
157            $start = $criteria->getStart();
158        }
159        $result = $this->db->query($sql, $limit, $start);
160        if (!$result) {
161            return false;
162        }
163        while (false !== ($myrow = $this->db->fetchArray($result))) {
164            $ret[] = $myrow;
165            unset($myrow);
166        }
167
168        return $ret;
169    }
170
171    /**
172     * Count the number of online users
173     *
174     * @param CriteriaElement|CriteriaCompo $criteria {@link CriteriaElement}
175     *
176     * @return bool
177     */
178    public function getCount(CriteriaElement $criteria = null)
179    {
180        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('online');
181        if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
182            $sql .= ' ' . $criteria->renderWhere();
183        }
184        if (!$result = $this->db->query($sql)) {
185            return false;
186        }
187        list($ret) = $this->db->fetchRow($result);
188
189        return $ret;
190    }
191}
192