Passed
Push — master ( 33c64b...8d1135 )
by Michael
03:38
created

class/OnlineHandler.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace XoopsModules\Newbb;
4
5
/**
6
 * NewBB 5.0x,  the forum module for XOOPS project
7
 *
8
 * @copyright      XOOPS Project (https://xoops.org)
9
 * @license        GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
10
 * @author         Taiwen Jiang (phppp or D.J.) <[email protected]>
11
 * @since          4.00
12
 * @package        module::newbb
13
 */
14
15
use Xmf\IPAddress;
16
use XoopsModules\Newbb;
17
18
// defined('XOOPS_ROOT_PATH') || die('Restricted access');
19
20
require_once dirname(__DIR__) . '/include/functions.config.php';
21
22
/**
23
 * Class OnlineHandler
24
 */
25
class OnlineHandler
26
{
27
    public $db;
28
    public $forum_id;
29
    public $forumObject;
30
    public $topic_id;
31
    public $user_ids = [];
32
33
    /**
34
     * OnlineHandler constructor.
35
     * @param \XoopsDatabase|null $db
36
     */
37
    public function __construct(\XoopsDatabase $db = null)
38
    {
39
        $this->db = $db;
40
    }
41
42
    /**
43
     * @param null|Newbb\Forum $forum
44
     * @param null|Topic       $forumtopic
45
     */
46
    public function init($forum = null, $forumtopic = null)
47
    {
48
        if (is_object($forum)) {
49
            $this->forum_id    = $forum->getVar('forum_id');
50
            $this->forumObject = $forum;
51
        } else {
52
            $this->forum_id    = (int)$forum;
53
            $this->forumObject = $forum;
54
        }
55
        if (is_object($forumtopic)) {
56
            $this->topic_id = $forumtopic->getVar('topic_id');
57
            if (empty($this->forum_id)) {
58
                $this->forum_id = $forumtopic->getVar('forum_id');
59
            }
60
        } else {
61
            $this->topic_id = (int)$forumtopic;
62
        }
63
64
        $this->update();
65
    }
66
67
    public function update()
68
    {
69
        global $xoopsModule;
70
71
        mt_srand((float)microtime() * 1000000);
0 ignored issues
show
(double)microtime() * 1000000 of type double is incompatible with the type integer expected by parameter $seed of mt_srand(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
        mt_srand(/** @scrutinizer ignore-type */ (float)microtime() * 1000000);
Loading history...
72
        // set gc probabillity to 10% for now..
73
        if (mt_rand(1, 100) < 60) {
74
            $this->gc(150);
75
        }
76
        if (is_object($GLOBALS['xoopsUser'])) {
77
            $uid   = $GLOBALS['xoopsUser']->getVar('uid');
78
            $uname = $GLOBALS['xoopsUser']->getVar('uname');
79
            $name  = $GLOBALS['xoopsUser']->getVar('name');
80
        } else {
81
            $uid   = 0;
82
            $uname = '';
83
            $name  = '';
84
        }
85
86
        $xoops_onlineHandler = xoops_getHandler('online');
87
        $xoopsupdate         = $xoops_onlineHandler->write($uid, $uname, time(), $xoopsModule->getVar('mid'), \Xmf\IPAddress::fromRequest()->asReadable());
88
        if (!$xoopsupdate) {
89
            //xoops_error("newbb online upate error");
90
        }
91
92
        $uname = (empty($GLOBALS['xoopsModuleConfig']['show_realname']) || empty($name)) ? $uname : $name;
93
        $this->write($uid, $uname, time(), $this->forum_id, IPAddress::fromRequest()->asReadable(), $this->topic_id);
94
    }
95
96
    /**
97
     * @param $xoopsTpl
98
     */
99
    public function render(\Smarty $xoopsTpl)
100
    {
101
        require_once dirname(__DIR__) . '/include/functions.render.php';
102
        require_once dirname(__DIR__) . '/include/functions.user.php';
103
        $criteria = null;
104
        if ($this->topic_id) {
105
            $criteria = new \Criteria('online_topic', $this->topic_id);
106
        } elseif ($this->forum_id) {
107
            $criteria = new \Criteria('online_forum', $this->forum_id);
108
        }
109
        $users     = $this->getAll($criteria);
110
        $num_total = count($users);
111
112
        $num_user     = 0;
113
        $users_id     = [];
114
        $users_online = [];
115
        for ($i = 0; $i < $num_total; ++$i) {
116
            if (empty($users[$i]['online_uid'])) {
117
                continue;
118
            }
119
            $users_id[]                             = $users[$i]['online_uid'];
120
            $users_online[$users[$i]['online_uid']] = [
121
                'link'  => XOOPS_URL . '/userinfo.php?uid=' . $users[$i]['online_uid'],
122
                'uname' => $users[$i]['online_uname'],
123
            ];
124
            ++$num_user;
125
        }
126
        $num_anonymous           = $num_total - $num_user;
127
        $online                  = [];
128
        $online['image']         = newbbDisplayImage('whosonline');
129
        $online['num_total']     = $num_total;
130
        $online['num_user']      = $num_user;
131
        $online['num_anonymous'] = $num_anonymous;
132
        $administrator_list      = newbbIsModuleAdministrators($users_id);
133
        $moderator_list          = [];
134
        if ($member_list = array_diff(array_keys($administrator_list), $users_id)) {
135
            if (is_object($this->forumObject)) {
136
                $moderator_list = $this->forumObject->getVar('forum_moderator');
137
            } else {
138
                $moderator_list = newbbIsForumModerators($member_list);
139
            }
140
        }
141
        foreach ($users_online as $uid => $user) {
142
            if (!empty($administrator_list[$uid])) {
143
                $user['level'] = 2;
144
            } elseif (!empty($moderator_list[$uid])) {
145
                $user['level'] = 1;
146
            } else {
147
                $user['level'] = 0;
148
            }
149
            $online['users'][] = $user;
150
        }
151
152
        $xoopsTpl->assign_by_ref('online', $online);
153
    }
154
155
    /**
156
     * Deprecated
157
     */
158
    public function showOnline()
159
    {
160
        require_once dirname(__DIR__) . '/include/functions.render.php';
161
        require_once dirname(__DIR__) . '/include/functions.user.php';
162
        $criteria = null;
163
        if ($this->topic_id) {
164
            $criteria = new \Criteria('online_topic', $this->topic_id);
165
        } elseif ($this->forum_id) {
166
            $criteria = new \Criteria('online_forum', $this->forum_id);
167
        }
168
        $users     = $this->getAll($criteria);
169
        $num_total = count($users);
170
171
        $num_user     = 0;
172
        $users_id     = [];
173
        $users_online = [];
174
        for ($i = 0; $i < $num_total; ++$i) {
175
            if (empty($users[$i]['online_uid'])) {
176
                continue;
177
            }
178
            $users_id[]                             = $users[$i]['online_uid'];
179
            $users_online[$users[$i]['online_uid']] = [
180
                'link'  => XOOPS_URL . '/userinfo.php?uid=' . $users[$i]['online_uid'],
181
                'uname' => $users[$i]['online_uname'],
182
            ];
183
            ++$num_user;
184
        }
185
        $num_anonymous           = $num_total - $num_user;
186
        $online                  = [];
187
        $online['image']         = newbbDisplayImage('whosonline');
188
        $online['statistik']     = newbbDisplayImage('statistik');
189
        $online['num_total']     = $num_total;
190
        $online['num_user']      = $num_user;
191
        $online['num_anonymous'] = $num_anonymous;
192
        $administrator_list      = newbbIsModuleAdministrators($users_id);
193
        $moderator_list          = [];
194
        if ($member_list = array_diff($users_id, array_keys($administrator_list))) {
195
            if (is_object($this->forumObject)) {
196
                $moderator_list = $this->forumObject->getVar('forum_moderator');
197
            } else {
198
                $moderator_list = newbbIsForumModerators($member_list);
199
            }
200
        }
201
202
        foreach ($users_online as $uid => $user) {
203
            if (in_array($uid, $administrator_list, true)) {
204
                $user['level'] = 2;
205
            } elseif (in_array($uid, $moderator_list, true)) {
206
                $user['level'] = 1;
207
            } else {
208
                $user['level'] = 0;
209
            }
210
            $online['users'][] = $user;
211
        }
212
213
        return $online;
214
    }
215
216
    /**
217
     * Write online information to the database
218
     *
219
     * @param  int    $uid      UID of the active user
220
     * @param  string $uname    Username
221
     * @param         $time
222
     * @param  string $forum_id Current forum_id
223
     * @param  string $ip       User's IP adress
224
     * @param         $topic_id
225
     * @return bool   TRUE on success
226
     * @internal param string $timestamp
227
     */
228
    public function write($uid, $uname, $time, $forum_id, $ip, $topic_id)
229
    {
230
        global $xoopsModule, $xoopsDB;
231
232
        $uid = (int)$uid;
233
        if ($uid > 0) {
234
            $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('newbb_online') . ' WHERE online_uid=' . $uid;
235
        } else {
236
            $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('newbb_online') . ' WHERE online_uid=' . $uid . " AND online_ip='" . $ip . "'";
237
        }
238
        list($count) = $this->db->fetchRow($this->db->queryF($sql));
239
        if ($count > 0) {
240
            $sql = 'UPDATE ' . $this->db->prefix('newbb_online') . " SET online_updated= '" . $time . "', online_forum = '" . $forum_id . "', online_topic = '" . $topic_id . "' WHERE online_uid = " . $uid;
241
            if (0 == $uid) {
242
                $sql .= " AND online_ip='" . $ip . "'";
243
            }
244
        } else {
245
            $sql = sprintf('INSERT INTO `%s` (online_uid, online_uname, online_updated, online_ip, online_forum, online_topic) VALUES (%u, %s, %u, %s, %u, %u)', $this->db->prefix('newbb_online'), $uid, $this->db->quote($uname), $time, $this->db->quote($ip), $forum_id, $topic_id);
246
        }
247
        if (!$this->db->queryF($sql)) {
248
            //xoops_error($this->db->error());
249
            return false;
250
        }
251
252
        /** @var \XoopsOnlineHandler $xoops_onlineHandler */
253
        $xoops_onlineHandler = xoops_getHandler('online');
254
        $xoopsOnlineTable    = $xoops_onlineHandler->table;
255
256
        $sql = 'DELETE FROM '
257
               . $this->db->prefix('newbb_online')
258
               . ' WHERE'
259
               . ' ( online_uid > 0 AND online_uid NOT IN ( SELECT online_uid FROM '
260
               . $xoopsOnlineTable
261
               . ' WHERE online_module ='
262
               . $xoopsModule->getVar('mid')
263
               . ' ) )'
264
               . ' OR ( online_uid = 0 AND online_ip NOT IN ( SELECT online_ip FROM '
265
               . $xoopsOnlineTable
266
               . ' WHERE online_module ='
267
               . $xoopsModule->getVar('mid')
268
               . ' AND online_uid = 0 ) )';
269
270
        if ($result = $this->db->queryF($sql)) {
271
            return true;
272
        }
273
        //xoops_error($this->db->error());
274
        return false;
275
    }
276
277
    /**
278
     * Garbage Collection
279
     *
280
     * Delete all online information that has not been updated for a certain time
281
     *
282
     * @param int $expire Expiration time in seconds
283
     */
284
    public function gc($expire)
285
    {
286
        global $xoopsModule;
287
        $sql = 'DELETE FROM ' . $this->db->prefix('newbb_online') . ' WHERE online_updated < ' . (time() - (int)$expire);
288
        $this->db->queryF($sql);
289
290
        $xoops_onlineHandler = xoops_getHandler('online');
291
        $xoops_onlineHandler->gc($expire);
292
    }
293
294
    /**
295
     * Get an array of online information
296
     *
297
     * @param  \CriteriaElement $criteria {@link \CriteriaElement}
298
     * @return array           Array of associative arrays of online information
299
     */
300
    public function getAll(\CriteriaElement $criteria = null)
301
    {
302
        $ret   = [];
303
        $limit = $start = 0;
304
        $sql   = 'SELECT * FROM ' . $this->db->prefix('newbb_online');
305
        if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
306
            $sql   .= ' ' . $criteria->renderWhere();
307
            $limit = $criteria->getLimit();
308
            $start = $criteria->getStart();
309
        }
310
        $result = $this->db->query($sql, $limit, $start);
311
        if (!$result) {
312
            return $ret;
313
        }
314
        while (false !== ($myrow = $this->db->fetchArray($result))) {
315
            $ret[] = $myrow;
316
            if ($myrow['online_uid'] > 0) {
317
                $this->user_ids[] = $myrow['online_uid'];
318
            }
319
            unset($myrow);
320
        }
321
        $this->user_ids = array_unique($this->user_ids);
322
323
        return $ret;
324
    }
325
326
    /**
327
     * @param $uids
328
     * @return array
329
     */
330
    public function checkStatus($uids)
331
    {
332
        $online_users = [];
333
        $ret          = [];
334
        if (!empty($this->user_ids)) {
335
            $online_users = $this->user_ids;
336
        } else {
337
            $sql = 'SELECT online_uid FROM ' . $this->db->prefix('newbb_online');
338
            if (!empty($uids)) {
339
                $sql .= ' WHERE online_uid IN (' . implode(', ', array_map('intval', $uids)) . ')';
340
            }
341
342
            $result = $this->db->query($sql);
343
            if (!$result) {
344
                return $ret;
345
            }
346
            while (false !== (list($uid) = $this->db->fetchRow($result))) {
347
                $online_users[] = $uid;
348
            }
349
        }
350
        foreach ($uids as $uid) {
351
            if (in_array($uid, $online_users, true)) {
352
                $ret[$uid] = 1;
353
            }
354
        }
355
356
        return $ret;
357
    }
358
359
    /**
360
     * Count the number of online users
361
     *
362
     * @param  \CriteriaElement $criteria {@link CriteriaElement}
363
     * @return bool
364
     */
365
    public function getCount(\CriteriaElement $criteria = null)
366
    {
367
        $sql = 'SELECT COUNT(*) FROM ' . $this->db->prefix('newbb_online');
368
        if (is_object($criteria) && is_subclass_of($criteria, 'CriteriaElement')) {
369
            $sql .= ' ' . $criteria->renderWhere();
370
        }
371
        if (!$result = $this->db->query($sql)) {
372
            return false;
373
        }
374
        list($ret) = $this->db->fetchRow($result);
375
376
        return $ret;
377
    }
378
}
379