Completed
Push — master ( e0a21e...61fe4c )
by Maxence
21:04 queued 15s
created
tests/lib/Share20/ManagerTest.php 1 patch
Indentation   +4657 added lines, -4657 removed lines patch added patch discarded remove patch
@@ -64,10 +64,10 @@  discard block
 block discarded – undo
64 64
 use Psr\Log\LoggerInterface;
65 65
 
66 66
 class DummyShareManagerListener {
67
-	public function post() {
68
-	}
69
-	public function listener() {
70
-	}
67
+    public function post() {
68
+    }
69
+    public function listener() {
70
+    }
71 71
 }
72 72
 
73 73
 /**
@@ -77,4860 +77,4860 @@  discard block
 block discarded – undo
77 77
  * @group DB
78 78
  */
79 79
 class ManagerTest extends \Test\TestCase {
80
-	/** @var Manager */
81
-	protected $manager;
82
-	/** @var LoggerInterface|MockObject */
83
-	protected $logger;
84
-	/** @var IConfig|MockObject */
85
-	protected $config;
86
-	/** @var ISecureRandom|MockObject */
87
-	protected $secureRandom;
88
-	/** @var IHasher|MockObject */
89
-	protected $hasher;
90
-	/** @var IShareProvider|MockObject */
91
-	protected $defaultProvider;
92
-	/** @var IMountManager|MockObject */
93
-	protected $mountManager;
94
-	/** @var IGroupManager|MockObject */
95
-	protected $groupManager;
96
-	/** @var IL10N|MockObject */
97
-	protected $l;
98
-	/** @var IFactory|MockObject */
99
-	protected $l10nFactory;
100
-	/** @var DummyFactory */
101
-	protected $factory;
102
-	/** @var IUserManager|MockObject */
103
-	protected $userManager;
104
-	/** @var IRootFolder | MockObject */
105
-	protected $rootFolder;
106
-	/** @var IEventDispatcher|MockObject */
107
-	protected $dispatcher;
108
-	/** @var IMailer|MockObject */
109
-	protected $mailer;
110
-	/** @var IURLGenerator|MockObject */
111
-	protected $urlGenerator;
112
-	/** @var \OC_Defaults|MockObject */
113
-	protected $defaults;
114
-	/** @var IUserSession|MockObject */
115
-	protected $userSession;
116
-	/** @var KnownUserService|MockObject */
117
-	protected $knownUserService;
118
-	/** @var ShareDisableChecker|MockObject */
119
-	protected $shareDisabledChecker;
120
-	private DateTimeZone $timezone;
121
-	/** @var IDateTimeZone|MockObject */
122
-	protected $dateTimeZone;
123
-	/** @var IAppConfig|MockObject */
124
-	protected $appConfig;
125
-
126
-	protected function setUp(): void {
127
-		$this->logger = $this->createMock(LoggerInterface::class);
128
-		$this->config = $this->createMock(IConfig::class);
129
-		$this->secureRandom = $this->createMock(ISecureRandom::class);
130
-		$this->hasher = $this->createMock(IHasher::class);
131
-		$this->mountManager = $this->createMock(IMountManager::class);
132
-		$this->groupManager = $this->createMock(IGroupManager::class);
133
-		$this->userManager = $this->createMock(IUserManager::class);
134
-		$this->rootFolder = $this->createMock(IRootFolder::class);
135
-		$this->mailer = $this->createMock(IMailer::class);
136
-		$this->urlGenerator = $this->createMock(IURLGenerator::class);
137
-		$this->defaults = $this->createMock(\OC_Defaults::class);
138
-		$this->dispatcher = $this->createMock(IEventDispatcher::class);
139
-		$this->userSession = $this->createMock(IUserSession::class);
140
-		$this->knownUserService = $this->createMock(KnownUserService::class);
141
-
142
-		$this->shareDisabledChecker = new ShareDisableChecker($this->config, $this->userManager, $this->groupManager);
143
-		$this->dateTimeZone = $this->createMock(IDateTimeZone::class);
144
-		$this->timezone = new \DateTimeZone('Pacific/Auckland');
145
-		$this->dateTimeZone->method('getTimeZone')->willReturnCallback(fn () => $this->timezone);
146
-
147
-		$this->appConfig = $this->createMock(IAppConfig::class);
148
-
149
-		$this->l10nFactory = $this->createMock(IFactory::class);
150
-		$this->l = $this->createMock(IL10N::class);
151
-		$this->l->method('t')
152
-			->willReturnCallback(function ($text, $parameters = []) {
153
-				return vsprintf($text, $parameters);
154
-			});
155
-		$this->l->method('n')
156
-			->willReturnCallback(function ($singular, $plural, $count, $parameters = []) {
157
-				return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters);
158
-			});
159
-		$this->l10nFactory->method('get')->willReturn($this->l);
160
-
161
-		$this->factory = new DummyFactory(\OC::$server);
162
-
163
-		$this->manager = $this->createManager($this->factory);
164
-
165
-		$this->defaultProvider = $this->createMock(DefaultShareProvider::class);
166
-		$this->defaultProvider->method('identifier')->willReturn('default');
167
-		$this->factory->setProvider($this->defaultProvider);
168
-	}
169
-
170
-	private function createManager(IProviderFactory $factory): Manager {
171
-		return new Manager(
172
-			$this->logger,
173
-			$this->config,
174
-			$this->secureRandom,
175
-			$this->hasher,
176
-			$this->mountManager,
177
-			$this->groupManager,
178
-			$this->l10nFactory,
179
-			$factory,
180
-			$this->userManager,
181
-			$this->rootFolder,
182
-			$this->mailer,
183
-			$this->urlGenerator,
184
-			$this->defaults,
185
-			$this->dispatcher,
186
-			$this->userSession,
187
-			$this->knownUserService,
188
-			$this->shareDisabledChecker,
189
-			$this->dateTimeZone,
190
-			$this->appConfig,
191
-		);
192
-	}
193
-
194
-	/**
195
-	 * @return MockBuilder
196
-	 */
197
-	private function createManagerMock() {
198
-		return $this->getMockBuilder(Manager::class)
199
-			->setConstructorArgs([
200
-				$this->logger,
201
-				$this->config,
202
-				$this->secureRandom,
203
-				$this->hasher,
204
-				$this->mountManager,
205
-				$this->groupManager,
206
-				$this->l10nFactory,
207
-				$this->factory,
208
-				$this->userManager,
209
-				$this->rootFolder,
210
-				$this->mailer,
211
-				$this->urlGenerator,
212
-				$this->defaults,
213
-				$this->dispatcher,
214
-				$this->userSession,
215
-				$this->knownUserService,
216
-				$this->shareDisabledChecker,
217
-				$this->dateTimeZone,
218
-				$this->appConfig,
219
-			]);
220
-	}
221
-
222
-	private function createFolderMock(string $folderPath): MockObject&Folder {
223
-		$folder = $this->createMock(Folder::class);
224
-		$folder->method('getPath')->willReturn($folderPath);
225
-		$folder->method('getRelativePath')->willReturnCallback(
226
-			fn (string $path): ?string => PathHelper::getRelativePath($folderPath, $path)
227
-		);
228
-		return $folder;
229
-	}
230
-
231
-	public function testDeleteNoShareId(): void {
232
-		$this->expectException(\InvalidArgumentException::class);
233
-
234
-		$share = $this->manager->newShare();
235
-
236
-		$this->manager->deleteShare($share);
237
-	}
238
-
239
-	public static function dataTestDelete(): array {
240
-		return [
241
-			[IShare::TYPE_USER, 'sharedWithUser'],
242
-			[IShare::TYPE_GROUP, 'sharedWithGroup'],
243
-			[IShare::TYPE_LINK, ''],
244
-			[IShare::TYPE_REMOTE, '[email protected]'],
245
-		];
246
-	}
247
-
248
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestDelete')]
249
-	public function testDelete($shareType, $sharedWith): void {
250
-		$manager = $this->createManagerMock()
251
-			->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
252
-			->getMock();
253
-
254
-		$manager->method('deleteChildren')->willReturn([]);
255
-
256
-		$path = $this->createMock(File::class);
257
-		$path->method('getId')->willReturn(1);
258
-
259
-		$share = $this->manager->newShare();
260
-		$share->setId(42)
261
-			->setProviderId('prov')
262
-			->setShareType($shareType)
263
-			->setSharedWith($sharedWith)
264
-			->setSharedBy('sharedBy')
265
-			->setNode($path)
266
-			->setTarget('myTarget');
267
-
268
-		$manager->expects($this->once())->method('deleteChildren')->with($share);
269
-		$manager->expects($this->once())->method('promoteReshares')->with($share);
270
-
271
-		$this->defaultProvider
272
-			->expects($this->once())
273
-			->method('delete')
274
-			->with($share);
275
-
276
-		$calls = [
277
-			BeforeShareDeletedEvent::class,
278
-			ShareDeletedEvent::class,
279
-		];
280
-		$this->dispatcher->expects($this->exactly(2))
281
-			->method('dispatchTyped')
282
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
283
-				$expected = array_shift($calls);
284
-				$this->assertInstanceOf($expected, $event);
285
-				$this->assertEquals($share, $event->getShare());
286
-			});
287
-
288
-		$manager->deleteShare($share);
289
-	}
290
-
291
-	public function testDeleteLazyShare(): void {
292
-		$manager = $this->createManagerMock()
293
-			->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
294
-			->getMock();
295
-
296
-		$manager->method('deleteChildren')->willReturn([]);
297
-
298
-		$share = $this->manager->newShare();
299
-		$share->setId(42)
300
-			->setProviderId('prov')
301
-			->setShareType(IShare::TYPE_USER)
302
-			->setSharedWith('sharedWith')
303
-			->setSharedBy('sharedBy')
304
-			->setShareOwner('shareOwner')
305
-			->setTarget('myTarget')
306
-			->setNodeId(1)
307
-			->setNodeType('file');
308
-
309
-		$this->rootFolder->expects($this->never())->method($this->anything());
310
-
311
-		$manager->expects($this->once())->method('deleteChildren')->with($share);
312
-		$manager->expects($this->once())->method('promoteReshares')->with($share);
313
-
314
-		$this->defaultProvider
315
-			->expects($this->once())
316
-			->method('delete')
317
-			->with($share);
318
-
319
-		$calls = [
320
-			BeforeShareDeletedEvent::class,
321
-			ShareDeletedEvent::class,
322
-		];
323
-		$this->dispatcher->expects($this->exactly(2))
324
-			->method('dispatchTyped')
325
-			->willReturnCallback(function ($event) use (&$calls, $share): void {
326
-				$expected = array_shift($calls);
327
-				$this->assertInstanceOf($expected, $event);
328
-				$this->assertEquals($share, $event->getShare());
329
-			});
330
-
331
-		$manager->deleteShare($share);
332
-	}
333
-
334
-	public function testDeleteNested(): void {
335
-		$manager = $this->createManagerMock()
336
-			->onlyMethods(['getShareById', 'promoteReshares'])
337
-			->getMock();
338
-
339
-		$path = $this->createMock(File::class);
340
-		$path->method('getId')->willReturn(1);
341
-
342
-		$share1 = $this->manager->newShare();
343
-		$share1->setId(42)
344
-			->setProviderId('prov')
345
-			->setShareType(IShare::TYPE_USER)
346
-			->setSharedWith('sharedWith1')
347
-			->setSharedBy('sharedBy1')
348
-			->setNode($path)
349
-			->setTarget('myTarget1');
350
-
351
-		$share2 = $this->manager->newShare();
352
-		$share2->setId(43)
353
-			->setProviderId('prov')
354
-			->setShareType(IShare::TYPE_GROUP)
355
-			->setSharedWith('sharedWith2')
356
-			->setSharedBy('sharedBy2')
357
-			->setNode($path)
358
-			->setTarget('myTarget2')
359
-			->setParent(42);
360
-
361
-		$share3 = $this->manager->newShare();
362
-		$share3->setId(44)
363
-			->setProviderId('prov')
364
-			->setShareType(IShare::TYPE_LINK)
365
-			->setSharedBy('sharedBy3')
366
-			->setNode($path)
367
-			->setTarget('myTarget3')
368
-			->setParent(43);
369
-
370
-		$this->defaultProvider
371
-			->method('getChildren')
372
-			->willReturnMap([
373
-				[$share1, [$share2]],
374
-				[$share2, [$share3]],
375
-				[$share3, []],
376
-			]);
377
-
378
-		$deleteCalls = [
379
-			$share3,
380
-			$share2,
381
-			$share1,
382
-		];
383
-		$this->defaultProvider->expects($this->exactly(3))
384
-			->method('delete')
385
-			->willReturnCallback(function ($share) use (&$deleteCalls): void {
386
-				$expected = array_shift($deleteCalls);
387
-				$this->assertEquals($expected, $share);
388
-			});
389
-
390
-		$dispatchCalls = [
391
-			[BeforeShareDeletedEvent::class, $share1],
392
-			[BeforeShareDeletedEvent::class, $share2],
393
-			[BeforeShareDeletedEvent::class, $share3],
394
-			[ShareDeletedEvent::class, $share3],
395
-			[ShareDeletedEvent::class, $share2],
396
-			[ShareDeletedEvent::class, $share1],
397
-		];
398
-		$this->dispatcher->expects($this->exactly(6))
399
-			->method('dispatchTyped')
400
-			->willReturnCallback(function ($event) use (&$dispatchCalls): void {
401
-				$expected = array_shift($dispatchCalls);
402
-				$this->assertInstanceOf($expected[0], $event);
403
-				$this->assertEquals($expected[1]->getId(), $event->getShare()->getId());
404
-			});
405
-
406
-		$manager->deleteShare($share1);
407
-	}
408
-
409
-	public function testDeleteFromSelf(): void {
410
-		$manager = $this->createManagerMock()
411
-			->onlyMethods(['getShareById'])
412
-			->getMock();
413
-
414
-		$recipientId = 'unshareFrom';
415
-		$share = $this->manager->newShare();
416
-		$share->setId(42)
417
-			->setProviderId('prov')
418
-			->setShareType(IShare::TYPE_USER)
419
-			->setSharedWith('sharedWith')
420
-			->setSharedBy('sharedBy')
421
-			->setShareOwner('shareOwner')
422
-			->setTarget('myTarget')
423
-			->setNodeId(1)
424
-			->setNodeType('file');
425
-
426
-		$this->defaultProvider
427
-			->expects($this->once())
428
-			->method('deleteFromSelf')
429
-			->with($share, $recipientId);
430
-
431
-		$this->dispatcher->expects($this->once())
432
-			->method('dispatchTyped')
433
-			->with(
434
-				$this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) {
435
-					return $e->getShare() === $share;
436
-				})
437
-			);
438
-
439
-		$manager->deleteFromSelf($share, $recipientId);
440
-	}
441
-
442
-	public function testDeleteChildren(): void {
443
-		$manager = $this->createManagerMock()
444
-			->onlyMethods(['deleteShare'])
445
-			->getMock();
446
-
447
-		$share = $this->createMock(IShare::class);
448
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
449
-
450
-		$child1 = $this->createMock(IShare::class);
451
-		$child1->method('getShareType')->willReturn(IShare::TYPE_USER);
452
-		$child2 = $this->createMock(IShare::class);
453
-		$child2->method('getShareType')->willReturn(IShare::TYPE_USER);
454
-		$child3 = $this->createMock(IShare::class);
455
-		$child3->method('getShareType')->willReturn(IShare::TYPE_USER);
456
-
457
-		$shares = [
458
-			$child1,
459
-			$child2,
460
-			$child3,
461
-		];
462
-
463
-		$this->defaultProvider
464
-			->expects($this->exactly(4))
465
-			->method('getChildren')
466
-			->willReturnCallback(function ($_share) use ($share, $shares) {
467
-				if ($_share === $share) {
468
-					return $shares;
469
-				}
470
-				return [];
471
-			});
472
-
473
-		$calls = [
474
-			$child1,
475
-			$child2,
476
-			$child3,
477
-		];
478
-		$this->defaultProvider->expects($this->exactly(3))
479
-			->method('delete')
480
-			->willReturnCallback(function ($share) use (&$calls): void {
481
-				$expected = array_shift($calls);
482
-				$this->assertEquals($expected, $share);
483
-			});
484
-
485
-		$result = self::invokePrivate($manager, 'deleteChildren', [$share]);
486
-		$this->assertSame($shares, $result);
487
-	}
488
-
489
-	public function testPromoteReshareFile(): void {
490
-		$manager = $this->createManagerMock()
491
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
492
-			->getMock();
493
-
494
-		$file = $this->createMock(File::class);
495
-
496
-		$share = $this->createMock(IShare::class);
497
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
498
-		$share->method('getNodeType')->willReturn('folder');
499
-		$share->method('getSharedWith')->willReturn('userB');
500
-		$share->method('getNode')->willReturn($file);
501
-
502
-		$reShare = $this->createMock(IShare::class);
503
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
504
-		$reShare->method('getSharedBy')->willReturn('userB');
505
-		$reShare->method('getSharedWith')->willReturn('userC');
506
-		$reShare->method('getNode')->willReturn($file);
507
-
508
-		$this->defaultProvider->method('getSharesBy')
509
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
510
-				$this->assertEquals($file, $node);
511
-				if ($shareType === IShare::TYPE_USER) {
512
-					return match($userId) {
513
-						'userB' => [$reShare],
514
-					};
515
-				} else {
516
-					return [];
517
-				}
518
-			});
519
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
520
-
521
-		$manager->expects($this->exactly(1))->method('updateShare')->with($reShare);
522
-
523
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
524
-	}
525
-
526
-	public function testPromoteReshare(): void {
527
-		$manager = $this->createManagerMock()
528
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
529
-			->getMock();
530
-
531
-		$folder = $this->createFolderMock('/path/to/folder');
532
-
533
-		$subFolder = $this->createFolderMock('/path/to/folder/sub');
534
-
535
-		$otherFolder = $this->createFolderMock('/path/to/otherfolder/');
536
-
537
-		$share = $this->createMock(IShare::class);
538
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
539
-		$share->method('getNodeType')->willReturn('folder');
540
-		$share->method('getSharedWith')->willReturn('userB');
541
-		$share->method('getNode')->willReturn($folder);
542
-
543
-		$reShare = $this->createMock(IShare::class);
544
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
545
-		$reShare->method('getSharedBy')->willReturn('userB');
546
-		$reShare->method('getSharedWith')->willReturn('userC');
547
-		$reShare->method('getNode')->willReturn($folder);
548
-
549
-		$reShareInSubFolder = $this->createMock(IShare::class);
550
-		$reShareInSubFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
551
-		$reShareInSubFolder->method('getSharedBy')->willReturn('userB');
552
-		$reShareInSubFolder->method('getNode')->willReturn($subFolder);
553
-
554
-		$reShareInOtherFolder = $this->createMock(IShare::class);
555
-		$reShareInOtherFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
556
-		$reShareInOtherFolder->method('getSharedBy')->willReturn('userB');
557
-		$reShareInOtherFolder->method('getNode')->willReturn($otherFolder);
558
-
559
-		$this->defaultProvider->method('getSharesBy')
560
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
561
-				if ($shareType === IShare::TYPE_USER) {
562
-					return match($userId) {
563
-						'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder],
564
-					};
565
-				} else {
566
-					return [];
567
-				}
568
-			});
569
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
570
-
571
-		$calls = [
572
-			$reShare,
573
-			$reShareInSubFolder,
574
-		];
575
-		$manager->expects($this->exactly(2))
576
-			->method('updateShare')
577
-			->willReturnCallback(function ($share) use (&$calls): void {
578
-				$expected = array_shift($calls);
579
-				$this->assertEquals($expected, $share);
580
-			});
581
-
582
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
583
-	}
584
-
585
-	public function testPromoteReshareWhenUserHasAnotherShare(): void {
586
-		$manager = $this->createManagerMock()
587
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
588
-			->getMock();
589
-
590
-		$folder = $this->createFolderMock('/path/to/folder');
591
-
592
-		$share = $this->createMock(IShare::class);
593
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
594
-		$share->method('getNodeType')->willReturn('folder');
595
-		$share->method('getSharedWith')->willReturn('userB');
596
-		$share->method('getNode')->willReturn($folder);
597
-
598
-		$reShare = $this->createMock(IShare::class);
599
-		$reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
600
-		$reShare->method('getNodeType')->willReturn('folder');
601
-		$reShare->method('getSharedBy')->willReturn('userB');
602
-		$reShare->method('getNode')->willReturn($folder);
603
-
604
-		$this->defaultProvider->method('getSharesBy')->willReturn([$reShare]);
605
-		$manager->method('generalCreateChecks')->willReturn(true);
606
-
607
-		/* No share is promoted because generalCreateChecks does not throw */
608
-		$manager->expects($this->never())->method('updateShare');
609
-
610
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
611
-	}
612
-
613
-	public function testPromoteReshareOfUsersInGroupShare(): void {
614
-		$manager = $this->createManagerMock()
615
-			->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
616
-			->getMock();
617
-
618
-		$folder = $this->createFolderMock('/path/to/folder');
619
-
620
-		$userA = $this->createMock(IUser::class);
621
-		$userA->method('getUID')->willReturn('userA');
622
-
623
-		$share = $this->createMock(IShare::class);
624
-		$share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
625
-		$share->method('getNodeType')->willReturn('folder');
626
-		$share->method('getSharedWith')->willReturn('Group');
627
-		$share->method('getNode')->willReturn($folder);
628
-		$share->method('getShareOwner')->willReturn($userA);
629
-
630
-		$reShare1 = $this->createMock(IShare::class);
631
-		$reShare1->method('getShareType')->willReturn(IShare::TYPE_USER);
632
-		$reShare1->method('getNodeType')->willReturn('folder');
633
-		$reShare1->method('getSharedBy')->willReturn('userB');
634
-		$reShare1->method('getNode')->willReturn($folder);
635
-
636
-		$reShare2 = $this->createMock(IShare::class);
637
-		$reShare2->method('getShareType')->willReturn(IShare::TYPE_USER);
638
-		$reShare2->method('getNodeType')->willReturn('folder');
639
-		$reShare2->method('getSharedBy')->willReturn('userC');
640
-		$reShare2->method('getNode')->willReturn($folder);
641
-
642
-		$userB = $this->createMock(IUser::class);
643
-		$userB->method('getUID')->willReturn('userB');
644
-		$userC = $this->createMock(IUser::class);
645
-		$userC->method('getUID')->willReturn('userC');
646
-		$group = $this->createMock(IGroup::class);
647
-		$group->method('getUsers')->willReturn([$userB, $userC]);
648
-		$this->groupManager->method('get')->with('Group')->willReturn($group);
649
-
650
-		$this->defaultProvider->method('getSharesBy')
651
-			->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
652
-				if ($shareType === IShare::TYPE_USER) {
653
-					return match($userId) {
654
-						'userB' => [$reShare1],
655
-						'userC' => [$reShare2],
656
-					};
657
-				} else {
658
-					return [];
659
-				}
660
-			});
661
-		$manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
662
-
663
-		$manager->method('getSharedWith')->willReturn([]);
664
-
665
-		$calls = [
666
-			$reShare1,
667
-			$reShare2,
668
-		];
669
-		$manager->expects($this->exactly(2))
670
-			->method('updateShare')
671
-			->willReturnCallback(function ($share) use (&$calls): void {
672
-				$expected = array_shift($calls);
673
-				$this->assertEquals($expected, $share);
674
-			});
675
-
676
-		self::invokePrivate($manager, 'promoteReshares', [$share]);
677
-	}
678
-
679
-	public function testGetShareById(): void {
680
-		$share = $this->createMock(IShare::class);
681
-
682
-		$this->defaultProvider
683
-			->expects($this->once())
684
-			->method('getShareById')
685
-			->with(42)
686
-			->willReturn($share);
687
-
688
-		$this->assertEquals($share, $this->manager->getShareById('default:42'));
689
-	}
690
-
691
-
692
-	public function testGetExpiredShareById(): void {
693
-		$this->expectException(ShareNotFound::class);
694
-
695
-		$manager = $this->createManagerMock()
696
-			->onlyMethods(['deleteShare'])
697
-			->getMock();
698
-
699
-		$date = new \DateTime();
700
-		$date->setTime(0, 0, 0);
701
-
702
-		$share = $this->manager->newShare();
703
-		$share->setExpirationDate($date)
704
-			->setShareType(IShare::TYPE_LINK);
705
-
706
-		$this->defaultProvider->expects($this->once())
707
-			->method('getShareById')
708
-			->with('42')
709
-			->willReturn($share);
710
-
711
-		$manager->expects($this->once())
712
-			->method('deleteShare')
713
-			->with($share);
714
-
715
-		$manager->getShareById('default:42');
716
-	}
717
-
718
-
719
-	public function testVerifyPasswordNullButEnforced(): void {
720
-		$this->expectException(\InvalidArgumentException::class);
721
-		$this->expectExceptionMessage('Passwords are enforced for link and mail shares');
722
-
723
-		$this->config->method('getAppValue')->willReturnMap([
724
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
725
-		]);
726
-
727
-		$this->appConfig->method('getValueBool')->willReturnMap([
728
-			['core', 'shareapi_enforce_links_password', true],
729
-		]);
730
-
731
-		self::invokePrivate($this->manager, 'verifyPassword', [null]);
732
-	}
733
-
734
-	public function testVerifyPasswordNotEnforcedGroup(): void {
735
-		$this->config->method('getAppValue')->willReturnMap([
736
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'],
737
-			['core', 'shareapi_enforce_links_password', 'no', 'yes'],
738
-		]);
739
-
740
-		// Create admin user
741
-		$user = $this->createMock(IUser::class);
742
-		$this->userSession->method('getUser')->willReturn($user);
743
-		$this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['admin']);
744
-
745
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
746
-		$this->assertNull($result);
747
-	}
748
-
749
-	public function testVerifyPasswordNotEnforcedMultipleGroups(): void {
750
-		$this->config->method('getAppValue')->willReturnMap([
751
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'],
752
-			['core', 'shareapi_enforce_links_password', 'no', 'yes'],
753
-		]);
754
-
755
-		// Create admin user
756
-		$user = $this->createMock(IUser::class);
757
-		$this->userSession->method('getUser')->willReturn($user);
758
-		$this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['special']);
759
-
760
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
761
-		$this->assertNull($result);
762
-	}
763
-
764
-	public function testVerifyPasswordNull(): void {
765
-		$this->config->method('getAppValue')->willReturnMap([
766
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
767
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
768
-		]);
769
-
770
-		$result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
771
-		$this->assertNull($result);
772
-	}
773
-
774
-	public function testVerifyPasswordHook(): void {
775
-		$this->config->method('getAppValue')->willReturnMap([
776
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
777
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
778
-		]);
779
-
780
-		$this->dispatcher->expects($this->once())->method('dispatchTyped')
781
-			->willReturnCallback(function (Event $event): void {
782
-				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
783
-				/** @var ValidatePasswordPolicyEvent $event */
784
-				$this->assertSame('password', $event->getPassword());
785
-			}
786
-			);
787
-
788
-		$result = self::invokePrivate($this->manager, 'verifyPassword', ['password']);
789
-		$this->assertNull($result);
790
-	}
791
-
792
-
793
-	public function testVerifyPasswordHookFails(): void {
794
-		$this->expectException(\Exception::class);
795
-		$this->expectExceptionMessage('password not accepted');
796
-
797
-		$this->config->method('getAppValue')->willReturnMap([
798
-			['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
799
-			['core', 'shareapi_enforce_links_password', 'no', 'no'],
800
-		]);
801
-
802
-		$this->dispatcher->expects($this->once())->method('dispatchTyped')
803
-			->willReturnCallback(function (Event $event): void {
804
-				$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
805
-				/** @var ValidatePasswordPolicyEvent $event */
806
-				$this->assertSame('password', $event->getPassword());
807
-				throw new HintException('password not accepted');
808
-			}
809
-			);
810
-
811
-		self::invokePrivate($this->manager, 'verifyPassword', ['password']);
812
-	}
813
-
814
-	public function createShare($id, $type, $node, $sharedWith, $sharedBy, $shareOwner,
815
-		$permissions, $expireDate = null, $password = null, $attributes = null) {
816
-		$share = $this->createMock(IShare::class);
817
-
818
-		$share->method('getShareType')->willReturn($type);
819
-		$share->method('getSharedWith')->willReturn($sharedWith);
820
-		$share->method('getSharedBy')->willReturn($sharedBy);
821
-		$share->method('getShareOwner')->willReturn($shareOwner);
822
-		$share->method('getNode')->willReturn($node);
823
-		if ($node && $node->getId()) {
824
-			$share->method('getNodeId')->willReturn($node->getId());
825
-		}
826
-		$share->method('getPermissions')->willReturn($permissions);
827
-		$share->method('getAttributes')->willReturn($attributes);
828
-		$share->method('getExpirationDate')->willReturn($expireDate);
829
-		$share->method('getPassword')->willReturn($password);
830
-
831
-		return $share;
832
-	}
833
-
834
-	public function dataGeneralChecks() {
835
-		$user0 = 'user0';
836
-		$user2 = 'user1';
837
-		$group0 = 'group0';
838
-		$owner = $this->createMock(IUser::class);
839
-		$owner->method('getUID')
840
-			->willReturn($user0);
841
-
842
-		$file = $this->createMock(File::class);
843
-		$node = $this->createMock(Node::class);
844
-		$storage = $this->createMock(IStorage::class);
845
-		$storage->method('instanceOfStorage')
846
-			->with('\OCA\Files_Sharing\External\Storage')
847
-			->willReturn(false);
848
-		$file->method('getStorage')
849
-			->willReturn($storage);
850
-		$file->method('getId')->willReturn(108);
851
-		$node->method('getStorage')
852
-			->willReturn($storage);
853
-		$node->method('getId')->willReturn(108);
854
-
855
-		$data = [
856
-			[$this->createShare(null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
857
-			[$this->createShare(null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
858
-			[$this->createShare(null, IShare::TYPE_USER, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
859
-			[$this->createShare(null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
860
-			[$this->createShare(null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
861
-			[$this->createShare(null, IShare::TYPE_GROUP, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
862
-			[$this->createShare(null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
863
-			[$this->createShare(null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
864
-			[$this->createShare(null, IShare::TYPE_LINK, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
865
-			[$this->createShare(null, -1, $file, null, $user0, $user0, 31, null, null), 'Unknown share type', true],
866
-
867
-			[$this->createShare(null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null), 'Share initiator must be set', true],
868
-			[$this->createShare(null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null), 'Share initiator must be set', true],
869
-			[$this->createShare(null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null), 'Share initiator must be set', true],
870
-
871
-			[$this->createShare(null, IShare::TYPE_USER, $file, $user0, $user0, $user0, 31, null, null), 'Cannot share with yourself', true],
872
-
873
-			[$this->createShare(null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null), 'Shared path must be set', true],
874
-			[$this->createShare(null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null), 'Shared path must be set', true],
875
-			[$this->createShare(null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null), 'Shared path must be set', true],
876
-
877
-			[$this->createShare(null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
878
-			[$this->createShare(null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
879
-			[$this->createShare(null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
880
-		];
881
-
882
-		$nonShareAble = $this->createMock(Folder::class);
883
-		$nonShareAble->method('getId')->willReturn(108);
884
-		$nonShareAble->method('isShareable')->willReturn(false);
885
-		$nonShareAble->method('getPath')->willReturn('path');
886
-		$nonShareAble->method('getName')->willReturn('name');
887
-		$nonShareAble->method('getOwner')
888
-			->willReturn($owner);
889
-		$nonShareAble->method('getStorage')
890
-			->willReturn($storage);
891
-
892
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $nonShareAble, $user2, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
893
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $nonShareAble, $group0, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
894
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $nonShareAble, null, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
895
-
896
-		$limitedPermssions = $this->createMock(File::class);
897
-		$limitedPermssions->method('isShareable')->willReturn(true);
898
-		$limitedPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
899
-		$limitedPermssions->method('getId')->willReturn(108);
900
-		$limitedPermssions->method('getPath')->willReturn('path');
901
-		$limitedPermssions->method('getName')->willReturn('name');
902
-		$limitedPermssions->method('getOwner')
903
-			->willReturn($owner);
904
-		$limitedPermssions->method('getStorage')
905
-			->willReturn($storage);
906
-
907
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
908
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
909
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
910
-
911
-		$mount = $this->createMock(MoveableMount::class);
912
-		$limitedPermssions->method('getMountPoint')->willReturn($mount);
913
-
914
-		// increase permissions of a re-share
915
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null), 'Cannot increase permissions of path', true];
916
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true];
917
-
918
-		$nonMovableStorage = $this->createMock(IStorage::class);
919
-		$nonMovableStorage->method('instanceOfStorage')
920
-			->with('\OCA\Files_Sharing\External\Storage')
921
-			->willReturn(false);
922
-		$nonMovableStorage->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
923
-		$nonMoveableMountPermssions = $this->createMock(Folder::class);
924
-		$nonMoveableMountPermssions->method('isShareable')->willReturn(true);
925
-		$nonMoveableMountPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
926
-		$nonMoveableMountPermssions->method('getId')->willReturn(108);
927
-		$nonMoveableMountPermssions->method('getPath')->willReturn('path');
928
-		$nonMoveableMountPermssions->method('getName')->willReturn('name');
929
-		$nonMoveableMountPermssions->method('getInternalPath')->willReturn('');
930
-		$nonMoveableMountPermssions->method('getOwner')
931
-			->willReturn($owner);
932
-		$nonMoveableMountPermssions->method('getStorage')
933
-			->willReturn($nonMovableStorage);
934
-
935
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $nonMoveableMountPermssions, $user2, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false];
936
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $nonMoveableMountPermssions, $group0, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false];
937
-
938
-		$rootFolder = $this->createMock(Folder::class);
939
-		$rootFolder->method('isShareable')->willReturn(true);
940
-		$rootFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
941
-		$rootFolder->method('getId')->willReturn(42);
942
-
943
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $rootFolder, $user2, $user0, $user0, 30, null, null), 'You cannot share your root folder', true];
944
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null), 'You cannot share your root folder', true];
945
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null), 'You cannot share your root folder', true];
946
-
947
-		$allPermssionsFiles = $this->createMock(File::class);
948
-		$allPermssionsFiles->method('isShareable')->willReturn(true);
949
-		$allPermssionsFiles->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
950
-		$allPermssionsFiles->method('getId')->willReturn(187);
951
-		$allPermssionsFiles->method('getOwner')
952
-			->willReturn($owner);
953
-		$allPermssionsFiles->method('getStorage')
954
-			->willReturn($storage);
955
-
956
-		// test invalid CREATE or DELETE permissions
957
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, Constants::PERMISSION_ALL, null, null), 'File shares cannot have create or delete permissions', true];
958
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_CREATE, null, null), 'File shares cannot have create or delete permissions', true];
959
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_DELETE, null, null), 'File shares cannot have create or delete permissions', true];
960
-
961
-		$allPermssions = $this->createMock(Folder::class);
962
-		$allPermssions->method('isShareable')->willReturn(true);
963
-		$allPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
964
-		$allPermssions->method('getId')->willReturn(108);
965
-		$allPermssions->method('getOwner')
966
-			->willReturn($owner);
967
-		$allPermssions->method('getStorage')
968
-			->willReturn($storage);
969
-
970
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true];
971
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true];
972
-
973
-		// test invalid permissions
974
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null), 'Valid permissions are required for sharing', true];
975
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null), 'Valid permissions are required for sharing', true];
976
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null), 'Valid permissions are required for sharing', true];
977
-
978
-		// working shares
979
-		$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false];
980
-		$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false];
981
-		$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null), null, false];
982
-
983
-
984
-		$remoteStorage = $this->createMock(IStorage::class);
985
-		$remoteStorage->method('instanceOfStorage')
986
-			->with('\OCA\Files_Sharing\External\Storage')
987
-			->willReturn(true);
988
-		$remoteFile = $this->createMock(Folder::class);
989
-		$remoteFile->method('isShareable')->willReturn(true);
990
-		$remoteFile->method('getPermissions')->willReturn(Constants::PERMISSION_READ ^ Constants::PERMISSION_UPDATE);
991
-		$remoteFile->method('getId')->willReturn(108);
992
-		$remoteFile->method('getOwner')
993
-			->willReturn($owner);
994
-		$remoteFile->method('getStorage')
995
-			->willReturn($storage);
996
-		$data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 1, null, null), null, false];
997
-		$data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 3, null, null), null, false];
998
-		$data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 31, null, null), 'Cannot increase permissions of ', true];
999
-
1000
-		return $data;
1001
-	}
1002
-
1003
-	/**
1004
-	 *
1005
-	 * @param $share
1006
-	 * @param $exceptionMessage
1007
-	 * @param $exception
1008
-	 */
1009
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataGeneralChecks')]
1010
-	public function testGeneralChecks($share, $exceptionMessage, $exception): void {
1011
-		$thrown = null;
1012
-
1013
-		$this->userManager->method('userExists')->willReturnMap([
1014
-			['user0', true],
1015
-			['user1', true],
1016
-		]);
1017
-
1018
-		$this->groupManager->method('groupExists')->willReturnMap([
1019
-			['group0', true],
1020
-		]);
1021
-
1022
-		$userFolder = $this->createMock(Folder::class);
1023
-		$userFolder->expects($this->any())
1024
-			->method('getId')
1025
-			->willReturn(42);
1026
-		// Id 108 is used in the data to refer to the node of the share.
1027
-		$userFolder->method('getById')
1028
-			->with(108)
1029
-			->willReturn([$share->getNode()]);
1030
-		$userFolder->expects($this->any())
1031
-			->method('getRelativePath')
1032
-			->willReturnArgument(0);
1033
-		$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1034
-
1035
-
1036
-		try {
1037
-			self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1038
-			$thrown = false;
1039
-		} catch (GenericShareException $e) {
1040
-			$this->assertEquals($exceptionMessage, $e->getHint());
1041
-			$thrown = true;
1042
-		} catch (\InvalidArgumentException $e) {
1043
-			$this->assertEquals($exceptionMessage, $e->getMessage());
1044
-			$thrown = true;
1045
-		}
1046
-
1047
-		$this->assertSame($exception, $thrown);
1048
-	}
1049
-
1050
-
1051
-	public function testGeneralCheckShareRoot(): void {
1052
-		$this->expectException(\InvalidArgumentException::class);
1053
-		$this->expectExceptionMessage('You cannot share your root folder');
1054
-
1055
-		$thrown = null;
1056
-
1057
-		$this->userManager->method('userExists')->willReturnMap([
1058
-			['user0', true],
1059
-			['user1', true],
1060
-		]);
1061
-
1062
-		$userFolder = $this->createMock(Folder::class);
1063
-		$userFolder->method('isSubNode')->with($userFolder)->willReturn(false);
1064
-		$this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1065
-
1066
-		$share = $this->manager->newShare();
1067
-
1068
-		$share->setShareType(IShare::TYPE_USER)
1069
-			->setSharedWith('user0')
1070
-			->setSharedBy('user1')
1071
-			->setNode($userFolder);
1072
-
1073
-		self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1074
-	}
1075
-
1076
-	public static function validateExpirationDateInternalProvider() {
1077
-		return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]];
1078
-	}
1079
-
1080
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1081
-	public function testValidateExpirationDateInternalInPast($shareType): void {
1082
-		$this->expectException(GenericShareException::class);
1083
-		$this->expectExceptionMessage('Expiration date is in the past');
1084
-
1085
-		// Expire date in the past
1086
-		$past = new \DateTime();
1087
-		$past->sub(new \DateInterval('P1D'));
1088
-
1089
-		$share = $this->manager->newShare();
1090
-		$share->setShareType($shareType);
1091
-		$share->setExpirationDate($past);
1092
-
1093
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1094
-	}
1095
-
1096
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1097
-	public function testValidateExpirationDateInternalEnforceButNotSet($shareType): void {
1098
-		$this->expectException(\InvalidArgumentException::class);
1099
-		$this->expectExceptionMessage('Expiration date is enforced');
1100
-
1101
-		$share = $this->manager->newShare();
1102
-		$share->setProviderId('foo')->setId('bar');
1103
-		$share->setShareType($shareType);
1104
-		if ($shareType === IShare::TYPE_USER) {
1105
-			$this->config->method('getAppValue')
1106
-				->willReturnMap([
1107
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1108
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1109
-				]);
1110
-		} else {
1111
-			$this->config->method('getAppValue')
1112
-				->willReturnMap([
1113
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1114
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1115
-				]);
1116
-		}
1117
-
1118
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1119
-	}
1120
-
1121
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1122
-	public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType): void {
1123
-		$share = $this->manager->newShare();
1124
-		$share->setProviderId('foo')->setId('bar');
1125
-		$share->setShareType($shareType);
1126
-
1127
-		if ($shareType === IShare::TYPE_USER) {
1128
-			$this->config->method('getAppValue')
1129
-				->willReturnMap([
1130
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1131
-				]);
1132
-		} else {
1133
-			$this->config->method('getAppValue')
1134
-				->willReturnMap([
1135
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1136
-				]);
1137
-		}
1138
-
1139
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1140
-
1141
-		$this->assertNull($share->getExpirationDate());
1142
-	}
1143
-
1144
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1145
-	public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType): void {
1146
-		$share = $this->manager->newShare();
1147
-		$share->setShareType($shareType);
1148
-
1149
-		if ($shareType === IShare::TYPE_USER) {
1150
-			$this->config->method('getAppValue')
1151
-				->willReturnMap([
1152
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1153
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1154
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1155
-					['core', 'internal_defaultExpDays', '3', '3'],
1156
-				]);
1157
-		} else {
1158
-			$this->config->method('getAppValue')
1159
-				->willReturnMap([
1160
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1161
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1162
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1163
-					['core', 'remote_defaultExpDays', '3', '3'],
1164
-				]);
1165
-		}
1166
-
1167
-		$expected = new \DateTime('now', $this->timezone);
1168
-		$expected->setTime(0, 0, 0);
1169
-		$expected->add(new \DateInterval('P3D'));
1170
-
1171
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1172
-
1173
-		$this->assertNotNull($share->getExpirationDate());
1174
-		$this->assertEquals($expected, $share->getExpirationDate());
1175
-	}
1176
-
1177
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1178
-	public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType): void {
1179
-		$share = $this->manager->newShare();
1180
-		$share->setShareType($shareType);
1181
-
1182
-		if ($shareType === IShare::TYPE_USER) {
1183
-			$this->config->method('getAppValue')
1184
-				->willReturnMap([
1185
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1186
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1187
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1188
-					['core', 'internal_defaultExpDays', '3', '1'],
1189
-				]);
1190
-		} else {
1191
-			$this->config->method('getAppValue')
1192
-				->willReturnMap([
1193
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1194
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1195
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1196
-					['core', 'remote_defaultExpDays', '3', '1'],
1197
-				]);
1198
-		}
1199
-
1200
-		$expected = new \DateTime('now', $this->timezone);
1201
-		$expected->setTime(0, 0, 0);
1202
-		$expected->add(new \DateInterval('P1D'));
1203
-
1204
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1205
-
1206
-		$this->assertNotNull($share->getExpirationDate());
1207
-		$this->assertEquals($expected, $share->getExpirationDate());
1208
-	}
1209
-
1210
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1211
-	public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType): void {
1212
-		$this->expectException(GenericShareException::class);
1213
-		$this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1214
-
1215
-		$future = new \DateTime();
1216
-		$future->add(new \DateInterval('P7D'));
1217
-
1218
-		$share = $this->manager->newShare();
1219
-		$share->setShareType($shareType);
1220
-		$share->setExpirationDate($future);
1221
-
1222
-		if ($shareType === IShare::TYPE_USER) {
1223
-			$this->config->method('getAppValue')
1224
-				->willReturnMap([
1225
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1226
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1227
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1228
-				]);
1229
-		} else {
1230
-			$this->config->method('getAppValue')
1231
-				->willReturnMap([
1232
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1233
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1234
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1235
-				]);
1236
-		}
1237
-
1238
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1239
-	}
1240
-
1241
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1242
-	public function testValidateExpirationDateInternalEnforceValid($shareType): void {
1243
-		$future = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1244
-		$future->add(new \DateInterval('P2D'));
1245
-		$future->setTime(1, 2, 3);
1246
-
1247
-		$expected = clone $future;
1248
-		$expected->setTime(0, 0, 0);
1249
-
1250
-		$share = $this->manager->newShare();
1251
-		$share->setShareType($shareType);
1252
-		$share->setExpirationDate($future);
1253
-
1254
-		if ($shareType === IShare::TYPE_USER) {
1255
-			$this->config->method('getAppValue')
1256
-				->willReturnMap([
1257
-					['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1258
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1259
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1260
-				]);
1261
-		} else {
1262
-			$this->config->method('getAppValue')
1263
-				->willReturnMap([
1264
-					['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1265
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1266
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1267
-				]);
1268
-		}
1269
-
1270
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1271
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1272
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1273
-			return $data['expirationDate'] == $future;
1274
-		}));
1275
-
1276
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1277
-
1278
-		$this->assertEquals($expected, $share->getExpirationDate());
1279
-	}
1280
-
1281
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1282
-	public function testValidateExpirationDateInternalNoDefault($shareType): void {
1283
-		$date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1284
-		$date->add(new \DateInterval('P5D'));
1285
-		$date->setTime(1, 2, 3);
1286
-
1287
-		$expected = clone $date;
1288
-		$expected->setTime(0, 0, 0);
1289
-
1290
-		$share = $this->manager->newShare();
1291
-		$share->setShareType($shareType);
1292
-		$share->setExpirationDate($date);
1293
-
1294
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1295
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1296
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1297
-			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1298
-		}));
1299
-
1300
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1301
-
1302
-		$this->assertEquals($expected, $share->getExpirationDate());
1303
-	}
1304
-
1305
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1306
-	public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void {
1307
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1308
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1309
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1310
-			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1311
-		}));
1312
-
1313
-		$share = $this->manager->newShare();
1314
-		$share->setShareType($shareType);
1315
-		$share->setPassword('password');
1316
-
1317
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1318
-
1319
-		$this->assertNull($share->getExpirationDate());
1320
-	}
1321
-
1322
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1323
-	public function testValidateExpirationDateInternalNoDateDefault($shareType): void {
1324
-		$share = $this->manager->newShare();
1325
-		$share->setShareType($shareType);
1326
-
1327
-		$expected = new \DateTime('now', $this->timezone);
1328
-		$expected->setTime(0, 0);
1329
-		$expected->add(new \DateInterval('P3D'));
1330
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1331
-
1332
-		if ($shareType === IShare::TYPE_USER) {
1333
-			$this->config->method('getAppValue')
1334
-				->willReturnMap([
1335
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1336
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1337
-					['core', 'internal_defaultExpDays', '3', '3'],
1338
-				]);
1339
-		} else {
1340
-			$this->config->method('getAppValue')
1341
-				->willReturnMap([
1342
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1343
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1344
-					['core', 'remote_defaultExpDays', '3', '3'],
1345
-				]);
1346
-		}
1347
-
1348
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1349
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1350
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1351
-			return $data['expirationDate'] == $expected;
1352
-		}));
1353
-
1354
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1355
-
1356
-		$this->assertEquals($expected, $share->getExpirationDate());
1357
-	}
1358
-
1359
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1360
-	public function testValidateExpirationDateInternalDefault($shareType): void {
1361
-		$future = new \DateTime('now', $this->timezone);
1362
-		$future->add(new \DateInterval('P5D'));
1363
-		$future->setTime(1, 2, 3);
1364
-
1365
-		$expected = clone $future;
1366
-		$expected->setTime(0, 0);
1367
-
1368
-		$share = $this->manager->newShare();
1369
-		$share->setShareType($shareType);
1370
-		$share->setExpirationDate($future);
1371
-
1372
-		if ($shareType === IShare::TYPE_USER) {
1373
-			$this->config->method('getAppValue')
1374
-				->willReturnMap([
1375
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1376
-					['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1377
-					['core', 'internal_defaultExpDays', '3', '1'],
1378
-				]);
1379
-		} else {
1380
-			$this->config->method('getAppValue')
1381
-				->willReturnMap([
1382
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1383
-					['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1384
-					['core', 'remote_defaultExpDays', '3', '1'],
1385
-				]);
1386
-		}
1387
-
1388
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1389
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1390
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1391
-			return $data['expirationDate'] == $expected;
1392
-		}));
1393
-
1394
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1395
-
1396
-		$this->assertEquals($expected, $share->getExpirationDate());
1397
-	}
1398
-
1399
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1400
-	public function testValidateExpirationDateInternalHookModification($shareType): void {
1401
-		$nextWeek = new \DateTime('now', $this->timezone);
1402
-		$nextWeek->add(new \DateInterval('P7D'));
1403
-		$nextWeek->setTime(0, 0, 0);
1404
-
1405
-		$save = clone $nextWeek;
1406
-
1407
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1408
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1409
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1410
-			$data['expirationDate']->sub(new \DateInterval('P2D'));
1411
-		});
1412
-
1413
-		$share = $this->manager->newShare();
1414
-		$share->setShareType($shareType);
1415
-		$share->setExpirationDate($nextWeek);
1416
-
1417
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1418
-
1419
-		$save->sub(new \DateInterval('P2D'));
1420
-		$this->assertEquals($save, $share->getExpirationDate());
1421
-	}
1422
-
1423
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1424
-	public function testValidateExpirationDateInternalHookException($shareType): void {
1425
-		$this->expectException(\Exception::class);
1426
-		$this->expectExceptionMessage('Invalid date!');
1427
-
1428
-		$nextWeek = new \DateTime();
1429
-		$nextWeek->add(new \DateInterval('P7D'));
1430
-		$nextWeek->setTime(0, 0, 0);
1431
-
1432
-		$share = $this->manager->newShare();
1433
-		$share->setShareType($shareType);
1434
-		$share->setExpirationDate($nextWeek);
1435
-
1436
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1437
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1438
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1439
-			$data['accepted'] = false;
1440
-			$data['message'] = 'Invalid date!';
1441
-		});
1442
-
1443
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1444
-	}
1445
-
1446
-	#[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1447
-	public function testValidateExpirationDateInternalExistingShareNoDefault($shareType): void {
1448
-		$share = $this->manager->newShare();
1449
-		$share->setShareType($shareType);
1450
-		$share->setId('42')->setProviderId('foo');
1451
-
1452
-		if ($shareType === IShare::TYPE_USER) {
1453
-			$this->config->method('getAppValue')
1454
-				->willReturnMap([
1455
-					['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1456
-					['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
1457
-				]);
1458
-		} else {
1459
-			$this->config->method('getAppValue')
1460
-				->willReturnMap([
1461
-					['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1462
-					['core', 'shareapi_remote_expire_after_n_days', '7', '6'],
1463
-				]);
1464
-		}
1465
-
1466
-		self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1467
-
1468
-		$this->assertEquals(null, $share->getExpirationDate());
1469
-	}
1470
-
1471
-	public function testValidateExpirationDateInPast(): void {
1472
-		$this->expectException(GenericShareException::class);
1473
-		$this->expectExceptionMessage('Expiration date is in the past');
1474
-
1475
-		// Expire date in the past
1476
-		$past = new \DateTime();
1477
-		$past->sub(new \DateInterval('P1D'));
1478
-
1479
-		$share = $this->manager->newShare();
1480
-		$share->setExpirationDate($past);
1481
-
1482
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1483
-	}
1484
-
1485
-	public function testValidateExpirationDateEnforceButNotSet(): void {
1486
-		$this->expectException(\InvalidArgumentException::class);
1487
-		$this->expectExceptionMessage('Expiration date is enforced');
1488
-
1489
-		$share = $this->manager->newShare();
1490
-		$share->setProviderId('foo')->setId('bar');
1491
-
1492
-		$this->config->method('getAppValue')
1493
-			->willReturnMap([
1494
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1495
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1496
-			]);
1497
-
1498
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1499
-	}
1500
-
1501
-	public function testValidateExpirationDateEnforceButNotEnabledAndNotSet(): void {
1502
-		$share = $this->manager->newShare();
1503
-		$share->setProviderId('foo')->setId('bar');
1504
-
1505
-		$this->config->method('getAppValue')
1506
-			->willReturnMap([
1507
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1508
-			]);
1509
-
1510
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1511
-
1512
-		$this->assertNull($share->getExpirationDate());
1513
-	}
1514
-
1515
-	public function testValidateExpirationDateEnforceButNotSetNewShare(): void {
1516
-		$share = $this->manager->newShare();
1517
-
1518
-		$this->config->method('getAppValue')
1519
-			->willReturnMap([
1520
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1521
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1522
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1523
-				['core', 'link_defaultExpDays', '3', '3'],
1524
-			]);
1525
-
1526
-		$expected = new \DateTime('now', $this->timezone);
1527
-		$expected->setTime(0, 0, 0);
1528
-		$expected->add(new \DateInterval('P3D'));
1529
-
1530
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1531
-
1532
-		$this->assertNotNull($share->getExpirationDate());
1533
-		$this->assertEquals($expected, $share->getExpirationDate());
1534
-	}
1535
-
1536
-	public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare(): void {
1537
-		$share = $this->manager->newShare();
1538
-
1539
-		$this->config->method('getAppValue')
1540
-			->willReturnMap([
1541
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1542
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1543
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1544
-				['core', 'link_defaultExpDays', '3', '1'],
1545
-			]);
1546
-
1547
-		$expected = new \DateTime('now', $this->timezone);
1548
-		$expected->setTime(0, 0, 0);
1549
-		$expected->add(new \DateInterval('P1D'));
1550
-
1551
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1552
-
1553
-		$this->assertNotNull($share->getExpirationDate());
1554
-		$this->assertEquals($expected, $share->getExpirationDate());
1555
-	}
1556
-
1557
-	public function testValidateExpirationDateEnforceTooFarIntoFuture(): void {
1558
-		$this->expectException(GenericShareException::class);
1559
-		$this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
80
+    /** @var Manager */
81
+    protected $manager;
82
+    /** @var LoggerInterface|MockObject */
83
+    protected $logger;
84
+    /** @var IConfig|MockObject */
85
+    protected $config;
86
+    /** @var ISecureRandom|MockObject */
87
+    protected $secureRandom;
88
+    /** @var IHasher|MockObject */
89
+    protected $hasher;
90
+    /** @var IShareProvider|MockObject */
91
+    protected $defaultProvider;
92
+    /** @var IMountManager|MockObject */
93
+    protected $mountManager;
94
+    /** @var IGroupManager|MockObject */
95
+    protected $groupManager;
96
+    /** @var IL10N|MockObject */
97
+    protected $l;
98
+    /** @var IFactory|MockObject */
99
+    protected $l10nFactory;
100
+    /** @var DummyFactory */
101
+    protected $factory;
102
+    /** @var IUserManager|MockObject */
103
+    protected $userManager;
104
+    /** @var IRootFolder | MockObject */
105
+    protected $rootFolder;
106
+    /** @var IEventDispatcher|MockObject */
107
+    protected $dispatcher;
108
+    /** @var IMailer|MockObject */
109
+    protected $mailer;
110
+    /** @var IURLGenerator|MockObject */
111
+    protected $urlGenerator;
112
+    /** @var \OC_Defaults|MockObject */
113
+    protected $defaults;
114
+    /** @var IUserSession|MockObject */
115
+    protected $userSession;
116
+    /** @var KnownUserService|MockObject */
117
+    protected $knownUserService;
118
+    /** @var ShareDisableChecker|MockObject */
119
+    protected $shareDisabledChecker;
120
+    private DateTimeZone $timezone;
121
+    /** @var IDateTimeZone|MockObject */
122
+    protected $dateTimeZone;
123
+    /** @var IAppConfig|MockObject */
124
+    protected $appConfig;
125
+
126
+    protected function setUp(): void {
127
+        $this->logger = $this->createMock(LoggerInterface::class);
128
+        $this->config = $this->createMock(IConfig::class);
129
+        $this->secureRandom = $this->createMock(ISecureRandom::class);
130
+        $this->hasher = $this->createMock(IHasher::class);
131
+        $this->mountManager = $this->createMock(IMountManager::class);
132
+        $this->groupManager = $this->createMock(IGroupManager::class);
133
+        $this->userManager = $this->createMock(IUserManager::class);
134
+        $this->rootFolder = $this->createMock(IRootFolder::class);
135
+        $this->mailer = $this->createMock(IMailer::class);
136
+        $this->urlGenerator = $this->createMock(IURLGenerator::class);
137
+        $this->defaults = $this->createMock(\OC_Defaults::class);
138
+        $this->dispatcher = $this->createMock(IEventDispatcher::class);
139
+        $this->userSession = $this->createMock(IUserSession::class);
140
+        $this->knownUserService = $this->createMock(KnownUserService::class);
141
+
142
+        $this->shareDisabledChecker = new ShareDisableChecker($this->config, $this->userManager, $this->groupManager);
143
+        $this->dateTimeZone = $this->createMock(IDateTimeZone::class);
144
+        $this->timezone = new \DateTimeZone('Pacific/Auckland');
145
+        $this->dateTimeZone->method('getTimeZone')->willReturnCallback(fn () => $this->timezone);
146
+
147
+        $this->appConfig = $this->createMock(IAppConfig::class);
148
+
149
+        $this->l10nFactory = $this->createMock(IFactory::class);
150
+        $this->l = $this->createMock(IL10N::class);
151
+        $this->l->method('t')
152
+            ->willReturnCallback(function ($text, $parameters = []) {
153
+                return vsprintf($text, $parameters);
154
+            });
155
+        $this->l->method('n')
156
+            ->willReturnCallback(function ($singular, $plural, $count, $parameters = []) {
157
+                return vsprintf(str_replace('%n', $count, ($count === 1) ? $singular : $plural), $parameters);
158
+            });
159
+        $this->l10nFactory->method('get')->willReturn($this->l);
160
+
161
+        $this->factory = new DummyFactory(\OC::$server);
162
+
163
+        $this->manager = $this->createManager($this->factory);
164
+
165
+        $this->defaultProvider = $this->createMock(DefaultShareProvider::class);
166
+        $this->defaultProvider->method('identifier')->willReturn('default');
167
+        $this->factory->setProvider($this->defaultProvider);
168
+    }
169
+
170
+    private function createManager(IProviderFactory $factory): Manager {
171
+        return new Manager(
172
+            $this->logger,
173
+            $this->config,
174
+            $this->secureRandom,
175
+            $this->hasher,
176
+            $this->mountManager,
177
+            $this->groupManager,
178
+            $this->l10nFactory,
179
+            $factory,
180
+            $this->userManager,
181
+            $this->rootFolder,
182
+            $this->mailer,
183
+            $this->urlGenerator,
184
+            $this->defaults,
185
+            $this->dispatcher,
186
+            $this->userSession,
187
+            $this->knownUserService,
188
+            $this->shareDisabledChecker,
189
+            $this->dateTimeZone,
190
+            $this->appConfig,
191
+        );
192
+    }
193
+
194
+    /**
195
+     * @return MockBuilder
196
+     */
197
+    private function createManagerMock() {
198
+        return $this->getMockBuilder(Manager::class)
199
+            ->setConstructorArgs([
200
+                $this->logger,
201
+                $this->config,
202
+                $this->secureRandom,
203
+                $this->hasher,
204
+                $this->mountManager,
205
+                $this->groupManager,
206
+                $this->l10nFactory,
207
+                $this->factory,
208
+                $this->userManager,
209
+                $this->rootFolder,
210
+                $this->mailer,
211
+                $this->urlGenerator,
212
+                $this->defaults,
213
+                $this->dispatcher,
214
+                $this->userSession,
215
+                $this->knownUserService,
216
+                $this->shareDisabledChecker,
217
+                $this->dateTimeZone,
218
+                $this->appConfig,
219
+            ]);
220
+    }
221
+
222
+    private function createFolderMock(string $folderPath): MockObject&Folder {
223
+        $folder = $this->createMock(Folder::class);
224
+        $folder->method('getPath')->willReturn($folderPath);
225
+        $folder->method('getRelativePath')->willReturnCallback(
226
+            fn (string $path): ?string => PathHelper::getRelativePath($folderPath, $path)
227
+        );
228
+        return $folder;
229
+    }
230
+
231
+    public function testDeleteNoShareId(): void {
232
+        $this->expectException(\InvalidArgumentException::class);
233
+
234
+        $share = $this->manager->newShare();
235
+
236
+        $this->manager->deleteShare($share);
237
+    }
238
+
239
+    public static function dataTestDelete(): array {
240
+        return [
241
+            [IShare::TYPE_USER, 'sharedWithUser'],
242
+            [IShare::TYPE_GROUP, 'sharedWithGroup'],
243
+            [IShare::TYPE_LINK, ''],
244
+            [IShare::TYPE_REMOTE, '[email protected]'],
245
+        ];
246
+    }
247
+
248
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestDelete')]
249
+    public function testDelete($shareType, $sharedWith): void {
250
+        $manager = $this->createManagerMock()
251
+            ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
252
+            ->getMock();
253
+
254
+        $manager->method('deleteChildren')->willReturn([]);
255
+
256
+        $path = $this->createMock(File::class);
257
+        $path->method('getId')->willReturn(1);
258
+
259
+        $share = $this->manager->newShare();
260
+        $share->setId(42)
261
+            ->setProviderId('prov')
262
+            ->setShareType($shareType)
263
+            ->setSharedWith($sharedWith)
264
+            ->setSharedBy('sharedBy')
265
+            ->setNode($path)
266
+            ->setTarget('myTarget');
267
+
268
+        $manager->expects($this->once())->method('deleteChildren')->with($share);
269
+        $manager->expects($this->once())->method('promoteReshares')->with($share);
270
+
271
+        $this->defaultProvider
272
+            ->expects($this->once())
273
+            ->method('delete')
274
+            ->with($share);
275
+
276
+        $calls = [
277
+            BeforeShareDeletedEvent::class,
278
+            ShareDeletedEvent::class,
279
+        ];
280
+        $this->dispatcher->expects($this->exactly(2))
281
+            ->method('dispatchTyped')
282
+            ->willReturnCallback(function ($event) use (&$calls, $share): void {
283
+                $expected = array_shift($calls);
284
+                $this->assertInstanceOf($expected, $event);
285
+                $this->assertEquals($share, $event->getShare());
286
+            });
287
+
288
+        $manager->deleteShare($share);
289
+    }
290
+
291
+    public function testDeleteLazyShare(): void {
292
+        $manager = $this->createManagerMock()
293
+            ->onlyMethods(['getShareById', 'deleteChildren', 'promoteReshares'])
294
+            ->getMock();
295
+
296
+        $manager->method('deleteChildren')->willReturn([]);
297
+
298
+        $share = $this->manager->newShare();
299
+        $share->setId(42)
300
+            ->setProviderId('prov')
301
+            ->setShareType(IShare::TYPE_USER)
302
+            ->setSharedWith('sharedWith')
303
+            ->setSharedBy('sharedBy')
304
+            ->setShareOwner('shareOwner')
305
+            ->setTarget('myTarget')
306
+            ->setNodeId(1)
307
+            ->setNodeType('file');
308
+
309
+        $this->rootFolder->expects($this->never())->method($this->anything());
310
+
311
+        $manager->expects($this->once())->method('deleteChildren')->with($share);
312
+        $manager->expects($this->once())->method('promoteReshares')->with($share);
313
+
314
+        $this->defaultProvider
315
+            ->expects($this->once())
316
+            ->method('delete')
317
+            ->with($share);
318
+
319
+        $calls = [
320
+            BeforeShareDeletedEvent::class,
321
+            ShareDeletedEvent::class,
322
+        ];
323
+        $this->dispatcher->expects($this->exactly(2))
324
+            ->method('dispatchTyped')
325
+            ->willReturnCallback(function ($event) use (&$calls, $share): void {
326
+                $expected = array_shift($calls);
327
+                $this->assertInstanceOf($expected, $event);
328
+                $this->assertEquals($share, $event->getShare());
329
+            });
330
+
331
+        $manager->deleteShare($share);
332
+    }
333
+
334
+    public function testDeleteNested(): void {
335
+        $manager = $this->createManagerMock()
336
+            ->onlyMethods(['getShareById', 'promoteReshares'])
337
+            ->getMock();
338
+
339
+        $path = $this->createMock(File::class);
340
+        $path->method('getId')->willReturn(1);
341
+
342
+        $share1 = $this->manager->newShare();
343
+        $share1->setId(42)
344
+            ->setProviderId('prov')
345
+            ->setShareType(IShare::TYPE_USER)
346
+            ->setSharedWith('sharedWith1')
347
+            ->setSharedBy('sharedBy1')
348
+            ->setNode($path)
349
+            ->setTarget('myTarget1');
350
+
351
+        $share2 = $this->manager->newShare();
352
+        $share2->setId(43)
353
+            ->setProviderId('prov')
354
+            ->setShareType(IShare::TYPE_GROUP)
355
+            ->setSharedWith('sharedWith2')
356
+            ->setSharedBy('sharedBy2')
357
+            ->setNode($path)
358
+            ->setTarget('myTarget2')
359
+            ->setParent(42);
360
+
361
+        $share3 = $this->manager->newShare();
362
+        $share3->setId(44)
363
+            ->setProviderId('prov')
364
+            ->setShareType(IShare::TYPE_LINK)
365
+            ->setSharedBy('sharedBy3')
366
+            ->setNode($path)
367
+            ->setTarget('myTarget3')
368
+            ->setParent(43);
369
+
370
+        $this->defaultProvider
371
+            ->method('getChildren')
372
+            ->willReturnMap([
373
+                [$share1, [$share2]],
374
+                [$share2, [$share3]],
375
+                [$share3, []],
376
+            ]);
377
+
378
+        $deleteCalls = [
379
+            $share3,
380
+            $share2,
381
+            $share1,
382
+        ];
383
+        $this->defaultProvider->expects($this->exactly(3))
384
+            ->method('delete')
385
+            ->willReturnCallback(function ($share) use (&$deleteCalls): void {
386
+                $expected = array_shift($deleteCalls);
387
+                $this->assertEquals($expected, $share);
388
+            });
389
+
390
+        $dispatchCalls = [
391
+            [BeforeShareDeletedEvent::class, $share1],
392
+            [BeforeShareDeletedEvent::class, $share2],
393
+            [BeforeShareDeletedEvent::class, $share3],
394
+            [ShareDeletedEvent::class, $share3],
395
+            [ShareDeletedEvent::class, $share2],
396
+            [ShareDeletedEvent::class, $share1],
397
+        ];
398
+        $this->dispatcher->expects($this->exactly(6))
399
+            ->method('dispatchTyped')
400
+            ->willReturnCallback(function ($event) use (&$dispatchCalls): void {
401
+                $expected = array_shift($dispatchCalls);
402
+                $this->assertInstanceOf($expected[0], $event);
403
+                $this->assertEquals($expected[1]->getId(), $event->getShare()->getId());
404
+            });
405
+
406
+        $manager->deleteShare($share1);
407
+    }
408
+
409
+    public function testDeleteFromSelf(): void {
410
+        $manager = $this->createManagerMock()
411
+            ->onlyMethods(['getShareById'])
412
+            ->getMock();
413
+
414
+        $recipientId = 'unshareFrom';
415
+        $share = $this->manager->newShare();
416
+        $share->setId(42)
417
+            ->setProviderId('prov')
418
+            ->setShareType(IShare::TYPE_USER)
419
+            ->setSharedWith('sharedWith')
420
+            ->setSharedBy('sharedBy')
421
+            ->setShareOwner('shareOwner')
422
+            ->setTarget('myTarget')
423
+            ->setNodeId(1)
424
+            ->setNodeType('file');
425
+
426
+        $this->defaultProvider
427
+            ->expects($this->once())
428
+            ->method('deleteFromSelf')
429
+            ->with($share, $recipientId);
430
+
431
+        $this->dispatcher->expects($this->once())
432
+            ->method('dispatchTyped')
433
+            ->with(
434
+                $this->callBack(function (ShareDeletedFromSelfEvent $e) use ($share) {
435
+                    return $e->getShare() === $share;
436
+                })
437
+            );
438
+
439
+        $manager->deleteFromSelf($share, $recipientId);
440
+    }
441
+
442
+    public function testDeleteChildren(): void {
443
+        $manager = $this->createManagerMock()
444
+            ->onlyMethods(['deleteShare'])
445
+            ->getMock();
446
+
447
+        $share = $this->createMock(IShare::class);
448
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
449
+
450
+        $child1 = $this->createMock(IShare::class);
451
+        $child1->method('getShareType')->willReturn(IShare::TYPE_USER);
452
+        $child2 = $this->createMock(IShare::class);
453
+        $child2->method('getShareType')->willReturn(IShare::TYPE_USER);
454
+        $child3 = $this->createMock(IShare::class);
455
+        $child3->method('getShareType')->willReturn(IShare::TYPE_USER);
456
+
457
+        $shares = [
458
+            $child1,
459
+            $child2,
460
+            $child3,
461
+        ];
462
+
463
+        $this->defaultProvider
464
+            ->expects($this->exactly(4))
465
+            ->method('getChildren')
466
+            ->willReturnCallback(function ($_share) use ($share, $shares) {
467
+                if ($_share === $share) {
468
+                    return $shares;
469
+                }
470
+                return [];
471
+            });
472
+
473
+        $calls = [
474
+            $child1,
475
+            $child2,
476
+            $child3,
477
+        ];
478
+        $this->defaultProvider->expects($this->exactly(3))
479
+            ->method('delete')
480
+            ->willReturnCallback(function ($share) use (&$calls): void {
481
+                $expected = array_shift($calls);
482
+                $this->assertEquals($expected, $share);
483
+            });
484
+
485
+        $result = self::invokePrivate($manager, 'deleteChildren', [$share]);
486
+        $this->assertSame($shares, $result);
487
+    }
488
+
489
+    public function testPromoteReshareFile(): void {
490
+        $manager = $this->createManagerMock()
491
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
492
+            ->getMock();
493
+
494
+        $file = $this->createMock(File::class);
495
+
496
+        $share = $this->createMock(IShare::class);
497
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
498
+        $share->method('getNodeType')->willReturn('folder');
499
+        $share->method('getSharedWith')->willReturn('userB');
500
+        $share->method('getNode')->willReturn($file);
501
+
502
+        $reShare = $this->createMock(IShare::class);
503
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
504
+        $reShare->method('getSharedBy')->willReturn('userB');
505
+        $reShare->method('getSharedWith')->willReturn('userC');
506
+        $reShare->method('getNode')->willReturn($file);
507
+
508
+        $this->defaultProvider->method('getSharesBy')
509
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $file) {
510
+                $this->assertEquals($file, $node);
511
+                if ($shareType === IShare::TYPE_USER) {
512
+                    return match($userId) {
513
+                        'userB' => [$reShare],
514
+                    };
515
+                } else {
516
+                    return [];
517
+                }
518
+            });
519
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
520
+
521
+        $manager->expects($this->exactly(1))->method('updateShare')->with($reShare);
522
+
523
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
524
+    }
525
+
526
+    public function testPromoteReshare(): void {
527
+        $manager = $this->createManagerMock()
528
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'generalCreateChecks'])
529
+            ->getMock();
530
+
531
+        $folder = $this->createFolderMock('/path/to/folder');
532
+
533
+        $subFolder = $this->createFolderMock('/path/to/folder/sub');
534
+
535
+        $otherFolder = $this->createFolderMock('/path/to/otherfolder/');
536
+
537
+        $share = $this->createMock(IShare::class);
538
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
539
+        $share->method('getNodeType')->willReturn('folder');
540
+        $share->method('getSharedWith')->willReturn('userB');
541
+        $share->method('getNode')->willReturn($folder);
542
+
543
+        $reShare = $this->createMock(IShare::class);
544
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
545
+        $reShare->method('getSharedBy')->willReturn('userB');
546
+        $reShare->method('getSharedWith')->willReturn('userC');
547
+        $reShare->method('getNode')->willReturn($folder);
548
+
549
+        $reShareInSubFolder = $this->createMock(IShare::class);
550
+        $reShareInSubFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
551
+        $reShareInSubFolder->method('getSharedBy')->willReturn('userB');
552
+        $reShareInSubFolder->method('getNode')->willReturn($subFolder);
553
+
554
+        $reShareInOtherFolder = $this->createMock(IShare::class);
555
+        $reShareInOtherFolder->method('getShareType')->willReturn(IShare::TYPE_USER);
556
+        $reShareInOtherFolder->method('getSharedBy')->willReturn('userB');
557
+        $reShareInOtherFolder->method('getNode')->willReturn($otherFolder);
558
+
559
+        $this->defaultProvider->method('getSharesBy')
560
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare, $reShareInSubFolder, $reShareInOtherFolder) {
561
+                if ($shareType === IShare::TYPE_USER) {
562
+                    return match($userId) {
563
+                        'userB' => [$reShare,$reShareInSubFolder,$reShareInOtherFolder],
564
+                    };
565
+                } else {
566
+                    return [];
567
+                }
568
+            });
569
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
570
+
571
+        $calls = [
572
+            $reShare,
573
+            $reShareInSubFolder,
574
+        ];
575
+        $manager->expects($this->exactly(2))
576
+            ->method('updateShare')
577
+            ->willReturnCallback(function ($share) use (&$calls): void {
578
+                $expected = array_shift($calls);
579
+                $this->assertEquals($expected, $share);
580
+            });
581
+
582
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
583
+    }
584
+
585
+    public function testPromoteReshareWhenUserHasAnotherShare(): void {
586
+        $manager = $this->createManagerMock()
587
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
588
+            ->getMock();
589
+
590
+        $folder = $this->createFolderMock('/path/to/folder');
591
+
592
+        $share = $this->createMock(IShare::class);
593
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
594
+        $share->method('getNodeType')->willReturn('folder');
595
+        $share->method('getSharedWith')->willReturn('userB');
596
+        $share->method('getNode')->willReturn($folder);
597
+
598
+        $reShare = $this->createMock(IShare::class);
599
+        $reShare->method('getShareType')->willReturn(IShare::TYPE_USER);
600
+        $reShare->method('getNodeType')->willReturn('folder');
601
+        $reShare->method('getSharedBy')->willReturn('userB');
602
+        $reShare->method('getNode')->willReturn($folder);
603
+
604
+        $this->defaultProvider->method('getSharesBy')->willReturn([$reShare]);
605
+        $manager->method('generalCreateChecks')->willReturn(true);
606
+
607
+        /* No share is promoted because generalCreateChecks does not throw */
608
+        $manager->expects($this->never())->method('updateShare');
609
+
610
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
611
+    }
612
+
613
+    public function testPromoteReshareOfUsersInGroupShare(): void {
614
+        $manager = $this->createManagerMock()
615
+            ->onlyMethods(['updateShare', 'getSharesInFolder', 'getSharedWith', 'generalCreateChecks'])
616
+            ->getMock();
617
+
618
+        $folder = $this->createFolderMock('/path/to/folder');
619
+
620
+        $userA = $this->createMock(IUser::class);
621
+        $userA->method('getUID')->willReturn('userA');
622
+
623
+        $share = $this->createMock(IShare::class);
624
+        $share->method('getShareType')->willReturn(IShare::TYPE_GROUP);
625
+        $share->method('getNodeType')->willReturn('folder');
626
+        $share->method('getSharedWith')->willReturn('Group');
627
+        $share->method('getNode')->willReturn($folder);
628
+        $share->method('getShareOwner')->willReturn($userA);
629
+
630
+        $reShare1 = $this->createMock(IShare::class);
631
+        $reShare1->method('getShareType')->willReturn(IShare::TYPE_USER);
632
+        $reShare1->method('getNodeType')->willReturn('folder');
633
+        $reShare1->method('getSharedBy')->willReturn('userB');
634
+        $reShare1->method('getNode')->willReturn($folder);
635
+
636
+        $reShare2 = $this->createMock(IShare::class);
637
+        $reShare2->method('getShareType')->willReturn(IShare::TYPE_USER);
638
+        $reShare2->method('getNodeType')->willReturn('folder');
639
+        $reShare2->method('getSharedBy')->willReturn('userC');
640
+        $reShare2->method('getNode')->willReturn($folder);
641
+
642
+        $userB = $this->createMock(IUser::class);
643
+        $userB->method('getUID')->willReturn('userB');
644
+        $userC = $this->createMock(IUser::class);
645
+        $userC->method('getUID')->willReturn('userC');
646
+        $group = $this->createMock(IGroup::class);
647
+        $group->method('getUsers')->willReturn([$userB, $userC]);
648
+        $this->groupManager->method('get')->with('Group')->willReturn($group);
649
+
650
+        $this->defaultProvider->method('getSharesBy')
651
+            ->willReturnCallback(function ($userId, $shareType, $node, $reshares, $limit, $offset) use ($reShare1, $reShare2) {
652
+                if ($shareType === IShare::TYPE_USER) {
653
+                    return match($userId) {
654
+                        'userB' => [$reShare1],
655
+                        'userC' => [$reShare2],
656
+                    };
657
+                } else {
658
+                    return [];
659
+                }
660
+            });
661
+        $manager->method('generalCreateChecks')->willThrowException(new GenericShareException());
662
+
663
+        $manager->method('getSharedWith')->willReturn([]);
664
+
665
+        $calls = [
666
+            $reShare1,
667
+            $reShare2,
668
+        ];
669
+        $manager->expects($this->exactly(2))
670
+            ->method('updateShare')
671
+            ->willReturnCallback(function ($share) use (&$calls): void {
672
+                $expected = array_shift($calls);
673
+                $this->assertEquals($expected, $share);
674
+            });
675
+
676
+        self::invokePrivate($manager, 'promoteReshares', [$share]);
677
+    }
678
+
679
+    public function testGetShareById(): void {
680
+        $share = $this->createMock(IShare::class);
681
+
682
+        $this->defaultProvider
683
+            ->expects($this->once())
684
+            ->method('getShareById')
685
+            ->with(42)
686
+            ->willReturn($share);
687
+
688
+        $this->assertEquals($share, $this->manager->getShareById('default:42'));
689
+    }
690
+
691
+
692
+    public function testGetExpiredShareById(): void {
693
+        $this->expectException(ShareNotFound::class);
694
+
695
+        $manager = $this->createManagerMock()
696
+            ->onlyMethods(['deleteShare'])
697
+            ->getMock();
698
+
699
+        $date = new \DateTime();
700
+        $date->setTime(0, 0, 0);
701
+
702
+        $share = $this->manager->newShare();
703
+        $share->setExpirationDate($date)
704
+            ->setShareType(IShare::TYPE_LINK);
705
+
706
+        $this->defaultProvider->expects($this->once())
707
+            ->method('getShareById')
708
+            ->with('42')
709
+            ->willReturn($share);
710
+
711
+        $manager->expects($this->once())
712
+            ->method('deleteShare')
713
+            ->with($share);
714
+
715
+        $manager->getShareById('default:42');
716
+    }
717
+
718
+
719
+    public function testVerifyPasswordNullButEnforced(): void {
720
+        $this->expectException(\InvalidArgumentException::class);
721
+        $this->expectExceptionMessage('Passwords are enforced for link and mail shares');
722
+
723
+        $this->config->method('getAppValue')->willReturnMap([
724
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
725
+        ]);
726
+
727
+        $this->appConfig->method('getValueBool')->willReturnMap([
728
+            ['core', 'shareapi_enforce_links_password', true],
729
+        ]);
730
+
731
+        self::invokePrivate($this->manager, 'verifyPassword', [null]);
732
+    }
733
+
734
+    public function testVerifyPasswordNotEnforcedGroup(): void {
735
+        $this->config->method('getAppValue')->willReturnMap([
736
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin"]'],
737
+            ['core', 'shareapi_enforce_links_password', 'no', 'yes'],
738
+        ]);
739
+
740
+        // Create admin user
741
+        $user = $this->createMock(IUser::class);
742
+        $this->userSession->method('getUser')->willReturn($user);
743
+        $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['admin']);
744
+
745
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
746
+        $this->assertNull($result);
747
+    }
748
+
749
+    public function testVerifyPasswordNotEnforcedMultipleGroups(): void {
750
+        $this->config->method('getAppValue')->willReturnMap([
751
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', '["admin", "special"]'],
752
+            ['core', 'shareapi_enforce_links_password', 'no', 'yes'],
753
+        ]);
754
+
755
+        // Create admin user
756
+        $user = $this->createMock(IUser::class);
757
+        $this->userSession->method('getUser')->willReturn($user);
758
+        $this->groupManager->method('getUserGroupIds')->with($user)->willReturn(['special']);
759
+
760
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
761
+        $this->assertNull($result);
762
+    }
763
+
764
+    public function testVerifyPasswordNull(): void {
765
+        $this->config->method('getAppValue')->willReturnMap([
766
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
767
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
768
+        ]);
769
+
770
+        $result = self::invokePrivate($this->manager, 'verifyPassword', [null]);
771
+        $this->assertNull($result);
772
+    }
773
+
774
+    public function testVerifyPasswordHook(): void {
775
+        $this->config->method('getAppValue')->willReturnMap([
776
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
777
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
778
+        ]);
779
+
780
+        $this->dispatcher->expects($this->once())->method('dispatchTyped')
781
+            ->willReturnCallback(function (Event $event): void {
782
+                $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
783
+                /** @var ValidatePasswordPolicyEvent $event */
784
+                $this->assertSame('password', $event->getPassword());
785
+            }
786
+            );
787
+
788
+        $result = self::invokePrivate($this->manager, 'verifyPassword', ['password']);
789
+        $this->assertNull($result);
790
+    }
791
+
792
+
793
+    public function testVerifyPasswordHookFails(): void {
794
+        $this->expectException(\Exception::class);
795
+        $this->expectExceptionMessage('password not accepted');
796
+
797
+        $this->config->method('getAppValue')->willReturnMap([
798
+            ['core', 'shareapi_enforce_links_password_excluded_groups', '', ''],
799
+            ['core', 'shareapi_enforce_links_password', 'no', 'no'],
800
+        ]);
801
+
802
+        $this->dispatcher->expects($this->once())->method('dispatchTyped')
803
+            ->willReturnCallback(function (Event $event): void {
804
+                $this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event);
805
+                /** @var ValidatePasswordPolicyEvent $event */
806
+                $this->assertSame('password', $event->getPassword());
807
+                throw new HintException('password not accepted');
808
+            }
809
+            );
810
+
811
+        self::invokePrivate($this->manager, 'verifyPassword', ['password']);
812
+    }
813
+
814
+    public function createShare($id, $type, $node, $sharedWith, $sharedBy, $shareOwner,
815
+        $permissions, $expireDate = null, $password = null, $attributes = null) {
816
+        $share = $this->createMock(IShare::class);
817
+
818
+        $share->method('getShareType')->willReturn($type);
819
+        $share->method('getSharedWith')->willReturn($sharedWith);
820
+        $share->method('getSharedBy')->willReturn($sharedBy);
821
+        $share->method('getShareOwner')->willReturn($shareOwner);
822
+        $share->method('getNode')->willReturn($node);
823
+        if ($node && $node->getId()) {
824
+            $share->method('getNodeId')->willReturn($node->getId());
825
+        }
826
+        $share->method('getPermissions')->willReturn($permissions);
827
+        $share->method('getAttributes')->willReturn($attributes);
828
+        $share->method('getExpirationDate')->willReturn($expireDate);
829
+        $share->method('getPassword')->willReturn($password);
830
+
831
+        return $share;
832
+    }
833
+
834
+    public function dataGeneralChecks() {
835
+        $user0 = 'user0';
836
+        $user2 = 'user1';
837
+        $group0 = 'group0';
838
+        $owner = $this->createMock(IUser::class);
839
+        $owner->method('getUID')
840
+            ->willReturn($user0);
841
+
842
+        $file = $this->createMock(File::class);
843
+        $node = $this->createMock(Node::class);
844
+        $storage = $this->createMock(IStorage::class);
845
+        $storage->method('instanceOfStorage')
846
+            ->with('\OCA\Files_Sharing\External\Storage')
847
+            ->willReturn(false);
848
+        $file->method('getStorage')
849
+            ->willReturn($storage);
850
+        $file->method('getId')->willReturn(108);
851
+        $node->method('getStorage')
852
+            ->willReturn($storage);
853
+        $node->method('getId')->willReturn(108);
854
+
855
+        $data = [
856
+            [$this->createShare(null, IShare::TYPE_USER, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
857
+            [$this->createShare(null, IShare::TYPE_USER, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
858
+            [$this->createShare(null, IShare::TYPE_USER, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient is not a valid user', true],
859
+            [$this->createShare(null, IShare::TYPE_GROUP, $file, null, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
860
+            [$this->createShare(null, IShare::TYPE_GROUP, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
861
+            [$this->createShare(null, IShare::TYPE_GROUP, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient is not a valid group', true],
862
+            [$this->createShare(null, IShare::TYPE_LINK, $file, $user2, $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
863
+            [$this->createShare(null, IShare::TYPE_LINK, $file, $group0, $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
864
+            [$this->createShare(null, IShare::TYPE_LINK, $file, '[email protected]', $user0, $user0, 31, null, null), 'Share recipient should be empty', true],
865
+            [$this->createShare(null, -1, $file, null, $user0, $user0, 31, null, null), 'Unknown share type', true],
866
+
867
+            [$this->createShare(null, IShare::TYPE_USER, $file, $user2, null, $user0, 31, null, null), 'Share initiator must be set', true],
868
+            [$this->createShare(null, IShare::TYPE_GROUP, $file, $group0, null, $user0, 31, null, null), 'Share initiator must be set', true],
869
+            [$this->createShare(null, IShare::TYPE_LINK, $file, null, null, $user0, 31, null, null), 'Share initiator must be set', true],
870
+
871
+            [$this->createShare(null, IShare::TYPE_USER, $file, $user0, $user0, $user0, 31, null, null), 'Cannot share with yourself', true],
872
+
873
+            [$this->createShare(null, IShare::TYPE_USER, null, $user2, $user0, $user0, 31, null, null), 'Shared path must be set', true],
874
+            [$this->createShare(null, IShare::TYPE_GROUP, null, $group0, $user0, $user0, 31, null, null), 'Shared path must be set', true],
875
+            [$this->createShare(null, IShare::TYPE_LINK, null, null, $user0, $user0, 31, null, null), 'Shared path must be set', true],
876
+
877
+            [$this->createShare(null, IShare::TYPE_USER, $node, $user2, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
878
+            [$this->createShare(null, IShare::TYPE_GROUP, $node, $group0, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
879
+            [$this->createShare(null, IShare::TYPE_LINK, $node, null, $user0, $user0, 31, null, null), 'Shared path must be either a file or a folder', true],
880
+        ];
881
+
882
+        $nonShareAble = $this->createMock(Folder::class);
883
+        $nonShareAble->method('getId')->willReturn(108);
884
+        $nonShareAble->method('isShareable')->willReturn(false);
885
+        $nonShareAble->method('getPath')->willReturn('path');
886
+        $nonShareAble->method('getName')->willReturn('name');
887
+        $nonShareAble->method('getOwner')
888
+            ->willReturn($owner);
889
+        $nonShareAble->method('getStorage')
890
+            ->willReturn($storage);
891
+
892
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $nonShareAble, $user2, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
893
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $nonShareAble, $group0, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
894
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $nonShareAble, null, $user0, $user0, 31, null, null), 'You are not allowed to share name', true];
895
+
896
+        $limitedPermssions = $this->createMock(File::class);
897
+        $limitedPermssions->method('isShareable')->willReturn(true);
898
+        $limitedPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
899
+        $limitedPermssions->method('getId')->willReturn(108);
900
+        $limitedPermssions->method('getPath')->willReturn('path');
901
+        $limitedPermssions->method('getName')->willReturn('name');
902
+        $limitedPermssions->method('getOwner')
903
+            ->willReturn($owner);
904
+        $limitedPermssions->method('getStorage')
905
+            ->willReturn($storage);
906
+
907
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
908
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
909
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, null, null, null), 'Valid permissions are required for sharing', true];
910
+
911
+        $mount = $this->createMock(MoveableMount::class);
912
+        $limitedPermssions->method('getMountPoint')->willReturn($mount);
913
+
914
+        // increase permissions of a re-share
915
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null), 'Cannot increase permissions of path', true];
916
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true];
917
+
918
+        $nonMovableStorage = $this->createMock(IStorage::class);
919
+        $nonMovableStorage->method('instanceOfStorage')
920
+            ->with('\OCA\Files_Sharing\External\Storage')
921
+            ->willReturn(false);
922
+        $nonMovableStorage->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
923
+        $nonMoveableMountPermssions = $this->createMock(Folder::class);
924
+        $nonMoveableMountPermssions->method('isShareable')->willReturn(true);
925
+        $nonMoveableMountPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_READ);
926
+        $nonMoveableMountPermssions->method('getId')->willReturn(108);
927
+        $nonMoveableMountPermssions->method('getPath')->willReturn('path');
928
+        $nonMoveableMountPermssions->method('getName')->willReturn('name');
929
+        $nonMoveableMountPermssions->method('getInternalPath')->willReturn('');
930
+        $nonMoveableMountPermssions->method('getOwner')
931
+            ->willReturn($owner);
932
+        $nonMoveableMountPermssions->method('getStorage')
933
+            ->willReturn($nonMovableStorage);
934
+
935
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $nonMoveableMountPermssions, $user2, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false];
936
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $nonMoveableMountPermssions, $group0, $user0, $user0, 11, null, null), 'Cannot increase permissions of path', false];
937
+
938
+        $rootFolder = $this->createMock(Folder::class);
939
+        $rootFolder->method('isShareable')->willReturn(true);
940
+        $rootFolder->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
941
+        $rootFolder->method('getId')->willReturn(42);
942
+
943
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $rootFolder, $user2, $user0, $user0, 30, null, null), 'You cannot share your root folder', true];
944
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null), 'You cannot share your root folder', true];
945
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null), 'You cannot share your root folder', true];
946
+
947
+        $allPermssionsFiles = $this->createMock(File::class);
948
+        $allPermssionsFiles->method('isShareable')->willReturn(true);
949
+        $allPermssionsFiles->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
950
+        $allPermssionsFiles->method('getId')->willReturn(187);
951
+        $allPermssionsFiles->method('getOwner')
952
+            ->willReturn($owner);
953
+        $allPermssionsFiles->method('getStorage')
954
+            ->willReturn($storage);
955
+
956
+        // test invalid CREATE or DELETE permissions
957
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, Constants::PERMISSION_ALL, null, null), 'File shares cannot have create or delete permissions', true];
958
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_CREATE, null, null), 'File shares cannot have create or delete permissions', true];
959
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, Constants::PERMISSION_READ | Constants::PERMISSION_DELETE, null, null), 'File shares cannot have create or delete permissions', true];
960
+
961
+        $allPermssions = $this->createMock(Folder::class);
962
+        $allPermssions->method('isShareable')->willReturn(true);
963
+        $allPermssions->method('getPermissions')->willReturn(Constants::PERMISSION_ALL);
964
+        $allPermssions->method('getId')->willReturn(108);
965
+        $allPermssions->method('getOwner')
966
+            ->willReturn($owner);
967
+        $allPermssions->method('getStorage')
968
+            ->willReturn($storage);
969
+
970
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true];
971
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true];
972
+
973
+        // test invalid permissions
974
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null), 'Valid permissions are required for sharing', true];
975
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null), 'Valid permissions are required for sharing', true];
976
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null), 'Valid permissions are required for sharing', true];
977
+
978
+        // working shares
979
+        $data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false];
980
+        $data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false];
981
+        $data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null), null, false];
982
+
983
+
984
+        $remoteStorage = $this->createMock(IStorage::class);
985
+        $remoteStorage->method('instanceOfStorage')
986
+            ->with('\OCA\Files_Sharing\External\Storage')
987
+            ->willReturn(true);
988
+        $remoteFile = $this->createMock(Folder::class);
989
+        $remoteFile->method('isShareable')->willReturn(true);
990
+        $remoteFile->method('getPermissions')->willReturn(Constants::PERMISSION_READ ^ Constants::PERMISSION_UPDATE);
991
+        $remoteFile->method('getId')->willReturn(108);
992
+        $remoteFile->method('getOwner')
993
+            ->willReturn($owner);
994
+        $remoteFile->method('getStorage')
995
+            ->willReturn($storage);
996
+        $data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 1, null, null), null, false];
997
+        $data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 3, null, null), null, false];
998
+        $data[] = [$this->createShare(null, IShare::TYPE_REMOTE, $remoteFile, $user2, $user0, $user0, 31, null, null), 'Cannot increase permissions of ', true];
999
+
1000
+        return $data;
1001
+    }
1002
+
1003
+    /**
1004
+     *
1005
+     * @param $share
1006
+     * @param $exceptionMessage
1007
+     * @param $exception
1008
+     */
1009
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataGeneralChecks')]
1010
+    public function testGeneralChecks($share, $exceptionMessage, $exception): void {
1011
+        $thrown = null;
1012
+
1013
+        $this->userManager->method('userExists')->willReturnMap([
1014
+            ['user0', true],
1015
+            ['user1', true],
1016
+        ]);
1017
+
1018
+        $this->groupManager->method('groupExists')->willReturnMap([
1019
+            ['group0', true],
1020
+        ]);
1021
+
1022
+        $userFolder = $this->createMock(Folder::class);
1023
+        $userFolder->expects($this->any())
1024
+            ->method('getId')
1025
+            ->willReturn(42);
1026
+        // Id 108 is used in the data to refer to the node of the share.
1027
+        $userFolder->method('getById')
1028
+            ->with(108)
1029
+            ->willReturn([$share->getNode()]);
1030
+        $userFolder->expects($this->any())
1031
+            ->method('getRelativePath')
1032
+            ->willReturnArgument(0);
1033
+        $this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1034
+
1035
+
1036
+        try {
1037
+            self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1038
+            $thrown = false;
1039
+        } catch (GenericShareException $e) {
1040
+            $this->assertEquals($exceptionMessage, $e->getHint());
1041
+            $thrown = true;
1042
+        } catch (\InvalidArgumentException $e) {
1043
+            $this->assertEquals($exceptionMessage, $e->getMessage());
1044
+            $thrown = true;
1045
+        }
1046
+
1047
+        $this->assertSame($exception, $thrown);
1048
+    }
1049
+
1050
+
1051
+    public function testGeneralCheckShareRoot(): void {
1052
+        $this->expectException(\InvalidArgumentException::class);
1053
+        $this->expectExceptionMessage('You cannot share your root folder');
1054
+
1055
+        $thrown = null;
1056
+
1057
+        $this->userManager->method('userExists')->willReturnMap([
1058
+            ['user0', true],
1059
+            ['user1', true],
1060
+        ]);
1061
+
1062
+        $userFolder = $this->createMock(Folder::class);
1063
+        $userFolder->method('isSubNode')->with($userFolder)->willReturn(false);
1064
+        $this->rootFolder->method('getUserFolder')->willReturn($userFolder);
1065
+
1066
+        $share = $this->manager->newShare();
1067
+
1068
+        $share->setShareType(IShare::TYPE_USER)
1069
+            ->setSharedWith('user0')
1070
+            ->setSharedBy('user1')
1071
+            ->setNode($userFolder);
1072
+
1073
+        self::invokePrivate($this->manager, 'generalCreateChecks', [$share]);
1074
+    }
1075
+
1076
+    public static function validateExpirationDateInternalProvider() {
1077
+        return [[IShare::TYPE_USER], [IShare::TYPE_REMOTE], [IShare::TYPE_REMOTE_GROUP]];
1078
+    }
1079
+
1080
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1081
+    public function testValidateExpirationDateInternalInPast($shareType): void {
1082
+        $this->expectException(GenericShareException::class);
1083
+        $this->expectExceptionMessage('Expiration date is in the past');
1084
+
1085
+        // Expire date in the past
1086
+        $past = new \DateTime();
1087
+        $past->sub(new \DateInterval('P1D'));
1088
+
1089
+        $share = $this->manager->newShare();
1090
+        $share->setShareType($shareType);
1091
+        $share->setExpirationDate($past);
1092
+
1093
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1094
+    }
1095
+
1096
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1097
+    public function testValidateExpirationDateInternalEnforceButNotSet($shareType): void {
1098
+        $this->expectException(\InvalidArgumentException::class);
1099
+        $this->expectExceptionMessage('Expiration date is enforced');
1100
+
1101
+        $share = $this->manager->newShare();
1102
+        $share->setProviderId('foo')->setId('bar');
1103
+        $share->setShareType($shareType);
1104
+        if ($shareType === IShare::TYPE_USER) {
1105
+            $this->config->method('getAppValue')
1106
+                ->willReturnMap([
1107
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1108
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1109
+                ]);
1110
+        } else {
1111
+            $this->config->method('getAppValue')
1112
+                ->willReturnMap([
1113
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1114
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1115
+                ]);
1116
+        }
1117
+
1118
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1119
+    }
1120
+
1121
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1122
+    public function testValidateExpirationDateInternalEnforceButNotEnabledAndNotSet($shareType): void {
1123
+        $share = $this->manager->newShare();
1124
+        $share->setProviderId('foo')->setId('bar');
1125
+        $share->setShareType($shareType);
1126
+
1127
+        if ($shareType === IShare::TYPE_USER) {
1128
+            $this->config->method('getAppValue')
1129
+                ->willReturnMap([
1130
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1131
+                ]);
1132
+        } else {
1133
+            $this->config->method('getAppValue')
1134
+                ->willReturnMap([
1135
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1136
+                ]);
1137
+        }
1138
+
1139
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1140
+
1141
+        $this->assertNull($share->getExpirationDate());
1142
+    }
1143
+
1144
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1145
+    public function testValidateExpirationDateInternalEnforceButNotSetNewShare($shareType): void {
1146
+        $share = $this->manager->newShare();
1147
+        $share->setShareType($shareType);
1148
+
1149
+        if ($shareType === IShare::TYPE_USER) {
1150
+            $this->config->method('getAppValue')
1151
+                ->willReturnMap([
1152
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1153
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1154
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1155
+                    ['core', 'internal_defaultExpDays', '3', '3'],
1156
+                ]);
1157
+        } else {
1158
+            $this->config->method('getAppValue')
1159
+                ->willReturnMap([
1160
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1161
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1162
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1163
+                    ['core', 'remote_defaultExpDays', '3', '3'],
1164
+                ]);
1165
+        }
1166
+
1167
+        $expected = new \DateTime('now', $this->timezone);
1168
+        $expected->setTime(0, 0, 0);
1169
+        $expected->add(new \DateInterval('P3D'));
1170
+
1171
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1172
+
1173
+        $this->assertNotNull($share->getExpirationDate());
1174
+        $this->assertEquals($expected, $share->getExpirationDate());
1175
+    }
1176
+
1177
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1178
+    public function testValidateExpirationDateInternalEnforceRelaxedDefaultButNotSetNewShare($shareType): void {
1179
+        $share = $this->manager->newShare();
1180
+        $share->setShareType($shareType);
1181
+
1182
+        if ($shareType === IShare::TYPE_USER) {
1183
+            $this->config->method('getAppValue')
1184
+                ->willReturnMap([
1185
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1186
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1187
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1188
+                    ['core', 'internal_defaultExpDays', '3', '1'],
1189
+                ]);
1190
+        } else {
1191
+            $this->config->method('getAppValue')
1192
+                ->willReturnMap([
1193
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1194
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1195
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1196
+                    ['core', 'remote_defaultExpDays', '3', '1'],
1197
+                ]);
1198
+        }
1199
+
1200
+        $expected = new \DateTime('now', $this->timezone);
1201
+        $expected->setTime(0, 0, 0);
1202
+        $expected->add(new \DateInterval('P1D'));
1203
+
1204
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1205
+
1206
+        $this->assertNotNull($share->getExpirationDate());
1207
+        $this->assertEquals($expected, $share->getExpirationDate());
1208
+    }
1209
+
1210
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1211
+    public function testValidateExpirationDateInternalEnforceTooFarIntoFuture($shareType): void {
1212
+        $this->expectException(GenericShareException::class);
1213
+        $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1214
+
1215
+        $future = new \DateTime();
1216
+        $future->add(new \DateInterval('P7D'));
1217
+
1218
+        $share = $this->manager->newShare();
1219
+        $share->setShareType($shareType);
1220
+        $share->setExpirationDate($future);
1221
+
1222
+        if ($shareType === IShare::TYPE_USER) {
1223
+            $this->config->method('getAppValue')
1224
+                ->willReturnMap([
1225
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1226
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1227
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1228
+                ]);
1229
+        } else {
1230
+            $this->config->method('getAppValue')
1231
+                ->willReturnMap([
1232
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1233
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1234
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1235
+                ]);
1236
+        }
1237
+
1238
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1239
+    }
1240
+
1241
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1242
+    public function testValidateExpirationDateInternalEnforceValid($shareType): void {
1243
+        $future = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1244
+        $future->add(new \DateInterval('P2D'));
1245
+        $future->setTime(1, 2, 3);
1246
+
1247
+        $expected = clone $future;
1248
+        $expected->setTime(0, 0, 0);
1249
+
1250
+        $share = $this->manager->newShare();
1251
+        $share->setShareType($shareType);
1252
+        $share->setExpirationDate($future);
1253
+
1254
+        if ($shareType === IShare::TYPE_USER) {
1255
+            $this->config->method('getAppValue')
1256
+                ->willReturnMap([
1257
+                    ['core', 'shareapi_enforce_internal_expire_date', 'no', 'yes'],
1258
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1259
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1260
+                ]);
1261
+        } else {
1262
+            $this->config->method('getAppValue')
1263
+                ->willReturnMap([
1264
+                    ['core', 'shareapi_enforce_remote_expire_date', 'no', 'yes'],
1265
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1266
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1267
+                ]);
1268
+        }
1269
+
1270
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1271
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1272
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1273
+            return $data['expirationDate'] == $future;
1274
+        }));
1275
+
1276
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1277
+
1278
+        $this->assertEquals($expected, $share->getExpirationDate());
1279
+    }
1280
+
1281
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1282
+    public function testValidateExpirationDateInternalNoDefault($shareType): void {
1283
+        $date = new \DateTime('now', $this->dateTimeZone->getTimeZone());
1284
+        $date->add(new \DateInterval('P5D'));
1285
+        $date->setTime(1, 2, 3);
1286
+
1287
+        $expected = clone $date;
1288
+        $expected->setTime(0, 0, 0);
1289
+
1290
+        $share = $this->manager->newShare();
1291
+        $share->setShareType($shareType);
1292
+        $share->setExpirationDate($date);
1293
+
1294
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1295
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1296
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1297
+            return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1298
+        }));
1299
+
1300
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1301
+
1302
+        $this->assertEquals($expected, $share->getExpirationDate());
1303
+    }
1304
+
1305
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1306
+    public function testValidateExpirationDateInternalNoDateNoDefault($shareType): void {
1307
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1308
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1309
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1310
+            return $data['expirationDate'] === null && $data['passwordSet'] === true;
1311
+        }));
1312
+
1313
+        $share = $this->manager->newShare();
1314
+        $share->setShareType($shareType);
1315
+        $share->setPassword('password');
1316
+
1317
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1318
+
1319
+        $this->assertNull($share->getExpirationDate());
1320
+    }
1321
+
1322
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1323
+    public function testValidateExpirationDateInternalNoDateDefault($shareType): void {
1324
+        $share = $this->manager->newShare();
1325
+        $share->setShareType($shareType);
1326
+
1327
+        $expected = new \DateTime('now', $this->timezone);
1328
+        $expected->setTime(0, 0);
1329
+        $expected->add(new \DateInterval('P3D'));
1330
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1331
+
1332
+        if ($shareType === IShare::TYPE_USER) {
1333
+            $this->config->method('getAppValue')
1334
+                ->willReturnMap([
1335
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1336
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1337
+                    ['core', 'internal_defaultExpDays', '3', '3'],
1338
+                ]);
1339
+        } else {
1340
+            $this->config->method('getAppValue')
1341
+                ->willReturnMap([
1342
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1343
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1344
+                    ['core', 'remote_defaultExpDays', '3', '3'],
1345
+                ]);
1346
+        }
1347
+
1348
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1349
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1350
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1351
+            return $data['expirationDate'] == $expected;
1352
+        }));
1353
+
1354
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1355
+
1356
+        $this->assertEquals($expected, $share->getExpirationDate());
1357
+    }
1358
+
1359
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1360
+    public function testValidateExpirationDateInternalDefault($shareType): void {
1361
+        $future = new \DateTime('now', $this->timezone);
1362
+        $future->add(new \DateInterval('P5D'));
1363
+        $future->setTime(1, 2, 3);
1364
+
1365
+        $expected = clone $future;
1366
+        $expected->setTime(0, 0);
1367
+
1368
+        $share = $this->manager->newShare();
1369
+        $share->setShareType($shareType);
1370
+        $share->setExpirationDate($future);
1371
+
1372
+        if ($shareType === IShare::TYPE_USER) {
1373
+            $this->config->method('getAppValue')
1374
+                ->willReturnMap([
1375
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1376
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '3'],
1377
+                    ['core', 'internal_defaultExpDays', '3', '1'],
1378
+                ]);
1379
+        } else {
1380
+            $this->config->method('getAppValue')
1381
+                ->willReturnMap([
1382
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1383
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '3'],
1384
+                    ['core', 'remote_defaultExpDays', '3', '1'],
1385
+                ]);
1386
+        }
1387
+
1388
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1389
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1390
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1391
+            return $data['expirationDate'] == $expected;
1392
+        }));
1393
+
1394
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1395
+
1396
+        $this->assertEquals($expected, $share->getExpirationDate());
1397
+    }
1398
+
1399
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1400
+    public function testValidateExpirationDateInternalHookModification($shareType): void {
1401
+        $nextWeek = new \DateTime('now', $this->timezone);
1402
+        $nextWeek->add(new \DateInterval('P7D'));
1403
+        $nextWeek->setTime(0, 0, 0);
1404
+
1405
+        $save = clone $nextWeek;
1406
+
1407
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1408
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1409
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1410
+            $data['expirationDate']->sub(new \DateInterval('P2D'));
1411
+        });
1412
+
1413
+        $share = $this->manager->newShare();
1414
+        $share->setShareType($shareType);
1415
+        $share->setExpirationDate($nextWeek);
1416
+
1417
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1418
+
1419
+        $save->sub(new \DateInterval('P2D'));
1420
+        $this->assertEquals($save, $share->getExpirationDate());
1421
+    }
1422
+
1423
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1424
+    public function testValidateExpirationDateInternalHookException($shareType): void {
1425
+        $this->expectException(\Exception::class);
1426
+        $this->expectExceptionMessage('Invalid date!');
1427
+
1428
+        $nextWeek = new \DateTime();
1429
+        $nextWeek->add(new \DateInterval('P7D'));
1430
+        $nextWeek->setTime(0, 0, 0);
1431
+
1432
+        $share = $this->manager->newShare();
1433
+        $share->setShareType($shareType);
1434
+        $share->setExpirationDate($nextWeek);
1435
+
1436
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1437
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1438
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1439
+            $data['accepted'] = false;
1440
+            $data['message'] = 'Invalid date!';
1441
+        });
1442
+
1443
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1444
+    }
1445
+
1446
+    #[\PHPUnit\Framework\Attributes\DataProvider('validateExpirationDateInternalProvider')]
1447
+    public function testValidateExpirationDateInternalExistingShareNoDefault($shareType): void {
1448
+        $share = $this->manager->newShare();
1449
+        $share->setShareType($shareType);
1450
+        $share->setId('42')->setProviderId('foo');
1451
+
1452
+        if ($shareType === IShare::TYPE_USER) {
1453
+            $this->config->method('getAppValue')
1454
+                ->willReturnMap([
1455
+                    ['core', 'shareapi_default_internal_expire_date', 'no', 'yes'],
1456
+                    ['core', 'shareapi_internal_expire_after_n_days', '7', '6'],
1457
+                ]);
1458
+        } else {
1459
+            $this->config->method('getAppValue')
1460
+                ->willReturnMap([
1461
+                    ['core', 'shareapi_default_remote_expire_date', 'no', 'yes'],
1462
+                    ['core', 'shareapi_remote_expire_after_n_days', '7', '6'],
1463
+                ]);
1464
+        }
1465
+
1466
+        self::invokePrivate($this->manager, 'validateExpirationDateInternal', [$share]);
1467
+
1468
+        $this->assertEquals(null, $share->getExpirationDate());
1469
+    }
1470
+
1471
+    public function testValidateExpirationDateInPast(): void {
1472
+        $this->expectException(GenericShareException::class);
1473
+        $this->expectExceptionMessage('Expiration date is in the past');
1474
+
1475
+        // Expire date in the past
1476
+        $past = new \DateTime();
1477
+        $past->sub(new \DateInterval('P1D'));
1478
+
1479
+        $share = $this->manager->newShare();
1480
+        $share->setExpirationDate($past);
1481
+
1482
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1483
+    }
1484
+
1485
+    public function testValidateExpirationDateEnforceButNotSet(): void {
1486
+        $this->expectException(\InvalidArgumentException::class);
1487
+        $this->expectExceptionMessage('Expiration date is enforced');
1488
+
1489
+        $share = $this->manager->newShare();
1490
+        $share->setProviderId('foo')->setId('bar');
1491
+
1492
+        $this->config->method('getAppValue')
1493
+            ->willReturnMap([
1494
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1495
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1496
+            ]);
1497
+
1498
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1499
+    }
1500
+
1501
+    public function testValidateExpirationDateEnforceButNotEnabledAndNotSet(): void {
1502
+        $share = $this->manager->newShare();
1503
+        $share->setProviderId('foo')->setId('bar');
1504
+
1505
+        $this->config->method('getAppValue')
1506
+            ->willReturnMap([
1507
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1508
+            ]);
1509
+
1510
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1511
+
1512
+        $this->assertNull($share->getExpirationDate());
1513
+    }
1514
+
1515
+    public function testValidateExpirationDateEnforceButNotSetNewShare(): void {
1516
+        $share = $this->manager->newShare();
1517
+
1518
+        $this->config->method('getAppValue')
1519
+            ->willReturnMap([
1520
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1521
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1522
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1523
+                ['core', 'link_defaultExpDays', '3', '3'],
1524
+            ]);
1525
+
1526
+        $expected = new \DateTime('now', $this->timezone);
1527
+        $expected->setTime(0, 0, 0);
1528
+        $expected->add(new \DateInterval('P3D'));
1529
+
1530
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1531
+
1532
+        $this->assertNotNull($share->getExpirationDate());
1533
+        $this->assertEquals($expected, $share->getExpirationDate());
1534
+    }
1535
+
1536
+    public function testValidateExpirationDateEnforceRelaxedDefaultButNotSetNewShare(): void {
1537
+        $share = $this->manager->newShare();
1538
+
1539
+        $this->config->method('getAppValue')
1540
+            ->willReturnMap([
1541
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1542
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1543
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1544
+                ['core', 'link_defaultExpDays', '3', '1'],
1545
+            ]);
1546
+
1547
+        $expected = new \DateTime('now', $this->timezone);
1548
+        $expected->setTime(0, 0, 0);
1549
+        $expected->add(new \DateInterval('P1D'));
1550
+
1551
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1552
+
1553
+        $this->assertNotNull($share->getExpirationDate());
1554
+        $this->assertEquals($expected, $share->getExpirationDate());
1555
+    }
1556
+
1557
+    public function testValidateExpirationDateEnforceTooFarIntoFuture(): void {
1558
+        $this->expectException(GenericShareException::class);
1559
+        $this->expectExceptionMessage('Cannot set expiration date more than 3 days in the future');
1560 1560
 
1561
-		$future = new \DateTime();
1562
-		$future->add(new \DateInterval('P7D'));
1561
+        $future = new \DateTime();
1562
+        $future->add(new \DateInterval('P7D'));
1563 1563
 
1564
-		$share = $this->manager->newShare();
1565
-		$share->setExpirationDate($future);
1564
+        $share = $this->manager->newShare();
1565
+        $share->setExpirationDate($future);
1566 1566
 
1567
-		$this->config->method('getAppValue')
1568
-			->willReturnMap([
1569
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1570
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1571
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1572
-			]);
1567
+        $this->config->method('getAppValue')
1568
+            ->willReturnMap([
1569
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1570
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1571
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1572
+            ]);
1573 1573
 
1574
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1575
-	}
1574
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1575
+    }
1576 1576
 
1577
-	public function testValidateExpirationDateEnforceValid(): void {
1578
-		$future = new \DateTime('now', $this->timezone);
1579
-		$future->add(new \DateInterval('P2D'));
1580
-		$future->setTime(1, 2, 3);
1577
+    public function testValidateExpirationDateEnforceValid(): void {
1578
+        $future = new \DateTime('now', $this->timezone);
1579
+        $future->add(new \DateInterval('P2D'));
1580
+        $future->setTime(1, 2, 3);
1581 1581
 
1582
-		$expected = clone $future;
1583
-		$expected->setTime(0, 0, 0);
1582
+        $expected = clone $future;
1583
+        $expected->setTime(0, 0, 0);
1584 1584
 
1585
-		$share = $this->manager->newShare();
1586
-		$share->setExpirationDate($future);
1587
-
1588
-		$this->config->method('getAppValue')
1589
-			->willReturnMap([
1590
-				['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1591
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1592
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1593
-			]);
1594
-
1595
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1596
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1597
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1598
-			return $data['expirationDate'] == $future;
1599
-		}));
1585
+        $share = $this->manager->newShare();
1586
+        $share->setExpirationDate($future);
1587
+
1588
+        $this->config->method('getAppValue')
1589
+            ->willReturnMap([
1590
+                ['core', 'shareapi_enforce_expire_date', 'no', 'yes'],
1591
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1592
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1593
+            ]);
1594
+
1595
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1596
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1597
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($future) {
1598
+            return $data['expirationDate'] == $future;
1599
+        }));
1600 1600
 
1601
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1602
-
1603
-		$this->assertEquals($expected, $share->getExpirationDate());
1604
-	}
1605
-
1606
-	public function testValidateExpirationDateNoDefault(): void {
1607
-		$date = new \DateTime('now', $this->timezone);
1608
-		$date->add(new \DateInterval('P5D'));
1609
-		$date->setTime(1, 2, 3);
1610
-
1611
-		$expected = clone $date;
1612
-		$expected->setTime(0, 0);
1613
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1614
-
1615
-		$share = $this->manager->newShare();
1616
-		$share->setExpirationDate($date);
1617
-
1618
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1619
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1620
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1621
-			return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1622
-		}));
1623
-
1624
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1625
-
1626
-		$this->assertEquals($expected, $share->getExpirationDate());
1627
-	}
1628
-
1629
-	public function testValidateExpirationDateNoDateNoDefault(): void {
1630
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1631
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1632
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1633
-			return $data['expirationDate'] === null && $data['passwordSet'] === true;
1634
-		}));
1635
-
1636
-		$share = $this->manager->newShare();
1637
-		$share->setPassword('password');
1638
-
1639
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1640
-
1641
-		$this->assertNull($share->getExpirationDate());
1642
-	}
1643
-
1644
-	public function testValidateExpirationDateNoDateDefault(): void {
1645
-		$share = $this->manager->newShare();
1646
-
1647
-		$expected = new \DateTime('now', $this->timezone);
1648
-		$expected->add(new \DateInterval('P3D'));
1649
-		$expected->setTime(0, 0);
1650
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1651
-
1652
-		$this->config->method('getAppValue')
1653
-			->willReturnMap([
1654
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1655
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1656
-				['core', 'link_defaultExpDays', '3', '3'],
1657
-			]);
1658
-
1659
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1660
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1661
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1662
-			return $data['expirationDate'] == $expected;
1663
-		}));
1664
-
1665
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1666
-
1667
-		$this->assertEquals($expected, $share->getExpirationDate());
1668
-	}
1669
-
1670
-	public function testValidateExpirationDateDefault(): void {
1671
-		$future = new \DateTime('now', $this->timezone);
1672
-		$future->add(new \DateInterval('P5D'));
1673
-		$future->setTime(1, 2, 3);
1674
-
1675
-		$expected = clone $future;
1676
-		$expected->setTime(0, 0);
1677
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1678
-
1679
-		$share = $this->manager->newShare();
1680
-		$share->setExpirationDate($future);
1601
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1602
+
1603
+        $this->assertEquals($expected, $share->getExpirationDate());
1604
+    }
1605
+
1606
+    public function testValidateExpirationDateNoDefault(): void {
1607
+        $date = new \DateTime('now', $this->timezone);
1608
+        $date->add(new \DateInterval('P5D'));
1609
+        $date->setTime(1, 2, 3);
1610
+
1611
+        $expected = clone $date;
1612
+        $expected->setTime(0, 0);
1613
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1614
+
1615
+        $share = $this->manager->newShare();
1616
+        $share->setExpirationDate($date);
1617
+
1618
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1619
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1620
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1621
+            return $data['expirationDate'] == $expected && $data['passwordSet'] === false;
1622
+        }));
1623
+
1624
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1625
+
1626
+        $this->assertEquals($expected, $share->getExpirationDate());
1627
+    }
1628
+
1629
+    public function testValidateExpirationDateNoDateNoDefault(): void {
1630
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1631
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1632
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) {
1633
+            return $data['expirationDate'] === null && $data['passwordSet'] === true;
1634
+        }));
1635
+
1636
+        $share = $this->manager->newShare();
1637
+        $share->setPassword('password');
1638
+
1639
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1640
+
1641
+        $this->assertNull($share->getExpirationDate());
1642
+    }
1643
+
1644
+    public function testValidateExpirationDateNoDateDefault(): void {
1645
+        $share = $this->manager->newShare();
1646
+
1647
+        $expected = new \DateTime('now', $this->timezone);
1648
+        $expected->add(new \DateInterval('P3D'));
1649
+        $expected->setTime(0, 0);
1650
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1651
+
1652
+        $this->config->method('getAppValue')
1653
+            ->willReturnMap([
1654
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1655
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1656
+                ['core', 'link_defaultExpDays', '3', '3'],
1657
+            ]);
1658
+
1659
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1660
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1661
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1662
+            return $data['expirationDate'] == $expected;
1663
+        }));
1664
+
1665
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1666
+
1667
+        $this->assertEquals($expected, $share->getExpirationDate());
1668
+    }
1669
+
1670
+    public function testValidateExpirationDateDefault(): void {
1671
+        $future = new \DateTime('now', $this->timezone);
1672
+        $future->add(new \DateInterval('P5D'));
1673
+        $future->setTime(1, 2, 3);
1674
+
1675
+        $expected = clone $future;
1676
+        $expected->setTime(0, 0);
1677
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1678
+
1679
+        $share = $this->manager->newShare();
1680
+        $share->setExpirationDate($future);
1681 1681
 
1682
-		$this->config->method('getAppValue')
1683
-			->willReturnMap([
1684
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1685
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1686
-				['core', 'link_defaultExpDays', '3', '1'],
1687
-			]);
1688
-
1689
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1690
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1691
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1692
-			return $data['expirationDate'] == $expected;
1693
-		}));
1682
+        $this->config->method('getAppValue')
1683
+            ->willReturnMap([
1684
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1685
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1686
+                ['core', 'link_defaultExpDays', '3', '1'],
1687
+            ]);
1688
+
1689
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1690
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1691
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1692
+            return $data['expirationDate'] == $expected;
1693
+        }));
1694 1694
 
1695
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1695
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1696 1696
 
1697
-		$this->assertEquals($expected, $share->getExpirationDate());
1698
-	}
1697
+        $this->assertEquals($expected, $share->getExpirationDate());
1698
+    }
1699 1699
 
1700
-	public function testValidateExpirationNegativeOffsetTimezone(): void {
1701
-		$this->timezone = new \DateTimeZone('Pacific/Tahiti');
1702
-		$future = new \DateTime();
1703
-		$future->add(new \DateInterval('P5D'));
1700
+    public function testValidateExpirationNegativeOffsetTimezone(): void {
1701
+        $this->timezone = new \DateTimeZone('Pacific/Tahiti');
1702
+        $future = new \DateTime();
1703
+        $future->add(new \DateInterval('P5D'));
1704 1704
 
1705
-		$expected = clone $future;
1706
-		$expected->setTimezone($this->timezone);
1707
-		$expected->setTime(0, 0);
1708
-		$expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1705
+        $expected = clone $future;
1706
+        $expected->setTimezone($this->timezone);
1707
+        $expected->setTime(0, 0);
1708
+        $expected->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1709 1709
 
1710
-		$share = $this->manager->newShare();
1711
-		$share->setExpirationDate($future);
1712
-
1713
-		$this->config->method('getAppValue')
1714
-			->willReturnMap([
1715
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1716
-				['core', 'shareapi_expire_after_n_days', '7', '3'],
1717
-				['core', 'link_defaultExpDays', '3', '1'],
1718
-			]);
1719
-
1720
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1721
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1722
-		$hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1723
-			return $data['expirationDate'] == $expected;
1724
-		}));
1725
-
1726
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1727
-
1728
-		$this->assertEquals($expected, $share->getExpirationDate());
1729
-	}
1730
-
1731
-	public function testValidateExpirationDateHookModification(): void {
1732
-		$nextWeek = new \DateTime('now', $this->timezone);
1733
-		$nextWeek->add(new \DateInterval('P7D'));
1710
+        $share = $this->manager->newShare();
1711
+        $share->setExpirationDate($future);
1712
+
1713
+        $this->config->method('getAppValue')
1714
+            ->willReturnMap([
1715
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1716
+                ['core', 'shareapi_expire_after_n_days', '7', '3'],
1717
+                ['core', 'link_defaultExpDays', '3', '1'],
1718
+            ]);
1719
+
1720
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1721
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1722
+        $hookListener->expects($this->once())->method('listener')->with($this->callback(function ($data) use ($expected) {
1723
+            return $data['expirationDate'] == $expected;
1724
+        }));
1725
+
1726
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1727
+
1728
+        $this->assertEquals($expected, $share->getExpirationDate());
1729
+    }
1730
+
1731
+    public function testValidateExpirationDateHookModification(): void {
1732
+        $nextWeek = new \DateTime('now', $this->timezone);
1733
+        $nextWeek->add(new \DateInterval('P7D'));
1734 1734
 
1735
-		$save = clone $nextWeek;
1736
-		$save->setTime(0, 0);
1737
-		$save->sub(new \DateInterval('P2D'));
1738
-		$save->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1739
-
1740
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1741
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1742
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1743
-			$data['expirationDate']->sub(new \DateInterval('P2D'));
1744
-		});
1745
-
1746
-		$share = $this->manager->newShare();
1747
-		$share->setExpirationDate($nextWeek);
1748
-
1749
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1750
-
1751
-		$this->assertEquals($save, $share->getExpirationDate());
1752
-	}
1753
-
1754
-	public function testValidateExpirationDateHookException(): void {
1755
-		$this->expectException(\Exception::class);
1756
-		$this->expectExceptionMessage('Invalid date!');
1757
-
1758
-		$nextWeek = new \DateTime();
1759
-		$nextWeek->add(new \DateInterval('P7D'));
1760
-		$nextWeek->setTime(0, 0, 0);
1761
-
1762
-		$share = $this->manager->newShare();
1763
-		$share->setExpirationDate($nextWeek);
1764
-
1765
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
1766
-		Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1767
-		$hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1768
-			$data['accepted'] = false;
1769
-			$data['message'] = 'Invalid date!';
1770
-		});
1771
-
1772
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1773
-	}
1774
-
1775
-	public function testValidateExpirationDateExistingShareNoDefault(): void {
1776
-		$share = $this->manager->newShare();
1777
-
1778
-		$share->setId('42')->setProviderId('foo');
1779
-
1780
-		$this->config->method('getAppValue')
1781
-			->willReturnMap([
1782
-				['core', 'shareapi_default_expire_date', 'no', 'yes'],
1783
-				['core', 'shareapi_expire_after_n_days', '7', '6'],
1784
-			]);
1785
-
1786
-		self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1787
-
1788
-		$this->assertEquals(null, $share->getExpirationDate());
1789
-	}
1790
-
1791
-	public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups(): void {
1792
-		$this->expectException(\Exception::class);
1793
-		$this->expectExceptionMessage('Sharing is only allowed with group members');
1735
+        $save = clone $nextWeek;
1736
+        $save->setTime(0, 0);
1737
+        $save->sub(new \DateInterval('P2D'));
1738
+        $save->setTimezone(new \DateTimeZone(date_default_timezone_get()));
1739
+
1740
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1741
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1742
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1743
+            $data['expirationDate']->sub(new \DateInterval('P2D'));
1744
+        });
1745
+
1746
+        $share = $this->manager->newShare();
1747
+        $share->setExpirationDate($nextWeek);
1748
+
1749
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1750
+
1751
+        $this->assertEquals($save, $share->getExpirationDate());
1752
+    }
1753
+
1754
+    public function testValidateExpirationDateHookException(): void {
1755
+        $this->expectException(\Exception::class);
1756
+        $this->expectExceptionMessage('Invalid date!');
1757
+
1758
+        $nextWeek = new \DateTime();
1759
+        $nextWeek->add(new \DateInterval('P7D'));
1760
+        $nextWeek->setTime(0, 0, 0);
1761
+
1762
+        $share = $this->manager->newShare();
1763
+        $share->setExpirationDate($nextWeek);
1764
+
1765
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
1766
+        Util::connectHook('\OC\Share', 'verifyExpirationDate', $hookListener, 'listener');
1767
+        $hookListener->expects($this->once())->method('listener')->willReturnCallback(function ($data): void {
1768
+            $data['accepted'] = false;
1769
+            $data['message'] = 'Invalid date!';
1770
+        });
1771
+
1772
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1773
+    }
1774
+
1775
+    public function testValidateExpirationDateExistingShareNoDefault(): void {
1776
+        $share = $this->manager->newShare();
1777
+
1778
+        $share->setId('42')->setProviderId('foo');
1779
+
1780
+        $this->config->method('getAppValue')
1781
+            ->willReturnMap([
1782
+                ['core', 'shareapi_default_expire_date', 'no', 'yes'],
1783
+                ['core', 'shareapi_expire_after_n_days', '7', '6'],
1784
+            ]);
1785
+
1786
+        self::invokePrivate($this->manager, 'validateExpirationDateLink', [$share]);
1787
+
1788
+        $this->assertEquals(null, $share->getExpirationDate());
1789
+    }
1790
+
1791
+    public function testUserCreateChecksShareWithGroupMembersOnlyDifferentGroups(): void {
1792
+        $this->expectException(\Exception::class);
1793
+        $this->expectExceptionMessage('Sharing is only allowed with group members');
1794 1794
 
1795
-		$share = $this->manager->newShare();
1795
+        $share = $this->manager->newShare();
1796 1796
 
1797
-		$sharedBy = $this->createMock(IUser::class);
1798
-		$sharedWith = $this->createMock(IUser::class);
1799
-		$share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1797
+        $sharedBy = $this->createMock(IUser::class);
1798
+        $sharedWith = $this->createMock(IUser::class);
1799
+        $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1800 1800
 
1801
-		$this->groupManager
1802
-			->method('getUserGroupIds')
1803
-			->willReturnMap(
1804
-				[
1805
-					[$sharedBy, ['group1']],
1806
-					[$sharedWith, ['group2']],
1807
-				]
1808
-			);
1801
+        $this->groupManager
1802
+            ->method('getUserGroupIds')
1803
+            ->willReturnMap(
1804
+                [
1805
+                    [$sharedBy, ['group1']],
1806
+                    [$sharedWith, ['group2']],
1807
+                ]
1808
+            );
1809 1809
 
1810
-		$this->userManager->method('get')->willReturnMap([
1811
-			['sharedBy', $sharedBy],
1812
-			['sharedWith', $sharedWith],
1813
-		]);
1810
+        $this->userManager->method('get')->willReturnMap([
1811
+            ['sharedBy', $sharedBy],
1812
+            ['sharedWith', $sharedWith],
1813
+        ]);
1814 1814
 
1815
-		$this->config
1816
-			->method('getAppValue')
1817
-			->willReturnMap([
1818
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1819
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1820
-			]);
1815
+        $this->config
1816
+            ->method('getAppValue')
1817
+            ->willReturnMap([
1818
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1819
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1820
+            ]);
1821 1821
 
1822
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1823
-	}
1822
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1823
+    }
1824 1824
 
1825
-	public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup(): void {
1826
-		$share = $this->manager->newShare();
1825
+    public function testUserCreateChecksShareWithGroupMembersOnlySharedGroup(): void {
1826
+        $share = $this->manager->newShare();
1827 1827
 
1828
-		$sharedBy = $this->createMock(IUser::class);
1829
-		$sharedWith = $this->createMock(IUser::class);
1830
-		$share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1828
+        $sharedBy = $this->createMock(IUser::class);
1829
+        $sharedWith = $this->createMock(IUser::class);
1830
+        $share->setSharedBy('sharedBy')->setSharedWith('sharedWith');
1831 1831
 
1832
-		$path = $this->createMock(Node::class);
1833
-		$share->setNode($path);
1832
+        $path = $this->createMock(Node::class);
1833
+        $share->setNode($path);
1834 1834
 
1835
-		$this->groupManager
1836
-			->method('getUserGroupIds')
1837
-			->willReturnMap(
1838
-				[
1839
-					[$sharedBy, ['group1', 'group3']],
1840
-					[$sharedWith, ['group2', 'group3']],
1841
-				]
1842
-			);
1835
+        $this->groupManager
1836
+            ->method('getUserGroupIds')
1837
+            ->willReturnMap(
1838
+                [
1839
+                    [$sharedBy, ['group1', 'group3']],
1840
+                    [$sharedWith, ['group2', 'group3']],
1841
+                ]
1842
+            );
1843 1843
 
1844
-		$this->userManager->method('get')->willReturnMap([
1845
-			['sharedBy', $sharedBy],
1846
-			['sharedWith', $sharedWith],
1847
-		]);
1844
+        $this->userManager->method('get')->willReturnMap([
1845
+            ['sharedBy', $sharedBy],
1846
+            ['sharedWith', $sharedWith],
1847
+        ]);
1848 1848
 
1849
-		$this->config
1850
-			->method('getAppValue')
1851
-			->willReturnMap([
1852
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1853
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1854
-			]);
1849
+        $this->config
1850
+            ->method('getAppValue')
1851
+            ->willReturnMap([
1852
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
1853
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
1854
+            ]);
1855 1855
 
1856
-		$this->defaultProvider
1857
-			->method('getSharesByPath')
1858
-			->with($path)
1859
-			->willReturn([]);
1856
+        $this->defaultProvider
1857
+            ->method('getSharesByPath')
1858
+            ->with($path)
1859
+            ->willReturn([]);
1860 1860
 
1861
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1862
-		$this->addToAssertionCount(1);
1863
-	}
1861
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1862
+        $this->addToAssertionCount(1);
1863
+    }
1864 1864
 
1865 1865
 
1866
-	public function testUserCreateChecksIdenticalShareExists(): void {
1867
-		$this->expectException(AlreadySharedException::class);
1868
-		$this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with the account user');
1866
+    public function testUserCreateChecksIdenticalShareExists(): void {
1867
+        $this->expectException(AlreadySharedException::class);
1868
+        $this->expectExceptionMessage('Sharing name.txt failed, because this item is already shared with the account user');
1869 1869
 
1870
-		$share = $this->manager->newShare();
1871
-		$share->setSharedWithDisplayName('user');
1872
-		$share2 = $this->manager->newShare();
1870
+        $share = $this->manager->newShare();
1871
+        $share->setSharedWithDisplayName('user');
1872
+        $share2 = $this->manager->newShare();
1873 1873
 
1874
-		$sharedWith = $this->createMock(IUser::class);
1875
-		$path = $this->createMock(Node::class);
1874
+        $sharedWith = $this->createMock(IUser::class);
1875
+        $path = $this->createMock(Node::class);
1876 1876
 
1877
-		$share->setSharedWith('sharedWith')->setNode($path)
1878
-			->setProviderId('foo')->setId('bar');
1877
+        $share->setSharedWith('sharedWith')->setNode($path)
1878
+            ->setProviderId('foo')->setId('bar');
1879 1879
 
1880
-		$share2->setSharedWith('sharedWith')->setNode($path)
1881
-			->setProviderId('foo')->setId('baz');
1880
+        $share2->setSharedWith('sharedWith')->setNode($path)
1881
+            ->setProviderId('foo')->setId('baz');
1882 1882
 
1883
-		$this->defaultProvider
1884
-			->method('getSharesByPath')
1885
-			->with($path)
1886
-			->willReturn([$share2]);
1883
+        $this->defaultProvider
1884
+            ->method('getSharesByPath')
1885
+            ->with($path)
1886
+            ->willReturn([$share2]);
1887 1887
 
1888
-		$path->method('getName')
1889
-			->willReturn('name.txt');
1888
+        $path->method('getName')
1889
+            ->willReturn('name.txt');
1890 1890
 
1891
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1892
-	}
1893
-
1894
-
1895
-	public function testUserCreateChecksIdenticalPathSharedViaGroup(): void {
1896
-		$this->expectException(AlreadySharedException::class);
1897
-		$this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with the account userName');
1898
-
1899
-		$share = $this->manager->newShare();
1891
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1892
+    }
1893
+
1894
+
1895
+    public function testUserCreateChecksIdenticalPathSharedViaGroup(): void {
1896
+        $this->expectException(AlreadySharedException::class);
1897
+        $this->expectExceptionMessage('Sharing name2.txt failed, because this item is already shared with the account userName');
1898
+
1899
+        $share = $this->manager->newShare();
1900 1900
 
1901
-		$sharedWith = $this->createMock(IUser::class);
1902
-		$sharedWith->method('getUID')->willReturn('sharedWith');
1903
-
1904
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1901
+        $sharedWith = $this->createMock(IUser::class);
1902
+        $sharedWith->method('getUID')->willReturn('sharedWith');
1903
+
1904
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1905 1905
 
1906
-		$path = $this->createMock(Node::class);
1906
+        $path = $this->createMock(Node::class);
1907 1907
 
1908
-		$share->setSharedWith('sharedWith')
1909
-			->setNode($path)
1910
-			->setShareOwner('shareOwner')
1911
-			->setSharedWithDisplayName('userName')
1912
-			->setProviderId('foo')
1913
-			->setId('bar');
1908
+        $share->setSharedWith('sharedWith')
1909
+            ->setNode($path)
1910
+            ->setShareOwner('shareOwner')
1911
+            ->setSharedWithDisplayName('userName')
1912
+            ->setProviderId('foo')
1913
+            ->setId('bar');
1914 1914
 
1915
-		$share2 = $this->manager->newShare();
1916
-		$share2->setShareType(IShare::TYPE_GROUP)
1917
-			->setShareOwner('shareOwner2')
1918
-			->setProviderId('foo')
1919
-			->setId('baz')
1920
-			->setSharedWith('group');
1915
+        $share2 = $this->manager->newShare();
1916
+        $share2->setShareType(IShare::TYPE_GROUP)
1917
+            ->setShareOwner('shareOwner2')
1918
+            ->setProviderId('foo')
1919
+            ->setId('baz')
1920
+            ->setSharedWith('group');
1921 1921
 
1922
-		$group = $this->createMock(IGroup::class);
1923
-		$group->method('inGroup')
1924
-			->with($sharedWith)
1925
-			->willReturn(true);
1922
+        $group = $this->createMock(IGroup::class);
1923
+        $group->method('inGroup')
1924
+            ->with($sharedWith)
1925
+            ->willReturn(true);
1926 1926
 
1927
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1927
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1928 1928
 
1929
-		$this->defaultProvider
1930
-			->method('getSharesByPath')
1931
-			->with($path)
1932
-			->willReturn([$share2]);
1929
+        $this->defaultProvider
1930
+            ->method('getSharesByPath')
1931
+            ->with($path)
1932
+            ->willReturn([$share2]);
1933 1933
 
1934
-		$path->method('getName')
1935
-			->willReturn('name2.txt');
1934
+        $path->method('getName')
1935
+            ->willReturn('name2.txt');
1936 1936
 
1937
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1938
-	}
1937
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
1938
+    }
1939 1939
 
1940
-	public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup(): void {
1941
-		$share = $this->manager->newShare();
1940
+    public function testUserCreateChecksIdenticalPathSharedViaDeletedGroup(): void {
1941
+        $share = $this->manager->newShare();
1942 1942
 
1943
-		$sharedWith = $this->createMock(IUser::class);
1944
-		$sharedWith->method('getUID')->willReturn('sharedWith');
1943
+        $sharedWith = $this->createMock(IUser::class);
1944
+        $sharedWith->method('getUID')->willReturn('sharedWith');
1945 1945
 
1946
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1946
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1947 1947
 
1948
-		$path = $this->createMock(Node::class);
1948
+        $path = $this->createMock(Node::class);
1949 1949
 
1950
-		$share->setSharedWith('sharedWith')
1951
-			->setNode($path)
1952
-			->setShareOwner('shareOwner')
1953
-			->setProviderId('foo')
1954
-			->setId('bar');
1950
+        $share->setSharedWith('sharedWith')
1951
+            ->setNode($path)
1952
+            ->setShareOwner('shareOwner')
1953
+            ->setProviderId('foo')
1954
+            ->setId('bar');
1955 1955
 
1956
-		$share2 = $this->manager->newShare();
1957
-		$share2->setShareType(IShare::TYPE_GROUP)
1958
-			->setShareOwner('shareOwner2')
1959
-			->setProviderId('foo')
1960
-			->setId('baz')
1961
-			->setSharedWith('group');
1956
+        $share2 = $this->manager->newShare();
1957
+        $share2->setShareType(IShare::TYPE_GROUP)
1958
+            ->setShareOwner('shareOwner2')
1959
+            ->setProviderId('foo')
1960
+            ->setId('baz')
1961
+            ->setSharedWith('group');
1962 1962
 
1963
-		$this->groupManager->method('get')->with('group')->willReturn(null);
1963
+        $this->groupManager->method('get')->with('group')->willReturn(null);
1964 1964
 
1965
-		$this->defaultProvider
1966
-			->method('getSharesByPath')
1967
-			->with($path)
1968
-			->willReturn([$share2]);
1965
+        $this->defaultProvider
1966
+            ->method('getSharesByPath')
1967
+            ->with($path)
1968
+            ->willReturn([$share2]);
1969 1969
 
1970
-		$this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share]));
1971
-	}
1970
+        $this->assertNull($this->invokePrivate($this->manager, 'userCreateChecks', [$share]));
1971
+    }
1972 1972
 
1973
-	public function testUserCreateChecksIdenticalPathNotSharedWithUser(): void {
1974
-		$share = $this->manager->newShare();
1975
-		$sharedWith = $this->createMock(IUser::class);
1976
-		$path = $this->createMock(Node::class);
1977
-		$share->setSharedWith('sharedWith')
1978
-			->setNode($path)
1979
-			->setShareOwner('shareOwner')
1980
-			->setProviderId('foo')
1981
-			->setId('bar');
1973
+    public function testUserCreateChecksIdenticalPathNotSharedWithUser(): void {
1974
+        $share = $this->manager->newShare();
1975
+        $sharedWith = $this->createMock(IUser::class);
1976
+        $path = $this->createMock(Node::class);
1977
+        $share->setSharedWith('sharedWith')
1978
+            ->setNode($path)
1979
+            ->setShareOwner('shareOwner')
1980
+            ->setProviderId('foo')
1981
+            ->setId('bar');
1982 1982
 
1983
-		$this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1983
+        $this->userManager->method('get')->with('sharedWith')->willReturn($sharedWith);
1984 1984
 
1985
-		$share2 = $this->manager->newShare();
1986
-		$share2->setShareType(IShare::TYPE_GROUP)
1987
-			->setShareOwner('shareOwner2')
1988
-			->setProviderId('foo')
1989
-			->setId('baz');
1985
+        $share2 = $this->manager->newShare();
1986
+        $share2->setShareType(IShare::TYPE_GROUP)
1987
+            ->setShareOwner('shareOwner2')
1988
+            ->setProviderId('foo')
1989
+            ->setId('baz');
1990 1990
 
1991
-		$group = $this->createMock(IGroup::class);
1992
-		$group->method('inGroup')
1993
-			->with($sharedWith)
1994
-			->willReturn(false);
1991
+        $group = $this->createMock(IGroup::class);
1992
+        $group->method('inGroup')
1993
+            ->with($sharedWith)
1994
+            ->willReturn(false);
1995 1995
 
1996
-		$this->groupManager->method('get')->with('group')->willReturn($group);
1996
+        $this->groupManager->method('get')->with('group')->willReturn($group);
1997 1997
 
1998
-		$share2->setSharedWith('group');
1998
+        $share2->setSharedWith('group');
1999 1999
 
2000
-		$this->defaultProvider
2001
-			->method('getSharesByPath')
2002
-			->with($path)
2003
-			->willReturn([$share2]);
2000
+        $this->defaultProvider
2001
+            ->method('getSharesByPath')
2002
+            ->with($path)
2003
+            ->willReturn([$share2]);
2004 2004
 
2005
-		self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2006
-		$this->addToAssertionCount(1);
2007
-	}
2005
+        self::invokePrivate($this->manager, 'userCreateChecks', [$share]);
2006
+        $this->addToAssertionCount(1);
2007
+    }
2008 2008
 
2009 2009
 
2010
-	public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed(): void {
2011
-		$this->expectException(\Exception::class);
2012
-		$this->expectExceptionMessage('Group sharing is now allowed');
2010
+    public function testGroupCreateChecksShareWithGroupMembersGroupSharingNotAllowed(): void {
2011
+        $this->expectException(\Exception::class);
2012
+        $this->expectExceptionMessage('Group sharing is now allowed');
2013 2013
 
2014
-		$share = $this->manager->newShare();
2014
+        $share = $this->manager->newShare();
2015 2015
 
2016
-		$this->config
2017
-			->method('getAppValue')
2018
-			->willReturnMap([
2019
-				['core', 'shareapi_allow_group_sharing', 'yes', 'no'],
2020
-			]);
2016
+        $this->config
2017
+            ->method('getAppValue')
2018
+            ->willReturnMap([
2019
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'no'],
2020
+            ]);
2021 2021
 
2022
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2023
-	}
2022
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2023
+    }
2024 2024
 
2025 2025
 
2026
-	public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup(): void {
2027
-		$this->expectException(\Exception::class);
2028
-		$this->expectExceptionMessage('Sharing is only allowed within your own groups');
2026
+    public function testGroupCreateChecksShareWithGroupMembersOnlyNotInGroup(): void {
2027
+        $this->expectException(\Exception::class);
2028
+        $this->expectExceptionMessage('Sharing is only allowed within your own groups');
2029 2029
 
2030
-		$share = $this->manager->newShare();
2030
+        $share = $this->manager->newShare();
2031 2031
 
2032
-		$user = $this->createMock(IUser::class);
2033
-		$group = $this->createMock(IGroup::class);
2034
-		$share->setSharedBy('user')->setSharedWith('group');
2032
+        $user = $this->createMock(IUser::class);
2033
+        $group = $this->createMock(IGroup::class);
2034
+        $share->setSharedBy('user')->setSharedWith('group');
2035 2035
 
2036
-		$group->method('inGroup')->with($user)->willReturn(false);
2036
+        $group->method('inGroup')->with($user)->willReturn(false);
2037 2037
 
2038
-		$this->groupManager->method('get')->with('group')->willReturn($group);
2039
-		$this->userManager->method('get')->with('user')->willReturn($user);
2038
+        $this->groupManager->method('get')->with('group')->willReturn($group);
2039
+        $this->userManager->method('get')->with('user')->willReturn($user);
2040 2040
 
2041
-		$this->config
2042
-			->method('getAppValue')
2043
-			->willReturnMap([
2044
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2045
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2046
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2047
-			]);
2041
+        $this->config
2042
+            ->method('getAppValue')
2043
+            ->willReturnMap([
2044
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2045
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2046
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2047
+            ]);
2048 2048
 
2049
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2050
-	}
2049
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2050
+    }
2051 2051
 
2052 2052
 
2053
-	public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup(): void {
2054
-		$this->expectException(\Exception::class);
2055
-		$this->expectExceptionMessage('Sharing is only allowed within your own groups');
2053
+    public function testGroupCreateChecksShareWithGroupMembersOnlyNullGroup(): void {
2054
+        $this->expectException(\Exception::class);
2055
+        $this->expectExceptionMessage('Sharing is only allowed within your own groups');
2056 2056
 
2057
-		$share = $this->manager->newShare();
2057
+        $share = $this->manager->newShare();
2058 2058
 
2059
-		$user = $this->createMock(IUser::class);
2060
-		$share->setSharedBy('user')->setSharedWith('group');
2059
+        $user = $this->createMock(IUser::class);
2060
+        $share->setSharedBy('user')->setSharedWith('group');
2061 2061
 
2062
-		$this->groupManager->method('get')->with('group')->willReturn(null);
2063
-		$this->userManager->method('get')->with('user')->willReturn($user);
2062
+        $this->groupManager->method('get')->with('group')->willReturn(null);
2063
+        $this->userManager->method('get')->with('user')->willReturn($user);
2064 2064
 
2065
-		$this->config
2066
-			->method('getAppValue')
2067
-			->willReturnMap([
2068
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2069
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2070
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2071
-			]);
2065
+        $this->config
2066
+            ->method('getAppValue')
2067
+            ->willReturnMap([
2068
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2069
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2070
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2071
+            ]);
2072 2072
 
2073
-		$this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
2074
-	}
2073
+        $this->assertNull($this->invokePrivate($this->manager, 'groupCreateChecks', [$share]));
2074
+    }
2075 2075
 
2076
-	public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup(): void {
2077
-		$share = $this->manager->newShare();
2076
+    public function testGroupCreateChecksShareWithGroupMembersOnlyInGroup(): void {
2077
+        $share = $this->manager->newShare();
2078 2078
 
2079
-		$user = $this->createMock(IUser::class);
2080
-		$group = $this->createMock(IGroup::class);
2081
-		$share->setSharedBy('user')->setSharedWith('group');
2079
+        $user = $this->createMock(IUser::class);
2080
+        $group = $this->createMock(IGroup::class);
2081
+        $share->setSharedBy('user')->setSharedWith('group');
2082 2082
 
2083
-		$this->userManager->method('get')->with('user')->willReturn($user);
2084
-		$this->groupManager->method('get')->with('group')->willReturn($group);
2083
+        $this->userManager->method('get')->with('user')->willReturn($user);
2084
+        $this->groupManager->method('get')->with('group')->willReturn($group);
2085 2085
 
2086
-		$group->method('inGroup')->with($user)->willReturn(true);
2086
+        $group->method('inGroup')->with($user)->willReturn(true);
2087 2087
 
2088
-		$path = $this->createMock(Node::class);
2089
-		$share->setNode($path);
2088
+        $path = $this->createMock(Node::class);
2089
+        $share->setNode($path);
2090 2090
 
2091
-		$this->defaultProvider->method('getSharesByPath')
2092
-			->with($path)
2093
-			->willReturn([]);
2091
+        $this->defaultProvider->method('getSharesByPath')
2092
+            ->with($path)
2093
+            ->willReturn([]);
2094 2094
 
2095
-		$this->config
2096
-			->method('getAppValue')
2097
-			->willReturnMap([
2098
-				['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2099
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2100
-				['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2101
-			]);
2095
+        $this->config
2096
+            ->method('getAppValue')
2097
+            ->willReturnMap([
2098
+                ['core', 'shareapi_only_share_with_group_members', 'no', 'yes'],
2099
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2100
+                ['core', 'shareapi_only_share_with_group_members_exclude_group_list', '', '[]'],
2101
+            ]);
2102 2102
 
2103
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2104
-		$this->addToAssertionCount(1);
2105
-	}
2103
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2104
+        $this->addToAssertionCount(1);
2105
+    }
2106 2106
 
2107 2107
 
2108
-	public function testGroupCreateChecksPathAlreadySharedWithSameGroup(): void {
2109
-		$this->expectException(\Exception::class);
2110
-		$this->expectExceptionMessage('Path is already shared with this group');
2108
+    public function testGroupCreateChecksPathAlreadySharedWithSameGroup(): void {
2109
+        $this->expectException(\Exception::class);
2110
+        $this->expectExceptionMessage('Path is already shared with this group');
2111 2111
 
2112
-		$share = $this->manager->newShare();
2112
+        $share = $this->manager->newShare();
2113 2113
 
2114
-		$path = $this->createMock(Node::class);
2115
-		$share->setSharedWith('sharedWith')
2116
-			->setNode($path)
2117
-			->setProviderId('foo')
2118
-			->setId('bar');
2114
+        $path = $this->createMock(Node::class);
2115
+        $share->setSharedWith('sharedWith')
2116
+            ->setNode($path)
2117
+            ->setProviderId('foo')
2118
+            ->setId('bar');
2119 2119
 
2120
-		$share2 = $this->manager->newShare();
2121
-		$share2->setSharedWith('sharedWith')
2122
-			->setProviderId('foo')
2123
-			->setId('baz');
2120
+        $share2 = $this->manager->newShare();
2121
+        $share2->setSharedWith('sharedWith')
2122
+            ->setProviderId('foo')
2123
+            ->setId('baz');
2124 2124
 
2125
-		$this->defaultProvider->method('getSharesByPath')
2126
-			->with($path)
2127
-			->willReturn([$share2]);
2125
+        $this->defaultProvider->method('getSharesByPath')
2126
+            ->with($path)
2127
+            ->willReturn([$share2]);
2128 2128
 
2129
-		$this->config
2130
-			->method('getAppValue')
2131
-			->willReturnMap([
2132
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2133
-			]);
2129
+        $this->config
2130
+            ->method('getAppValue')
2131
+            ->willReturnMap([
2132
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2133
+            ]);
2134 2134
 
2135
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2136
-	}
2135
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2136
+    }
2137 2137
 
2138
-	public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup(): void {
2139
-		$share = $this->manager->newShare();
2138
+    public function testGroupCreateChecksPathAlreadySharedWithDifferentGroup(): void {
2139
+        $share = $this->manager->newShare();
2140 2140
 
2141
-		$share->setSharedWith('sharedWith');
2141
+        $share->setSharedWith('sharedWith');
2142 2142
 
2143
-		$path = $this->createMock(Node::class);
2144
-		$share->setNode($path);
2143
+        $path = $this->createMock(Node::class);
2144
+        $share->setNode($path);
2145 2145
 
2146
-		$share2 = $this->manager->newShare();
2147
-		$share2->setSharedWith('sharedWith2');
2146
+        $share2 = $this->manager->newShare();
2147
+        $share2->setSharedWith('sharedWith2');
2148 2148
 
2149
-		$this->defaultProvider->method('getSharesByPath')
2150
-			->with($path)
2151
-			->willReturn([$share2]);
2149
+        $this->defaultProvider->method('getSharesByPath')
2150
+            ->with($path)
2151
+            ->willReturn([$share2]);
2152 2152
 
2153
-		$this->config
2154
-			->method('getAppValue')
2155
-			->willReturnMap([
2156
-				['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2157
-			]);
2153
+        $this->config
2154
+            ->method('getAppValue')
2155
+            ->willReturnMap([
2156
+                ['core', 'shareapi_allow_group_sharing', 'yes', 'yes'],
2157
+            ]);
2158 2158
 
2159
-		self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2160
-		$this->addToAssertionCount(1);
2161
-	}
2159
+        self::invokePrivate($this->manager, 'groupCreateChecks', [$share]);
2160
+        $this->addToAssertionCount(1);
2161
+    }
2162 2162
 
2163 2163
 
2164
-	public function testLinkCreateChecksNoLinkSharesAllowed(): void {
2165
-		$this->expectException(\Exception::class);
2166
-		$this->expectExceptionMessage('Link sharing is not allowed');
2164
+    public function testLinkCreateChecksNoLinkSharesAllowed(): void {
2165
+        $this->expectException(\Exception::class);
2166
+        $this->expectExceptionMessage('Link sharing is not allowed');
2167 2167
 
2168
-		$share = $this->manager->newShare();
2168
+        $share = $this->manager->newShare();
2169 2169
 
2170
-		$this->config
2171
-			->method('getAppValue')
2172
-			->willReturnMap([
2173
-				['core', 'shareapi_allow_links', 'yes', 'no'],
2174
-			]);
2170
+        $this->config
2171
+            ->method('getAppValue')
2172
+            ->willReturnMap([
2173
+                ['core', 'shareapi_allow_links', 'yes', 'no'],
2174
+            ]);
2175 2175
 
2176
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2177
-	}
2176
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2177
+    }
2178 2178
 
2179 2179
 
2180
-	public function testFileLinkCreateChecksNoPublicUpload(): void {
2181
-		$share = $this->manager->newShare();
2180
+    public function testFileLinkCreateChecksNoPublicUpload(): void {
2181
+        $share = $this->manager->newShare();
2182 2182
 
2183
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2184
-		$share->setNodeType('file');
2183
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2184
+        $share->setNodeType('file');
2185 2185
 
2186
-		$this->config
2187
-			->method('getAppValue')
2188
-			->willReturnMap([
2189
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2190
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2191
-			]);
2186
+        $this->config
2187
+            ->method('getAppValue')
2188
+            ->willReturnMap([
2189
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2190
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2191
+            ]);
2192 2192
 
2193
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2194
-		$this->addToAssertionCount(1);
2195
-	}
2193
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2194
+        $this->addToAssertionCount(1);
2195
+    }
2196 2196
 
2197
-	public function testFolderLinkCreateChecksNoPublicUpload(): void {
2198
-		$this->expectException(\Exception::class);
2199
-		$this->expectExceptionMessage('Public upload is not allowed');
2197
+    public function testFolderLinkCreateChecksNoPublicUpload(): void {
2198
+        $this->expectException(\Exception::class);
2199
+        $this->expectExceptionMessage('Public upload is not allowed');
2200 2200
 
2201
-		$share = $this->manager->newShare();
2201
+        $share = $this->manager->newShare();
2202 2202
 
2203
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2204
-		$share->setNodeType('folder');
2203
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2204
+        $share->setNodeType('folder');
2205 2205
 
2206
-		$this->config
2207
-			->method('getAppValue')
2208
-			->willReturnMap([
2209
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2210
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2211
-			]);
2206
+        $this->config
2207
+            ->method('getAppValue')
2208
+            ->willReturnMap([
2209
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2210
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2211
+            ]);
2212 2212
 
2213
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2214
-	}
2213
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2214
+    }
2215 2215
 
2216
-	public function testLinkCreateChecksPublicUpload(): void {
2217
-		$share = $this->manager->newShare();
2216
+    public function testLinkCreateChecksPublicUpload(): void {
2217
+        $share = $this->manager->newShare();
2218 2218
 
2219
-		$share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2220
-		$share->setSharedWith('sharedWith');
2221
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
2222
-		$share->setNode($folder);
2219
+        $share->setPermissions(Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
2220
+        $share->setSharedWith('sharedWith');
2221
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
2222
+        $share->setNode($folder);
2223 2223
 
2224
-		$this->config
2225
-			->method('getAppValue')
2226
-			->willReturnMap([
2227
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2228
-				['core', 'shareapi_allow_public_upload', 'yes', 'yes']
2229
-			]);
2224
+        $this->config
2225
+            ->method('getAppValue')
2226
+            ->willReturnMap([
2227
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2228
+                ['core', 'shareapi_allow_public_upload', 'yes', 'yes']
2229
+            ]);
2230 2230
 
2231
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2232
-		$this->addToAssertionCount(1);
2233
-	}
2231
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2232
+        $this->addToAssertionCount(1);
2233
+    }
2234 2234
 
2235
-	public function testLinkCreateChecksReadOnly(): void {
2236
-		$share = $this->manager->newShare();
2235
+    public function testLinkCreateChecksReadOnly(): void {
2236
+        $share = $this->manager->newShare();
2237 2237
 
2238
-		$share->setPermissions(Constants::PERMISSION_READ);
2239
-		$share->setSharedWith('sharedWith');
2240
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
2241
-		$share->setNode($folder);
2238
+        $share->setPermissions(Constants::PERMISSION_READ);
2239
+        $share->setSharedWith('sharedWith');
2240
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
2241
+        $share->setNode($folder);
2242 2242
 
2243
-		$this->config
2244
-			->method('getAppValue')
2245
-			->willReturnMap([
2246
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
2247
-				['core', 'shareapi_allow_public_upload', 'yes', 'no']
2248
-			]);
2243
+        $this->config
2244
+            ->method('getAppValue')
2245
+            ->willReturnMap([
2246
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
2247
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no']
2248
+            ]);
2249 2249
 
2250
-		self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2251
-		$this->addToAssertionCount(1);
2252
-	}
2253
-
2254
-
2255
-	public function testPathCreateChecksContainsSharedMount(): void {
2256
-		$this->expectException(\InvalidArgumentException::class);
2257
-		$this->expectExceptionMessage('You cannot share a folder that contains other shares');
2250
+        self::invokePrivate($this->manager, 'linkCreateChecks', [$share]);
2251
+        $this->addToAssertionCount(1);
2252
+    }
2253
+
2254
+
2255
+    public function testPathCreateChecksContainsSharedMount(): void {
2256
+        $this->expectException(\InvalidArgumentException::class);
2257
+        $this->expectExceptionMessage('You cannot share a folder that contains other shares');
2258 2258
 
2259
-		$path = $this->createMock(Folder::class);
2260
-		$path->method('getPath')->willReturn('path');
2259
+        $path = $this->createMock(Folder::class);
2260
+        $path->method('getPath')->willReturn('path');
2261 2261
 
2262
-		$mount = $this->createMock(IMountPoint::class);
2263
-		$storage = $this->createMock(IStorage::class);
2264
-		$mount->method('getStorage')->willReturn($storage);
2265
-		$storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(true);
2266
-
2267
-		$this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2268
-
2269
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2270
-	}
2271
-
2272
-	public function testPathCreateChecksContainsNoSharedMount(): void {
2273
-		$path = $this->createMock(Folder::class);
2274
-		$path->method('getPath')->willReturn('path');
2262
+        $mount = $this->createMock(IMountPoint::class);
2263
+        $storage = $this->createMock(IStorage::class);
2264
+        $mount->method('getStorage')->willReturn($storage);
2265
+        $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(true);
2266
+
2267
+        $this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2268
+
2269
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2270
+    }
2271
+
2272
+    public function testPathCreateChecksContainsNoSharedMount(): void {
2273
+        $path = $this->createMock(Folder::class);
2274
+        $path->method('getPath')->willReturn('path');
2275 2275
 
2276
-		$mount = $this->createMock(IMountPoint::class);
2277
-		$storage = $this->createMock(IStorage::class);
2278
-		$mount->method('getStorage')->willReturn($storage);
2279
-		$storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(false);
2280
-
2281
-		$this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2282
-
2283
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2284
-		$this->addToAssertionCount(1);
2285
-	}
2286
-
2287
-	public function testPathCreateChecksContainsNoFolder(): void {
2288
-		$path = $this->createMock(File::class);
2289
-
2290
-		self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2291
-		$this->addToAssertionCount(1);
2292
-	}
2293
-
2294
-	public static function dataIsSharingDisabledForUser() {
2295
-		$data = [];
2296
-
2297
-		// No exclude groups
2298
-		$data[] = ['no', null, null, [], false];
2299
-
2300
-		// empty exclude / allow list, user no groups
2301
-		$data[] = ['yes', '', json_encode(['']), [], false];
2302
-		$data[] = ['allow', '', json_encode(['']), [], true];
2303
-
2304
-		// empty exclude / allow list, user groups
2305
-		$data[] = ['yes', '', json_encode(['']), ['group1', 'group2'], false];
2306
-		$data[] = ['allow', '', json_encode(['']), ['group1', 'group2'], true];
2307
-
2308
-		// Convert old list to json
2309
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), [], false];
2310
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), [], true];
2311
-
2312
-		// Old list partly groups in common
2313
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2314
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2315
-
2316
-		// Old list only groups in common
2317
-		$data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], true];
2318
-		$data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], false];
2319
-
2320
-		// New list partly in common
2321
-		$data[] = ['yes', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2322
-		$data[] = ['allow', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2323
-
2324
-		// New list only groups in common
2325
-		$data[] = ['yes', json_encode(['group1', 'group2']), null, ['group2'], true];
2326
-		$data[] = ['allow', json_encode(['group1', 'group2']), null, ['group2'], false];
2327
-
2328
-		return $data;
2329
-	}
2276
+        $mount = $this->createMock(IMountPoint::class);
2277
+        $storage = $this->createMock(IStorage::class);
2278
+        $mount->method('getStorage')->willReturn($storage);
2279
+        $storage->method('instanceOfStorage')->with('\OCA\Files_Sharing\ISharedStorage')->willReturn(false);
2280
+
2281
+        $this->mountManager->method('findIn')->with('path')->willReturn([$mount]);
2282
+
2283
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2284
+        $this->addToAssertionCount(1);
2285
+    }
2286
+
2287
+    public function testPathCreateChecksContainsNoFolder(): void {
2288
+        $path = $this->createMock(File::class);
2289
+
2290
+        self::invokePrivate($this->manager, 'pathCreateChecks', [$path]);
2291
+        $this->addToAssertionCount(1);
2292
+    }
2293
+
2294
+    public static function dataIsSharingDisabledForUser() {
2295
+        $data = [];
2296
+
2297
+        // No exclude groups
2298
+        $data[] = ['no', null, null, [], false];
2299
+
2300
+        // empty exclude / allow list, user no groups
2301
+        $data[] = ['yes', '', json_encode(['']), [], false];
2302
+        $data[] = ['allow', '', json_encode(['']), [], true];
2303
+
2304
+        // empty exclude / allow list, user groups
2305
+        $data[] = ['yes', '', json_encode(['']), ['group1', 'group2'], false];
2306
+        $data[] = ['allow', '', json_encode(['']), ['group1', 'group2'], true];
2307
+
2308
+        // Convert old list to json
2309
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), [], false];
2310
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), [], true];
2311
+
2312
+        // Old list partly groups in common
2313
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2314
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1', 'group3'], false];
2315
+
2316
+        // Old list only groups in common
2317
+        $data[] = ['yes', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], true];
2318
+        $data[] = ['allow', 'group1,group2', json_encode(['group1', 'group2']), ['group1'], false];
2319
+
2320
+        // New list partly in common
2321
+        $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2322
+        $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group1', 'group3'], false];
2323
+
2324
+        // New list only groups in common
2325
+        $data[] = ['yes', json_encode(['group1', 'group2']), null, ['group2'], true];
2326
+        $data[] = ['allow', json_encode(['group1', 'group2']), null, ['group2'], false];
2327
+
2328
+        return $data;
2329
+    }
2330 2330
 
2331
-	/**
2332
-	 *
2333
-	 * @param string $excludeGroups
2334
-	 * @param string $groupList
2335
-	 * @param string $setList
2336
-	 * @param string[] $groupIds
2337
-	 * @param bool $expected
2338
-	 */
2339
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataIsSharingDisabledForUser')]
2340
-	public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected): void {
2341
-		$user = $this->createMock(IUser::class);
2331
+    /**
2332
+     *
2333
+     * @param string $excludeGroups
2334
+     * @param string $groupList
2335
+     * @param string $setList
2336
+     * @param string[] $groupIds
2337
+     * @param bool $expected
2338
+     */
2339
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataIsSharingDisabledForUser')]
2340
+    public function testIsSharingDisabledForUser($excludeGroups, $groupList, $setList, $groupIds, $expected): void {
2341
+        $user = $this->createMock(IUser::class);
2342 2342
 
2343
-		$this->config->method('getAppValue')
2344
-			->willReturnMap([
2345
-				['core', 'shareapi_exclude_groups', 'no', $excludeGroups],
2346
-				['core', 'shareapi_exclude_groups_list', '', $groupList],
2347
-			]);
2343
+        $this->config->method('getAppValue')
2344
+            ->willReturnMap([
2345
+                ['core', 'shareapi_exclude_groups', 'no', $excludeGroups],
2346
+                ['core', 'shareapi_exclude_groups_list', '', $groupList],
2347
+            ]);
2348 2348
 
2349
-		if ($setList !== null) {
2350
-			$this->config->expects($this->once())
2351
-				->method('setAppValue')
2352
-				->with('core', 'shareapi_exclude_groups_list', $setList);
2353
-		} else {
2354
-			$this->config->expects($this->never())
2355
-				->method('setAppValue');
2356
-		}
2349
+        if ($setList !== null) {
2350
+            $this->config->expects($this->once())
2351
+                ->method('setAppValue')
2352
+                ->with('core', 'shareapi_exclude_groups_list', $setList);
2353
+        } else {
2354
+            $this->config->expects($this->never())
2355
+                ->method('setAppValue');
2356
+        }
2357 2357
 
2358
-		$this->groupManager->method('getUserGroupIds')
2359
-			->with($user)
2360
-			->willReturn($groupIds);
2358
+        $this->groupManager->method('getUserGroupIds')
2359
+            ->with($user)
2360
+            ->willReturn($groupIds);
2361 2361
 
2362
-		$this->userManager->method('get')->with('user')->willReturn($user);
2363
-
2364
-		$res = $this->manager->sharingDisabledForUser('user');
2365
-		$this->assertEquals($expected, $res);
2366
-	}
2367
-
2368
-	public static function dataCanShare() {
2369
-		$data = [];
2370
-
2371
-		/*
2362
+        $this->userManager->method('get')->with('user')->willReturn($user);
2363
+
2364
+        $res = $this->manager->sharingDisabledForUser('user');
2365
+        $this->assertEquals($expected, $res);
2366
+    }
2367
+
2368
+    public static function dataCanShare() {
2369
+        $data = [];
2370
+
2371
+        /*
2372 2372
 		 * [expected, sharing enabled, disabled for user]
2373 2373
 		 */
2374 2374
 
2375
-		$data[] = [false, 'no', false];
2376
-		$data[] = [false, 'no', true];
2377
-		$data[] = [true, 'yes', false];
2378
-		$data[] = [false, 'yes', true];
2379
-
2380
-		return $data;
2381
-	}
2382
-
2383
-	/**
2384
-	 *
2385
-	 * @param bool $expected
2386
-	 * @param string $sharingEnabled
2387
-	 * @param bool $disabledForUser
2388
-	 */
2389
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataCanShare')]
2390
-	public function testCanShare($expected, $sharingEnabled, $disabledForUser): void {
2391
-		$this->config->method('getAppValue')
2392
-			->willReturnMap([
2393
-				['core', 'shareapi_enabled', 'yes', $sharingEnabled],
2394
-			]);
2395
-
2396
-		$manager = $this->createManagerMock()
2397
-			->onlyMethods(['sharingDisabledForUser'])
2398
-			->getMock();
2399
-
2400
-		$manager->method('sharingDisabledForUser')
2401
-			->with('user')
2402
-			->willReturn($disabledForUser);
2403
-
2404
-		$share = $this->manager->newShare();
2405
-		$share->setSharedBy('user');
2406
-
2407
-		$exception = false;
2408
-		try {
2409
-			$res = self::invokePrivate($manager, 'canShare', [$share]);
2410
-		} catch (\Exception $e) {
2411
-			$exception = true;
2412
-		}
2413
-
2414
-		$this->assertEquals($expected, !$exception);
2415
-	}
2416
-
2417
-	public function testCreateShareUser(): void {
2418
-		/** @var Manager&MockObject $manager */
2419
-		$manager = $this->createManagerMock()
2420
-			->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2421
-			->getMock();
2422
-
2423
-		$shareOwner = $this->createMock(IUser::class);
2424
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2425
-
2426
-		$storage = $this->createMock(IStorage::class);
2427
-		$path = $this->createMock(File::class);
2428
-		$path->method('getOwner')->willReturn($shareOwner);
2429
-		$path->method('getName')->willReturn('target');
2430
-		$path->method('getStorage')->willReturn($storage);
2431
-
2432
-		$share = $this->createShare(
2433
-			null,
2434
-			IShare::TYPE_USER,
2435
-			$path,
2436
-			'sharedWith',
2437
-			'sharedBy',
2438
-			null,
2439
-			Constants::PERMISSION_ALL);
2440
-
2441
-		$manager->expects($this->once())
2442
-			->method('canShare')
2443
-			->with($share)
2444
-			->willReturn(true);
2445
-		$manager->expects($this->once())
2446
-			->method('generalCreateChecks')
2447
-			->with($share);
2448
-		;
2449
-		$manager->expects($this->once())
2450
-			->method('userCreateChecks')
2451
-			->with($share);
2452
-		;
2453
-		$manager->expects($this->once())
2454
-			->method('pathCreateChecks')
2455
-			->with($path);
2456
-
2457
-		$this->defaultProvider
2458
-			->expects($this->once())
2459
-			->method('create')
2460
-			->with($share)
2461
-			->willReturnArgument(0);
2462
-
2463
-		$share->expects($this->once())
2464
-			->method('setShareOwner')
2465
-			->with('shareOwner');
2466
-		$share->expects($this->once())
2467
-			->method('setTarget')
2468
-			->with('/target');
2469
-
2470
-		$manager->createShare($share);
2471
-	}
2472
-
2473
-	public function testCreateShareGroup(): void {
2474
-		$manager = $this->createManagerMock()
2475
-			->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
2476
-			->getMock();
2477
-
2478
-		$shareOwner = $this->createMock(IUser::class);
2479
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2480
-
2481
-		$storage = $this->createMock(IStorage::class);
2482
-		$path = $this->createMock(File::class);
2483
-		$path->method('getOwner')->willReturn($shareOwner);
2484
-		$path->method('getName')->willReturn('target');
2485
-		$path->method('getStorage')->willReturn($storage);
2486
-
2487
-		$share = $this->createShare(
2488
-			null,
2489
-			IShare::TYPE_GROUP,
2490
-			$path,
2491
-			'sharedWith',
2492
-			'sharedBy',
2493
-			null,
2494
-			Constants::PERMISSION_ALL);
2495
-
2496
-		$manager->expects($this->once())
2497
-			->method('canShare')
2498
-			->with($share)
2499
-			->willReturn(true);
2500
-		$manager->expects($this->once())
2501
-			->method('generalCreateChecks')
2502
-			->with($share);
2503
-		;
2504
-		$manager->expects($this->once())
2505
-			->method('groupCreateChecks')
2506
-			->with($share);
2507
-		;
2508
-		$manager->expects($this->once())
2509
-			->method('pathCreateChecks')
2510
-			->with($path);
2511
-
2512
-		$this->defaultProvider
2513
-			->expects($this->once())
2514
-			->method('create')
2515
-			->with($share)
2516
-			->willReturnArgument(0);
2517
-
2518
-		$share->expects($this->once())
2519
-			->method('setShareOwner')
2520
-			->with('shareOwner');
2521
-		$share->expects($this->once())
2522
-			->method('setTarget')
2523
-			->with('/target');
2524
-
2525
-		$manager->createShare($share);
2526
-	}
2527
-
2528
-	public function testCreateShareLink(): void {
2529
-		$manager = $this->createManagerMock()
2530
-			->onlyMethods([
2531
-				'canShare',
2532
-				'generalCreateChecks',
2533
-				'linkCreateChecks',
2534
-				'pathCreateChecks',
2535
-				'validateExpirationDateLink',
2536
-				'verifyPassword',
2537
-				'setLinkParent',
2538
-			])
2539
-			->getMock();
2540
-
2541
-		$shareOwner = $this->createMock(IUser::class);
2542
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2543
-
2544
-		$storage = $this->createMock(IStorage::class);
2545
-		$path = $this->createMock(File::class);
2546
-		$path->method('getOwner')->willReturn($shareOwner);
2547
-		$path->method('getName')->willReturn('target');
2548
-		$path->method('getId')->willReturn(1);
2549
-		$path->method('getStorage')->willReturn($storage);
2550
-
2551
-		$date = new \DateTime();
2552
-
2553
-		$share = $this->manager->newShare();
2554
-		$share->setShareType(IShare::TYPE_LINK)
2555
-			->setNode($path)
2556
-			->setSharedBy('sharedBy')
2557
-			->setPermissions(Constants::PERMISSION_ALL)
2558
-			->setExpirationDate($date)
2559
-			->setPassword('password');
2560
-
2561
-		$manager->expects($this->once())
2562
-			->method('canShare')
2563
-			->with($share)
2564
-			->willReturn(true);
2565
-		$manager->expects($this->once())
2566
-			->method('generalCreateChecks')
2567
-			->with($share);
2568
-		;
2569
-		$manager->expects($this->once())
2570
-			->method('linkCreateChecks')
2571
-			->with($share);
2572
-		;
2573
-		$manager->expects($this->once())
2574
-			->method('pathCreateChecks')
2575
-			->with($path);
2576
-		$manager->expects($this->once())
2577
-			->method('validateExpirationDateLink')
2578
-			->with($share)
2579
-			->willReturn($share);
2580
-		$manager->expects($this->once())
2581
-			->method('verifyPassword')
2582
-			->with('password');
2583
-		$manager->expects($this->once())
2584
-			->method('setLinkParent')
2585
-			->with($share);
2586
-
2587
-		$this->hasher->expects($this->once())
2588
-			->method('hash')
2589
-			->with('password')
2590
-			->willReturn('hashed');
2591
-
2592
-		$this->secureRandom->method('generate')
2593
-			->willReturn('token');
2594
-
2595
-		$this->defaultProvider
2596
-			->expects($this->once())
2597
-			->method('create')
2598
-			->with($share)
2599
-			->willReturnCallback(function (Share $share) {
2600
-				return $share->setId(42);
2601
-			});
2602
-
2603
-		$calls = [
2604
-			BeforeShareCreatedEvent::class,
2605
-			ShareCreatedEvent::class,
2606
-		];
2607
-		$this->dispatcher->expects($this->exactly(2))
2608
-			->method('dispatchTyped')
2609
-			->willReturnCallback(function ($event) use (&$calls, $date, $path): void {
2610
-				$expected = array_shift($calls);
2611
-				$this->assertInstanceOf($expected, $event);
2612
-				$share = $event->getShare();
2613
-
2614
-				$this->assertEquals(IShare::TYPE_LINK, $share->getShareType(), 'getShareType');
2615
-				$this->assertEquals($path, $share->getNode(), 'getNode');
2616
-				$this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2617
-				$this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2618
-				$this->assertEquals($date, $share->getExpirationDate(), 'getExpirationDate');
2619
-				$this->assertEquals('hashed', $share->getPassword(), 'getPassword');
2620
-				$this->assertEquals('token', $share->getToken(), 'getToken');
2621
-
2622
-				if ($expected === ShareCreatedEvent::class) {
2623
-					$this->assertEquals('42', $share->getId(), 'getId');
2624
-					$this->assertEquals('/target', $share->getTarget(), 'getTarget');
2625
-				}
2626
-			});
2627
-
2628
-		/** @var IShare $share */
2629
-		$share = $manager->createShare($share);
2630
-
2631
-		$this->assertSame('shareOwner', $share->getShareOwner());
2632
-		$this->assertEquals('/target', $share->getTarget());
2633
-		$this->assertSame($date, $share->getExpirationDate());
2634
-		$this->assertEquals('token', $share->getToken());
2635
-		$this->assertEquals('hashed', $share->getPassword());
2636
-	}
2637
-
2638
-	public function testCreateShareMail(): void {
2639
-		$manager = $this->createManagerMock()
2640
-			->onlyMethods([
2641
-				'canShare',
2642
-				'generalCreateChecks',
2643
-				'linkCreateChecks',
2644
-				'pathCreateChecks',
2645
-				'validateExpirationDateLink',
2646
-				'verifyPassword',
2647
-				'setLinkParent',
2648
-			])
2649
-			->getMock();
2650
-
2651
-		$shareOwner = $this->createMock(IUser::class);
2652
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2653
-
2654
-		$storage = $this->createMock(IStorage::class);
2655
-		$path = $this->createMock(File::class);
2656
-		$path->method('getOwner')->willReturn($shareOwner);
2657
-		$path->method('getName')->willReturn('target');
2658
-		$path->method('getId')->willReturn(1);
2659
-		$path->method('getStorage')->willReturn($storage);
2660
-
2661
-		$share = $this->manager->newShare();
2662
-		$share->setShareType(IShare::TYPE_EMAIL)
2663
-			->setNode($path)
2664
-			->setSharedBy('sharedBy')
2665
-			->setPermissions(Constants::PERMISSION_ALL);
2666
-
2667
-		$manager->expects($this->once())
2668
-			->method('canShare')
2669
-			->with($share)
2670
-			->willReturn(true);
2671
-		$manager->expects($this->once())
2672
-			->method('generalCreateChecks')
2673
-			->with($share);
2674
-
2675
-		$manager->expects($this->once())
2676
-			->method('linkCreateChecks');
2677
-		$manager->expects($this->once())
2678
-			->method('pathCreateChecks')
2679
-			->with($path);
2680
-		$manager->expects($this->once())
2681
-			->method('validateExpirationDateLink')
2682
-			->with($share)
2683
-			->willReturn($share);
2684
-		$manager->expects($this->once())
2685
-			->method('verifyPassword');
2686
-		$manager->expects($this->once())
2687
-			->method('setLinkParent');
2688
-
2689
-		$this->secureRandom->method('generate')
2690
-			->willReturn('token');
2691
-
2692
-		$this->defaultProvider
2693
-			->expects($this->once())
2694
-			->method('create')
2695
-			->with($share)
2696
-			->willReturnCallback(function (Share $share) {
2697
-				return $share->setId(42);
2698
-			});
2699
-
2700
-		$calls = [
2701
-			BeforeShareCreatedEvent::class,
2702
-			ShareCreatedEvent::class,
2703
-		];
2704
-		$this->dispatcher->expects($this->exactly(2))
2705
-			->method('dispatchTyped')
2706
-			->willReturnCallback(function ($event) use (&$calls, $path): void {
2707
-				$expected = array_shift($calls);
2708
-				$this->assertInstanceOf($expected, $event);
2709
-				$share = $event->getShare();
2710
-
2711
-				$this->assertEquals(IShare::TYPE_EMAIL, $share->getShareType(), 'getShareType');
2712
-				$this->assertEquals($path, $share->getNode(), 'getNode');
2713
-				$this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2714
-				$this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2715
-				$this->assertNull($share->getExpirationDate(), 'getExpirationDate');
2716
-				$this->assertNull($share->getPassword(), 'getPassword');
2717
-				$this->assertEquals('token', $share->getToken(), 'getToken');
2718
-
2719
-				if ($expected === ShareCreatedEvent::class) {
2720
-					$this->assertEquals('42', $share->getId(), 'getId');
2721
-					$this->assertEquals('/target', $share->getTarget(), 'getTarget');
2722
-				}
2723
-			});
2724
-
2725
-		/** @var IShare $share */
2726
-		$share = $manager->createShare($share);
2727
-
2728
-		$this->assertSame('shareOwner', $share->getShareOwner());
2729
-		$this->assertEquals('/target', $share->getTarget());
2730
-		$this->assertEquals('token', $share->getToken());
2731
-	}
2732
-
2733
-
2734
-	public function testCreateShareHookError(): void {
2735
-		$this->expectException(\Exception::class);
2736
-		$this->expectExceptionMessage('I won\'t let you share');
2737
-
2738
-		$manager = $this->createManagerMock()
2739
-			->onlyMethods([
2740
-				'canShare',
2741
-				'generalCreateChecks',
2742
-				'userCreateChecks',
2743
-				'pathCreateChecks',
2744
-			])
2745
-			->getMock();
2746
-
2747
-		$shareOwner = $this->createMock(IUser::class);
2748
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2749
-
2750
-		$storage = $this->createMock(IStorage::class);
2751
-		$path = $this->createMock(File::class);
2752
-		$path->method('getOwner')->willReturn($shareOwner);
2753
-		$path->method('getName')->willReturn('target');
2754
-		$path->method('getStorage')->willReturn($storage);
2755
-
2756
-		$share = $this->createShare(
2757
-			null,
2758
-			IShare::TYPE_USER,
2759
-			$path,
2760
-			'sharedWith',
2761
-			'sharedBy',
2762
-			null,
2763
-			Constants::PERMISSION_ALL);
2764
-
2765
-		$manager->expects($this->once())
2766
-			->method('canShare')
2767
-			->with($share)
2768
-			->willReturn(true);
2769
-		$manager->expects($this->once())
2770
-			->method('generalCreateChecks')
2771
-			->with($share);
2772
-		;
2773
-		$manager->expects($this->once())
2774
-			->method('userCreateChecks')
2775
-			->with($share);
2776
-		;
2777
-		$manager->expects($this->once())
2778
-			->method('pathCreateChecks')
2779
-			->with($path);
2780
-
2781
-		$share->expects($this->once())
2782
-			->method('setShareOwner')
2783
-			->with('shareOwner');
2784
-		$share->expects($this->once())
2785
-			->method('setTarget')
2786
-			->with('/target');
2787
-
2788
-		// Pre share
2789
-		$this->dispatcher->expects($this->once())
2790
-			->method('dispatchTyped')
2791
-			->with(
2792
-				$this->isInstanceOf(BeforeShareCreatedEvent::class)
2793
-			)->willReturnCallback(function (BeforeShareCreatedEvent $e): void {
2794
-				$e->setError('I won\'t let you share!');
2795
-				$e->stopPropagation();
2796
-			}
2797
-			);
2798
-
2799
-		$manager->createShare($share);
2800
-	}
2801
-
2802
-	public function testCreateShareOfIncomingFederatedShare(): void {
2803
-		$manager = $this->createManagerMock()
2804
-			->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2805
-			->getMock();
2806
-
2807
-		$shareOwner = $this->createMock(IUser::class);
2808
-		$shareOwner->method('getUID')->willReturn('shareOwner');
2809
-
2810
-		$storage = $this->createMock(IStorage::class);
2811
-		$storage->method('instanceOfStorage')
2812
-			->with('OCA\Files_Sharing\External\Storage')
2813
-			->willReturn(true);
2814
-
2815
-		$storage2 = $this->createMock(IStorage::class);
2816
-		$storage2->method('instanceOfStorage')
2817
-			->with('OCA\Files_Sharing\External\Storage')
2818
-			->willReturn(false);
2819
-
2820
-		$path = $this->createMock(File::class);
2821
-		$path->expects($this->never())->method('getOwner');
2822
-		$path->method('getName')->willReturn('target');
2823
-		$path->method('getStorage')->willReturn($storage);
2824
-
2825
-		$parent = $this->createMock(Folder::class);
2826
-		$parent->method('getStorage')->willReturn($storage);
2827
-
2828
-		$parentParent = $this->createMock(Folder::class);
2829
-		$parentParent->method('getStorage')->willReturn($storage2);
2830
-		$parentParent->method('getOwner')->willReturn($shareOwner);
2831
-
2832
-		$path->method('getParent')->willReturn($parent);
2833
-		$parent->method('getParent')->willReturn($parentParent);
2834
-
2835
-		$share = $this->createShare(
2836
-			null,
2837
-			IShare::TYPE_USER,
2838
-			$path,
2839
-			'sharedWith',
2840
-			'sharedBy',
2841
-			null,
2842
-			Constants::PERMISSION_ALL);
2843
-
2844
-		$manager->expects($this->once())
2845
-			->method('canShare')
2846
-			->with($share)
2847
-			->willReturn(true);
2848
-		$manager->expects($this->once())
2849
-			->method('generalCreateChecks')
2850
-			->with($share);
2851
-		;
2852
-		$manager->expects($this->once())
2853
-			->method('userCreateChecks')
2854
-			->with($share);
2855
-		;
2856
-		$manager->expects($this->once())
2857
-			->method('pathCreateChecks')
2858
-			->with($path);
2859
-
2860
-		$this->defaultProvider
2861
-			->expects($this->once())
2862
-			->method('create')
2863
-			->with($share)
2864
-			->willReturnArgument(0);
2865
-
2866
-		$share->expects($this->once())
2867
-			->method('setShareOwner')
2868
-			->with('shareOwner');
2869
-		$share->expects($this->once())
2870
-			->method('setTarget')
2871
-			->with('/target');
2872
-
2873
-		$manager->createShare($share);
2874
-	}
2875
-
2876
-	public function testGetSharesBy(): void {
2877
-		$share = $this->manager->newShare();
2878
-
2879
-		$node = $this->createMock(Folder::class);
2880
-
2881
-		$this->defaultProvider->expects($this->once())
2882
-			->method('getSharesBy')
2883
-			->with(
2884
-				$this->equalTo('user'),
2885
-				$this->equalTo(IShare::TYPE_USER),
2886
-				$this->equalTo($node),
2887
-				$this->equalTo(true),
2888
-				$this->equalTo(1),
2889
-				$this->equalTo(1)
2890
-			)->willReturn([$share]);
2891
-
2892
-		$shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2893
-
2894
-		$this->assertCount(1, $shares);
2895
-		$this->assertSame($share, $shares[0]);
2896
-	}
2897
-
2898
-	public function testGetSharesByOwnerless(): void {
2899
-		$mount = $this->createMock(IShareOwnerlessMount::class);
2900
-
2901
-		$node = $this->createMock(Folder::class);
2902
-		$node
2903
-			->expects($this->once())
2904
-			->method('getMountPoint')
2905
-			->willReturn($mount);
2906
-
2907
-		$share = $this->manager->newShare();
2908
-		$share->setNode($node);
2909
-		$share->setShareType(IShare::TYPE_USER);
2910
-
2911
-		$this->defaultProvider
2912
-			->expects($this->once())
2913
-			->method('getSharesByPath')
2914
-			->with($this->equalTo($node))
2915
-			->willReturn([$share]);
2916
-
2917
-		$shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2918
-
2919
-		$this->assertCount(1, $shares);
2920
-		$this->assertSame($share, $shares[0]);
2921
-	}
2922
-
2923
-	/**
2924
-	 * Test to ensure we correctly remove expired link shares
2925
-	 *
2926
-	 * We have 8 Shares and we want the 3 first valid shares.
2927
-	 * share 3-6 and 8 are expired. Thus at the end of this test we should
2928
-	 * have received share 1,2 and 7. And from the manager. Share 3-6 should be
2929
-	 * deleted (as they are evaluated). but share 8 should still be there.
2930
-	 */
2931
-	public function testGetSharesByExpiredLinkShares(): void {
2932
-		$manager = $this->createManagerMock()
2933
-			->onlyMethods(['deleteShare'])
2934
-			->getMock();
2935
-
2936
-		/** @var IShare[] $shares */
2937
-		$shares = [];
2938
-
2939
-		/*
2375
+        $data[] = [false, 'no', false];
2376
+        $data[] = [false, 'no', true];
2377
+        $data[] = [true, 'yes', false];
2378
+        $data[] = [false, 'yes', true];
2379
+
2380
+        return $data;
2381
+    }
2382
+
2383
+    /**
2384
+     *
2385
+     * @param bool $expected
2386
+     * @param string $sharingEnabled
2387
+     * @param bool $disabledForUser
2388
+     */
2389
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataCanShare')]
2390
+    public function testCanShare($expected, $sharingEnabled, $disabledForUser): void {
2391
+        $this->config->method('getAppValue')
2392
+            ->willReturnMap([
2393
+                ['core', 'shareapi_enabled', 'yes', $sharingEnabled],
2394
+            ]);
2395
+
2396
+        $manager = $this->createManagerMock()
2397
+            ->onlyMethods(['sharingDisabledForUser'])
2398
+            ->getMock();
2399
+
2400
+        $manager->method('sharingDisabledForUser')
2401
+            ->with('user')
2402
+            ->willReturn($disabledForUser);
2403
+
2404
+        $share = $this->manager->newShare();
2405
+        $share->setSharedBy('user');
2406
+
2407
+        $exception = false;
2408
+        try {
2409
+            $res = self::invokePrivate($manager, 'canShare', [$share]);
2410
+        } catch (\Exception $e) {
2411
+            $exception = true;
2412
+        }
2413
+
2414
+        $this->assertEquals($expected, !$exception);
2415
+    }
2416
+
2417
+    public function testCreateShareUser(): void {
2418
+        /** @var Manager&MockObject $manager */
2419
+        $manager = $this->createManagerMock()
2420
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2421
+            ->getMock();
2422
+
2423
+        $shareOwner = $this->createMock(IUser::class);
2424
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2425
+
2426
+        $storage = $this->createMock(IStorage::class);
2427
+        $path = $this->createMock(File::class);
2428
+        $path->method('getOwner')->willReturn($shareOwner);
2429
+        $path->method('getName')->willReturn('target');
2430
+        $path->method('getStorage')->willReturn($storage);
2431
+
2432
+        $share = $this->createShare(
2433
+            null,
2434
+            IShare::TYPE_USER,
2435
+            $path,
2436
+            'sharedWith',
2437
+            'sharedBy',
2438
+            null,
2439
+            Constants::PERMISSION_ALL);
2440
+
2441
+        $manager->expects($this->once())
2442
+            ->method('canShare')
2443
+            ->with($share)
2444
+            ->willReturn(true);
2445
+        $manager->expects($this->once())
2446
+            ->method('generalCreateChecks')
2447
+            ->with($share);
2448
+        ;
2449
+        $manager->expects($this->once())
2450
+            ->method('userCreateChecks')
2451
+            ->with($share);
2452
+        ;
2453
+        $manager->expects($this->once())
2454
+            ->method('pathCreateChecks')
2455
+            ->with($path);
2456
+
2457
+        $this->defaultProvider
2458
+            ->expects($this->once())
2459
+            ->method('create')
2460
+            ->with($share)
2461
+            ->willReturnArgument(0);
2462
+
2463
+        $share->expects($this->once())
2464
+            ->method('setShareOwner')
2465
+            ->with('shareOwner');
2466
+        $share->expects($this->once())
2467
+            ->method('setTarget')
2468
+            ->with('/target');
2469
+
2470
+        $manager->createShare($share);
2471
+    }
2472
+
2473
+    public function testCreateShareGroup(): void {
2474
+        $manager = $this->createManagerMock()
2475
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'groupCreateChecks', 'pathCreateChecks'])
2476
+            ->getMock();
2477
+
2478
+        $shareOwner = $this->createMock(IUser::class);
2479
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2480
+
2481
+        $storage = $this->createMock(IStorage::class);
2482
+        $path = $this->createMock(File::class);
2483
+        $path->method('getOwner')->willReturn($shareOwner);
2484
+        $path->method('getName')->willReturn('target');
2485
+        $path->method('getStorage')->willReturn($storage);
2486
+
2487
+        $share = $this->createShare(
2488
+            null,
2489
+            IShare::TYPE_GROUP,
2490
+            $path,
2491
+            'sharedWith',
2492
+            'sharedBy',
2493
+            null,
2494
+            Constants::PERMISSION_ALL);
2495
+
2496
+        $manager->expects($this->once())
2497
+            ->method('canShare')
2498
+            ->with($share)
2499
+            ->willReturn(true);
2500
+        $manager->expects($this->once())
2501
+            ->method('generalCreateChecks')
2502
+            ->with($share);
2503
+        ;
2504
+        $manager->expects($this->once())
2505
+            ->method('groupCreateChecks')
2506
+            ->with($share);
2507
+        ;
2508
+        $manager->expects($this->once())
2509
+            ->method('pathCreateChecks')
2510
+            ->with($path);
2511
+
2512
+        $this->defaultProvider
2513
+            ->expects($this->once())
2514
+            ->method('create')
2515
+            ->with($share)
2516
+            ->willReturnArgument(0);
2517
+
2518
+        $share->expects($this->once())
2519
+            ->method('setShareOwner')
2520
+            ->with('shareOwner');
2521
+        $share->expects($this->once())
2522
+            ->method('setTarget')
2523
+            ->with('/target');
2524
+
2525
+        $manager->createShare($share);
2526
+    }
2527
+
2528
+    public function testCreateShareLink(): void {
2529
+        $manager = $this->createManagerMock()
2530
+            ->onlyMethods([
2531
+                'canShare',
2532
+                'generalCreateChecks',
2533
+                'linkCreateChecks',
2534
+                'pathCreateChecks',
2535
+                'validateExpirationDateLink',
2536
+                'verifyPassword',
2537
+                'setLinkParent',
2538
+            ])
2539
+            ->getMock();
2540
+
2541
+        $shareOwner = $this->createMock(IUser::class);
2542
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2543
+
2544
+        $storage = $this->createMock(IStorage::class);
2545
+        $path = $this->createMock(File::class);
2546
+        $path->method('getOwner')->willReturn($shareOwner);
2547
+        $path->method('getName')->willReturn('target');
2548
+        $path->method('getId')->willReturn(1);
2549
+        $path->method('getStorage')->willReturn($storage);
2550
+
2551
+        $date = new \DateTime();
2552
+
2553
+        $share = $this->manager->newShare();
2554
+        $share->setShareType(IShare::TYPE_LINK)
2555
+            ->setNode($path)
2556
+            ->setSharedBy('sharedBy')
2557
+            ->setPermissions(Constants::PERMISSION_ALL)
2558
+            ->setExpirationDate($date)
2559
+            ->setPassword('password');
2560
+
2561
+        $manager->expects($this->once())
2562
+            ->method('canShare')
2563
+            ->with($share)
2564
+            ->willReturn(true);
2565
+        $manager->expects($this->once())
2566
+            ->method('generalCreateChecks')
2567
+            ->with($share);
2568
+        ;
2569
+        $manager->expects($this->once())
2570
+            ->method('linkCreateChecks')
2571
+            ->with($share);
2572
+        ;
2573
+        $manager->expects($this->once())
2574
+            ->method('pathCreateChecks')
2575
+            ->with($path);
2576
+        $manager->expects($this->once())
2577
+            ->method('validateExpirationDateLink')
2578
+            ->with($share)
2579
+            ->willReturn($share);
2580
+        $manager->expects($this->once())
2581
+            ->method('verifyPassword')
2582
+            ->with('password');
2583
+        $manager->expects($this->once())
2584
+            ->method('setLinkParent')
2585
+            ->with($share);
2586
+
2587
+        $this->hasher->expects($this->once())
2588
+            ->method('hash')
2589
+            ->with('password')
2590
+            ->willReturn('hashed');
2591
+
2592
+        $this->secureRandom->method('generate')
2593
+            ->willReturn('token');
2594
+
2595
+        $this->defaultProvider
2596
+            ->expects($this->once())
2597
+            ->method('create')
2598
+            ->with($share)
2599
+            ->willReturnCallback(function (Share $share) {
2600
+                return $share->setId(42);
2601
+            });
2602
+
2603
+        $calls = [
2604
+            BeforeShareCreatedEvent::class,
2605
+            ShareCreatedEvent::class,
2606
+        ];
2607
+        $this->dispatcher->expects($this->exactly(2))
2608
+            ->method('dispatchTyped')
2609
+            ->willReturnCallback(function ($event) use (&$calls, $date, $path): void {
2610
+                $expected = array_shift($calls);
2611
+                $this->assertInstanceOf($expected, $event);
2612
+                $share = $event->getShare();
2613
+
2614
+                $this->assertEquals(IShare::TYPE_LINK, $share->getShareType(), 'getShareType');
2615
+                $this->assertEquals($path, $share->getNode(), 'getNode');
2616
+                $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2617
+                $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2618
+                $this->assertEquals($date, $share->getExpirationDate(), 'getExpirationDate');
2619
+                $this->assertEquals('hashed', $share->getPassword(), 'getPassword');
2620
+                $this->assertEquals('token', $share->getToken(), 'getToken');
2621
+
2622
+                if ($expected === ShareCreatedEvent::class) {
2623
+                    $this->assertEquals('42', $share->getId(), 'getId');
2624
+                    $this->assertEquals('/target', $share->getTarget(), 'getTarget');
2625
+                }
2626
+            });
2627
+
2628
+        /** @var IShare $share */
2629
+        $share = $manager->createShare($share);
2630
+
2631
+        $this->assertSame('shareOwner', $share->getShareOwner());
2632
+        $this->assertEquals('/target', $share->getTarget());
2633
+        $this->assertSame($date, $share->getExpirationDate());
2634
+        $this->assertEquals('token', $share->getToken());
2635
+        $this->assertEquals('hashed', $share->getPassword());
2636
+    }
2637
+
2638
+    public function testCreateShareMail(): void {
2639
+        $manager = $this->createManagerMock()
2640
+            ->onlyMethods([
2641
+                'canShare',
2642
+                'generalCreateChecks',
2643
+                'linkCreateChecks',
2644
+                'pathCreateChecks',
2645
+                'validateExpirationDateLink',
2646
+                'verifyPassword',
2647
+                'setLinkParent',
2648
+            ])
2649
+            ->getMock();
2650
+
2651
+        $shareOwner = $this->createMock(IUser::class);
2652
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2653
+
2654
+        $storage = $this->createMock(IStorage::class);
2655
+        $path = $this->createMock(File::class);
2656
+        $path->method('getOwner')->willReturn($shareOwner);
2657
+        $path->method('getName')->willReturn('target');
2658
+        $path->method('getId')->willReturn(1);
2659
+        $path->method('getStorage')->willReturn($storage);
2660
+
2661
+        $share = $this->manager->newShare();
2662
+        $share->setShareType(IShare::TYPE_EMAIL)
2663
+            ->setNode($path)
2664
+            ->setSharedBy('sharedBy')
2665
+            ->setPermissions(Constants::PERMISSION_ALL);
2666
+
2667
+        $manager->expects($this->once())
2668
+            ->method('canShare')
2669
+            ->with($share)
2670
+            ->willReturn(true);
2671
+        $manager->expects($this->once())
2672
+            ->method('generalCreateChecks')
2673
+            ->with($share);
2674
+
2675
+        $manager->expects($this->once())
2676
+            ->method('linkCreateChecks');
2677
+        $manager->expects($this->once())
2678
+            ->method('pathCreateChecks')
2679
+            ->with($path);
2680
+        $manager->expects($this->once())
2681
+            ->method('validateExpirationDateLink')
2682
+            ->with($share)
2683
+            ->willReturn($share);
2684
+        $manager->expects($this->once())
2685
+            ->method('verifyPassword');
2686
+        $manager->expects($this->once())
2687
+            ->method('setLinkParent');
2688
+
2689
+        $this->secureRandom->method('generate')
2690
+            ->willReturn('token');
2691
+
2692
+        $this->defaultProvider
2693
+            ->expects($this->once())
2694
+            ->method('create')
2695
+            ->with($share)
2696
+            ->willReturnCallback(function (Share $share) {
2697
+                return $share->setId(42);
2698
+            });
2699
+
2700
+        $calls = [
2701
+            BeforeShareCreatedEvent::class,
2702
+            ShareCreatedEvent::class,
2703
+        ];
2704
+        $this->dispatcher->expects($this->exactly(2))
2705
+            ->method('dispatchTyped')
2706
+            ->willReturnCallback(function ($event) use (&$calls, $path): void {
2707
+                $expected = array_shift($calls);
2708
+                $this->assertInstanceOf($expected, $event);
2709
+                $share = $event->getShare();
2710
+
2711
+                $this->assertEquals(IShare::TYPE_EMAIL, $share->getShareType(), 'getShareType');
2712
+                $this->assertEquals($path, $share->getNode(), 'getNode');
2713
+                $this->assertEquals('sharedBy', $share->getSharedBy(), 'getSharedBy');
2714
+                $this->assertEquals(Constants::PERMISSION_ALL, $share->getPermissions(), 'getPermissions');
2715
+                $this->assertNull($share->getExpirationDate(), 'getExpirationDate');
2716
+                $this->assertNull($share->getPassword(), 'getPassword');
2717
+                $this->assertEquals('token', $share->getToken(), 'getToken');
2718
+
2719
+                if ($expected === ShareCreatedEvent::class) {
2720
+                    $this->assertEquals('42', $share->getId(), 'getId');
2721
+                    $this->assertEquals('/target', $share->getTarget(), 'getTarget');
2722
+                }
2723
+            });
2724
+
2725
+        /** @var IShare $share */
2726
+        $share = $manager->createShare($share);
2727
+
2728
+        $this->assertSame('shareOwner', $share->getShareOwner());
2729
+        $this->assertEquals('/target', $share->getTarget());
2730
+        $this->assertEquals('token', $share->getToken());
2731
+    }
2732
+
2733
+
2734
+    public function testCreateShareHookError(): void {
2735
+        $this->expectException(\Exception::class);
2736
+        $this->expectExceptionMessage('I won\'t let you share');
2737
+
2738
+        $manager = $this->createManagerMock()
2739
+            ->onlyMethods([
2740
+                'canShare',
2741
+                'generalCreateChecks',
2742
+                'userCreateChecks',
2743
+                'pathCreateChecks',
2744
+            ])
2745
+            ->getMock();
2746
+
2747
+        $shareOwner = $this->createMock(IUser::class);
2748
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2749
+
2750
+        $storage = $this->createMock(IStorage::class);
2751
+        $path = $this->createMock(File::class);
2752
+        $path->method('getOwner')->willReturn($shareOwner);
2753
+        $path->method('getName')->willReturn('target');
2754
+        $path->method('getStorage')->willReturn($storage);
2755
+
2756
+        $share = $this->createShare(
2757
+            null,
2758
+            IShare::TYPE_USER,
2759
+            $path,
2760
+            'sharedWith',
2761
+            'sharedBy',
2762
+            null,
2763
+            Constants::PERMISSION_ALL);
2764
+
2765
+        $manager->expects($this->once())
2766
+            ->method('canShare')
2767
+            ->with($share)
2768
+            ->willReturn(true);
2769
+        $manager->expects($this->once())
2770
+            ->method('generalCreateChecks')
2771
+            ->with($share);
2772
+        ;
2773
+        $manager->expects($this->once())
2774
+            ->method('userCreateChecks')
2775
+            ->with($share);
2776
+        ;
2777
+        $manager->expects($this->once())
2778
+            ->method('pathCreateChecks')
2779
+            ->with($path);
2780
+
2781
+        $share->expects($this->once())
2782
+            ->method('setShareOwner')
2783
+            ->with('shareOwner');
2784
+        $share->expects($this->once())
2785
+            ->method('setTarget')
2786
+            ->with('/target');
2787
+
2788
+        // Pre share
2789
+        $this->dispatcher->expects($this->once())
2790
+            ->method('dispatchTyped')
2791
+            ->with(
2792
+                $this->isInstanceOf(BeforeShareCreatedEvent::class)
2793
+            )->willReturnCallback(function (BeforeShareCreatedEvent $e): void {
2794
+                $e->setError('I won\'t let you share!');
2795
+                $e->stopPropagation();
2796
+            }
2797
+            );
2798
+
2799
+        $manager->createShare($share);
2800
+    }
2801
+
2802
+    public function testCreateShareOfIncomingFederatedShare(): void {
2803
+        $manager = $this->createManagerMock()
2804
+            ->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
2805
+            ->getMock();
2806
+
2807
+        $shareOwner = $this->createMock(IUser::class);
2808
+        $shareOwner->method('getUID')->willReturn('shareOwner');
2809
+
2810
+        $storage = $this->createMock(IStorage::class);
2811
+        $storage->method('instanceOfStorage')
2812
+            ->with('OCA\Files_Sharing\External\Storage')
2813
+            ->willReturn(true);
2814
+
2815
+        $storage2 = $this->createMock(IStorage::class);
2816
+        $storage2->method('instanceOfStorage')
2817
+            ->with('OCA\Files_Sharing\External\Storage')
2818
+            ->willReturn(false);
2819
+
2820
+        $path = $this->createMock(File::class);
2821
+        $path->expects($this->never())->method('getOwner');
2822
+        $path->method('getName')->willReturn('target');
2823
+        $path->method('getStorage')->willReturn($storage);
2824
+
2825
+        $parent = $this->createMock(Folder::class);
2826
+        $parent->method('getStorage')->willReturn($storage);
2827
+
2828
+        $parentParent = $this->createMock(Folder::class);
2829
+        $parentParent->method('getStorage')->willReturn($storage2);
2830
+        $parentParent->method('getOwner')->willReturn($shareOwner);
2831
+
2832
+        $path->method('getParent')->willReturn($parent);
2833
+        $parent->method('getParent')->willReturn($parentParent);
2834
+
2835
+        $share = $this->createShare(
2836
+            null,
2837
+            IShare::TYPE_USER,
2838
+            $path,
2839
+            'sharedWith',
2840
+            'sharedBy',
2841
+            null,
2842
+            Constants::PERMISSION_ALL);
2843
+
2844
+        $manager->expects($this->once())
2845
+            ->method('canShare')
2846
+            ->with($share)
2847
+            ->willReturn(true);
2848
+        $manager->expects($this->once())
2849
+            ->method('generalCreateChecks')
2850
+            ->with($share);
2851
+        ;
2852
+        $manager->expects($this->once())
2853
+            ->method('userCreateChecks')
2854
+            ->with($share);
2855
+        ;
2856
+        $manager->expects($this->once())
2857
+            ->method('pathCreateChecks')
2858
+            ->with($path);
2859
+
2860
+        $this->defaultProvider
2861
+            ->expects($this->once())
2862
+            ->method('create')
2863
+            ->with($share)
2864
+            ->willReturnArgument(0);
2865
+
2866
+        $share->expects($this->once())
2867
+            ->method('setShareOwner')
2868
+            ->with('shareOwner');
2869
+        $share->expects($this->once())
2870
+            ->method('setTarget')
2871
+            ->with('/target');
2872
+
2873
+        $manager->createShare($share);
2874
+    }
2875
+
2876
+    public function testGetSharesBy(): void {
2877
+        $share = $this->manager->newShare();
2878
+
2879
+        $node = $this->createMock(Folder::class);
2880
+
2881
+        $this->defaultProvider->expects($this->once())
2882
+            ->method('getSharesBy')
2883
+            ->with(
2884
+                $this->equalTo('user'),
2885
+                $this->equalTo(IShare::TYPE_USER),
2886
+                $this->equalTo($node),
2887
+                $this->equalTo(true),
2888
+                $this->equalTo(1),
2889
+                $this->equalTo(1)
2890
+            )->willReturn([$share]);
2891
+
2892
+        $shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2893
+
2894
+        $this->assertCount(1, $shares);
2895
+        $this->assertSame($share, $shares[0]);
2896
+    }
2897
+
2898
+    public function testGetSharesByOwnerless(): void {
2899
+        $mount = $this->createMock(IShareOwnerlessMount::class);
2900
+
2901
+        $node = $this->createMock(Folder::class);
2902
+        $node
2903
+            ->expects($this->once())
2904
+            ->method('getMountPoint')
2905
+            ->willReturn($mount);
2906
+
2907
+        $share = $this->manager->newShare();
2908
+        $share->setNode($node);
2909
+        $share->setShareType(IShare::TYPE_USER);
2910
+
2911
+        $this->defaultProvider
2912
+            ->expects($this->once())
2913
+            ->method('getSharesByPath')
2914
+            ->with($this->equalTo($node))
2915
+            ->willReturn([$share]);
2916
+
2917
+        $shares = $this->manager->getSharesBy('user', IShare::TYPE_USER, $node, true, 1, 1);
2918
+
2919
+        $this->assertCount(1, $shares);
2920
+        $this->assertSame($share, $shares[0]);
2921
+    }
2922
+
2923
+    /**
2924
+     * Test to ensure we correctly remove expired link shares
2925
+     *
2926
+     * We have 8 Shares and we want the 3 first valid shares.
2927
+     * share 3-6 and 8 are expired. Thus at the end of this test we should
2928
+     * have received share 1,2 and 7. And from the manager. Share 3-6 should be
2929
+     * deleted (as they are evaluated). but share 8 should still be there.
2930
+     */
2931
+    public function testGetSharesByExpiredLinkShares(): void {
2932
+        $manager = $this->createManagerMock()
2933
+            ->onlyMethods(['deleteShare'])
2934
+            ->getMock();
2935
+
2936
+        /** @var IShare[] $shares */
2937
+        $shares = [];
2938
+
2939
+        /*
2940 2940
 		 * This results in an array of 8 IShare elements
2941 2941
 		 */
2942
-		for ($i = 0; $i < 8; $i++) {
2943
-			$share = $this->manager->newShare();
2944
-			$share->setId($i);
2945
-			$shares[] = $share;
2946
-		}
2942
+        for ($i = 0; $i < 8; $i++) {
2943
+            $share = $this->manager->newShare();
2944
+            $share->setId($i);
2945
+            $shares[] = $share;
2946
+        }
2947 2947
 
2948
-		$today = new \DateTime();
2949
-		$today->setTime(0, 0, 0);
2948
+        $today = new \DateTime();
2949
+        $today->setTime(0, 0, 0);
2950 2950
 
2951
-		/*
2951
+        /*
2952 2952
 		 * Set the expiration date to today for some shares
2953 2953
 		 */
2954
-		$shares[2]->setExpirationDate($today);
2955
-		$shares[3]->setExpirationDate($today);
2956
-		$shares[4]->setExpirationDate($today);
2957
-		$shares[5]->setExpirationDate($today);
2954
+        $shares[2]->setExpirationDate($today);
2955
+        $shares[3]->setExpirationDate($today);
2956
+        $shares[4]->setExpirationDate($today);
2957
+        $shares[5]->setExpirationDate($today);
2958 2958
 
2959
-		/** @var IShare[] $i */
2960
-		$shares2 = [];
2961
-		for ($i = 0; $i < 8; $i++) {
2962
-			$shares2[] = clone $shares[$i];
2963
-		}
2959
+        /** @var IShare[] $i */
2960
+        $shares2 = [];
2961
+        for ($i = 0; $i < 8; $i++) {
2962
+            $shares2[] = clone $shares[$i];
2963
+        }
2964 2964
 
2965
-		$node = $this->createMock(File::class);
2965
+        $node = $this->createMock(File::class);
2966 2966
 
2967
-		/*
2967
+        /*
2968 2968
 		 * Simulate the getSharesBy call.
2969 2969
 		 */
2970
-		$this->defaultProvider
2971
-			->method('getSharesBy')
2972
-			->willReturnCallback(function ($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
2973
-				return array_slice($shares2, $offset, $limit);
2974
-			});
2970
+        $this->defaultProvider
2971
+            ->method('getSharesBy')
2972
+            ->willReturnCallback(function ($uid, $type, $node, $reshares, $limit, $offset) use (&$shares2) {
2973
+                return array_slice($shares2, $offset, $limit);
2974
+            });
2975 2975
 
2976
-		/*
2976
+        /*
2977 2977
 		 * Simulate the deleteShare call.
2978 2978
 		 */
2979
-		$manager->method('deleteShare')
2980
-			->willReturnCallback(function ($share) use (&$shares2): void {
2981
-				for ($i = 0; $i < count($shares2); $i++) {
2982
-					if ($shares2[$i]->getId() === $share->getId()) {
2983
-						array_splice($shares2, $i, 1);
2984
-						break;
2985
-					}
2986
-				}
2987
-			});
2988
-
2989
-		$res = $manager->getSharesBy('user', IShare::TYPE_LINK, $node, true, 3, 0);
2990
-
2991
-		$this->assertCount(3, $res);
2992
-		$this->assertEquals($shares[0]->getId(), $res[0]->getId());
2993
-		$this->assertEquals($shares[1]->getId(), $res[1]->getId());
2994
-		$this->assertEquals($shares[6]->getId(), $res[2]->getId());
2995
-
2996
-		$this->assertCount(4, $shares2);
2997
-		$this->assertEquals(0, $shares2[0]->getId());
2998
-		$this->assertEquals(1, $shares2[1]->getId());
2999
-		$this->assertEquals(6, $shares2[2]->getId());
3000
-		$this->assertEquals(7, $shares2[3]->getId());
3001
-		$this->assertSame($today, $shares[3]->getExpirationDate());
3002
-	}
3003
-
3004
-	public function testGetShareByToken(): void {
3005
-		$this->config
3006
-			->expects($this->exactly(2))
3007
-			->method('getAppValue')
3008
-			->willReturnMap([
3009
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3010
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3011
-			]);
3012
-
3013
-		$factory = $this->createMock(IProviderFactory::class);
3014
-
3015
-		$manager = $this->createManager($factory);
3016
-
3017
-		$share = $this->createMock(IShare::class);
3018
-
3019
-		$factory->expects($this->once())
3020
-			->method('getProviderForType')
3021
-			->with(IShare::TYPE_LINK)
3022
-			->willReturn($this->defaultProvider);
3023
-
3024
-		$this->defaultProvider->expects($this->once())
3025
-			->method('getShareByToken')
3026
-			->with('token')
3027
-			->willReturn($share);
3028
-
3029
-		$ret = $manager->getShareByToken('token');
3030
-		$this->assertSame($share, $ret);
3031
-	}
3032
-
3033
-	public function testGetShareByTokenRoom(): void {
3034
-		$this->config
3035
-			->expects($this->exactly(2))
3036
-			->method('getAppValue')
3037
-			->willReturnMap([
3038
-				['core', 'shareapi_allow_links', 'yes', 'no'],
3039
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3040
-			]);
3041
-
3042
-		$factory = $this->createMock(IProviderFactory::class);
3043
-
3044
-		$manager = $this->createManager($factory);
3045
-
3046
-		$share = $this->createMock(IShare::class);
3047
-
3048
-		$roomShareProvider = $this->createMock(IShareProvider::class);
3049
-
3050
-		$factory->expects($this->any())
3051
-			->method('getProviderForType')
3052
-			->willReturnCallback(function ($shareType) use ($roomShareProvider) {
3053
-				if ($shareType !== IShare::TYPE_ROOM) {
3054
-					throw new ProviderException();
3055
-				}
3056
-
3057
-				return $roomShareProvider;
3058
-			});
3059
-
3060
-		$roomShareProvider->expects($this->once())
3061
-			->method('getShareByToken')
3062
-			->with('token')
3063
-			->willReturn($share);
3064
-
3065
-		$ret = $manager->getShareByToken('token');
3066
-		$this->assertSame($share, $ret);
3067
-	}
3068
-
3069
-	public function testGetShareByTokenWithException(): void {
3070
-		$this->config
3071
-			->expects($this->exactly(2))
3072
-			->method('getAppValue')
3073
-			->willReturnMap([
3074
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3075
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3076
-			]);
3077
-
3078
-		$factory = $this->createMock(IProviderFactory::class);
3079
-
3080
-		$manager = $this->createManager($factory);
3081
-
3082
-		$share = $this->createMock(IShare::class);
3083
-
3084
-		$calls = [
3085
-			[IShare::TYPE_LINK],
3086
-			[IShare::TYPE_REMOTE],
3087
-		];
3088
-		$factory->expects($this->exactly(2))
3089
-			->method('getProviderForType')
3090
-			->willReturnCallback(function () use (&$calls) {
3091
-				$expected = array_shift($calls);
3092
-				$this->assertEquals($expected, func_get_args());
3093
-				return $this->defaultProvider;
3094
-			});
3095
-
3096
-		$this->defaultProvider->expects($this->exactly(2))
3097
-			->method('getShareByToken')
3098
-			->with('token')
3099
-			->willReturnOnConsecutiveCalls(
3100
-				$this->throwException(new ShareNotFound()),
3101
-				$share
3102
-			);
3103
-
3104
-		$ret = $manager->getShareByToken('token');
3105
-		$this->assertSame($share, $ret);
3106
-	}
3107
-
3108
-
3109
-	public function testGetShareByTokenHideDisabledUser(): void {
3110
-		$this->expectException(ShareNotFound::class);
3111
-		$this->expectExceptionMessage('The requested share comes from a disabled user');
3112
-
3113
-		$this->config
3114
-			->expects($this->exactly(2))
3115
-			->method('getAppValue')
3116
-			->willReturnMap([
3117
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3118
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'yes'],
3119
-			]);
3120
-
3121
-		$this->l->expects($this->once())
3122
-			->method('t')
3123
-			->willReturnArgument(0);
3124
-
3125
-		$manager = $this->createManagerMock()
3126
-			->onlyMethods(['deleteShare'])
3127
-			->getMock();
3128
-
3129
-		$date = new \DateTime();
3130
-		$date->setTime(0, 0, 0);
3131
-		$date->add(new \DateInterval('P2D'));
3132
-		$share = $this->manager->newShare();
3133
-		$share->setExpirationDate($date);
3134
-		$share->setShareOwner('owner');
3135
-		$share->setSharedBy('sharedBy');
3136
-
3137
-		$sharedBy = $this->createMock(IUser::class);
3138
-		$owner = $this->createMock(IUser::class);
3139
-
3140
-		$this->userManager->method('get')->willReturnMap([
3141
-			['sharedBy', $sharedBy],
3142
-			['owner', $owner],
3143
-		]);
3144
-
3145
-		$owner->expects($this->once())
3146
-			->method('isEnabled')
3147
-			->willReturn(true);
3148
-		$sharedBy->expects($this->once())
3149
-			->method('isEnabled')
3150
-			->willReturn(false);
3151
-
3152
-		$this->defaultProvider->expects($this->once())
3153
-			->method('getShareByToken')
3154
-			->with('expiredToken')
3155
-			->willReturn($share);
3156
-
3157
-		$manager->expects($this->never())
3158
-			->method('deleteShare');
3159
-
3160
-		$manager->getShareByToken('expiredToken');
3161
-	}
3162
-
3163
-
3164
-	public function testGetShareByTokenExpired(): void {
3165
-		$this->expectException(ShareNotFound::class);
3166
-		$this->expectExceptionMessage('The requested share does not exist anymore');
3167
-
3168
-		$this->config
3169
-			->expects($this->once())
3170
-			->method('getAppValue')
3171
-			->with('core', 'shareapi_allow_links', 'yes')
3172
-			->willReturn('yes');
3173
-
3174
-		$this->l->expects($this->once())
3175
-			->method('t')
3176
-			->willReturnArgument(0);
3177
-
3178
-		$manager = $this->createManagerMock()
3179
-			->onlyMethods(['deleteShare'])
3180
-			->getMock();
3181
-
3182
-		$date = new \DateTime();
3183
-		$date->setTime(0, 0, 0);
3184
-		$share = $this->manager->newShare();
3185
-		$share->setExpirationDate($date);
3186
-
3187
-		$this->defaultProvider->expects($this->once())
3188
-			->method('getShareByToken')
3189
-			->with('expiredToken')
3190
-			->willReturn($share);
3191
-
3192
-		$manager->expects($this->once())
3193
-			->method('deleteShare')
3194
-			->with($this->equalTo($share));
3195
-
3196
-		$manager->getShareByToken('expiredToken');
3197
-	}
3198
-
3199
-	public function testGetShareByTokenNotExpired(): void {
3200
-		$this->config
3201
-			->expects($this->exactly(2))
3202
-			->method('getAppValue')
3203
-			->willReturnMap([
3204
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3205
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3206
-			]);
3207
-
3208
-		$date = new \DateTime();
3209
-		$date->setTime(0, 0, 0);
3210
-		$date->add(new \DateInterval('P2D'));
3211
-		$share = $this->manager->newShare();
3212
-		$share->setExpirationDate($date);
3213
-
3214
-		$this->defaultProvider->expects($this->once())
3215
-			->method('getShareByToken')
3216
-			->with('expiredToken')
3217
-			->willReturn($share);
3218
-
3219
-		$res = $this->manager->getShareByToken('expiredToken');
3220
-
3221
-		$this->assertSame($share, $res);
3222
-	}
3223
-
3224
-
3225
-	public function testGetShareByTokenWithPublicLinksDisabled(): void {
3226
-		$this->expectException(ShareNotFound::class);
3227
-
3228
-		$this->config
3229
-			->expects($this->once())
3230
-			->method('getAppValue')
3231
-			->with('core', 'shareapi_allow_links', 'yes')
3232
-			->willReturn('no');
3233
-		$this->manager->getShareByToken('validToken');
3234
-	}
3235
-
3236
-	public function testGetShareByTokenPublicUploadDisabled(): void {
3237
-		$this->config
3238
-			->expects($this->exactly(3))
3239
-			->method('getAppValue')
3240
-			->willReturnMap([
3241
-				['core', 'shareapi_allow_links', 'yes', 'yes'],
3242
-				['core', 'shareapi_allow_public_upload', 'yes', 'no'],
3243
-				['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3244
-			]);
3245
-
3246
-		$share = $this->manager->newShare();
3247
-		$share->setShareType(IShare::TYPE_LINK)
3248
-			->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
3249
-		$share->setSharedWith('sharedWith');
3250
-		$folder = $this->createMock(\OC\Files\Node\Folder::class);
3251
-		$share->setNode($folder);
3252
-
3253
-		$this->defaultProvider->expects($this->once())
3254
-			->method('getShareByToken')
3255
-			->willReturn('validToken')
3256
-			->willReturn($share);
3257
-
3258
-		$res = $this->manager->getShareByToken('validToken');
3259
-
3260
-		$this->assertSame(Constants::PERMISSION_READ, $res->getPermissions());
3261
-	}
3262
-
3263
-	public function testCheckPasswordNoLinkShare(): void {
3264
-		$share = $this->createMock(IShare::class);
3265
-		$share->method('getShareType')->willReturn(IShare::TYPE_USER);
3266
-		$this->assertFalse($this->manager->checkPassword($share, 'password'));
3267
-	}
3268
-
3269
-	public function testCheckPasswordNoPassword(): void {
3270
-		$share = $this->createMock(IShare::class);
3271
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3272
-		$this->assertFalse($this->manager->checkPassword($share, 'password'));
3273
-
3274
-		$share->method('getPassword')->willReturn('password');
3275
-		$this->assertFalse($this->manager->checkPassword($share, null));
3276
-	}
3277
-
3278
-	public function testCheckPasswordInvalidPassword(): void {
3279
-		$share = $this->createMock(IShare::class);
3280
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3281
-		$share->method('getPassword')->willReturn('password');
3282
-
3283
-		$this->hasher->method('verify')->with('invalidpassword', 'password', '')->willReturn(false);
3284
-
3285
-		$this->assertFalse($this->manager->checkPassword($share, 'invalidpassword'));
3286
-	}
3287
-
3288
-	public function testCheckPasswordValidPassword(): void {
3289
-		$share = $this->createMock(IShare::class);
3290
-		$share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3291
-		$share->method('getPassword')->willReturn('passwordHash');
3292
-
3293
-		$this->hasher->method('verify')->with('password', 'passwordHash', '')->willReturn(true);
3294
-
3295
-		$this->assertTrue($this->manager->checkPassword($share, 'password'));
3296
-	}
3297
-
3298
-	public function testCheckPasswordUpdateShare(): void {
3299
-		$share = $this->manager->newShare();
3300
-		$share->setShareType(IShare::TYPE_LINK)
3301
-			->setPassword('passwordHash');
3302
-
3303
-		$this->hasher->method('verify')->with('password', 'passwordHash', '')
3304
-			->willReturnCallback(function ($pass, $hash, &$newHash) {
3305
-				$newHash = 'newHash';
3306
-
3307
-				return true;
3308
-			});
3309
-
3310
-		$this->defaultProvider->expects($this->once())
3311
-			->method('update')
3312
-			->with($this->callback(function (IShare $share) {
3313
-				return $share->getPassword() === 'newHash';
3314
-			}));
3315
-
3316
-		$this->assertTrue($this->manager->checkPassword($share, 'password'));
3317
-	}
3318
-
3319
-
3320
-	public function testUpdateShareCantChangeShareType(): void {
3321
-		$this->expectException(\Exception::class);
3322
-		$this->expectExceptionMessage('Cannot change share type');
3323
-
3324
-		$manager = $this->createManagerMock()
3325
-			->onlyMethods([
3326
-				'canShare',
3327
-				'getShareById'
3328
-			])
3329
-			->getMock();
3330
-
3331
-		$originalShare = $this->manager->newShare();
3332
-		$originalShare->setShareType(IShare::TYPE_GROUP);
3333
-
3334
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3335
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3336
-
3337
-		$share = $this->manager->newShare();
3338
-		$attrs = $this->manager->newShare()->newAttributes();
3339
-		$attrs->setAttribute('app1', 'perm1', true);
3340
-		$share->setProviderId('foo')
3341
-			->setId('42')
3342
-			->setShareType(IShare::TYPE_USER);
3343
-
3344
-		$manager->updateShare($share);
3345
-	}
3346
-
3347
-
3348
-	public function testUpdateShareCantChangeRecipientForGroupShare(): void {
3349
-		$this->expectException(\Exception::class);
3350
-		$this->expectExceptionMessage('Can only update recipient on user shares');
3351
-
3352
-		$manager = $this->createManagerMock()
3353
-			->onlyMethods([
3354
-				'canShare',
3355
-				'getShareById'
3356
-			])
3357
-			->getMock();
3358
-
3359
-		$originalShare = $this->manager->newShare();
3360
-		$originalShare->setShareType(IShare::TYPE_GROUP)
3361
-			->setSharedWith('origGroup');
3362
-
3363
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3364
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3365
-
3366
-		$share = $this->manager->newShare();
3367
-		$share->setProviderId('foo')
3368
-			->setId('42')
3369
-			->setShareType(IShare::TYPE_GROUP)
3370
-			->setSharedWith('newGroup');
3371
-
3372
-		$manager->updateShare($share);
3373
-	}
3374
-
3375
-
3376
-	public function testUpdateShareCantShareWithOwner(): void {
3377
-		$this->expectException(\Exception::class);
3378
-		$this->expectExceptionMessage('Cannot share with the share owner');
3379
-
3380
-		$manager = $this->createManagerMock()
3381
-			->onlyMethods([
3382
-				'canShare',
3383
-				'getShareById'
3384
-			])
3385
-			->getMock();
3386
-
3387
-		$originalShare = $this->manager->newShare();
3388
-		$originalShare->setShareType(IShare::TYPE_USER)
3389
-			->setSharedWith('sharedWith');
3390
-
3391
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3392
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3393
-
3394
-		$share = $this->manager->newShare();
3395
-		$share->setProviderId('foo')
3396
-			->setId('42')
3397
-			->setShareType(IShare::TYPE_USER)
3398
-			->setSharedWith('newUser')
3399
-			->setShareOwner('newUser');
3400
-
3401
-		$manager->updateShare($share);
3402
-	}
3403
-
3404
-	public function testUpdateShareUser(): void {
3405
-		$this->userManager->expects($this->any())->method('userExists')->willReturn(true);
3406
-
3407
-		$manager = $this->createManagerMock()
3408
-			->onlyMethods([
3409
-				'canShare',
3410
-				'getShareById',
3411
-				'generalCreateChecks',
3412
-				'userCreateChecks',
3413
-				'pathCreateChecks',
3414
-			])
3415
-			->getMock();
3416
-
3417
-		$originalShare = $this->manager->newShare();
3418
-		$originalShare->setShareType(IShare::TYPE_USER)
3419
-			->setSharedWith('origUser')
3420
-			->setPermissions(1);
3421
-
3422
-		$node = $this->createMock(File::class);
3423
-		$node->method('getId')->willReturn(100);
3424
-		$node->method('getPath')->willReturn('/newUser/files/myPath');
3425
-
3426
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3427
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3428
-
3429
-		$share = $this->manager->newShare();
3430
-		$attrs = $this->manager->newShare()->newAttributes();
3431
-		$attrs->setAttribute('app1', 'perm1', true);
3432
-		$share->setProviderId('foo')
3433
-			->setId('42')
3434
-			->setShareType(IShare::TYPE_USER)
3435
-			->setSharedWith('origUser')
3436
-			->setShareOwner('newUser')
3437
-			->setSharedBy('sharer')
3438
-			->setPermissions(31)
3439
-			->setAttributes($attrs)
3440
-			->setNode($node);
3441
-
3442
-		$this->defaultProvider->expects($this->once())
3443
-			->method('update')
3444
-			->with($share)
3445
-			->willReturn($share);
3446
-
3447
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3448
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3449
-		$hookListener->expects($this->never())->method('post');
3450
-
3451
-		$this->rootFolder->method('getUserFolder')->with('newUser')->willReturnSelf();
3452
-		$this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath');
3453
-
3454
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3455
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3456
-		$hookListener2->expects($this->once())->method('post')->with([
3457
-			'itemType' => 'file',
3458
-			'itemSource' => 100,
3459
-			'shareType' => IShare::TYPE_USER,
3460
-			'shareWith' => 'origUser',
3461
-			'uidOwner' => 'sharer',
3462
-			'permissions' => 31,
3463
-			'path' => '/myPath',
3464
-			'attributes' => $attrs->toArray(),
3465
-		]);
3466
-
3467
-		$manager->updateShare($share);
3468
-	}
3469
-
3470
-	public function testUpdateShareGroup(): void {
3471
-		$manager = $this->createManagerMock()
3472
-			->onlyMethods([
3473
-				'canShare',
3474
-				'getShareById',
3475
-				'generalCreateChecks',
3476
-				'groupCreateChecks',
3477
-				'pathCreateChecks',
3478
-			])
3479
-			->getMock();
3480
-
3481
-		$originalShare = $this->manager->newShare();
3482
-		$originalShare->setShareType(IShare::TYPE_GROUP)
3483
-			->setSharedWith('origUser')
3484
-			->setPermissions(31);
3485
-
3486
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3487
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3488
-
3489
-		$node = $this->createMock(File::class);
3490
-
3491
-		$share = $this->manager->newShare();
3492
-		$share->setProviderId('foo')
3493
-			->setId('42')
3494
-			->setShareType(IShare::TYPE_GROUP)
3495
-			->setSharedWith('origUser')
3496
-			->setShareOwner('owner')
3497
-			->setNode($node)
3498
-			->setPermissions(31);
3499
-
3500
-		$this->defaultProvider->expects($this->once())
3501
-			->method('update')
3502
-			->with($share)
3503
-			->willReturn($share);
3504
-
3505
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3506
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3507
-		$hookListener->expects($this->never())->method('post');
3508
-
3509
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3510
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3511
-		$hookListener2->expects($this->never())->method('post');
3512
-
3513
-		$manager->updateShare($share);
3514
-	}
3515
-
3516
-	public function testUpdateShareLink(): void {
3517
-		$manager = $this->createManagerMock()
3518
-			->onlyMethods([
3519
-				'canShare',
3520
-				'getShareById',
3521
-				'generalCreateChecks',
3522
-				'linkCreateChecks',
3523
-				'pathCreateChecks',
3524
-				'verifyPassword',
3525
-				'validateExpirationDateLink',
3526
-			])
3527
-			->getMock();
3528
-
3529
-		$originalShare = $this->manager->newShare();
3530
-		$originalShare->setShareType(IShare::TYPE_LINK)
3531
-			->setPermissions(15);
3532
-
3533
-		$tomorrow = new \DateTime();
3534
-		$tomorrow->setTime(0, 0, 0);
3535
-		$tomorrow->add(new \DateInterval('P1D'));
3536
-
3537
-		$file = $this->createMock(File::class);
3538
-		$file->method('getId')->willReturn(100);
3539
-
3540
-		$share = $this->manager->newShare();
3541
-		$share->setProviderId('foo')
3542
-			->setId('42')
3543
-			->setShareType(IShare::TYPE_LINK)
3544
-			->setToken('token')
3545
-			->setSharedBy('owner')
3546
-			->setShareOwner('owner')
3547
-			->setPassword('password')
3548
-			->setExpirationDate($tomorrow)
3549
-			->setNode($file)
3550
-			->setPermissions(15);
3551
-
3552
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3553
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3554
-		$manager->expects($this->once())->method('validateExpirationDateLink')->with($share);
3555
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3556
-
3557
-		$this->hasher->expects($this->once())
3558
-			->method('hash')
3559
-			->with('password')
3560
-			->willReturn('hashed');
3561
-
3562
-		$this->defaultProvider->expects($this->once())
3563
-			->method('update')
3564
-			->with($share)
3565
-			->willReturn($share);
3566
-
3567
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3568
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3569
-		$hookListener->expects($this->once())->method('post')->with([
3570
-			'itemType' => 'file',
3571
-			'itemSource' => 100,
3572
-			'date' => $tomorrow,
3573
-			'uidOwner' => 'owner',
3574
-		]);
3575
-
3576
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3577
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3578
-		$hookListener2->expects($this->once())->method('post')->with([
3579
-			'itemType' => 'file',
3580
-			'itemSource' => 100,
3581
-			'uidOwner' => 'owner',
3582
-			'token' => 'token',
3583
-			'disabled' => false,
3584
-		]);
3585
-
3586
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3587
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3588
-		$hookListener3->expects($this->never())->method('post');
3589
-
3590
-
3591
-		$manager->updateShare($share);
3592
-	}
3593
-
3594
-	public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword(): void {
3595
-		$this->expectException(\InvalidArgumentException::class);
3596
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3597
-
3598
-		$manager = $this->createManagerMock()
3599
-			->onlyMethods([
3600
-				'canShare',
3601
-				'getShareById',
3602
-				'generalCreateChecks',
3603
-				'linkCreateChecks',
3604
-				'pathCreateChecks',
3605
-				'verifyPassword',
3606
-				'validateExpirationDateLink',
3607
-			])
3608
-			->getMock();
3609
-
3610
-		$originalShare = $this->manager->newShare();
3611
-		$originalShare->setShareType(IShare::TYPE_LINK)
3612
-			->setPermissions(15);
3613
-
3614
-		$tomorrow = new \DateTime();
3615
-		$tomorrow->setTime(0, 0, 0);
3616
-		$tomorrow->add(new \DateInterval('P1D'));
3617
-
3618
-		$file = $this->createMock(File::class);
3619
-		$file->method('getId')->willReturn(100);
3620
-
3621
-		$share = $this->manager->newShare();
3622
-		$share->setProviderId('foo')
3623
-			->setId('42')
3624
-			->setShareType(IShare::TYPE_LINK)
3625
-			->setToken('token')
3626
-			->setSharedBy('owner')
3627
-			->setShareOwner('owner')
3628
-			->setPassword(null)
3629
-			->setSendPasswordByTalk(true)
3630
-			->setExpirationDate($tomorrow)
3631
-			->setNode($file)
3632
-			->setPermissions(15);
3633
-
3634
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3635
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3636
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3637
-		$manager->expects($this->once())->method('linkCreateChecks')->with($share);
3638
-		$manager->expects($this->never())->method('verifyPassword');
3639
-		$manager->expects($this->never())->method('pathCreateChecks');
3640
-		$manager->expects($this->never())->method('validateExpirationDateLink');
3641
-
3642
-		$this->hasher->expects($this->never())
3643
-			->method('hash');
3644
-
3645
-		$this->defaultProvider->expects($this->never())
3646
-			->method('update');
3647
-
3648
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3649
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3650
-		$hookListener->expects($this->never())->method('post');
3651
-
3652
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3653
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3654
-		$hookListener2->expects($this->never())->method('post');
3655
-
3656
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3657
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3658
-		$hookListener3->expects($this->never())->method('post');
3659
-
3660
-		$manager->updateShare($share);
3661
-	}
3662
-
3663
-	public function testUpdateShareMail(): void {
3664
-		$manager = $this->createManagerMock()
3665
-			->onlyMethods([
3666
-				'canShare',
3667
-				'getShareById',
3668
-				'generalCreateChecks',
3669
-				'verifyPassword',
3670
-				'pathCreateChecks',
3671
-				'linkCreateChecks',
3672
-				'validateExpirationDateLink',
3673
-			])
3674
-			->getMock();
3675
-
3676
-		$originalShare = $this->manager->newShare();
3677
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3678
-			->setPermissions(Constants::PERMISSION_ALL);
3679
-
3680
-		$tomorrow = new \DateTime();
3681
-		$tomorrow->setTime(0, 0, 0);
3682
-		$tomorrow->add(new \DateInterval('P1D'));
3683
-
3684
-		$file = $this->createMock(File::class);
3685
-		$file->method('getId')->willReturn(100);
3686
-
3687
-		$share = $this->manager->newShare();
3688
-		$share->setProviderId('foo')
3689
-			->setId('42')
3690
-			->setShareType(IShare::TYPE_EMAIL)
3691
-			->setToken('token')
3692
-			->setSharedBy('owner')
3693
-			->setShareOwner('owner')
3694
-			->setPassword('password')
3695
-			->setExpirationDate($tomorrow)
3696
-			->setNode($file)
3697
-			->setPermissions(Constants::PERMISSION_ALL);
3698
-
3699
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3700
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3701
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3702
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3703
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
3704
-		$manager->expects($this->once())->method('linkCreateChecks');
3705
-		$manager->expects($this->once())->method('validateExpirationDateLink');
3706
-
3707
-		$this->hasher->expects($this->once())
3708
-			->method('hash')
3709
-			->with('password')
3710
-			->willReturn('hashed');
3711
-
3712
-		$this->defaultProvider->expects($this->once())
3713
-			->method('update')
3714
-			->with($share, 'password')
3715
-			->willReturn($share);
3716
-
3717
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3718
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3719
-		$hookListener->expects($this->once())->method('post')->with([
3720
-			'itemType' => 'file',
3721
-			'itemSource' => 100,
3722
-			'date' => $tomorrow,
3723
-			'uidOwner' => 'owner',
3724
-		]);
3725
-
3726
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3727
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3728
-		$hookListener2->expects($this->once())->method('post')->with([
3729
-			'itemType' => 'file',
3730
-			'itemSource' => 100,
3731
-			'uidOwner' => 'owner',
3732
-			'token' => 'token',
3733
-			'disabled' => false,
3734
-		]);
3735
-
3736
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3737
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3738
-		$hookListener3->expects($this->never())->method('post');
3739
-
3740
-		$manager->updateShare($share);
3741
-	}
3742
-
3743
-	public function testUpdateShareMailEnableSendPasswordByTalk(): void {
3744
-		$manager = $this->createManagerMock()
3745
-			->onlyMethods([
3746
-				'canShare',
3747
-				'getShareById',
3748
-				'generalCreateChecks',
3749
-				'verifyPassword',
3750
-				'pathCreateChecks',
3751
-				'linkCreateChecks',
3752
-				'validateExpirationDateLink',
3753
-			])
3754
-			->getMock();
3755
-
3756
-		$originalShare = $this->manager->newShare();
3757
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3758
-			->setPermissions(Constants::PERMISSION_ALL)
3759
-			->setPassword(null)
3760
-			->setSendPasswordByTalk(false);
3761
-
3762
-		$tomorrow = new \DateTime();
3763
-		$tomorrow->setTime(0, 0, 0);
3764
-		$tomorrow->add(new \DateInterval('P1D'));
3765
-
3766
-		$file = $this->createMock(File::class);
3767
-		$file->method('getId')->willReturn(100);
3768
-
3769
-		$share = $this->manager->newShare();
3770
-		$share->setProviderId('foo')
3771
-			->setId('42')
3772
-			->setShareType(IShare::TYPE_EMAIL)
3773
-			->setToken('token')
3774
-			->setSharedBy('owner')
3775
-			->setShareOwner('owner')
3776
-			->setPassword('password')
3777
-			->setSendPasswordByTalk(true)
3778
-			->setExpirationDate($tomorrow)
3779
-			->setNode($file)
3780
-			->setPermissions(Constants::PERMISSION_ALL);
3781
-
3782
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3783
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3784
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3785
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3786
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
3787
-		$manager->expects($this->once())->method('linkCreateChecks');
3788
-		$manager->expects($this->once())->method('validateExpirationDateLink');
3789
-
3790
-		$this->hasher->expects($this->once())
3791
-			->method('hash')
3792
-			->with('password')
3793
-			->willReturn('hashed');
3794
-
3795
-		$this->defaultProvider->expects($this->once())
3796
-			->method('update')
3797
-			->with($share, 'password')
3798
-			->willReturn($share);
3799
-
3800
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3801
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3802
-		$hookListener->expects($this->once())->method('post')->with([
3803
-			'itemType' => 'file',
3804
-			'itemSource' => 100,
3805
-			'date' => $tomorrow,
3806
-			'uidOwner' => 'owner',
3807
-		]);
3808
-
3809
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3810
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3811
-		$hookListener2->expects($this->once())->method('post')->with([
3812
-			'itemType' => 'file',
3813
-			'itemSource' => 100,
3814
-			'uidOwner' => 'owner',
3815
-			'token' => 'token',
3816
-			'disabled' => false,
3817
-		]);
3818
-
3819
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3820
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3821
-		$hookListener3->expects($this->never())->method('post');
3822
-
3823
-		$manager->updateShare($share);
3824
-	}
3825
-
3826
-	public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword(): void {
3827
-		$manager = $this->createManagerMock()
3828
-			->onlyMethods([
3829
-				'canShare',
3830
-				'getShareById',
3831
-				'generalCreateChecks',
3832
-				'verifyPassword',
3833
-				'pathCreateChecks',
3834
-				'linkCreateChecks',
3835
-				'validateExpirationDateLink',
3836
-			])
3837
-			->getMock();
3838
-
3839
-		$originalShare = $this->manager->newShare();
3840
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3841
-			->setPermissions(Constants::PERMISSION_ALL)
3842
-			->setPassword('anotherPasswordHash')
3843
-			->setSendPasswordByTalk(false);
3844
-
3845
-		$tomorrow = new \DateTime();
3846
-		$tomorrow->setTime(0, 0, 0);
3847
-		$tomorrow->add(new \DateInterval('P1D'));
3848
-
3849
-		$file = $this->createMock(File::class);
3850
-		$file->method('getId')->willReturn(100);
3851
-
3852
-		$share = $this->manager->newShare();
3853
-		$share->setProviderId('foo')
3854
-			->setId('42')
3855
-			->setShareType(IShare::TYPE_EMAIL)
3856
-			->setToken('token')
3857
-			->setSharedBy('owner')
3858
-			->setShareOwner('owner')
3859
-			->setPassword('password')
3860
-			->setSendPasswordByTalk(true)
3861
-			->setExpirationDate($tomorrow)
3862
-			->setNode($file)
3863
-			->setPermissions(Constants::PERMISSION_ALL);
3864
-
3865
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3866
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3867
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3868
-		$manager->expects($this->once())->method('verifyPassword')->with('password');
3869
-		$manager->expects($this->once())->method('pathCreateChecks')->with($file);
3870
-		$manager->expects($this->once())->method('linkCreateChecks');
3871
-		$manager->expects($this->once())->method('validateExpirationDateLink');
3872
-
3873
-		$this->hasher->expects($this->once())
3874
-			->method('verify')
3875
-			->with('password', 'anotherPasswordHash')
3876
-			->willReturn(false);
3877
-
3878
-		$this->hasher->expects($this->once())
3879
-			->method('hash')
3880
-			->with('password')
3881
-			->willReturn('hashed');
3882
-
3883
-		$this->defaultProvider->expects($this->once())
3884
-			->method('update')
3885
-			->with($share, 'password')
3886
-			->willReturn($share);
3887
-
3888
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3889
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3890
-		$hookListener->expects($this->once())->method('post')->with([
3891
-			'itemType' => 'file',
3892
-			'itemSource' => 100,
3893
-			'date' => $tomorrow,
3894
-			'uidOwner' => 'owner',
3895
-		]);
3896
-
3897
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3898
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3899
-		$hookListener2->expects($this->once())->method('post')->with([
3900
-			'itemType' => 'file',
3901
-			'itemSource' => 100,
3902
-			'uidOwner' => 'owner',
3903
-			'token' => 'token',
3904
-			'disabled' => false,
3905
-		]);
3906
-
3907
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3908
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3909
-		$hookListener3->expects($this->never())->method('post');
3910
-
3911
-		$manager->updateShare($share);
3912
-	}
3913
-
3914
-	public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword(): void {
3915
-		$this->expectException(\InvalidArgumentException::class);
3916
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3917
-
3918
-		$manager = $this->createManagerMock()
3919
-			->onlyMethods([
3920
-				'canShare',
3921
-				'getShareById',
3922
-				'generalCreateChecks',
3923
-				'verifyPassword',
3924
-				'pathCreateChecks',
3925
-				'linkCreateChecks',
3926
-				'validateExpirationDateLink',
3927
-			])
3928
-			->getMock();
3929
-
3930
-		$originalShare = $this->manager->newShare();
3931
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
3932
-			->setPermissions(Constants::PERMISSION_ALL)
3933
-			->setPassword(null)
3934
-			->setSendPasswordByTalk(false);
3935
-
3936
-		$tomorrow = new \DateTime();
3937
-		$tomorrow->setTime(0, 0, 0);
3938
-		$tomorrow->add(new \DateInterval('P1D'));
3939
-
3940
-		$file = $this->createMock(File::class);
3941
-		$file->method('getId')->willReturn(100);
3942
-
3943
-		$share = $this->manager->newShare();
3944
-		$share->setProviderId('foo')
3945
-			->setId('42')
3946
-			->setShareType(IShare::TYPE_EMAIL)
3947
-			->setToken('token')
3948
-			->setSharedBy('owner')
3949
-			->setShareOwner('owner')
3950
-			->setPassword(null)
3951
-			->setSendPasswordByTalk(true)
3952
-			->setExpirationDate($tomorrow)
3953
-			->setNode($file)
3954
-			->setPermissions(Constants::PERMISSION_ALL);
3955
-
3956
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
3957
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3958
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
3959
-		$manager->expects($this->never())->method('verifyPassword');
3960
-		$manager->expects($this->never())->method('pathCreateChecks');
3961
-		$manager->expects($this->once())->method('linkCreateChecks');
3962
-		$manager->expects($this->never())->method('validateExpirationDateLink');
3963
-
3964
-		// If the password is empty, we have nothing to hash
3965
-		$this->hasher->expects($this->never())
3966
-			->method('hash');
3967
-
3968
-		$this->defaultProvider->expects($this->never())
3969
-			->method('update');
3970
-
3971
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
3972
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3973
-		$hookListener->expects($this->never())->method('post');
3974
-
3975
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
3976
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3977
-		$hookListener2->expects($this->never())->method('post');
3978
-
3979
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
3980
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3981
-		$hookListener3->expects($this->never())->method('post');
3982
-
3983
-		$manager->updateShare($share);
3984
-	}
3985
-
3986
-
3987
-	public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword(): void {
3988
-		$this->expectException(\InvalidArgumentException::class);
3989
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3990
-
3991
-		$manager = $this->createManagerMock()
3992
-			->onlyMethods([
3993
-				'canShare',
3994
-				'getShareById',
3995
-				'generalCreateChecks',
3996
-				'verifyPassword',
3997
-				'pathCreateChecks',
3998
-				'linkCreateChecks',
3999
-				'validateExpirationDateLink',
4000
-			])
4001
-			->getMock();
4002
-
4003
-		$originalShare = $this->manager->newShare();
4004
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4005
-			->setPermissions(Constants::PERMISSION_ALL)
4006
-			->setPassword('passwordHash')
4007
-			->setSendPasswordByTalk(false);
4008
-
4009
-		$tomorrow = new \DateTime();
4010
-		$tomorrow->setTime(0, 0, 0);
4011
-		$tomorrow->add(new \DateInterval('P1D'));
4012
-
4013
-		$file = $this->createMock(File::class);
4014
-		$file->method('getId')->willReturn(100);
4015
-
4016
-		$share = $this->manager->newShare();
4017
-		$share->setProviderId('foo')
4018
-			->setId('42')
4019
-			->setShareType(IShare::TYPE_EMAIL)
4020
-			->setToken('token')
4021
-			->setSharedBy('owner')
4022
-			->setShareOwner('owner')
4023
-			->setPassword(null)
4024
-			->setSendPasswordByTalk(true)
4025
-			->setExpirationDate($tomorrow)
4026
-			->setNode($file)
4027
-			->setPermissions(Constants::PERMISSION_ALL);
4028
-
4029
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
4030
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4031
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4032
-		$manager->expects($this->once())->method('verifyPassword');
4033
-		$manager->expects($this->never())->method('pathCreateChecks');
4034
-		$manager->expects($this->once())->method('linkCreateChecks');
4035
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4036
-
4037
-		// If the password is empty, we have nothing to hash
4038
-		$this->hasher->expects($this->never())
4039
-			->method('hash');
4040
-
4041
-		$this->defaultProvider->expects($this->never())
4042
-			->method('update');
4043
-
4044
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4045
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4046
-		$hookListener->expects($this->never())->method('post');
4047
-
4048
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4049
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4050
-		$hookListener2->expects($this->never())->method('post');
4051
-
4052
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4053
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4054
-		$hookListener3->expects($this->never())->method('post');
4055
-
4056
-		$manager->updateShare($share);
4057
-	}
4058
-
4059
-
4060
-	public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString(): void {
4061
-		$this->expectException(\InvalidArgumentException::class);
4062
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4063
-
4064
-		$manager = $this->createManagerMock()
4065
-			->onlyMethods([
4066
-				'canShare',
4067
-				'getShareById',
4068
-				'generalCreateChecks',
4069
-				'verifyPassword',
4070
-				'pathCreateChecks',
4071
-				'linkCreateChecks',
4072
-				'validateExpirationDateLink',
4073
-			])
4074
-			->getMock();
4075
-
4076
-		$originalShare = $this->manager->newShare();
4077
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4078
-			->setPermissions(Constants::PERMISSION_ALL)
4079
-			->setPassword('passwordHash')
4080
-			->setSendPasswordByTalk(false);
4081
-
4082
-		$tomorrow = new \DateTime();
4083
-		$tomorrow->setTime(0, 0, 0);
4084
-		$tomorrow->add(new \DateInterval('P1D'));
4085
-
4086
-		$file = $this->createMock(File::class);
4087
-		$file->method('getId')->willReturn(100);
4088
-
4089
-		$share = $this->manager->newShare();
4090
-		$share->setProviderId('foo')
4091
-			->setId('42')
4092
-			->setShareType(IShare::TYPE_EMAIL)
4093
-			->setToken('token')
4094
-			->setSharedBy('owner')
4095
-			->setShareOwner('owner')
4096
-			->setPassword('')
4097
-			->setSendPasswordByTalk(true)
4098
-			->setExpirationDate($tomorrow)
4099
-			->setNode($file)
4100
-			->setPermissions(Constants::PERMISSION_ALL);
4101
-
4102
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
4103
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4104
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4105
-		$manager->expects($this->once())->method('verifyPassword');
4106
-		$manager->expects($this->never())->method('pathCreateChecks');
4107
-		$manager->expects($this->once())->method('linkCreateChecks');
4108
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4109
-
4110
-		// If the password is empty, we have nothing to hash
4111
-		$this->hasher->expects($this->never())
4112
-			->method('hash');
4113
-
4114
-		$this->defaultProvider->expects($this->never())
4115
-			->method('update');
4116
-
4117
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4118
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4119
-		$hookListener->expects($this->never())->method('post');
4120
-
4121
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4122
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4123
-		$hookListener2->expects($this->never())->method('post');
4124
-
4125
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4126
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4127
-		$hookListener3->expects($this->never())->method('post');
4128
-
4129
-		$manager->updateShare($share);
4130
-	}
4131
-
4132
-
4133
-	public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword(): void {
4134
-		$this->expectException(\InvalidArgumentException::class);
4135
-		$this->expectExceptionMessage('Cannot enable sending the password by Talk without setting a new password');
4136
-
4137
-		$manager = $this->createManagerMock()
4138
-			->onlyMethods([
4139
-				'canShare',
4140
-				'getShareById',
4141
-				'generalCreateChecks',
4142
-				'verifyPassword',
4143
-				'pathCreateChecks',
4144
-				'linkCreateChecks',
4145
-				'validateExpirationDateLink',
4146
-			])
4147
-			->getMock();
4148
-
4149
-		$originalShare = $this->manager->newShare();
4150
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4151
-			->setPermissions(Constants::PERMISSION_ALL)
4152
-			->setPassword('password')
4153
-			->setSendPasswordByTalk(false);
4154
-
4155
-		$tomorrow = new \DateTime();
4156
-		$tomorrow->setTime(0, 0, 0);
4157
-		$tomorrow->add(new \DateInterval('P1D'));
4158
-
4159
-		$file = $this->createMock(File::class);
4160
-		$file->method('getId')->willReturn(100);
4161
-
4162
-		$share = $this->manager->newShare();
4163
-		$share->setProviderId('foo')
4164
-			->setId('42')
4165
-			->setShareType(IShare::TYPE_EMAIL)
4166
-			->setToken('token')
4167
-			->setSharedBy('owner')
4168
-			->setShareOwner('owner')
4169
-			->setPassword('password')
4170
-			->setSendPasswordByTalk(true)
4171
-			->setExpirationDate($tomorrow)
4172
-			->setNode($file)
4173
-			->setPermissions(Constants::PERMISSION_ALL);
4174
-
4175
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
4176
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4177
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4178
-		$manager->expects($this->never())->method('verifyPassword');
4179
-		$manager->expects($this->never())->method('pathCreateChecks');
4180
-		$manager->expects($this->once())->method('linkCreateChecks');
4181
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4182
-
4183
-		// If the old & new passwords are the same, we don't do anything
4184
-		$this->hasher->expects($this->never())
4185
-			->method('verify');
4186
-		$this->hasher->expects($this->never())
4187
-			->method('hash');
4188
-
4189
-		$this->defaultProvider->expects($this->never())
4190
-			->method('update');
4191
-
4192
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4193
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4194
-		$hookListener->expects($this->never())->method('post');
4195
-
4196
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4197
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4198
-		$hookListener2->expects($this->never())->method('post');
4199
-
4200
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4201
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4202
-		$hookListener3->expects($this->never())->method('post');
4203
-
4204
-		$manager->updateShare($share);
4205
-	}
4206
-
4207
-	public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword(): void {
4208
-		$this->expectException(\InvalidArgumentException::class);
4209
-		$this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4210
-
4211
-		$manager = $this->createManagerMock()
4212
-			->onlyMethods([
4213
-				'canShare',
4214
-				'getShareById',
4215
-				'generalCreateChecks',
4216
-				'verifyPassword',
4217
-				'pathCreateChecks',
4218
-				'linkCreateChecks',
4219
-				'validateExpirationDateLink',
4220
-			])
4221
-			->getMock();
4222
-
4223
-		$originalShare = $this->manager->newShare();
4224
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4225
-			->setPermissions(Constants::PERMISSION_ALL)
4226
-			->setPassword('passwordHash')
4227
-			->setSendPasswordByTalk(true);
4228
-
4229
-		$tomorrow = new \DateTime();
4230
-		$tomorrow->setTime(0, 0, 0);
4231
-		$tomorrow->add(new \DateInterval('P1D'));
4232
-
4233
-		$file = $this->createMock(File::class);
4234
-		$file->method('getId')->willReturn(100);
4235
-
4236
-		$share = $this->manager->newShare();
4237
-		$share->setProviderId('foo')
4238
-			->setId('42')
4239
-			->setShareType(IShare::TYPE_EMAIL)
4240
-			->setToken('token')
4241
-			->setSharedBy('owner')
4242
-			->setShareOwner('owner')
4243
-			->setPassword('passwordHash')
4244
-			->setSendPasswordByTalk(false)
4245
-			->setExpirationDate($tomorrow)
4246
-			->setNode($file)
4247
-			->setPermissions(Constants::PERMISSION_ALL);
4248
-
4249
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
4250
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4251
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4252
-		$manager->expects($this->never())->method('verifyPassword');
4253
-		$manager->expects($this->never())->method('pathCreateChecks');
4254
-		$manager->expects($this->once())->method('linkCreateChecks');
4255
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4256
-
4257
-		// If the old & new passwords are the same, we don't do anything
4258
-		$this->hasher->expects($this->never())
4259
-			->method('verify');
4260
-		$this->hasher->expects($this->never())
4261
-			->method('hash');
4262
-
4263
-		$this->defaultProvider->expects($this->never())
4264
-			->method('update');
4265
-
4266
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4267
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4268
-		$hookListener->expects($this->never())->method('post');
4269
-
4270
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4271
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4272
-		$hookListener2->expects($this->never())->method('post');
4273
-
4274
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4275
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4276
-		$hookListener3->expects($this->never())->method('post');
4277
-
4278
-		$manager->updateShare($share);
4279
-	}
4280
-
4281
-	public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword(): void {
4282
-		$this->expectException(\InvalidArgumentException::class);
4283
-		$this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4284
-
4285
-		$manager = $this->createManagerMock()
4286
-			->onlyMethods([
4287
-				'canShare',
4288
-				'getShareById',
4289
-				'generalCreateChecks',
4290
-				'verifyPassword',
4291
-				'pathCreateChecks',
4292
-				'linkCreateChecks',
4293
-				'validateExpirationDateLink',
4294
-			])
4295
-			->getMock();
4296
-
4297
-		$originalShare = $this->manager->newShare();
4298
-		$originalShare->setShareType(IShare::TYPE_EMAIL)
4299
-			->setPermissions(Constants::PERMISSION_ALL)
4300
-			->setPassword('passwordHash')
4301
-			->setSendPasswordByTalk(true);
4302
-
4303
-		$tomorrow = new \DateTime();
4304
-		$tomorrow->setTime(0, 0, 0);
4305
-		$tomorrow->add(new \DateInterval('P1D'));
4306
-
4307
-		$file = $this->createMock(File::class);
4308
-		$file->method('getId')->willReturn(100);
4309
-
4310
-		$share = $this->manager->newShare();
4311
-		$share->setProviderId('foo')
4312
-			->setId('42')
4313
-			->setShareType(IShare::TYPE_EMAIL)
4314
-			->setToken('token')
4315
-			->setSharedBy('owner')
4316
-			->setShareOwner('owner')
4317
-			->setPassword('passwordHash')
4318
-			->setSendPasswordByTalk(false)
4319
-			->setExpirationDate($tomorrow)
4320
-			->setNode($file)
4321
-			->setPermissions(Constants::PERMISSION_ALL);
4322
-
4323
-		$manager->expects($this->once())->method('canShare')->willReturn(true);
4324
-		$manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4325
-		$manager->expects($this->once())->method('generalCreateChecks')->with($share);
4326
-		$manager->expects($this->never())->method('verifyPassword');
4327
-		$manager->expects($this->never())->method('pathCreateChecks');
4328
-		$manager->expects($this->once())->method('linkCreateChecks');
4329
-		$manager->expects($this->never())->method('validateExpirationDateLink');
4330
-
4331
-		// If the old & new passwords are the same, we don't do anything
4332
-		$this->hasher->expects($this->never())
4333
-			->method('verify');
4334
-		$this->hasher->expects($this->never())
4335
-			->method('hash');
4336
-
4337
-		$this->defaultProvider->expects($this->never())
4338
-			->method('update');
4339
-
4340
-		$hookListener = $this->createMock(DummyShareManagerListener::class);
4341
-		Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4342
-		$hookListener->expects($this->never())->method('post');
2979
+        $manager->method('deleteShare')
2980
+            ->willReturnCallback(function ($share) use (&$shares2): void {
2981
+                for ($i = 0; $i < count($shares2); $i++) {
2982
+                    if ($shares2[$i]->getId() === $share->getId()) {
2983
+                        array_splice($shares2, $i, 1);
2984
+                        break;
2985
+                    }
2986
+                }
2987
+            });
2988
+
2989
+        $res = $manager->getSharesBy('user', IShare::TYPE_LINK, $node, true, 3, 0);
2990
+
2991
+        $this->assertCount(3, $res);
2992
+        $this->assertEquals($shares[0]->getId(), $res[0]->getId());
2993
+        $this->assertEquals($shares[1]->getId(), $res[1]->getId());
2994
+        $this->assertEquals($shares[6]->getId(), $res[2]->getId());
2995
+
2996
+        $this->assertCount(4, $shares2);
2997
+        $this->assertEquals(0, $shares2[0]->getId());
2998
+        $this->assertEquals(1, $shares2[1]->getId());
2999
+        $this->assertEquals(6, $shares2[2]->getId());
3000
+        $this->assertEquals(7, $shares2[3]->getId());
3001
+        $this->assertSame($today, $shares[3]->getExpirationDate());
3002
+    }
3003
+
3004
+    public function testGetShareByToken(): void {
3005
+        $this->config
3006
+            ->expects($this->exactly(2))
3007
+            ->method('getAppValue')
3008
+            ->willReturnMap([
3009
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3010
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3011
+            ]);
3012
+
3013
+        $factory = $this->createMock(IProviderFactory::class);
3014
+
3015
+        $manager = $this->createManager($factory);
3016
+
3017
+        $share = $this->createMock(IShare::class);
3018
+
3019
+        $factory->expects($this->once())
3020
+            ->method('getProviderForType')
3021
+            ->with(IShare::TYPE_LINK)
3022
+            ->willReturn($this->defaultProvider);
3023
+
3024
+        $this->defaultProvider->expects($this->once())
3025
+            ->method('getShareByToken')
3026
+            ->with('token')
3027
+            ->willReturn($share);
3028
+
3029
+        $ret = $manager->getShareByToken('token');
3030
+        $this->assertSame($share, $ret);
3031
+    }
3032
+
3033
+    public function testGetShareByTokenRoom(): void {
3034
+        $this->config
3035
+            ->expects($this->exactly(2))
3036
+            ->method('getAppValue')
3037
+            ->willReturnMap([
3038
+                ['core', 'shareapi_allow_links', 'yes', 'no'],
3039
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3040
+            ]);
3041
+
3042
+        $factory = $this->createMock(IProviderFactory::class);
3043
+
3044
+        $manager = $this->createManager($factory);
3045
+
3046
+        $share = $this->createMock(IShare::class);
3047
+
3048
+        $roomShareProvider = $this->createMock(IShareProvider::class);
3049
+
3050
+        $factory->expects($this->any())
3051
+            ->method('getProviderForType')
3052
+            ->willReturnCallback(function ($shareType) use ($roomShareProvider) {
3053
+                if ($shareType !== IShare::TYPE_ROOM) {
3054
+                    throw new ProviderException();
3055
+                }
3056
+
3057
+                return $roomShareProvider;
3058
+            });
3059
+
3060
+        $roomShareProvider->expects($this->once())
3061
+            ->method('getShareByToken')
3062
+            ->with('token')
3063
+            ->willReturn($share);
3064
+
3065
+        $ret = $manager->getShareByToken('token');
3066
+        $this->assertSame($share, $ret);
3067
+    }
3068
+
3069
+    public function testGetShareByTokenWithException(): void {
3070
+        $this->config
3071
+            ->expects($this->exactly(2))
3072
+            ->method('getAppValue')
3073
+            ->willReturnMap([
3074
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3075
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3076
+            ]);
3077
+
3078
+        $factory = $this->createMock(IProviderFactory::class);
3079
+
3080
+        $manager = $this->createManager($factory);
3081
+
3082
+        $share = $this->createMock(IShare::class);
3083
+
3084
+        $calls = [
3085
+            [IShare::TYPE_LINK],
3086
+            [IShare::TYPE_REMOTE],
3087
+        ];
3088
+        $factory->expects($this->exactly(2))
3089
+            ->method('getProviderForType')
3090
+            ->willReturnCallback(function () use (&$calls) {
3091
+                $expected = array_shift($calls);
3092
+                $this->assertEquals($expected, func_get_args());
3093
+                return $this->defaultProvider;
3094
+            });
3095
+
3096
+        $this->defaultProvider->expects($this->exactly(2))
3097
+            ->method('getShareByToken')
3098
+            ->with('token')
3099
+            ->willReturnOnConsecutiveCalls(
3100
+                $this->throwException(new ShareNotFound()),
3101
+                $share
3102
+            );
3103
+
3104
+        $ret = $manager->getShareByToken('token');
3105
+        $this->assertSame($share, $ret);
3106
+    }
3107
+
3108
+
3109
+    public function testGetShareByTokenHideDisabledUser(): void {
3110
+        $this->expectException(ShareNotFound::class);
3111
+        $this->expectExceptionMessage('The requested share comes from a disabled user');
3112
+
3113
+        $this->config
3114
+            ->expects($this->exactly(2))
3115
+            ->method('getAppValue')
3116
+            ->willReturnMap([
3117
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3118
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'yes'],
3119
+            ]);
3120
+
3121
+        $this->l->expects($this->once())
3122
+            ->method('t')
3123
+            ->willReturnArgument(0);
3124
+
3125
+        $manager = $this->createManagerMock()
3126
+            ->onlyMethods(['deleteShare'])
3127
+            ->getMock();
3128
+
3129
+        $date = new \DateTime();
3130
+        $date->setTime(0, 0, 0);
3131
+        $date->add(new \DateInterval('P2D'));
3132
+        $share = $this->manager->newShare();
3133
+        $share->setExpirationDate($date);
3134
+        $share->setShareOwner('owner');
3135
+        $share->setSharedBy('sharedBy');
3136
+
3137
+        $sharedBy = $this->createMock(IUser::class);
3138
+        $owner = $this->createMock(IUser::class);
3139
+
3140
+        $this->userManager->method('get')->willReturnMap([
3141
+            ['sharedBy', $sharedBy],
3142
+            ['owner', $owner],
3143
+        ]);
3144
+
3145
+        $owner->expects($this->once())
3146
+            ->method('isEnabled')
3147
+            ->willReturn(true);
3148
+        $sharedBy->expects($this->once())
3149
+            ->method('isEnabled')
3150
+            ->willReturn(false);
3151
+
3152
+        $this->defaultProvider->expects($this->once())
3153
+            ->method('getShareByToken')
3154
+            ->with('expiredToken')
3155
+            ->willReturn($share);
3156
+
3157
+        $manager->expects($this->never())
3158
+            ->method('deleteShare');
3159
+
3160
+        $manager->getShareByToken('expiredToken');
3161
+    }
3162
+
3163
+
3164
+    public function testGetShareByTokenExpired(): void {
3165
+        $this->expectException(ShareNotFound::class);
3166
+        $this->expectExceptionMessage('The requested share does not exist anymore');
3167
+
3168
+        $this->config
3169
+            ->expects($this->once())
3170
+            ->method('getAppValue')
3171
+            ->with('core', 'shareapi_allow_links', 'yes')
3172
+            ->willReturn('yes');
3173
+
3174
+        $this->l->expects($this->once())
3175
+            ->method('t')
3176
+            ->willReturnArgument(0);
3177
+
3178
+        $manager = $this->createManagerMock()
3179
+            ->onlyMethods(['deleteShare'])
3180
+            ->getMock();
3181
+
3182
+        $date = new \DateTime();
3183
+        $date->setTime(0, 0, 0);
3184
+        $share = $this->manager->newShare();
3185
+        $share->setExpirationDate($date);
3186
+
3187
+        $this->defaultProvider->expects($this->once())
3188
+            ->method('getShareByToken')
3189
+            ->with('expiredToken')
3190
+            ->willReturn($share);
3191
+
3192
+        $manager->expects($this->once())
3193
+            ->method('deleteShare')
3194
+            ->with($this->equalTo($share));
3195
+
3196
+        $manager->getShareByToken('expiredToken');
3197
+    }
3198
+
3199
+    public function testGetShareByTokenNotExpired(): void {
3200
+        $this->config
3201
+            ->expects($this->exactly(2))
3202
+            ->method('getAppValue')
3203
+            ->willReturnMap([
3204
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3205
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3206
+            ]);
3207
+
3208
+        $date = new \DateTime();
3209
+        $date->setTime(0, 0, 0);
3210
+        $date->add(new \DateInterval('P2D'));
3211
+        $share = $this->manager->newShare();
3212
+        $share->setExpirationDate($date);
3213
+
3214
+        $this->defaultProvider->expects($this->once())
3215
+            ->method('getShareByToken')
3216
+            ->with('expiredToken')
3217
+            ->willReturn($share);
3218
+
3219
+        $res = $this->manager->getShareByToken('expiredToken');
3220
+
3221
+        $this->assertSame($share, $res);
3222
+    }
3223
+
3224
+
3225
+    public function testGetShareByTokenWithPublicLinksDisabled(): void {
3226
+        $this->expectException(ShareNotFound::class);
3227
+
3228
+        $this->config
3229
+            ->expects($this->once())
3230
+            ->method('getAppValue')
3231
+            ->with('core', 'shareapi_allow_links', 'yes')
3232
+            ->willReturn('no');
3233
+        $this->manager->getShareByToken('validToken');
3234
+    }
3235
+
3236
+    public function testGetShareByTokenPublicUploadDisabled(): void {
3237
+        $this->config
3238
+            ->expects($this->exactly(3))
3239
+            ->method('getAppValue')
3240
+            ->willReturnMap([
3241
+                ['core', 'shareapi_allow_links', 'yes', 'yes'],
3242
+                ['core', 'shareapi_allow_public_upload', 'yes', 'no'],
3243
+                ['files_sharing', 'hide_disabled_user_shares', 'no', 'no'],
3244
+            ]);
3245
+
3246
+        $share = $this->manager->newShare();
3247
+        $share->setShareType(IShare::TYPE_LINK)
3248
+            ->setPermissions(Constants::PERMISSION_READ | Constants::PERMISSION_CREATE | Constants::PERMISSION_UPDATE);
3249
+        $share->setSharedWith('sharedWith');
3250
+        $folder = $this->createMock(\OC\Files\Node\Folder::class);
3251
+        $share->setNode($folder);
3252
+
3253
+        $this->defaultProvider->expects($this->once())
3254
+            ->method('getShareByToken')
3255
+            ->willReturn('validToken')
3256
+            ->willReturn($share);
3257
+
3258
+        $res = $this->manager->getShareByToken('validToken');
3259
+
3260
+        $this->assertSame(Constants::PERMISSION_READ, $res->getPermissions());
3261
+    }
3262
+
3263
+    public function testCheckPasswordNoLinkShare(): void {
3264
+        $share = $this->createMock(IShare::class);
3265
+        $share->method('getShareType')->willReturn(IShare::TYPE_USER);
3266
+        $this->assertFalse($this->manager->checkPassword($share, 'password'));
3267
+    }
3268
+
3269
+    public function testCheckPasswordNoPassword(): void {
3270
+        $share = $this->createMock(IShare::class);
3271
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3272
+        $this->assertFalse($this->manager->checkPassword($share, 'password'));
3273
+
3274
+        $share->method('getPassword')->willReturn('password');
3275
+        $this->assertFalse($this->manager->checkPassword($share, null));
3276
+    }
3277
+
3278
+    public function testCheckPasswordInvalidPassword(): void {
3279
+        $share = $this->createMock(IShare::class);
3280
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3281
+        $share->method('getPassword')->willReturn('password');
3282
+
3283
+        $this->hasher->method('verify')->with('invalidpassword', 'password', '')->willReturn(false);
3284
+
3285
+        $this->assertFalse($this->manager->checkPassword($share, 'invalidpassword'));
3286
+    }
3287
+
3288
+    public function testCheckPasswordValidPassword(): void {
3289
+        $share = $this->createMock(IShare::class);
3290
+        $share->method('getShareType')->willReturn(IShare::TYPE_LINK);
3291
+        $share->method('getPassword')->willReturn('passwordHash');
3292
+
3293
+        $this->hasher->method('verify')->with('password', 'passwordHash', '')->willReturn(true);
3294
+
3295
+        $this->assertTrue($this->manager->checkPassword($share, 'password'));
3296
+    }
3297
+
3298
+    public function testCheckPasswordUpdateShare(): void {
3299
+        $share = $this->manager->newShare();
3300
+        $share->setShareType(IShare::TYPE_LINK)
3301
+            ->setPassword('passwordHash');
3302
+
3303
+        $this->hasher->method('verify')->with('password', 'passwordHash', '')
3304
+            ->willReturnCallback(function ($pass, $hash, &$newHash) {
3305
+                $newHash = 'newHash';
3306
+
3307
+                return true;
3308
+            });
3309
+
3310
+        $this->defaultProvider->expects($this->once())
3311
+            ->method('update')
3312
+            ->with($this->callback(function (IShare $share) {
3313
+                return $share->getPassword() === 'newHash';
3314
+            }));
3315
+
3316
+        $this->assertTrue($this->manager->checkPassword($share, 'password'));
3317
+    }
3318
+
3319
+
3320
+    public function testUpdateShareCantChangeShareType(): void {
3321
+        $this->expectException(\Exception::class);
3322
+        $this->expectExceptionMessage('Cannot change share type');
3323
+
3324
+        $manager = $this->createManagerMock()
3325
+            ->onlyMethods([
3326
+                'canShare',
3327
+                'getShareById'
3328
+            ])
3329
+            ->getMock();
3330
+
3331
+        $originalShare = $this->manager->newShare();
3332
+        $originalShare->setShareType(IShare::TYPE_GROUP);
3333
+
3334
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3335
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3336
+
3337
+        $share = $this->manager->newShare();
3338
+        $attrs = $this->manager->newShare()->newAttributes();
3339
+        $attrs->setAttribute('app1', 'perm1', true);
3340
+        $share->setProviderId('foo')
3341
+            ->setId('42')
3342
+            ->setShareType(IShare::TYPE_USER);
3343
+
3344
+        $manager->updateShare($share);
3345
+    }
3346
+
3347
+
3348
+    public function testUpdateShareCantChangeRecipientForGroupShare(): void {
3349
+        $this->expectException(\Exception::class);
3350
+        $this->expectExceptionMessage('Can only update recipient on user shares');
3351
+
3352
+        $manager = $this->createManagerMock()
3353
+            ->onlyMethods([
3354
+                'canShare',
3355
+                'getShareById'
3356
+            ])
3357
+            ->getMock();
3358
+
3359
+        $originalShare = $this->manager->newShare();
3360
+        $originalShare->setShareType(IShare::TYPE_GROUP)
3361
+            ->setSharedWith('origGroup');
3362
+
3363
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3364
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3365
+
3366
+        $share = $this->manager->newShare();
3367
+        $share->setProviderId('foo')
3368
+            ->setId('42')
3369
+            ->setShareType(IShare::TYPE_GROUP)
3370
+            ->setSharedWith('newGroup');
3371
+
3372
+        $manager->updateShare($share);
3373
+    }
3374
+
3375
+
3376
+    public function testUpdateShareCantShareWithOwner(): void {
3377
+        $this->expectException(\Exception::class);
3378
+        $this->expectExceptionMessage('Cannot share with the share owner');
3379
+
3380
+        $manager = $this->createManagerMock()
3381
+            ->onlyMethods([
3382
+                'canShare',
3383
+                'getShareById'
3384
+            ])
3385
+            ->getMock();
3386
+
3387
+        $originalShare = $this->manager->newShare();
3388
+        $originalShare->setShareType(IShare::TYPE_USER)
3389
+            ->setSharedWith('sharedWith');
3390
+
3391
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3392
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3393
+
3394
+        $share = $this->manager->newShare();
3395
+        $share->setProviderId('foo')
3396
+            ->setId('42')
3397
+            ->setShareType(IShare::TYPE_USER)
3398
+            ->setSharedWith('newUser')
3399
+            ->setShareOwner('newUser');
3400
+
3401
+        $manager->updateShare($share);
3402
+    }
3403
+
3404
+    public function testUpdateShareUser(): void {
3405
+        $this->userManager->expects($this->any())->method('userExists')->willReturn(true);
3406
+
3407
+        $manager = $this->createManagerMock()
3408
+            ->onlyMethods([
3409
+                'canShare',
3410
+                'getShareById',
3411
+                'generalCreateChecks',
3412
+                'userCreateChecks',
3413
+                'pathCreateChecks',
3414
+            ])
3415
+            ->getMock();
3416
+
3417
+        $originalShare = $this->manager->newShare();
3418
+        $originalShare->setShareType(IShare::TYPE_USER)
3419
+            ->setSharedWith('origUser')
3420
+            ->setPermissions(1);
3421
+
3422
+        $node = $this->createMock(File::class);
3423
+        $node->method('getId')->willReturn(100);
3424
+        $node->method('getPath')->willReturn('/newUser/files/myPath');
3425
+
3426
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3427
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3428
+
3429
+        $share = $this->manager->newShare();
3430
+        $attrs = $this->manager->newShare()->newAttributes();
3431
+        $attrs->setAttribute('app1', 'perm1', true);
3432
+        $share->setProviderId('foo')
3433
+            ->setId('42')
3434
+            ->setShareType(IShare::TYPE_USER)
3435
+            ->setSharedWith('origUser')
3436
+            ->setShareOwner('newUser')
3437
+            ->setSharedBy('sharer')
3438
+            ->setPermissions(31)
3439
+            ->setAttributes($attrs)
3440
+            ->setNode($node);
3441
+
3442
+        $this->defaultProvider->expects($this->once())
3443
+            ->method('update')
3444
+            ->with($share)
3445
+            ->willReturn($share);
3446
+
3447
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3448
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3449
+        $hookListener->expects($this->never())->method('post');
3450
+
3451
+        $this->rootFolder->method('getUserFolder')->with('newUser')->willReturnSelf();
3452
+        $this->rootFolder->method('getRelativePath')->with('/newUser/files/myPath')->willReturn('/myPath');
3453
+
3454
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3455
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3456
+        $hookListener2->expects($this->once())->method('post')->with([
3457
+            'itemType' => 'file',
3458
+            'itemSource' => 100,
3459
+            'shareType' => IShare::TYPE_USER,
3460
+            'shareWith' => 'origUser',
3461
+            'uidOwner' => 'sharer',
3462
+            'permissions' => 31,
3463
+            'path' => '/myPath',
3464
+            'attributes' => $attrs->toArray(),
3465
+        ]);
3466
+
3467
+        $manager->updateShare($share);
3468
+    }
3469
+
3470
+    public function testUpdateShareGroup(): void {
3471
+        $manager = $this->createManagerMock()
3472
+            ->onlyMethods([
3473
+                'canShare',
3474
+                'getShareById',
3475
+                'generalCreateChecks',
3476
+                'groupCreateChecks',
3477
+                'pathCreateChecks',
3478
+            ])
3479
+            ->getMock();
3480
+
3481
+        $originalShare = $this->manager->newShare();
3482
+        $originalShare->setShareType(IShare::TYPE_GROUP)
3483
+            ->setSharedWith('origUser')
3484
+            ->setPermissions(31);
3485
+
3486
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3487
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3488
+
3489
+        $node = $this->createMock(File::class);
3490
+
3491
+        $share = $this->manager->newShare();
3492
+        $share->setProviderId('foo')
3493
+            ->setId('42')
3494
+            ->setShareType(IShare::TYPE_GROUP)
3495
+            ->setSharedWith('origUser')
3496
+            ->setShareOwner('owner')
3497
+            ->setNode($node)
3498
+            ->setPermissions(31);
3499
+
3500
+        $this->defaultProvider->expects($this->once())
3501
+            ->method('update')
3502
+            ->with($share)
3503
+            ->willReturn($share);
3504
+
3505
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3506
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3507
+        $hookListener->expects($this->never())->method('post');
3508
+
3509
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3510
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener2, 'post');
3511
+        $hookListener2->expects($this->never())->method('post');
3512
+
3513
+        $manager->updateShare($share);
3514
+    }
3515
+
3516
+    public function testUpdateShareLink(): void {
3517
+        $manager = $this->createManagerMock()
3518
+            ->onlyMethods([
3519
+                'canShare',
3520
+                'getShareById',
3521
+                'generalCreateChecks',
3522
+                'linkCreateChecks',
3523
+                'pathCreateChecks',
3524
+                'verifyPassword',
3525
+                'validateExpirationDateLink',
3526
+            ])
3527
+            ->getMock();
3528
+
3529
+        $originalShare = $this->manager->newShare();
3530
+        $originalShare->setShareType(IShare::TYPE_LINK)
3531
+            ->setPermissions(15);
3532
+
3533
+        $tomorrow = new \DateTime();
3534
+        $tomorrow->setTime(0, 0, 0);
3535
+        $tomorrow->add(new \DateInterval('P1D'));
3536
+
3537
+        $file = $this->createMock(File::class);
3538
+        $file->method('getId')->willReturn(100);
3539
+
3540
+        $share = $this->manager->newShare();
3541
+        $share->setProviderId('foo')
3542
+            ->setId('42')
3543
+            ->setShareType(IShare::TYPE_LINK)
3544
+            ->setToken('token')
3545
+            ->setSharedBy('owner')
3546
+            ->setShareOwner('owner')
3547
+            ->setPassword('password')
3548
+            ->setExpirationDate($tomorrow)
3549
+            ->setNode($file)
3550
+            ->setPermissions(15);
3551
+
3552
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3553
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3554
+        $manager->expects($this->once())->method('validateExpirationDateLink')->with($share);
3555
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3556
+
3557
+        $this->hasher->expects($this->once())
3558
+            ->method('hash')
3559
+            ->with('password')
3560
+            ->willReturn('hashed');
3561
+
3562
+        $this->defaultProvider->expects($this->once())
3563
+            ->method('update')
3564
+            ->with($share)
3565
+            ->willReturn($share);
3566
+
3567
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3568
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3569
+        $hookListener->expects($this->once())->method('post')->with([
3570
+            'itemType' => 'file',
3571
+            'itemSource' => 100,
3572
+            'date' => $tomorrow,
3573
+            'uidOwner' => 'owner',
3574
+        ]);
3575
+
3576
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3577
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3578
+        $hookListener2->expects($this->once())->method('post')->with([
3579
+            'itemType' => 'file',
3580
+            'itemSource' => 100,
3581
+            'uidOwner' => 'owner',
3582
+            'token' => 'token',
3583
+            'disabled' => false,
3584
+        ]);
3585
+
3586
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3587
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3588
+        $hookListener3->expects($this->never())->method('post');
3589
+
3590
+
3591
+        $manager->updateShare($share);
3592
+    }
3593
+
3594
+    public function testUpdateShareLinkEnableSendPasswordByTalkWithNoPassword(): void {
3595
+        $this->expectException(\InvalidArgumentException::class);
3596
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3597
+
3598
+        $manager = $this->createManagerMock()
3599
+            ->onlyMethods([
3600
+                'canShare',
3601
+                'getShareById',
3602
+                'generalCreateChecks',
3603
+                'linkCreateChecks',
3604
+                'pathCreateChecks',
3605
+                'verifyPassword',
3606
+                'validateExpirationDateLink',
3607
+            ])
3608
+            ->getMock();
3609
+
3610
+        $originalShare = $this->manager->newShare();
3611
+        $originalShare->setShareType(IShare::TYPE_LINK)
3612
+            ->setPermissions(15);
3613
+
3614
+        $tomorrow = new \DateTime();
3615
+        $tomorrow->setTime(0, 0, 0);
3616
+        $tomorrow->add(new \DateInterval('P1D'));
3617
+
3618
+        $file = $this->createMock(File::class);
3619
+        $file->method('getId')->willReturn(100);
3620
+
3621
+        $share = $this->manager->newShare();
3622
+        $share->setProviderId('foo')
3623
+            ->setId('42')
3624
+            ->setShareType(IShare::TYPE_LINK)
3625
+            ->setToken('token')
3626
+            ->setSharedBy('owner')
3627
+            ->setShareOwner('owner')
3628
+            ->setPassword(null)
3629
+            ->setSendPasswordByTalk(true)
3630
+            ->setExpirationDate($tomorrow)
3631
+            ->setNode($file)
3632
+            ->setPermissions(15);
3633
+
3634
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3635
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3636
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3637
+        $manager->expects($this->once())->method('linkCreateChecks')->with($share);
3638
+        $manager->expects($this->never())->method('verifyPassword');
3639
+        $manager->expects($this->never())->method('pathCreateChecks');
3640
+        $manager->expects($this->never())->method('validateExpirationDateLink');
3641
+
3642
+        $this->hasher->expects($this->never())
3643
+            ->method('hash');
3644
+
3645
+        $this->defaultProvider->expects($this->never())
3646
+            ->method('update');
3647
+
3648
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3649
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3650
+        $hookListener->expects($this->never())->method('post');
3651
+
3652
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3653
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3654
+        $hookListener2->expects($this->never())->method('post');
3655
+
3656
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3657
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3658
+        $hookListener3->expects($this->never())->method('post');
3659
+
3660
+        $manager->updateShare($share);
3661
+    }
3662
+
3663
+    public function testUpdateShareMail(): void {
3664
+        $manager = $this->createManagerMock()
3665
+            ->onlyMethods([
3666
+                'canShare',
3667
+                'getShareById',
3668
+                'generalCreateChecks',
3669
+                'verifyPassword',
3670
+                'pathCreateChecks',
3671
+                'linkCreateChecks',
3672
+                'validateExpirationDateLink',
3673
+            ])
3674
+            ->getMock();
3675
+
3676
+        $originalShare = $this->manager->newShare();
3677
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3678
+            ->setPermissions(Constants::PERMISSION_ALL);
3679
+
3680
+        $tomorrow = new \DateTime();
3681
+        $tomorrow->setTime(0, 0, 0);
3682
+        $tomorrow->add(new \DateInterval('P1D'));
3683
+
3684
+        $file = $this->createMock(File::class);
3685
+        $file->method('getId')->willReturn(100);
3686
+
3687
+        $share = $this->manager->newShare();
3688
+        $share->setProviderId('foo')
3689
+            ->setId('42')
3690
+            ->setShareType(IShare::TYPE_EMAIL)
3691
+            ->setToken('token')
3692
+            ->setSharedBy('owner')
3693
+            ->setShareOwner('owner')
3694
+            ->setPassword('password')
3695
+            ->setExpirationDate($tomorrow)
3696
+            ->setNode($file)
3697
+            ->setPermissions(Constants::PERMISSION_ALL);
3698
+
3699
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3700
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3701
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3702
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3703
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
3704
+        $manager->expects($this->once())->method('linkCreateChecks');
3705
+        $manager->expects($this->once())->method('validateExpirationDateLink');
3706
+
3707
+        $this->hasher->expects($this->once())
3708
+            ->method('hash')
3709
+            ->with('password')
3710
+            ->willReturn('hashed');
3711
+
3712
+        $this->defaultProvider->expects($this->once())
3713
+            ->method('update')
3714
+            ->with($share, 'password')
3715
+            ->willReturn($share);
3716
+
3717
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3718
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3719
+        $hookListener->expects($this->once())->method('post')->with([
3720
+            'itemType' => 'file',
3721
+            'itemSource' => 100,
3722
+            'date' => $tomorrow,
3723
+            'uidOwner' => 'owner',
3724
+        ]);
3725
+
3726
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3727
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3728
+        $hookListener2->expects($this->once())->method('post')->with([
3729
+            'itemType' => 'file',
3730
+            'itemSource' => 100,
3731
+            'uidOwner' => 'owner',
3732
+            'token' => 'token',
3733
+            'disabled' => false,
3734
+        ]);
3735
+
3736
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3737
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3738
+        $hookListener3->expects($this->never())->method('post');
3739
+
3740
+        $manager->updateShare($share);
3741
+    }
3742
+
3743
+    public function testUpdateShareMailEnableSendPasswordByTalk(): void {
3744
+        $manager = $this->createManagerMock()
3745
+            ->onlyMethods([
3746
+                'canShare',
3747
+                'getShareById',
3748
+                'generalCreateChecks',
3749
+                'verifyPassword',
3750
+                'pathCreateChecks',
3751
+                'linkCreateChecks',
3752
+                'validateExpirationDateLink',
3753
+            ])
3754
+            ->getMock();
3755
+
3756
+        $originalShare = $this->manager->newShare();
3757
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3758
+            ->setPermissions(Constants::PERMISSION_ALL)
3759
+            ->setPassword(null)
3760
+            ->setSendPasswordByTalk(false);
3761
+
3762
+        $tomorrow = new \DateTime();
3763
+        $tomorrow->setTime(0, 0, 0);
3764
+        $tomorrow->add(new \DateInterval('P1D'));
3765
+
3766
+        $file = $this->createMock(File::class);
3767
+        $file->method('getId')->willReturn(100);
3768
+
3769
+        $share = $this->manager->newShare();
3770
+        $share->setProviderId('foo')
3771
+            ->setId('42')
3772
+            ->setShareType(IShare::TYPE_EMAIL)
3773
+            ->setToken('token')
3774
+            ->setSharedBy('owner')
3775
+            ->setShareOwner('owner')
3776
+            ->setPassword('password')
3777
+            ->setSendPasswordByTalk(true)
3778
+            ->setExpirationDate($tomorrow)
3779
+            ->setNode($file)
3780
+            ->setPermissions(Constants::PERMISSION_ALL);
3781
+
3782
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3783
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3784
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3785
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3786
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
3787
+        $manager->expects($this->once())->method('linkCreateChecks');
3788
+        $manager->expects($this->once())->method('validateExpirationDateLink');
3789
+
3790
+        $this->hasher->expects($this->once())
3791
+            ->method('hash')
3792
+            ->with('password')
3793
+            ->willReturn('hashed');
3794
+
3795
+        $this->defaultProvider->expects($this->once())
3796
+            ->method('update')
3797
+            ->with($share, 'password')
3798
+            ->willReturn($share);
3799
+
3800
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3801
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3802
+        $hookListener->expects($this->once())->method('post')->with([
3803
+            'itemType' => 'file',
3804
+            'itemSource' => 100,
3805
+            'date' => $tomorrow,
3806
+            'uidOwner' => 'owner',
3807
+        ]);
3808
+
3809
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3810
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3811
+        $hookListener2->expects($this->once())->method('post')->with([
3812
+            'itemType' => 'file',
3813
+            'itemSource' => 100,
3814
+            'uidOwner' => 'owner',
3815
+            'token' => 'token',
3816
+            'disabled' => false,
3817
+        ]);
3818
+
3819
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3820
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3821
+        $hookListener3->expects($this->never())->method('post');
3822
+
3823
+        $manager->updateShare($share);
3824
+    }
3825
+
3826
+    public function testUpdateShareMailEnableSendPasswordByTalkWithDifferentPassword(): void {
3827
+        $manager = $this->createManagerMock()
3828
+            ->onlyMethods([
3829
+                'canShare',
3830
+                'getShareById',
3831
+                'generalCreateChecks',
3832
+                'verifyPassword',
3833
+                'pathCreateChecks',
3834
+                'linkCreateChecks',
3835
+                'validateExpirationDateLink',
3836
+            ])
3837
+            ->getMock();
3838
+
3839
+        $originalShare = $this->manager->newShare();
3840
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3841
+            ->setPermissions(Constants::PERMISSION_ALL)
3842
+            ->setPassword('anotherPasswordHash')
3843
+            ->setSendPasswordByTalk(false);
3844
+
3845
+        $tomorrow = new \DateTime();
3846
+        $tomorrow->setTime(0, 0, 0);
3847
+        $tomorrow->add(new \DateInterval('P1D'));
3848
+
3849
+        $file = $this->createMock(File::class);
3850
+        $file->method('getId')->willReturn(100);
3851
+
3852
+        $share = $this->manager->newShare();
3853
+        $share->setProviderId('foo')
3854
+            ->setId('42')
3855
+            ->setShareType(IShare::TYPE_EMAIL)
3856
+            ->setToken('token')
3857
+            ->setSharedBy('owner')
3858
+            ->setShareOwner('owner')
3859
+            ->setPassword('password')
3860
+            ->setSendPasswordByTalk(true)
3861
+            ->setExpirationDate($tomorrow)
3862
+            ->setNode($file)
3863
+            ->setPermissions(Constants::PERMISSION_ALL);
3864
+
3865
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3866
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3867
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3868
+        $manager->expects($this->once())->method('verifyPassword')->with('password');
3869
+        $manager->expects($this->once())->method('pathCreateChecks')->with($file);
3870
+        $manager->expects($this->once())->method('linkCreateChecks');
3871
+        $manager->expects($this->once())->method('validateExpirationDateLink');
3872
+
3873
+        $this->hasher->expects($this->once())
3874
+            ->method('verify')
3875
+            ->with('password', 'anotherPasswordHash')
3876
+            ->willReturn(false);
3877
+
3878
+        $this->hasher->expects($this->once())
3879
+            ->method('hash')
3880
+            ->with('password')
3881
+            ->willReturn('hashed');
3882
+
3883
+        $this->defaultProvider->expects($this->once())
3884
+            ->method('update')
3885
+            ->with($share, 'password')
3886
+            ->willReturn($share);
3887
+
3888
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3889
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3890
+        $hookListener->expects($this->once())->method('post')->with([
3891
+            'itemType' => 'file',
3892
+            'itemSource' => 100,
3893
+            'date' => $tomorrow,
3894
+            'uidOwner' => 'owner',
3895
+        ]);
3896
+
3897
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3898
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3899
+        $hookListener2->expects($this->once())->method('post')->with([
3900
+            'itemType' => 'file',
3901
+            'itemSource' => 100,
3902
+            'uidOwner' => 'owner',
3903
+            'token' => 'token',
3904
+            'disabled' => false,
3905
+        ]);
3906
+
3907
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3908
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3909
+        $hookListener3->expects($this->never())->method('post');
3910
+
3911
+        $manager->updateShare($share);
3912
+    }
3913
+
3914
+    public function testUpdateShareMailEnableSendPasswordByTalkWithNoPassword(): void {
3915
+        $this->expectException(\InvalidArgumentException::class);
3916
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3917
+
3918
+        $manager = $this->createManagerMock()
3919
+            ->onlyMethods([
3920
+                'canShare',
3921
+                'getShareById',
3922
+                'generalCreateChecks',
3923
+                'verifyPassword',
3924
+                'pathCreateChecks',
3925
+                'linkCreateChecks',
3926
+                'validateExpirationDateLink',
3927
+            ])
3928
+            ->getMock();
3929
+
3930
+        $originalShare = $this->manager->newShare();
3931
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
3932
+            ->setPermissions(Constants::PERMISSION_ALL)
3933
+            ->setPassword(null)
3934
+            ->setSendPasswordByTalk(false);
3935
+
3936
+        $tomorrow = new \DateTime();
3937
+        $tomorrow->setTime(0, 0, 0);
3938
+        $tomorrow->add(new \DateInterval('P1D'));
3939
+
3940
+        $file = $this->createMock(File::class);
3941
+        $file->method('getId')->willReturn(100);
3942
+
3943
+        $share = $this->manager->newShare();
3944
+        $share->setProviderId('foo')
3945
+            ->setId('42')
3946
+            ->setShareType(IShare::TYPE_EMAIL)
3947
+            ->setToken('token')
3948
+            ->setSharedBy('owner')
3949
+            ->setShareOwner('owner')
3950
+            ->setPassword(null)
3951
+            ->setSendPasswordByTalk(true)
3952
+            ->setExpirationDate($tomorrow)
3953
+            ->setNode($file)
3954
+            ->setPermissions(Constants::PERMISSION_ALL);
3955
+
3956
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
3957
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
3958
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
3959
+        $manager->expects($this->never())->method('verifyPassword');
3960
+        $manager->expects($this->never())->method('pathCreateChecks');
3961
+        $manager->expects($this->once())->method('linkCreateChecks');
3962
+        $manager->expects($this->never())->method('validateExpirationDateLink');
3963
+
3964
+        // If the password is empty, we have nothing to hash
3965
+        $this->hasher->expects($this->never())
3966
+            ->method('hash');
3967
+
3968
+        $this->defaultProvider->expects($this->never())
3969
+            ->method('update');
3970
+
3971
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
3972
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
3973
+        $hookListener->expects($this->never())->method('post');
3974
+
3975
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
3976
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
3977
+        $hookListener2->expects($this->never())->method('post');
3978
+
3979
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
3980
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
3981
+        $hookListener3->expects($this->never())->method('post');
3982
+
3983
+        $manager->updateShare($share);
3984
+    }
3985
+
3986
+
3987
+    public function testUpdateShareMailEnableSendPasswordByTalkRemovingPassword(): void {
3988
+        $this->expectException(\InvalidArgumentException::class);
3989
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
3990
+
3991
+        $manager = $this->createManagerMock()
3992
+            ->onlyMethods([
3993
+                'canShare',
3994
+                'getShareById',
3995
+                'generalCreateChecks',
3996
+                'verifyPassword',
3997
+                'pathCreateChecks',
3998
+                'linkCreateChecks',
3999
+                'validateExpirationDateLink',
4000
+            ])
4001
+            ->getMock();
4002
+
4003
+        $originalShare = $this->manager->newShare();
4004
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4005
+            ->setPermissions(Constants::PERMISSION_ALL)
4006
+            ->setPassword('passwordHash')
4007
+            ->setSendPasswordByTalk(false);
4008
+
4009
+        $tomorrow = new \DateTime();
4010
+        $tomorrow->setTime(0, 0, 0);
4011
+        $tomorrow->add(new \DateInterval('P1D'));
4012
+
4013
+        $file = $this->createMock(File::class);
4014
+        $file->method('getId')->willReturn(100);
4015
+
4016
+        $share = $this->manager->newShare();
4017
+        $share->setProviderId('foo')
4018
+            ->setId('42')
4019
+            ->setShareType(IShare::TYPE_EMAIL)
4020
+            ->setToken('token')
4021
+            ->setSharedBy('owner')
4022
+            ->setShareOwner('owner')
4023
+            ->setPassword(null)
4024
+            ->setSendPasswordByTalk(true)
4025
+            ->setExpirationDate($tomorrow)
4026
+            ->setNode($file)
4027
+            ->setPermissions(Constants::PERMISSION_ALL);
4028
+
4029
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
4030
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4031
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4032
+        $manager->expects($this->once())->method('verifyPassword');
4033
+        $manager->expects($this->never())->method('pathCreateChecks');
4034
+        $manager->expects($this->once())->method('linkCreateChecks');
4035
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4036
+
4037
+        // If the password is empty, we have nothing to hash
4038
+        $this->hasher->expects($this->never())
4039
+            ->method('hash');
4040
+
4041
+        $this->defaultProvider->expects($this->never())
4042
+            ->method('update');
4043
+
4044
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4045
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4046
+        $hookListener->expects($this->never())->method('post');
4047
+
4048
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4049
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4050
+        $hookListener2->expects($this->never())->method('post');
4051
+
4052
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4053
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4054
+        $hookListener3->expects($this->never())->method('post');
4055
+
4056
+        $manager->updateShare($share);
4057
+    }
4058
+
4059
+
4060
+    public function testUpdateShareMailEnableSendPasswordByTalkRemovingPasswordWithEmptyString(): void {
4061
+        $this->expectException(\InvalidArgumentException::class);
4062
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk with an empty password');
4063
+
4064
+        $manager = $this->createManagerMock()
4065
+            ->onlyMethods([
4066
+                'canShare',
4067
+                'getShareById',
4068
+                'generalCreateChecks',
4069
+                'verifyPassword',
4070
+                'pathCreateChecks',
4071
+                'linkCreateChecks',
4072
+                'validateExpirationDateLink',
4073
+            ])
4074
+            ->getMock();
4075
+
4076
+        $originalShare = $this->manager->newShare();
4077
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4078
+            ->setPermissions(Constants::PERMISSION_ALL)
4079
+            ->setPassword('passwordHash')
4080
+            ->setSendPasswordByTalk(false);
4081
+
4082
+        $tomorrow = new \DateTime();
4083
+        $tomorrow->setTime(0, 0, 0);
4084
+        $tomorrow->add(new \DateInterval('P1D'));
4085
+
4086
+        $file = $this->createMock(File::class);
4087
+        $file->method('getId')->willReturn(100);
4088
+
4089
+        $share = $this->manager->newShare();
4090
+        $share->setProviderId('foo')
4091
+            ->setId('42')
4092
+            ->setShareType(IShare::TYPE_EMAIL)
4093
+            ->setToken('token')
4094
+            ->setSharedBy('owner')
4095
+            ->setShareOwner('owner')
4096
+            ->setPassword('')
4097
+            ->setSendPasswordByTalk(true)
4098
+            ->setExpirationDate($tomorrow)
4099
+            ->setNode($file)
4100
+            ->setPermissions(Constants::PERMISSION_ALL);
4101
+
4102
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
4103
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4104
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4105
+        $manager->expects($this->once())->method('verifyPassword');
4106
+        $manager->expects($this->never())->method('pathCreateChecks');
4107
+        $manager->expects($this->once())->method('linkCreateChecks');
4108
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4109
+
4110
+        // If the password is empty, we have nothing to hash
4111
+        $this->hasher->expects($this->never())
4112
+            ->method('hash');
4113
+
4114
+        $this->defaultProvider->expects($this->never())
4115
+            ->method('update');
4116
+
4117
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4118
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4119
+        $hookListener->expects($this->never())->method('post');
4120
+
4121
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4122
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4123
+        $hookListener2->expects($this->never())->method('post');
4124
+
4125
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4126
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4127
+        $hookListener3->expects($this->never())->method('post');
4128
+
4129
+        $manager->updateShare($share);
4130
+    }
4131
+
4132
+
4133
+    public function testUpdateShareMailEnableSendPasswordByTalkWithPreviousPassword(): void {
4134
+        $this->expectException(\InvalidArgumentException::class);
4135
+        $this->expectExceptionMessage('Cannot enable sending the password by Talk without setting a new password');
4136
+
4137
+        $manager = $this->createManagerMock()
4138
+            ->onlyMethods([
4139
+                'canShare',
4140
+                'getShareById',
4141
+                'generalCreateChecks',
4142
+                'verifyPassword',
4143
+                'pathCreateChecks',
4144
+                'linkCreateChecks',
4145
+                'validateExpirationDateLink',
4146
+            ])
4147
+            ->getMock();
4148
+
4149
+        $originalShare = $this->manager->newShare();
4150
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4151
+            ->setPermissions(Constants::PERMISSION_ALL)
4152
+            ->setPassword('password')
4153
+            ->setSendPasswordByTalk(false);
4154
+
4155
+        $tomorrow = new \DateTime();
4156
+        $tomorrow->setTime(0, 0, 0);
4157
+        $tomorrow->add(new \DateInterval('P1D'));
4158
+
4159
+        $file = $this->createMock(File::class);
4160
+        $file->method('getId')->willReturn(100);
4161
+
4162
+        $share = $this->manager->newShare();
4163
+        $share->setProviderId('foo')
4164
+            ->setId('42')
4165
+            ->setShareType(IShare::TYPE_EMAIL)
4166
+            ->setToken('token')
4167
+            ->setSharedBy('owner')
4168
+            ->setShareOwner('owner')
4169
+            ->setPassword('password')
4170
+            ->setSendPasswordByTalk(true)
4171
+            ->setExpirationDate($tomorrow)
4172
+            ->setNode($file)
4173
+            ->setPermissions(Constants::PERMISSION_ALL);
4174
+
4175
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
4176
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4177
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4178
+        $manager->expects($this->never())->method('verifyPassword');
4179
+        $manager->expects($this->never())->method('pathCreateChecks');
4180
+        $manager->expects($this->once())->method('linkCreateChecks');
4181
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4182
+
4183
+        // If the old & new passwords are the same, we don't do anything
4184
+        $this->hasher->expects($this->never())
4185
+            ->method('verify');
4186
+        $this->hasher->expects($this->never())
4187
+            ->method('hash');
4188
+
4189
+        $this->defaultProvider->expects($this->never())
4190
+            ->method('update');
4191
+
4192
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4193
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4194
+        $hookListener->expects($this->never())->method('post');
4195
+
4196
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4197
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4198
+        $hookListener2->expects($this->never())->method('post');
4199
+
4200
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4201
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4202
+        $hookListener3->expects($this->never())->method('post');
4203
+
4204
+        $manager->updateShare($share);
4205
+    }
4206
+
4207
+    public function testUpdateShareMailDisableSendPasswordByTalkWithPreviousPassword(): void {
4208
+        $this->expectException(\InvalidArgumentException::class);
4209
+        $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4210
+
4211
+        $manager = $this->createManagerMock()
4212
+            ->onlyMethods([
4213
+                'canShare',
4214
+                'getShareById',
4215
+                'generalCreateChecks',
4216
+                'verifyPassword',
4217
+                'pathCreateChecks',
4218
+                'linkCreateChecks',
4219
+                'validateExpirationDateLink',
4220
+            ])
4221
+            ->getMock();
4222
+
4223
+        $originalShare = $this->manager->newShare();
4224
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4225
+            ->setPermissions(Constants::PERMISSION_ALL)
4226
+            ->setPassword('passwordHash')
4227
+            ->setSendPasswordByTalk(true);
4228
+
4229
+        $tomorrow = new \DateTime();
4230
+        $tomorrow->setTime(0, 0, 0);
4231
+        $tomorrow->add(new \DateInterval('P1D'));
4232
+
4233
+        $file = $this->createMock(File::class);
4234
+        $file->method('getId')->willReturn(100);
4235
+
4236
+        $share = $this->manager->newShare();
4237
+        $share->setProviderId('foo')
4238
+            ->setId('42')
4239
+            ->setShareType(IShare::TYPE_EMAIL)
4240
+            ->setToken('token')
4241
+            ->setSharedBy('owner')
4242
+            ->setShareOwner('owner')
4243
+            ->setPassword('passwordHash')
4244
+            ->setSendPasswordByTalk(false)
4245
+            ->setExpirationDate($tomorrow)
4246
+            ->setNode($file)
4247
+            ->setPermissions(Constants::PERMISSION_ALL);
4248
+
4249
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
4250
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4251
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4252
+        $manager->expects($this->never())->method('verifyPassword');
4253
+        $manager->expects($this->never())->method('pathCreateChecks');
4254
+        $manager->expects($this->once())->method('linkCreateChecks');
4255
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4256
+
4257
+        // If the old & new passwords are the same, we don't do anything
4258
+        $this->hasher->expects($this->never())
4259
+            ->method('verify');
4260
+        $this->hasher->expects($this->never())
4261
+            ->method('hash');
4262
+
4263
+        $this->defaultProvider->expects($this->never())
4264
+            ->method('update');
4265
+
4266
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4267
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4268
+        $hookListener->expects($this->never())->method('post');
4269
+
4270
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4271
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4272
+        $hookListener2->expects($this->never())->method('post');
4273
+
4274
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4275
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4276
+        $hookListener3->expects($this->never())->method('post');
4277
+
4278
+        $manager->updateShare($share);
4279
+    }
4280
+
4281
+    public function testUpdateShareMailDisableSendPasswordByTalkWithoutChangingPassword(): void {
4282
+        $this->expectException(\InvalidArgumentException::class);
4283
+        $this->expectExceptionMessage('Cannot disable sending the password by Talk without setting a new password');
4284
+
4285
+        $manager = $this->createManagerMock()
4286
+            ->onlyMethods([
4287
+                'canShare',
4288
+                'getShareById',
4289
+                'generalCreateChecks',
4290
+                'verifyPassword',
4291
+                'pathCreateChecks',
4292
+                'linkCreateChecks',
4293
+                'validateExpirationDateLink',
4294
+            ])
4295
+            ->getMock();
4296
+
4297
+        $originalShare = $this->manager->newShare();
4298
+        $originalShare->setShareType(IShare::TYPE_EMAIL)
4299
+            ->setPermissions(Constants::PERMISSION_ALL)
4300
+            ->setPassword('passwordHash')
4301
+            ->setSendPasswordByTalk(true);
4302
+
4303
+        $tomorrow = new \DateTime();
4304
+        $tomorrow->setTime(0, 0, 0);
4305
+        $tomorrow->add(new \DateInterval('P1D'));
4306
+
4307
+        $file = $this->createMock(File::class);
4308
+        $file->method('getId')->willReturn(100);
4309
+
4310
+        $share = $this->manager->newShare();
4311
+        $share->setProviderId('foo')
4312
+            ->setId('42')
4313
+            ->setShareType(IShare::TYPE_EMAIL)
4314
+            ->setToken('token')
4315
+            ->setSharedBy('owner')
4316
+            ->setShareOwner('owner')
4317
+            ->setPassword('passwordHash')
4318
+            ->setSendPasswordByTalk(false)
4319
+            ->setExpirationDate($tomorrow)
4320
+            ->setNode($file)
4321
+            ->setPermissions(Constants::PERMISSION_ALL);
4322
+
4323
+        $manager->expects($this->once())->method('canShare')->willReturn(true);
4324
+        $manager->expects($this->once())->method('getShareById')->with('foo:42')->willReturn($originalShare);
4325
+        $manager->expects($this->once())->method('generalCreateChecks')->with($share);
4326
+        $manager->expects($this->never())->method('verifyPassword');
4327
+        $manager->expects($this->never())->method('pathCreateChecks');
4328
+        $manager->expects($this->once())->method('linkCreateChecks');
4329
+        $manager->expects($this->never())->method('validateExpirationDateLink');
4330
+
4331
+        // If the old & new passwords are the same, we don't do anything
4332
+        $this->hasher->expects($this->never())
4333
+            ->method('verify');
4334
+        $this->hasher->expects($this->never())
4335
+            ->method('hash');
4336
+
4337
+        $this->defaultProvider->expects($this->never())
4338
+            ->method('update');
4339
+
4340
+        $hookListener = $this->createMock(DummyShareManagerListener::class);
4341
+        Util::connectHook('OCP\Share', 'post_set_expiration_date', $hookListener, 'post');
4342
+        $hookListener->expects($this->never())->method('post');
4343 4343
 
4344
-		$hookListener2 = $this->createMock(DummyShareManagerListener::class);
4345
-		Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4346
-		$hookListener2->expects($this->never())->method('post');
4344
+        $hookListener2 = $this->createMock(DummyShareManagerListener::class);
4345
+        Util::connectHook('OCP\Share', 'post_update_password', $hookListener2, 'post');
4346
+        $hookListener2->expects($this->never())->method('post');
4347 4347
 
4348
-		$hookListener3 = $this->createMock(DummyShareManagerListener::class);
4349
-		Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4350
-		$hookListener3->expects($this->never())->method('post');
4348
+        $hookListener3 = $this->createMock(DummyShareManagerListener::class);
4349
+        Util::connectHook('OCP\Share', 'post_update_permissions', $hookListener3, 'post');
4350
+        $hookListener3->expects($this->never())->method('post');
4351 4351
 
4352
-		$manager->updateShare($share);
4353
-	}
4352
+        $manager->updateShare($share);
4353
+    }
4354 4354
 
4355
-	public function testMoveShareLink(): void {
4356
-		$this->expectException(\InvalidArgumentException::class);
4357
-		$this->expectExceptionMessage('Cannot change target of link share');
4355
+    public function testMoveShareLink(): void {
4356
+        $this->expectException(\InvalidArgumentException::class);
4357
+        $this->expectExceptionMessage('Cannot change target of link share');
4358 4358
 
4359
-		$share = $this->manager->newShare();
4360
-		$share->setShareType(IShare::TYPE_LINK);
4359
+        $share = $this->manager->newShare();
4360
+        $share->setShareType(IShare::TYPE_LINK);
4361 4361
 
4362
-		$recipient = $this->createMock(IUser::class);
4362
+        $recipient = $this->createMock(IUser::class);
4363 4363
 
4364
-		$this->manager->moveShare($share, $recipient);
4365
-	}
4364
+        $this->manager->moveShare($share, $recipient);
4365
+    }
4366 4366
 
4367 4367
 
4368
-	public function testMoveShareUserNotRecipient(): void {
4369
-		$this->expectException(\InvalidArgumentException::class);
4370
-		$this->expectExceptionMessage('Invalid share recipient');
4368
+    public function testMoveShareUserNotRecipient(): void {
4369
+        $this->expectException(\InvalidArgumentException::class);
4370
+        $this->expectExceptionMessage('Invalid share recipient');
4371 4371
 
4372
-		$share = $this->manager->newShare();
4373
-		$share->setShareType(IShare::TYPE_USER);
4374
-
4375
-		$share->setSharedWith('sharedWith');
4372
+        $share = $this->manager->newShare();
4373
+        $share->setShareType(IShare::TYPE_USER);
4374
+
4375
+        $share->setSharedWith('sharedWith');
4376 4376
 
4377
-		$this->manager->moveShare($share, 'recipient');
4378
-	}
4377
+        $this->manager->moveShare($share, 'recipient');
4378
+    }
4379 4379
 
4380
-	public function testMoveShareUser(): void {
4381
-		$share = $this->manager->newShare();
4382
-		$share->setShareType(IShare::TYPE_USER)
4383
-			->setId('42')
4384
-			->setProviderId('foo');
4380
+    public function testMoveShareUser(): void {
4381
+        $share = $this->manager->newShare();
4382
+        $share->setShareType(IShare::TYPE_USER)
4383
+            ->setId('42')
4384
+            ->setProviderId('foo');
4385 4385
 
4386
-		$share->setSharedWith('recipient');
4386
+        $share->setSharedWith('recipient');
4387 4387
 
4388
-		$this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4388
+        $this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4389 4389
 
4390
-		$this->manager->moveShare($share, 'recipient');
4391
-		$this->addToAssertionCount(1);
4392
-	}
4390
+        $this->manager->moveShare($share, 'recipient');
4391
+        $this->addToAssertionCount(1);
4392
+    }
4393 4393
 
4394 4394
 
4395
-	public function testMoveShareGroupNotRecipient(): void {
4396
-		$this->expectException(\InvalidArgumentException::class);
4397
-		$this->expectExceptionMessage('Invalid share recipient');
4395
+    public function testMoveShareGroupNotRecipient(): void {
4396
+        $this->expectException(\InvalidArgumentException::class);
4397
+        $this->expectExceptionMessage('Invalid share recipient');
4398 4398
 
4399
-		$share = $this->manager->newShare();
4400
-		$share->setShareType(IShare::TYPE_GROUP);
4399
+        $share = $this->manager->newShare();
4400
+        $share->setShareType(IShare::TYPE_GROUP);
4401 4401
 
4402
-		$sharedWith = $this->createMock(IGroup::class);
4403
-		$share->setSharedWith('shareWith');
4402
+        $sharedWith = $this->createMock(IGroup::class);
4403
+        $share->setSharedWith('shareWith');
4404 4404
 
4405
-		$recipient = $this->createMock(IUser::class);
4406
-		$sharedWith->method('inGroup')->with($recipient)->willReturn(false);
4405
+        $recipient = $this->createMock(IUser::class);
4406
+        $sharedWith->method('inGroup')->with($recipient)->willReturn(false);
4407 4407
 
4408
-		$this->groupManager->method('get')->with('shareWith')->willReturn($sharedWith);
4409
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4410
-
4411
-		$this->manager->moveShare($share, 'recipient');
4412
-	}
4408
+        $this->groupManager->method('get')->with('shareWith')->willReturn($sharedWith);
4409
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4410
+
4411
+        $this->manager->moveShare($share, 'recipient');
4412
+    }
4413 4413
 
4414 4414
 
4415
-	public function testMoveShareGroupNull(): void {
4416
-		$this->expectException(\InvalidArgumentException::class);
4417
-		$this->expectExceptionMessage('Group "shareWith" does not exist');
4415
+    public function testMoveShareGroupNull(): void {
4416
+        $this->expectException(\InvalidArgumentException::class);
4417
+        $this->expectExceptionMessage('Group "shareWith" does not exist');
4418 4418
 
4419
-		$share = $this->manager->newShare();
4420
-		$share->setShareType(IShare::TYPE_GROUP);
4421
-		$share->setSharedWith('shareWith');
4419
+        $share = $this->manager->newShare();
4420
+        $share->setShareType(IShare::TYPE_GROUP);
4421
+        $share->setSharedWith('shareWith');
4422 4422
 
4423
-		$recipient = $this->createMock(IUser::class);
4423
+        $recipient = $this->createMock(IUser::class);
4424 4424
 
4425
-		$this->groupManager->method('get')->with('shareWith')->willReturn(null);
4426
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4425
+        $this->groupManager->method('get')->with('shareWith')->willReturn(null);
4426
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4427 4427
 
4428
-		$this->manager->moveShare($share, 'recipient');
4429
-	}
4428
+        $this->manager->moveShare($share, 'recipient');
4429
+    }
4430 4430
 
4431
-	public function testMoveShareGroup(): void {
4432
-		$share = $this->manager->newShare();
4433
-		$share->setShareType(IShare::TYPE_GROUP)
4434
-			->setId('42')
4435
-			->setProviderId('foo');
4431
+    public function testMoveShareGroup(): void {
4432
+        $share = $this->manager->newShare();
4433
+        $share->setShareType(IShare::TYPE_GROUP)
4434
+            ->setId('42')
4435
+            ->setProviderId('foo');
4436 4436
 
4437
-		$group = $this->createMock(IGroup::class);
4438
-		$share->setSharedWith('group');
4437
+        $group = $this->createMock(IGroup::class);
4438
+        $share->setSharedWith('group');
4439 4439
 
4440
-		$recipient = $this->createMock(IUser::class);
4441
-		$group->method('inGroup')->with($recipient)->willReturn(true);
4440
+        $recipient = $this->createMock(IUser::class);
4441
+        $group->method('inGroup')->with($recipient)->willReturn(true);
4442 4442
 
4443
-		$this->groupManager->method('get')->with('group')->willReturn($group);
4444
-		$this->userManager->method('get')->with('recipient')->willReturn($recipient);
4443
+        $this->groupManager->method('get')->with('group')->willReturn($group);
4444
+        $this->userManager->method('get')->with('recipient')->willReturn($recipient);
4445 4445
 
4446
-		$this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4446
+        $this->defaultProvider->method('move')->with($share, 'recipient')->willReturnArgument(0);
4447 4447
 
4448
-		$this->manager->moveShare($share, 'recipient');
4449
-		$this->addToAssertionCount(1);
4450
-	}
4448
+        $this->manager->moveShare($share, 'recipient');
4449
+        $this->addToAssertionCount(1);
4450
+    }
4451 4451
 
4452
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataTestShareProviderExists')]
4453
-	public function testShareProviderExists($shareType, $expected): void {
4454
-		$factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
4455
-		$factory->expects($this->any())->method('getProviderForType')
4456
-			->willReturnCallback(function ($id) {
4457
-				if ($id === IShare::TYPE_USER) {
4458
-					return true;
4459
-				}
4460
-				throw new ProviderException();
4461
-			});
4452
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataTestShareProviderExists')]
4453
+    public function testShareProviderExists($shareType, $expected): void {
4454
+        $factory = $this->getMockBuilder('OCP\Share\IProviderFactory')->getMock();
4455
+        $factory->expects($this->any())->method('getProviderForType')
4456
+            ->willReturnCallback(function ($id) {
4457
+                if ($id === IShare::TYPE_USER) {
4458
+                    return true;
4459
+                }
4460
+                throw new ProviderException();
4461
+            });
4462 4462
 
4463
-		$manager = $this->createManager($factory);
4464
-		$this->assertSame($expected,
4465
-			$manager->shareProviderExists($shareType)
4466
-		);
4467
-	}
4463
+        $manager = $this->createManager($factory);
4464
+        $this->assertSame($expected,
4465
+            $manager->shareProviderExists($shareType)
4466
+        );
4467
+    }
4468 4468
 
4469
-	public static function dataTestShareProviderExists() {
4470
-		return [
4471
-			[IShare::TYPE_USER, true],
4472
-			[42, false],
4473
-		];
4474
-	}
4469
+    public static function dataTestShareProviderExists() {
4470
+        return [
4471
+            [IShare::TYPE_USER, true],
4472
+            [42, false],
4473
+        ];
4474
+    }
4475 4475
 
4476
-	public function testGetSharesInFolder(): void {
4477
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4476
+    public function testGetSharesInFolder(): void {
4477
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4478 4478
 
4479
-		$manager = $this->createManager($factory);
4479
+        $manager = $this->createManager($factory);
4480 4480
 
4481
-		$factory->setProvider($this->defaultProvider);
4482
-		$extraProvider = $this->createMock(IShareProvider::class);
4483
-		$factory->setSecondProvider($extraProvider);
4481
+        $factory->setProvider($this->defaultProvider);
4482
+        $extraProvider = $this->createMock(IShareProvider::class);
4483
+        $factory->setSecondProvider($extraProvider);
4484 4484
 
4485
-		$share1 = $this->createMock(IShare::class);
4486
-		$share2 = $this->createMock(IShare::class);
4487
-		$share3 = $this->createMock(IShare::class);
4488
-		$share4 = $this->createMock(IShare::class);
4485
+        $share1 = $this->createMock(IShare::class);
4486
+        $share2 = $this->createMock(IShare::class);
4487
+        $share3 = $this->createMock(IShare::class);
4488
+        $share4 = $this->createMock(IShare::class);
4489 4489
 
4490
-		$folder = $this->createMock(Folder::class);
4490
+        $folder = $this->createMock(Folder::class);
4491 4491
 
4492
-		$this->defaultProvider->method('getSharesInFolder')
4493
-			->with(
4494
-				$this->equalTo('user'),
4495
-				$this->equalTo($folder),
4496
-				$this->equalTo(false)
4497
-			)->willReturn([
4498
-				1 => [$share1],
4499
-				2 => [$share2],
4500
-			]);
4501
-
4502
-		$extraProvider->method('getSharesInFolder')
4503
-			->with(
4504
-				$this->equalTo('user'),
4505
-				$this->equalTo($folder),
4506
-				$this->equalTo(false)
4507
-			)->willReturn([
4508
-				2 => [$share3],
4509
-				3 => [$share4],
4510
-			]);
4511
-
4512
-		$result = $manager->getSharesInFolder('user', $folder, false);
4513
-
4514
-		$expects = [
4515
-			1 => [$share1],
4516
-			2 => [$share2, $share3],
4517
-			3 => [$share4],
4518
-		];
4519
-
4520
-		$this->assertSame($expects, $result);
4521
-	}
4522
-
4523
-	public function testGetSharesInFolderOwnerless(): void {
4524
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4525
-
4526
-		$manager = $this->createManager($factory);
4527
-
4528
-		$factory->setProvider($this->defaultProvider);
4529
-		$extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class);
4530
-		$factory->setSecondProvider($extraProvider);
4531
-
4532
-		$share1 = $this->createMock(IShare::class);
4533
-		$share2 = $this->createMock(IShare::class);
4534
-
4535
-		$mount = $this->createMock(IShareOwnerlessMount::class);
4536
-
4537
-		$folder = $this->createMock(Folder::class);
4538
-		$folder
4539
-			->method('getMountPoint')
4540
-			->willReturn($mount);
4541
-
4542
-		$this->defaultProvider
4543
-			->method('getAllSharesInFolder')
4544
-			->with($folder)
4545
-			->willReturn([1 => [$share1]]);
4546
-
4547
-		$extraProvider
4548
-			->method('getAllSharesInFolder')
4549
-			->with($folder)
4550
-			->willReturn([1 => [$share2]]);
4551
-
4552
-		$this->assertSame([
4553
-			1 => [$share1, $share2],
4554
-		], $manager->getSharesInFolder('user', $folder));
4555
-	}
4556
-
4557
-
4558
-	public function testGetAccessList(): void {
4559
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4560
-
4561
-		$manager = $this->createManager($factory);
4562
-
4563
-		$factory->setProvider($this->defaultProvider);
4564
-		$extraProvider = $this->createMock(IShareProvider::class);
4565
-		$factory->setSecondProvider($extraProvider);
4566
-
4567
-		$nodeOwner = $this->createMock(IUser::class);
4568
-		$nodeOwner->expects($this->once())
4569
-			->method('getUID')
4570
-			->willReturn('user1');
4571
-
4572
-		$node = $this->createMock(Node::class);
4573
-		$node->expects($this->once())
4574
-			->method('getOwner')
4575
-			->willReturn($nodeOwner);
4576
-		$node->method('getId')
4577
-			->willReturn(42);
4578
-
4579
-		$userFolder = $this->createMock(Folder::class);
4580
-		$file = $this->createMock(File::class);
4581
-		$folder = $this->createMock(Folder::class);
4582
-
4583
-		$owner = $this->createMock(IUser::class);
4584
-		$owner->expects($this->once())
4585
-			->method('getUID')
4586
-			->willReturn('owner');
4587
-
4588
-		$file->method('getParent')
4589
-			->willReturn($folder);
4590
-		$file->method('getPath')
4591
-			->willReturn('/owner/files/folder/file');
4592
-		$file->method('getOwner')
4593
-			->willReturn($owner);
4594
-		$file->method('getId')
4595
-			->willReturn(23);
4596
-		$folder->method('getParent')
4597
-			->willReturn($userFolder);
4598
-		$folder->method('getPath')
4599
-			->willReturn('/owner/files/folder');
4600
-		$userFolder->method('getFirstNodeById')
4601
-			->with($this->equalTo(42))
4602
-			->willReturn($file);
4603
-		$userFolder->method('getPath')
4604
-			->willReturn('/user1/files');
4605
-
4606
-		$this->userManager->method('userExists')
4607
-			->with($this->equalTo('user1'))
4608
-			->willReturn(true);
4609
-
4610
-		$this->defaultProvider->method('getAccessList')
4611
-			->with(
4612
-				$this->equalTo([$file, $folder]),
4613
-				false
4614
-			)
4615
-			->willReturn([
4616
-				'users' => [
4617
-					'user1',
4618
-					'user2',
4619
-					'user3',
4620
-					'123456',
4621
-				],
4622
-				'public' => true,
4623
-			]);
4624
-
4625
-		$extraProvider->method('getAccessList')
4626
-			->with(
4627
-				$this->equalTo([$file, $folder]),
4628
-				false
4629
-			)
4630
-			->willReturn([
4631
-				'users' => [
4632
-					'user3',
4633
-					'user4',
4634
-					'user5',
4635
-					'234567',
4636
-				],
4637
-				'remote' => true,
4638
-			]);
4639
-
4640
-		$this->rootFolder->method('getUserFolder')
4641
-			->with($this->equalTo('user1'))
4642
-			->willReturn($userFolder);
4643
-
4644
-		$expected = [
4645
-			'users' => ['owner', 'user1', 'user2', 'user3', '123456','user4', 'user5', '234567'],
4646
-			'remote' => true,
4647
-			'public' => true,
4648
-		];
4649
-
4650
-		$result = $manager->getAccessList($node, true, false);
4651
-
4652
-		$this->assertSame($expected['public'], $result['public']);
4653
-		$this->assertSame($expected['remote'], $result['remote']);
4654
-		$this->assertSame($expected['users'], $result['users']);
4655
-	}
4656
-
4657
-	public function testGetAccessListWithCurrentAccess(): void {
4658
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4659
-
4660
-		$manager = $this->createManager($factory);
4661
-
4662
-		$factory->setProvider($this->defaultProvider);
4663
-		$extraProvider = $this->createMock(IShareProvider::class);
4664
-		$factory->setSecondProvider($extraProvider);
4665
-
4666
-		$nodeOwner = $this->createMock(IUser::class);
4667
-		$nodeOwner->expects($this->once())
4668
-			->method('getUID')
4669
-			->willReturn('user1');
4670
-
4671
-		$node = $this->createMock(Node::class);
4672
-		$node->expects($this->once())
4673
-			->method('getOwner')
4674
-			->willReturn($nodeOwner);
4675
-		$node->method('getId')
4676
-			->willReturn(42);
4677
-
4678
-		$userFolder = $this->createMock(Folder::class);
4679
-		$file = $this->createMock(File::class);
4680
-
4681
-		$owner = $this->createMock(IUser::class);
4682
-		$owner->expects($this->once())
4683
-			->method('getUID')
4684
-			->willReturn('owner');
4685
-		$folder = $this->createMock(Folder::class);
4686
-
4687
-		$file->method('getParent')
4688
-			->willReturn($folder);
4689
-		$file->method('getPath')
4690
-			->willReturn('/owner/files/folder/file');
4691
-		$file->method('getOwner')
4692
-			->willReturn($owner);
4693
-		$file->method('getId')
4694
-			->willReturn(23);
4695
-		$folder->method('getParent')
4696
-			->willReturn($userFolder);
4697
-		$folder->method('getPath')
4698
-			->willReturn('/owner/files/folder');
4699
-		$userFolder->method('getFirstNodeById')
4700
-			->with($this->equalTo(42))
4701
-			->willReturn($file);
4702
-		$userFolder->method('getPath')
4703
-			->willReturn('/user1/files');
4704
-
4705
-		$this->userManager->method('userExists')
4706
-			->with($this->equalTo('user1'))
4707
-			->willReturn(true);
4708
-
4709
-		$this->defaultProvider->method('getAccessList')
4710
-			->with(
4711
-				$this->equalTo([$file, $folder]),
4712
-				true
4713
-			)
4714
-			->willReturn([
4715
-				'users' => [
4716
-					'user1' => [],
4717
-					'user2' => [],
4718
-					'user3' => [],
4719
-					'123456' => [],
4720
-				],
4721
-				'public' => true,
4722
-			]);
4723
-
4724
-		$extraProvider->method('getAccessList')
4725
-			->with(
4726
-				$this->equalTo([$file, $folder]),
4727
-				true
4728
-			)
4729
-			->willReturn([
4730
-				'users' => [
4731
-					'user3' => [],
4732
-					'user4' => [],
4733
-					'user5' => [],
4734
-					'234567' => [],
4735
-				],
4736
-				'remote' => [
4737
-					'remote1',
4738
-				],
4739
-			]);
4740
-
4741
-		$this->rootFolder->method('getUserFolder')
4742
-			->with($this->equalTo('user1'))
4743
-			->willReturn($userFolder);
4744
-
4745
-		$expected = [
4746
-			'users' => [
4747
-				'owner' => [
4748
-					'node_id' => 23,
4749
-					'node_path' => '/folder/file'
4750
-				]
4751
-				, 'user1' => [], 'user2' => [], 'user3' => [], '123456' => [], 'user4' => [], 'user5' => [], '234567' => []],
4752
-			'remote' => [
4753
-				'remote1',
4754
-			],
4755
-			'public' => true,
4756
-		];
4757
-
4758
-		$result = $manager->getAccessList($node, true, true);
4759
-
4760
-		$this->assertSame($expected['public'], $result['public']);
4761
-		$this->assertSame($expected['remote'], $result['remote']);
4762
-		$this->assertSame($expected['users'], $result['users']);
4763
-	}
4764
-
4765
-	public function testGetAllShares(): void {
4766
-		$factory = new DummyFactory2($this->createMock(IServerContainer::class));
4767
-
4768
-		$manager = $this->createManager($factory);
4769
-
4770
-		$factory->setProvider($this->defaultProvider);
4771
-		$extraProvider = $this->createMock(IShareProvider::class);
4772
-		$factory->setSecondProvider($extraProvider);
4773
-
4774
-		$share1 = $this->createMock(IShare::class);
4775
-		$share2 = $this->createMock(IShare::class);
4776
-		$share3 = $this->createMock(IShare::class);
4777
-		$share4 = $this->createMock(IShare::class);
4778
-
4779
-		$this->defaultProvider->method('getAllShares')
4780
-			->willReturnCallback(function () use ($share1, $share2) {
4781
-				yield $share1;
4782
-				yield $share2;
4783
-			});
4784
-		$extraProvider->method('getAllShares')
4785
-			->willReturnCallback(function () use ($share3, $share4) {
4786
-				yield $share3;
4787
-				yield $share4;
4788
-			});
4789
-
4790
-		// "yield from", used in "getAllShares()", does not reset the keys, so
4791
-		// "use_keys" has to be disabled to collect all the values while
4792
-		// ignoring the keys returned by the generator.
4793
-		$result = iterator_to_array($manager->getAllShares(), $use_keys = false);
4794
-
4795
-		$expects = [$share1, $share2, $share3, $share4];
4796
-
4797
-		$this->assertSame($expects, $result);
4798
-	}
4799
-
4800
-	public static function dataCurrentUserCanEnumerateTargetUser(): array {
4801
-		return [
4802
-			'Full match guest' => [true, true, false, false, false, false, false, true],
4803
-			'Full match user' => [false, true, false, false, false, false, false, true],
4804
-			'Enumeration off guest' => [true, false, false, false, false, false, false, false],
4805
-			'Enumeration off user' => [false, false, false, false, false, false, false, false],
4806
-			'Enumeration guest' => [true, false, true, false, false, false, false, true],
4807
-			'Enumeration user' => [false, false, true, false, false, false, false, true],
4808
-
4809
-			// Restricted enumerations guests never works
4810
-			'Guest phone' => [true, false, true, true, false, false, false, false],
4811
-			'Guest group' => [true, false, true, false, true, false, false, false],
4812
-			'Guest both' => [true, false, true, true, true, false, false, false],
4813
-
4814
-			// Restricted enumerations users
4815
-			'User phone but not known' => [false, false, true, true, false, false, false, false],
4816
-			'User phone known' => [false, false, true, true, false, true, false, true],
4817
-			'User group but no match' => [false, false, true, false, true, false, false, false],
4818
-			'User group with match' => [false, false, true, false, true, false, true, true],
4819
-		];
4820
-	}
4821
-
4822
-	/**
4823
-	 * @param bool $expected
4824
-	 */
4825
-	#[\PHPUnit\Framework\Attributes\DataProvider('dataCurrentUserCanEnumerateTargetUser')]
4826
-	public function testCurrentUserCanEnumerateTargetUser(bool $currentUserIsGuest, bool $allowEnumerationFullMatch, bool $allowEnumeration, bool $limitEnumerationToPhone, bool $limitEnumerationToGroups, bool $isKnownToUser, bool $haveCommonGroup, bool $expected): void {
4827
-		/** @var IManager|MockObject $manager */
4828
-		$manager = $this->createManagerMock()
4829
-			->onlyMethods([
4830
-				'allowEnumerationFullMatch',
4831
-				'allowEnumeration',
4832
-				'limitEnumerationToPhone',
4833
-				'limitEnumerationToGroups',
4834
-			])
4835
-			->getMock();
4836
-
4837
-		$manager->method('allowEnumerationFullMatch')
4838
-			->willReturn($allowEnumerationFullMatch);
4839
-		$manager->method('allowEnumeration')
4840
-			->willReturn($allowEnumeration);
4841
-		$manager->method('limitEnumerationToPhone')
4842
-			->willReturn($limitEnumerationToPhone);
4843
-		$manager->method('limitEnumerationToGroups')
4844
-			->willReturn($limitEnumerationToGroups);
4845
-
4846
-		$this->knownUserService->method('isKnownToUser')
4847
-			->with('current', 'target')
4848
-			->willReturn($isKnownToUser);
4849
-
4850
-		$currentUser = null;
4851
-		if (!$currentUserIsGuest) {
4852
-			$currentUser = $this->createMock(IUser::class);
4853
-			$currentUser->method('getUID')
4854
-				->willReturn('current');
4855
-		}
4856
-		$targetUser = $this->createMock(IUser::class);
4857
-		$targetUser->method('getUID')
4858
-			->willReturn('target');
4859
-
4860
-		if ($haveCommonGroup) {
4861
-			$this->groupManager->method('getUserGroupIds')
4862
-				->willReturnMap([
4863
-					[$targetUser, ['gid1', 'gid2']],
4864
-					[$currentUser, ['gid2', 'gid3']],
4865
-				]);
4866
-		} else {
4867
-			$this->groupManager->method('getUserGroupIds')
4868
-				->willReturnMap([
4869
-					[$targetUser, ['gid1', 'gid2']],
4870
-					[$currentUser, ['gid3', 'gid4']],
4871
-				]);
4872
-		}
4873
-
4874
-		$this->assertSame($expected, $manager->currentUserCanEnumerateTargetUser($currentUser, $targetUser));
4875
-	}
4492
+        $this->defaultProvider->method('getSharesInFolder')
4493
+            ->with(
4494
+                $this->equalTo('user'),
4495
+                $this->equalTo($folder),
4496
+                $this->equalTo(false)
4497
+            )->willReturn([
4498
+                1 => [$share1],
4499
+                2 => [$share2],
4500
+            ]);
4501
+
4502
+        $extraProvider->method('getSharesInFolder')
4503
+            ->with(
4504
+                $this->equalTo('user'),
4505
+                $this->equalTo($folder),
4506
+                $this->equalTo(false)
4507
+            )->willReturn([
4508
+                2 => [$share3],
4509
+                3 => [$share4],
4510
+            ]);
4511
+
4512
+        $result = $manager->getSharesInFolder('user', $folder, false);
4513
+
4514
+        $expects = [
4515
+            1 => [$share1],
4516
+            2 => [$share2, $share3],
4517
+            3 => [$share4],
4518
+        ];
4519
+
4520
+        $this->assertSame($expects, $result);
4521
+    }
4522
+
4523
+    public function testGetSharesInFolderOwnerless(): void {
4524
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4525
+
4526
+        $manager = $this->createManager($factory);
4527
+
4528
+        $factory->setProvider($this->defaultProvider);
4529
+        $extraProvider = $this->createMock(IShareProviderSupportsAllSharesInFolder::class);
4530
+        $factory->setSecondProvider($extraProvider);
4531
+
4532
+        $share1 = $this->createMock(IShare::class);
4533
+        $share2 = $this->createMock(IShare::class);
4534
+
4535
+        $mount = $this->createMock(IShareOwnerlessMount::class);
4536
+
4537
+        $folder = $this->createMock(Folder::class);
4538
+        $folder
4539
+            ->method('getMountPoint')
4540
+            ->willReturn($mount);
4541
+
4542
+        $this->defaultProvider
4543
+            ->method('getAllSharesInFolder')
4544
+            ->with($folder)
4545
+            ->willReturn([1 => [$share1]]);
4546
+
4547
+        $extraProvider
4548
+            ->method('getAllSharesInFolder')
4549
+            ->with($folder)
4550
+            ->willReturn([1 => [$share2]]);
4551
+
4552
+        $this->assertSame([
4553
+            1 => [$share1, $share2],
4554
+        ], $manager->getSharesInFolder('user', $folder));
4555
+    }
4556
+
4557
+
4558
+    public function testGetAccessList(): void {
4559
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4560
+
4561
+        $manager = $this->createManager($factory);
4562
+
4563
+        $factory->setProvider($this->defaultProvider);
4564
+        $extraProvider = $this->createMock(IShareProvider::class);
4565
+        $factory->setSecondProvider($extraProvider);
4566
+
4567
+        $nodeOwner = $this->createMock(IUser::class);
4568
+        $nodeOwner->expects($this->once())
4569
+            ->method('getUID')
4570
+            ->willReturn('user1');
4571
+
4572
+        $node = $this->createMock(Node::class);
4573
+        $node->expects($this->once())
4574
+            ->method('getOwner')
4575
+            ->willReturn($nodeOwner);
4576
+        $node->method('getId')
4577
+            ->willReturn(42);
4578
+
4579
+        $userFolder = $this->createMock(Folder::class);
4580
+        $file = $this->createMock(File::class);
4581
+        $folder = $this->createMock(Folder::class);
4582
+
4583
+        $owner = $this->createMock(IUser::class);
4584
+        $owner->expects($this->once())
4585
+            ->method('getUID')
4586
+            ->willReturn('owner');
4587
+
4588
+        $file->method('getParent')
4589
+            ->willReturn($folder);
4590
+        $file->method('getPath')
4591
+            ->willReturn('/owner/files/folder/file');
4592
+        $file->method('getOwner')
4593
+            ->willReturn($owner);
4594
+        $file->method('getId')
4595
+            ->willReturn(23);
4596
+        $folder->method('getParent')
4597
+            ->willReturn($userFolder);
4598
+        $folder->method('getPath')
4599
+            ->willReturn('/owner/files/folder');
4600
+        $userFolder->method('getFirstNodeById')
4601
+            ->with($this->equalTo(42))
4602
+            ->willReturn($file);
4603
+        $userFolder->method('getPath')
4604
+            ->willReturn('/user1/files');
4605
+
4606
+        $this->userManager->method('userExists')
4607
+            ->with($this->equalTo('user1'))
4608
+            ->willReturn(true);
4609
+
4610
+        $this->defaultProvider->method('getAccessList')
4611
+            ->with(
4612
+                $this->equalTo([$file, $folder]),
4613
+                false
4614
+            )
4615
+            ->willReturn([
4616
+                'users' => [
4617
+                    'user1',
4618
+                    'user2',
4619
+                    'user3',
4620
+                    '123456',
4621
+                ],
4622
+                'public' => true,
4623
+            ]);
4624
+
4625
+        $extraProvider->method('getAccessList')
4626
+            ->with(
4627
+                $this->equalTo([$file, $folder]),
4628
+                false
4629
+            )
4630
+            ->willReturn([
4631
+                'users' => [
4632
+                    'user3',
4633
+                    'user4',
4634
+                    'user5',
4635
+                    '234567',
4636
+                ],
4637
+                'remote' => true,
4638
+            ]);
4639
+
4640
+        $this->rootFolder->method('getUserFolder')
4641
+            ->with($this->equalTo('user1'))
4642
+            ->willReturn($userFolder);
4643
+
4644
+        $expected = [
4645
+            'users' => ['owner', 'user1', 'user2', 'user3', '123456','user4', 'user5', '234567'],
4646
+            'remote' => true,
4647
+            'public' => true,
4648
+        ];
4649
+
4650
+        $result = $manager->getAccessList($node, true, false);
4651
+
4652
+        $this->assertSame($expected['public'], $result['public']);
4653
+        $this->assertSame($expected['remote'], $result['remote']);
4654
+        $this->assertSame($expected['users'], $result['users']);
4655
+    }
4656
+
4657
+    public function testGetAccessListWithCurrentAccess(): void {
4658
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4659
+
4660
+        $manager = $this->createManager($factory);
4661
+
4662
+        $factory->setProvider($this->defaultProvider);
4663
+        $extraProvider = $this->createMock(IShareProvider::class);
4664
+        $factory->setSecondProvider($extraProvider);
4665
+
4666
+        $nodeOwner = $this->createMock(IUser::class);
4667
+        $nodeOwner->expects($this->once())
4668
+            ->method('getUID')
4669
+            ->willReturn('user1');
4670
+
4671
+        $node = $this->createMock(Node::class);
4672
+        $node->expects($this->once())
4673
+            ->method('getOwner')
4674
+            ->willReturn($nodeOwner);
4675
+        $node->method('getId')
4676
+            ->willReturn(42);
4677
+
4678
+        $userFolder = $this->createMock(Folder::class);
4679
+        $file = $this->createMock(File::class);
4680
+
4681
+        $owner = $this->createMock(IUser::class);
4682
+        $owner->expects($this->once())
4683
+            ->method('getUID')
4684
+            ->willReturn('owner');
4685
+        $folder = $this->createMock(Folder::class);
4686
+
4687
+        $file->method('getParent')
4688
+            ->willReturn($folder);
4689
+        $file->method('getPath')
4690
+            ->willReturn('/owner/files/folder/file');
4691
+        $file->method('getOwner')
4692
+            ->willReturn($owner);
4693
+        $file->method('getId')
4694
+            ->willReturn(23);
4695
+        $folder->method('getParent')
4696
+            ->willReturn($userFolder);
4697
+        $folder->method('getPath')
4698
+            ->willReturn('/owner/files/folder');
4699
+        $userFolder->method('getFirstNodeById')
4700
+            ->with($this->equalTo(42))
4701
+            ->willReturn($file);
4702
+        $userFolder->method('getPath')
4703
+            ->willReturn('/user1/files');
4704
+
4705
+        $this->userManager->method('userExists')
4706
+            ->with($this->equalTo('user1'))
4707
+            ->willReturn(true);
4708
+
4709
+        $this->defaultProvider->method('getAccessList')
4710
+            ->with(
4711
+                $this->equalTo([$file, $folder]),
4712
+                true
4713
+            )
4714
+            ->willReturn([
4715
+                'users' => [
4716
+                    'user1' => [],
4717
+                    'user2' => [],
4718
+                    'user3' => [],
4719
+                    '123456' => [],
4720
+                ],
4721
+                'public' => true,
4722
+            ]);
4723
+
4724
+        $extraProvider->method('getAccessList')
4725
+            ->with(
4726
+                $this->equalTo([$file, $folder]),
4727
+                true
4728
+            )
4729
+            ->willReturn([
4730
+                'users' => [
4731
+                    'user3' => [],
4732
+                    'user4' => [],
4733
+                    'user5' => [],
4734
+                    '234567' => [],
4735
+                ],
4736
+                'remote' => [
4737
+                    'remote1',
4738
+                ],
4739
+            ]);
4740
+
4741
+        $this->rootFolder->method('getUserFolder')
4742
+            ->with($this->equalTo('user1'))
4743
+            ->willReturn($userFolder);
4744
+
4745
+        $expected = [
4746
+            'users' => [
4747
+                'owner' => [
4748
+                    'node_id' => 23,
4749
+                    'node_path' => '/folder/file'
4750
+                ]
4751
+                , 'user1' => [], 'user2' => [], 'user3' => [], '123456' => [], 'user4' => [], 'user5' => [], '234567' => []],
4752
+            'remote' => [
4753
+                'remote1',
4754
+            ],
4755
+            'public' => true,
4756
+        ];
4757
+
4758
+        $result = $manager->getAccessList($node, true, true);
4759
+
4760
+        $this->assertSame($expected['public'], $result['public']);
4761
+        $this->assertSame($expected['remote'], $result['remote']);
4762
+        $this->assertSame($expected['users'], $result['users']);
4763
+    }
4764
+
4765
+    public function testGetAllShares(): void {
4766
+        $factory = new DummyFactory2($this->createMock(IServerContainer::class));
4767
+
4768
+        $manager = $this->createManager($factory);
4769
+
4770
+        $factory->setProvider($this->defaultProvider);
4771
+        $extraProvider = $this->createMock(IShareProvider::class);
4772
+        $factory->setSecondProvider($extraProvider);
4773
+
4774
+        $share1 = $this->createMock(IShare::class);
4775
+        $share2 = $this->createMock(IShare::class);
4776
+        $share3 = $this->createMock(IShare::class);
4777
+        $share4 = $this->createMock(IShare::class);
4778
+
4779
+        $this->defaultProvider->method('getAllShares')
4780
+            ->willReturnCallback(function () use ($share1, $share2) {
4781
+                yield $share1;
4782
+                yield $share2;
4783
+            });
4784
+        $extraProvider->method('getAllShares')
4785
+            ->willReturnCallback(function () use ($share3, $share4) {
4786
+                yield $share3;
4787
+                yield $share4;
4788
+            });
4789
+
4790
+        // "yield from", used in "getAllShares()", does not reset the keys, so
4791
+        // "use_keys" has to be disabled to collect all the values while
4792
+        // ignoring the keys returned by the generator.
4793
+        $result = iterator_to_array($manager->getAllShares(), $use_keys = false);
4794
+
4795
+        $expects = [$share1, $share2, $share3, $share4];
4796
+
4797
+        $this->assertSame($expects, $result);
4798
+    }
4799
+
4800
+    public static function dataCurrentUserCanEnumerateTargetUser(): array {
4801
+        return [
4802
+            'Full match guest' => [true, true, false, false, false, false, false, true],
4803
+            'Full match user' => [false, true, false, false, false, false, false, true],
4804
+            'Enumeration off guest' => [true, false, false, false, false, false, false, false],
4805
+            'Enumeration off user' => [false, false, false, false, false, false, false, false],
4806
+            'Enumeration guest' => [true, false, true, false, false, false, false, true],
4807
+            'Enumeration user' => [false, false, true, false, false, false, false, true],
4808
+
4809
+            // Restricted enumerations guests never works
4810
+            'Guest phone' => [true, false, true, true, false, false, false, false],
4811
+            'Guest group' => [true, false, true, false, true, false, false, false],
4812
+            'Guest both' => [true, false, true, true, true, false, false, false],
4813
+
4814
+            // Restricted enumerations users
4815
+            'User phone but not known' => [false, false, true, true, false, false, false, false],
4816
+            'User phone known' => [false, false, true, true, false, true, false, true],
4817
+            'User group but no match' => [false, false, true, false, true, false, false, false],
4818
+            'User group with match' => [false, false, true, false, true, false, true, true],
4819
+        ];
4820
+    }
4821
+
4822
+    /**
4823
+     * @param bool $expected
4824
+     */
4825
+    #[\PHPUnit\Framework\Attributes\DataProvider('dataCurrentUserCanEnumerateTargetUser')]
4826
+    public function testCurrentUserCanEnumerateTargetUser(bool $currentUserIsGuest, bool $allowEnumerationFullMatch, bool $allowEnumeration, bool $limitEnumerationToPhone, bool $limitEnumerationToGroups, bool $isKnownToUser, bool $haveCommonGroup, bool $expected): void {
4827
+        /** @var IManager|MockObject $manager */
4828
+        $manager = $this->createManagerMock()
4829
+            ->onlyMethods([
4830
+                'allowEnumerationFullMatch',
4831
+                'allowEnumeration',
4832
+                'limitEnumerationToPhone',
4833
+                'limitEnumerationToGroups',
4834
+            ])
4835
+            ->getMock();
4836
+
4837
+        $manager->method('allowEnumerationFullMatch')
4838
+            ->willReturn($allowEnumerationFullMatch);
4839
+        $manager->method('allowEnumeration')
4840
+            ->willReturn($allowEnumeration);
4841
+        $manager->method('limitEnumerationToPhone')
4842
+            ->willReturn($limitEnumerationToPhone);
4843
+        $manager->method('limitEnumerationToGroups')
4844
+            ->willReturn($limitEnumerationToGroups);
4845
+
4846
+        $this->knownUserService->method('isKnownToUser')
4847
+            ->with('current', 'target')
4848
+            ->willReturn($isKnownToUser);
4849
+
4850
+        $currentUser = null;
4851
+        if (!$currentUserIsGuest) {
4852
+            $currentUser = $this->createMock(IUser::class);
4853
+            $currentUser->method('getUID')
4854
+                ->willReturn('current');
4855
+        }
4856
+        $targetUser = $this->createMock(IUser::class);
4857
+        $targetUser->method('getUID')
4858
+            ->willReturn('target');
4859
+
4860
+        if ($haveCommonGroup) {
4861
+            $this->groupManager->method('getUserGroupIds')
4862
+                ->willReturnMap([
4863
+                    [$targetUser, ['gid1', 'gid2']],
4864
+                    [$currentUser, ['gid2', 'gid3']],
4865
+                ]);
4866
+        } else {
4867
+            $this->groupManager->method('getUserGroupIds')
4868
+                ->willReturnMap([
4869
+                    [$targetUser, ['gid1', 'gid2']],
4870
+                    [$currentUser, ['gid3', 'gid4']],
4871
+                ]);
4872
+        }
4873
+
4874
+        $this->assertSame($expected, $manager->currentUserCanEnumerateTargetUser($currentUser, $targetUser));
4875
+    }
4876 4876
 }
4877 4877
 
4878 4878
 class DummyFactory implements IProviderFactory {
4879
-	/** @var IShareProvider */
4880
-	protected $provider;
4881
-
4882
-	public function __construct(IServerContainer $serverContainer) {
4883
-	}
4884
-
4885
-	/**
4886
-	 * @param IShareProvider $provider
4887
-	 */
4888
-	public function setProvider($provider) {
4889
-		$this->provider = $provider;
4890
-	}
4891
-
4892
-	/**
4893
-	 * @param string $id
4894
-	 * @return IShareProvider
4895
-	 */
4896
-	public function getProvider($id) {
4897
-		return $this->provider;
4898
-	}
4899
-
4900
-	/**
4901
-	 * @param int $shareType
4902
-	 * @return IShareProvider
4903
-	 */
4904
-	public function getProviderForType($shareType) {
4905
-		return $this->provider;
4906
-	}
4907
-
4908
-	/**
4909
-	 * @return IShareProvider[]
4910
-	 */
4911
-	public function getAllProviders() {
4912
-		return [$this->provider];
4913
-	}
4914
-
4915
-	public function registerProvider(string $shareProvier): void {
4916
-	}
4879
+    /** @var IShareProvider */
4880
+    protected $provider;
4881
+
4882
+    public function __construct(IServerContainer $serverContainer) {
4883
+    }
4884
+
4885
+    /**
4886
+     * @param IShareProvider $provider
4887
+     */
4888
+    public function setProvider($provider) {
4889
+        $this->provider = $provider;
4890
+    }
4891
+
4892
+    /**
4893
+     * @param string $id
4894
+     * @return IShareProvider
4895
+     */
4896
+    public function getProvider($id) {
4897
+        return $this->provider;
4898
+    }
4899
+
4900
+    /**
4901
+     * @param int $shareType
4902
+     * @return IShareProvider
4903
+     */
4904
+    public function getProviderForType($shareType) {
4905
+        return $this->provider;
4906
+    }
4907
+
4908
+    /**
4909
+     * @return IShareProvider[]
4910
+     */
4911
+    public function getAllProviders() {
4912
+        return [$this->provider];
4913
+    }
4914
+
4915
+    public function registerProvider(string $shareProvier): void {
4916
+    }
4917 4917
 }
4918 4918
 
4919 4919
 class DummyFactory2 extends DummyFactory {
4920
-	/** @var IShareProvider */
4921
-	private $provider2;
4922
-
4923
-	/**
4924
-	 * @param IShareProvider $provider
4925
-	 */
4926
-	public function setSecondProvider($provider) {
4927
-		$this->provider2 = $provider;
4928
-	}
4929
-
4930
-	public function getAllProviders() {
4931
-		return [$this->provider, $this->provider2];
4932
-	}
4933
-
4934
-	public function registerProvider(string $shareProvier): void {
4935
-	}
4920
+    /** @var IShareProvider */
4921
+    private $provider2;
4922
+
4923
+    /**
4924
+     * @param IShareProvider $provider
4925
+     */
4926
+    public function setSecondProvider($provider) {
4927
+        $this->provider2 = $provider;
4928
+    }
4929
+
4930
+    public function getAllProviders() {
4931
+        return [$this->provider, $this->provider2];
4932
+    }
4933
+
4934
+    public function registerProvider(string $shareProvier): void {
4935
+    }
4936 4936
 }
Please login to merge, or discard this patch.