roomID = \intval($_GET['id']); } $this->room = RoomCache::getInstance()->getRoom($this->roomID); if ($this->room === null) { throw new IllegalLinkException(); } if (!$this->room->canSee($user = null, $reason)) { throw $reason; } if (!$this->room->canSeeLog($user = null, $reason)) { throw $reason; } if (isset($_GET['messageid'])) { $this->messageID = \intval($_GET['messageid']); } if ($this->messageID) { $this->message = new Message($this->messageID); if (!$this->message->getMessageType()->getProcessor()->canSeeInLog($this->message, $this->room)) { throw new PermissionDeniedException(); } } if (isset($_REQUEST['datetime'])) { $this->datetime = \strtotime($_REQUEST['datetime']); } } /** * @inheritDoc */ public function readData() { parent::readData(); if ($this->datetime) { // Determine message types supporting fast select $objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType'); $fastSelect = \array_map(static function ($item) { return $item->objectTypeID; }, \array_filter($objectTypes, static function ($item) { // TODO: Consider a method couldAppearInLog(): bool return $item->getProcessor()->supportsFastSelect(); })); $minimum = 0; $loops = 0; do { // Build fast select filter $condition = new PreparedStatementConditionBuilder(); $condition->add('((roomID = ? AND objectTypeID IN (?)) OR objectTypeID NOT IN (?))', [ $this->room->roomID, $fastSelect, $fastSelect ]); $condition->add('time >= ?', [ $this->datetime ]); if ($minimum) { $condition->add('messageID > ?', [ $minimum ]); } $sql = "SELECT messageID FROM chat1_message {$condition} ORDER BY messageID ASC"; $statement = WCF::getDB()->prepare($sql, 20); $statement->execute($condition->getParameters()); $messageIDs = $statement->fetchAll(\PDO::FETCH_COLUMN); $objectList = new MessageList(); $objectList->setObjectIDs($messageIDs); $objectList->readObjects(); $objects = $objectList->getObjects(); if (empty($objects)) { // TODO: UserInputException? throw new IllegalLinkException(); } foreach ($objects as $message) { if ($message->getMessageType()->getProcessor()->canSeeInLog($message, $this->room)) { $parameters = [ 'messageid' => $message->messageID, 'object' => $this->room, ]; HeaderUtil::redirect(LinkHandler::getInstance()->getControllerLink(self::class, $parameters)); exit; } $minimum = $message->messageID; } } while (++$loops <= 3); // Do a best guess redirect to an ID that is as near as possible $parameters = [ 'application' => 'chat', 'messageid' => $minimum, 'object' => $this->room, ]; HeaderUtil::redirect(LinkHandler::getInstance()->getControllerLink(self::class, $parameters)); exit; } } /** * @inheritDoc */ public function assignVariables() { parent::assignVariables(); PageLocationManager::getInstance()->addParentLocation( 'be.bastelstu.chat.Room', $this->room->roomID, $this->room ); WCF::getTPL()->assign([ 'room' => $this->room, 'roomList' => RoomCache::getInstance()->getRooms(), 'messageID' => $this->messageID, 'message' => $this->message, 'config' => $this->getConfig(), ]); } }