Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Chat/Parser/Command.php3
-rw-r--r--lib/Chat/Parser/SystemMessage.php26
-rw-r--r--lib/Chat/Parser/UserMention.php2
-rw-r--r--lib/Controller/ChatController.php31
-rw-r--r--lib/Controller/RoomController.php230
-rw-r--r--lib/Controller/SignalingController.php7
-rw-r--r--lib/Manager.php57
-rw-r--r--lib/Middleware/InjectionMiddleware.php4
-rw-r--r--lib/Migration/Version10000Date20201015134000.php13
-rw-r--r--lib/Model/Attendee.php113
-rw-r--r--lib/Model/AttendeeMapper.php72
-rw-r--r--lib/Model/Session.php71
-rw-r--r--lib/Model/SessionMapper.php64
-rw-r--r--lib/Participant.php174
-rw-r--r--lib/Room.php35
-rw-r--r--lib/Service/SessionService.php60
16 files changed, 644 insertions, 318 deletions
diff --git a/lib/Chat/Parser/Command.php b/lib/Chat/Parser/Command.php
index 4e093c269..1e321d8d8 100644
--- a/lib/Chat/Parser/Command.php
+++ b/lib/Chat/Parser/Command.php
@@ -44,7 +44,8 @@ class Command {
$participant = $message->getParticipant();
if ($data['visibility'] !== \OCA\Talk\Model\Command::RESPONSE_ALL &&
- $data['user'] !== $participant->getUser()) {
+ ($participant->getAttendee()->getActorType() !== 'users'
+ || $data['user'] !== $participant->getAttendee()->getActorId())) {
$message->setVisibility(false);
return;
}
diff --git a/lib/Chat/Parser/SystemMessage.php b/lib/Chat/Parser/SystemMessage.php
index c69aeaf95..e9509b722 100644
--- a/lib/Chat/Parser/SystemMessage.php
+++ b/lib/Chat/Parser/SystemMessage.php
@@ -92,11 +92,15 @@ class SystemMessage {
$participant = $chatMessage->getParticipant();
if (!$participant->isGuest()) {
+ $currentActorId = $participant->getAttendee()->getActorId();
$currentUserIsActor = $parsedParameters['actor']['type'] === 'user' &&
- $participant->getUser() === $parsedParameters['actor']['id'];
+ $participant->getAttendee()->getActorType() === 'users' &&
+ $currentActorId === $parsedParameters['actor']['id'];
} else {
$currentUserIsActor = $parsedParameters['actor']['type'] === 'guest' &&
- sha1($participant->getSessionId()) === $parsedParameters['actor']['id'];
+ $participant->getAttendee()->getActorType() === 'guest' &&
+ $participant->getAttendee()->getActorId() === $parsedParameters['actor']['id'];
+ $currentActorId = null;
}
$cliIsActor = $parsedParameters['actor']['type'] === 'guest' &&
'guest/cli' === $parsedParameters['actor']['id'];
@@ -197,7 +201,7 @@ class SystemMessage {
}
} elseif ($currentUserIsActor) {
$parsedMessage = $this->l->t('You added {user}');
- } elseif (!$participant->isGuest() && $participant->getUser() === $parsedParameters['user']['id']) {
+ } elseif (!$participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} added you');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator added you');
@@ -217,7 +221,7 @@ class SystemMessage {
$parsedMessage = $this->l->t('{actor} removed {user}');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You removed {user}');
- } elseif (!$participant->isGuest() && $participant->getUser() === $parsedParameters['user']['id']) {
+ } elseif (!$participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} removed you');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator removed you');
@@ -231,7 +235,7 @@ class SystemMessage {
$parsedMessage = $this->l->t('{actor} promoted {user} to moderator');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You promoted {user} to moderator');
- } elseif (!$participant->isGuest() && $participant->getUser() === $parsedParameters['user']['id']) {
+ } elseif (!$participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} promoted you to moderator');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator promoted you to moderator');
@@ -244,7 +248,7 @@ class SystemMessage {
$parsedMessage = $this->l->t('{actor} demoted {user} from moderator');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You demoted {user} from moderator');
- } elseif (!$participant->isGuest() && $participant->getUser() === $parsedParameters['user']['id']) {
+ } elseif (!$participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} demoted you from moderator');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator demoted you from moderator');
@@ -257,7 +261,7 @@ class SystemMessage {
$parsedMessage = $this->l->t('{actor} promoted {user} to moderator');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You promoted {user} to moderator');
- } elseif ($participant->isGuest() && $participant->getSessionId() === $parsedParameters['user']['id']) {
+ } elseif ($participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} promoted you to moderator');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator promoted you to moderator');
@@ -270,7 +274,7 @@ class SystemMessage {
$parsedMessage = $this->l->t('{actor} demoted {user} from moderator');
if ($currentUserIsActor) {
$parsedMessage = $this->l->t('You demoted {user} from moderator');
- } elseif ($participant->isGuest() && $participant->getSessionId() === $parsedParameters['user']['id']) {
+ } elseif ($participant->isGuest() && $currentActorId === $parsedParameters['user']['id']) {
$parsedMessage = $this->l->t('{actor} demoted you from moderator');
if ($cliIsActor) {
$parsedMessage = $this->l->t('An administrator demoted you from moderator');
@@ -327,8 +331,8 @@ class SystemMessage {
$path = $name;
if (!$participant->isGuest()) {
- if ($share->getShareOwner() !== $participant->getUser()) {
- $userFolder = $this->rootFolder->getUserFolder($participant->getUser());
+ if ($share->getShareOwner() !== $participant->getAttendee()->getActorId()) {
+ $userFolder = $this->rootFolder->getUserFolder($participant->getAttendee()->getActorId());
if ($userFolder instanceof Node) {
$userNodes = $userFolder->getById($node->getId());
@@ -337,7 +341,7 @@ class SystemMessage {
// 1. Only be executed on "Waiting for new messages"
// 2. Once per request
\OC_Util::tearDownFS();
- \OC_Util::setupFS($participant->getUser());
+ \OC_Util::setupFS($participant->ggetAttendee()->getActorId());
$userNodes = $userFolder->getById($node->getId());
}
diff --git a/lib/Chat/Parser/UserMention.php b/lib/Chat/Parser/UserMention.php
index 9f83f996e..4d5862ef9 100644
--- a/lib/Chat/Parser/UserMention.php
+++ b/lib/Chat/Parser/UserMention.php
@@ -118,7 +118,7 @@ class UserMention {
$messageParameters[$mentionParameterId] = [
'type' => $mention['type'],
'id' => $chatMessage->getRoom()->getToken(),
- 'name' => $chatMessage->getRoom()->getDisplayName($chatMessage->getParticipant()->getUser()),
+ 'name' => $chatMessage->getRoom()->getDisplayName($chatMessage->getParticipant()->getAttendee()->getActorId()),
'call-type' => $this->getRoomType($chatMessage->getRoom()),
];
} elseif ($mention['type'] === 'guest') {
diff --git a/lib/Controller/ChatController.php b/lib/Controller/ChatController.php
index 6aaf30d8b..8a5d48066 100644
--- a/lib/Controller/ChatController.php
+++ b/lib/Controller/ChatController.php
@@ -29,6 +29,7 @@ use OCA\Talk\Chat\AutoComplete\Sorter;
use OCA\Talk\Chat\ChatManager;
use OCA\Talk\Chat\MessageParser;
use OCA\Talk\GuestManager;
+use OCA\Talk\Model\AttendeeMapper;
use OCA\Talk\Model\Message;
use OCA\Talk\Participant;
use OCA\Talk\Room;
@@ -67,6 +68,9 @@ class ChatController extends AEnvironmentAwareController {
/** @var ChatManager */
private $chatManager;
+ /** @var AttendeeMapper */
+ private $attendeeMapper;
+
/** @var GuestManager */
private $guestManager;
@@ -103,6 +107,7 @@ class ChatController extends AEnvironmentAwareController {
TalkSession $session,
IAppManager $appManager,
ChatManager $chatManager,
+ AttendeeMapper $attendeeMapper,
GuestManager $guestManager,
MessageParser $messageParser,
IManager $autoCompleteManager,
@@ -119,6 +124,7 @@ class ChatController extends AEnvironmentAwareController {
$this->session = $session;
$this->appManager = $appManager;
$this->chatManager = $chatManager;
+ $this->attendeeMapper = $attendeeMapper;
$this->guestManager = $guestManager;
$this->messageParser = $messageParser;
$this->autoCompleteManager = $autoCompleteManager;
@@ -206,7 +212,9 @@ class ChatController extends AEnvironmentAwareController {
return new DataResponse([], Http::STATUS_CREATED);
}
- $this->participant->setLastReadMessage((int) $comment->getId());
+ $attendee = $this->participant->getAttendee();
+ $attendee->setLastReadMessage((int) $comment->getId());
+ $this->attendeeMapper->update($attendee);
$data = $chatMessage->toArray();
if ($parentMessage instanceof Message) {
@@ -299,9 +307,12 @@ class ChatController extends AEnvironmentAwareController {
* we only update the read marker to the last known id, when it is higher
* then the current read marker.
*/
+
+ $attendee = $this->participant->getAttendee();
if ($lookIntoFuture && $setReadMarker === 1 &&
- $lastKnownMessageId > $this->participant->getLastReadMessage()) {
- $this->participant->setLastReadMessage($lastKnownMessageId);
+ $lastKnownMessageId > $attendee->getLastReadMessage()) {
+ $attendee->setLastReadMessage($lastKnownMessageId);
+ $this->attendeeMapper->update($attendee);
}
$currentUser = $this->userManager->get($this->userId);
@@ -393,14 +404,16 @@ class ChatController extends AEnvironmentAwareController {
if ($newLastKnown instanceof IComment) {
$response->addHeader('X-Chat-Last-Given', $newLastKnown->getId());
/**
- * This false set the read marker on new messages although you
+ * This falsely set the read marker on new messages although you
* navigated away to a different chat already. So we removed this
* and instead update the read marker before your next waiting.
* So when you are still there, it will just have a wrong read
* marker for the time until your next request starts, while it will
* not update the value, when you actually left the chat already.
* if ($setReadMarker === 1 && $lookIntoFuture) {
- * $this->participant->setLastReadMessage((int) $newLastKnown->getId());
+ * $attendee = $this->participant->getAttendee();
+ * $attendee->setLastReadMessage((int) $newLastKnown->getId());
+ * $this->attendeeMapper->update($attendee);
* }
*/
}
@@ -416,7 +429,9 @@ class ChatController extends AEnvironmentAwareController {
* @return DataResponse
*/
public function setReadMarker(int $lastReadMessage): DataResponse {
- $this->participant->setLastReadMessage($lastReadMessage);
+ $attendee = $this->participant->getAttendee();
+ $attendee->setLastReadMessage($lastReadMessage);
+ $this->attendeeMapper->update($attendee);
return new DataResponse();
}
@@ -464,7 +479,9 @@ class ChatController extends AEnvironmentAwareController {
$results = $this->prepareResultArray($results, $statuses);
- $roomDisplayName = $this->room->getDisplayName($this->participant->getUser());
+ $attendee = $this->participant->getAttendee();
+ $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+ $roomDisplayName = $this->room->getDisplayName($userId);
if (($search === '' || strpos('all', $search) !== false || stripos($roomDisplayName, $search) !== false) && $this->room->getType() !== Room::ONE_TO_ONE_CALL) {
if ($search === '' ||
stripos($roomDisplayName, $search) === 0 ||
diff --git a/lib/Controller/RoomController.php b/lib/Controller/RoomController.php
index 54e1edda6..30a0de3fd 100644
--- a/lib/Controller/RoomController.php
+++ b/lib/Controller/RoomController.php
@@ -40,6 +40,8 @@ use OCA\Talk\Exceptions\RoomNotFoundException;
use OCA\Talk\Exceptions\UnauthorizedException;
use OCA\Talk\GuestManager;
use OCA\Talk\Manager;
+use OCA\Talk\Model\AttendeeMapper;
+use OCA\Talk\Model\Session;
use OCA\Talk\Participant;
use OCA\Talk\Room;
use OCA\Talk\Service\RoomService;
@@ -79,6 +81,8 @@ class RoomController extends AEnvironmentAwareController {
protected $manager;
/** @var RoomService */
protected $roomService;
+ /** @var AttendeeMapper */
+ protected $attendeeMapper;
/** @var GuestManager */
protected $guestManager;
/** @var IUserStatusManager */
@@ -107,6 +111,7 @@ class RoomController extends AEnvironmentAwareController {
IGroupManager $groupManager,
Manager $manager,
RoomService $roomService,
+ AttendeeMapper $attendeeMapper,
GuestManager $guestManager,
IUserStatusManager $statusManager,
ChatManager $chatManager,
@@ -124,6 +129,7 @@ class RoomController extends AEnvironmentAwareController {
$this->groupManager = $groupManager;
$this->manager = $manager;
$this->roomService = $roomService;
+ $this->attendeeMapper = $attendeeMapper;
$this->guestManager = $guestManager;
$this->statusManager = $statusManager;
$this->chatManager = $chatManager;
@@ -332,6 +338,9 @@ class RoomController extends AEnvironmentAwareController {
return $roomData;
}
+ $attendee = $currentParticipant->getAttendee();
+ $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+
$lastActivity = $room->getLastActivity();
if ($lastActivity instanceof \DateTimeInterface) {
$lastActivity = $lastActivity->getTimestamp();
@@ -348,25 +357,31 @@ class RoomController extends AEnvironmentAwareController {
$roomData = array_merge($roomData, [
'name' => $room->getName(),
- 'displayName' => $room->getDisplayName($currentParticipant->getUser()),
+ 'displayName' => $room->getDisplayName($userId),
'objectType' => $room->getObjectType(),
'objectId' => $room->getObjectId(),
- 'participantType' => $currentParticipant->getParticipantType(),
- // Deprecated, use participantFlags instead.
- 'participantInCall' => ($currentParticipant->getInCallFlags() & Participant::FLAG_IN_CALL) !== 0,
- 'participantFlags' => $currentParticipant->getInCallFlags(),
+ 'participantType' => $attendee->getParticipantType(),
'readOnly' => $room->getReadOnly(),
'count' => 0, // Deprecated, remove in future API version
'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface,
'lastActivity' => $lastActivity,
- 'isFavorite' => $currentParticipant->isFavorite(),
- 'notificationLevel' => $currentParticipant->getNotificationLevel(),
+ 'isFavorite' => $attendee->isFavorite(),
+ 'notificationLevel' => $attendee->getNotificationLevel(),
'lobbyState' => $room->getLobbyState(),
'lobbyTimer' => $lobbyTimer,
- 'lastPing' => $currentParticipant->getLastPing(),
- 'sessionId' => $currentParticipant->getSessionId(),
]);
+ $session = $currentParticipant->getSession();
+ if ($session instanceof Session) {
+ $roomData = array_merge($roomData, [
+ // Deprecated, use participantFlags instead.
+ 'participantInCall' => ($session->getInCall() & Participant::FLAG_IN_CALL) !== 0,
+ 'participantFlags' => $session->getInCall(),
+ 'lastPing' => $session->getLastPing(),
+ 'sessionId' => $session->getSessionId(),
+ ]);
+ }
+
if ($roomData['notificationLevel'] === Participant::NOTIFY_DEFAULT) {
if ($currentParticipant->isGuest()) {
$roomData['notificationLevel'] = Participant::NOTIFY_NEVER;
@@ -390,62 +405,65 @@ class RoomController extends AEnvironmentAwareController {
$roomData['canStartCall'] = $currentParticipant->canStartCall();
- $currentUser = $this->userManager->get($currentParticipant->getUser());
- if ($currentUser instanceof IUser) {
- $lastReadMessage = $currentParticipant->getLastReadMessage();
- if ($lastReadMessage === -1) {
- /*
- * Because the migration from the old comment_read_markers was
- * not possible in a programmatic way with a reasonable O(1) or O(n)
- * but only with O(user×chat), we do the conversion here.
- */
- $lastReadMessage = $this->chatManager->getLastReadMessageFromLegacy($room, $currentUser);
- $currentParticipant->setLastReadMessage($lastReadMessage);
- }
- $roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room, $lastReadMessage);
+ if ($userId !== '') {
+ $currentUser = $this->userManager->get($userId);
+ if ($currentUser instanceof IUser) {
+ $lastReadMessage = $attendee->getLastReadMessage();
+ if ($lastReadMessage === -1) {
+ /*
+ * Because the migration from the old comment_read_markers was
+ * not possible in a programmatic way with a reasonable O(1) or O(n)
+ * but only with O(user×chat), we do the conversion here.
+ */
+ $lastReadMessage = $this->chatManager->getLastReadMessageFromLegacy($room, $currentUser);
+ $attendee->setLastReadMessage($lastReadMessage);
+ $this->attendeeMapper->update($attendee);
+ }
+ $roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room, $lastReadMessage);
- $lastMention = $currentParticipant->getLastMentionMessage();
- $roomData['unreadMention'] = $lastMention !== 0 && $lastReadMessage < $lastMention;
- $roomData['lastReadMessage'] = $lastReadMessage;
+ $lastMention = $attendee->getLastMentionMessage();
+ $roomData['unreadMention'] = $lastMention !== 0 && $lastReadMessage < $lastMention;
+ $roomData['lastReadMessage'] = $lastReadMessage;
+ }
}
$numActiveGuests = 0;
$cleanGuests = false;
$participantList = [];
$participants = $room->getParticipants();
- uasort($participants, function (Participant $participant1, Participant $participant2) {
- return $participant2->getLastPing() - $participant1->getLastPing();
- });
-
- foreach ($participants as $participant) {
- if ($participant->isGuest()) {
- if ($participant->getLastPing() <= $this->timeFactory->getTime() - 100) {
- $cleanGuests = true;
- } else {
- $numActiveGuests++;
- }
- } else {
- $user = $this->userManager->get($participant->getUser());
- if ($user instanceof IUser) {
- $participantList[(string)$user->getUID()] = [
- 'name' => $user->getDisplayName(),
- 'type' => $participant->getParticipantType(),
- 'call' => $participant->getInCallFlags(),
- 'sessionId' => $participant->getSessionId(),
- ];
-
- if ($room->getType() === Room::ONE_TO_ONE_CALL &&
- $user->getUID() !== $currentParticipant->getUser()) {
- // FIXME This should not be done, but currently all the clients use it to get the avatar of the user …
- $roomData['name'] = $user->getUID();
- }
- }
-
- if ($participant->getSessionId() !== '0' && $participant->getLastPing() <= $this->timeFactory->getTime() - 100) {
- $room->leaveRoom($participant->getUser());
- }
- }
- }
+// uasort($participants, function (Participant $participant1, Participant $participant2) {
+// return $participant2->getLastPing() - $participant1->getLastPing();
+// });
+//
+// foreach ($participants as $participant) {
+// if ($participant->isGuest()) {
+// if ($participant->getLastPing() <= $this->timeFactory->getTime() - 100) {
+// $cleanGuests = true;
+// } else {
+// $numActiveGuests++;
+// }
+// } else {
+// $user = $this->userManager->get($participant->getUser());
+// if ($user instanceof IUser) {
+// $participantList[(string)$user->getUID()] = [
+// 'name' => $user->getDisplayName(),
+// 'type' => $participant->getParticipantType(),
+// 'call' => $participant->getInCallFlags(),
+// 'sessionId' => $participant->getSessionId(),
+// ];
+//
+// if ($room->getType() === Room::ONE_TO_ONE_CALL &&
+// $user->getUID() !== $currentParticipant->getUser()) {
+// // FIXME This should not be done, but currently all the clients use it to get the avatar of the user …
+// $roomData['name'] = $user->getUID();
+// }
+// }
+//
+// if ($participant->getSessionId() !== '0' && $participant->getLastPing() <= $this->timeFactory->getTime() - 100) {
+// $room->leaveRoom($participant->getUser());
+// }
+// }
+// }
if ($cleanGuests) {
$room->cleanGuestParticipants();
@@ -539,25 +557,34 @@ class RoomController extends AEnvironmentAwareController {
return $roomData;
}
+ $attendee = $currentParticipant->getAttendee();
+ $userId = $attendee->getActorType() === 'users' ? $attendee->getActorId() : '';
+
$roomData = array_merge($roomData, [
'name' => $room->getName(),
- 'displayName' => $room->getDisplayName($currentParticipant->getUser()),
+ 'displayName' => $room->getDisplayName($userId),
'objectType' => $room->getObjectType(),
'objectId' => $room->getObjectId(),
- 'participantType' => $currentParticipant->getParticipantType(),
- 'participantFlags' => $currentParticipant->getInCallFlags(),
+ 'participantType' => $attendee->getParticipantType(),
'readOnly' => $room->getReadOnly(),
'hasCall' => $room->getActiveSince() instanceof \DateTimeInterface,
'lastActivity' => $lastActivity,
- 'isFavorite' => $currentParticipant->isFavorite(),
- 'notificationLevel' => $currentParticipant->getNotificationLevel(),
+ 'isFavorite' => $attendee->isFavorite(),
+ 'notificationLevel' => $attendee->getNotificationLevel(),
'lobbyState' => $room->getLobbyState(),
'lobbyTimer' => $lobbyTimer,
'sipEnabled' => $room->getSIPEnabled(),
- 'lastPing' => $currentParticipant->getLastPing(),
- 'sessionId' => $currentParticipant->getSessionId(),
]);
+ $session = $currentParticipant->getSession();
+ if ($session instanceof Session) {
+ $roomData = array_merge($roomData, [
+ 'participantFlags' => $session->getInCall(),
+ 'lastPing' => $session->getLastPing(),
+ 'sessionId' => $session->getSessionId(),
+ ]);
+ }
+
if ($roomData['notificationLevel'] === Participant::NOTIFY_DEFAULT) {
if ($currentParticipant->isGuest()) {
$roomData['notificationLevel'] = Participant::NOTIFY_NEVER;
@@ -581,40 +608,43 @@ class RoomController extends AEnvironmentAwareController {
$roomData['canStartCall'] = $currentParticipant->canStartCall();
- $currentUser = $this->userManager->get($currentParticipant->getUser());
- if ($currentUser instanceof IUser) {
- $lastReadMessage = $currentParticipant->getLastReadMessage();
- if ($lastReadMessage === -1) {
- /*
- * Because the migration from the old comment_read_markers was
- * not possible in a programmatic way with a reasonable O(1) or O(n)
- * but only with O(user×chat), we do the conversion here.
- */
- $lastReadMessage = $this->chatManager->getLastReadMessageFromLegacy($room, $currentUser);
- $currentParticipant->setLastReadMessage($lastReadMessage);
- }
- if ($room->getLastMessage() && $lastReadMessage === (int) $room->getLastMessage()->getId()) {
- // When the last message is the last read message, there are no unread messages,
- // so we can save the query.
- $roomData['unreadMessages'] = 0;
- } else {
- $roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room, $lastReadMessage);
- }
+ if ($attendee->getActorType() === 'users') {
+ $currentUser = $this->userManager->get($attendee->getActorId());
+ if ($currentUser instanceof IUser) {
+ $lastReadMessage = $attendee->getLastReadMessage();
+ if ($lastReadMessage === -1) {
+ /*
+ * Because the migration from the old comment_read_markers was
+ * not possible in a programmatic way with a reasonable O(1) or O(n)
+ * but only with O(user×chat), we do the conversion here.
+ */
+ $lastReadMessage = $this->chatManager->getLastReadMessageFromLegacy($room, $currentUser);
+ $attendee->setLastReadMessage($lastReadMessage);
+ $this->attendeeMapper->update($attendee);
+ }
+ if ($room->getLastMessage() && $lastReadMessage === (int) $room->getLastMessage()->getId()) {
+ // When the last message is the last read message, there are no unread messages,
+ // so we can save the query.
+ $roomData['unreadMessages'] = 0;
+ } else {
+ $roomData['unreadMessages'] = $this->chatManager->getUnreadCount($room, $lastReadMessage);
+ }
- $lastMention = $currentParticipant->getLastMentionMessage();
- $roomData['unreadMention'] = $lastMention !== 0 && $lastReadMessage < $lastMention;
- $roomData['lastReadMessage'] = $lastReadMessage;
+ $lastMention = $attendee->getLastMentionMessage();
+ $roomData['unreadMention'] = $lastMention !== 0 && $lastReadMessage < $lastMention;
+ $roomData['lastReadMessage'] = $lastReadMessage;
- $roomData['canDeleteConversation'] = $room->getType() !== Room::ONE_TO_ONE_CALL
- && $currentParticipant->hasModeratorPermissions(false);
- $roomData['canLeaveConversation'] = true;
+ $roomData['canDeleteConversation'] = $room->getType() !== Room::ONE_TO_ONE_CALL
+ && $currentParticipant->hasModeratorPermissions(false);
+ $roomData['canLeaveConversation'] = true;
+ }
}
// FIXME This should not be done, but currently all the clients use it to get the avatar of the user …
if ($room->getType() === Room::ONE_TO_ONE_CALL) {
$participants = json_decode($room->getName(), true);
foreach ($participants as $participant) {
- if ($participant !== $currentParticipant->getUser()) {
+ if ($participant !== $attendee->getActorId()) {
$roomData['name'] = $participant;
}
}
@@ -861,7 +891,9 @@ class RoomController extends AEnvironmentAwareController {
* @return DataResponse
*/
public function addToFavorites(): DataResponse {
- $this->participant->setFavorite(true);
+ $attendee = $this->participant->getAttendee();
+ $attendee->setFavorite(true);
+ $this->attendeeMapper->update($attendee);
return new DataResponse([]);
}
@@ -872,7 +904,9 @@ class RoomController extends AEnvironmentAwareController {
* @return DataResponse
*/
public function removeFromFavorites(): DataResponse {
- $this->participant->setFavorite(false);
+ $attendee = $this->participant->getAttendee();
+ $attendee->setFavorite(false);
+ $this->attendeeMapper->update($attendee);
return new DataResponse([]);
}
@@ -884,10 +918,18 @@ class RoomController extends AEnvironmentAwareController {
* @return DataResponse
*/
public function setNotificationLevel(int $level): DataResponse {
- if (!$this->participant->setNotificationLevel($level)) {
+ if (!\in_array($level, [
+ Participant::NOTIFY_ALWAYS,
+ Participant::NOTIFY_MENTION,
+ Participant::NOTIFY_NEVER
+ ], true)) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
+ $attendee = $this->participant->getAttendee();
+ $attendee->setNotificationLevel($level);
+ $this->attendeeMapper->update($attendee);
+
return new DataResponse();
}
diff --git a/lib/Controller/SignalingController.php b/lib/Controller/SignalingController.php
index 4f75a818f..5ab3c5aee 100644
--- a/lib/Controller/SignalingController.php
+++ b/lib/Controller/SignalingController.php
@@ -32,6 +32,7 @@ use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Manager;
use OCA\Talk\Participant;
use OCA\Talk\Room;
+use OCA\Talk\Service\SessionService;
use OCA\Talk\Signaling\Messages;
use OCA\Talk\TalkSession;
use OCP\AppFramework\Http;
@@ -60,6 +61,8 @@ class SignalingController extends OCSController {
private $session;
/** @var Manager */
private $manager;
+ /** @var SessionService */
+ private $sessionService;
/** @var IDBConnection */
private $dbConnection;
/** @var Messages */
@@ -81,6 +84,7 @@ class SignalingController extends OCSController {
\OCA\Talk\Signaling\Manager $signalingManager,
TalkSession $session,
Manager $manager,
+ SessionService $sessionService,
IDBConnection $connection,
Messages $messages,
IUserManager $userManager,
@@ -94,6 +98,7 @@ class SignalingController extends OCSController {
$this->session = $session;
$this->dbConnection = $connection;
$this->manager = $manager;
+ $this->sessionService = $sessionService;
$this->messages = $messages;
$this->userManager = $userManager;
$this->dispatcher = $dispatcher;
@@ -597,7 +602,7 @@ class SignalingController extends OCSController {
}
// Ping all active sessions with one query
- $room->pingSessionIds($pingSessionIds, $now);
+ $this->sessionService->updateMultipleLastPings($pingSessionIds, $now);
$response = [
'type' => 'room',
diff --git a/lib/Manager.php b/lib/Manager.php
index 091c70368..a92aff209 100644
--- a/lib/Manager.php
+++ b/lib/Manager.php
@@ -27,6 +27,8 @@ use OCA\Talk\Chat\CommentsManager;
use OCA\Talk\Events\RoomEvent;
use OCA\Talk\Exceptions\ParticipantNotFoundException;
use OCA\Talk\Exceptions\RoomNotFoundException;
+use OCA\Talk\Model\AttendeeMapper;
+use OCA\Talk\Model\SessionMapper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
@@ -51,6 +53,10 @@ class Manager {
private $config;
/** @var Config */
private $talkConfig;
+ /** @var AttendeeMapper */
+ private $attendeeMapper;
+ /** @var SessionMapper */
+ private $sessionMapper;
/** @var ISecureRandom */
private $secureRandom;
/** @var IUserManager */
@@ -71,6 +77,8 @@ class Manager {
public function __construct(IDBConnection $db,
IConfig $config,
Config $talkConfig,
+ AttendeeMapper $attendeeMapper,
+ SessionMapper $sessionMapper,
ISecureRandom $secureRandom,
IUserManager $userManager,
CommentsManager $commentsManager,
@@ -82,6 +90,8 @@ class Manager {
$this->db = $db;
$this->config = $config;
$this->talkConfig = $talkConfig;
+ $this->attendeeMapper = $attendeeMapper;
+ $this->sessionMapper = $sessionMapper;
$this->secureRandom = $secureRandom;
$this->userManager = $userManager;
$this->commentsManager = $commentsManager;
@@ -147,7 +157,7 @@ class Manager {
$this->dispatcher,
$this->timeFactory,
$this->hasher,
- (int) $row['id'],
+ (int) $row['r_id'],
(int) $row['type'],
(int) $row['read_only'],
(int) $row['lobby_state'],
@@ -173,25 +183,18 @@ class Manager {
* @return Participant
*/
public function createParticipantObject(Room $room, array $row): Participant {
- $lastJoinedCall = null;
- if (!empty($row['last_joined_call'])) {
- $lastJoinedCall = $this->timeFactory->getDateTime($row['last_joined_call']);
+ $attendee = $this->attendeeMapper->createAttendeeFromRow($row);
+ $session = null;
+ if (!empty($row['s_id'])) {
+ $session = $this->sessionMapper->createSessionFromRow($row);
}
return new Participant(
$this->db,
$this->config,
$room,
- (string) $row['actor_id'],
- (int) $row['participant_type'],
- 0, // FIXME this is in talk_sessions now (int) $row['last_ping'],
- '0', // FIXME this is in talk_sessions now (string) $row['session_id'],
- Participant::FLAG_DISCONNECTED, // FIXME this is in talk_sessions now (int) $row['in_call'],
- (int) $row['notification_level'],
- (bool) $row['favorite'],
- (int) $row['last_read_message'],
- (int) $row['last_mention_message'],
- $lastJoinedCall
+ $attendee,
+ $session
);
}
@@ -249,6 +252,7 @@ class Manager {
public function searchRoomsByToken(string $searchToken = '', int $limit = null, int $offset = null): array {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms')
->setMaxResults(1);
@@ -293,7 +297,10 @@ class Manager {
*/
public function getRoomsForUser(string $userId, bool $includeLastMessage = false): array {
$query = $this->db->getQueryBuilder();
- $query->select('r.*')->addSelect('a.*')
+ $query->select('r.*')
+ ->addSelect('a.*')
+ ->selectAlias('r.id', 'r_id')
+ ->selectAlias('a.id', 'a_id')
->from('talk_rooms', 'r')
->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
@@ -346,12 +353,15 @@ class Manager {
*/
public function getRoomForUser(int $roomId, ?string $userId): Room {
$query = $this->db->getQueryBuilder();
- $query->select('*')
+ $query->select('r.*')
+ ->selectAlias('r.id', 'r_id')
->from('talk_rooms', 'r')
->where($query->expr()->eq('r.id', $query->createNamedParameter($roomId, IQueryBuilder::PARAM_INT)));
if ($userId !== null) {
// Non guest user
+ $query->addSelect('a.*')
+ ->selectAlias('a.id', 'a_id');
$query->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
$query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
@@ -411,14 +421,16 @@ class Manager {
public function getRoomForUserByToken(string $token, ?string $userId, bool $includeLastMessage = false): Room {
$query = $this->db->getQueryBuilder();
$query->select('r.*')
+ ->selectAlias('r.id', 'r_id')
->from('talk_rooms', 'r')
->where($query->expr()->eq('r.token', $query->createNamedParameter($token)))
->setMaxResults(1);
if ($userId !== null) {
// Non guest user
- $query->addSelect('p.*')
- ->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
+ $query->addSelect('a.*')
+ ->selectAlias('a.id', 'a_id');
+ $query->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($userId)),
$query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
$query->expr()->eq('a.room_id', 'r.id')
@@ -466,6 +478,7 @@ class Manager {
public function getRoomById(int $roomId): Room {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms')
->where($query->expr()->eq('id', $query->createNamedParameter($roomId, IQueryBuilder::PARAM_INT)));
@@ -496,12 +509,15 @@ class Manager {
$query = $this->db->getQueryBuilder();
$query->select('r.*')
+ ->selectAlias('r.id', 'r_id')
->from('talk_rooms', 'r')
->where($query->expr()->eq('r.token', $query->createNamedParameter($token)));
if ($preloadUserId !== null) {
+
$query->addSelect('a.*')
- ->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
+ ->selectAlias('a.id', 'a_id');
+ $query->leftJoin('r', 'talk_attendees', 'a', $query->expr()->andX(
$query->expr()->eq('a.actor_id', $query->createNamedParameter($preloadUserId)),
$query->expr()->eq('a.actor_type', $query->createNamedParameter('users')),
$query->expr()->eq('a.room_id', 'r.id')
@@ -538,6 +554,7 @@ class Manager {
public function getRoomByObject(string $objectType, string $objectId): Room {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms')
->where($query->expr()->eq('object_type', $query->createNamedParameter($objectType)))
->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId)));
@@ -617,6 +634,7 @@ class Manager {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms')
->where($query->expr()->eq('type', $query->createNamedParameter(Room::ONE_TO_ONE_CALL, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('name', $query->createNamedParameter($name)));
@@ -646,6 +664,7 @@ class Manager {
public function getChangelogRoom(string $userId): Room {
$query = $this->db->getQueryBuilder();
$query->select('*')
+ ->selectAlias('id', 'r_id')
->from('talk_rooms')
->where($query->expr()->eq('type', $query->createNamedParameter(Room::CHANGELOG_CONVERSATION, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('name', $query->createNamedParameter($userId)));
diff --git a/lib/Middleware/InjectionMiddleware.php b/lib/Middleware/InjectionMiddleware.php
index 9b7e89427..5ef6d17ba 100644
--- a/lib/Middleware/InjectionMiddleware.php
+++ b/lib/Middleware/InjectionMiddleware.php
@@ -117,7 +117,7 @@ class InjectionMiddleware extends Middleware {
*/
protected function getLoggedIn(AEnvironmentAwareController $controller, bool $moderatorRequired): void {
$token = $this->request->getParam('token');
- $room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
+ $room = $this->manager->getRoomForUserByToken($token, $this->userId);
$controller->setRoom($room);
$participant = $room->getParticipant($this->userId);
@@ -136,7 +136,7 @@ class InjectionMiddleware extends Middleware {
*/
protected function getLoggedInOrGuest(AEnvironmentAwareController $controller, bool $moderatorRequired): void {
$token = $this->request->getParam('token');
- $room = $this->manager->getRoomForParticipantByToken($token, $this->userId);
+ $room = $this->manager->getRoomForUserByToken($token, $this->userId);
$controller->setRoom($room);
if ($this->userId !== null) {
diff --git a/lib/Migration/Version10000Date20201015134000.php b/lib/Migration/Version10000Date20201015134000.php
index b4b19ff36..4ed340a14 100644
--- a/lib/Migration/Version10000Date20201015134000.php
+++ b/lib/Migration/Version10000Date20201015134000.php
@@ -101,8 +101,11 @@ class Version10000Date20201015134000 extends SimpleMigrationStep {
'default' => Participant::NOTIFY_DEFAULT,
'notnull' => false,
]);
- $table->addColumn('last_joined_call', Type::DATETIME, [
- 'notnull' => false,
+ $table->addColumn('last_joined_call', Type::INTEGER, [
+ 'notnull' => true,
+ 'length' => 11,
+ 'default' => 0,
+ 'unsigned' => true,
]);
$table->addColumn('last_read_message', Type::BIGINT, [
'default' => 0,
@@ -194,9 +197,9 @@ class Version10000Date20201015134000 extends SimpleMigrationStep {
$result = $query->execute();
while ($row = $result->fetch()) {
- $lastJoinedCall = null;
+ $lastJoinedCall = 0;
if (!empty($row['last_joined_call'])) {
- $lastJoinedCall = $this->timeFactory->getDateTime($row['last_joined_call']);
+ $lastJoinedCall = $this->timeFactory->getDateTime($row['last_joined_call'])->getTimestamp();
}
$insert
@@ -206,7 +209,7 @@ class Version10000Date20201015134000 extends SimpleMigrationStep {
->setParameter('participant_type', (int) $row['participant_type'], IQueryBuilder::PARAM_INT)
->setParameter('favorite', (bool) $row['favorite'], IQueryBuilder::PARAM_BOOL)
->setParameter('notification_level', (int) $row['notification_level'], IQueryBuilder::PARAM_INT)
- ->setParameter('last_joined_call', $lastJoinedCall, IQueryBuilder::PARAM_DATE)
+ ->setParameter('last_joined_call', $lastJoinedCall, IQueryBuilder::PARAM_INT)
->setParameter('last_read_message', (int) $row['last_read_message'], IQueryBuilder::PARAM_INT)
->setParameter('last_mention_message', (int) $row['last_mention_message'], IQueryBuilder::PARAM_INT)
;
diff --git a/lib/Model/Attendee.php b/lib/Model/Attendee.php
new file mode 100644
index 000000000..6c5690803
--- /dev/null
+++ b/lib/Model/Attendee.php
@@ -0,0 +1,113 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Model;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * @method void setRoomId(int $roomId)
+ * @method string getRoomId()
+ * @method void setActorType(string $actorType)
+ * @method string getActorType()
+ * @method void setActorId(string $actorId)
+ * @method string getActorId()
+ * @method void setPin(string $pin)
+ * @method string getPin()
+ * @method void setParticipantType(int $participantType)
+ * @method int getParticipantType()
+ * @method void setFavorite(bool $favorite)
+ * @method bool isFavorite()
+ * @method void setNotificationLevel(int $notificationLevel)
+ * @method int getNotificationLevel()
+ * @method void setLastJoinedCall(int $lastJoinedCall)
+ * @method int getLastJoinedCall()
+ * @method void setLastReadMessage(int $lastReadMessage)
+ * @method int getLastReadMessage()
+ * @method void setLastMentionMessage(int $lastMentionMessage)
+ * @method int getLastMentionMessage()
+ */
+class Attendee extends Entity {
+
+ /** @var int */
+ protected $roomId;
+
+ /** @var string */
+ protected $actorType;
+
+ /** @var string */
+ protected $actorId;
+
+ /** @var string */
+ protected $pin;
+
+ /** @var int */
+ protected $participantType;
+
+ /** @var bool */
+ protected $favorite;
+
+ /** @var int */
+ protected $notificationLevel;
+
+ /** @var int */
+ protected $lastJoinedCall;
+
+ /** @var int */
+ protected $lastReadMessage;
+
+ /** @var int */
+ protected $lastMentionMessage;
+
+ public function __construct() {
+ $this->addType('room_id', 'int');
+ $this->addType('actor_type', 'string');
+ $this->addType('actor_id', 'string');
+ $this->addType('pin', 'string');
+ $this->addType('participant_type', 'int');
+ $this->addType('favorite', 'bool');
+ $this->addType('notification_level', 'int');
+ $this->addType('last_joined_call', 'int');
+ $this->addType('last_read_message', 'int');
+ $this->addType('last_mention_message', 'int');
+ }
+
+ /**
+ * @return array
+ */
+ public function asArray(): array {
+ return [
+ 'id' => $this->getId(),
+ 'room_id' => $this->getRoomId(),
+ 'actor_type' => $this->getActorType(),
+ 'actor_id' => $this->getActorId(),
+ 'pin' => $this->getPin(),
+ 'participant_type' => $this->getParticipantType(),
+ 'favorite' => $this->isFavorite(),
+ 'notification_level' => $this->getNotificationLevel(),
+ 'last_joined_call' => $this->getLastJoinedCall(),
+ 'last_read_message' => $this->getLastReadMessage(),
+ 'last_mention_message' => $this->getLastMentionMessage(),
+ ];
+ }
+}
diff --git a/lib/Model/AttendeeMapper.php b/lib/Model/AttendeeMapper.php
new file mode 100644
index 000000000..4c7e7dcd8
--- /dev/null
+++ b/lib/Model/AttendeeMapper.php
@@ -0,0 +1,72 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Model;
+
+use OCP\AppFramework\Db\QBMapper;
+use OCP\IDBConnection;
+
+/**
+ * @method Attendee mapRowToEntity(array $row)
+ */
+class AttendeeMapper extends QBMapper {
+
+ /**
+ * @param IDBConnection $db
+ */
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'talk_attendees', Attendee::class);
+ }
+
+ /**
+ * @param string $actorType
+ * @param string $actorId
+ * @return Attendee
+ * @throws \OCP\AppFramework\Db\DoesNotExistException
+ */
+ public function findByActor(string $actorType, string $actorId): Attendee {
+ $query = $this->db->getQueryBuilder();
+ $query->select('*')
+ ->from($this->getTableName())
+ ->where($query->expr()->eq('actor_type', $query->createNamedParameter($actorType)))
+ ->andWhere($query->expr()->eq('actor_id', $query->createNamedParameter($actorId)));
+
+ return $this->findEntity($query);
+ }
+
+ public function createAttendeeFromRow(array $row): Attendee {
+ return $this->mapRowToEntity([
+ 'id' => $row['a_id'],
+ 'room_id' => $row['id'],
+ 'actor_type' => $row['actor_type'],
+ 'actor_id' => $row['actor_id'],
+ 'pin' => $row['pin'],
+ 'participant_type' => (int) $row['participant_type'],
+ 'favorite' => (bool) $row['favorite'],
+ 'notification_level' => (int) $row['notification_level'],
+ 'last_joined_call' => (int) $row['last_joined_call'],
+ 'last_read_message' => (int) $row['last_read_message'],
+ 'last_mention_message' => (int) $row['last_mention_message'],
+ ]);
+ }
+}
diff --git a/lib/Model/Session.php b/lib/Model/Session.php
new file mode 100644
index 000000000..c647e7082
--- /dev/null
+++ b/lib/Model/Session.php
@@ -0,0 +1,71 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Model;
+
+use OCP\AppFramework\Db\Entity;
+
+/**
+ * @method void setAttendeeId(int $attendeeId)
+ * @method string getAttendeeId()
+ * @method void setSessionId(string $sessionId)
+ * @method string getSessionId()
+ * @method void setInCall(int $inCall)
+ * @method int getInCall()
+ * @method void setLastPing(int $lastPing)
+ * @method int getLastPing()
+ */
+class Session extends Entity {
+
+ /** @var int */
+ protected $attendeeId;
+
+ /** @var string */
+ protected $sessionId;
+
+ /** @var int */
+ protected $inCall;
+
+ /** @var int */
+ protected $lastPing;
+
+ public function __construct() {
+ $this->addType('attendee_id', 'int');
+ $this->addType('session_id', 'string');
+ $this->addType('in_call', 'int');
+ $this->addType('last_ping', 'int');
+ }
+
+ /**
+ * @return array
+ */
+ public function asArray(): array {
+ return [
+ 'id' => $this->getId(),
+ 'attendee_id' => $this->getAttendeeId(),
+ 'session_id' => $this->getSessionId(),
+ 'in_call' => $this->getInCall(),
+ 'last_ping' => $this->getLastPing(),
+ ];
+ }
+}
diff --git a/lib/Model/SessionMapper.php b/lib/Model/SessionMapper.php
new file mode 100644
index 000000000..c45cafd90
--- /dev/null
+++ b/lib/Model/SessionMapper.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Model;
+
+use OCP\AppFramework\Db\QBMapper;
+use OCP\IDBConnection;
+
+/**
+ * @method Session mapRowToEntity(array $row)
+ */
+class SessionMapper extends QBMapper {
+
+ /**
+ * @param IDBConnection $db
+ */
+ public function __construct(IDBConnection $db) {
+ parent::__construct($db, 'talk_sessions', Session::class);
+ }
+
+ /**
+ * @param string $sessionId
+ * @return Session
+ * @throws \OCP\AppFramework\Db\DoesNotExistException
+ */
+ public function findBySessionId(string $sessionId): Session {
+ $query = $this->db->getQueryBuilder();
+ $query->select('*')
+ ->from($this->getTableName())
+ ->where($query->expr()->eq('session_id', $query->createNamedParameter($sessionId)));
+
+ return $this->findEntity($query);
+ }
+
+ public function createSessionFromRow(array $row): Session {
+ return $this->mapRowToEntity([
+ 'id' => $row['s_id'],
+ 'session_id' => $row['session_id'],
+ 'attendee_id' => (int) $row['a_id'],
+ 'in_call' => (int) $row['in_call'],
+ 'last_ping' => (int) $row['last_ping'],
+ ]);
+ }
+}
diff --git a/lib/Participant.php b/lib/Participant.php
index 3b6d61c12..f8bd34a53 100644
--- a/lib/Participant.php
+++ b/lib/Participant.php
@@ -25,7 +25,8 @@ declare(strict_types=1);
namespace OCA\Talk;
-use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCA\Talk\Model\Attendee;
+use OCA\Talk\Model\Session;
use OCP\IConfig;
use OCP\IDBConnection;
@@ -54,180 +55,43 @@ class Participant {
protected $config;
/** @var Room */
protected $room;
- /** @var string */
- protected $user;
- /** @var int */
- protected $participantType;
- /** @var int */
- protected $lastPing;
- /** @var string */
- protected $sessionId;
- /** @var int */
- protected $inCall;
- /** @var int */
- protected $notificationLevel;
- /** @var bool */
- private $isFavorite;
- /** @var int */
- private $lastReadMessage;
- /** @var int */
- private $lastMentionMessage;
- /** @var \DateTime|null */
- private $lastJoinedCall;
+ /** @var Attendee */
+ protected $attendee;
+ /** @var Session|null */
+ protected $session;
public function __construct(IDBConnection $db,
IConfig $config,
Room $room,
- string $user,
- int $participantType,
- int $lastPing,
- string $sessionId,
- int $inCall,
- int $notificationLevel,
- bool $isFavorite,
- int $lastReadMessage,
- int $lastMentionMessage,
- \DateTime $lastJoinedCall = null) {
+ Attendee $attendee,
+ ?Session $session) {
$this->db = $db;
$this->config = $config;
$this->room = $room;
- $this->user = $user;
- $this->participantType = $participantType;
- $this->lastPing = $lastPing;
- $this->sessionId = $sessionId;
- $this->inCall = $inCall;
- $this->notificationLevel = $notificationLevel;
- $this->isFavorite = $isFavorite;
- $this->lastReadMessage = $lastReadMessage;
- $this->lastMentionMessage = $lastMentionMessage;
- $this->lastJoinedCall = $lastJoinedCall;
+ $this->attendee = $attendee;
+ $this->session = $session;
}
- public function getUser(): string {
- return $this->user;
+ public function getAttendee(): Attendee {
+ return $this->attendee;
}
- public function getParticipantType(): int {
- return $this->participantType;
+ public function getSession(): ?Session {
+ return $this->session;
}
public function isGuest(): bool {
- return \in_array($this->participantType, [self::GUEST, self::GUEST_MODERATOR], true);
+ $participantType = $this->attendee->getParticipantType();
+ return \in_array($participantType, [self::GUEST, self::GUEST_MODERATOR], true);
}
public function hasModeratorPermissions(bool $guestModeratorAllowed = true): bool {
+ $participantType = $this->attendee->getParticipantType();
if (!$guestModeratorAllowed) {
- return \in_array($this->participantType, [self::OWNER, self::MODERATOR], true);
+ return \in_array($participantType, [self::OWNER, self::MODERATOR], true);
}
- return \in_array($this->participantType, [self::OWNER, self::MODERATOR, self::GUEST_MODERATOR], true);
- }
-
- public function getLastPing(): int {
- return $this->lastPing;
- }
-
- public function getSessionId(): string {
- return $this->sessionId;
- }
-
- public function getInCallFlags(): int {
- return $this->inCall;
- }
-
- /**
- * @return \DateTime|null
- */
- public function getJoinedCall(): ?\DateTime {
- return $this->lastJoinedCall;
- }
-
- public function isFavorite(): bool {
- return $this->isFavorite;
- }
-
- public function setFavorite(bool $favor): bool {
- if (!$this->user) {
- return false;
- }
-
- $query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
- ->set('favorite', $query->createNamedParameter((int) $favor, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->eq('user_id', $query->createNamedParameter($this->user)))
- ->andWhere($query->expr()->eq('room_id', $query->createNamedParameter($this->room->getId())));
- $query->execute();
-
- $this->isFavorite = $favor;
- return true;
- }
-
- public function getNotificationLevel(): int {
- return $this->notificationLevel;
- }
-
- public function setNotificationLevel(int $notificationLevel): bool {
- if (!$this->user) {
- return false;
- }
-
- if (!\in_array($notificationLevel, [
- self::NOTIFY_ALWAYS,
- self::NOTIFY_MENTION,
- self::NOTIFY_NEVER
- ], true)) {
- return false;
- }
-
- $query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
- ->set('notification_level', $query->createNamedParameter($notificationLevel, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->eq('user_id', $query->createNamedParameter($this->user)))
- ->andWhere($query->expr()->eq('room_id', $query->createNamedParameter($this->room->getId())));
- $query->execute();
-
- $this->notificationLevel = $notificationLevel;
- return true;
- }
-
- public function getLastReadMessage(): int {
- return $this->lastReadMessage;
- }
-
- public function setLastReadMessage(int $messageId): bool {
- if (!$this->user) {
- return false;
- }
-
- $query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
- ->set('last_read_message', $query->createNamedParameter($messageId, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->eq('user_id', $query->createNamedParameter($this->user)))
- ->andWhere($query->expr()->eq('room_id', $query->createNamedParameter($this->room->getId())));
- $query->execute();
-
- $this->lastReadMessage = $messageId;
- return true;
- }
-
- public function getLastMentionMessage(): int {
- return $this->lastMentionMessage;
- }
-
- public function setLastMentionMessage(int $messageId): bool {
- if (!$this->user) {
- return false;
- }
-
- $query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
- ->set('last_mention_message', $query->createNamedParameter($messageId, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->eq('user_id', $query->createNamedParameter($this->user)))
- ->andWhere($query->expr()->eq('room_id', $query->createNamedParameter($this->room->getId())));
- $query->execute();
-
- $this->lastMentionMessage = $messageId;
- return true;
+ return \in_array($participantType, [self::OWNER, self::MODERATOR, self::GUEST_MODERATOR], true);
}
public function canStartCall(): bool {
diff --git a/lib/Room.php b/lib/Room.php
index 622620224..824f2e9a7 100644
--- a/lib/Room.php
+++ b/lib/Room.php
@@ -403,8 +403,8 @@ class Room {
$this->dispatcher->dispatch(self::EVENT_BEFORE_ROOM_DELETE, $event);
$query = $this->db->getQueryBuilder();
- // Delete all participants
- $query->delete('talk_participants')
+ // Delete attendees
+ $query->delete('talk_attendees')
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)));
$query->execute();
@@ -583,7 +583,7 @@ class Room {
if ($oldType === self::PUBLIC_CALL) {
// Kick all guests and users that were not invited
$query = $this->db->getQueryBuilder();
- $query->delete('talk_participants')
+ $query->delete('talk_attendees')
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->in('participant_type', $query->createNamedParameter([Participant::GUEST, Participant::USER_SELF_JOINED], IQueryBuilder::PARAM_INT_ARRAY)));
$query->execute();
@@ -785,12 +785,14 @@ class Room {
$this->dispatcher->dispatch(self::EVENT_BEFORE_PARTICIPANT_TYPE_SET, $event);
$query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
+ $query->update('talk_attendees')
->set('participant_type', $query->createNamedParameter($participantType, IQueryBuilder::PARAM_INT))
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($participant->getUser())));
+ ->andWhere($query->expr()->eq('actor_id', $query->createNamedParameter($participant->getUser())))
+ ->andWhere($query->expr()->eq('actor_type', $query->createNamedParameter('users')));
if ($participant->getUser() === '') {
+ // FIXME
$query->andWhere($query->expr()->eq('session_id', $query->createNamedParameter($participant->getSessionId())));
}
@@ -814,9 +816,10 @@ class Room {
$this->dispatcher->dispatch(self::EVENT_BEFORE_USER_REMOVE, $event);
$query = $this->db->getQueryBuilder();
- $query->delete('talk_participants')
+ $query->delete('talk_attendees')
->where($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
- ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($user->getUID())));
+ ->andWhere($query->expr()->eq('actor_id', $query->createNamedParameter($user->getUID())))
+ ->andWhere($query->expr()->eq('actor_type', $query->createNamedParameter('users')));
$query->execute();
$this->dispatcher->dispatch(self::EVENT_AFTER_USER_REMOVE, $event);
@@ -929,8 +932,9 @@ class Room {
// And kill session when leaving a self joined room
$query = $this->db->getQueryBuilder();
- $query->delete('talk_participants')
- ->where($query->expr()->eq('user_id', $query->createNamedParameter($participant->getUser())))
+ $query->delete('talk_attendees')
+ ->where($query->expr()->eq('actor_id', $query->createNamedParameter($participant->getUser())))
+ ->andWhere($query->expr()->eq('actor_type', $query->createNamedParameter('users')))
->andWhere($query->expr()->eq('room_id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('participant_type', $query->createNamedParameter(Participant::USER_SELF_JOINED, IQueryBuilder::PARAM_INT)));
if ($sessionId !== null && $sessionId !== '0') {
@@ -1388,17 +1392,4 @@ class Room {
$query->execute();
}
-
- /**
- * @param string[] $sessionIds
- * @param int $timestamp
- */
- public function pingSessionIds(array $sessionIds, int $timestamp): void {
- $query = $this->db->getQueryBuilder();
- $query->update('talk_participants')
- ->set('last_ping', $query->createNamedParameter($timestamp, IQueryBuilder::PARAM_INT))
- ->where($query->expr()->in('session_id', $query->createNamedParameter($sessionIds, IQueryBuilder::PARAM_STR_ARRAY)));
-
- $query->execute();
- }
}
diff --git a/lib/Service/SessionService.php b/lib/Service/SessionService.php
new file mode 100644
index 000000000..822a7b710
--- /dev/null
+++ b/lib/Service/SessionService.php
@@ -0,0 +1,60 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Joas Schilling <coding@schilljs.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OCA\Talk\Service;
+
+use OCA\Talk\Model\SessionMapper;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class SessionService {
+ /** @var SessionMapper */
+ protected $mapper;
+ /** @var IDBConnection */
+ protected $connection;
+
+ public function __construct(SessionMapper $mapper,
+ IDBConnection $connection) {
+ $this->mapper = $mapper;
+ $this->connection = $connection;
+ }
+
+ /**
+ * Update last ping for multiple sessions
+ *
+ * Since this function is called by the HPB with potentially hundreds of
+ * sessions, we do not use the SessionMapper to get the entities first, as
+ * that would just not scale good enough.
+ *
+ * @param string[] $sessionIds
+ * @param int $lastPing
+ */
+ public function updateMultipleLastPings(array $sessionIds, int $lastPing): void {
+ $query = $this->connection->getQueryBuilder();
+ $query->update('talk_sessions')
+ ->set('last_ping', $query->createNamedParameter($lastPing, IQueryBuilder::PARAM_INT))
+ ->where($query->expr()->in('session_id', $query->createNamedParameter($sessionIds, IQueryBuilder::PARAM_STR_ARRAY)));
+
+ $query->execute();
+ }
+}