Completed
Pull Request — master (#330)
by Maxence
01:30
created

ShareByCircleProvider::move()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 11
loc 11
rs 9.9
cc 1
nc 1
nop 2
1
<?php
2
/**
3
 * Circles - Bring cloud-users closer together.
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Maxence Lange <[email protected]>
9
 * @author Vinicius Cubas Brand <[email protected]>
10
 * @author Daniel Tygel <[email protected]>
11
 *
12
 * @copyright 2017
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
30
31
namespace OCA\Circles;
32
33
34
use OC;
35
use OC\Files\Cache\Cache;
36
use OC\Share20\Exception\InvalidShare;
37
use OC\Share20\Share;
38
use OC\User\NoUserException;
39
use OCA\Circles\Api\v1\Circles;
40
use OCA\Circles\AppInfo\Application;
41
use OCA\Circles\Db\CircleProviderRequest;
42
use OCA\Circles\Db\CirclesRequest;
43
use OCA\Circles\Db\MembersRequest;
44
use OCA\Circles\Db\TokensRequest;
45
use OCA\Circles\Model\Circle;
46
use OCA\Circles\Service\CirclesService;
47
use OCA\Circles\Service\ConfigService;
48
use OCA\Circles\Service\MiscService;
49
use OCA\Circles\Service\TimezoneService;
50
use OCP\AppFramework\QueryException;
51
use OCP\DB\QueryBuilder\IQueryBuilder;
52
use OCP\Files\Folder;
53
use OCP\Files\IRootFolder;
54
use OCP\Files\Node;
55
use OCP\Files\NotFoundException;
56
use OCP\IDBConnection;
57
use OCP\IL10N;
58
use OCP\ILogger;
59
use OCP\IURLGenerator;
60
use OCP\IUserManager;
61
use OCP\Security\ISecureRandom;
62
use OCP\Share\Exceptions\IllegalIDChangeException;
63
use OCP\Share\Exceptions\ShareNotFound;
64
use OCP\Share\IShare;
65
use OCP\Share\IShareProvider;
66
67
68
class ShareByCircleProvider extends CircleProviderRequest implements IShareProvider {
69
70
71
	/** @var ILogger */
72
	private $logger;
73
74
	/** @var ISecureRandom */
75
	private $secureRandom;
76
77
	/** @var IUserManager */
78
	private $userManager;
79
80
	/** @var IRootFolder */
81
	private $rootFolder;
82
83
	/** @var IURLGenerator */
84
	private $urlGenerator;
85
86
	/** @var CirclesRequest */
87
	private $circlesRequest;
88
89
	/** @var MembersRequest */
90
	private $membersRequest;
91
92
	/** @var TokensRequest */
93
	private $tokensRequest;
94
95
	/**
96
	 * DefaultShareProvider constructor.
97
	 *
98
	 * @param IDBConnection $connection
99
	 * @param ISecureRandom $secureRandom
100
	 * @param IUserManager $userManager
101
	 * @param IRootFolder $rootFolder
102
	 * @param IL10N $l10n
103
	 * @param ILogger $logger
104
	 * @param IURLGenerator $urlGenerator
105
	 *
106
	 * @throws QueryException
107
	 */
108
	public function __construct(
109
		IDBConnection $connection, ISecureRandom $secureRandom, IUserManager $userManager,
110
		IRootFolder $rootFolder, IL10N $l10n, ILogger $logger, IURLGenerator $urlGenerator
111
	) {
112
		$app = new Application();
113
		$container = $app->getContainer();
114
		$configService = $container->query(ConfigService::class);
115
		$miscService = $container->query(MiscService::class);
116
		$timezoneService = $container->query(TimezoneService::class);
117
118
		parent::__construct($l10n, $connection, $configService, $timezoneService, $miscService);
119
120
		$this->secureRandom = $secureRandom;
121
		$this->userManager = $userManager;
122
		$this->rootFolder = $rootFolder;
123
		$this->logger = $logger;
124
		$this->urlGenerator = $urlGenerator;
125
		$this->circlesRequest = $container->query(CirclesRequest::class);
126
		$this->membersRequest = $container->query(MembersRequest::class);
127
		$this->tokensRequest = $container->query(TokensRequest::class);
128
	}
129
130
131
	/**
132
	 * Return the identifier of this provider.
133
	 *
134
	 * @return string
135
	 */
136
	public function identifier() {
137
		return 'ocCircleShare';
138
	}
139
140
141
	/**
142
	 * Create a share if it does not exist already.
143
	 *
144
	 * @param IShare $share
145
	 *
146
	 * @return IShare The share object
147
	 * @throws \Exception
148
	 */
149
	public function create(IShare $share) {
150
		try {
151
			$nodeId = $share->getNode()
152
							->getId();
153
154
			$qb = $this->findShareParentSql($nodeId, $share->getSharedWith());
155
			$exists = $qb->execute();
156
			$data = $exists->fetch();
157
			$exists->closeCursor();
158
159
			if ($data !== false) {
160
				throw $this->errorShareAlreadyExist($share);
161
			}
162
163
			$share->setToken($this->uuid(15));
164
			if ($this->configService->enforcePasswordProtection()) {
165
				$share->setPassword($this->uuid(15));
166
			}
167
168
			$this->createShare($share);
169
170
			$circle =
171
				$this->circlesRequest->getCircle($share->getSharedWith(), $share->getSharedby());
172
			$circle->getHigherViewer()
173
				   ->hasToBeMember();
174
175
			Circles::shareToCircle(
176
				$circle->getUniqueId(), 'files', '',
177
				['id' => $share->getId(), 'share' => $this->shareObjectToArray($share)],
178
				'\OCA\Circles\Circles\FileSharingBroadcaster'
179
			);
180
181
			return $this->getShareById($share->getId());
182
		} catch (\Exception $e) {
183
			throw $e;
184
		}
185
	}
186
187
188
	/**
189
	 * Update a share
190
	 * permissions right, owner and initiator
191
	 *
192
	 * @param IShare $share
193
	 *
194
	 * @return IShare The share object
195
	 */
196
	public function update(IShare $share) {
197
198
		$qb = $this->getBaseUpdateSql();
199
		$this->limitToShare($qb, $share->getId());
200
		$qb->set('permissions', $qb->createNamedParameter($share->getPermissions()))
201
		   ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
202
		   ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
203
		$qb->execute();
204
205
		return $share;
206
	}
207
208
209
	/**
210
	 * Delete a share, and it's children
211
	 *
212
	 * @param IShare $share
213
	 */
214
	public function delete(IShare $share) {
215
		$qb = $this->getBaseDeleteSql();
216
		$this->limitToShareAndChildren($qb, $share->getId());
217
218
		$qb->execute();
219
220
		$this->tokensRequest->removeTokenByShareId($share->getId());
221
	}
222
223
224
	/**
225
	 * Unshare a file from self as recipient.
226
	 * Because every circles share are group shares, we will set permissions to 0
227
	 *
228
	 * @param IShare $share
229
	 * @param string $userId
230
	 */
231 View Code Duplication
	public function deleteFromSelf(IShare $share, $userId) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
232
		$childId = $this->getShareChildId($share, $userId);
233
234
		$qb = $this->getBaseUpdateSql();
235
		$qb->set('permissions', $qb->createNamedParameter(0));
236
		$this->limitToShare($qb, $childId);
237
238
		$qb->execute();
239
	}
240
241
242
	/**
243
	 * Move a share as a recipient.
244
	 *
245
	 * @param IShare $share
246
	 * @param string $userId
247
	 *
248
	 * @return IShare
249
	 *
250
	 */
251 View Code Duplication
	public function move(IShare $share, $userId) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252
253
		$childId = $this->getShareChildId($share, $userId);
254
255
		$qb = $this->getBaseUpdateSql();
256
		$qb->set('file_target', $qb->createNamedParameter($share->getTarget()));
257
		$this->limitToShare($qb, $childId);
258
		$qb->execute();
259
260
		return $share;
261
	}
262
263
264
	/**
265
	 * return the child ID of a share
266
	 *
267
	 * @param IShare $share
268
	 * @param string $userId
269
	 *
270
	 * @return bool
271
	 */
272
	private function getShareChildId(IShare $share, $userId) {
273
		$qb = $this->getBaseSelectSql($share->getId());
274
		$this->limitToShareChildren($qb, $userId, $share->getId());
275
276
		$child = $qb->execute();
277
		$data = $child->fetch();
278
		$child->closeCursor();
279
280
		if ($data === false) {
281
			return $this->createShareChild($userId, $share);
282
		}
283
284
		return $data['id'];
285
	}
286
287
288
	/**
289
	 * Create a child and returns its ID
290
	 *
291
	 * @param IShare $share
292
	 */
293
	private function createShare($share) {
294
		$this->miscService->log(
295
			'Creating share (1/4) - type: ' . $share->getShareType() . ' - token: '
296
			. $share->getToken() . ' - type: ' . $share->getShareType() . ' - with: '
297
			. $share->getSharedWith() . ' - permissions: ' . $share->getPermissions(), 0
298
		);
299
300
		$qb = $this->getBaseInsertSql($share);
301
		$this->miscService->log('Share creation (2/4) : ' . json_encode($qb->getSQL()), 0);
302
303
		$result = $qb->execute();
304
		$this->miscService->log('Share creation result (3/4) : ' . json_encode($result), 0);
305
306
		$id = $qb->getLastInsertId();
307
		$this->miscService->log('Share created ID (4/4) : ' . $id, 0);
308
309
		try {
310
			$share->setId($id);
311
		} catch (IllegalIDChangeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Bug introduced by
The class OCP\Share\Exceptions\IllegalIDChangeException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
312
		}
313
	}
314
315
316
	/**
317
	 * Create a child and returns its ID
318
	 *
319
	 * @param string $userId
320
	 * @param IShare $share
321
	 *
322
	 * @return int
323
	 */
324
	private function createShareChild($userId, $share) {
325
		$qb = $this->getBaseInsertSql($share);
326
327
		$qb->setValue('parent', $qb->createNamedParameter($share->getId()));
328
		$qb->setValue('share_with', $qb->createNamedParameter($userId));
329
		$qb->execute();
330
		$id = $qb->getLastInsertId();
331
332
		return (int)$id;
333
	}
334
335
336
	/**
337
	 * Get all shares by the given user in a folder
338
	 *
339
	 * @param string $userId
340
	 * @param Folder $node
341
	 * @param bool $reshares Also get the shares where $user is the owner instead of just the
342
	 *     shares where $user is the initiator
343
	 *
344
	 * @return Share[]
345
	 */
346
	public function getSharesInFolder($userId, Folder $node, $reshares) {
347
		$qb = $this->getBaseSelectSql();
348
		$this->limitToShareOwner($qb, $userId, true);
349
		$cursor = $qb->execute();
350
351
		$shares = [];
352
		while ($data = $cursor->fetch()) {
353
			$shares[$data['file_source']][] = $this->createShareObject($data);
354
		}
355
		$cursor->closeCursor();
356
357
		return $shares;
358
	}
359
360
361
	/**
362
	 * Get all shares by the given user
363
	 *
364
	 * @param string $userId
365
	 * @param int $shareType
366
	 * @param Node|null $node
367
	 * @param bool $reShares
368
	 * @param int $limit The maximum number of shares to be returned, -1 for all shares
369
	 * @param int $offset
370
	 *
371
	 * @return Share[]
372
	 */
373
	public function getSharesBy($userId, $shareType, $node, $reShares, $limit, $offset) {
374
		$qb = $this->getBaseSelectSql();
375
376
		if ($node === null) {
377
			$this->limitToShareOwner($qb, $userId, $reShares);
378
		} else {
379
			$this->limitToFiles($qb, $node->getId());
380
		}
381
382
		$this->limitToPage($qb, $limit, $offset);
383
		$cursor = $qb->execute();
384
385
		$shares = [];
386
		while ($data = $cursor->fetch()) {
387
			$shares[] = $this->createShareObject($this->editShareEntry($data));
388
		}
389
		$cursor->closeCursor();
390
391
		return $shares;
392
	}
393
394
395
	/**
396
	 * returns a better formatted string to display more information about
397
	 * the circle to the Sharing UI
398
	 *
399
	 * @param $data
400
	 *
401
	 * @return array<string,string>
402
	 * @throws NoUserException
403
	 */
404
	private function editShareEntry($data) {
405
		$data['share_with'] =
406
			sprintf(
407
				'%s (%s, %s) [%s]', $data['circle_name'],
408
				Circle::TypeLongString($data['circle_type']),
409
				$this->miscService->getDisplayName($data['circle_owner']), $data['share_with']
410
			);
411
412
413
		return $data;
414
	}
415
416
417
	/**
418
	 * Get share by its id
419
	 *
420
	 * @param int $shareId
421
	 * @param string|null $recipientId
422
	 *
423
	 * @return Share
0 ignored issues
show
Documentation introduced by
Should the return type not be IShare?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
424
	 * @throws ShareNotFound
425
	 */
426
	public function getShareById($shareId, $recipientId = null) {
427
		$qb = $this->getBaseSelectSql();
428
429
		$this->limitToShare($qb, $shareId);
430
431
		$cursor = $qb->execute();
432
		$data = $cursor->fetch();
433
		$cursor->closeCursor();
434
435
		if ($data === false) {
436
			throw new ShareNotFound();
437
		}
438
439
		return $this->createShareObject($data);
440
	}
441
442
443
	/**
444
	 * Get shares for a given path
445
	 *
446
	 * @param Node $path
447
	 *
448
	 * @return IShare[]|null
0 ignored issues
show
Documentation introduced by
Should the return type not be array? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
449
	 */
450 View Code Duplication
	public function getSharesByPath(Node $path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
451
		$qb = $this->getBaseSelectSql();
452
		$this->limitToFiles($qb, [$path->getId()]);
453
		$cursor = $qb->execute();
454
455
		$shares = [];
456
		while ($data = $cursor->fetch()) {
457
			$shares[] = $this->createShareObject($data);
458
		}
459
		$cursor->closeCursor();
460
461
		return $shares;
462
	}
463
464
465
	/**
466
	 * Get shared with the given user
467
	 *
468
	 * @param string $userId get shares where this user is the recipient
469
	 * @param int $shareType
470
	 * @param Node|null $node
471
	 * @param int $limit The max number of entries returned, -1 for all
472
	 * @param int $offset
473
	 *
474
	 * @return IShare[]
475
	 */
476
	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
477
478
		$shares = $this->getSharedWithCircleMembers($userId, $shareType, $node, $limit, $offset);
479
480
		return $shares;
481
	}
482
483
484
	/**
485
	 * @param string $userId
486
	 * @param $shareType
487
	 * @param Node $node
488
	 * @param int $limit
489
	 * @param int $offset
490
	 *
491
	 * @return IShare[]
492
	 */
493
	private function getSharedWithCircleMembers($userId, $shareType, $node, $limit, $offset) {
494
495
		$qb = $this->getCompleteSelectSql();
496
		$this->linkToFileCache($qb, $userId);
497
		$this->limitToPage($qb, $limit, $offset);
498
499
		if ($node !== null) {
500
			$this->limitToFiles($qb, [$node->getId()]);
501
		}
502
503
		$this->linkToMember($qb, $userId, $this->configService->isLinkedGroupsAllowed());
504
505
		$cursor = $qb->execute();
506
507
		$shares = [];
508
		while ($data = $cursor->fetch()) {
509
			self::editShareFromParentEntry($data);
510
			if (self::isAccessibleResult($data)) {
511
				$shares[] = $this->createShareObject($data);
512
			}
513
		}
514
		$cursor->closeCursor();
515
516
		return $shares;
517
	}
518
519
520
	/**
521
	 * Get a share by token
522
	 *
523
	 * @param string $token
524
	 *
525
	 * @return IShare
526
	 * @throws ShareNotFound
527
	 * @deprecated - use local querybuilder lib instead
528
	 */
529
	public function getShareByToken($token) {
530
		$qb = $this->dbConnection->getQueryBuilder();
531
532
		$this->miscService->log("Opening share by token '#" . $token . "'", 0);
533
534
		$cursor = $qb->select('*')
535
					 ->from('share')
536
					 ->where(
537
						 $qb->expr()
538
							->eq(
539
								'share_type',
540
								$qb->createNamedParameter(\OCP\Share::SHARE_TYPE_CIRCLE)
541
							)
542
					 )
543
					 ->andWhere(
544
						 $qb->expr()
545
							->eq('token', $qb->createNamedParameter($token))
546
					 )
547
					 ->execute();
548
549
		$data = $cursor->fetch();
550
551
		if ($data === false) {
552
			$this->miscService->log("Share '#" . $token . "' not found.", 0);
553
			throw new ShareNotFound('Share not found', $this->l10n->t('Could not find share'));
554
		}
555
556
		try {
557
			$share = $this->createShareObject($data);
558
		} catch (InvalidShare $e) {
0 ignored issues
show
Bug introduced by
The class OC\Share20\Exception\InvalidShare does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
559
			$this->miscService->log(
560
				"Share Object '#" . $token . "' not created. " . json_encode($data), 0
561
			);
562
			throw new ShareNotFound('Share not found', $this->l10n->t('Could not find share'));
563
		}
564
565
		return $share;
566
	}
567
568
569
	/**
570
	 * We don't return a thing about children.
571
	 * The call to this function is deprecated and should be removed in next release of NC.
572
	 * Also, we get the children in the delete() method.
573
	 *
574
	 * @param IShare $parent
575
	 *
576
	 * @return array
577
	 */
578
	public function getChildren(IShare $parent) {
579
		return [];
580
	}
581
582
583
	/**
584
	 * A user is deleted from the system
585
	 * So clean up the relevant shares.
586
	 *
587
	 * @param string $uid
588
	 * @param int $shareType
589
	 */
590
	public function userDeleted($uid, $shareType) {
591
		// TODO: Implement userDeleted() method.
592
	}
593
594
595
	/**
596
	 * A group is deleted from the system.
597
	 * We handle our own groups.
598
	 *
599
	 * @param string $gid
600
	 */
601
	public function groupDeleted($gid) {
602
		return;
603
	}
604
605
606
	/**
607
	 * A user is deleted from a group.
608
	 * We handle our own groups.
609
	 *
610
	 * @param string $uid
611
	 * @param string $gid
612
	 */
613
	public function userDeletedFromGroup($uid, $gid) {
614
		return;
615
	}
616
617
618
	/**
619
	 * Create a share object
620
	 *
621
	 * @param array $data
622
	 *
623
	 * @return IShare
624
	 */
625
	private function createShareObject($data) {
626
		$share = new Share($this->rootFolder, $this->userManager);
627
		$share->setId((int)$data['id'])
628
			  ->setPermissions((int)$data['permissions'])
629
			  ->setNodeType($data['item_type'])
630
			  ->setPassword($data['password']);
631
632
		$share->setNodeId((int)$data['file_source'])
633
			  ->setTarget($data['file_target']);
634
635
		$this->assignShareObjectSharesProperties($share, $data);
636
		$this->assignShareObjectPropertiesFromParent($share, $data);
637
638
		$share->setProviderId($this->identifier());
639
640
		return $share;
641
	}
642
643
644
	/**
645
	 * @param IShare $share
646
	 * @param $data
647
	 */
648
	private function assignShareObjectPropertiesFromParent(IShare &$share, $data) {
649
		if (isset($data['f_permissions'])) {
650
			$entryData = $data;
651
			$entryData['permissions'] = $entryData['f_permissions'];
652
			$entryData['parent'] = $entryData['f_parent'];
653
			$share->setNodeCacheEntry(
654
				Cache::cacheEntryFromData(
655
					$entryData,
656
					OC::$server->getMimeTypeLoader()
657
				)
658
			);
659
		}
660
	}
661
662
663
	/**
664
	 * @param IShare $share
665
	 * @param $data
666
	 */
667
	private function assignShareObjectSharesProperties(IShare &$share, $data) {
668
		$shareTime = new \DateTime();
669
		$shareTime->setTimestamp((int)$data['stime']);
670
671
		$share->setShareTime($shareTime);
672
		$share->setSharedWith($data['share_with'])
673
			  ->setSharedBy($data['uid_initiator'])
674
			  ->setShareOwner($data['uid_owner'])
675
			  ->setShareType((int)$data['share_type']);
676
677
		if (array_key_exists('circle_type', $data)
678
			&& method_exists($share, 'setSharedWithDisplayName')) {
679
			$share->setSharedWithAvatar(CirclesService::getCircleIcon($data['circle_type']))
680
				  ->setSharedWithDisplayName(
681
					  sprintf(
682
						  '%s (%s, %s)', $data['circle_name'],
683
						  Circle::TypeLongString($data['circle_type']),
684
						  $this->miscService->getDisplayName($data['circle_owner'])
685
					  )
686
				  );
687
		}
688
	}
689
690
691
	/**
692
	 * @param IShare $share
693
	 *
694
	 * @return \Exception
695
	 */
696
	private function errorShareAlreadyExist($share) {
697
		$share_src = $share->getNode()
698
						   ->getName();
699
700
		$message = 'Sharing %s failed, this item is already shared with this circle';
701
		$message_t = $this->l10n->t($message, array($share_src));
702
		$this->logger->debug(
703
			sprintf($message, $share_src, $share->getSharedWith()), ['app' => 'circles']
704
		);
705
706
		return new \Exception($message_t);
707
	}
708
709
710
	/**
711
	 * Get the access list to the array of provided nodes.
712
	 *
713
	 * @param Node[] $nodes The list of nodes to get access for
714
	 * @param bool $currentAccess If current access is required (like for removed shares that might
715
	 *     get revived later)
716
	 *
717
	 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,array>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
718
	 * @see IManager::getAccessList() for sample docs
719
	 *
720
	 * @since 12
721
	 */
722
	public function getAccessList($nodes, $currentAccess) {
723
		$ids = [];
724
		foreach ($nodes as $node) {
725
			$ids[] = $node->getId();
726
		}
727
728
		$qb = $this->getAccessListBaseSelectSql();
729
		$this->limitToFiles($qb, $ids);
730
731
		$users = $this->parseAccessListResult($qb);
732
733
		if ($currentAccess === false) {
734
			$users = array_keys($users);
735
		}
736
737
		return ['users' => $users];
738
	}
739
740
741
	/**
742
	 * Restore a share for a given recipient. The implementation could be provider independant.
743
	 *
744
	 * @param IShare $share
745
	 * @param string $recipient
746
	 *
747
	 * @return IShare The restored share object
748
	 *
749
	 * @since 14.0.0
750
	 */
751
	public function restore(IShare $share, string $recipient): IShare {
752
		return $share;
753
	}
754
755
756
	/**
757
	 * return array regarding getAccessList format.
758
	 * ie. \OC\Share20\Manager::getAccessList()
759
	 *
760
	 * @param IQueryBuilder $qb
761
	 *
762
	 * @return array
763
	 */
764
	private function parseAccessListResult(IQueryBuilder $qb) {
765
766
		$cursor = $qb->execute();
767
		$users = [];
768
769
		while ($row = $cursor->fetch()) {
770
			$userId = $row['user_id'];
771
772
			if (!key_exists($userId, $users)) {
773
				$users[$userId] = [
774
					'node_id'   => $row['file_source'],
775
					'node_path' => $row['file_target']
776
				];
777
			}
778
		}
779
		$cursor->closeCursor();
780
781
		return $users;
782
	}
783
784
785
	/**
786
	 * @param IShare $share
787
	 *
788
	 * @return array
789
	 * @throws NotFoundException
790
	 */
791
	private function shareObjectToArray(IShare $share) {
792
		return [
793
			'id'          => $share->getId(),
794
			'sharedWith'  => $share->getSharedWith(),
795
			'sharedBy'    => $share->getSharedBy(),
796
			'nodeId'      => $share->getNodeId(),
797
			'shareOwner'  => $share->getShareOwner(),
798
			'permissions' => $share->getPermissions(),
799
			'token'       => $share->getToken(),
800
			'password'    => $share->getPassword()
801
		];
802
	}
803
804
805
	/**
806
	 * Generate uuid: 2b5a7a87-8db1-445f-a17b-405790f91c80
807
	 *
808
	 * @param int $length
809
	 *
810
	 * @return string
811
	 */
812
	private function uuid(int $length = 0): string {
813
		$uuid = sprintf(
814
			'%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), mt_rand(0, 0xffff),
815
			mt_rand(0, 0xffff), mt_rand(0, 0xfff) | 0x4000, mt_rand(0, 0x3fff) | 0x8000,
816
			mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
817
		);
818
819
		if ($length > 0) {
820
			if ($length <= 16) {
821
				$uuid = str_replace('-', '', $uuid);
822
			}
823
824
			$uuid = substr($uuid, 0, $length);
825
		}
826
827
		return $uuid;
828
	}
829
830
831
832
}
833