Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Allow to revert the user status of multiple users in 3 queries instea…
…d of 3*n

Signed-off-by: Joas Schilling <[email protected]>
  • Loading branch information
nickvergessen committed Feb 15, 2022
commit deec4f31dbe02008207f9b8c21f0302af919c652
4 changes: 4 additions & 0 deletions apps/user_status/lib/Connector/UserStatusProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,8 @@ public function setUserStatus(string $userId, string $messageId, string $status,
public function revertUserStatus(string $userId, string $messageId, string $status): void {
$this->service->revertUserStatus($userId, $messageId, $status);
}

public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void {
$this->service->revertMultipleUserStatus($userIds, $messageId, $status);
}
}
19 changes: 18 additions & 1 deletion apps/user_status/lib/Db/UserStatusMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public function findByUserId(string $userId, bool $isBackup = false):UserStatus
* @param array $userIds
* @return array
*/
public function findByUserIds(array $userIds):array {
public function findByUserIds(array $userIds): array {
$qb = $this->db->getQueryBuilder();
$qb
->select('*')
Expand Down Expand Up @@ -177,4 +177,21 @@ public function deleteCurrentStatusToRestoreBackup(string $userId, string $messa
->andWhere($qb->expr()->eq('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)));
return $qb->executeStatement() > 0;
}

public function deleteByIds(array $ids): void {
$qb = $this->db->getQueryBuilder();
$qb->delete($this->tableName)
->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
$qb->executeStatement();
}

public function restoreBackupStatuses(array $ids): void {
$qb = $this->db->getQueryBuilder();
$qb->update($this->tableName)
->set('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
->set('user_id', $qb->func()->substring('user_id', $qb->createNamedParameter(2, IQueryBuilder::PARAM_INT)))
->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));

$qb->executeStatement();
}
}
38 changes: 36 additions & 2 deletions apps/user_status/lib/Service/StatusService.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IConfig;
use OCP\IUser;
use OCP\UserStatus\IUserStatus;

/**
Expand Down Expand Up @@ -460,7 +461,7 @@ public function backupCurrentStatus(string $userId): bool {
return true;
}

public function revertUserStatus(string $userId, ?string $messageId, string $status): void {
public function revertUserStatus(string $userId, string $messageId, string $status): void {
try {
/** @var UserStatus $userStatus */
$backupUserStatus = $this->mapper->findByUserId($userId, true);
Expand All @@ -469,7 +470,7 @@ public function revertUserStatus(string $userId, ?string $messageId, string $sta
return;
}

$deleted = $this->mapper->deleteCurrentStatusToRestoreBackup($userId, $messageId ?? '', $status);
$deleted = $this->mapper->deleteCurrentStatusToRestoreBackup($userId, $messageId, $status);
if (!$deleted) {
// Another status is set automatically or no status, do nothing
return;
Expand All @@ -480,4 +481,37 @@ public function revertUserStatus(string $userId, ?string $messageId, string $sta
$backupUserStatus->setUserId(substr($backupUserStatus->getUserId(), 1));
$this->mapper->update($backupUserStatus);
}

public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void {
// Get all user statuses and the backups
$findById = $userIds;
foreach ($userIds as $userId) {
$findById[] = '_' . $userId;
}
$userStatuses = $this->mapper->findByUserIds($findById);

$backups = $restoreIds = $statuesToDelete = [];
foreach ($userStatuses as $userStatus) {
if (!$userStatus->getIsBackup()
&& $userStatus->getMessageId() === $messageId
&& $userStatus->getStatus() === $status) {
$statuesToDelete[$userStatus->getUserId()] = $userStatus->getId();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo deleting statues 🗽

} else if ($userStatus->getIsBackup()) {
$backups[$userStatus->getUserId()] = $userStatus->getId();
}
}

// For users with both (normal and backup) delete the status when matching
foreach ($statuesToDelete as $userId => $statusId) {
$backupUserId = '_' . $userId;
if (isset($backups[$backupUserId])) {
$restoreIds[] = $backups[$backupUserId];
}
}

$this->mapper->deleteByIds(array_values($statuesToDelete));

// For users that matched restore the previous status
$this->mapper->restoreBackupStatuses($restoreIds);
}
}
52 changes: 52 additions & 0 deletions apps/user_status/tests/Unit/Db/UserStatusMapperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,56 @@ private function insertSampleStatuses(): void {
$this->mapper->insert($userStatus2);
$this->mapper->insert($userStatus3);
}

public function testRestoreBackupStatuses(): void {
$userStatus1 = new UserStatus();
$userStatus1->setUserId('_user1');
$userStatus1->setStatus('online');
$userStatus1->setStatusTimestamp(5000);
$userStatus1->setIsUserDefined(true);
$userStatus1->setIsBackup(true);
$userStatus1->setCustomIcon('🚀');
$userStatus1->setCustomMessage('Releasing');
$userStatus1->setClearAt(50000);
$userStatus1 = $this->mapper->insert($userStatus1);

$userStatus2 = new UserStatus();
$userStatus2->setUserId('_user2');
$userStatus2->setStatus('away');
$userStatus2->setStatusTimestamp(5000);
$userStatus2->setIsUserDefined(true);
$userStatus2->setIsBackup(true);
$userStatus2->setCustomIcon('💩');
$userStatus2->setCustomMessage('Do not disturb');
$userStatus2->setClearAt(50000);
$userStatus2 = $this->mapper->insert($userStatus2);

$userStatus3 = new UserStatus();
$userStatus3->setUserId('_user3');
$userStatus3->setStatus('away');
$userStatus3->setStatusTimestamp(5000);
$userStatus3->setIsUserDefined(true);
$userStatus3->setIsBackup(true);
$userStatus3->setCustomIcon('🏝️');
$userStatus3->setCustomMessage('Vacationing');
$userStatus3->setClearAt(50000);
$this->mapper->insert($userStatus3);

$this->mapper->restoreBackupStatuses([$userStatus1->getId(), $userStatus2->getId()]);

$user1Status = $this->mapper->findByUserId('user1', false);
$this->assertEquals('user1', $user1Status->getUserId());
$this->assertEquals(false, $user1Status->getIsBackup());
$this->assertEquals('Releasing', $user1Status->getCustomMessage());

$user2Status = $this->mapper->findByUserId('user2', false);
$this->assertEquals('user2', $user2Status->getUserId());
$this->assertEquals(false, $user2Status->getIsBackup());
$this->assertEquals('Do not disturb', $user2Status->getCustomMessage());

$user3Status = $this->mapper->findByUserId('user3', true);
$this->assertEquals('_user3', $user3Status->getUserId());
$this->assertEquals(true, $user3Status->getIsBackup());
$this->assertEquals('Vacationing', $user3Status->getCustomMessage());
}
}
58 changes: 58 additions & 0 deletions apps/user_status/tests/Unit/Service/StatusServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,62 @@ public function testBackup() {

$this->service->backupCurrentStatus('john');
}

public function testRevertMultipleUserStatus(): void {
$john = new UserStatus();
$john->setId(1);
$john->setStatus(IUserStatus::AWAY);
$john->setStatusTimestamp(1337);
$john->setIsUserDefined(false);
$john->setMessageId('call');
$john->setUserId('john');
$john->setIsBackup(false);

$johnBackup = new UserStatus();
$johnBackup->setId(2);
$johnBackup->setStatus(IUserStatus::ONLINE);
$johnBackup->setStatusTimestamp(1337);
$johnBackup->setIsUserDefined(true);
$johnBackup->setMessageId('hello');
$johnBackup->setUserId('_john');
$johnBackup->setIsBackup(true);

$noBackup = new UserStatus();
$noBackup->setId(3);
$noBackup->setStatus(IUserStatus::AWAY);
$noBackup->setStatusTimestamp(1337);
$noBackup->setIsUserDefined(false);
$noBackup->setMessageId('call');
$noBackup->setUserId('nobackup');
$noBackup->setIsBackup(false);

$backupOnly = new UserStatus();
$backupOnly->setId(4);
$backupOnly->setStatus(IUserStatus::ONLINE);
$backupOnly->setStatusTimestamp(1337);
$backupOnly->setIsUserDefined(true);
$backupOnly->setMessageId('hello');
$backupOnly->setUserId('_backuponly');
$backupOnly->setIsBackup(true);

$this->mapper->expects($this->once())
->method('findByUserIds')
->with(['john', 'nobackup', 'backuponly', '_john', '_nobackup', '_backuponly'])
->willReturn([
$john,
$johnBackup,
$noBackup,
$backupOnly,
]);

$this->mapper->expects($this->once())
->method('deleteByIds')
->with([1, 3]);

$this->mapper->expects($this->once())
->method('restoreBackupStatuses')
->with([2]);

$this->service->revertMultipleUserStatus(['john', 'nobackup', 'backuponly'], 'call', IUserStatus::AWAY);
}
}
11 changes: 11 additions & 0 deletions lib/private/UserStatus/ISettableProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,15 @@ public function setUserStatus(string $userId, string $messageId, string $status,
* @param string $status The expected current status.
*/
public function revertUserStatus(string $userId, string $messageId, string $status): void;

/**
* Revert an automatically set user status. For example after leaving a call,
* change back to the previously set status. If the user has already updated
* their status, this method does nothing.
*
* @param string[] $userIds The users for which we want to update the status.
* @param string $messageId The expected current messageId.
* @param string $status The expected current status.
*/
public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void;
}
8 changes: 8 additions & 0 deletions lib/private/UserStatus/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,12 @@ public function revertUserStatus(string $userId, string $messageId, string $stat
}
$this->provider->revertUserStatus($userId, $messageId, $status);
}

public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void {
$this->setupProvider();
if (!$this->provider || !($this->provider instanceof ISettableProvider)) {
return;
}
$this->provider->revertMultipleUserStatus($userIds, $messageId, $status);
}
}
15 changes: 14 additions & 1 deletion lib/public/UserStatus/IManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ interface IManager {
* @return IUserStatus[]
* @since 20.0.0
*/
public function getUserStatuses(array $userIds):array;
public function getUserStatuses(array $userIds): array;


/**
* Set a new status for the selected user.
*
* @param string $userId The user for which we want to update the status.
* @param string $messageId The id of the predefined message.
* @param string $status The status to assign
* @param bool $createBackup If true, this will store the old status so that it is possible to revert it later (e.g. after a call).
* @since 23.0.0
*/
Expand All @@ -58,7 +59,19 @@ public function setUserStatus(string $userId, string $messageId, string $status,
*
* @param string $userId The user for which we want to update the status.
* @param string $messageId The expected current messageId. If the user has already updated their status, this method does nothing.
* @param string $status The expected current status. If the user has already updated their status, this method does nothing.
* @since 23.0.0
*/
public function revertUserStatus(string $userId, string $messageId, string $status): void;

/**
* Revert an automatically set user status. For example after leaving a call,
* change back to the previously set status.
*
* @param string[] $userIds The user for which we want to update the status.
* @param string $messageId The expected current messageId. If the user has already updated their status, this method does nothing.
* @param string $status The expected current status. If the user has already updated their status, this method does nothing.
* @since 23.0.0
*/
public function revertMultipleUserStatus(array $userIds, string $messageId, string $status): void;
}