diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php index ec1d18c3523..cabf5d428b1 100644 --- a/lib/Controller/RoomController.php +++ b/lib/Controller/RoomController.php @@ -477,7 +477,7 @@ protected function formatRoomV1(Room $room, ?Participant $currentParticipant): a $numActiveGuests = 0; $cleanGuests = false; $participantList = []; - $participants = $this->participantService->getParticipantsForRoom($room, true); // FIXME NEEDS the session but can potentially kill APIv1? + $participants = $this->participantService->getSessionsAndParticipantsForRoom($room); // FIXME NEEDS the session but can potentially kill APIv1? uasort($participants, function (Participant $participant1, Participant $participant2) { $s1 = $participant1->getSession() ? $participant1->getSession()->getLastPing() : 0; $s2 = $participant2->getSession() ? $participant2->getSession()->getLastPing() : 0; @@ -1110,7 +1110,7 @@ public function getParticipants(bool $includeStatus = false): DataResponse { } $maxPingAge = $this->timeFactory->getTime() - 100; - $participants = $this->participantService->getParticipantsForRoom($this->room, true); + $participants = $this->participantService->getSessionsAndParticipantsForRoom($this->room); $results = $headers = $statuses = []; if ($this->userId !== null diff --git a/lib/Manager.php b/lib/Manager.php index 2f1b848c737..aca843f2881 100644 --- a/lib/Manager.php +++ b/lib/Manager.php @@ -317,7 +317,7 @@ public function getRoomsForUser(string $userId, bool $loadSession = false, bool ->where($query->expr()->isNotNull('a.id')); if ($loadSession) { - $helper->selectSessionsTable($query); + $helper->selectSessionsTable($query); // FIXME ? $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( $query->expr()->eq('a.id', 's.attendee_id') )); diff --git a/lib/Model/SelectHelper.php b/lib/Model/SelectHelper.php index ade976f5c19..3bf0463c819 100644 --- a/lib/Model/SelectHelper.php +++ b/lib/Model/SelectHelper.php @@ -83,4 +83,17 @@ public function selectSessionsTable(IQueryBuilder $query, string $alias = 's'): ->addSelect($alias . 'last_ping') ->selectAlias($alias . 'id', 's_id'); } + + public function selectSessionsTableMax(IQueryBuilder $query, string $alias = 's'): void { + if ($alias !== '') { + $alias .= '.'; + } + + $query->selectAlias($query->func()->max($alias . 'attendee_id'), 'attendee_id') + ->selectAlias($query->func()->max($alias . 'session_id'), 'session_id') + // BIT_OR would be better, but SQLite does not support something like it. + ->selectAlias($query->func()->max($alias . 'in_call'), 'in_call') + ->selectAlias($query->func()->max($alias . 'last_ping'), 'last_ping') + ->selectAlias($query->func()->max($alias . 'id'), 's_id'); + } } diff --git a/lib/Room.php b/lib/Room.php index 96140f6af40..664059e4aeb 100644 --- a/lib/Room.php +++ b/lib/Room.php @@ -427,13 +427,14 @@ public function getParticipant(?string $userId, $sessionId = null): Participant ->setMaxResults(1); if ($sessionId !== false) { - $helper->selectSessionsTable($query); if ($sessionId !== null) { + $helper->selectSessionsTable($query); $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), $query->expr()->eq('a.id', 's.attendee_id') )); } else { + $helper->selectSessionsTable($query); // FIXME PROBLEM $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); } } @@ -494,7 +495,7 @@ public function getParticipantByPin(string $pin): Participant { $helper = new SelectHelper(); $helper->selectAttendeesTable($query); $query->from('talk_attendees', 'a') - ->andWhere($query->expr()->eq('a.pin', $query->createNamedParameter($pin))) + ->where($query->expr()->eq('a.pin', $query->createNamedParameter($pin))) ->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId()))) ->setMaxResults(1); $result = $query->execute(); @@ -521,18 +522,20 @@ public function getParticipantByAttendeeId(int $attendeeId, $sessionId = null): $helper = new SelectHelper(); $helper->selectAttendeesTable($query); $query->from('talk_attendees', 'a') - ->andWhere($query->expr()->eq('a.id', $query->createNamedParameter($attendeeId, IQueryBuilder::PARAM_INT))) + ->where($query->expr()->eq('a.id', $query->createNamedParameter($attendeeId, IQueryBuilder::PARAM_INT))) ->andWhere($query->expr()->eq('a.room_id', $query->createNamedParameter($this->getId()))) ->setMaxResults(1); if ($sessionId !== false) { - $helper->selectSessionsTable($query); if ($sessionId !== null) { + $helper->selectSessionsTable($query); $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), $query->expr()->eq('a.id', 's.attendee_id') )); } else { + $helper->selectSessionsTableMax($query); + $query->groupBy('a.id'); $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); } } @@ -564,7 +567,7 @@ public function getParticipantByActor(string $actorType, string $actorId, $sessi $query = $this->db->getQueryBuilder(); $helper = new SelectHelper(); - $helper->selectSessionsTable($query); + $helper->selectAttendeesTable($query); $query->from('talk_attendees', 'a') ->andWhere($query->expr()->eq('a.actor_type', $query->createNamedParameter($actorType))) ->andWhere($query->expr()->eq('a.actor_id', $query->createNamedParameter($actorId))) @@ -572,13 +575,15 @@ public function getParticipantByActor(string $actorType, string $actorId, $sessi ->setMaxResults(1); if ($sessionId !== false) { - $helper->selectSessionsTable($query); if ($sessionId !== null) { + $helper->selectSessionsTable($query); $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->andX( $query->expr()->eq('s.session_id', $query->createNamedParameter($sessionId)), $query->expr()->eq('a.id', 's.attendee_id') )); } else { + $helper->selectSessionsTableMax($query); + $query->groupBy('a.id'); $query->leftJoin('a', 'talk_sessions', 's', $query->expr()->eq('a.id', 's.attendee_id')); } } diff --git a/lib/Service/ParticipantService.php b/lib/Service/ParticipantService.php index db91478519c..2995b6f647a 100644 --- a/lib/Service/ParticipantService.php +++ b/lib/Service/ParticipantService.php @@ -583,10 +583,9 @@ public function getLastCommonReadChatMessageForMultipleRooms(array $roomIds): ar /** * @param Room $room - * @param bool $loadSession Loads a random session if possible for the users * @return Participant[] */ - public function getParticipantsForRoom(Room $room, bool $loadSession = false): array { + public function getParticipantsForRoom(Room $room): array { $query = $this->connection->getQueryBuilder(); $helper = new SelectHelper(); @@ -594,13 +593,30 @@ public function getParticipantsForRoom(Room $room, bool $loadSession = false): a $query->from('talk_attendees', 'a') ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))); - if ($loadSession) { - $helper->selectSessionsTable($query); - $query->leftJoin( + return $this->getParticipantsFromQuery($query, $room); + } + + /** + * Get all sessions and attendees without a session for the room + * + * This will return multiple items for the same attendee if the attendee + * has multiple sessions in the room. + * + * @param Room $room + * @return Participant[] + */ + public function getSessionsAndParticipantsForRoom(Room $room): array { + $query = $this->connection->getQueryBuilder(); + + $helper = new SelectHelper(); + $helper->selectAttendeesTable($query); + $helper->selectSessionsTable($query); + $query->from('talk_attendees', 'a') + ->leftJoin( 'a', 'talk_sessions', 's', $query->expr()->eq('s.attendee_id', 'a.id') - ); - } + ) + ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))); return $this->getParticipantsFromQuery($query, $room); } @@ -622,7 +638,7 @@ public function getParticipantsForAllSessions(Room $room, int $maxAge = 0): arra $query->expr()->eq('s.attendee_id', 'a.id') ) ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) - ->andWhere($query->expr()->isNotNull('s.id')); + ->andWhere($query->expr()->isNotNull('a.id')); if ($maxAge > 0) { $query->andWhere($query->expr()->gt('s.last_ping', $query->createNamedParameter($maxAge, IQueryBuilder::PARAM_INT))); @@ -667,7 +683,7 @@ public function getParticipantsByNotificationLevel(Room $room, int $notification $helper = new SelectHelper(); $helper->selectAttendeesTable($query); - $helper->selectSessionsTable($query); + $helper->selectSessionsTableMax($query); $query->from('talk_attendees', 'a') // Currently we only care if the user has a session at all, so we can select any: #ThisIsFine ->leftJoin( @@ -675,7 +691,8 @@ public function getParticipantsByNotificationLevel(Room $room, int $notification $query->expr()->eq('s.attendee_id', 'a.id') ) ->where($query->expr()->eq('a.room_id', $query->createNamedParameter($room->getId(), IQueryBuilder::PARAM_INT))) - ->andWhere($query->expr()->eq('a.notification_level', $query->createNamedParameter($notificationLevel, IQueryBuilder::PARAM_INT))); + ->andWhere($query->expr()->eq('a.notification_level', $query->createNamedParameter($notificationLevel, IQueryBuilder::PARAM_INT))) + ->groupBy('a.id'); return $this->getParticipantsFromQuery($query, $room); }