Collection.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Collaboration\Resources;
  8. use Doctrine\DBAL\Exception\ConstraintViolationException;
  9. use OCP\Collaboration\Resources\ICollection;
  10. use OCP\Collaboration\Resources\IManager;
  11. use OCP\Collaboration\Resources\IResource;
  12. use OCP\Collaboration\Resources\ResourceException;
  13. use OCP\DB\QueryBuilder\IQueryBuilder;
  14. use OCP\IDBConnection;
  15. use OCP\IUser;
  16. class Collection implements ICollection {
  17. /** @var IResource[] */
  18. protected array $resources = [];
  19. public function __construct(
  20. /** @var Manager $manager */
  21. protected IManager $manager,
  22. protected IDBConnection $connection,
  23. protected int $id,
  24. protected string $name,
  25. protected ?IUser $userForAccess = null,
  26. protected ?bool $access = null,
  27. ) {
  28. }
  29. /**
  30. * @since 16.0.0
  31. */
  32. public function getId(): int {
  33. return $this->id;
  34. }
  35. /**
  36. * @since 16.0.0
  37. */
  38. public function getName(): string {
  39. return $this->name;
  40. }
  41. /**
  42. * @since 16.0.0
  43. */
  44. public function setName(string $name): void {
  45. $query = $this->connection->getQueryBuilder();
  46. $query->update(Manager::TABLE_COLLECTIONS)
  47. ->set('name', $query->createNamedParameter($name))
  48. ->where($query->expr()->eq('id', $query->createNamedParameter($this->getId(), IQueryBuilder::PARAM_INT)));
  49. $query->executeStatement();
  50. $this->name = $name;
  51. }
  52. /**
  53. * @return IResource[]
  54. * @since 16.0.0
  55. */
  56. public function getResources(): array {
  57. if (empty($this->resources)) {
  58. $this->resources = $this->manager->getResourcesByCollectionForUser($this, $this->userForAccess);
  59. }
  60. return $this->resources;
  61. }
  62. /**
  63. * Adds a resource to a collection
  64. *
  65. * @throws ResourceException when the resource is already part of the collection
  66. * @since 16.0.0
  67. */
  68. public function addResource(IResource $resource): void {
  69. array_map(function (IResource $r) use ($resource) {
  70. if ($this->isSameResource($r, $resource)) {
  71. throw new ResourceException('Already part of the collection');
  72. }
  73. }, $this->getResources());
  74. $this->resources[] = $resource;
  75. $query = $this->connection->getQueryBuilder();
  76. $query->insert(Manager::TABLE_RESOURCES)
  77. ->values([
  78. 'collection_id' => $query->createNamedParameter($this->id, IQueryBuilder::PARAM_INT),
  79. 'resource_type' => $query->createNamedParameter($resource->getType()),
  80. 'resource_id' => $query->createNamedParameter($resource->getId()),
  81. ]);
  82. try {
  83. $query->execute();
  84. } catch (ConstraintViolationException $e) {
  85. throw new ResourceException('Already part of the collection');
  86. }
  87. $this->manager->invalidateAccessCacheForCollection($this);
  88. }
  89. /**
  90. * Removes a resource from a collection
  91. *
  92. * @since 16.0.0
  93. */
  94. public function removeResource(IResource $resource): void {
  95. $this->resources = array_filter($this->getResources(), function (IResource $r) use ($resource) {
  96. return !$this->isSameResource($r, $resource);
  97. });
  98. $query = $this->connection->getQueryBuilder();
  99. $query->delete(Manager::TABLE_RESOURCES)
  100. ->where($query->expr()->eq('collection_id', $query->createNamedParameter($this->id, IQueryBuilder::PARAM_INT)))
  101. ->andWhere($query->expr()->eq('resource_type', $query->createNamedParameter($resource->getType())))
  102. ->andWhere($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId())));
  103. $query->executeStatement();
  104. if (empty($this->resources)) {
  105. $this->removeCollection();
  106. } else {
  107. $this->manager->invalidateAccessCacheForCollection($this);
  108. }
  109. }
  110. /**
  111. * Can a user/guest access the collection
  112. *
  113. * @since 16.0.0
  114. */
  115. public function canAccess(?IUser $user): bool {
  116. if ($user instanceof IUser) {
  117. return $this->canUserAccess($user);
  118. }
  119. return $this->canGuestAccess();
  120. }
  121. protected function canUserAccess(IUser $user): bool {
  122. if (\is_bool($this->access) && $this->userForAccess instanceof IUser && $user->getUID() === $this->userForAccess->getUID()) {
  123. return $this->access;
  124. }
  125. $access = $this->manager->canAccessCollection($this, $user);
  126. if ($this->userForAccess instanceof IUser && $user->getUID() === $this->userForAccess->getUID()) {
  127. $this->access = $access;
  128. }
  129. return $access;
  130. }
  131. protected function canGuestAccess(): bool {
  132. if (\is_bool($this->access) && !$this->userForAccess instanceof IUser) {
  133. return $this->access;
  134. }
  135. $access = $this->manager->canAccessCollection($this, null);
  136. if (!$this->userForAccess instanceof IUser) {
  137. $this->access = $access;
  138. }
  139. return $access;
  140. }
  141. protected function isSameResource(IResource $resource1, IResource $resource2): bool {
  142. return $resource1->getType() === $resource2->getType() &&
  143. $resource1->getId() === $resource2->getId();
  144. }
  145. protected function removeCollection(): void {
  146. $query = $this->connection->getQueryBuilder();
  147. $query->delete(Manager::TABLE_COLLECTIONS)
  148. ->where($query->expr()->eq('id', $query->createNamedParameter($this->id, IQueryBuilder::PARAM_INT)));
  149. $query->executeStatement();
  150. $this->manager->invalidateAccessCacheForCollection($this);
  151. $this->id = 0;
  152. }
  153. }