mirror of
https://github.com/wbbaddons/Tims-Chat.git
synced 2024-11-16 16:30:09 +00:00
306 lines
8.8 KiB
PHP
306 lines
8.8 KiB
PHP
<?php
|
|
|
|
/*
|
|
* Copyright (c) 2010-2024 Tim Düsterhus.
|
|
*
|
|
* Use of this software is governed by the Business Source License
|
|
* included in the LICENSE file.
|
|
*
|
|
* Change Date: 2028-06-15
|
|
*
|
|
* On the date above, in accordance with the Business Source
|
|
* License, use of this software will be governed by version 2
|
|
* or later of the General Public License.
|
|
*/
|
|
|
|
namespace chat\data\room;
|
|
|
|
use chat\page\RoomPage;
|
|
use chat\system\cache\runtime\UserRuntimeCache as ChatUserRuntimeCache;
|
|
use chat\system\permission\PermissionHandler;
|
|
use wcf\data\DatabaseObject;
|
|
use wcf\data\ITitledLinkObject;
|
|
use wcf\data\user\UserProfile;
|
|
use wcf\system\event\EventHandler;
|
|
use wcf\system\exception\PermissionDeniedException;
|
|
use wcf\system\request\IRouteController;
|
|
use wcf\system\request\LinkHandler;
|
|
use wcf\system\WCF;
|
|
use wcf\util\StringUtil;
|
|
|
|
/**
|
|
* Represents a chat room.
|
|
*
|
|
* @property-read integer $roomID
|
|
* @property-read string $title
|
|
* @property-read string $topic
|
|
* @property-read integer $position
|
|
* @property-read integer $userLimit
|
|
* @property-read integer $isTemporary
|
|
* @property-read integer $ownerID
|
|
* @property-read integer $topicUseHtml
|
|
*/
|
|
final class Room extends DatabaseObject implements
|
|
IRouteController,
|
|
ITitledLinkObject,
|
|
\JsonSerializable
|
|
{
|
|
/**
|
|
* @var ?(integer[])
|
|
*/
|
|
private static $userToRoom;
|
|
|
|
/**
|
|
* @see Room::getTitle()
|
|
*/
|
|
public function __toString(): string
|
|
{
|
|
return $this->getTitle();
|
|
}
|
|
|
|
/**
|
|
* Returns whether the given user can see at least
|
|
* one chat room. If no user is given the current user
|
|
* should be assumed
|
|
*/
|
|
public static function canSeeAny(?UserProfile $user = null): bool
|
|
{
|
|
$rooms = RoomCache::getInstance()->getRooms();
|
|
foreach ($rooms as $room) {
|
|
if ($room->canSee($user)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the given user can see this room.
|
|
* If no user is given the current user should be assumed.
|
|
*/
|
|
public function canSee(?UserProfile $user = null, ?\Exception &$reason = null): bool
|
|
{
|
|
static $cache = [ ];
|
|
if ($user === null) {
|
|
$user = new UserProfile(WCF::getUser());
|
|
}
|
|
|
|
if (!isset($cache[$this->roomID])) {
|
|
$cache[$this->roomID] = [];
|
|
}
|
|
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
|
|
return ($reason = $cache[$this->roomID][$user->userID]) === null;
|
|
}
|
|
|
|
if (!$user->userID) {
|
|
$reason = new PermissionDeniedException();
|
|
|
|
return ($cache[$this->roomID][$user->userID] = $reason) === null;
|
|
}
|
|
|
|
$result = null;
|
|
if (!PermissionHandler::get($user)->getPermission($this, 'user.canSee')) {
|
|
$result = new PermissionDeniedException();
|
|
}
|
|
|
|
$parameters = [
|
|
'user' => $user,
|
|
'result' => $result,
|
|
];
|
|
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
|
|
$reason = $parameters['result'];
|
|
|
|
if (!($reason === null || $reason instanceof \Throwable)) {
|
|
throw new \DomainException('Result of canSee must be a \Throwable or null.');
|
|
}
|
|
|
|
return ($cache[$this->roomID][$user->userID] = $reason) === null;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the given user can see the log of this room.
|
|
* If no user is given the current user should be assumed.
|
|
*/
|
|
public function canSeeLog(?UserProfile $user = null, ?\Exception &$reason = null): bool
|
|
{
|
|
static $cache = [ ];
|
|
if ($user === null) {
|
|
$user = new UserProfile(WCF::getUser());
|
|
}
|
|
|
|
if (!isset($cache[$this->roomID])) {
|
|
$cache[$this->roomID] = [];
|
|
}
|
|
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
|
|
return ($reason = $cache[$this->roomID][$user->userID]) === null;
|
|
}
|
|
|
|
$result = null;
|
|
if (!PermissionHandler::get($user)->getPermission($this, 'user.canSeeLog')) {
|
|
$result = new PermissionDeniedException();
|
|
}
|
|
|
|
$parameters = [
|
|
'user' => $user,
|
|
'result' => $result,
|
|
];
|
|
EventHandler::getInstance()->fireAction($this, 'canSeeLog', $parameters);
|
|
$reason = $parameters['result'];
|
|
|
|
if (!($reason === null || $reason instanceof \Throwable)) {
|
|
throw new \DomainException('Result of canSeeLog must be a \Throwable or null.');
|
|
}
|
|
|
|
return ($cache[$this->roomID][$user->userID] = $reason) === null;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the given user can join this room.
|
|
* If no user is given the current user should be assumed.
|
|
*/
|
|
public function canJoin(?UserProfile $user = null, ?\Exception &$reason = null): bool
|
|
{
|
|
static $cache = [ ];
|
|
if ($user === null) {
|
|
$user = new UserProfile(WCF::getUser());
|
|
}
|
|
|
|
if (!isset($cache[$this->roomID])) {
|
|
$cache[$this->roomID] = [];
|
|
}
|
|
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
|
|
return ($reason = $cache[$this->roomID][$user->userID]) === null;
|
|
}
|
|
|
|
$parameters = [
|
|
'user' => $user,
|
|
'result' => null,
|
|
];
|
|
EventHandler::getInstance()->fireAction($this, 'canJoin', $parameters);
|
|
$reason = $parameters['result'];
|
|
|
|
if (!($reason === null || $reason instanceof \Throwable)) {
|
|
throw new \DomainException('Result of canJoin must be a \Throwable or null.');
|
|
}
|
|
|
|
return ($cache[$this->roomID][$user->userID] = $reason) === null;
|
|
}
|
|
|
|
/**
|
|
* Returns whether the given user can write public messages in this room.
|
|
* If no user is given the current user should be assumed.
|
|
*/
|
|
public function canWritePublicly(?UserProfile $user = null, ?\Exception &$reason = null): bool
|
|
{
|
|
static $cache = [ ];
|
|
if ($user === null) {
|
|
$user = new UserProfile(WCF::getUser());
|
|
}
|
|
|
|
if (!isset($cache[$this->roomID])) {
|
|
$cache[$this->roomID] = [];
|
|
}
|
|
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
|
|
return ($reason = $cache[$this->roomID][$user->userID]) === null;
|
|
}
|
|
|
|
$result = null;
|
|
if (!PermissionHandler::get($user)->getPermission($this, 'user.canWrite')) {
|
|
$result = new PermissionDeniedException();
|
|
}
|
|
|
|
$parameters = [
|
|
'user' => $user,
|
|
'result' => $result,
|
|
];
|
|
EventHandler::getInstance()->fireAction($this, 'canWritePublicly', $parameters);
|
|
$reason = $parameters['result'];
|
|
|
|
if (!($reason === null || $reason instanceof \Throwable)) {
|
|
throw new \DomainException('Result of canWritePublicly must be a \Throwable or null.');
|
|
}
|
|
|
|
return ($cache[$this->roomID][$user->userID] = $reason) === null;
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getTitle(): string
|
|
{
|
|
return WCF::getLanguage()->get($this->title);
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getTopic(): string
|
|
{
|
|
$topic = StringUtil::trim(WCF::getLanguage()->get($this->topic));
|
|
|
|
if (!$this->topicUseHtml) {
|
|
$topic = StringUtil::encodeHTML($topic);
|
|
}
|
|
|
|
return $topic;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of users in this room.
|
|
*
|
|
* @return \chat\data\user\User[]
|
|
*/
|
|
public function getUsers()
|
|
{
|
|
if (self::$userToRoom === null) {
|
|
$sql = "SELECT r2u.userID,
|
|
r2u.roomID
|
|
FROM chat1_room_to_user r2u
|
|
INNER JOIN wcf1_user u
|
|
ON r2u.userID = u.userID
|
|
WHERE r2u.active = ?
|
|
ORDER BY u.username ASC";
|
|
$statement = WCF::getDB()->prepare($sql);
|
|
$statement->execute([ 1 ]);
|
|
self::$userToRoom = $statement->fetchMap('roomID', 'userID', false);
|
|
|
|
if (!empty(self::$userToRoom)) {
|
|
ChatUserRuntimeCache::getInstance()->cacheObjectIDs(\array_merge(...self::$userToRoom));
|
|
}
|
|
}
|
|
|
|
if (!isset(self::$userToRoom[$this->roomID])) {
|
|
return [ ];
|
|
}
|
|
|
|
return ChatUserRuntimeCache::getInstance()->getObjects(self::$userToRoom[$this->roomID]);
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function getLink(): string
|
|
{
|
|
return LinkHandler::getInstance()->getControllerLink(
|
|
RoomPage::class,
|
|
[
|
|
'object' => $this,
|
|
'forceFrontend' => true,
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function jsonSerialize(): array
|
|
{
|
|
return [
|
|
'title' => $this->getTitle(),
|
|
'topic' => $this->getTopic(),
|
|
'link' => $this->getLink(),
|
|
];
|
|
}
|
|
}
|