183 lines
6.3 KiB
PHP
183 lines
6.3 KiB
PHP
<?php
|
|
|
|
namespace ForkBB\Models;
|
|
|
|
use ForkBB\Models\Model;
|
|
use ForkBB\Models\User\Model as User;
|
|
use ForkBB\Models\Page;
|
|
|
|
class Online extends Model
|
|
{
|
|
/**
|
|
* Обработка данных пользователей онлайн
|
|
* Обновление данных текущего пользователя
|
|
* Возврат данных по пользователям онлайн
|
|
*
|
|
* @param Page $page
|
|
*
|
|
* @return Online
|
|
*/
|
|
public function calc(Page $page)
|
|
{
|
|
if ($this->done) {
|
|
return $this;
|
|
}
|
|
$this->done = true;
|
|
|
|
$position = $page->onlinePos;
|
|
if (null === $position) {
|
|
return $this;
|
|
}
|
|
$detail = $page->onlineDetail && $this->c->config->o_users_online == '1';
|
|
$filter = $page->onlineFilter;
|
|
|
|
$this->updateUser($position);
|
|
|
|
$all = 0;
|
|
$now = \time();
|
|
$tOnline = $now - $this->c->config->o_timeout_online;
|
|
$tVisit = $now - $this->c->config->o_timeout_visit;
|
|
$online = [];
|
|
$users = [];
|
|
$guests = [];
|
|
$bots = [];
|
|
$deleteG = false;
|
|
$deleteU = false;
|
|
|
|
if ($detail) {
|
|
$sql = 'SELECT o.user_id, o.ident, o.logged, o.o_position, o.o_name FROM ::online AS o ORDER BY o.logged';
|
|
} else {
|
|
$sql = 'SELECT o.user_id, o.ident, o.logged FROM ::online AS o ORDER BY o.logged';
|
|
}
|
|
$stmt = $this->c->DB->query($sql);
|
|
|
|
while ($cur = $stmt->fetch()) {
|
|
// посетитель уже не онлайн (или почти не онлайн)
|
|
if ($cur['logged'] < $tOnline) {
|
|
// пользователь
|
|
if ($cur['user_id'] > 1) {
|
|
if ($cur['logged'] < $tVisit) {
|
|
$deleteU = true;
|
|
$this->c->DB->exec('UPDATE ::users SET last_visit=?i:last WHERE id=?i:id', [':last' => $cur['logged'], ':id' => $cur['user_id']]); //????
|
|
}
|
|
// гость
|
|
} else {
|
|
$deleteG = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// пользователи онлайн и общее количество
|
|
$online[$cur['user_id']] = true;
|
|
++$all;
|
|
|
|
if (! $detail) {
|
|
continue;
|
|
}
|
|
|
|
// включен фильтр и проверка не пройдена
|
|
if ($filter && $cur['o_position'] !== $position) {
|
|
continue;
|
|
}
|
|
|
|
// пользователь
|
|
if ($cur['user_id'] > 1) {
|
|
$users[$cur['user_id']] = [
|
|
'name' => $cur['ident'],
|
|
'logged' => $cur['logged'],
|
|
];
|
|
// гость
|
|
} elseif ($cur['o_name'] == '') {
|
|
$guests[] = [
|
|
'name' => $cur['ident'],
|
|
'logged' => $cur['logged'],
|
|
];
|
|
// бот
|
|
} else {
|
|
$bots[$cur['o_name']][] = [
|
|
'name' => $cur['ident'],
|
|
'logged' => $cur['logged'],
|
|
];
|
|
}
|
|
}
|
|
|
|
// удаление просроченных пользователей
|
|
if ($deleteU) {
|
|
$this->c->DB->exec('DELETE FROM ::online WHERE logged<?i:visit', [':visit' => $tVisit]);
|
|
}
|
|
|
|
// удаление просроченных гостей
|
|
if ($deleteG) {
|
|
$this->c->DB->exec('DELETE FROM ::online WHERE user_id=1 AND logged<?i:online', [':online' => $tOnline]);
|
|
}
|
|
|
|
// обновление максимального значение пользоватеелй онлайн
|
|
if ($this->c->config->st_max_users < $all) {
|
|
$this->c->config->st_max_users = $all;
|
|
$this->c->config->st_max_users_time = $now;
|
|
$this->c->config->save();
|
|
}
|
|
|
|
$this->all = $all;
|
|
$this->detail = $detail;
|
|
|
|
unset($online[1]);
|
|
$this->online = $online;
|
|
|
|
if ($detail) {
|
|
$this->users = $users;
|
|
$this->guests = $guests;
|
|
$this->bots = $bots;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Обновление данных текущего пользователя
|
|
*
|
|
* @param string $position
|
|
*/
|
|
protected function updateUser($position)
|
|
{
|
|
// гость
|
|
if ($this->c->user->isGuest) {
|
|
$vars = [
|
|
':logged' => \time(),
|
|
':pos' => $position,
|
|
':name' => (string) $this->c->user->isBot,
|
|
':ip' => $this->c->user->ip
|
|
];
|
|
if ($this->c->user->isLogged) {
|
|
$this->c->DB->exec('UPDATE ::online SET logged=?i:logged, o_position=?s:pos, o_name=?s:name WHERE user_id=1 AND ident=?s:ip', $vars);
|
|
} else {
|
|
$this->c->DB->exec('INSERT INTO ::online (user_id, ident, logged, o_position, o_name) SELECT 1, ?s:ip, ?i:logged, ?s:pos, ?s:name FROM ::groups WHERE NOT EXISTS (SELECT 1 FROM ::online WHERE user_id=1 AND ident=?s:ip) LIMIT 1', $vars);
|
|
}
|
|
} else {
|
|
// пользователь
|
|
$vars = [
|
|
':logged' => \time(),
|
|
':pos' => $position,
|
|
':id' => $this->c->user->id,
|
|
':name' => $this->c->user->username,
|
|
];
|
|
if ($this->c->user->isLogged) {
|
|
$this->c->DB->exec('UPDATE ::online SET logged=?i:logged, o_position=?s:pos WHERE user_id=?i:id', $vars);
|
|
} else {
|
|
$this->c->DB->exec('INSERT INTO ::online (user_id, ident, logged, o_position) SELECT ?i:id, ?s:name, ?i:logged, ?s:pos FROM ::groups WHERE NOT EXISTS (SELECT 1 FROM ::online WHERE user_id=?i:id) LIMIT 1', $vars);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Удаление юзера из таблицы online
|
|
*/
|
|
public function delete(User $user)
|
|
{
|
|
if ($user->isGuest) {
|
|
$this->c->DB->exec('DELETE FROM ::online WHERE user_id=1 AND ident=?s:ip', [':ip' => $user->ip]);
|
|
} else {
|
|
$this->c->DB->exec('DELETE FROM ::online WHERE user_id=?i:id', [':id' => $user->id]);
|
|
}
|
|
}
|
|
}
|