]> source.dussan.org Git - nextcloud-server.git/commitdiff
fix(userstatus): CALL status should overwrite MEETING status
authorAnna Larch <anna@nextcloud.com>
Wed, 17 Jan 2024 15:15:15 +0000 (16:15 +0100)
committerAnna Larch <anna@nextcloud.com>
Wed, 24 Jan 2024 17:23:21 +0000 (18:23 +0100)
Signed-off-by: Anna Larch <anna@nextcloud.com>
apps/dav/lib/CalDAV/Status/StatusService.php
apps/user_status/lib/Service/StatusService.php
apps/user_status/tests/Integration/Service/StatusServiceIntegrationTest.php

index 3fcd4957fa2314176239100ce4f73e8fd4380e14..58f2d5883fcb2bd042278b965dd7db02466d5082 100644 (file)
@@ -77,12 +77,13 @@ class StatusService {
                        return;
                }
 
-               $userStatusTimestamp = null;
-               $currentStatus = null;
                try {
                        $currentStatus = $this->userStatusService->findByUserId($userId);
-                       $userStatusTimestamp = $currentStatus->getIsUserDefined() ? $currentStatus->getStatusTimestamp() : null;
+                       // Was the status set by anything other than the calendar automation?
+                       $userStatusTimestamp = $currentStatus->getIsUserDefined() && $currentStatus->getMessageId() !== IUserStatus::MESSAGE_CALENDAR_BUSY ? $currentStatus->getStatusTimestamp() : null;
                } catch (DoesNotExistException) {
+                       $userStatusTimestamp = null;
+                       $currentStatus = null;
                }
 
                if($currentStatus !== null && $currentStatus->getMessageId() === IUserStatus::MESSAGE_CALL
@@ -123,19 +124,21 @@ class StatusService {
                        return;
                }
 
-               // One event that fulfills all status conditions is enough
-               // 1. Not an OOO event
-               // 2. Current user status was not set after the start of this event
-               // 3. Event is not set to be transparent
-               $count = count($applicableEvents);
-               $this->logger->debug("Found $count applicable event(s), changing user status", ['user' => $userId]);
-               $this->userStatusService->setUserStatus(
-                       $userId,
-                       IUserStatus::AWAY,
-                       IUserStatus::MESSAGE_CALENDAR_BUSY,
-                       true
-               );
-
+               // Only update the status if it's neccesary otherwise we mess up the timestamp
+               if($currentStatus !== null && $currentStatus->getMessageId() !== IUserStatus::MESSAGE_CALENDAR_BUSY) {
+                       // One event that fulfills all status conditions is enough
+                       // 1. Not an OOO event
+                       // 2. Current user status (that is not a calendar status) was not set after the start of this event
+                       // 3. Event is not set to be transparent
+                       $count = count($applicableEvents);
+                       $this->logger->debug("Found $count applicable event(s), changing user status", ['user' => $userId]);
+                       $this->userStatusService->setUserStatus(
+                               $userId,
+                               IUserStatus::AWAY,
+                               IUserStatus::MESSAGE_CALENDAR_BUSY,
+                               true
+                       );
+               }
        }
 
        private function getCalendarEvents(User $user): array {
index c623262eec65d38ed5ca06542745625e92512e2d..813f6b9d4e171f79f63102b4a4ea45999653c833 100644 (file)
@@ -172,8 +172,6 @@ class StatusService {
                        throw new InvalidStatusTypeException('Status-type "' . $status . '" is not supported');
                }
 
-
-
                if ($statusTimestamp === null) {
                        $statusTimestamp = $this->timeFactory->getTime();
                }
@@ -257,21 +255,38 @@ class StatusService {
                        throw new InvalidMessageIdException('Message-Id "' . $messageId . '" is not supported');
                }
 
+               try {
+                       $userStatus = $this->mapper->findByUserId($userId);
+               } catch (DoesNotExistException $e) {
+                       // We don't need to do anything
+                       $userStatus = new UserStatus();
+                       $userStatus->setUserId($userId);
+               }
+
+               // CALL trumps CALENDAR status, but we don't need to do anything but overwrite the message
+               if ($userStatus->getMessageId() === IUserStatus::MESSAGE_CALENDAR_BUSY && $messageId === IUserStatus::MESSAGE_CALL) {
+                       $userStatus->setStatus($status);
+                       $userStatus->setStatusTimestamp($this->timeFactory->getTime());
+                       $userStatus->setIsUserDefined(true);
+                       $userStatus->setIsBackup(false);
+                       $userStatus->setMessageId($messageId);
+                       $userStatus->setCustomIcon(null);
+                       $userStatus->setCustomMessage($customMessage);
+                       $userStatus->setClearAt(null);
+                       $userStatus->setStatusMessageTimestamp($this->timeFactory->now()->getTimestamp());
+                       return $this->mapper->update($userStatus);
+               }
+
                if ($createBackup) {
                        if ($this->backupCurrentStatus($userId) === false) {
                                return null; // Already a status set automatically => abort.
                        }
 
                        // If we just created the backup
+                       // we need to create a new status to insert
+                       // Unfortunatley there's no way to unset the DB ID on an Entity
                        $userStatus = new UserStatus();
                        $userStatus->setUserId($userId);
-               } else {
-                       try {
-                               $userStatus = $this->mapper->findByUserId($userId);
-                       } catch (DoesNotExistException $ex) {
-                               $userStatus = new UserStatus();
-                               $userStatus->setUserId($userId);
-                       }
                }
 
                $userStatus->setStatus($status);
index 182cac562179df29bdea5fbcd1ea1a418ab10675..9179f066fa85d471345b3f256528de0282406a33 100644 (file)
@@ -126,6 +126,73 @@ class StatusServiceIntegrationTest extends TestCase {
                );
        }
 
+       public function testCallOverwritesMeetingStatus(): void {
+               $this->service->setStatus(
+                       'test123',
+                       IUserStatus::ONLINE,
+                       null,
+                       false,
+               );
+               $this->service->setUserStatus(
+                       'test123',
+                       IUserStatus::AWAY,
+                       IUserStatus::MESSAGE_CALENDAR_BUSY,
+                       true,
+               );
+               self::assertSame(
+                       'meeting',
+                       $this->service->findByUserId('test123')->getMessageId(),
+               );
+
+               $this->service->setUserStatus(
+                       'test123',
+                       IUserStatus::AWAY,
+                       IUserStatus::MESSAGE_CALL,
+                       true,
+               );
+               self::assertSame(
+                       IUserStatus::AWAY,
+                       $this->service->findByUserId('test123')->getStatus(),
+               );
+
+               self::assertSame(
+                       IUserStatus::MESSAGE_CALL,
+                       $this->service->findByUserId('test123')->getMessageId(),
+               );
+       }
+
+       public function testOtherAutomationsDoNotOverwriteEachOther(): void {
+               $this->service->setStatus(
+                       'test123',
+                       IUserStatus::ONLINE,
+                       null,
+                       false,
+               );
+               $this->service->setUserStatus(
+                       'test123',
+                       IUserStatus::AWAY,
+                       IUserStatus::MESSAGE_CALENDAR_BUSY,
+                       true,
+               );
+               self::assertSame(
+                       'meeting',
+                       $this->service->findByUserId('test123')->getMessageId(),
+               );
+
+               $nostatus = $this->service->setUserStatus(
+                       'test123',
+                       IUserStatus::AWAY,
+                       IUserStatus::MESSAGE_AVAILABILITY,
+                       true,
+               );
+
+               self::assertNull($nostatus);
+               self::assertSame(
+                       IUserStatus::MESSAGE_CALENDAR_BUSY,
+                       $this->service->findByUserId('test123')->getMessageId(),
+               );
+       }
+
        public function testCi(): void {
                // TODO: remove if CI turns red
                self::assertTrue(false);