Passed
Push — master ( 078203...c81798 )
by Joas
14:40 queued 14s
created
lib/private/Collaboration/Resources/Manager.php 2 patches
Indentation   +481 added lines, -481 removed lines patch added patch discarded remove patch
@@ -41,485 +41,485 @@
 block discarded – undo
41 41
 use Psr\Log\LoggerInterface;
42 42
 
43 43
 class Manager implements IManager {
44
-	public const TABLE_COLLECTIONS = 'collres_collections';
45
-	public const TABLE_RESOURCES = 'collres_resources';
46
-	public const TABLE_ACCESS_CACHE = 'collres_accesscache';
47
-
48
-	/** @var IDBConnection */
49
-	protected $connection;
50
-	/** @var IProviderManager */
51
-	protected $providerManager;
52
-	/** @var LoggerInterface */
53
-	protected $logger;
54
-
55
-	/** @var string[] */
56
-	protected $providers = [];
57
-
58
-
59
-	public function __construct(IDBConnection $connection, IProviderManager $providerManager, LoggerInterface $logger) {
60
-		$this->connection = $connection;
61
-		$this->providerManager = $providerManager;
62
-		$this->logger = $logger;
63
-	}
64
-
65
-	/**
66
-	 * @param int $id
67
-	 * @return ICollection
68
-	 * @throws CollectionException when the collection could not be found
69
-	 * @since 16.0.0
70
-	 */
71
-	public function getCollection(int $id): ICollection {
72
-		$query = $this->connection->getQueryBuilder();
73
-		$query->select('*')
74
-			->from(self::TABLE_COLLECTIONS)
75
-			->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
76
-		$result = $query->execute();
77
-		$row = $result->fetch();
78
-		$result->closeCursor();
79
-
80
-		if (!$row) {
81
-			throw new CollectionException('Collection not found');
82
-		}
83
-
84
-		return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name']);
85
-	}
86
-
87
-	/**
88
-	 * @param int $id
89
-	 * @param IUser|null $user
90
-	 * @return ICollection
91
-	 * @throws CollectionException when the collection could not be found
92
-	 * @since 16.0.0
93
-	 */
94
-	public function getCollectionForUser(int $id, ?IUser $user): ICollection {
95
-		$query = $this->connection->getQueryBuilder();
96
-		$userId = $user instanceof IUser ? $user->getUID() : '';
97
-
98
-		$query->select('*')
99
-			->from(self::TABLE_COLLECTIONS, 'c')
100
-			->leftJoin(
101
-				'c', self::TABLE_ACCESS_CACHE, 'a',
102
-				$query->expr()->andX(
103
-					$query->expr()->eq('c.id', 'a.collection_id'),
104
-					$query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
105
-				)
106
-			)
107
-			->where($query->expr()->eq('c.id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
108
-		$result = $query->execute();
109
-		$row = $result->fetch();
110
-		$result->closeCursor();
111
-
112
-		if (!$row) {
113
-			throw new CollectionException('Collection not found');
114
-		}
115
-
116
-		$access = $row['access'] === null ? null : (bool) $row['access'];
117
-		if ($user instanceof IUser) {
118
-			return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name'], $user, $access);
119
-		}
120
-
121
-		return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name'], $user, $access);
122
-	}
123
-
124
-	/**
125
-	 * @param IUser $user
126
-	 * @param string $filter
127
-	 * @param int $limit
128
-	 * @param int $start
129
-	 * @return ICollection[]
130
-	 * @since 16.0.0
131
-	 */
132
-	public function searchCollections(IUser $user, string $filter, int $limit = 50, int $start = 0): array {
133
-		$query = $this->connection->getQueryBuilder();
134
-		$userId = $user->getUID();
135
-
136
-		$query->select('c.*', 'a.access')
137
-			->from(self::TABLE_COLLECTIONS, 'c')
138
-			->leftJoin(
139
-				'c', self::TABLE_ACCESS_CACHE, 'a',
140
-				$query->expr()->andX(
141
-					$query->expr()->eq('c.id', 'a.collection_id'),
142
-					$query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
143
-				)
144
-			)
145
-			->where($query->expr()->eq('a.access', $query->createNamedParameter(1, IQueryBuilder::PARAM_INT)))
146
-			->orderBy('c.id')
147
-			->setMaxResults($limit)
148
-			->setFirstResult($start);
149
-
150
-		if ($filter !== '') {
151
-			$query->andWhere($query->expr()->iLike('c.name', $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($filter) . '%')));
152
-		}
153
-
154
-		$result = $query->execute();
155
-		$collections = [];
156
-
157
-		$foundResults = 0;
158
-		while ($row = $result->fetch()) {
159
-			$foundResults++;
160
-			$access = $row['access'] === null ? null : (bool) $row['access'];
161
-			$collection = new Collection($this, $this->connection, (int)$row['id'], (string)$row['name'], $user, $access);
162
-			if ($collection->canAccess($user)) {
163
-				$collections[] = $collection;
164
-			}
165
-		}
166
-		$result->closeCursor();
167
-
168
-		if (empty($collections) && $foundResults === $limit) {
169
-			return $this->searchCollections($user, $filter, $limit, $start + $limit);
170
-		}
171
-
172
-		return $collections;
173
-	}
174
-
175
-	/**
176
-	 * @param string $name
177
-	 * @return ICollection
178
-	 * @since 16.0.0
179
-	 */
180
-	public function newCollection(string $name): ICollection {
181
-		$query = $this->connection->getQueryBuilder();
182
-		$query->insert(self::TABLE_COLLECTIONS)
183
-			->values([
184
-				'name' => $query->createNamedParameter($name),
185
-			]);
186
-		$query->execute();
187
-
188
-		return new Collection($this, $this->connection, $query->getLastInsertId(), $name);
189
-	}
190
-
191
-	/**
192
-	 * @param string $type
193
-	 * @param string $id
194
-	 * @return IResource
195
-	 * @since 16.0.0
196
-	 */
197
-	public function createResource(string $type, string $id): IResource {
198
-		return new Resource($this, $this->connection, $type, $id);
199
-	}
200
-
201
-	/**
202
-	 * @param string $type
203
-	 * @param string $id
204
-	 * @param IUser|null $user
205
-	 * @return IResource
206
-	 * @throws ResourceException
207
-	 * @since 16.0.0
208
-	 */
209
-	public function getResourceForUser(string $type, string $id, ?IUser $user): IResource {
210
-		$query = $this->connection->getQueryBuilder();
211
-		$userId = $user instanceof IUser ? $user->getUID() : '';
212
-
213
-		$query->select('r.*', 'a.access')
214
-			->from(self::TABLE_RESOURCES, 'r')
215
-			->leftJoin(
216
-				'r', self::TABLE_ACCESS_CACHE, 'a',
217
-				$query->expr()->andX(
218
-					$query->expr()->eq('r.resource_id', 'a.resource_id'),
219
-					$query->expr()->eq('r.resource_type', 'a.resource_type'),
220
-					$query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
221
-				)
222
-			)
223
-			->where($query->expr()->eq('r.resource_type', $query->createNamedParameter($type, IQueryBuilder::PARAM_STR)))
224
-			->andWhere($query->expr()->eq('r.resource_id', $query->createNamedParameter($id, IQueryBuilder::PARAM_STR)));
225
-		$result = $query->execute();
226
-		$row = $result->fetch();
227
-		$result->closeCursor();
228
-
229
-		if (!$row) {
230
-			throw new ResourceException('Resource not found');
231
-		}
232
-
233
-		$access = $row['access'] === null ? null : (bool) $row['access'];
234
-		if ($user instanceof IUser) {
235
-			return new Resource($this, $this->connection, $type, $id, $user, $access);
236
-		}
237
-
238
-		return new Resource($this, $this->connection, $type, $id, null, $access);
239
-	}
240
-
241
-	/**
242
-	 * @param ICollection $collection
243
-	 * @param IUser|null $user
244
-	 * @return IResource[]
245
-	 * @since 16.0.0
246
-	 */
247
-	public function getResourcesByCollectionForUser(ICollection $collection, ?IUser $user): array {
248
-		$query = $this->connection->getQueryBuilder();
249
-		$userId = $user instanceof IUser ? $user->getUID() : '';
250
-
251
-		$query->select('r.*', 'a.access')
252
-			->from(self::TABLE_RESOURCES, 'r')
253
-			->leftJoin(
254
-				'r', self::TABLE_ACCESS_CACHE, 'a',
255
-				$query->expr()->andX(
256
-					$query->expr()->eq('r.resource_id', 'a.resource_id'),
257
-					$query->expr()->eq('r.resource_type', 'a.resource_type'),
258
-					$query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
259
-				)
260
-			)
261
-			->where($query->expr()->eq('r.collection_id', $query->createNamedParameter($collection->getId(), IQueryBuilder::PARAM_INT)));
262
-
263
-		$resources = [];
264
-		$result = $query->execute();
265
-		while ($row = $result->fetch()) {
266
-			$access = $row['access'] === null ? null : (bool) $row['access'];
267
-			$resources[] = new Resource($this, $this->connection, $row['resource_type'], $row['resource_id'], $user, $access);
268
-		}
269
-		$result->closeCursor();
270
-
271
-		return $resources;
272
-	}
273
-
274
-	/**
275
-	 * Get the rich object data of a resource
276
-	 *
277
-	 * @param IResource $resource
278
-	 * @return array
279
-	 * @since 16.0.0
280
-	 */
281
-	public function getResourceRichObject(IResource $resource): array {
282
-		foreach ($this->providerManager->getResourceProviders() as $provider) {
283
-			if ($provider->getType() === $resource->getType()) {
284
-				try {
285
-					return $provider->getResourceRichObject($resource);
286
-				} catch (ResourceException $e) {
287
-				}
288
-			}
289
-		}
290
-
291
-		return [];
292
-	}
293
-
294
-	/**
295
-	 * Can a user/guest access the collection
296
-	 *
297
-	 * @param IResource $resource
298
-	 * @param IUser|null $user
299
-	 * @return bool
300
-	 * @since 16.0.0
301
-	 */
302
-	public function canAccessResource(IResource $resource, ?IUser $user): bool {
303
-		$access = $this->checkAccessCacheForUserByResource($resource, $user);
304
-		if (\is_bool($access)) {
305
-			return $access;
306
-		}
307
-
308
-		$access = false;
309
-		foreach ($this->providerManager->getResourceProviders() as $provider) {
310
-			if ($provider->getType() === $resource->getType()) {
311
-				try {
312
-					if ($provider->canAccessResource($resource, $user)) {
313
-						$access = true;
314
-						break;
315
-					}
316
-				} catch (ResourceException $e) {
317
-				}
318
-			}
319
-		}
320
-
321
-		$this->cacheAccessForResource($resource, $user, $access);
322
-		return $access;
323
-	}
324
-
325
-	/**
326
-	 * Can a user/guest access the collection
327
-	 *
328
-	 * @param ICollection $collection
329
-	 * @param IUser|null $user
330
-	 * @return bool
331
-	 * @since 16.0.0
332
-	 */
333
-	public function canAccessCollection(ICollection $collection, ?IUser $user): bool {
334
-		$access = $this->checkAccessCacheForUserByCollection($collection, $user);
335
-		if (\is_bool($access)) {
336
-			return $access;
337
-		}
338
-
339
-		$access = null;
340
-		// Access is granted when a user can access all resources
341
-		foreach ($collection->getResources() as $resource) {
342
-			if (!$resource->canAccess($user)) {
343
-				$access = false;
344
-				break;
345
-			}
346
-
347
-			$access = true;
348
-		}
349
-
350
-		$this->cacheAccessForCollection($collection, $user, $access);
351
-		return $access;
352
-	}
353
-
354
-	protected function checkAccessCacheForUserByResource(IResource $resource, ?IUser $user): ?bool {
355
-		$query = $this->connection->getQueryBuilder();
356
-		$userId = $user instanceof IUser ? $user->getUID() : '';
357
-
358
-		$query->select('access')
359
-			->from(self::TABLE_ACCESS_CACHE)
360
-			->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId(), IQueryBuilder::PARAM_STR)))
361
-			->andWhere($query->expr()->eq('resource_type', $query->createNamedParameter($resource->getType(), IQueryBuilder::PARAM_STR)))
362
-			->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
363
-			->setMaxResults(1);
364
-
365
-		$hasAccess = null;
366
-		$result = $query->execute();
367
-		if ($row = $result->fetch()) {
368
-			$hasAccess = (bool) $row['access'];
369
-		}
370
-		$result->closeCursor();
371
-
372
-		return $hasAccess;
373
-	}
374
-
375
-	protected function checkAccessCacheForUserByCollection(ICollection $collection, ?IUser $user): ?bool {
376
-		$query = $this->connection->getQueryBuilder();
377
-		$userId = $user instanceof IUser ? $user->getUID() : '';
378
-
379
-		$query->select('access')
380
-			->from(self::TABLE_ACCESS_CACHE)
381
-			->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId(), IQueryBuilder::PARAM_INT)))
382
-			->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
383
-			->setMaxResults(1);
384
-
385
-		$hasAccess = null;
386
-		$result = $query->execute();
387
-		if ($row = $result->fetch()) {
388
-			$hasAccess = (bool) $row['access'];
389
-		}
390
-		$result->closeCursor();
391
-
392
-		return $hasAccess;
393
-	}
394
-
395
-	public function cacheAccessForResource(IResource $resource, ?IUser $user, bool $access): void {
396
-		$query = $this->connection->getQueryBuilder();
397
-		$userId = $user instanceof IUser ? $user->getUID() : '';
398
-
399
-		$query->insert(self::TABLE_ACCESS_CACHE)
400
-			->values([
401
-				'user_id' => $query->createNamedParameter($userId),
402
-				'resource_id' => $query->createNamedParameter($resource->getId()),
403
-				'resource_type' => $query->createNamedParameter($resource->getType()),
404
-				'access' => $query->createNamedParameter($access, IQueryBuilder::PARAM_BOOL),
405
-			]);
406
-		try {
407
-			$query->execute();
408
-		} catch (UniqueConstraintViolationException $e) {
409
-		}
410
-	}
411
-
412
-	public function cacheAccessForCollection(ICollection $collection, ?IUser $user, bool $access): void {
413
-		$query = $this->connection->getQueryBuilder();
414
-		$userId = $user instanceof IUser ? $user->getUID() : '';
415
-
416
-		$query->insert(self::TABLE_ACCESS_CACHE)
417
-			->values([
418
-				'user_id' => $query->createNamedParameter($userId),
419
-				'collection_id' => $query->createNamedParameter($collection->getId()),
420
-				'access' => $query->createNamedParameter($access, IQueryBuilder::PARAM_BOOL),
421
-			]);
422
-		try {
423
-			$query->execute();
424
-		} catch (UniqueConstraintViolationException $e) {
425
-		}
426
-	}
427
-
428
-	public function invalidateAccessCacheForUser(?IUser $user): void {
429
-		$query = $this->connection->getQueryBuilder();
430
-		$userId = $user instanceof IUser ? $user->getUID() : '';
431
-
432
-		$query->delete(self::TABLE_ACCESS_CACHE)
433
-			->where($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
434
-		$query->execute();
435
-	}
436
-
437
-	public function invalidateAccessCacheForResource(IResource $resource): void {
438
-		$query = $this->connection->getQueryBuilder();
439
-
440
-		$query->delete(self::TABLE_ACCESS_CACHE)
441
-			->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId())))
442
-			->andWhere($query->expr()->eq('resource_type', $query->createNamedParameter($resource->getType(), IQueryBuilder::PARAM_STR)));
443
-		$query->execute();
444
-
445
-		foreach ($resource->getCollections() as $collection) {
446
-			$this->invalidateAccessCacheForCollection($collection);
447
-		}
448
-	}
449
-
450
-	public function invalidateAccessCacheForAllCollections(): void {
451
-		$query = $this->connection->getQueryBuilder();
452
-
453
-		$query->delete(self::TABLE_ACCESS_CACHE)
454
-			->where($query->expr()->neq('collection_id', $query->createNamedParameter(0)));
455
-		$query->execute();
456
-	}
457
-
458
-	public function invalidateAccessCacheForCollection(ICollection $collection): void {
459
-		$query = $this->connection->getQueryBuilder();
460
-
461
-		$query->delete(self::TABLE_ACCESS_CACHE)
462
-			->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId())));
463
-		$query->execute();
464
-	}
465
-
466
-	public function invalidateAccessCacheForProvider(IProvider $provider): void {
467
-		$query = $this->connection->getQueryBuilder();
468
-
469
-		$query->delete(self::TABLE_ACCESS_CACHE)
470
-			->where($query->expr()->eq('resource_type', $query->createNamedParameter($provider->getType(), IQueryBuilder::PARAM_STR)));
471
-		$query->execute();
472
-	}
473
-
474
-	public function invalidateAccessCacheForResourceByUser(IResource $resource, ?IUser $user): void {
475
-		$query = $this->connection->getQueryBuilder();
476
-		$userId = $user instanceof IUser ? $user->getUID() : '';
477
-
478
-		$query->delete(self::TABLE_ACCESS_CACHE)
479
-			->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId())))
480
-			->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
481
-		$query->execute();
482
-
483
-		foreach ($resource->getCollections() as $collection) {
484
-			$this->invalidateAccessCacheForCollectionByUser($collection, $user);
485
-		}
486
-	}
487
-
488
-	protected function invalidateAccessCacheForCollectionByUser(ICollection $collection, ?IUser $user): void {
489
-		$query = $this->connection->getQueryBuilder();
490
-		$userId = $user instanceof IUser ? $user->getUID() : '';
491
-
492
-		$query->delete(self::TABLE_ACCESS_CACHE)
493
-			->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId())))
494
-			->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
495
-		$query->execute();
496
-	}
497
-
498
-	public function invalidateAccessCacheForProviderByUser(IProvider $provider, ?IUser $user): void {
499
-		$query = $this->connection->getQueryBuilder();
500
-		$userId = $user instanceof IUser ? $user->getUID() : '';
501
-
502
-		$query->delete(self::TABLE_ACCESS_CACHE)
503
-			->where($query->expr()->eq('resource_type', $query->createNamedParameter($provider->getType(), IQueryBuilder::PARAM_STR)))
504
-			->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
505
-		$query->execute();
506
-	}
507
-
508
-	/**
509
-	 * @param string $provider
510
-	 */
511
-	public function registerResourceProvider(string $provider): void {
512
-		$this->logger->debug('\OC\Collaboration\Resources\Manager::registerResourceProvider is deprecated', ['provider' => $provider]);
513
-		$this->providerManager->registerResourceProvider($provider);
514
-	}
515
-
516
-	/**
517
-	 * Get the resource type of the provider
518
-	 *
519
-	 * @return string
520
-	 * @since 16.0.0
521
-	 */
522
-	public function getType(): string {
523
-		return '';
524
-	}
44
+    public const TABLE_COLLECTIONS = 'collres_collections';
45
+    public const TABLE_RESOURCES = 'collres_resources';
46
+    public const TABLE_ACCESS_CACHE = 'collres_accesscache';
47
+
48
+    /** @var IDBConnection */
49
+    protected $connection;
50
+    /** @var IProviderManager */
51
+    protected $providerManager;
52
+    /** @var LoggerInterface */
53
+    protected $logger;
54
+
55
+    /** @var string[] */
56
+    protected $providers = [];
57
+
58
+
59
+    public function __construct(IDBConnection $connection, IProviderManager $providerManager, LoggerInterface $logger) {
60
+        $this->connection = $connection;
61
+        $this->providerManager = $providerManager;
62
+        $this->logger = $logger;
63
+    }
64
+
65
+    /**
66
+     * @param int $id
67
+     * @return ICollection
68
+     * @throws CollectionException when the collection could not be found
69
+     * @since 16.0.0
70
+     */
71
+    public function getCollection(int $id): ICollection {
72
+        $query = $this->connection->getQueryBuilder();
73
+        $query->select('*')
74
+            ->from(self::TABLE_COLLECTIONS)
75
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
76
+        $result = $query->execute();
77
+        $row = $result->fetch();
78
+        $result->closeCursor();
79
+
80
+        if (!$row) {
81
+            throw new CollectionException('Collection not found');
82
+        }
83
+
84
+        return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name']);
85
+    }
86
+
87
+    /**
88
+     * @param int $id
89
+     * @param IUser|null $user
90
+     * @return ICollection
91
+     * @throws CollectionException when the collection could not be found
92
+     * @since 16.0.0
93
+     */
94
+    public function getCollectionForUser(int $id, ?IUser $user): ICollection {
95
+        $query = $this->connection->getQueryBuilder();
96
+        $userId = $user instanceof IUser ? $user->getUID() : '';
97
+
98
+        $query->select('*')
99
+            ->from(self::TABLE_COLLECTIONS, 'c')
100
+            ->leftJoin(
101
+                'c', self::TABLE_ACCESS_CACHE, 'a',
102
+                $query->expr()->andX(
103
+                    $query->expr()->eq('c.id', 'a.collection_id'),
104
+                    $query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
105
+                )
106
+            )
107
+            ->where($query->expr()->eq('c.id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
108
+        $result = $query->execute();
109
+        $row = $result->fetch();
110
+        $result->closeCursor();
111
+
112
+        if (!$row) {
113
+            throw new CollectionException('Collection not found');
114
+        }
115
+
116
+        $access = $row['access'] === null ? null : (bool) $row['access'];
117
+        if ($user instanceof IUser) {
118
+            return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name'], $user, $access);
119
+        }
120
+
121
+        return new Collection($this, $this->connection, (int) $row['id'], (string) $row['name'], $user, $access);
122
+    }
123
+
124
+    /**
125
+     * @param IUser $user
126
+     * @param string $filter
127
+     * @param int $limit
128
+     * @param int $start
129
+     * @return ICollection[]
130
+     * @since 16.0.0
131
+     */
132
+    public function searchCollections(IUser $user, string $filter, int $limit = 50, int $start = 0): array {
133
+        $query = $this->connection->getQueryBuilder();
134
+        $userId = $user->getUID();
135
+
136
+        $query->select('c.*', 'a.access')
137
+            ->from(self::TABLE_COLLECTIONS, 'c')
138
+            ->leftJoin(
139
+                'c', self::TABLE_ACCESS_CACHE, 'a',
140
+                $query->expr()->andX(
141
+                    $query->expr()->eq('c.id', 'a.collection_id'),
142
+                    $query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
143
+                )
144
+            )
145
+            ->where($query->expr()->eq('a.access', $query->createNamedParameter(1, IQueryBuilder::PARAM_INT)))
146
+            ->orderBy('c.id')
147
+            ->setMaxResults($limit)
148
+            ->setFirstResult($start);
149
+
150
+        if ($filter !== '') {
151
+            $query->andWhere($query->expr()->iLike('c.name', $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($filter) . '%')));
152
+        }
153
+
154
+        $result = $query->execute();
155
+        $collections = [];
156
+
157
+        $foundResults = 0;
158
+        while ($row = $result->fetch()) {
159
+            $foundResults++;
160
+            $access = $row['access'] === null ? null : (bool) $row['access'];
161
+            $collection = new Collection($this, $this->connection, (int)$row['id'], (string)$row['name'], $user, $access);
162
+            if ($collection->canAccess($user)) {
163
+                $collections[] = $collection;
164
+            }
165
+        }
166
+        $result->closeCursor();
167
+
168
+        if (empty($collections) && $foundResults === $limit) {
169
+            return $this->searchCollections($user, $filter, $limit, $start + $limit);
170
+        }
171
+
172
+        return $collections;
173
+    }
174
+
175
+    /**
176
+     * @param string $name
177
+     * @return ICollection
178
+     * @since 16.0.0
179
+     */
180
+    public function newCollection(string $name): ICollection {
181
+        $query = $this->connection->getQueryBuilder();
182
+        $query->insert(self::TABLE_COLLECTIONS)
183
+            ->values([
184
+                'name' => $query->createNamedParameter($name),
185
+            ]);
186
+        $query->execute();
187
+
188
+        return new Collection($this, $this->connection, $query->getLastInsertId(), $name);
189
+    }
190
+
191
+    /**
192
+     * @param string $type
193
+     * @param string $id
194
+     * @return IResource
195
+     * @since 16.0.0
196
+     */
197
+    public function createResource(string $type, string $id): IResource {
198
+        return new Resource($this, $this->connection, $type, $id);
199
+    }
200
+
201
+    /**
202
+     * @param string $type
203
+     * @param string $id
204
+     * @param IUser|null $user
205
+     * @return IResource
206
+     * @throws ResourceException
207
+     * @since 16.0.0
208
+     */
209
+    public function getResourceForUser(string $type, string $id, ?IUser $user): IResource {
210
+        $query = $this->connection->getQueryBuilder();
211
+        $userId = $user instanceof IUser ? $user->getUID() : '';
212
+
213
+        $query->select('r.*', 'a.access')
214
+            ->from(self::TABLE_RESOURCES, 'r')
215
+            ->leftJoin(
216
+                'r', self::TABLE_ACCESS_CACHE, 'a',
217
+                $query->expr()->andX(
218
+                    $query->expr()->eq('r.resource_id', 'a.resource_id'),
219
+                    $query->expr()->eq('r.resource_type', 'a.resource_type'),
220
+                    $query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
221
+                )
222
+            )
223
+            ->where($query->expr()->eq('r.resource_type', $query->createNamedParameter($type, IQueryBuilder::PARAM_STR)))
224
+            ->andWhere($query->expr()->eq('r.resource_id', $query->createNamedParameter($id, IQueryBuilder::PARAM_STR)));
225
+        $result = $query->execute();
226
+        $row = $result->fetch();
227
+        $result->closeCursor();
228
+
229
+        if (!$row) {
230
+            throw new ResourceException('Resource not found');
231
+        }
232
+
233
+        $access = $row['access'] === null ? null : (bool) $row['access'];
234
+        if ($user instanceof IUser) {
235
+            return new Resource($this, $this->connection, $type, $id, $user, $access);
236
+        }
237
+
238
+        return new Resource($this, $this->connection, $type, $id, null, $access);
239
+    }
240
+
241
+    /**
242
+     * @param ICollection $collection
243
+     * @param IUser|null $user
244
+     * @return IResource[]
245
+     * @since 16.0.0
246
+     */
247
+    public function getResourcesByCollectionForUser(ICollection $collection, ?IUser $user): array {
248
+        $query = $this->connection->getQueryBuilder();
249
+        $userId = $user instanceof IUser ? $user->getUID() : '';
250
+
251
+        $query->select('r.*', 'a.access')
252
+            ->from(self::TABLE_RESOURCES, 'r')
253
+            ->leftJoin(
254
+                'r', self::TABLE_ACCESS_CACHE, 'a',
255
+                $query->expr()->andX(
256
+                    $query->expr()->eq('r.resource_id', 'a.resource_id'),
257
+                    $query->expr()->eq('r.resource_type', 'a.resource_type'),
258
+                    $query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
259
+                )
260
+            )
261
+            ->where($query->expr()->eq('r.collection_id', $query->createNamedParameter($collection->getId(), IQueryBuilder::PARAM_INT)));
262
+
263
+        $resources = [];
264
+        $result = $query->execute();
265
+        while ($row = $result->fetch()) {
266
+            $access = $row['access'] === null ? null : (bool) $row['access'];
267
+            $resources[] = new Resource($this, $this->connection, $row['resource_type'], $row['resource_id'], $user, $access);
268
+        }
269
+        $result->closeCursor();
270
+
271
+        return $resources;
272
+    }
273
+
274
+    /**
275
+     * Get the rich object data of a resource
276
+     *
277
+     * @param IResource $resource
278
+     * @return array
279
+     * @since 16.0.0
280
+     */
281
+    public function getResourceRichObject(IResource $resource): array {
282
+        foreach ($this->providerManager->getResourceProviders() as $provider) {
283
+            if ($provider->getType() === $resource->getType()) {
284
+                try {
285
+                    return $provider->getResourceRichObject($resource);
286
+                } catch (ResourceException $e) {
287
+                }
288
+            }
289
+        }
290
+
291
+        return [];
292
+    }
293
+
294
+    /**
295
+     * Can a user/guest access the collection
296
+     *
297
+     * @param IResource $resource
298
+     * @param IUser|null $user
299
+     * @return bool
300
+     * @since 16.0.0
301
+     */
302
+    public function canAccessResource(IResource $resource, ?IUser $user): bool {
303
+        $access = $this->checkAccessCacheForUserByResource($resource, $user);
304
+        if (\is_bool($access)) {
305
+            return $access;
306
+        }
307
+
308
+        $access = false;
309
+        foreach ($this->providerManager->getResourceProviders() as $provider) {
310
+            if ($provider->getType() === $resource->getType()) {
311
+                try {
312
+                    if ($provider->canAccessResource($resource, $user)) {
313
+                        $access = true;
314
+                        break;
315
+                    }
316
+                } catch (ResourceException $e) {
317
+                }
318
+            }
319
+        }
320
+
321
+        $this->cacheAccessForResource($resource, $user, $access);
322
+        return $access;
323
+    }
324
+
325
+    /**
326
+     * Can a user/guest access the collection
327
+     *
328
+     * @param ICollection $collection
329
+     * @param IUser|null $user
330
+     * @return bool
331
+     * @since 16.0.0
332
+     */
333
+    public function canAccessCollection(ICollection $collection, ?IUser $user): bool {
334
+        $access = $this->checkAccessCacheForUserByCollection($collection, $user);
335
+        if (\is_bool($access)) {
336
+            return $access;
337
+        }
338
+
339
+        $access = null;
340
+        // Access is granted when a user can access all resources
341
+        foreach ($collection->getResources() as $resource) {
342
+            if (!$resource->canAccess($user)) {
343
+                $access = false;
344
+                break;
345
+            }
346
+
347
+            $access = true;
348
+        }
349
+
350
+        $this->cacheAccessForCollection($collection, $user, $access);
351
+        return $access;
352
+    }
353
+
354
+    protected function checkAccessCacheForUserByResource(IResource $resource, ?IUser $user): ?bool {
355
+        $query = $this->connection->getQueryBuilder();
356
+        $userId = $user instanceof IUser ? $user->getUID() : '';
357
+
358
+        $query->select('access')
359
+            ->from(self::TABLE_ACCESS_CACHE)
360
+            ->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId(), IQueryBuilder::PARAM_STR)))
361
+            ->andWhere($query->expr()->eq('resource_type', $query->createNamedParameter($resource->getType(), IQueryBuilder::PARAM_STR)))
362
+            ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
363
+            ->setMaxResults(1);
364
+
365
+        $hasAccess = null;
366
+        $result = $query->execute();
367
+        if ($row = $result->fetch()) {
368
+            $hasAccess = (bool) $row['access'];
369
+        }
370
+        $result->closeCursor();
371
+
372
+        return $hasAccess;
373
+    }
374
+
375
+    protected function checkAccessCacheForUserByCollection(ICollection $collection, ?IUser $user): ?bool {
376
+        $query = $this->connection->getQueryBuilder();
377
+        $userId = $user instanceof IUser ? $user->getUID() : '';
378
+
379
+        $query->select('access')
380
+            ->from(self::TABLE_ACCESS_CACHE)
381
+            ->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId(), IQueryBuilder::PARAM_INT)))
382
+            ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR)))
383
+            ->setMaxResults(1);
384
+
385
+        $hasAccess = null;
386
+        $result = $query->execute();
387
+        if ($row = $result->fetch()) {
388
+            $hasAccess = (bool) $row['access'];
389
+        }
390
+        $result->closeCursor();
391
+
392
+        return $hasAccess;
393
+    }
394
+
395
+    public function cacheAccessForResource(IResource $resource, ?IUser $user, bool $access): void {
396
+        $query = $this->connection->getQueryBuilder();
397
+        $userId = $user instanceof IUser ? $user->getUID() : '';
398
+
399
+        $query->insert(self::TABLE_ACCESS_CACHE)
400
+            ->values([
401
+                'user_id' => $query->createNamedParameter($userId),
402
+                'resource_id' => $query->createNamedParameter($resource->getId()),
403
+                'resource_type' => $query->createNamedParameter($resource->getType()),
404
+                'access' => $query->createNamedParameter($access, IQueryBuilder::PARAM_BOOL),
405
+            ]);
406
+        try {
407
+            $query->execute();
408
+        } catch (UniqueConstraintViolationException $e) {
409
+        }
410
+    }
411
+
412
+    public function cacheAccessForCollection(ICollection $collection, ?IUser $user, bool $access): void {
413
+        $query = $this->connection->getQueryBuilder();
414
+        $userId = $user instanceof IUser ? $user->getUID() : '';
415
+
416
+        $query->insert(self::TABLE_ACCESS_CACHE)
417
+            ->values([
418
+                'user_id' => $query->createNamedParameter($userId),
419
+                'collection_id' => $query->createNamedParameter($collection->getId()),
420
+                'access' => $query->createNamedParameter($access, IQueryBuilder::PARAM_BOOL),
421
+            ]);
422
+        try {
423
+            $query->execute();
424
+        } catch (UniqueConstraintViolationException $e) {
425
+        }
426
+    }
427
+
428
+    public function invalidateAccessCacheForUser(?IUser $user): void {
429
+        $query = $this->connection->getQueryBuilder();
430
+        $userId = $user instanceof IUser ? $user->getUID() : '';
431
+
432
+        $query->delete(self::TABLE_ACCESS_CACHE)
433
+            ->where($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
434
+        $query->execute();
435
+    }
436
+
437
+    public function invalidateAccessCacheForResource(IResource $resource): void {
438
+        $query = $this->connection->getQueryBuilder();
439
+
440
+        $query->delete(self::TABLE_ACCESS_CACHE)
441
+            ->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId())))
442
+            ->andWhere($query->expr()->eq('resource_type', $query->createNamedParameter($resource->getType(), IQueryBuilder::PARAM_STR)));
443
+        $query->execute();
444
+
445
+        foreach ($resource->getCollections() as $collection) {
446
+            $this->invalidateAccessCacheForCollection($collection);
447
+        }
448
+    }
449
+
450
+    public function invalidateAccessCacheForAllCollections(): void {
451
+        $query = $this->connection->getQueryBuilder();
452
+
453
+        $query->delete(self::TABLE_ACCESS_CACHE)
454
+            ->where($query->expr()->neq('collection_id', $query->createNamedParameter(0)));
455
+        $query->execute();
456
+    }
457
+
458
+    public function invalidateAccessCacheForCollection(ICollection $collection): void {
459
+        $query = $this->connection->getQueryBuilder();
460
+
461
+        $query->delete(self::TABLE_ACCESS_CACHE)
462
+            ->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId())));
463
+        $query->execute();
464
+    }
465
+
466
+    public function invalidateAccessCacheForProvider(IProvider $provider): void {
467
+        $query = $this->connection->getQueryBuilder();
468
+
469
+        $query->delete(self::TABLE_ACCESS_CACHE)
470
+            ->where($query->expr()->eq('resource_type', $query->createNamedParameter($provider->getType(), IQueryBuilder::PARAM_STR)));
471
+        $query->execute();
472
+    }
473
+
474
+    public function invalidateAccessCacheForResourceByUser(IResource $resource, ?IUser $user): void {
475
+        $query = $this->connection->getQueryBuilder();
476
+        $userId = $user instanceof IUser ? $user->getUID() : '';
477
+
478
+        $query->delete(self::TABLE_ACCESS_CACHE)
479
+            ->where($query->expr()->eq('resource_id', $query->createNamedParameter($resource->getId())))
480
+            ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
481
+        $query->execute();
482
+
483
+        foreach ($resource->getCollections() as $collection) {
484
+            $this->invalidateAccessCacheForCollectionByUser($collection, $user);
485
+        }
486
+    }
487
+
488
+    protected function invalidateAccessCacheForCollectionByUser(ICollection $collection, ?IUser $user): void {
489
+        $query = $this->connection->getQueryBuilder();
490
+        $userId = $user instanceof IUser ? $user->getUID() : '';
491
+
492
+        $query->delete(self::TABLE_ACCESS_CACHE)
493
+            ->where($query->expr()->eq('collection_id', $query->createNamedParameter($collection->getId())))
494
+            ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
495
+        $query->execute();
496
+    }
497
+
498
+    public function invalidateAccessCacheForProviderByUser(IProvider $provider, ?IUser $user): void {
499
+        $query = $this->connection->getQueryBuilder();
500
+        $userId = $user instanceof IUser ? $user->getUID() : '';
501
+
502
+        $query->delete(self::TABLE_ACCESS_CACHE)
503
+            ->where($query->expr()->eq('resource_type', $query->createNamedParameter($provider->getType(), IQueryBuilder::PARAM_STR)))
504
+            ->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
505
+        $query->execute();
506
+    }
507
+
508
+    /**
509
+     * @param string $provider
510
+     */
511
+    public function registerResourceProvider(string $provider): void {
512
+        $this->logger->debug('\OC\Collaboration\Resources\Manager::registerResourceProvider is deprecated', ['provider' => $provider]);
513
+        $this->providerManager->registerResourceProvider($provider);
514
+    }
515
+
516
+    /**
517
+     * Get the resource type of the provider
518
+     *
519
+     * @return string
520
+     * @since 16.0.0
521
+     */
522
+    public function getType(): string {
523
+        return '';
524
+    }
525 525
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
 			->setFirstResult($start);
149 149
 
150 150
 		if ($filter !== '') {
151
-			$query->andWhere($query->expr()->iLike('c.name', $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($filter) . '%')));
151
+			$query->andWhere($query->expr()->iLike('c.name', $query->createNamedParameter('%'.$this->connection->escapeLikeParameter($filter).'%')));
152 152
 		}
153 153
 
154 154
 		$result = $query->execute();
@@ -158,7 +158,7 @@  discard block
 block discarded – undo
158 158
 		while ($row = $result->fetch()) {
159 159
 			$foundResults++;
160 160
 			$access = $row['access'] === null ? null : (bool) $row['access'];
161
-			$collection = new Collection($this, $this->connection, (int)$row['id'], (string)$row['name'], $user, $access);
161
+			$collection = new Collection($this, $this->connection, (int) $row['id'], (string) $row['name'], $user, $access);
162 162
 			if ($collection->canAccess($user)) {
163 163
 				$collections[] = $collection;
164 164
 			}
Please login to merge, or discard this patch.