UserStatusMapper.php 6.1 KB

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