UserStatusMapper.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\UserStatus\Db;
  8. use OCP\AppFramework\Db\QBMapper;
  9. use OCP\DB\QueryBuilder\IQueryBuilder;
  10. use OCP\IDBConnection;
  11. use OCP\UserStatus\IUserStatus;
  12. /**
  13. * @template-extends QBMapper<UserStatus>
  14. */
  15. class UserStatusMapper extends QBMapper {
  16. /**
  17. * @param IDBConnection $db
  18. */
  19. public function __construct(IDBConnection $db) {
  20. parent::__construct($db, 'user_status');
  21. }
  22. /**
  23. * @param int|null $limit
  24. * @param int|null $offset
  25. * @return UserStatus[]
  26. */
  27. public function findAll(?int $limit = null, ?int $offset = null):array {
  28. $qb = $this->db->getQueryBuilder();
  29. $qb
  30. ->select('*')
  31. ->from($this->tableName);
  32. if ($limit !== null) {
  33. $qb->setMaxResults($limit);
  34. }
  35. if ($offset !== null) {
  36. $qb->setFirstResult($offset);
  37. }
  38. return $this->findEntities($qb);
  39. }
  40. /**
  41. * @param int|null $limit
  42. * @param int|null $offset
  43. * @return array
  44. */
  45. public function findAllRecent(?int $limit = null, ?int $offset = null): array {
  46. $qb = $this->db->getQueryBuilder();
  47. $qb
  48. ->select('*')
  49. ->from($this->tableName)
  50. ->orderBy('status_message_timestamp', 'DESC')
  51. ->where($qb->expr()->andX(
  52. $qb->expr()->neq('status_message_timestamp', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
  53. $qb->expr()->orX(
  54. $qb->expr()->notIn('status', $qb->createNamedParameter([IUserStatus::ONLINE, IUserStatus::AWAY, IUserStatus::OFFLINE], IQueryBuilder::PARAM_STR_ARRAY)),
  55. $qb->expr()->isNotNull('message_id'),
  56. $qb->expr()->isNotNull('custom_icon'),
  57. $qb->expr()->isNotNull('custom_message'),
  58. ),
  59. $qb->expr()->notLike('user_id', $qb->createNamedParameter($this->db->escapeLikeParameter('_') . '%'))
  60. ));
  61. if ($limit !== null) {
  62. $qb->setMaxResults($limit);
  63. }
  64. if ($offset !== null) {
  65. $qb->setFirstResult($offset);
  66. }
  67. return $this->findEntities($qb);
  68. }
  69. /**
  70. * @param string $userId
  71. * @return UserStatus
  72. * @throws \OCP\AppFramework\Db\DoesNotExistException
  73. */
  74. public function findByUserId(string $userId, bool $isBackup = false): UserStatus {
  75. $qb = $this->db->getQueryBuilder();
  76. $qb
  77. ->select('*')
  78. ->from($this->tableName)
  79. ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($isBackup ? '_' . $userId : $userId, IQueryBuilder::PARAM_STR)));
  80. return $this->findEntity($qb);
  81. }
  82. /**
  83. * @param array $userIds
  84. * @return array
  85. */
  86. public function findByUserIds(array $userIds): array {
  87. $qb = $this->db->getQueryBuilder();
  88. $qb
  89. ->select('*')
  90. ->from($this->tableName)
  91. ->where($qb->expr()->in('user_id', $qb->createNamedParameter($userIds, IQueryBuilder::PARAM_STR_ARRAY)));
  92. return $this->findEntities($qb);
  93. }
  94. /**
  95. * @param int $olderThan
  96. * @param int $now
  97. */
  98. public function clearStatusesOlderThan(int $olderThan, int $now): void {
  99. $qb = $this->db->getQueryBuilder();
  100. $qb->update($this->tableName)
  101. ->set('status', $qb->createNamedParameter(IUserStatus::OFFLINE))
  102. ->set('is_user_defined', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
  103. ->set('status_timestamp', $qb->createNamedParameter($now, IQueryBuilder::PARAM_INT))
  104. ->where($qb->expr()->lte('status_timestamp', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT)))
  105. ->andWhere($qb->expr()->neq('status', $qb->createNamedParameter(IUserStatus::OFFLINE)))
  106. ->andWhere($qb->expr()->orX(
  107. $qb->expr()->eq('is_user_defined', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL),
  108. $qb->expr()->eq('status', $qb->createNamedParameter(IUserStatus::ONLINE))
  109. ));
  110. $qb->execute();
  111. }
  112. /**
  113. * Clear all statuses older than a given timestamp
  114. *
  115. * @param int $timestamp
  116. */
  117. public function clearOlderThanClearAt(int $timestamp): void {
  118. $qb = $this->db->getQueryBuilder();
  119. $qb->delete($this->tableName)
  120. ->where($qb->expr()->isNotNull('clear_at'))
  121. ->andWhere($qb->expr()->lte('clear_at', $qb->createNamedParameter($timestamp, IQueryBuilder::PARAM_INT)));
  122. $qb->execute();
  123. }
  124. /**
  125. * Deletes a user status so we can restore the backup
  126. *
  127. * @param string $userId
  128. * @param string $messageId
  129. * @return bool True if an entry was deleted
  130. */
  131. public function deleteCurrentStatusToRestoreBackup(string $userId, string $messageId): bool {
  132. $qb = $this->db->getQueryBuilder();
  133. $qb->delete($this->tableName)
  134. ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)))
  135. ->andWhere($qb->expr()->eq('message_id', $qb->createNamedParameter($messageId)))
  136. ->andWhere($qb->expr()->eq('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)));
  137. return $qb->executeStatement() > 0;
  138. }
  139. public function deleteByIds(array $ids): void {
  140. $qb = $this->db->getQueryBuilder();
  141. $qb->delete($this->tableName)
  142. ->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
  143. $qb->executeStatement();
  144. }
  145. /**
  146. * @param string $userId
  147. * @return bool
  148. * @throws \OCP\DB\Exception
  149. */
  150. public function createBackupStatus(string $userId): bool {
  151. // Prefix user account with an underscore because user_id is marked as unique
  152. // in the table. Starting a username with an underscore is not allowed so this
  153. // shouldn't create any trouble.
  154. $qb = $this->db->getQueryBuilder();
  155. $qb->update($this->tableName)
  156. ->set('is_backup', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
  157. ->set('user_id', $qb->createNamedParameter('_' . $userId))
  158. ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($userId)));
  159. return $qb->executeStatement() > 0;
  160. }
  161. public function restoreBackupStatuses(array $ids): void {
  162. $qb = $this->db->getQueryBuilder();
  163. $qb->update($this->tableName)
  164. ->set('is_backup', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
  165. ->set('user_id', $qb->func()->substring('user_id', $qb->createNamedParameter(2, IQueryBuilder::PARAM_INT)))
  166. ->where($qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)));
  167. $qb->executeStatement();
  168. }
  169. }