* @package be.bastelstu.chat * @subpackage data.room */ class Room extends \chat\data\CHATDatabaseObject implements \wcf\system\request\IRouteController { /** * @see \wcf\data\DatabaseObject::$databaseTableName */ protected static $databaseTableName = 'room'; /** * @see \wcf\data\DatabaseObject::$databaseTableIndexName */ protected static $databaseTableIndexName = 'roomID'; /** * cached users * * @var array<\wcf\data\user\UserProfile> */ protected static $users = null; /** * room id of the “global” pseudo chat room */ const GLOBAL_ROOM = -1; /** * @see \wcf\data\chat\room\ChatRoom::getTitle(); */ public function __toString() { return $this->getTitle(); } /** * Returns whther the user is allowed to always enter the room. * * @param \wcf\data\user\User $user * @return boolean */ public function canAlwaysEnter(\wcf\data\user\User $user = null) { if ($user === null) $user = WCF::getUser(); if (!$user->userID) return false; $user = new \wcf\data\user\UserProfile($user); if ($this->isPermanent && $user->getPermission('admin.chat.canManageSuspensions')) return true; if ($this->isPermanent && $user->getPermission('mod.chat.canGban')) return true; $ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject()); if ($ph->getPermission($this, 'mod.canAlwaysEnter')) return true; if ($ph->getPermission($this, 'mod.canBan')) return true; return false; } /** * Returns whether the user is allowed to enter the room. * * @param \wcf\data\user\User $user * @return boolean */ public function canEnter(\wcf\data\user\User $user = null) { if ($user === null) $user = WCF::getUser(); if (!$user->userID) return false; if ($this->canAlwaysEnter($user)) return true; $user = new \wcf\data\user\UserProfile($user); $ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject()); if (!$ph->getPermission($this, 'user.canEnter')) return false; $suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject()); // room suspension if (isset($suspensions[$this->roomID][Suspension::TYPE_BAN])) { if ($suspensions[$this->roomID][Suspension::TYPE_BAN]->isValid()) { return false; } } // global suspension if (isset($suspensions[null][Suspension::TYPE_BAN])) { if ($suspensions[null][Suspension::TYPE_BAN]->isValid()) { return false; } } return true; } /** * Returns whether the user is allowed to write messages in this room. * * @param \wcf\data\user\User $user * @return boolean */ public function canWrite(\wcf\data\user\User $user = null) { if ($user === null) $user = WCF::getUser(); if (!$user->userID) return false; $user = new \wcf\data\user\UserProfile($user); if ($user->getPermission('admin.chat.canManageSuspensions')) return true; if ($user->getPermission('mod.chat.canGmute')) return true; $ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject()); if ($ph->getPermission($this, 'mod.canAlwaysWrite')) return true; if ($ph->getPermission($this, 'mod.canMute')) return true; if (!$ph->getPermission($this, 'user.canWrite')) return false; $suspensions = Suspension::getSuspensionsForUser($user->getDecoratedObject()); // room suspension if (isset($suspensions[$this->roomID][Suspension::TYPE_MUTE])) { if ($suspensions[$this->roomID][Suspension::TYPE_MUTE]->isValid()) { return false; } } // global suspension if (isset($suspensions[null][Suspension::TYPE_MUTE])) { if ($suspensions[null][Suspension::TYPE_MUTE]->isValid()) { return false; } } return true; } /** * Returns whether the user is allowed to mute other users in this room. * * @param \wcf\data\user\User $user * @return boolean */ public function canMute(\wcf\data\user\User $user = null) { if ($user === null) $user = WCF::getUser(); if (!$user->userID) return false; $user = new \wcf\data\user\UserProfile($user); if ($user->getPermission('admin.chat.canManageSuspensions')) return true; if ($user->getPermission('mod.chat.canGmute')) return true; $ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject()); return $ph->getPermission($this, 'mod.canMute'); } /** * Returns whether the user is allowed to ban other users in this room. * * @param \wcf\data\user\User $user * @return boolean */ public function canBan(\wcf\data\user\User $user = null) { if ($user === null) $user = WCF::getUser(); if (!$user->userID) return false; $user = new \wcf\data\user\UserProfile($user); if ($user->getPermission('admin.chat.canManageSuspensions')) return true; if ($user->getPermission('mod.chat.canGban')) return true; $ph = new \chat\system\permission\PermissionHandler($user->getDecoratedObject()); return $ph->getPermission($this, 'mod.canBan'); } /** * Returns the ID of this chatroom. * * @see \wcf\system\request\IRouteController */ public function getID() { return $this->roomID; } /** * Returns the name of this chatroom. * * @see \wcf\system\request\IRouteController */ public function getTitle() { return \wcf\system\WCF::getLanguage()->get($this->title); } /** * Returns the topic of this chat room * * @return string */ public function getTopic() { return \wcf\system\WCF::getLanguage()->get($this->topic); } /** * Returns the users that are currently active in this room. * * @return array<\wcf\data\user\UserProfile> */ public function getUsers() { if (self::$users === null) { $userList = new \wcf\data\user\UserProfileList(); $userList->getConditionBuilder()->add('user_table.chatRoomID IS NOT NULL', array()); $userList->readObjects(); $users = $userList->getObjects(); foreach ($users as $userID => $user) { if (!isset(self::$users[$user->chatRoomID])) self::$users[$user->chatRoomID] = array(); self::$users[$user->chatRoomID][$userID] = $user; } } if ($this->roomID === self::GLOBAL_ROOM) { return array_reduce(self::$users, function($a, $b) { return $a + $b; }, array()); } if (!isset(self::$users[$this->roomID])) self::$users[$this->roomID] = array(); return self::$users[$this->roomID]; } /** * Returns the users that "timed out". * * @return \wcf\data\user\UserList */ public static function getDeadUsers() { if (\wcf\system\push\PushHandler::getInstance()->isEnabled()) { $time = TIME_NOW - 180; } else { $time = TIME_NOW; } $sql = "SELECT userID FROM wcf".WCF_N."_user WHERE chatRoomID IS NOT NULL AND chatLastActivity < ? FOR UPDATE"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute([ $time - 30 ]); $userIDs = []; while ($userID = $statement->fetchColumn()) $userIDs[] = $userID; $userList = new \wcf\data\user\UserList(); if (!empty($userIDs)) { $userList->getConditionBuilder()->add('user_table.userID IN (?)', array($userIDs)); } else { $userList->getConditionBuilder()->add('1 = 0', []); } $userList->readObjects(); return $userList; } }