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 (https://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: */
18: defined('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: */
28: class 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: $result = $this->db->queryF($sql);
84: if (!$this->db->isResultSet($result)) {
85: throw new \RuntimeException(
86: \sprintf(_DB_QUERY_ERROR, $sql) . $this->db->error(), E_USER_ERROR
87: );
88: }
89:
90: list($count) = $this->db->fetchRow($result);
91: if ($count > 0) {
92: $sql = 'UPDATE ' . $this->db->prefix('online')
93: . " SET online_updated = {$time}, online_module = {$module} WHERE online_uid = {$uid}";
94: if ($uid === 0) {
95: $sql .= " AND online_ip={$ip}";
96: }
97: } else {
98: if ($uid != 0) {
99: // this condition (no entry for a real user) exists when a user first signs in
100: // first, cleanup the uid == 0 row the user generated before signing in
101: $loginSql = sprintf('DELETE FROM %s WHERE online_uid = 0 AND online_ip=%s', $this->db->prefix('online'), $ip);
102: $this->db->queryF($loginSql);
103: }
104: $sql = sprintf(
105: 'INSERT INTO %s (online_uid, online_uname, online_updated, online_ip, online_module)'
106: . ' VALUES (%u, %s, %u, %s, %u)',
107: $this->db->prefix('online'),
108: $uid,
109: $uname,
110: $time,
111: $ip,
112: $module
113: );
114: }
115: if (!$this->db->queryF($sql)) {
116: return false;
117: }
118:
119: return true;
120: }
121:
122: /**
123: * Delete online information for a user
124: *
125: * @param int $uid UID
126: *
127: * @return bool TRUE on success
128: */
129: public function destroy($uid)
130: {
131: $sql = sprintf('DELETE FROM %s WHERE online_uid = %u', $this->db->prefix('online'), $uid);
132: if (!$result = $this->db->queryF($sql)) {
133: return false;
134: }
135:
136: return true;
137: }
138:
139: /**
140: * Garbage Collection
141: *
142: * Delete all online information that has not been updated for a certain time
143: *
144: * @param int $expire Expiration time in seconds
145: */
146: public function gc($expire)
147: {
148: $sql = sprintf(
149: 'DELETE FROM %s WHERE online_updated < %u',
150: $this->db->prefix('online'),
151: time() - (int)$expire
152: );
153: $this->db->queryF($sql);
154: }
155:
156: /**
157: * Get an array of online information
158: *
159: * @param CriteriaElement|CriteriaCompo|null $criteria {@link CriteriaElement}
160: * @return array|false Array of associative arrays of online information
161: */
162: public function getAll(CriteriaElement $criteria = null)
163: {
164: $ret = array();
165: $limit = $start = 0;
166: $sql = 'SELECT * FROM ' . $this->db->prefix('online');
167: if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
168: $sql .= ' ' . $criteria->renderWhere();
169: $limit = $criteria->getLimit();
170: $start = $criteria->getStart();
171: }
172: $result = $this->db->query($sql, $limit, $start);
173: if (!$this->db->isResultSet($result)) {
174: return $ret;
175: }
176: while (false !== ($myrow = $this->db->fetchArray($result))) {
177: $ret[] = $myrow;
178: unset($myrow);
179: }
180:
181: return $ret;
182: }
183:
184: /**
185: * Count the number of online users
186: *
187: * @param CriteriaElement|CriteriaCompo|null $criteria {@link CriteriaElement}
188: *
189: * @return int
190: */
191: public function getCount(CriteriaElement $criteria = null)
192: {
193: $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('online');
194: if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
195: $sql .= ' ' . $criteria->renderWhere();
196: }
197: $result = $this->db->query($sql);
198: if (!$this->db->isResultSet($result)) {
199: return 0;
200: }
201: list($ret) = $this->db->fetchRow($result);
202:
203: return (int)$ret;
204: }
205: }
206: