Completed
Push — master ( f93d6e...f8bed8 )
by
unknown
18:34
created
lib/private/Server.php 1 patch
Indentation   +1373 added lines, -1373 removed lines patch added patch discarded remove patch
@@ -248,1418 +248,1418 @@
 block discarded – undo
248 248
  * TODO: hookup all manager classes
249 249
  */
250 250
 class Server extends ServerContainer implements IServerContainer {
251
-	/** @var string */
252
-	private $webRoot;
253
-
254
-	/**
255
-	 * @param string $webRoot
256
-	 * @param \OC\Config $config
257
-	 */
258
-	public function __construct($webRoot, \OC\Config $config) {
259
-		parent::__construct();
260
-		$this->webRoot = $webRoot;
261
-
262
-		// To find out if we are running from CLI or not
263
-		$this->registerParameter('isCLI', \OC::$CLI);
264
-		$this->registerParameter('serverRoot', \OC::$SERVERROOT);
265
-
266
-		$this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
267
-			return $c;
268
-		});
269
-		$this->registerDeprecatedAlias(\OCP\IServerContainer::class, ContainerInterface::class);
270
-
271
-		$this->registerAlias(\OCP\Calendar\IManager::class, \OC\Calendar\Manager::class);
272
-
273
-		$this->registerAlias(\OCP\Calendar\Resource\IManager::class, \OC\Calendar\Resource\Manager::class);
274
-
275
-		$this->registerAlias(\OCP\Calendar\Room\IManager::class, \OC\Calendar\Room\Manager::class);
276
-
277
-		$this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class);
278
-
279
-		$this->registerAlias(\OCP\ContextChat\IContentManager::class, \OC\ContextChat\ContentManager::class);
280
-
281
-		$this->registerAlias(\OCP\DirectEditing\IManager::class, \OC\DirectEditing\Manager::class);
282
-		$this->registerAlias(ITemplateManager::class, TemplateManager::class);
283
-		$this->registerAlias(\OCP\Template\ITemplateManager::class, \OC\Template\TemplateManager::class);
284
-
285
-		$this->registerAlias(IActionFactory::class, ActionFactory::class);
286
-
287
-		$this->registerService(View::class, function (Server $c) {
288
-			return new View();
289
-		}, false);
290
-
291
-		$this->registerService(IPreview::class, function (ContainerInterface $c) {
292
-			return new PreviewManager(
293
-				$c->get(\OCP\IConfig::class),
294
-				$c->get(IRootFolder::class),
295
-				new \OC\Preview\Storage\Root(
296
-					$c->get(IRootFolder::class),
297
-					$c->get(SystemConfig::class)
298
-				),
299
-				$c->get(IEventDispatcher::class),
300
-				$c->get(GeneratorHelper::class),
301
-				$c->get(ISession::class)->get('user_id'),
302
-				$c->get(Coordinator::class),
303
-				$c->get(IServerContainer::class),
304
-				$c->get(IBinaryFinder::class),
305
-				$c->get(IMagickSupport::class)
306
-			);
307
-		});
308
-		$this->registerAlias(IMimeIconProvider::class, MimeIconProvider::class);
309
-
310
-		$this->registerService(\OC\Preview\Watcher::class, function (ContainerInterface $c) {
311
-			return new \OC\Preview\Watcher(
312
-				new \OC\Preview\Storage\Root(
313
-					$c->get(IRootFolder::class),
314
-					$c->get(SystemConfig::class)
315
-				)
316
-			);
317
-		});
318
-
319
-		$this->registerService(IProfiler::class, function (Server $c) {
320
-			return new Profiler($c->get(SystemConfig::class));
321
-		});
322
-
323
-		$this->registerService(Encryption\Manager::class, function (Server $c): Encryption\Manager {
324
-			$view = new View();
325
-			$util = new Encryption\Util(
326
-				$view,
327
-				$c->get(IUserManager::class),
328
-				$c->get(IGroupManager::class),
329
-				$c->get(\OCP\IConfig::class)
330
-			);
331
-			return new Encryption\Manager(
332
-				$c->get(\OCP\IConfig::class),
333
-				$c->get(LoggerInterface::class),
334
-				$c->getL10N('core'),
335
-				new View(),
336
-				$util,
337
-				new ArrayCache()
338
-			);
339
-		});
340
-		$this->registerAlias(\OCP\Encryption\IManager::class, Encryption\Manager::class);
341
-
342
-		$this->registerService(IFile::class, function (ContainerInterface $c) {
343
-			$util = new Encryption\Util(
344
-				new View(),
345
-				$c->get(IUserManager::class),
346
-				$c->get(IGroupManager::class),
347
-				$c->get(\OCP\IConfig::class)
348
-			);
349
-			return new Encryption\File(
350
-				$util,
351
-				$c->get(IRootFolder::class),
352
-				$c->get(\OCP\Share\IManager::class)
353
-			);
354
-		});
355
-
356
-		$this->registerService(IStorage::class, function (ContainerInterface $c) {
357
-			$view = new View();
358
-			$util = new Encryption\Util(
359
-				$view,
360
-				$c->get(IUserManager::class),
361
-				$c->get(IGroupManager::class),
362
-				$c->get(\OCP\IConfig::class)
363
-			);
364
-
365
-			return new Encryption\Keys\Storage(
366
-				$view,
367
-				$util,
368
-				$c->get(ICrypto::class),
369
-				$c->get(\OCP\IConfig::class)
370
-			);
371
-		});
372
-
373
-		$this->registerAlias(\OCP\ITagManager::class, TagManager::class);
374
-
375
-		$this->registerService('SystemTagManagerFactory', function (ContainerInterface $c) {
376
-			/** @var \OCP\IConfig $config */
377
-			$config = $c->get(\OCP\IConfig::class);
378
-			$factoryClass = $config->getSystemValue('systemtags.managerFactory', SystemTagManagerFactory::class);
379
-			return new $factoryClass($this);
380
-		});
381
-		$this->registerService(ISystemTagManager::class, function (ContainerInterface $c) {
382
-			return $c->get('SystemTagManagerFactory')->getManager();
383
-		});
384
-		/** @deprecated 19.0.0 */
385
-		$this->registerDeprecatedAlias('SystemTagManager', ISystemTagManager::class);
386
-
387
-		$this->registerService(ISystemTagObjectMapper::class, function (ContainerInterface $c) {
388
-			return $c->get('SystemTagManagerFactory')->getObjectMapper();
389
-		});
390
-		$this->registerAlias(IFileAccess::class, FileAccess::class);
391
-		$this->registerService('RootFolder', function (ContainerInterface $c) {
392
-			$manager = \OC\Files\Filesystem::getMountManager();
393
-			$view = new View();
394
-			/** @var IUserSession $userSession */
395
-			$userSession = $c->get(IUserSession::class);
396
-			$root = new Root(
397
-				$manager,
398
-				$view,
399
-				$userSession->getUser(),
400
-				$c->get(IUserMountCache::class),
401
-				$this->get(LoggerInterface::class),
402
-				$this->get(IUserManager::class),
403
-				$this->get(IEventDispatcher::class),
404
-				$this->get(ICacheFactory::class),
405
-				$this->get(IAppConfig::class),
406
-			);
407
-
408
-			$previewConnector = new \OC\Preview\WatcherConnector(
409
-				$root,
410
-				$c->get(SystemConfig::class),
411
-				$this->get(IEventDispatcher::class)
412
-			);
413
-			$previewConnector->connectWatcher();
414
-
415
-			return $root;
416
-		});
417
-		$this->registerService(HookConnector::class, function (ContainerInterface $c) {
418
-			return new HookConnector(
419
-				$c->get(IRootFolder::class),
420
-				new View(),
421
-				$c->get(IEventDispatcher::class),
422
-				$c->get(LoggerInterface::class)
423
-			);
424
-		});
425
-
426
-		$this->registerService(IRootFolder::class, function (ContainerInterface $c) {
427
-			return new LazyRoot(function () use ($c) {
428
-				return $c->get('RootFolder');
429
-			});
430
-		});
431
-
432
-		$this->registerAlias(\OCP\IUserManager::class, \OC\User\Manager::class);
433
-
434
-		$this->registerService(DisplayNameCache::class, function (ContainerInterface $c) {
435
-			return $c->get(\OC\User\Manager::class)->getDisplayNameCache();
436
-		});
437
-
438
-		$this->registerService(\OCP\IGroupManager::class, function (ContainerInterface $c) {
439
-			$groupManager = new \OC\Group\Manager(
440
-				$this->get(IUserManager::class),
441
-				$this->get(IEventDispatcher::class),
442
-				$this->get(LoggerInterface::class),
443
-				$this->get(ICacheFactory::class),
444
-				$this->get(IRemoteAddress::class),
445
-			);
446
-			return $groupManager;
447
-		});
448
-
449
-		$this->registerService(Store::class, function (ContainerInterface $c) {
450
-			$session = $c->get(ISession::class);
451
-			if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
452
-				$tokenProvider = $c->get(IProvider::class);
453
-			} else {
454
-				$tokenProvider = null;
455
-			}
456
-			$logger = $c->get(LoggerInterface::class);
457
-			$crypto = $c->get(ICrypto::class);
458
-			return new Store($session, $logger, $crypto, $tokenProvider);
459
-		});
460
-		$this->registerAlias(IStore::class, Store::class);
461
-		$this->registerAlias(IProvider::class, Authentication\Token\Manager::class);
462
-		$this->registerAlias(OCPIProvider::class, Authentication\Token\Manager::class);
463
-
464
-		$this->registerService(\OC\User\Session::class, function (Server $c) {
465
-			$manager = $c->get(IUserManager::class);
466
-			$session = new \OC\Session\Memory();
467
-			$timeFactory = new TimeFactory();
468
-			// Token providers might require a working database. This code
469
-			// might however be called when Nextcloud is not yet setup.
470
-			if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
471
-				$provider = $c->get(IProvider::class);
472
-			} else {
473
-				$provider = null;
474
-			}
475
-
476
-			$userSession = new \OC\User\Session(
477
-				$manager,
478
-				$session,
479
-				$timeFactory,
480
-				$provider,
481
-				$c->get(\OCP\IConfig::class),
482
-				$c->get(ISecureRandom::class),
483
-				$c->get('LockdownManager'),
484
-				$c->get(LoggerInterface::class),
485
-				$c->get(IEventDispatcher::class),
486
-			);
487
-			/** @deprecated 21.0.0 use BeforeUserCreatedEvent event with the IEventDispatcher instead */
488
-			$userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
489
-				\OC_Hook::emit('OC_User', 'pre_createUser', ['run' => true, 'uid' => $uid, 'password' => $password]);
490
-			});
491
-			/** @deprecated 21.0.0 use UserCreatedEvent event with the IEventDispatcher instead */
492
-			$userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) {
493
-				/** @var \OC\User\User $user */
494
-				\OC_Hook::emit('OC_User', 'post_createUser', ['uid' => $user->getUID(), 'password' => $password]);
495
-			});
496
-			/** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
497
-			$userSession->listen('\OC\User', 'preDelete', function ($user) {
498
-				/** @var \OC\User\User $user */
499
-				\OC_Hook::emit('OC_User', 'pre_deleteUser', ['run' => true, 'uid' => $user->getUID()]);
500
-			});
501
-			/** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
502
-			$userSession->listen('\OC\User', 'postDelete', function ($user) {
503
-				/** @var \OC\User\User $user */
504
-				\OC_Hook::emit('OC_User', 'post_deleteUser', ['uid' => $user->getUID()]);
505
-			});
506
-			$userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) {
507
-				/** @var \OC\User\User $user */
508
-				\OC_Hook::emit('OC_User', 'pre_setPassword', ['run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword]);
509
-			});
510
-			$userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) {
511
-				/** @var \OC\User\User $user */
512
-				\OC_Hook::emit('OC_User', 'post_setPassword', ['run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword]);
513
-			});
514
-			$userSession->listen('\OC\User', 'preLogin', function ($uid, $password) {
515
-				\OC_Hook::emit('OC_User', 'pre_login', ['run' => true, 'uid' => $uid, 'password' => $password]);
516
-
517
-				/** @var IEventDispatcher $dispatcher */
518
-				$dispatcher = $this->get(IEventDispatcher::class);
519
-				$dispatcher->dispatchTyped(new BeforeUserLoggedInEvent($uid, $password));
520
-			});
521
-			$userSession->listen('\OC\User', 'postLogin', function ($user, $loginName, $password, $isTokenLogin) {
522
-				/** @var \OC\User\User $user */
523
-				\OC_Hook::emit('OC_User', 'post_login', ['run' => true, 'uid' => $user->getUID(), 'loginName' => $loginName, 'password' => $password, 'isTokenLogin' => $isTokenLogin]);
524
-
525
-				/** @var IEventDispatcher $dispatcher */
526
-				$dispatcher = $this->get(IEventDispatcher::class);
527
-				$dispatcher->dispatchTyped(new UserLoggedInEvent($user, $loginName, $password, $isTokenLogin));
528
-			});
529
-			$userSession->listen('\OC\User', 'preRememberedLogin', function ($uid) {
530
-				/** @var IEventDispatcher $dispatcher */
531
-				$dispatcher = $this->get(IEventDispatcher::class);
532
-				$dispatcher->dispatchTyped(new BeforeUserLoggedInWithCookieEvent($uid));
533
-			});
534
-			$userSession->listen('\OC\User', 'postRememberedLogin', function ($user, $password) {
535
-				/** @var \OC\User\User $user */
536
-				\OC_Hook::emit('OC_User', 'post_login', ['run' => true, 'uid' => $user->getUID(), 'password' => $password]);
537
-
538
-				/** @var IEventDispatcher $dispatcher */
539
-				$dispatcher = $this->get(IEventDispatcher::class);
540
-				$dispatcher->dispatchTyped(new UserLoggedInWithCookieEvent($user, $password));
541
-			});
542
-			$userSession->listen('\OC\User', 'logout', function ($user) {
543
-				\OC_Hook::emit('OC_User', 'logout', []);
544
-
545
-				/** @var IEventDispatcher $dispatcher */
546
-				$dispatcher = $this->get(IEventDispatcher::class);
547
-				$dispatcher->dispatchTyped(new BeforeUserLoggedOutEvent($user));
548
-			});
549
-			$userSession->listen('\OC\User', 'postLogout', function ($user) {
550
-				/** @var IEventDispatcher $dispatcher */
551
-				$dispatcher = $this->get(IEventDispatcher::class);
552
-				$dispatcher->dispatchTyped(new UserLoggedOutEvent($user));
553
-			});
554
-			$userSession->listen('\OC\User', 'changeUser', function ($user, $feature, $value, $oldValue) {
555
-				/** @var \OC\User\User $user */
556
-				\OC_Hook::emit('OC_User', 'changeUser', ['run' => true, 'user' => $user, 'feature' => $feature, 'value' => $value, 'old_value' => $oldValue]);
557
-			});
558
-			return $userSession;
559
-		});
560
-		$this->registerAlias(\OCP\IUserSession::class, \OC\User\Session::class);
561
-
562
-		$this->registerAlias(\OCP\Authentication\TwoFactorAuth\IRegistry::class, \OC\Authentication\TwoFactorAuth\Registry::class);
563
-
564
-		$this->registerAlias(INavigationManager::class, \OC\NavigationManager::class);
565
-
566
-		$this->registerAlias(\OCP\IConfig::class, \OC\AllConfig::class);
567
-
568
-		$this->registerService(\OC\SystemConfig::class, function ($c) use ($config) {
569
-			return new \OC\SystemConfig($config);
570
-		});
571
-
572
-		$this->registerAlias(IAppConfig::class, \OC\AppConfig::class);
573
-		$this->registerAlias(IUserConfig::class, \OC\Config\UserConfig::class);
574
-		$this->registerAlias(IAppManager::class, AppManager::class);
575
-
576
-		$this->registerService(IFactory::class, function (Server $c) {
577
-			return new \OC\L10N\Factory(
578
-				$c->get(\OCP\IConfig::class),
579
-				$c->getRequest(),
580
-				$c->get(IUserSession::class),
581
-				$c->get(ICacheFactory::class),
582
-				\OC::$SERVERROOT,
583
-				$c->get(IAppManager::class),
584
-			);
585
-		});
586
-
587
-		$this->registerAlias(IURLGenerator::class, URLGenerator::class);
588
-
589
-		$this->registerAlias(ICache::class, Cache\File::class);
590
-		$this->registerService(Factory::class, function (Server $c) {
591
-			$profiler = $c->get(IProfiler::class);
592
-			$logger = $c->get(LoggerInterface::class);
593
-			$serverVersion = $c->get(ServerVersion::class);
594
-			/** @var SystemConfig $config */
595
-			$config = $c->get(SystemConfig::class);
596
-			if (!$config->getValue('installed', false) || (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
597
-				return new \OC\Memcache\Factory(
598
-					$logger,
599
-					$profiler,
600
-					$serverVersion,
601
-					ArrayCache::class,
602
-					ArrayCache::class,
603
-					ArrayCache::class
604
-				);
605
-			}
606
-
607
-			return new \OC\Memcache\Factory(
608
-				$logger,
609
-				$profiler,
610
-				$serverVersion,
611
-				/** @psalm-taint-escape callable */
612
-				$config->getValue('memcache.local', null),
613
-				/** @psalm-taint-escape callable */
614
-				$config->getValue('memcache.distributed', null),
615
-				/** @psalm-taint-escape callable */
616
-				$config->getValue('memcache.locking', null),
617
-				/** @psalm-taint-escape callable */
618
-				$config->getValue('redis_log_file')
619
-			);
620
-		});
621
-		$this->registerAlias(ICacheFactory::class, Factory::class);
622
-
623
-		$this->registerService('RedisFactory', function (Server $c) {
624
-			$systemConfig = $c->get(SystemConfig::class);
625
-			return new RedisFactory($systemConfig, $c->get(IEventLogger::class));
626
-		});
627
-
628
-		$this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
629
-			$l10n = $this->get(IFactory::class)->get('lib');
630
-			return new \OC\Activity\Manager(
631
-				$c->getRequest(),
632
-				$c->get(IUserSession::class),
633
-				$c->get(\OCP\IConfig::class),
634
-				$c->get(IValidator::class),
635
-				$c->get(IRichTextFormatter::class),
636
-				$l10n,
637
-				$c->get(ITimeFactory::class),
638
-			);
639
-		});
640
-
641
-		$this->registerService(\OCP\Activity\IEventMerger::class, function (Server $c) {
642
-			return new \OC\Activity\EventMerger(
643
-				$c->getL10N('lib')
644
-			);
645
-		});
646
-		$this->registerAlias(IValidator::class, Validator::class);
647
-
648
-		$this->registerService(AvatarManager::class, function (Server $c) {
649
-			return new AvatarManager(
650
-				$c->get(IUserSession::class),
651
-				$c->get(\OC\User\Manager::class),
652
-				$c->getAppDataDir('avatar'),
653
-				$c->getL10N('lib'),
654
-				$c->get(LoggerInterface::class),
655
-				$c->get(\OCP\IConfig::class),
656
-				$c->get(IAccountManager::class),
657
-				$c->get(KnownUserService::class)
658
-			);
659
-		});
660
-
661
-		$this->registerAlias(IAvatarManager::class, AvatarManager::class);
662
-
663
-		$this->registerAlias(\OCP\Support\CrashReport\IRegistry::class, \OC\Support\CrashReport\Registry::class);
664
-		$this->registerAlias(\OCP\Support\Subscription\IRegistry::class, \OC\Support\Subscription\Registry::class);
665
-		$this->registerAlias(\OCP\Support\Subscription\IAssertion::class, \OC\Support\Subscription\Assertion::class);
666
-
667
-		/** Only used by the PsrLoggerAdapter should not be used by apps */
668
-		$this->registerService(\OC\Log::class, function (Server $c) {
669
-			$logType = $c->get(AllConfig::class)->getSystemValue('log_type', 'file');
670
-			$factory = new LogFactory($c, $this->get(SystemConfig::class));
671
-			$logger = $factory->get($logType);
672
-			$registry = $c->get(\OCP\Support\CrashReport\IRegistry::class);
673
-
674
-			return new Log($logger, $this->get(SystemConfig::class), crashReporters: $registry);
675
-		});
676
-		// PSR-3 logger
677
-		$this->registerAlias(LoggerInterface::class, PsrLoggerAdapter::class);
678
-
679
-		$this->registerService(ILogFactory::class, function (Server $c) {
680
-			return new LogFactory($c, $this->get(SystemConfig::class));
681
-		});
682
-
683
-		$this->registerAlias(IJobList::class, \OC\BackgroundJob\JobList::class);
684
-
685
-		$this->registerService(Router::class, function (Server $c) {
686
-			$cacheFactory = $c->get(ICacheFactory::class);
687
-			if ($cacheFactory->isLocalCacheAvailable()) {
688
-				$router = $c->resolve(CachingRouter::class);
689
-			} else {
690
-				$router = $c->resolve(Router::class);
691
-			}
692
-			return $router;
693
-		});
694
-		$this->registerAlias(IRouter::class, Router::class);
695
-
696
-		$this->registerService(\OC\Security\RateLimiting\Backend\IBackend::class, function ($c) {
697
-			$config = $c->get(\OCP\IConfig::class);
698
-			if (ltrim($config->getSystemValueString('memcache.distributed', ''), '\\') === \OC\Memcache\Redis::class) {
699
-				$backend = new \OC\Security\RateLimiting\Backend\MemoryCacheBackend(
700
-					$c->get(AllConfig::class),
701
-					$this->get(ICacheFactory::class),
702
-					new \OC\AppFramework\Utility\TimeFactory()
703
-				);
704
-			} else {
705
-				$backend = new \OC\Security\RateLimiting\Backend\DatabaseBackend(
706
-					$c->get(AllConfig::class),
707
-					$c->get(IDBConnection::class),
708
-					new \OC\AppFramework\Utility\TimeFactory()
709
-				);
710
-			}
711
-
712
-			return $backend;
713
-		});
714
-
715
-		$this->registerAlias(\OCP\Security\ISecureRandom::class, SecureRandom::class);
716
-		$this->registerAlias(\OCP\Security\IRemoteHostValidator::class, \OC\Security\RemoteHostValidator::class);
717
-		$this->registerAlias(IVerificationToken::class, VerificationToken::class);
718
-
719
-		$this->registerAlias(ICrypto::class, Crypto::class);
720
-
721
-		$this->registerAlias(IHasher::class, Hasher::class);
722
-
723
-		$this->registerAlias(ICredentialsManager::class, CredentialsManager::class);
724
-
725
-		$this->registerAlias(IDBConnection::class, ConnectionAdapter::class);
726
-		$this->registerService(Connection::class, function (Server $c) {
727
-			$systemConfig = $c->get(SystemConfig::class);
728
-			$factory = new \OC\DB\ConnectionFactory($systemConfig, $c->get(ICacheFactory::class));
729
-			$type = $systemConfig->getValue('dbtype', 'sqlite');
730
-			if (!$factory->isValidType($type)) {
731
-				throw new \OC\DatabaseException('Invalid database type');
732
-			}
733
-			$connection = $factory->getConnection($type, []);
734
-			return $connection;
735
-		});
736
-
737
-		$this->registerAlias(ICertificateManager::class, CertificateManager::class);
738
-		$this->registerAlias(IClientService::class, ClientService::class);
739
-		$this->registerService(NegativeDnsCache::class, function (ContainerInterface $c) {
740
-			return new NegativeDnsCache(
741
-				$c->get(ICacheFactory::class),
742
-			);
743
-		});
744
-		$this->registerDeprecatedAlias('HttpClientService', IClientService::class);
745
-		$this->registerService(IEventLogger::class, function (ContainerInterface $c) {
746
-			return new EventLogger($c->get(SystemConfig::class), $c->get(LoggerInterface::class), $c->get(Log::class));
747
-		});
748
-
749
-		$this->registerService(IQueryLogger::class, function (ContainerInterface $c) {
750
-			$queryLogger = new QueryLogger();
751
-			if ($c->get(SystemConfig::class)->getValue('debug', false)) {
752
-				// In debug mode, module is being activated by default
753
-				$queryLogger->activate();
754
-			}
755
-			return $queryLogger;
756
-		});
757
-
758
-		$this->registerAlias(ITempManager::class, TempManager::class);
759
-		$this->registerAlias(IDateTimeZone::class, DateTimeZone::class);
760
-
761
-		$this->registerService(IDateTimeFormatter::class, function (Server $c) {
762
-			$language = $c->get(\OCP\IConfig::class)->getUserValue($c->get(ISession::class)->get('user_id'), 'core', 'lang', null);
763
-
764
-			return new DateTimeFormatter(
765
-				$c->get(IDateTimeZone::class)->getTimeZone(),
766
-				$c->getL10N('lib', $language)
767
-			);
768
-		});
769
-
770
-		$this->registerService(IUserMountCache::class, function (ContainerInterface $c) {
771
-			$mountCache = $c->get(UserMountCache::class);
772
-			$listener = new UserMountCacheListener($mountCache);
773
-			$listener->listen($c->get(IUserManager::class));
774
-			return $mountCache;
775
-		});
776
-
777
-		$this->registerService(IMountProviderCollection::class, function (ContainerInterface $c) {
778
-			$loader = $c->get(IStorageFactory::class);
779
-			$mountCache = $c->get(IUserMountCache::class);
780
-			$eventLogger = $c->get(IEventLogger::class);
781
-			$manager = new MountProviderCollection($loader, $mountCache, $eventLogger);
782
-
783
-			// builtin providers
784
-
785
-			$config = $c->get(\OCP\IConfig::class);
786
-			$logger = $c->get(LoggerInterface::class);
787
-			$objectStoreConfig = $c->get(PrimaryObjectStoreConfig::class);
788
-			$manager->registerProvider(new CacheMountProvider($config));
789
-			$manager->registerHomeProvider(new LocalHomeMountProvider());
790
-			$manager->registerHomeProvider(new ObjectHomeMountProvider($objectStoreConfig));
791
-			$manager->registerRootProvider(new RootMountProvider($objectStoreConfig, $config));
792
-			$manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config));
793
-
794
-			return $manager;
795
-		});
796
-
797
-		$this->registerService(IBus::class, function (ContainerInterface $c) {
798
-			$busClass = $c->get(\OCP\IConfig::class)->getSystemValueString('commandbus');
799
-			if ($busClass) {
800
-				[$app, $class] = explode('::', $busClass, 2);
801
-				if ($c->get(IAppManager::class)->isEnabledForUser($app)) {
802
-					$c->get(IAppManager::class)->loadApp($app);
803
-					return $c->get($class);
804
-				} else {
805
-					throw new ServiceUnavailableException("The app providing the command bus ($app) is not enabled");
806
-				}
807
-			} else {
808
-				$jobList = $c->get(IJobList::class);
809
-				return new CronBus($jobList);
810
-			}
811
-		});
812
-		$this->registerDeprecatedAlias('AsyncCommandBus', IBus::class);
813
-		$this->registerAlias(ITrustedDomainHelper::class, TrustedDomainHelper::class);
814
-		$this->registerAlias(IThrottler::class, Throttler::class);
815
-
816
-		$this->registerService(\OC\Security\Bruteforce\Backend\IBackend::class, function ($c) {
817
-			$config = $c->get(\OCP\IConfig::class);
818
-			if (!$config->getSystemValueBool('auth.bruteforce.protection.force.database', false)
819
-				&& ltrim($config->getSystemValueString('memcache.distributed', ''), '\\') === \OC\Memcache\Redis::class) {
820
-				$backend = $c->get(\OC\Security\Bruteforce\Backend\MemoryCacheBackend::class);
821
-			} else {
822
-				$backend = $c->get(\OC\Security\Bruteforce\Backend\DatabaseBackend::class);
823
-			}
824
-
825
-			return $backend;
826
-		});
827
-
828
-		$this->registerDeprecatedAlias('IntegrityCodeChecker', Checker::class);
829
-		$this->registerService(Checker::class, function (ContainerInterface $c) {
830
-			// IConfig requires a working database. This code
831
-			// might however be called when Nextcloud is not yet setup.
832
-			if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
833
-				$config = $c->get(\OCP\IConfig::class);
834
-				$appConfig = $c->get(\OCP\IAppConfig::class);
835
-			} else {
836
-				$config = null;
837
-				$appConfig = null;
838
-			}
839
-
840
-			return new Checker(
841
-				$c->get(ServerVersion::class),
842
-				$c->get(EnvironmentHelper::class),
843
-				new FileAccessHelper(),
844
-				$config,
845
-				$appConfig,
846
-				$c->get(ICacheFactory::class),
847
-				$c->get(IAppManager::class),
848
-				$c->get(IMimeTypeDetector::class)
849
-			);
850
-		});
851
-		$this->registerService(Request::class, function (ContainerInterface $c) {
852
-			if (isset($this['urlParams'])) {
853
-				$urlParams = $this['urlParams'];
854
-			} else {
855
-				$urlParams = [];
856
-			}
857
-
858
-			if (defined('PHPUNIT_RUN') && PHPUNIT_RUN
859
-				&& in_array('fakeinput', stream_get_wrappers())
860
-			) {
861
-				$stream = 'fakeinput://data';
862
-			} else {
863
-				$stream = 'php://input';
864
-			}
865
-
866
-			return new Request(
867
-				[
868
-					'get' => $_GET,
869
-					'post' => $_POST,
870
-					'files' => $_FILES,
871
-					'server' => $_SERVER,
872
-					'env' => $_ENV,
873
-					'cookies' => $_COOKIE,
874
-					'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
875
-						? $_SERVER['REQUEST_METHOD']
876
-						: '',
877
-					'urlParams' => $urlParams,
878
-				],
879
-				$this->get(IRequestId::class),
880
-				$this->get(\OCP\IConfig::class),
881
-				$this->get(CsrfTokenManager::class),
882
-				$stream
883
-			);
884
-		});
885
-		$this->registerAlias(\OCP\IRequest::class, Request::class);
886
-
887
-		$this->registerService(IRequestId::class, function (ContainerInterface $c): IRequestId {
888
-			return new RequestId(
889
-				$_SERVER['UNIQUE_ID'] ?? '',
890
-				$this->get(ISecureRandom::class)
891
-			);
892
-		});
893
-
894
-		/** @since 32.0.0 */
895
-		$this->registerAlias(IEmailValidator::class, EmailValidator::class);
896
-
897
-		$this->registerService(IMailer::class, function (Server $c) {
898
-			return new Mailer(
899
-				$c->get(\OCP\IConfig::class),
900
-				$c->get(LoggerInterface::class),
901
-				$c->get(Defaults::class),
902
-				$c->get(IURLGenerator::class),
903
-				$c->getL10N('lib'),
904
-				$c->get(IEventDispatcher::class),
905
-				$c->get(IFactory::class),
906
-				$c->get(IEmailValidator::class),
907
-			);
908
-		});
909
-
910
-		/** @since 30.0.0 */
911
-		$this->registerAlias(\OCP\Mail\Provider\IManager::class, \OC\Mail\Provider\Manager::class);
912
-
913
-		$this->registerService(ILDAPProviderFactory::class, function (ContainerInterface $c) {
914
-			$config = $c->get(\OCP\IConfig::class);
915
-			$factoryClass = $config->getSystemValue('ldapProviderFactory', null);
916
-			if (is_null($factoryClass) || !class_exists($factoryClass)) {
917
-				return new NullLDAPProviderFactory($this);
918
-			}
919
-			/** @var \OCP\LDAP\ILDAPProviderFactory $factory */
920
-			return new $factoryClass($this);
921
-		});
922
-		$this->registerService(ILDAPProvider::class, function (ContainerInterface $c) {
923
-			$factory = $c->get(ILDAPProviderFactory::class);
924
-			return $factory->getLDAPProvider();
925
-		});
926
-		$this->registerService(ILockingProvider::class, function (ContainerInterface $c) {
927
-			$ini = $c->get(IniGetWrapper::class);
928
-			$config = $c->get(\OCP\IConfig::class);
929
-			$ttl = $config->getSystemValueInt('filelocking.ttl', max(3600, $ini->getNumeric('max_execution_time')));
930
-			if ($config->getSystemValueBool('filelocking.enabled', true) || (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
931
-				/** @var \OC\Memcache\Factory $memcacheFactory */
932
-				$memcacheFactory = $c->get(ICacheFactory::class);
933
-				$memcache = $memcacheFactory->createLocking('lock');
934
-				if (!($memcache instanceof \OC\Memcache\NullCache)) {
935
-					$timeFactory = $c->get(ITimeFactory::class);
936
-					return new MemcacheLockingProvider($memcache, $timeFactory, $ttl);
937
-				}
938
-				return new DBLockingProvider(
939
-					$c->get(IDBConnection::class),
940
-					new TimeFactory(),
941
-					$ttl,
942
-					!\OC::$CLI
943
-				);
944
-			}
945
-			return new NoopLockingProvider();
946
-		});
947
-
948
-		$this->registerService(ILockManager::class, function (Server $c): LockManager {
949
-			return new LockManager();
950
-		});
951
-
952
-		$this->registerAlias(ILockdownManager::class, 'LockdownManager');
953
-		$this->registerService(SetupManager::class, function ($c) {
954
-			// create the setupmanager through the mount manager to resolve the cyclic dependency
955
-			return $c->get(\OC\Files\Mount\Manager::class)->getSetupManager();
956
-		});
957
-		$this->registerAlias(IMountManager::class, \OC\Files\Mount\Manager::class);
958
-
959
-		$this->registerService(IMimeTypeDetector::class, function (ContainerInterface $c) {
960
-			return new \OC\Files\Type\Detection(
961
-				$c->get(IURLGenerator::class),
962
-				$c->get(LoggerInterface::class),
963
-				\OC::$configDir,
964
-				\OC::$SERVERROOT . '/resources/config/'
965
-			);
966
-		});
967
-
968
-		$this->registerAlias(IMimeTypeLoader::class, Loader::class);
969
-		$this->registerService(BundleFetcher::class, function () {
970
-			return new BundleFetcher($this->getL10N('lib'));
971
-		});
972
-		$this->registerAlias(\OCP\Notification\IManager::class, Manager::class);
973
-
974
-		$this->registerService(CapabilitiesManager::class, function (ContainerInterface $c) {
975
-			$manager = new CapabilitiesManager($c->get(LoggerInterface::class));
976
-			$manager->registerCapability(function () use ($c) {
977
-				return new \OC\OCS\CoreCapabilities($c->get(\OCP\IConfig::class));
978
-			});
979
-			$manager->registerCapability(function () use ($c) {
980
-				return $c->get(\OC\Security\Bruteforce\Capabilities::class);
981
-			});
982
-			return $manager;
983
-		});
984
-
985
-		$this->registerService(ICommentsManager::class, function (Server $c) {
986
-			$config = $c->get(\OCP\IConfig::class);
987
-			$factoryClass = $config->getSystemValue('comments.managerFactory', CommentsManagerFactory::class);
988
-			/** @var \OCP\Comments\ICommentsManagerFactory $factory */
989
-			$factory = new $factoryClass($this);
990
-			$manager = $factory->getManager();
991
-
992
-			$manager->registerDisplayNameResolver('user', function ($id) use ($c) {
993
-				$manager = $c->get(IUserManager::class);
994
-				$userDisplayName = $manager->getDisplayName($id);
995
-				if ($userDisplayName === null) {
996
-					$l = $c->get(IFactory::class)->get('core');
997
-					return $l->t('Unknown account');
998
-				}
999
-				return $userDisplayName;
1000
-			});
1001
-
1002
-			return $manager;
1003
-		});
1004
-
1005
-		$this->registerAlias(\OC_Defaults::class, 'ThemingDefaults');
1006
-		$this->registerService('ThemingDefaults', function (Server $c) {
1007
-			try {
1008
-				$classExists = class_exists('OCA\Theming\ThemingDefaults');
1009
-			} catch (\OCP\AutoloadNotAllowedException $e) {
1010
-				// App disabled or in maintenance mode
1011
-				$classExists = false;
1012
-			}
1013
-
1014
-			if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isEnabledForAnyone('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) {
1015
-				$backgroundService = new BackgroundService(
1016
-					$c->get(IRootFolder::class),
1017
-					$c->getAppDataDir('theming'),
1018
-					$c->get(IAppConfig::class),
1019
-					$c->get(\OCP\IConfig::class),
1020
-					$c->get(ISession::class)->get('user_id'),
1021
-				);
1022
-				$imageManager = new ImageManager(
1023
-					$c->get(\OCP\IConfig::class),
1024
-					$c->getAppDataDir('theming'),
1025
-					$c->get(IURLGenerator::class),
1026
-					$c->get(ICacheFactory::class),
1027
-					$c->get(LoggerInterface::class),
1028
-					$c->get(ITempManager::class),
1029
-					$backgroundService,
1030
-				);
1031
-				return new ThemingDefaults(
1032
-					$c->get(\OCP\IConfig::class),
1033
-					$c->get(\OCP\IAppConfig::class),
1034
-					$c->getL10N('theming'),
1035
-					$c->get(IUserSession::class),
1036
-					$c->get(IURLGenerator::class),
1037
-					$c->get(ICacheFactory::class),
1038
-					new Util($c->get(ServerVersion::class), $c->get(\OCP\IConfig::class), $this->get(IAppManager::class), $c->getAppDataDir('theming'), $imageManager),
1039
-					$imageManager,
1040
-					$c->get(IAppManager::class),
1041
-					$c->get(INavigationManager::class),
1042
-					$backgroundService,
1043
-				);
1044
-			}
1045
-			return new \OC_Defaults();
1046
-		});
1047
-		$this->registerService(JSCombiner::class, function (Server $c) {
1048
-			return new JSCombiner(
1049
-				$c->getAppDataDir('js'),
1050
-				$c->get(IURLGenerator::class),
1051
-				$this->get(ICacheFactory::class),
1052
-				$c->get(\OCP\IConfig::class),
1053
-				$c->get(LoggerInterface::class)
1054
-			);
1055
-		});
1056
-		$this->registerAlias(\OCP\EventDispatcher\IEventDispatcher::class, \OC\EventDispatcher\EventDispatcher::class);
1057
-
1058
-		$this->registerService('CryptoWrapper', function (ContainerInterface $c) {
1059
-			// FIXME: Instantiated here due to cyclic dependency
1060
-			$request = new Request(
1061
-				[
1062
-					'get' => $_GET,
1063
-					'post' => $_POST,
1064
-					'files' => $_FILES,
1065
-					'server' => $_SERVER,
1066
-					'env' => $_ENV,
1067
-					'cookies' => $_COOKIE,
1068
-					'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
1069
-						? $_SERVER['REQUEST_METHOD']
1070
-						: null,
1071
-				],
1072
-				$c->get(IRequestId::class),
1073
-				$c->get(\OCP\IConfig::class)
1074
-			);
1075
-
1076
-			return new CryptoWrapper(
1077
-				$c->get(ICrypto::class),
1078
-				$c->get(ISecureRandom::class),
1079
-				$request
1080
-			);
1081
-		});
1082
-		$this->registerService(SessionStorage::class, function (ContainerInterface $c) {
1083
-			return new SessionStorage($c->get(ISession::class));
1084
-		});
1085
-		$this->registerAlias(\OCP\Security\IContentSecurityPolicyManager::class, ContentSecurityPolicyManager::class);
1086
-
1087
-		$this->registerService(IProviderFactory::class, function (ContainerInterface $c) {
1088
-			$config = $c->get(\OCP\IConfig::class);
1089
-			$factoryClass = $config->getSystemValue('sharing.managerFactory', ProviderFactory::class);
1090
-			/** @var \OCP\Share\IProviderFactory $factory */
1091
-			return $c->get($factoryClass);
1092
-		});
1093
-
1094
-		$this->registerAlias(\OCP\Share\IManager::class, \OC\Share20\Manager::class);
1095
-
1096
-		$this->registerService(\OCP\Collaboration\Collaborators\ISearch::class, function (Server $c) {
1097
-			$instance = new Collaboration\Collaborators\Search($c);
1098
-
1099
-			// register default plugins
1100
-			$instance->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => UserPlugin::class]);
1101
-			$instance->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => GroupPlugin::class]);
1102
-			$instance->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => MailPlugin::class]);
1103
-			$instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => RemotePlugin::class]);
1104
-			$instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE_GROUP', 'class' => RemoteGroupPlugin::class]);
1105
-
1106
-			return $instance;
1107
-		});
1108
-		$this->registerAlias(\OCP\Collaboration\Collaborators\ISearchResult::class, \OC\Collaboration\Collaborators\SearchResult::class);
1109
-
1110
-		$this->registerAlias(\OCP\Collaboration\AutoComplete\IManager::class, \OC\Collaboration\AutoComplete\Manager::class);
1111
-
1112
-		$this->registerAlias(\OCP\Collaboration\Resources\IProviderManager::class, \OC\Collaboration\Resources\ProviderManager::class);
1113
-		$this->registerAlias(\OCP\Collaboration\Resources\IManager::class, \OC\Collaboration\Resources\Manager::class);
1114
-
1115
-		$this->registerAlias(IReferenceManager::class, ReferenceManager::class);
1116
-		$this->registerAlias(ITeamManager::class, TeamManager::class);
1117
-
1118
-		$this->registerDeprecatedAlias('SettingsManager', \OC\Settings\Manager::class);
1119
-		$this->registerAlias(\OCP\Settings\IManager::class, \OC\Settings\Manager::class);
1120
-		$this->registerService(\OC\Files\AppData\Factory::class, function (ContainerInterface $c) {
1121
-			return new \OC\Files\AppData\Factory(
1122
-				$c->get(IRootFolder::class),
1123
-				$c->get(SystemConfig::class)
1124
-			);
1125
-		});
1126
-
1127
-		$this->registerService('LockdownManager', function (ContainerInterface $c) {
1128
-			return new LockdownManager(function () use ($c) {
1129
-				return $c->get(ISession::class);
1130
-			});
1131
-		});
1132
-
1133
-		$this->registerService(\OCP\OCS\IDiscoveryService::class, function (ContainerInterface $c) {
1134
-			return new DiscoveryService(
1135
-				$c->get(ICacheFactory::class),
1136
-				$c->get(IClientService::class)
1137
-			);
1138
-		});
1139
-		$this->registerAlias(IOCMDiscoveryService::class, OCMDiscoveryService::class);
1140
-
1141
-		$this->registerService(ICloudIdManager::class, function (ContainerInterface $c) {
1142
-			return new CloudIdManager(
1143
-				$c->get(ICacheFactory::class),
1144
-				$c->get(IEventDispatcher::class),
1145
-				$c->get(\OCP\Contacts\IManager::class),
1146
-				$c->get(IURLGenerator::class),
1147
-				$c->get(IUserManager::class),
1148
-			);
1149
-		});
251
+    /** @var string */
252
+    private $webRoot;
253
+
254
+    /**
255
+     * @param string $webRoot
256
+     * @param \OC\Config $config
257
+     */
258
+    public function __construct($webRoot, \OC\Config $config) {
259
+        parent::__construct();
260
+        $this->webRoot = $webRoot;
261
+
262
+        // To find out if we are running from CLI or not
263
+        $this->registerParameter('isCLI', \OC::$CLI);
264
+        $this->registerParameter('serverRoot', \OC::$SERVERROOT);
265
+
266
+        $this->registerService(ContainerInterface::class, function (ContainerInterface $c) {
267
+            return $c;
268
+        });
269
+        $this->registerDeprecatedAlias(\OCP\IServerContainer::class, ContainerInterface::class);
270
+
271
+        $this->registerAlias(\OCP\Calendar\IManager::class, \OC\Calendar\Manager::class);
272
+
273
+        $this->registerAlias(\OCP\Calendar\Resource\IManager::class, \OC\Calendar\Resource\Manager::class);
274
+
275
+        $this->registerAlias(\OCP\Calendar\Room\IManager::class, \OC\Calendar\Room\Manager::class);
276
+
277
+        $this->registerAlias(\OCP\Contacts\IManager::class, \OC\ContactsManager::class);
278
+
279
+        $this->registerAlias(\OCP\ContextChat\IContentManager::class, \OC\ContextChat\ContentManager::class);
280
+
281
+        $this->registerAlias(\OCP\DirectEditing\IManager::class, \OC\DirectEditing\Manager::class);
282
+        $this->registerAlias(ITemplateManager::class, TemplateManager::class);
283
+        $this->registerAlias(\OCP\Template\ITemplateManager::class, \OC\Template\TemplateManager::class);
284
+
285
+        $this->registerAlias(IActionFactory::class, ActionFactory::class);
286
+
287
+        $this->registerService(View::class, function (Server $c) {
288
+            return new View();
289
+        }, false);
290
+
291
+        $this->registerService(IPreview::class, function (ContainerInterface $c) {
292
+            return new PreviewManager(
293
+                $c->get(\OCP\IConfig::class),
294
+                $c->get(IRootFolder::class),
295
+                new \OC\Preview\Storage\Root(
296
+                    $c->get(IRootFolder::class),
297
+                    $c->get(SystemConfig::class)
298
+                ),
299
+                $c->get(IEventDispatcher::class),
300
+                $c->get(GeneratorHelper::class),
301
+                $c->get(ISession::class)->get('user_id'),
302
+                $c->get(Coordinator::class),
303
+                $c->get(IServerContainer::class),
304
+                $c->get(IBinaryFinder::class),
305
+                $c->get(IMagickSupport::class)
306
+            );
307
+        });
308
+        $this->registerAlias(IMimeIconProvider::class, MimeIconProvider::class);
309
+
310
+        $this->registerService(\OC\Preview\Watcher::class, function (ContainerInterface $c) {
311
+            return new \OC\Preview\Watcher(
312
+                new \OC\Preview\Storage\Root(
313
+                    $c->get(IRootFolder::class),
314
+                    $c->get(SystemConfig::class)
315
+                )
316
+            );
317
+        });
318
+
319
+        $this->registerService(IProfiler::class, function (Server $c) {
320
+            return new Profiler($c->get(SystemConfig::class));
321
+        });
322
+
323
+        $this->registerService(Encryption\Manager::class, function (Server $c): Encryption\Manager {
324
+            $view = new View();
325
+            $util = new Encryption\Util(
326
+                $view,
327
+                $c->get(IUserManager::class),
328
+                $c->get(IGroupManager::class),
329
+                $c->get(\OCP\IConfig::class)
330
+            );
331
+            return new Encryption\Manager(
332
+                $c->get(\OCP\IConfig::class),
333
+                $c->get(LoggerInterface::class),
334
+                $c->getL10N('core'),
335
+                new View(),
336
+                $util,
337
+                new ArrayCache()
338
+            );
339
+        });
340
+        $this->registerAlias(\OCP\Encryption\IManager::class, Encryption\Manager::class);
341
+
342
+        $this->registerService(IFile::class, function (ContainerInterface $c) {
343
+            $util = new Encryption\Util(
344
+                new View(),
345
+                $c->get(IUserManager::class),
346
+                $c->get(IGroupManager::class),
347
+                $c->get(\OCP\IConfig::class)
348
+            );
349
+            return new Encryption\File(
350
+                $util,
351
+                $c->get(IRootFolder::class),
352
+                $c->get(\OCP\Share\IManager::class)
353
+            );
354
+        });
355
+
356
+        $this->registerService(IStorage::class, function (ContainerInterface $c) {
357
+            $view = new View();
358
+            $util = new Encryption\Util(
359
+                $view,
360
+                $c->get(IUserManager::class),
361
+                $c->get(IGroupManager::class),
362
+                $c->get(\OCP\IConfig::class)
363
+            );
364
+
365
+            return new Encryption\Keys\Storage(
366
+                $view,
367
+                $util,
368
+                $c->get(ICrypto::class),
369
+                $c->get(\OCP\IConfig::class)
370
+            );
371
+        });
372
+
373
+        $this->registerAlias(\OCP\ITagManager::class, TagManager::class);
374
+
375
+        $this->registerService('SystemTagManagerFactory', function (ContainerInterface $c) {
376
+            /** @var \OCP\IConfig $config */
377
+            $config = $c->get(\OCP\IConfig::class);
378
+            $factoryClass = $config->getSystemValue('systemtags.managerFactory', SystemTagManagerFactory::class);
379
+            return new $factoryClass($this);
380
+        });
381
+        $this->registerService(ISystemTagManager::class, function (ContainerInterface $c) {
382
+            return $c->get('SystemTagManagerFactory')->getManager();
383
+        });
384
+        /** @deprecated 19.0.0 */
385
+        $this->registerDeprecatedAlias('SystemTagManager', ISystemTagManager::class);
386
+
387
+        $this->registerService(ISystemTagObjectMapper::class, function (ContainerInterface $c) {
388
+            return $c->get('SystemTagManagerFactory')->getObjectMapper();
389
+        });
390
+        $this->registerAlias(IFileAccess::class, FileAccess::class);
391
+        $this->registerService('RootFolder', function (ContainerInterface $c) {
392
+            $manager = \OC\Files\Filesystem::getMountManager();
393
+            $view = new View();
394
+            /** @var IUserSession $userSession */
395
+            $userSession = $c->get(IUserSession::class);
396
+            $root = new Root(
397
+                $manager,
398
+                $view,
399
+                $userSession->getUser(),
400
+                $c->get(IUserMountCache::class),
401
+                $this->get(LoggerInterface::class),
402
+                $this->get(IUserManager::class),
403
+                $this->get(IEventDispatcher::class),
404
+                $this->get(ICacheFactory::class),
405
+                $this->get(IAppConfig::class),
406
+            );
407
+
408
+            $previewConnector = new \OC\Preview\WatcherConnector(
409
+                $root,
410
+                $c->get(SystemConfig::class),
411
+                $this->get(IEventDispatcher::class)
412
+            );
413
+            $previewConnector->connectWatcher();
414
+
415
+            return $root;
416
+        });
417
+        $this->registerService(HookConnector::class, function (ContainerInterface $c) {
418
+            return new HookConnector(
419
+                $c->get(IRootFolder::class),
420
+                new View(),
421
+                $c->get(IEventDispatcher::class),
422
+                $c->get(LoggerInterface::class)
423
+            );
424
+        });
425
+
426
+        $this->registerService(IRootFolder::class, function (ContainerInterface $c) {
427
+            return new LazyRoot(function () use ($c) {
428
+                return $c->get('RootFolder');
429
+            });
430
+        });
431
+
432
+        $this->registerAlias(\OCP\IUserManager::class, \OC\User\Manager::class);
433
+
434
+        $this->registerService(DisplayNameCache::class, function (ContainerInterface $c) {
435
+            return $c->get(\OC\User\Manager::class)->getDisplayNameCache();
436
+        });
437
+
438
+        $this->registerService(\OCP\IGroupManager::class, function (ContainerInterface $c) {
439
+            $groupManager = new \OC\Group\Manager(
440
+                $this->get(IUserManager::class),
441
+                $this->get(IEventDispatcher::class),
442
+                $this->get(LoggerInterface::class),
443
+                $this->get(ICacheFactory::class),
444
+                $this->get(IRemoteAddress::class),
445
+            );
446
+            return $groupManager;
447
+        });
448
+
449
+        $this->registerService(Store::class, function (ContainerInterface $c) {
450
+            $session = $c->get(ISession::class);
451
+            if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
452
+                $tokenProvider = $c->get(IProvider::class);
453
+            } else {
454
+                $tokenProvider = null;
455
+            }
456
+            $logger = $c->get(LoggerInterface::class);
457
+            $crypto = $c->get(ICrypto::class);
458
+            return new Store($session, $logger, $crypto, $tokenProvider);
459
+        });
460
+        $this->registerAlias(IStore::class, Store::class);
461
+        $this->registerAlias(IProvider::class, Authentication\Token\Manager::class);
462
+        $this->registerAlias(OCPIProvider::class, Authentication\Token\Manager::class);
463
+
464
+        $this->registerService(\OC\User\Session::class, function (Server $c) {
465
+            $manager = $c->get(IUserManager::class);
466
+            $session = new \OC\Session\Memory();
467
+            $timeFactory = new TimeFactory();
468
+            // Token providers might require a working database. This code
469
+            // might however be called when Nextcloud is not yet setup.
470
+            if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
471
+                $provider = $c->get(IProvider::class);
472
+            } else {
473
+                $provider = null;
474
+            }
475
+
476
+            $userSession = new \OC\User\Session(
477
+                $manager,
478
+                $session,
479
+                $timeFactory,
480
+                $provider,
481
+                $c->get(\OCP\IConfig::class),
482
+                $c->get(ISecureRandom::class),
483
+                $c->get('LockdownManager'),
484
+                $c->get(LoggerInterface::class),
485
+                $c->get(IEventDispatcher::class),
486
+            );
487
+            /** @deprecated 21.0.0 use BeforeUserCreatedEvent event with the IEventDispatcher instead */
488
+            $userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) {
489
+                \OC_Hook::emit('OC_User', 'pre_createUser', ['run' => true, 'uid' => $uid, 'password' => $password]);
490
+            });
491
+            /** @deprecated 21.0.0 use UserCreatedEvent event with the IEventDispatcher instead */
492
+            $userSession->listen('\OC\User', 'postCreateUser', function ($user, $password) {
493
+                /** @var \OC\User\User $user */
494
+                \OC_Hook::emit('OC_User', 'post_createUser', ['uid' => $user->getUID(), 'password' => $password]);
495
+            });
496
+            /** @deprecated 21.0.0 use BeforeUserDeletedEvent event with the IEventDispatcher instead */
497
+            $userSession->listen('\OC\User', 'preDelete', function ($user) {
498
+                /** @var \OC\User\User $user */
499
+                \OC_Hook::emit('OC_User', 'pre_deleteUser', ['run' => true, 'uid' => $user->getUID()]);
500
+            });
501
+            /** @deprecated 21.0.0 use UserDeletedEvent event with the IEventDispatcher instead */
502
+            $userSession->listen('\OC\User', 'postDelete', function ($user) {
503
+                /** @var \OC\User\User $user */
504
+                \OC_Hook::emit('OC_User', 'post_deleteUser', ['uid' => $user->getUID()]);
505
+            });
506
+            $userSession->listen('\OC\User', 'preSetPassword', function ($user, $password, $recoveryPassword) {
507
+                /** @var \OC\User\User $user */
508
+                \OC_Hook::emit('OC_User', 'pre_setPassword', ['run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword]);
509
+            });
510
+            $userSession->listen('\OC\User', 'postSetPassword', function ($user, $password, $recoveryPassword) {
511
+                /** @var \OC\User\User $user */
512
+                \OC_Hook::emit('OC_User', 'post_setPassword', ['run' => true, 'uid' => $user->getUID(), 'password' => $password, 'recoveryPassword' => $recoveryPassword]);
513
+            });
514
+            $userSession->listen('\OC\User', 'preLogin', function ($uid, $password) {
515
+                \OC_Hook::emit('OC_User', 'pre_login', ['run' => true, 'uid' => $uid, 'password' => $password]);
516
+
517
+                /** @var IEventDispatcher $dispatcher */
518
+                $dispatcher = $this->get(IEventDispatcher::class);
519
+                $dispatcher->dispatchTyped(new BeforeUserLoggedInEvent($uid, $password));
520
+            });
521
+            $userSession->listen('\OC\User', 'postLogin', function ($user, $loginName, $password, $isTokenLogin) {
522
+                /** @var \OC\User\User $user */
523
+                \OC_Hook::emit('OC_User', 'post_login', ['run' => true, 'uid' => $user->getUID(), 'loginName' => $loginName, 'password' => $password, 'isTokenLogin' => $isTokenLogin]);
524
+
525
+                /** @var IEventDispatcher $dispatcher */
526
+                $dispatcher = $this->get(IEventDispatcher::class);
527
+                $dispatcher->dispatchTyped(new UserLoggedInEvent($user, $loginName, $password, $isTokenLogin));
528
+            });
529
+            $userSession->listen('\OC\User', 'preRememberedLogin', function ($uid) {
530
+                /** @var IEventDispatcher $dispatcher */
531
+                $dispatcher = $this->get(IEventDispatcher::class);
532
+                $dispatcher->dispatchTyped(new BeforeUserLoggedInWithCookieEvent($uid));
533
+            });
534
+            $userSession->listen('\OC\User', 'postRememberedLogin', function ($user, $password) {
535
+                /** @var \OC\User\User $user */
536
+                \OC_Hook::emit('OC_User', 'post_login', ['run' => true, 'uid' => $user->getUID(), 'password' => $password]);
537
+
538
+                /** @var IEventDispatcher $dispatcher */
539
+                $dispatcher = $this->get(IEventDispatcher::class);
540
+                $dispatcher->dispatchTyped(new UserLoggedInWithCookieEvent($user, $password));
541
+            });
542
+            $userSession->listen('\OC\User', 'logout', function ($user) {
543
+                \OC_Hook::emit('OC_User', 'logout', []);
544
+
545
+                /** @var IEventDispatcher $dispatcher */
546
+                $dispatcher = $this->get(IEventDispatcher::class);
547
+                $dispatcher->dispatchTyped(new BeforeUserLoggedOutEvent($user));
548
+            });
549
+            $userSession->listen('\OC\User', 'postLogout', function ($user) {
550
+                /** @var IEventDispatcher $dispatcher */
551
+                $dispatcher = $this->get(IEventDispatcher::class);
552
+                $dispatcher->dispatchTyped(new UserLoggedOutEvent($user));
553
+            });
554
+            $userSession->listen('\OC\User', 'changeUser', function ($user, $feature, $value, $oldValue) {
555
+                /** @var \OC\User\User $user */
556
+                \OC_Hook::emit('OC_User', 'changeUser', ['run' => true, 'user' => $user, 'feature' => $feature, 'value' => $value, 'old_value' => $oldValue]);
557
+            });
558
+            return $userSession;
559
+        });
560
+        $this->registerAlias(\OCP\IUserSession::class, \OC\User\Session::class);
561
+
562
+        $this->registerAlias(\OCP\Authentication\TwoFactorAuth\IRegistry::class, \OC\Authentication\TwoFactorAuth\Registry::class);
563
+
564
+        $this->registerAlias(INavigationManager::class, \OC\NavigationManager::class);
565
+
566
+        $this->registerAlias(\OCP\IConfig::class, \OC\AllConfig::class);
567
+
568
+        $this->registerService(\OC\SystemConfig::class, function ($c) use ($config) {
569
+            return new \OC\SystemConfig($config);
570
+        });
571
+
572
+        $this->registerAlias(IAppConfig::class, \OC\AppConfig::class);
573
+        $this->registerAlias(IUserConfig::class, \OC\Config\UserConfig::class);
574
+        $this->registerAlias(IAppManager::class, AppManager::class);
575
+
576
+        $this->registerService(IFactory::class, function (Server $c) {
577
+            return new \OC\L10N\Factory(
578
+                $c->get(\OCP\IConfig::class),
579
+                $c->getRequest(),
580
+                $c->get(IUserSession::class),
581
+                $c->get(ICacheFactory::class),
582
+                \OC::$SERVERROOT,
583
+                $c->get(IAppManager::class),
584
+            );
585
+        });
586
+
587
+        $this->registerAlias(IURLGenerator::class, URLGenerator::class);
588
+
589
+        $this->registerAlias(ICache::class, Cache\File::class);
590
+        $this->registerService(Factory::class, function (Server $c) {
591
+            $profiler = $c->get(IProfiler::class);
592
+            $logger = $c->get(LoggerInterface::class);
593
+            $serverVersion = $c->get(ServerVersion::class);
594
+            /** @var SystemConfig $config */
595
+            $config = $c->get(SystemConfig::class);
596
+            if (!$config->getValue('installed', false) || (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
597
+                return new \OC\Memcache\Factory(
598
+                    $logger,
599
+                    $profiler,
600
+                    $serverVersion,
601
+                    ArrayCache::class,
602
+                    ArrayCache::class,
603
+                    ArrayCache::class
604
+                );
605
+            }
606
+
607
+            return new \OC\Memcache\Factory(
608
+                $logger,
609
+                $profiler,
610
+                $serverVersion,
611
+                /** @psalm-taint-escape callable */
612
+                $config->getValue('memcache.local', null),
613
+                /** @psalm-taint-escape callable */
614
+                $config->getValue('memcache.distributed', null),
615
+                /** @psalm-taint-escape callable */
616
+                $config->getValue('memcache.locking', null),
617
+                /** @psalm-taint-escape callable */
618
+                $config->getValue('redis_log_file')
619
+            );
620
+        });
621
+        $this->registerAlias(ICacheFactory::class, Factory::class);
622
+
623
+        $this->registerService('RedisFactory', function (Server $c) {
624
+            $systemConfig = $c->get(SystemConfig::class);
625
+            return new RedisFactory($systemConfig, $c->get(IEventLogger::class));
626
+        });
627
+
628
+        $this->registerService(\OCP\Activity\IManager::class, function (Server $c) {
629
+            $l10n = $this->get(IFactory::class)->get('lib');
630
+            return new \OC\Activity\Manager(
631
+                $c->getRequest(),
632
+                $c->get(IUserSession::class),
633
+                $c->get(\OCP\IConfig::class),
634
+                $c->get(IValidator::class),
635
+                $c->get(IRichTextFormatter::class),
636
+                $l10n,
637
+                $c->get(ITimeFactory::class),
638
+            );
639
+        });
640
+
641
+        $this->registerService(\OCP\Activity\IEventMerger::class, function (Server $c) {
642
+            return new \OC\Activity\EventMerger(
643
+                $c->getL10N('lib')
644
+            );
645
+        });
646
+        $this->registerAlias(IValidator::class, Validator::class);
647
+
648
+        $this->registerService(AvatarManager::class, function (Server $c) {
649
+            return new AvatarManager(
650
+                $c->get(IUserSession::class),
651
+                $c->get(\OC\User\Manager::class),
652
+                $c->getAppDataDir('avatar'),
653
+                $c->getL10N('lib'),
654
+                $c->get(LoggerInterface::class),
655
+                $c->get(\OCP\IConfig::class),
656
+                $c->get(IAccountManager::class),
657
+                $c->get(KnownUserService::class)
658
+            );
659
+        });
660
+
661
+        $this->registerAlias(IAvatarManager::class, AvatarManager::class);
662
+
663
+        $this->registerAlias(\OCP\Support\CrashReport\IRegistry::class, \OC\Support\CrashReport\Registry::class);
664
+        $this->registerAlias(\OCP\Support\Subscription\IRegistry::class, \OC\Support\Subscription\Registry::class);
665
+        $this->registerAlias(\OCP\Support\Subscription\IAssertion::class, \OC\Support\Subscription\Assertion::class);
666
+
667
+        /** Only used by the PsrLoggerAdapter should not be used by apps */
668
+        $this->registerService(\OC\Log::class, function (Server $c) {
669
+            $logType = $c->get(AllConfig::class)->getSystemValue('log_type', 'file');
670
+            $factory = new LogFactory($c, $this->get(SystemConfig::class));
671
+            $logger = $factory->get($logType);
672
+            $registry = $c->get(\OCP\Support\CrashReport\IRegistry::class);
673
+
674
+            return new Log($logger, $this->get(SystemConfig::class), crashReporters: $registry);
675
+        });
676
+        // PSR-3 logger
677
+        $this->registerAlias(LoggerInterface::class, PsrLoggerAdapter::class);
678
+
679
+        $this->registerService(ILogFactory::class, function (Server $c) {
680
+            return new LogFactory($c, $this->get(SystemConfig::class));
681
+        });
682
+
683
+        $this->registerAlias(IJobList::class, \OC\BackgroundJob\JobList::class);
684
+
685
+        $this->registerService(Router::class, function (Server $c) {
686
+            $cacheFactory = $c->get(ICacheFactory::class);
687
+            if ($cacheFactory->isLocalCacheAvailable()) {
688
+                $router = $c->resolve(CachingRouter::class);
689
+            } else {
690
+                $router = $c->resolve(Router::class);
691
+            }
692
+            return $router;
693
+        });
694
+        $this->registerAlias(IRouter::class, Router::class);
695
+
696
+        $this->registerService(\OC\Security\RateLimiting\Backend\IBackend::class, function ($c) {
697
+            $config = $c->get(\OCP\IConfig::class);
698
+            if (ltrim($config->getSystemValueString('memcache.distributed', ''), '\\') === \OC\Memcache\Redis::class) {
699
+                $backend = new \OC\Security\RateLimiting\Backend\MemoryCacheBackend(
700
+                    $c->get(AllConfig::class),
701
+                    $this->get(ICacheFactory::class),
702
+                    new \OC\AppFramework\Utility\TimeFactory()
703
+                );
704
+            } else {
705
+                $backend = new \OC\Security\RateLimiting\Backend\DatabaseBackend(
706
+                    $c->get(AllConfig::class),
707
+                    $c->get(IDBConnection::class),
708
+                    new \OC\AppFramework\Utility\TimeFactory()
709
+                );
710
+            }
711
+
712
+            return $backend;
713
+        });
714
+
715
+        $this->registerAlias(\OCP\Security\ISecureRandom::class, SecureRandom::class);
716
+        $this->registerAlias(\OCP\Security\IRemoteHostValidator::class, \OC\Security\RemoteHostValidator::class);
717
+        $this->registerAlias(IVerificationToken::class, VerificationToken::class);
718
+
719
+        $this->registerAlias(ICrypto::class, Crypto::class);
720
+
721
+        $this->registerAlias(IHasher::class, Hasher::class);
722
+
723
+        $this->registerAlias(ICredentialsManager::class, CredentialsManager::class);
724
+
725
+        $this->registerAlias(IDBConnection::class, ConnectionAdapter::class);
726
+        $this->registerService(Connection::class, function (Server $c) {
727
+            $systemConfig = $c->get(SystemConfig::class);
728
+            $factory = new \OC\DB\ConnectionFactory($systemConfig, $c->get(ICacheFactory::class));
729
+            $type = $systemConfig->getValue('dbtype', 'sqlite');
730
+            if (!$factory->isValidType($type)) {
731
+                throw new \OC\DatabaseException('Invalid database type');
732
+            }
733
+            $connection = $factory->getConnection($type, []);
734
+            return $connection;
735
+        });
736
+
737
+        $this->registerAlias(ICertificateManager::class, CertificateManager::class);
738
+        $this->registerAlias(IClientService::class, ClientService::class);
739
+        $this->registerService(NegativeDnsCache::class, function (ContainerInterface $c) {
740
+            return new NegativeDnsCache(
741
+                $c->get(ICacheFactory::class),
742
+            );
743
+        });
744
+        $this->registerDeprecatedAlias('HttpClientService', IClientService::class);
745
+        $this->registerService(IEventLogger::class, function (ContainerInterface $c) {
746
+            return new EventLogger($c->get(SystemConfig::class), $c->get(LoggerInterface::class), $c->get(Log::class));
747
+        });
748
+
749
+        $this->registerService(IQueryLogger::class, function (ContainerInterface $c) {
750
+            $queryLogger = new QueryLogger();
751
+            if ($c->get(SystemConfig::class)->getValue('debug', false)) {
752
+                // In debug mode, module is being activated by default
753
+                $queryLogger->activate();
754
+            }
755
+            return $queryLogger;
756
+        });
757
+
758
+        $this->registerAlias(ITempManager::class, TempManager::class);
759
+        $this->registerAlias(IDateTimeZone::class, DateTimeZone::class);
760
+
761
+        $this->registerService(IDateTimeFormatter::class, function (Server $c) {
762
+            $language = $c->get(\OCP\IConfig::class)->getUserValue($c->get(ISession::class)->get('user_id'), 'core', 'lang', null);
763
+
764
+            return new DateTimeFormatter(
765
+                $c->get(IDateTimeZone::class)->getTimeZone(),
766
+                $c->getL10N('lib', $language)
767
+            );
768
+        });
769
+
770
+        $this->registerService(IUserMountCache::class, function (ContainerInterface $c) {
771
+            $mountCache = $c->get(UserMountCache::class);
772
+            $listener = new UserMountCacheListener($mountCache);
773
+            $listener->listen($c->get(IUserManager::class));
774
+            return $mountCache;
775
+        });
776
+
777
+        $this->registerService(IMountProviderCollection::class, function (ContainerInterface $c) {
778
+            $loader = $c->get(IStorageFactory::class);
779
+            $mountCache = $c->get(IUserMountCache::class);
780
+            $eventLogger = $c->get(IEventLogger::class);
781
+            $manager = new MountProviderCollection($loader, $mountCache, $eventLogger);
782
+
783
+            // builtin providers
784
+
785
+            $config = $c->get(\OCP\IConfig::class);
786
+            $logger = $c->get(LoggerInterface::class);
787
+            $objectStoreConfig = $c->get(PrimaryObjectStoreConfig::class);
788
+            $manager->registerProvider(new CacheMountProvider($config));
789
+            $manager->registerHomeProvider(new LocalHomeMountProvider());
790
+            $manager->registerHomeProvider(new ObjectHomeMountProvider($objectStoreConfig));
791
+            $manager->registerRootProvider(new RootMountProvider($objectStoreConfig, $config));
792
+            $manager->registerRootProvider(new ObjectStorePreviewCacheMountProvider($logger, $config));
793
+
794
+            return $manager;
795
+        });
796
+
797
+        $this->registerService(IBus::class, function (ContainerInterface $c) {
798
+            $busClass = $c->get(\OCP\IConfig::class)->getSystemValueString('commandbus');
799
+            if ($busClass) {
800
+                [$app, $class] = explode('::', $busClass, 2);
801
+                if ($c->get(IAppManager::class)->isEnabledForUser($app)) {
802
+                    $c->get(IAppManager::class)->loadApp($app);
803
+                    return $c->get($class);
804
+                } else {
805
+                    throw new ServiceUnavailableException("The app providing the command bus ($app) is not enabled");
806
+                }
807
+            } else {
808
+                $jobList = $c->get(IJobList::class);
809
+                return new CronBus($jobList);
810
+            }
811
+        });
812
+        $this->registerDeprecatedAlias('AsyncCommandBus', IBus::class);
813
+        $this->registerAlias(ITrustedDomainHelper::class, TrustedDomainHelper::class);
814
+        $this->registerAlias(IThrottler::class, Throttler::class);
815
+
816
+        $this->registerService(\OC\Security\Bruteforce\Backend\IBackend::class, function ($c) {
817
+            $config = $c->get(\OCP\IConfig::class);
818
+            if (!$config->getSystemValueBool('auth.bruteforce.protection.force.database', false)
819
+                && ltrim($config->getSystemValueString('memcache.distributed', ''), '\\') === \OC\Memcache\Redis::class) {
820
+                $backend = $c->get(\OC\Security\Bruteforce\Backend\MemoryCacheBackend::class);
821
+            } else {
822
+                $backend = $c->get(\OC\Security\Bruteforce\Backend\DatabaseBackend::class);
823
+            }
824
+
825
+            return $backend;
826
+        });
827
+
828
+        $this->registerDeprecatedAlias('IntegrityCodeChecker', Checker::class);
829
+        $this->registerService(Checker::class, function (ContainerInterface $c) {
830
+            // IConfig requires a working database. This code
831
+            // might however be called when Nextcloud is not yet setup.
832
+            if (\OC::$server->get(SystemConfig::class)->getValue('installed', false)) {
833
+                $config = $c->get(\OCP\IConfig::class);
834
+                $appConfig = $c->get(\OCP\IAppConfig::class);
835
+            } else {
836
+                $config = null;
837
+                $appConfig = null;
838
+            }
839
+
840
+            return new Checker(
841
+                $c->get(ServerVersion::class),
842
+                $c->get(EnvironmentHelper::class),
843
+                new FileAccessHelper(),
844
+                $config,
845
+                $appConfig,
846
+                $c->get(ICacheFactory::class),
847
+                $c->get(IAppManager::class),
848
+                $c->get(IMimeTypeDetector::class)
849
+            );
850
+        });
851
+        $this->registerService(Request::class, function (ContainerInterface $c) {
852
+            if (isset($this['urlParams'])) {
853
+                $urlParams = $this['urlParams'];
854
+            } else {
855
+                $urlParams = [];
856
+            }
857
+
858
+            if (defined('PHPUNIT_RUN') && PHPUNIT_RUN
859
+                && in_array('fakeinput', stream_get_wrappers())
860
+            ) {
861
+                $stream = 'fakeinput://data';
862
+            } else {
863
+                $stream = 'php://input';
864
+            }
865
+
866
+            return new Request(
867
+                [
868
+                    'get' => $_GET,
869
+                    'post' => $_POST,
870
+                    'files' => $_FILES,
871
+                    'server' => $_SERVER,
872
+                    'env' => $_ENV,
873
+                    'cookies' => $_COOKIE,
874
+                    'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
875
+                        ? $_SERVER['REQUEST_METHOD']
876
+                        : '',
877
+                    'urlParams' => $urlParams,
878
+                ],
879
+                $this->get(IRequestId::class),
880
+                $this->get(\OCP\IConfig::class),
881
+                $this->get(CsrfTokenManager::class),
882
+                $stream
883
+            );
884
+        });
885
+        $this->registerAlias(\OCP\IRequest::class, Request::class);
886
+
887
+        $this->registerService(IRequestId::class, function (ContainerInterface $c): IRequestId {
888
+            return new RequestId(
889
+                $_SERVER['UNIQUE_ID'] ?? '',
890
+                $this->get(ISecureRandom::class)
891
+            );
892
+        });
893
+
894
+        /** @since 32.0.0 */
895
+        $this->registerAlias(IEmailValidator::class, EmailValidator::class);
896
+
897
+        $this->registerService(IMailer::class, function (Server $c) {
898
+            return new Mailer(
899
+                $c->get(\OCP\IConfig::class),
900
+                $c->get(LoggerInterface::class),
901
+                $c->get(Defaults::class),
902
+                $c->get(IURLGenerator::class),
903
+                $c->getL10N('lib'),
904
+                $c->get(IEventDispatcher::class),
905
+                $c->get(IFactory::class),
906
+                $c->get(IEmailValidator::class),
907
+            );
908
+        });
909
+
910
+        /** @since 30.0.0 */
911
+        $this->registerAlias(\OCP\Mail\Provider\IManager::class, \OC\Mail\Provider\Manager::class);
912
+
913
+        $this->registerService(ILDAPProviderFactory::class, function (ContainerInterface $c) {
914
+            $config = $c->get(\OCP\IConfig::class);
915
+            $factoryClass = $config->getSystemValue('ldapProviderFactory', null);
916
+            if (is_null($factoryClass) || !class_exists($factoryClass)) {
917
+                return new NullLDAPProviderFactory($this);
918
+            }
919
+            /** @var \OCP\LDAP\ILDAPProviderFactory $factory */
920
+            return new $factoryClass($this);
921
+        });
922
+        $this->registerService(ILDAPProvider::class, function (ContainerInterface $c) {
923
+            $factory = $c->get(ILDAPProviderFactory::class);
924
+            return $factory->getLDAPProvider();
925
+        });
926
+        $this->registerService(ILockingProvider::class, function (ContainerInterface $c) {
927
+            $ini = $c->get(IniGetWrapper::class);
928
+            $config = $c->get(\OCP\IConfig::class);
929
+            $ttl = $config->getSystemValueInt('filelocking.ttl', max(3600, $ini->getNumeric('max_execution_time')));
930
+            if ($config->getSystemValueBool('filelocking.enabled', true) || (defined('PHPUNIT_RUN') && PHPUNIT_RUN)) {
931
+                /** @var \OC\Memcache\Factory $memcacheFactory */
932
+                $memcacheFactory = $c->get(ICacheFactory::class);
933
+                $memcache = $memcacheFactory->createLocking('lock');
934
+                if (!($memcache instanceof \OC\Memcache\NullCache)) {
935
+                    $timeFactory = $c->get(ITimeFactory::class);
936
+                    return new MemcacheLockingProvider($memcache, $timeFactory, $ttl);
937
+                }
938
+                return new DBLockingProvider(
939
+                    $c->get(IDBConnection::class),
940
+                    new TimeFactory(),
941
+                    $ttl,
942
+                    !\OC::$CLI
943
+                );
944
+            }
945
+            return new NoopLockingProvider();
946
+        });
947
+
948
+        $this->registerService(ILockManager::class, function (Server $c): LockManager {
949
+            return new LockManager();
950
+        });
951
+
952
+        $this->registerAlias(ILockdownManager::class, 'LockdownManager');
953
+        $this->registerService(SetupManager::class, function ($c) {
954
+            // create the setupmanager through the mount manager to resolve the cyclic dependency
955
+            return $c->get(\OC\Files\Mount\Manager::class)->getSetupManager();
956
+        });
957
+        $this->registerAlias(IMountManager::class, \OC\Files\Mount\Manager::class);
958
+
959
+        $this->registerService(IMimeTypeDetector::class, function (ContainerInterface $c) {
960
+            return new \OC\Files\Type\Detection(
961
+                $c->get(IURLGenerator::class),
962
+                $c->get(LoggerInterface::class),
963
+                \OC::$configDir,
964
+                \OC::$SERVERROOT . '/resources/config/'
965
+            );
966
+        });
967
+
968
+        $this->registerAlias(IMimeTypeLoader::class, Loader::class);
969
+        $this->registerService(BundleFetcher::class, function () {
970
+            return new BundleFetcher($this->getL10N('lib'));
971
+        });
972
+        $this->registerAlias(\OCP\Notification\IManager::class, Manager::class);
973
+
974
+        $this->registerService(CapabilitiesManager::class, function (ContainerInterface $c) {
975
+            $manager = new CapabilitiesManager($c->get(LoggerInterface::class));
976
+            $manager->registerCapability(function () use ($c) {
977
+                return new \OC\OCS\CoreCapabilities($c->get(\OCP\IConfig::class));
978
+            });
979
+            $manager->registerCapability(function () use ($c) {
980
+                return $c->get(\OC\Security\Bruteforce\Capabilities::class);
981
+            });
982
+            return $manager;
983
+        });
984
+
985
+        $this->registerService(ICommentsManager::class, function (Server $c) {
986
+            $config = $c->get(\OCP\IConfig::class);
987
+            $factoryClass = $config->getSystemValue('comments.managerFactory', CommentsManagerFactory::class);
988
+            /** @var \OCP\Comments\ICommentsManagerFactory $factory */
989
+            $factory = new $factoryClass($this);
990
+            $manager = $factory->getManager();
991
+
992
+            $manager->registerDisplayNameResolver('user', function ($id) use ($c) {
993
+                $manager = $c->get(IUserManager::class);
994
+                $userDisplayName = $manager->getDisplayName($id);
995
+                if ($userDisplayName === null) {
996
+                    $l = $c->get(IFactory::class)->get('core');
997
+                    return $l->t('Unknown account');
998
+                }
999
+                return $userDisplayName;
1000
+            });
1001
+
1002
+            return $manager;
1003
+        });
1004
+
1005
+        $this->registerAlias(\OC_Defaults::class, 'ThemingDefaults');
1006
+        $this->registerService('ThemingDefaults', function (Server $c) {
1007
+            try {
1008
+                $classExists = class_exists('OCA\Theming\ThemingDefaults');
1009
+            } catch (\OCP\AutoloadNotAllowedException $e) {
1010
+                // App disabled or in maintenance mode
1011
+                $classExists = false;
1012
+            }
1013
+
1014
+            if ($classExists && $c->get(\OCP\IConfig::class)->getSystemValueBool('installed', false) && $c->get(IAppManager::class)->isEnabledForAnyone('theming') && $c->get(TrustedDomainHelper::class)->isTrustedDomain($c->getRequest()->getInsecureServerHost())) {
1015
+                $backgroundService = new BackgroundService(
1016
+                    $c->get(IRootFolder::class),
1017
+                    $c->getAppDataDir('theming'),
1018
+                    $c->get(IAppConfig::class),
1019
+                    $c->get(\OCP\IConfig::class),
1020
+                    $c->get(ISession::class)->get('user_id'),
1021
+                );
1022
+                $imageManager = new ImageManager(
1023
+                    $c->get(\OCP\IConfig::class),
1024
+                    $c->getAppDataDir('theming'),
1025
+                    $c->get(IURLGenerator::class),
1026
+                    $c->get(ICacheFactory::class),
1027
+                    $c->get(LoggerInterface::class),
1028
+                    $c->get(ITempManager::class),
1029
+                    $backgroundService,
1030
+                );
1031
+                return new ThemingDefaults(
1032
+                    $c->get(\OCP\IConfig::class),
1033
+                    $c->get(\OCP\IAppConfig::class),
1034
+                    $c->getL10N('theming'),
1035
+                    $c->get(IUserSession::class),
1036
+                    $c->get(IURLGenerator::class),
1037
+                    $c->get(ICacheFactory::class),
1038
+                    new Util($c->get(ServerVersion::class), $c->get(\OCP\IConfig::class), $this->get(IAppManager::class), $c->getAppDataDir('theming'), $imageManager),
1039
+                    $imageManager,
1040
+                    $c->get(IAppManager::class),
1041
+                    $c->get(INavigationManager::class),
1042
+                    $backgroundService,
1043
+                );
1044
+            }
1045
+            return new \OC_Defaults();
1046
+        });
1047
+        $this->registerService(JSCombiner::class, function (Server $c) {
1048
+            return new JSCombiner(
1049
+                $c->getAppDataDir('js'),
1050
+                $c->get(IURLGenerator::class),
1051
+                $this->get(ICacheFactory::class),
1052
+                $c->get(\OCP\IConfig::class),
1053
+                $c->get(LoggerInterface::class)
1054
+            );
1055
+        });
1056
+        $this->registerAlias(\OCP\EventDispatcher\IEventDispatcher::class, \OC\EventDispatcher\EventDispatcher::class);
1057
+
1058
+        $this->registerService('CryptoWrapper', function (ContainerInterface $c) {
1059
+            // FIXME: Instantiated here due to cyclic dependency
1060
+            $request = new Request(
1061
+                [
1062
+                    'get' => $_GET,
1063
+                    'post' => $_POST,
1064
+                    'files' => $_FILES,
1065
+                    'server' => $_SERVER,
1066
+                    'env' => $_ENV,
1067
+                    'cookies' => $_COOKIE,
1068
+                    'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD']))
1069
+                        ? $_SERVER['REQUEST_METHOD']
1070
+                        : null,
1071
+                ],
1072
+                $c->get(IRequestId::class),
1073
+                $c->get(\OCP\IConfig::class)
1074
+            );
1075
+
1076
+            return new CryptoWrapper(
1077
+                $c->get(ICrypto::class),
1078
+                $c->get(ISecureRandom::class),
1079
+                $request
1080
+            );
1081
+        });
1082
+        $this->registerService(SessionStorage::class, function (ContainerInterface $c) {
1083
+            return new SessionStorage($c->get(ISession::class));
1084
+        });
1085
+        $this->registerAlias(\OCP\Security\IContentSecurityPolicyManager::class, ContentSecurityPolicyManager::class);
1086
+
1087
+        $this->registerService(IProviderFactory::class, function (ContainerInterface $c) {
1088
+            $config = $c->get(\OCP\IConfig::class);
1089
+            $factoryClass = $config->getSystemValue('sharing.managerFactory', ProviderFactory::class);
1090
+            /** @var \OCP\Share\IProviderFactory $factory */
1091
+            return $c->get($factoryClass);
1092
+        });
1093
+
1094
+        $this->registerAlias(\OCP\Share\IManager::class, \OC\Share20\Manager::class);
1095
+
1096
+        $this->registerService(\OCP\Collaboration\Collaborators\ISearch::class, function (Server $c) {
1097
+            $instance = new Collaboration\Collaborators\Search($c);
1098
+
1099
+            // register default plugins
1100
+            $instance->registerPlugin(['shareType' => 'SHARE_TYPE_USER', 'class' => UserPlugin::class]);
1101
+            $instance->registerPlugin(['shareType' => 'SHARE_TYPE_GROUP', 'class' => GroupPlugin::class]);
1102
+            $instance->registerPlugin(['shareType' => 'SHARE_TYPE_EMAIL', 'class' => MailPlugin::class]);
1103
+            $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE', 'class' => RemotePlugin::class]);
1104
+            $instance->registerPlugin(['shareType' => 'SHARE_TYPE_REMOTE_GROUP', 'class' => RemoteGroupPlugin::class]);
1105
+
1106
+            return $instance;
1107
+        });
1108
+        $this->registerAlias(\OCP\Collaboration\Collaborators\ISearchResult::class, \OC\Collaboration\Collaborators\SearchResult::class);
1109
+
1110
+        $this->registerAlias(\OCP\Collaboration\AutoComplete\IManager::class, \OC\Collaboration\AutoComplete\Manager::class);
1111
+
1112
+        $this->registerAlias(\OCP\Collaboration\Resources\IProviderManager::class, \OC\Collaboration\Resources\ProviderManager::class);
1113
+        $this->registerAlias(\OCP\Collaboration\Resources\IManager::class, \OC\Collaboration\Resources\Manager::class);
1114
+
1115
+        $this->registerAlias(IReferenceManager::class, ReferenceManager::class);
1116
+        $this->registerAlias(ITeamManager::class, TeamManager::class);
1117
+
1118
+        $this->registerDeprecatedAlias('SettingsManager', \OC\Settings\Manager::class);
1119
+        $this->registerAlias(\OCP\Settings\IManager::class, \OC\Settings\Manager::class);
1120
+        $this->registerService(\OC\Files\AppData\Factory::class, function (ContainerInterface $c) {
1121
+            return new \OC\Files\AppData\Factory(
1122
+                $c->get(IRootFolder::class),
1123
+                $c->get(SystemConfig::class)
1124
+            );
1125
+        });
1126
+
1127
+        $this->registerService('LockdownManager', function (ContainerInterface $c) {
1128
+            return new LockdownManager(function () use ($c) {
1129
+                return $c->get(ISession::class);
1130
+            });
1131
+        });
1132
+
1133
+        $this->registerService(\OCP\OCS\IDiscoveryService::class, function (ContainerInterface $c) {
1134
+            return new DiscoveryService(
1135
+                $c->get(ICacheFactory::class),
1136
+                $c->get(IClientService::class)
1137
+            );
1138
+        });
1139
+        $this->registerAlias(IOCMDiscoveryService::class, OCMDiscoveryService::class);
1140
+
1141
+        $this->registerService(ICloudIdManager::class, function (ContainerInterface $c) {
1142
+            return new CloudIdManager(
1143
+                $c->get(ICacheFactory::class),
1144
+                $c->get(IEventDispatcher::class),
1145
+                $c->get(\OCP\Contacts\IManager::class),
1146
+                $c->get(IURLGenerator::class),
1147
+                $c->get(IUserManager::class),
1148
+            );
1149
+        });
1150 1150
 
1151
-		$this->registerAlias(\OCP\GlobalScale\IConfig::class, \OC\GlobalScale\Config::class);
1152
-		$this->registerAlias(ICloudFederationProviderManager::class, CloudFederationProviderManager::class);
1153
-		$this->registerService(ICloudFederationFactory::class, function (Server $c) {
1154
-			return new CloudFederationFactory();
1155
-		});
1151
+        $this->registerAlias(\OCP\GlobalScale\IConfig::class, \OC\GlobalScale\Config::class);
1152
+        $this->registerAlias(ICloudFederationProviderManager::class, CloudFederationProviderManager::class);
1153
+        $this->registerService(ICloudFederationFactory::class, function (Server $c) {
1154
+            return new CloudFederationFactory();
1155
+        });
1156 1156
 
1157
-		$this->registerAlias(\OCP\AppFramework\Utility\IControllerMethodReflector::class, \OC\AppFramework\Utility\ControllerMethodReflector::class);
1157
+        $this->registerAlias(\OCP\AppFramework\Utility\IControllerMethodReflector::class, \OC\AppFramework\Utility\ControllerMethodReflector::class);
1158 1158
 
1159
-		$this->registerAlias(\OCP\AppFramework\Utility\ITimeFactory::class, \OC\AppFramework\Utility\TimeFactory::class);
1160
-		$this->registerAlias(\Psr\Clock\ClockInterface::class, \OCP\AppFramework\Utility\ITimeFactory::class);
1159
+        $this->registerAlias(\OCP\AppFramework\Utility\ITimeFactory::class, \OC\AppFramework\Utility\TimeFactory::class);
1160
+        $this->registerAlias(\Psr\Clock\ClockInterface::class, \OCP\AppFramework\Utility\ITimeFactory::class);
1161 1161
 
1162
-		$this->registerService(Defaults::class, function (Server $c) {
1163
-			return new Defaults(
1164
-				$c->get('ThemingDefaults')
1165
-			);
1166
-		});
1162
+        $this->registerService(Defaults::class, function (Server $c) {
1163
+            return new Defaults(
1164
+                $c->get('ThemingDefaults')
1165
+            );
1166
+        });
1167 1167
 
1168
-		$this->registerService(\OCP\ISession::class, function (ContainerInterface $c) {
1169
-			return $c->get(\OCP\IUserSession::class)->getSession();
1170
-		}, false);
1168
+        $this->registerService(\OCP\ISession::class, function (ContainerInterface $c) {
1169
+            return $c->get(\OCP\IUserSession::class)->getSession();
1170
+        }, false);
1171 1171
 
1172
-		$this->registerService(IShareHelper::class, function (ContainerInterface $c) {
1173
-			return new ShareHelper(
1174
-				$c->get(\OCP\Share\IManager::class)
1175
-			);
1176
-		});
1172
+        $this->registerService(IShareHelper::class, function (ContainerInterface $c) {
1173
+            return new ShareHelper(
1174
+                $c->get(\OCP\Share\IManager::class)
1175
+            );
1176
+        });
1177 1177
 
1178
-		$this->registerService(IApiFactory::class, function (ContainerInterface $c) {
1179
-			return new ApiFactory($c->get(IClientService::class));
1180
-		});
1178
+        $this->registerService(IApiFactory::class, function (ContainerInterface $c) {
1179
+            return new ApiFactory($c->get(IClientService::class));
1180
+        });
1181 1181
 
1182
-		$this->registerService(IInstanceFactory::class, function (ContainerInterface $c) {
1183
-			$memcacheFactory = $c->get(ICacheFactory::class);
1184
-			return new InstanceFactory($memcacheFactory->createLocal('remoteinstance.'), $c->get(IClientService::class));
1185
-		});
1182
+        $this->registerService(IInstanceFactory::class, function (ContainerInterface $c) {
1183
+            $memcacheFactory = $c->get(ICacheFactory::class);
1184
+            return new InstanceFactory($memcacheFactory->createLocal('remoteinstance.'), $c->get(IClientService::class));
1185
+        });
1186 1186
 
1187
-		$this->registerAlias(IContactsStore::class, ContactsStore::class);
1188
-		$this->registerAlias(IAccountManager::class, AccountManager::class);
1187
+        $this->registerAlias(IContactsStore::class, ContactsStore::class);
1188
+        $this->registerAlias(IAccountManager::class, AccountManager::class);
1189 1189
 
1190
-		$this->registerAlias(IStorageFactory::class, StorageFactory::class);
1190
+        $this->registerAlias(IStorageFactory::class, StorageFactory::class);
1191 1191
 
1192
-		$this->registerAlias(\OCP\Dashboard\IManager::class, \OC\Dashboard\Manager::class);
1192
+        $this->registerAlias(\OCP\Dashboard\IManager::class, \OC\Dashboard\Manager::class);
1193 1193
 
1194
-		$this->registerAlias(IFullTextSearchManager::class, FullTextSearchManager::class);
1195
-		$this->registerAlias(IFilesMetadataManager::class, FilesMetadataManager::class);
1194
+        $this->registerAlias(IFullTextSearchManager::class, FullTextSearchManager::class);
1195
+        $this->registerAlias(IFilesMetadataManager::class, FilesMetadataManager::class);
1196 1196
 
1197
-		$this->registerAlias(ISubAdmin::class, SubAdmin::class);
1197
+        $this->registerAlias(ISubAdmin::class, SubAdmin::class);
1198 1198
 
1199
-		$this->registerAlias(IInitialStateService::class, InitialStateService::class);
1199
+        $this->registerAlias(IInitialStateService::class, InitialStateService::class);
1200 1200
 
1201
-		$this->registerAlias(\OCP\IEmojiHelper::class, \OC\EmojiHelper::class);
1201
+        $this->registerAlias(\OCP\IEmojiHelper::class, \OC\EmojiHelper::class);
1202 1202
 
1203
-		$this->registerAlias(\OCP\UserStatus\IManager::class, \OC\UserStatus\Manager::class);
1203
+        $this->registerAlias(\OCP\UserStatus\IManager::class, \OC\UserStatus\Manager::class);
1204 1204
 
1205
-		$this->registerAlias(IBroker::class, Broker::class);
1205
+        $this->registerAlias(IBroker::class, Broker::class);
1206 1206
 
1207
-		$this->registerAlias(\OCP\Files\AppData\IAppDataFactory::class, \OC\Files\AppData\Factory::class);
1207
+        $this->registerAlias(\OCP\Files\AppData\IAppDataFactory::class, \OC\Files\AppData\Factory::class);
1208 1208
 
1209
-		$this->registerAlias(\OCP\Files\IFilenameValidator::class, \OC\Files\FilenameValidator::class);
1209
+        $this->registerAlias(\OCP\Files\IFilenameValidator::class, \OC\Files\FilenameValidator::class);
1210 1210
 
1211
-		$this->registerAlias(IBinaryFinder::class, BinaryFinder::class);
1211
+        $this->registerAlias(IBinaryFinder::class, BinaryFinder::class);
1212 1212
 
1213
-		$this->registerAlias(\OCP\Share\IPublicShareTemplateFactory::class, \OC\Share20\PublicShareTemplateFactory::class);
1213
+        $this->registerAlias(\OCP\Share\IPublicShareTemplateFactory::class, \OC\Share20\PublicShareTemplateFactory::class);
1214 1214
 
1215
-		$this->registerAlias(ITranslationManager::class, TranslationManager::class);
1215
+        $this->registerAlias(ITranslationManager::class, TranslationManager::class);
1216 1216
 
1217
-		$this->registerAlias(IConversionManager::class, ConversionManager::class);
1217
+        $this->registerAlias(IConversionManager::class, ConversionManager::class);
1218 1218
 
1219
-		$this->registerAlias(ISpeechToTextManager::class, SpeechToTextManager::class);
1219
+        $this->registerAlias(ISpeechToTextManager::class, SpeechToTextManager::class);
1220 1220
 
1221
-		$this->registerAlias(IEventSourceFactory::class, EventSourceFactory::class);
1221
+        $this->registerAlias(IEventSourceFactory::class, EventSourceFactory::class);
1222 1222
 
1223
-		$this->registerAlias(\OCP\TextProcessing\IManager::class, \OC\TextProcessing\Manager::class);
1223
+        $this->registerAlias(\OCP\TextProcessing\IManager::class, \OC\TextProcessing\Manager::class);
1224 1224
 
1225
-		$this->registerAlias(\OCP\TextToImage\IManager::class, \OC\TextToImage\Manager::class);
1225
+        $this->registerAlias(\OCP\TextToImage\IManager::class, \OC\TextToImage\Manager::class);
1226 1226
 
1227
-		$this->registerAlias(ILimiter::class, Limiter::class);
1227
+        $this->registerAlias(ILimiter::class, Limiter::class);
1228 1228
 
1229
-		$this->registerAlias(IPhoneNumberUtil::class, PhoneNumberUtil::class);
1229
+        $this->registerAlias(IPhoneNumberUtil::class, PhoneNumberUtil::class);
1230 1230
 
1231
-		// there is no reason for having OCMProvider as a Service
1232
-		$this->registerDeprecatedAlias(ICapabilityAwareOCMProvider::class, OCMProvider::class);
1233
-		$this->registerDeprecatedAlias(IOCMProvider::class, OCMProvider::class);
1231
+        // there is no reason for having OCMProvider as a Service
1232
+        $this->registerDeprecatedAlias(ICapabilityAwareOCMProvider::class, OCMProvider::class);
1233
+        $this->registerDeprecatedAlias(IOCMProvider::class, OCMProvider::class);
1234 1234
 
1235
-		$this->registerAlias(ISetupCheckManager::class, SetupCheckManager::class);
1235
+        $this->registerAlias(ISetupCheckManager::class, SetupCheckManager::class);
1236 1236
 
1237
-		$this->registerAlias(IProfileManager::class, ProfileManager::class);
1237
+        $this->registerAlias(IProfileManager::class, ProfileManager::class);
1238 1238
 
1239
-		$this->registerAlias(IAvailabilityCoordinator::class, AvailabilityCoordinator::class);
1239
+        $this->registerAlias(IAvailabilityCoordinator::class, AvailabilityCoordinator::class);
1240 1240
 
1241
-		$this->registerAlias(IDeclarativeManager::class, DeclarativeManager::class);
1241
+        $this->registerAlias(IDeclarativeManager::class, DeclarativeManager::class);
1242 1242
 
1243
-		$this->registerAlias(\OCP\TaskProcessing\IManager::class, \OC\TaskProcessing\Manager::class);
1243
+        $this->registerAlias(\OCP\TaskProcessing\IManager::class, \OC\TaskProcessing\Manager::class);
1244 1244
 
1245
-		$this->registerAlias(IRemoteAddress::class, RemoteAddress::class);
1245
+        $this->registerAlias(IRemoteAddress::class, RemoteAddress::class);
1246 1246
 
1247
-		$this->registerAlias(\OCP\Security\Ip\IFactory::class, \OC\Security\Ip\Factory::class);
1247
+        $this->registerAlias(\OCP\Security\Ip\IFactory::class, \OC\Security\Ip\Factory::class);
1248 1248
 
1249
-		$this->registerAlias(IRichTextFormatter::class, \OC\RichObjectStrings\RichTextFormatter::class);
1249
+        $this->registerAlias(IRichTextFormatter::class, \OC\RichObjectStrings\RichTextFormatter::class);
1250 1250
 
1251
-		$this->registerAlias(ISignatureManager::class, SignatureManager::class);
1251
+        $this->registerAlias(ISignatureManager::class, SignatureManager::class);
1252 1252
 
1253
-		$this->connectDispatcher();
1254
-	}
1253
+        $this->connectDispatcher();
1254
+    }
1255 1255
 
1256
-	public function boot() {
1257
-		/** @var HookConnector $hookConnector */
1258
-		$hookConnector = $this->get(HookConnector::class);
1259
-		$hookConnector->viewToNode();
1260
-	}
1261
-
1262
-	private function connectDispatcher(): void {
1263
-		/** @var IEventDispatcher $eventDispatcher */
1264
-		$eventDispatcher = $this->get(IEventDispatcher::class);
1265
-		$eventDispatcher->addServiceListener(LoginFailed::class, LoginFailedListener::class);
1266
-		$eventDispatcher->addServiceListener(PostLoginEvent::class, UserLoggedInListener::class);
1267
-		$eventDispatcher->addServiceListener(UserChangedEvent::class, UserChangedListener::class);
1268
-		$eventDispatcher->addServiceListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class);
1269
-
1270
-		FilesMetadataManager::loadListeners($eventDispatcher);
1271
-		GenerateBlurhashMetadata::loadListeners($eventDispatcher);
1272
-	}
1273
-
1274
-	/**
1275
-	 * @return \OCP\Contacts\IManager
1276
-	 * @deprecated 20.0.0
1277
-	 */
1278
-	public function getContactsManager() {
1279
-		return $this->get(\OCP\Contacts\IManager::class);
1280
-	}
1281
-
1282
-	/**
1283
-	 * @return \OC\Encryption\Manager
1284
-	 * @deprecated 20.0.0
1285
-	 */
1286
-	public function getEncryptionManager() {
1287
-		return $this->get(\OCP\Encryption\IManager::class);
1288
-	}
1289
-
1290
-	/**
1291
-	 * @return \OC\Encryption\File
1292
-	 * @deprecated 20.0.0
1293
-	 */
1294
-	public function getEncryptionFilesHelper() {
1295
-		return $this->get(IFile::class);
1296
-	}
1297
-
1298
-	/**
1299
-	 * The current request object holding all information about the request
1300
-	 * currently being processed is returned from this method.
1301
-	 * In case the current execution was not initiated by a web request null is returned
1302
-	 *
1303
-	 * @return \OCP\IRequest
1304
-	 * @deprecated 20.0.0
1305
-	 */
1306
-	public function getRequest() {
1307
-		return $this->get(IRequest::class);
1308
-	}
1309
-
1310
-	/**
1311
-	 * Returns the root folder of ownCloud's data directory
1312
-	 *
1313
-	 * @return IRootFolder
1314
-	 * @deprecated 20.0.0
1315
-	 */
1316
-	public function getRootFolder() {
1317
-		return $this->get(IRootFolder::class);
1318
-	}
1319
-
1320
-	/**
1321
-	 * Returns the root folder of ownCloud's data directory
1322
-	 * This is the lazy variant so this gets only initialized once it
1323
-	 * is actually used.
1324
-	 *
1325
-	 * @return IRootFolder
1326
-	 * @deprecated 20.0.0
1327
-	 */
1328
-	public function getLazyRootFolder() {
1329
-		return $this->get(IRootFolder::class);
1330
-	}
1331
-
1332
-	/**
1333
-	 * Returns a view to ownCloud's files folder
1334
-	 *
1335
-	 * @param string $userId user ID
1336
-	 * @return \OCP\Files\Folder|null
1337
-	 * @deprecated 20.0.0
1338
-	 */
1339
-	public function getUserFolder($userId = null) {
1340
-		if ($userId === null) {
1341
-			$user = $this->get(IUserSession::class)->getUser();
1342
-			if (!$user) {
1343
-				return null;
1344
-			}
1345
-			$userId = $user->getUID();
1346
-		}
1347
-		$root = $this->get(IRootFolder::class);
1348
-		return $root->getUserFolder($userId);
1349
-	}
1350
-
1351
-	/**
1352
-	 * @return \OC\User\Manager
1353
-	 * @deprecated 20.0.0
1354
-	 */
1355
-	public function getUserManager() {
1356
-		return $this->get(IUserManager::class);
1357
-	}
1358
-
1359
-	/**
1360
-	 * @return \OC\Group\Manager
1361
-	 * @deprecated 20.0.0
1362
-	 */
1363
-	public function getGroupManager() {
1364
-		return $this->get(IGroupManager::class);
1365
-	}
1366
-
1367
-	/**
1368
-	 * @return \OC\User\Session
1369
-	 * @deprecated 20.0.0
1370
-	 */
1371
-	public function getUserSession() {
1372
-		return $this->get(IUserSession::class);
1373
-	}
1374
-
1375
-	/**
1376
-	 * @return \OCP\ISession
1377
-	 * @deprecated 20.0.0
1378
-	 */
1379
-	public function getSession() {
1380
-		return $this->get(Session::class)->getSession();
1381
-	}
1382
-
1383
-	/**
1384
-	 * @param \OCP\ISession $session
1385
-	 * @return void
1386
-	 */
1387
-	public function setSession(\OCP\ISession $session) {
1388
-		$this->get(SessionStorage::class)->setSession($session);
1389
-		$this->get(Session::class)->setSession($session);
1390
-		$this->get(Store::class)->setSession($session);
1391
-	}
1392
-
1393
-	/**
1394
-	 * @return \OCP\IConfig
1395
-	 * @deprecated 20.0.0
1396
-	 */
1397
-	public function getConfig() {
1398
-		return $this->get(AllConfig::class);
1399
-	}
1400
-
1401
-	/**
1402
-	 * @return \OC\SystemConfig
1403
-	 * @deprecated 20.0.0
1404
-	 */
1405
-	public function getSystemConfig() {
1406
-		return $this->get(SystemConfig::class);
1407
-	}
1408
-
1409
-	/**
1410
-	 * @return IFactory
1411
-	 * @deprecated 20.0.0
1412
-	 */
1413
-	public function getL10NFactory() {
1414
-		return $this->get(IFactory::class);
1415
-	}
1416
-
1417
-	/**
1418
-	 * get an L10N instance
1419
-	 *
1420
-	 * @param string $app appid
1421
-	 * @param string $lang
1422
-	 * @return IL10N
1423
-	 * @deprecated 20.0.0 use DI of {@see IL10N} or {@see IFactory} instead, or {@see \OCP\Util::getL10N()} as a last resort
1424
-	 */
1425
-	public function getL10N($app, $lang = null) {
1426
-		return $this->get(IFactory::class)->get($app, $lang);
1427
-	}
1428
-
1429
-	/**
1430
-	 * @return IURLGenerator
1431
-	 * @deprecated 20.0.0
1432
-	 */
1433
-	public function getURLGenerator() {
1434
-		return $this->get(IURLGenerator::class);
1435
-	}
1436
-
1437
-	/**
1438
-	 * Returns an ICache instance. Since 8.1.0 it returns a fake cache. Use
1439
-	 * getMemCacheFactory() instead.
1440
-	 *
1441
-	 * @return ICache
1442
-	 * @deprecated 8.1.0 use getMemCacheFactory to obtain a proper cache
1443
-	 */
1444
-	public function getCache() {
1445
-		return $this->get(ICache::class);
1446
-	}
1447
-
1448
-	/**
1449
-	 * Returns an \OCP\CacheFactory instance
1450
-	 *
1451
-	 * @return \OCP\ICacheFactory
1452
-	 * @deprecated 20.0.0
1453
-	 */
1454
-	public function getMemCacheFactory() {
1455
-		return $this->get(ICacheFactory::class);
1456
-	}
1457
-
1458
-	/**
1459
-	 * Returns the current session
1460
-	 *
1461
-	 * @return \OCP\IDBConnection
1462
-	 * @deprecated 20.0.0
1463
-	 */
1464
-	public function getDatabaseConnection() {
1465
-		return $this->get(IDBConnection::class);
1466
-	}
1467
-
1468
-	/**
1469
-	 * Returns the activity manager
1470
-	 *
1471
-	 * @return \OCP\Activity\IManager
1472
-	 * @deprecated 20.0.0
1473
-	 */
1474
-	public function getActivityManager() {
1475
-		return $this->get(\OCP\Activity\IManager::class);
1476
-	}
1477
-
1478
-	/**
1479
-	 * Returns an job list for controlling background jobs
1480
-	 *
1481
-	 * @return IJobList
1482
-	 * @deprecated 20.0.0
1483
-	 */
1484
-	public function getJobList() {
1485
-		return $this->get(IJobList::class);
1486
-	}
1487
-
1488
-	/**
1489
-	 * Returns a SecureRandom instance
1490
-	 *
1491
-	 * @return \OCP\Security\ISecureRandom
1492
-	 * @deprecated 20.0.0
1493
-	 */
1494
-	public function getSecureRandom() {
1495
-		return $this->get(ISecureRandom::class);
1496
-	}
1497
-
1498
-	/**
1499
-	 * Returns a Crypto instance
1500
-	 *
1501
-	 * @return ICrypto
1502
-	 * @deprecated 20.0.0
1503
-	 */
1504
-	public function getCrypto() {
1505
-		return $this->get(ICrypto::class);
1506
-	}
1507
-
1508
-	/**
1509
-	 * Returns a Hasher instance
1510
-	 *
1511
-	 * @return IHasher
1512
-	 * @deprecated 20.0.0
1513
-	 */
1514
-	public function getHasher() {
1515
-		return $this->get(IHasher::class);
1516
-	}
1517
-
1518
-	/**
1519
-	 * Get the certificate manager
1520
-	 *
1521
-	 * @return \OCP\ICertificateManager
1522
-	 */
1523
-	public function getCertificateManager() {
1524
-		return $this->get(ICertificateManager::class);
1525
-	}
1526
-
1527
-	/**
1528
-	 * Get the manager for temporary files and folders
1529
-	 *
1530
-	 * @return \OCP\ITempManager
1531
-	 * @deprecated 20.0.0
1532
-	 */
1533
-	public function getTempManager() {
1534
-		return $this->get(ITempManager::class);
1535
-	}
1536
-
1537
-	/**
1538
-	 * Get the app manager
1539
-	 *
1540
-	 * @return \OCP\App\IAppManager
1541
-	 * @deprecated 20.0.0
1542
-	 */
1543
-	public function getAppManager() {
1544
-		return $this->get(IAppManager::class);
1545
-	}
1546
-
1547
-	/**
1548
-	 * Creates a new mailer
1549
-	 *
1550
-	 * @return IMailer
1551
-	 * @deprecated 20.0.0
1552
-	 */
1553
-	public function getMailer() {
1554
-		return $this->get(IMailer::class);
1555
-	}
1556
-
1557
-	/**
1558
-	 * Get the webroot
1559
-	 *
1560
-	 * @return string
1561
-	 * @deprecated 20.0.0
1562
-	 */
1563
-	public function getWebRoot() {
1564
-		return $this->webRoot;
1565
-	}
1566
-
1567
-	/**
1568
-	 * Get the locking provider
1569
-	 *
1570
-	 * @return ILockingProvider
1571
-	 * @since 8.1.0
1572
-	 * @deprecated 20.0.0
1573
-	 */
1574
-	public function getLockingProvider() {
1575
-		return $this->get(ILockingProvider::class);
1576
-	}
1577
-
1578
-	/**
1579
-	 * Get the MimeTypeDetector
1580
-	 *
1581
-	 * @return IMimeTypeDetector
1582
-	 * @deprecated 20.0.0
1583
-	 */
1584
-	public function getMimeTypeDetector() {
1585
-		return $this->get(IMimeTypeDetector::class);
1586
-	}
1587
-
1588
-	/**
1589
-	 * Get the MimeTypeLoader
1590
-	 *
1591
-	 * @return IMimeTypeLoader
1592
-	 * @deprecated 20.0.0
1593
-	 */
1594
-	public function getMimeTypeLoader() {
1595
-		return $this->get(IMimeTypeLoader::class);
1596
-	}
1597
-
1598
-	/**
1599
-	 * Get the Notification Manager
1600
-	 *
1601
-	 * @return \OCP\Notification\IManager
1602
-	 * @since 8.2.0
1603
-	 * @deprecated 20.0.0
1604
-	 */
1605
-	public function getNotificationManager() {
1606
-		return $this->get(\OCP\Notification\IManager::class);
1607
-	}
1608
-
1609
-	/**
1610
-	 * @return \OCA\Theming\ThemingDefaults
1611
-	 * @deprecated 20.0.0
1612
-	 */
1613
-	public function getThemingDefaults() {
1614
-		return $this->get('ThemingDefaults');
1615
-	}
1616
-
1617
-	/**
1618
-	 * @return \OC\IntegrityCheck\Checker
1619
-	 * @deprecated 20.0.0
1620
-	 */
1621
-	public function getIntegrityCodeChecker() {
1622
-		return $this->get('IntegrityCodeChecker');
1623
-	}
1624
-
1625
-	/**
1626
-	 * @return CsrfTokenManager
1627
-	 * @deprecated 20.0.0
1628
-	 */
1629
-	public function getCsrfTokenManager() {
1630
-		return $this->get(CsrfTokenManager::class);
1631
-	}
1632
-
1633
-	/**
1634
-	 * @return ContentSecurityPolicyNonceManager
1635
-	 * @deprecated 20.0.0
1636
-	 */
1637
-	public function getContentSecurityPolicyNonceManager() {
1638
-		return $this->get(ContentSecurityPolicyNonceManager::class);
1639
-	}
1640
-
1641
-	/**
1642
-	 * @return \OCP\Settings\IManager
1643
-	 * @deprecated 20.0.0
1644
-	 */
1645
-	public function getSettingsManager() {
1646
-		return $this->get(\OC\Settings\Manager::class);
1647
-	}
1648
-
1649
-	/**
1650
-	 * @return \OCP\Files\IAppData
1651
-	 * @deprecated 20.0.0 Use get(\OCP\Files\AppData\IAppDataFactory::class)->get($app) instead
1652
-	 */
1653
-	public function getAppDataDir($app) {
1654
-		$factory = $this->get(\OC\Files\AppData\Factory::class);
1655
-		return $factory->get($app);
1656
-	}
1657
-
1658
-	/**
1659
-	 * @return \OCP\Federation\ICloudIdManager
1660
-	 * @deprecated 20.0.0
1661
-	 */
1662
-	public function getCloudIdManager() {
1663
-		return $this->get(ICloudIdManager::class);
1664
-	}
1256
+    public function boot() {
1257
+        /** @var HookConnector $hookConnector */
1258
+        $hookConnector = $this->get(HookConnector::class);
1259
+        $hookConnector->viewToNode();
1260
+    }
1261
+
1262
+    private function connectDispatcher(): void {
1263
+        /** @var IEventDispatcher $eventDispatcher */
1264
+        $eventDispatcher = $this->get(IEventDispatcher::class);
1265
+        $eventDispatcher->addServiceListener(LoginFailed::class, LoginFailedListener::class);
1266
+        $eventDispatcher->addServiceListener(PostLoginEvent::class, UserLoggedInListener::class);
1267
+        $eventDispatcher->addServiceListener(UserChangedEvent::class, UserChangedListener::class);
1268
+        $eventDispatcher->addServiceListener(BeforeUserDeletedEvent::class, BeforeUserDeletedListener::class);
1269
+
1270
+        FilesMetadataManager::loadListeners($eventDispatcher);
1271
+        GenerateBlurhashMetadata::loadListeners($eventDispatcher);
1272
+    }
1273
+
1274
+    /**
1275
+     * @return \OCP\Contacts\IManager
1276
+     * @deprecated 20.0.0
1277
+     */
1278
+    public function getContactsManager() {
1279
+        return $this->get(\OCP\Contacts\IManager::class);
1280
+    }
1281
+
1282
+    /**
1283
+     * @return \OC\Encryption\Manager
1284
+     * @deprecated 20.0.0
1285
+     */
1286
+    public function getEncryptionManager() {
1287
+        return $this->get(\OCP\Encryption\IManager::class);
1288
+    }
1289
+
1290
+    /**
1291
+     * @return \OC\Encryption\File
1292
+     * @deprecated 20.0.0
1293
+     */
1294
+    public function getEncryptionFilesHelper() {
1295
+        return $this->get(IFile::class);
1296
+    }
1297
+
1298
+    /**
1299
+     * The current request object holding all information about the request
1300
+     * currently being processed is returned from this method.
1301
+     * In case the current execution was not initiated by a web request null is returned
1302
+     *
1303
+     * @return \OCP\IRequest
1304
+     * @deprecated 20.0.0
1305
+     */
1306
+    public function getRequest() {
1307
+        return $this->get(IRequest::class);
1308
+    }
1309
+
1310
+    /**
1311
+     * Returns the root folder of ownCloud's data directory
1312
+     *
1313
+     * @return IRootFolder
1314
+     * @deprecated 20.0.0
1315
+     */
1316
+    public function getRootFolder() {
1317
+        return $this->get(IRootFolder::class);
1318
+    }
1319
+
1320
+    /**
1321
+     * Returns the root folder of ownCloud's data directory
1322
+     * This is the lazy variant so this gets only initialized once it
1323
+     * is actually used.
1324
+     *
1325
+     * @return IRootFolder
1326
+     * @deprecated 20.0.0
1327
+     */
1328
+    public function getLazyRootFolder() {
1329
+        return $this->get(IRootFolder::class);
1330
+    }
1331
+
1332
+    /**
1333
+     * Returns a view to ownCloud's files folder
1334
+     *
1335
+     * @param string $userId user ID
1336
+     * @return \OCP\Files\Folder|null
1337
+     * @deprecated 20.0.0
1338
+     */
1339
+    public function getUserFolder($userId = null) {
1340
+        if ($userId === null) {
1341
+            $user = $this->get(IUserSession::class)->getUser();
1342
+            if (!$user) {
1343
+                return null;
1344
+            }
1345
+            $userId = $user->getUID();
1346
+        }
1347
+        $root = $this->get(IRootFolder::class);
1348
+        return $root->getUserFolder($userId);
1349
+    }
1350
+
1351
+    /**
1352
+     * @return \OC\User\Manager
1353
+     * @deprecated 20.0.0
1354
+     */
1355
+    public function getUserManager() {
1356
+        return $this->get(IUserManager::class);
1357
+    }
1358
+
1359
+    /**
1360
+     * @return \OC\Group\Manager
1361
+     * @deprecated 20.0.0
1362
+     */
1363
+    public function getGroupManager() {
1364
+        return $this->get(IGroupManager::class);
1365
+    }
1366
+
1367
+    /**
1368
+     * @return \OC\User\Session
1369
+     * @deprecated 20.0.0
1370
+     */
1371
+    public function getUserSession() {
1372
+        return $this->get(IUserSession::class);
1373
+    }
1374
+
1375
+    /**
1376
+     * @return \OCP\ISession
1377
+     * @deprecated 20.0.0
1378
+     */
1379
+    public function getSession() {
1380
+        return $this->get(Session::class)->getSession();
1381
+    }
1382
+
1383
+    /**
1384
+     * @param \OCP\ISession $session
1385
+     * @return void
1386
+     */
1387
+    public function setSession(\OCP\ISession $session) {
1388
+        $this->get(SessionStorage::class)->setSession($session);
1389
+        $this->get(Session::class)->setSession($session);
1390
+        $this->get(Store::class)->setSession($session);
1391
+    }
1392
+
1393
+    /**
1394
+     * @return \OCP\IConfig
1395
+     * @deprecated 20.0.0
1396
+     */
1397
+    public function getConfig() {
1398
+        return $this->get(AllConfig::class);
1399
+    }
1400
+
1401
+    /**
1402
+     * @return \OC\SystemConfig
1403
+     * @deprecated 20.0.0
1404
+     */
1405
+    public function getSystemConfig() {
1406
+        return $this->get(SystemConfig::class);
1407
+    }
1408
+
1409
+    /**
1410
+     * @return IFactory
1411
+     * @deprecated 20.0.0
1412
+     */
1413
+    public function getL10NFactory() {
1414
+        return $this->get(IFactory::class);
1415
+    }
1416
+
1417
+    /**
1418
+     * get an L10N instance
1419
+     *
1420
+     * @param string $app appid
1421
+     * @param string $lang
1422
+     * @return IL10N
1423
+     * @deprecated 20.0.0 use DI of {@see IL10N} or {@see IFactory} instead, or {@see \OCP\Util::getL10N()} as a last resort
1424
+     */
1425
+    public function getL10N($app, $lang = null) {
1426
+        return $this->get(IFactory::class)->get($app, $lang);
1427
+    }
1428
+
1429
+    /**
1430
+     * @return IURLGenerator
1431
+     * @deprecated 20.0.0
1432
+     */
1433
+    public function getURLGenerator() {
1434
+        return $this->get(IURLGenerator::class);
1435
+    }
1436
+
1437
+    /**
1438
+     * Returns an ICache instance. Since 8.1.0 it returns a fake cache. Use
1439
+     * getMemCacheFactory() instead.
1440
+     *
1441
+     * @return ICache
1442
+     * @deprecated 8.1.0 use getMemCacheFactory to obtain a proper cache
1443
+     */
1444
+    public function getCache() {
1445
+        return $this->get(ICache::class);
1446
+    }
1447
+
1448
+    /**
1449
+     * Returns an \OCP\CacheFactory instance
1450
+     *
1451
+     * @return \OCP\ICacheFactory
1452
+     * @deprecated 20.0.0
1453
+     */
1454
+    public function getMemCacheFactory() {
1455
+        return $this->get(ICacheFactory::class);
1456
+    }
1457
+
1458
+    /**
1459
+     * Returns the current session
1460
+     *
1461
+     * @return \OCP\IDBConnection
1462
+     * @deprecated 20.0.0
1463
+     */
1464
+    public function getDatabaseConnection() {
1465
+        return $this->get(IDBConnection::class);
1466
+    }
1467
+
1468
+    /**
1469
+     * Returns the activity manager
1470
+     *
1471
+     * @return \OCP\Activity\IManager
1472
+     * @deprecated 20.0.0
1473
+     */
1474
+    public function getActivityManager() {
1475
+        return $this->get(\OCP\Activity\IManager::class);
1476
+    }
1477
+
1478
+    /**
1479
+     * Returns an job list for controlling background jobs
1480
+     *
1481
+     * @return IJobList
1482
+     * @deprecated 20.0.0
1483
+     */
1484
+    public function getJobList() {
1485
+        return $this->get(IJobList::class);
1486
+    }
1487
+
1488
+    /**
1489
+     * Returns a SecureRandom instance
1490
+     *
1491
+     * @return \OCP\Security\ISecureRandom
1492
+     * @deprecated 20.0.0
1493
+     */
1494
+    public function getSecureRandom() {
1495
+        return $this->get(ISecureRandom::class);
1496
+    }
1497
+
1498
+    /**
1499
+     * Returns a Crypto instance
1500
+     *
1501
+     * @return ICrypto
1502
+     * @deprecated 20.0.0
1503
+     */
1504
+    public function getCrypto() {
1505
+        return $this->get(ICrypto::class);
1506
+    }
1507
+
1508
+    /**
1509
+     * Returns a Hasher instance
1510
+     *
1511
+     * @return IHasher
1512
+     * @deprecated 20.0.0
1513
+     */
1514
+    public function getHasher() {
1515
+        return $this->get(IHasher::class);
1516
+    }
1517
+
1518
+    /**
1519
+     * Get the certificate manager
1520
+     *
1521
+     * @return \OCP\ICertificateManager
1522
+     */
1523
+    public function getCertificateManager() {
1524
+        return $this->get(ICertificateManager::class);
1525
+    }
1526
+
1527
+    /**
1528
+     * Get the manager for temporary files and folders
1529
+     *
1530
+     * @return \OCP\ITempManager
1531
+     * @deprecated 20.0.0
1532
+     */
1533
+    public function getTempManager() {
1534
+        return $this->get(ITempManager::class);
1535
+    }
1536
+
1537
+    /**
1538
+     * Get the app manager
1539
+     *
1540
+     * @return \OCP\App\IAppManager
1541
+     * @deprecated 20.0.0
1542
+     */
1543
+    public function getAppManager() {
1544
+        return $this->get(IAppManager::class);
1545
+    }
1546
+
1547
+    /**
1548
+     * Creates a new mailer
1549
+     *
1550
+     * @return IMailer
1551
+     * @deprecated 20.0.0
1552
+     */
1553
+    public function getMailer() {
1554
+        return $this->get(IMailer::class);
1555
+    }
1556
+
1557
+    /**
1558
+     * Get the webroot
1559
+     *
1560
+     * @return string
1561
+     * @deprecated 20.0.0
1562
+     */
1563
+    public function getWebRoot() {
1564
+        return $this->webRoot;
1565
+    }
1566
+
1567
+    /**
1568
+     * Get the locking provider
1569
+     *
1570
+     * @return ILockingProvider
1571
+     * @since 8.1.0
1572
+     * @deprecated 20.0.0
1573
+     */
1574
+    public function getLockingProvider() {
1575
+        return $this->get(ILockingProvider::class);
1576
+    }
1577
+
1578
+    /**
1579
+     * Get the MimeTypeDetector
1580
+     *
1581
+     * @return IMimeTypeDetector
1582
+     * @deprecated 20.0.0
1583
+     */
1584
+    public function getMimeTypeDetector() {
1585
+        return $this->get(IMimeTypeDetector::class);
1586
+    }
1587
+
1588
+    /**
1589
+     * Get the MimeTypeLoader
1590
+     *
1591
+     * @return IMimeTypeLoader
1592
+     * @deprecated 20.0.0
1593
+     */
1594
+    public function getMimeTypeLoader() {
1595
+        return $this->get(IMimeTypeLoader::class);
1596
+    }
1597
+
1598
+    /**
1599
+     * Get the Notification Manager
1600
+     *
1601
+     * @return \OCP\Notification\IManager
1602
+     * @since 8.2.0
1603
+     * @deprecated 20.0.0
1604
+     */
1605
+    public function getNotificationManager() {
1606
+        return $this->get(\OCP\Notification\IManager::class);
1607
+    }
1608
+
1609
+    /**
1610
+     * @return \OCA\Theming\ThemingDefaults
1611
+     * @deprecated 20.0.0
1612
+     */
1613
+    public function getThemingDefaults() {
1614
+        return $this->get('ThemingDefaults');
1615
+    }
1616
+
1617
+    /**
1618
+     * @return \OC\IntegrityCheck\Checker
1619
+     * @deprecated 20.0.0
1620
+     */
1621
+    public function getIntegrityCodeChecker() {
1622
+        return $this->get('IntegrityCodeChecker');
1623
+    }
1624
+
1625
+    /**
1626
+     * @return CsrfTokenManager
1627
+     * @deprecated 20.0.0
1628
+     */
1629
+    public function getCsrfTokenManager() {
1630
+        return $this->get(CsrfTokenManager::class);
1631
+    }
1632
+
1633
+    /**
1634
+     * @return ContentSecurityPolicyNonceManager
1635
+     * @deprecated 20.0.0
1636
+     */
1637
+    public function getContentSecurityPolicyNonceManager() {
1638
+        return $this->get(ContentSecurityPolicyNonceManager::class);
1639
+    }
1640
+
1641
+    /**
1642
+     * @return \OCP\Settings\IManager
1643
+     * @deprecated 20.0.0
1644
+     */
1645
+    public function getSettingsManager() {
1646
+        return $this->get(\OC\Settings\Manager::class);
1647
+    }
1648
+
1649
+    /**
1650
+     * @return \OCP\Files\IAppData
1651
+     * @deprecated 20.0.0 Use get(\OCP\Files\AppData\IAppDataFactory::class)->get($app) instead
1652
+     */
1653
+    public function getAppDataDir($app) {
1654
+        $factory = $this->get(\OC\Files\AppData\Factory::class);
1655
+        return $factory->get($app);
1656
+    }
1657
+
1658
+    /**
1659
+     * @return \OCP\Federation\ICloudIdManager
1660
+     * @deprecated 20.0.0
1661
+     */
1662
+    public function getCloudIdManager() {
1663
+        return $this->get(ICloudIdManager::class);
1664
+    }
1665 1665
 }
Please login to merge, or discard this patch.
lib/private/Files/Node/Root.php 2 patches
Indentation   +467 added lines, -467 removed lines patch added patch discarded remove patch
@@ -54,471 +54,471 @@
 block discarded – undo
54 54
  * @package OC\Files\Node
55 55
  */
56 56
 class Root extends Folder implements IRootFolder {
57
-	private PublicEmitter $emitter;
58
-	private CappedMemoryCache $userFolderCache;
59
-	private ICache $pathByIdCache;
60
-	private bool $useDefaultHomeFoldersPermissions = true;
61
-
62
-	public function __construct(
63
-		private Manager $mountManager,
64
-		View $view,
65
-		private ?IUser $user,
66
-		private IUserMountCache $userMountCache,
67
-		private LoggerInterface $logger,
68
-		private IUserManager $userManager,
69
-		IEventDispatcher $eventDispatcher,
70
-		ICacheFactory $cacheFactory,
71
-		IAppConfig $appConfig,
72
-	) {
73
-		parent::__construct($this, $view, '');
74
-		$this->emitter = new PublicEmitter();
75
-		$this->userFolderCache = new CappedMemoryCache();
76
-		$eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
77
-			$this->userFolderCache = new CappedMemoryCache();
78
-		});
79
-		$this->pathByIdCache = $cacheFactory->createLocal('path-by-id');
80
-		$this->useDefaultHomeFoldersPermissions = count($appConfig->getValueArray(Application::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS)) === 0;
81
-	}
82
-
83
-	/**
84
-	 * Get the user for which the filesystem is setup
85
-	 *
86
-	 * @return \OC\User\User
87
-	 */
88
-	public function getUser() {
89
-		return $this->user;
90
-	}
91
-
92
-	/**
93
-	 * @param string $scope
94
-	 * @param string $method
95
-	 * @param callable $callback
96
-	 */
97
-	public function listen($scope, $method, callable $callback) {
98
-		$this->emitter->listen($scope, $method, $callback);
99
-	}
100
-
101
-	/**
102
-	 * @param string $scope optional
103
-	 * @param string $method optional
104
-	 * @param callable $callback optional
105
-	 */
106
-	public function removeListener($scope = null, $method = null, ?callable $callback = null) {
107
-		$this->emitter->removeListener($scope, $method, $callback);
108
-	}
109
-
110
-	/**
111
-	 * @param string $scope
112
-	 * @param string $method
113
-	 * @param Node[] $arguments
114
-	 */
115
-	public function emit($scope, $method, $arguments = []) {
116
-		$this->emitter->emit($scope, $method, $arguments);
117
-	}
118
-
119
-	/**
120
-	 * @param \OC\Files\Storage\Storage $storage
121
-	 * @param string $mountPoint
122
-	 * @param array $arguments
123
-	 */
124
-	public function mount($storage, $mountPoint, $arguments = []) {
125
-		$mount = new MountPoint($storage, $mountPoint, $arguments);
126
-		$this->mountManager->addMount($mount);
127
-	}
128
-
129
-	public function getMount(string $mountPoint): IMountPoint {
130
-		return $this->mountManager->find($mountPoint);
131
-	}
132
-
133
-	/**
134
-	 * @param string $mountPoint
135
-	 * @return \OC\Files\Mount\MountPoint[]
136
-	 */
137
-	public function getMountsIn(string $mountPoint): array {
138
-		return $this->mountManager->findIn($mountPoint);
139
-	}
140
-
141
-	/**
142
-	 * @param string $storageId
143
-	 * @return \OC\Files\Mount\MountPoint[]
144
-	 */
145
-	public function getMountByStorageId($storageId) {
146
-		return $this->mountManager->findByStorageId($storageId);
147
-	}
148
-
149
-	/**
150
-	 * @param int $numericId
151
-	 * @return MountPoint[]
152
-	 */
153
-	public function getMountByNumericStorageId($numericId) {
154
-		return $this->mountManager->findByNumericId($numericId);
155
-	}
156
-
157
-	/**
158
-	 * @param \OC\Files\Mount\MountPoint $mount
159
-	 */
160
-	public function unMount($mount) {
161
-		$this->mountManager->remove($mount);
162
-	}
163
-
164
-	public function get($path) {
165
-		$path = $this->normalizePath($path);
166
-		if ($this->isValidPath($path)) {
167
-			$fullPath = $this->getFullPath($path);
168
-			$fileInfo = $this->view->getFileInfo($fullPath, false);
169
-			if ($fileInfo) {
170
-				return $this->createNode($fullPath, $fileInfo, false);
171
-			} else {
172
-				throw new NotFoundException($path);
173
-			}
174
-		} else {
175
-			throw new NotPermittedException();
176
-		}
177
-	}
178
-
179
-	//most operations can't be done on the root
180
-
181
-	/**
182
-	 * @param string $targetPath
183
-	 * @return Node
184
-	 * @throws \OCP\Files\NotPermittedException
185
-	 */
186
-	public function rename($targetPath) {
187
-		throw new NotPermittedException();
188
-	}
189
-
190
-	public function delete() {
191
-		throw new NotPermittedException();
192
-	}
193
-
194
-	/**
195
-	 * @param string $targetPath
196
-	 * @return Node
197
-	 * @throws \OCP\Files\NotPermittedException
198
-	 */
199
-	public function copy($targetPath) {
200
-		throw new NotPermittedException();
201
-	}
202
-
203
-	/**
204
-	 * @param int $mtime
205
-	 * @throws \OCP\Files\NotPermittedException
206
-	 */
207
-	public function touch($mtime = null) {
208
-		throw new NotPermittedException();
209
-	}
210
-
211
-	/**
212
-	 * @return \OC\Files\Storage\Storage
213
-	 * @throws \OCP\Files\NotFoundException
214
-	 */
215
-	public function getStorage() {
216
-		throw new NotFoundException();
217
-	}
218
-
219
-	/**
220
-	 * @return string
221
-	 */
222
-	public function getPath() {
223
-		return '/';
224
-	}
225
-
226
-	/**
227
-	 * @return string
228
-	 */
229
-	public function getInternalPath() {
230
-		return '';
231
-	}
232
-
233
-	/**
234
-	 * @return int
235
-	 */
236
-	public function getId() {
237
-		return 0;
238
-	}
239
-
240
-	/**
241
-	 * @return array
242
-	 */
243
-	public function stat() {
244
-		return [];
245
-	}
246
-
247
-	/**
248
-	 * @return int
249
-	 */
250
-	public function getMTime() {
251
-		return 0;
252
-	}
253
-
254
-	/**
255
-	 * @param bool $includeMounts
256
-	 * @return int|float
257
-	 */
258
-	public function getSize($includeMounts = true): int|float {
259
-		return 0;
260
-	}
261
-
262
-	/**
263
-	 * @return string
264
-	 */
265
-	public function getEtag() {
266
-		return '';
267
-	}
268
-
269
-	/**
270
-	 * @return int
271
-	 */
272
-	public function getPermissions() {
273
-		return \OCP\Constants::PERMISSION_CREATE;
274
-	}
275
-
276
-	/**
277
-	 * @return bool
278
-	 */
279
-	public function isReadable() {
280
-		return false;
281
-	}
282
-
283
-	/**
284
-	 * @return bool
285
-	 */
286
-	public function isUpdateable() {
287
-		return false;
288
-	}
289
-
290
-	/**
291
-	 * @return bool
292
-	 */
293
-	public function isDeletable() {
294
-		return false;
295
-	}
296
-
297
-	/**
298
-	 * @return bool
299
-	 */
300
-	public function isShareable() {
301
-		return false;
302
-	}
303
-
304
-	/**
305
-	 * @throws \OCP\Files\NotFoundException
306
-	 */
307
-	public function getParent(): INode|IRootFolder {
308
-		throw new NotFoundException();
309
-	}
310
-
311
-	/**
312
-	 * @return string
313
-	 */
314
-	public function getName() {
315
-		return '';
316
-	}
317
-
318
-	/**
319
-	 * Returns a view to user's files folder
320
-	 *
321
-	 * @param string $userId user ID
322
-	 * @return \OCP\Files\Folder
323
-	 * @throws NoUserException
324
-	 * @throws NotPermittedException
325
-	 */
326
-	public function getUserFolder($userId) {
327
-		$userObject = $this->userManager->get($userId);
328
-
329
-		if (is_null($userObject)) {
330
-			$e = new NoUserException('Backends provided no user object');
331
-			$this->logger->error(
332
-				sprintf(
333
-					'Backends provided no user object for %s',
334
-					$userId
335
-				),
336
-				[
337
-					'app' => 'files',
338
-					'exception' => $e,
339
-				]
340
-			);
341
-			throw $e;
342
-		}
343
-
344
-		$userId = $userObject->getUID();
345
-
346
-		if (!$this->userFolderCache->hasKey($userId)) {
347
-			if ($this->mountManager->getSetupManager()->isSetupComplete($userObject)) {
348
-				try {
349
-					$folder = $this->get('/' . $userId . '/files');
350
-					if (!$folder instanceof \OCP\Files\Folder) {
351
-						throw new \Exception("Account folder for \"$userId\" exists as a file");
352
-					}
353
-				} catch (NotFoundException $e) {
354
-					if (!$this->nodeExists('/' . $userId)) {
355
-						$this->newFolder('/' . $userId);
356
-					}
357
-					$folder = $this->newFolder('/' . $userId . '/files');
358
-				}
359
-			} else {
360
-				$folder = new LazyUserFolder($this, $userObject, $this->mountManager, $this->useDefaultHomeFoldersPermissions);
361
-			}
362
-
363
-			$this->userFolderCache->set($userId, $folder);
364
-		}
365
-
366
-		return $this->userFolderCache->get($userId);
367
-	}
368
-
369
-	public function getUserMountCache() {
370
-		return $this->userMountCache;
371
-	}
372
-
373
-	public function getFirstNodeByIdInPath(int $id, string $path): ?INode {
374
-		// scope the cache by user, so we don't return nodes for different users
375
-		if ($this->user) {
376
-			$cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id);
377
-			if ($cachedPath && str_starts_with($cachedPath, $path)) {
378
-				// getting the node by path is significantly cheaper than finding it by id
379
-				try {
380
-					$node = $this->get($cachedPath);
381
-					// by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path
382
-					// if the cached path is invalid or a different file now we fall back to the uncached logic
383
-					if ($node && $node->getId() === $id) {
384
-						return $node;
385
-					}
386
-				} catch (NotFoundException|NotPermittedException) {
387
-					// The file may be moved but the old path still in cache
388
-				}
389
-			}
390
-		}
391
-		$node = current($this->getByIdInPath($id, $path));
392
-		if (!$node) {
393
-			return null;
394
-		}
395
-
396
-		if ($this->user) {
397
-			$this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath());
398
-		}
399
-		return $node;
400
-	}
401
-
402
-	/**
403
-	 * @param int $id
404
-	 * @return Node[]
405
-	 */
406
-	public function getByIdInPath(int $id, string $path): array {
407
-		$mountCache = $this->getUserMountCache();
408
-		if ($path !== '' && strpos($path, '/', 1) > 0) {
409
-			[, $user] = explode('/', $path);
410
-		} else {
411
-			$user = null;
412
-		}
413
-		$mountsContainingFile = $mountCache->getMountsForFileId($id, $user);
414
-
415
-		// if the mount isn't in the cache yet, perform a setup first, then try again
416
-		if (count($mountsContainingFile) === 0) {
417
-			$this->mountManager->getSetupManager()->setupForPath($path, true);
418
-			$mountsContainingFile = $mountCache->getMountsForFileId($id, $user);
419
-		}
420
-
421
-		// when a user has access through the same storage through multiple paths
422
-		// (such as an external storage that is both mounted for a user and shared to the user)
423
-		// the mount cache will only hold a single entry for the storage
424
-		// this can lead to issues as the different ways the user has access to a storage can have different permissions
425
-		//
426
-		// so instead of using the cached entries directly, we instead filter the current mounts by the rootid of the cache entry
427
-
428
-		$mountRootIds = array_map(function ($mount) {
429
-			return $mount->getRootId();
430
-		}, $mountsContainingFile);
431
-		$mountRootPaths = array_map(function ($mount) {
432
-			return $mount->getRootInternalPath();
433
-		}, $mountsContainingFile);
434
-		$mountProviders = array_unique(array_map(function ($mount) {
435
-			return $mount->getMountProvider();
436
-		}, $mountsContainingFile));
437
-		$mountRoots = array_combine($mountRootIds, $mountRootPaths);
438
-
439
-		$mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders);
440
-
441
-		$mountsContainingFile = array_filter($mounts, function ($mount) use ($mountRoots) {
442
-			return isset($mountRoots[$mount->getStorageRootId()]);
443
-		});
444
-
445
-		if (count($mountsContainingFile) === 0) {
446
-			if ($user === $this->getAppDataDirectoryName()) {
447
-				$folder = $this->get($path);
448
-				if ($folder instanceof Folder) {
449
-					return $folder->getByIdInRootMount($id);
450
-				} else {
451
-					throw new \Exception('getByIdInPath with non folder');
452
-				}
453
-			}
454
-			return [];
455
-		}
456
-
457
-		$nodes = array_map(function (IMountPoint $mount) use ($id, $mountRoots) {
458
-			$rootInternalPath = $mountRoots[$mount->getStorageRootId()];
459
-			$cacheEntry = $mount->getStorage()->getCache()->get($id);
460
-			if (!$cacheEntry) {
461
-				return null;
462
-			}
463
-
464
-			// cache jails will hide the "true" internal path
465
-			$internalPath = ltrim($rootInternalPath . '/' . $cacheEntry->getPath(), '/');
466
-			$pathRelativeToMount = substr($internalPath, strlen($rootInternalPath));
467
-			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
468
-			$absolutePath = rtrim($mount->getMountPoint() . $pathRelativeToMount, '/');
469
-			$storage = $mount->getStorage();
470
-			if ($storage === null) {
471
-				return null;
472
-			}
473
-			$ownerId = $storage->getOwner($pathRelativeToMount);
474
-			if ($ownerId !== false) {
475
-				$owner = Server::get(IUserManager::class)->get($ownerId);
476
-			} else {
477
-				$owner = null;
478
-			}
479
-			return $this->createNode($absolutePath, new FileInfo(
480
-				$absolutePath,
481
-				$storage,
482
-				$cacheEntry->getPath(),
483
-				$cacheEntry,
484
-				$mount,
485
-				$owner,
486
-			));
487
-		}, $mountsContainingFile);
488
-
489
-		$nodes = array_filter($nodes);
490
-
491
-		$folders = array_filter($nodes, function (Node $node) use ($path) {
492
-			return PathHelper::getRelativePath($path, $node->getPath()) !== null;
493
-		});
494
-		usort($folders, function ($a, $b) {
495
-			return $b->getPath() <=> $a->getPath();
496
-		});
497
-		return $folders;
498
-	}
499
-
500
-	public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode {
501
-		$path = $cacheEntry->getPath();
502
-		$fullPath = $mountPoint->getMountPoint() . $path;
503
-		// todo: LazyNode?
504
-		$info = new FileInfo($fullPath, $mountPoint->getStorage(), $path, $cacheEntry, $mountPoint);
505
-		$parentPath = dirname($fullPath);
506
-		$parent = new LazyFolder($this, function () use ($parentPath) {
507
-			$parent = $this->get($parentPath);
508
-			if ($parent instanceof \OCP\Files\Folder) {
509
-				return $parent;
510
-			} else {
511
-				throw new \Exception("parent $parentPath is not a folder");
512
-			}
513
-		}, [
514
-			'path' => $parentPath,
515
-		]);
516
-		$isDir = $info->getType() === FileInfo::TYPE_FOLDER;
517
-		$view = new View('');
518
-		if ($isDir) {
519
-			return new Folder($this, $view, $fullPath, $info, $parent);
520
-		} else {
521
-			return new File($this, $view, $fullPath, $info, $parent);
522
-		}
523
-	}
57
+    private PublicEmitter $emitter;
58
+    private CappedMemoryCache $userFolderCache;
59
+    private ICache $pathByIdCache;
60
+    private bool $useDefaultHomeFoldersPermissions = true;
61
+
62
+    public function __construct(
63
+        private Manager $mountManager,
64
+        View $view,
65
+        private ?IUser $user,
66
+        private IUserMountCache $userMountCache,
67
+        private LoggerInterface $logger,
68
+        private IUserManager $userManager,
69
+        IEventDispatcher $eventDispatcher,
70
+        ICacheFactory $cacheFactory,
71
+        IAppConfig $appConfig,
72
+    ) {
73
+        parent::__construct($this, $view, '');
74
+        $this->emitter = new PublicEmitter();
75
+        $this->userFolderCache = new CappedMemoryCache();
76
+        $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
77
+            $this->userFolderCache = new CappedMemoryCache();
78
+        });
79
+        $this->pathByIdCache = $cacheFactory->createLocal('path-by-id');
80
+        $this->useDefaultHomeFoldersPermissions = count($appConfig->getValueArray(Application::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS)) === 0;
81
+    }
82
+
83
+    /**
84
+     * Get the user for which the filesystem is setup
85
+     *
86
+     * @return \OC\User\User
87
+     */
88
+    public function getUser() {
89
+        return $this->user;
90
+    }
91
+
92
+    /**
93
+     * @param string $scope
94
+     * @param string $method
95
+     * @param callable $callback
96
+     */
97
+    public function listen($scope, $method, callable $callback) {
98
+        $this->emitter->listen($scope, $method, $callback);
99
+    }
100
+
101
+    /**
102
+     * @param string $scope optional
103
+     * @param string $method optional
104
+     * @param callable $callback optional
105
+     */
106
+    public function removeListener($scope = null, $method = null, ?callable $callback = null) {
107
+        $this->emitter->removeListener($scope, $method, $callback);
108
+    }
109
+
110
+    /**
111
+     * @param string $scope
112
+     * @param string $method
113
+     * @param Node[] $arguments
114
+     */
115
+    public function emit($scope, $method, $arguments = []) {
116
+        $this->emitter->emit($scope, $method, $arguments);
117
+    }
118
+
119
+    /**
120
+     * @param \OC\Files\Storage\Storage $storage
121
+     * @param string $mountPoint
122
+     * @param array $arguments
123
+     */
124
+    public function mount($storage, $mountPoint, $arguments = []) {
125
+        $mount = new MountPoint($storage, $mountPoint, $arguments);
126
+        $this->mountManager->addMount($mount);
127
+    }
128
+
129
+    public function getMount(string $mountPoint): IMountPoint {
130
+        return $this->mountManager->find($mountPoint);
131
+    }
132
+
133
+    /**
134
+     * @param string $mountPoint
135
+     * @return \OC\Files\Mount\MountPoint[]
136
+     */
137
+    public function getMountsIn(string $mountPoint): array {
138
+        return $this->mountManager->findIn($mountPoint);
139
+    }
140
+
141
+    /**
142
+     * @param string $storageId
143
+     * @return \OC\Files\Mount\MountPoint[]
144
+     */
145
+    public function getMountByStorageId($storageId) {
146
+        return $this->mountManager->findByStorageId($storageId);
147
+    }
148
+
149
+    /**
150
+     * @param int $numericId
151
+     * @return MountPoint[]
152
+     */
153
+    public function getMountByNumericStorageId($numericId) {
154
+        return $this->mountManager->findByNumericId($numericId);
155
+    }
156
+
157
+    /**
158
+     * @param \OC\Files\Mount\MountPoint $mount
159
+     */
160
+    public function unMount($mount) {
161
+        $this->mountManager->remove($mount);
162
+    }
163
+
164
+    public function get($path) {
165
+        $path = $this->normalizePath($path);
166
+        if ($this->isValidPath($path)) {
167
+            $fullPath = $this->getFullPath($path);
168
+            $fileInfo = $this->view->getFileInfo($fullPath, false);
169
+            if ($fileInfo) {
170
+                return $this->createNode($fullPath, $fileInfo, false);
171
+            } else {
172
+                throw new NotFoundException($path);
173
+            }
174
+        } else {
175
+            throw new NotPermittedException();
176
+        }
177
+    }
178
+
179
+    //most operations can't be done on the root
180
+
181
+    /**
182
+     * @param string $targetPath
183
+     * @return Node
184
+     * @throws \OCP\Files\NotPermittedException
185
+     */
186
+    public function rename($targetPath) {
187
+        throw new NotPermittedException();
188
+    }
189
+
190
+    public function delete() {
191
+        throw new NotPermittedException();
192
+    }
193
+
194
+    /**
195
+     * @param string $targetPath
196
+     * @return Node
197
+     * @throws \OCP\Files\NotPermittedException
198
+     */
199
+    public function copy($targetPath) {
200
+        throw new NotPermittedException();
201
+    }
202
+
203
+    /**
204
+     * @param int $mtime
205
+     * @throws \OCP\Files\NotPermittedException
206
+     */
207
+    public function touch($mtime = null) {
208
+        throw new NotPermittedException();
209
+    }
210
+
211
+    /**
212
+     * @return \OC\Files\Storage\Storage
213
+     * @throws \OCP\Files\NotFoundException
214
+     */
215
+    public function getStorage() {
216
+        throw new NotFoundException();
217
+    }
218
+
219
+    /**
220
+     * @return string
221
+     */
222
+    public function getPath() {
223
+        return '/';
224
+    }
225
+
226
+    /**
227
+     * @return string
228
+     */
229
+    public function getInternalPath() {
230
+        return '';
231
+    }
232
+
233
+    /**
234
+     * @return int
235
+     */
236
+    public function getId() {
237
+        return 0;
238
+    }
239
+
240
+    /**
241
+     * @return array
242
+     */
243
+    public function stat() {
244
+        return [];
245
+    }
246
+
247
+    /**
248
+     * @return int
249
+     */
250
+    public function getMTime() {
251
+        return 0;
252
+    }
253
+
254
+    /**
255
+     * @param bool $includeMounts
256
+     * @return int|float
257
+     */
258
+    public function getSize($includeMounts = true): int|float {
259
+        return 0;
260
+    }
261
+
262
+    /**
263
+     * @return string
264
+     */
265
+    public function getEtag() {
266
+        return '';
267
+    }
268
+
269
+    /**
270
+     * @return int
271
+     */
272
+    public function getPermissions() {
273
+        return \OCP\Constants::PERMISSION_CREATE;
274
+    }
275
+
276
+    /**
277
+     * @return bool
278
+     */
279
+    public function isReadable() {
280
+        return false;
281
+    }
282
+
283
+    /**
284
+     * @return bool
285
+     */
286
+    public function isUpdateable() {
287
+        return false;
288
+    }
289
+
290
+    /**
291
+     * @return bool
292
+     */
293
+    public function isDeletable() {
294
+        return false;
295
+    }
296
+
297
+    /**
298
+     * @return bool
299
+     */
300
+    public function isShareable() {
301
+        return false;
302
+    }
303
+
304
+    /**
305
+     * @throws \OCP\Files\NotFoundException
306
+     */
307
+    public function getParent(): INode|IRootFolder {
308
+        throw new NotFoundException();
309
+    }
310
+
311
+    /**
312
+     * @return string
313
+     */
314
+    public function getName() {
315
+        return '';
316
+    }
317
+
318
+    /**
319
+     * Returns a view to user's files folder
320
+     *
321
+     * @param string $userId user ID
322
+     * @return \OCP\Files\Folder
323
+     * @throws NoUserException
324
+     * @throws NotPermittedException
325
+     */
326
+    public function getUserFolder($userId) {
327
+        $userObject = $this->userManager->get($userId);
328
+
329
+        if (is_null($userObject)) {
330
+            $e = new NoUserException('Backends provided no user object');
331
+            $this->logger->error(
332
+                sprintf(
333
+                    'Backends provided no user object for %s',
334
+                    $userId
335
+                ),
336
+                [
337
+                    'app' => 'files',
338
+                    'exception' => $e,
339
+                ]
340
+            );
341
+            throw $e;
342
+        }
343
+
344
+        $userId = $userObject->getUID();
345
+
346
+        if (!$this->userFolderCache->hasKey($userId)) {
347
+            if ($this->mountManager->getSetupManager()->isSetupComplete($userObject)) {
348
+                try {
349
+                    $folder = $this->get('/' . $userId . '/files');
350
+                    if (!$folder instanceof \OCP\Files\Folder) {
351
+                        throw new \Exception("Account folder for \"$userId\" exists as a file");
352
+                    }
353
+                } catch (NotFoundException $e) {
354
+                    if (!$this->nodeExists('/' . $userId)) {
355
+                        $this->newFolder('/' . $userId);
356
+                    }
357
+                    $folder = $this->newFolder('/' . $userId . '/files');
358
+                }
359
+            } else {
360
+                $folder = new LazyUserFolder($this, $userObject, $this->mountManager, $this->useDefaultHomeFoldersPermissions);
361
+            }
362
+
363
+            $this->userFolderCache->set($userId, $folder);
364
+        }
365
+
366
+        return $this->userFolderCache->get($userId);
367
+    }
368
+
369
+    public function getUserMountCache() {
370
+        return $this->userMountCache;
371
+    }
372
+
373
+    public function getFirstNodeByIdInPath(int $id, string $path): ?INode {
374
+        // scope the cache by user, so we don't return nodes for different users
375
+        if ($this->user) {
376
+            $cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id);
377
+            if ($cachedPath && str_starts_with($cachedPath, $path)) {
378
+                // getting the node by path is significantly cheaper than finding it by id
379
+                try {
380
+                    $node = $this->get($cachedPath);
381
+                    // by validating that the cached path still has the requested fileid we can work around the need to invalidate the cached path
382
+                    // if the cached path is invalid or a different file now we fall back to the uncached logic
383
+                    if ($node && $node->getId() === $id) {
384
+                        return $node;
385
+                    }
386
+                } catch (NotFoundException|NotPermittedException) {
387
+                    // The file may be moved but the old path still in cache
388
+                }
389
+            }
390
+        }
391
+        $node = current($this->getByIdInPath($id, $path));
392
+        if (!$node) {
393
+            return null;
394
+        }
395
+
396
+        if ($this->user) {
397
+            $this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath());
398
+        }
399
+        return $node;
400
+    }
401
+
402
+    /**
403
+     * @param int $id
404
+     * @return Node[]
405
+     */
406
+    public function getByIdInPath(int $id, string $path): array {
407
+        $mountCache = $this->getUserMountCache();
408
+        if ($path !== '' && strpos($path, '/', 1) > 0) {
409
+            [, $user] = explode('/', $path);
410
+        } else {
411
+            $user = null;
412
+        }
413
+        $mountsContainingFile = $mountCache->getMountsForFileId($id, $user);
414
+
415
+        // if the mount isn't in the cache yet, perform a setup first, then try again
416
+        if (count($mountsContainingFile) === 0) {
417
+            $this->mountManager->getSetupManager()->setupForPath($path, true);
418
+            $mountsContainingFile = $mountCache->getMountsForFileId($id, $user);
419
+        }
420
+
421
+        // when a user has access through the same storage through multiple paths
422
+        // (such as an external storage that is both mounted for a user and shared to the user)
423
+        // the mount cache will only hold a single entry for the storage
424
+        // this can lead to issues as the different ways the user has access to a storage can have different permissions
425
+        //
426
+        // so instead of using the cached entries directly, we instead filter the current mounts by the rootid of the cache entry
427
+
428
+        $mountRootIds = array_map(function ($mount) {
429
+            return $mount->getRootId();
430
+        }, $mountsContainingFile);
431
+        $mountRootPaths = array_map(function ($mount) {
432
+            return $mount->getRootInternalPath();
433
+        }, $mountsContainingFile);
434
+        $mountProviders = array_unique(array_map(function ($mount) {
435
+            return $mount->getMountProvider();
436
+        }, $mountsContainingFile));
437
+        $mountRoots = array_combine($mountRootIds, $mountRootPaths);
438
+
439
+        $mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders);
440
+
441
+        $mountsContainingFile = array_filter($mounts, function ($mount) use ($mountRoots) {
442
+            return isset($mountRoots[$mount->getStorageRootId()]);
443
+        });
444
+
445
+        if (count($mountsContainingFile) === 0) {
446
+            if ($user === $this->getAppDataDirectoryName()) {
447
+                $folder = $this->get($path);
448
+                if ($folder instanceof Folder) {
449
+                    return $folder->getByIdInRootMount($id);
450
+                } else {
451
+                    throw new \Exception('getByIdInPath with non folder');
452
+                }
453
+            }
454
+            return [];
455
+        }
456
+
457
+        $nodes = array_map(function (IMountPoint $mount) use ($id, $mountRoots) {
458
+            $rootInternalPath = $mountRoots[$mount->getStorageRootId()];
459
+            $cacheEntry = $mount->getStorage()->getCache()->get($id);
460
+            if (!$cacheEntry) {
461
+                return null;
462
+            }
463
+
464
+            // cache jails will hide the "true" internal path
465
+            $internalPath = ltrim($rootInternalPath . '/' . $cacheEntry->getPath(), '/');
466
+            $pathRelativeToMount = substr($internalPath, strlen($rootInternalPath));
467
+            $pathRelativeToMount = ltrim($pathRelativeToMount, '/');
468
+            $absolutePath = rtrim($mount->getMountPoint() . $pathRelativeToMount, '/');
469
+            $storage = $mount->getStorage();
470
+            if ($storage === null) {
471
+                return null;
472
+            }
473
+            $ownerId = $storage->getOwner($pathRelativeToMount);
474
+            if ($ownerId !== false) {
475
+                $owner = Server::get(IUserManager::class)->get($ownerId);
476
+            } else {
477
+                $owner = null;
478
+            }
479
+            return $this->createNode($absolutePath, new FileInfo(
480
+                $absolutePath,
481
+                $storage,
482
+                $cacheEntry->getPath(),
483
+                $cacheEntry,
484
+                $mount,
485
+                $owner,
486
+            ));
487
+        }, $mountsContainingFile);
488
+
489
+        $nodes = array_filter($nodes);
490
+
491
+        $folders = array_filter($nodes, function (Node $node) use ($path) {
492
+            return PathHelper::getRelativePath($path, $node->getPath()) !== null;
493
+        });
494
+        usort($folders, function ($a, $b) {
495
+            return $b->getPath() <=> $a->getPath();
496
+        });
497
+        return $folders;
498
+    }
499
+
500
+    public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode {
501
+        $path = $cacheEntry->getPath();
502
+        $fullPath = $mountPoint->getMountPoint() . $path;
503
+        // todo: LazyNode?
504
+        $info = new FileInfo($fullPath, $mountPoint->getStorage(), $path, $cacheEntry, $mountPoint);
505
+        $parentPath = dirname($fullPath);
506
+        $parent = new LazyFolder($this, function () use ($parentPath) {
507
+            $parent = $this->get($parentPath);
508
+            if ($parent instanceof \OCP\Files\Folder) {
509
+                return $parent;
510
+            } else {
511
+                throw new \Exception("parent $parentPath is not a folder");
512
+            }
513
+        }, [
514
+            'path' => $parentPath,
515
+        ]);
516
+        $isDir = $info->getType() === FileInfo::TYPE_FOLDER;
517
+        $view = new View('');
518
+        if ($isDir) {
519
+            return new Folder($this, $view, $fullPath, $info, $parent);
520
+        } else {
521
+            return new File($this, $view, $fullPath, $info, $parent);
522
+        }
523
+    }
524 524
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
 		parent::__construct($this, $view, '');
74 74
 		$this->emitter = new PublicEmitter();
75 75
 		$this->userFolderCache = new CappedMemoryCache();
76
-		$eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
76
+		$eventDispatcher->addListener(FilesystemTornDownEvent::class, function() {
77 77
 			$this->userFolderCache = new CappedMemoryCache();
78 78
 		});
79 79
 		$this->pathByIdCache = $cacheFactory->createLocal('path-by-id');
@@ -255,7 +255,7 @@  discard block
 block discarded – undo
255 255
 	 * @param bool $includeMounts
256 256
 	 * @return int|float
257 257
 	 */
258
-	public function getSize($includeMounts = true): int|float {
258
+	public function getSize($includeMounts = true): int | float {
259 259
 		return 0;
260 260
 	}
261 261
 
@@ -304,7 +304,7 @@  discard block
 block discarded – undo
304 304
 	/**
305 305
 	 * @throws \OCP\Files\NotFoundException
306 306
 	 */
307
-	public function getParent(): INode|IRootFolder {
307
+	public function getParent(): INode | IRootFolder {
308 308
 		throw new NotFoundException();
309 309
 	}
310 310
 
@@ -346,15 +346,15 @@  discard block
 block discarded – undo
346 346
 		if (!$this->userFolderCache->hasKey($userId)) {
347 347
 			if ($this->mountManager->getSetupManager()->isSetupComplete($userObject)) {
348 348
 				try {
349
-					$folder = $this->get('/' . $userId . '/files');
349
+					$folder = $this->get('/'.$userId.'/files');
350 350
 					if (!$folder instanceof \OCP\Files\Folder) {
351 351
 						throw new \Exception("Account folder for \"$userId\" exists as a file");
352 352
 					}
353 353
 				} catch (NotFoundException $e) {
354
-					if (!$this->nodeExists('/' . $userId)) {
355
-						$this->newFolder('/' . $userId);
354
+					if (!$this->nodeExists('/'.$userId)) {
355
+						$this->newFolder('/'.$userId);
356 356
 					}
357
-					$folder = $this->newFolder('/' . $userId . '/files');
357
+					$folder = $this->newFolder('/'.$userId.'/files');
358 358
 				}
359 359
 			} else {
360 360
 				$folder = new LazyUserFolder($this, $userObject, $this->mountManager, $this->useDefaultHomeFoldersPermissions);
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
 	public function getFirstNodeByIdInPath(int $id, string $path): ?INode {
374 374
 		// scope the cache by user, so we don't return nodes for different users
375 375
 		if ($this->user) {
376
-			$cachedPath = $this->pathByIdCache->get($this->user->getUID() . '::' . $id);
376
+			$cachedPath = $this->pathByIdCache->get($this->user->getUID().'::'.$id);
377 377
 			if ($cachedPath && str_starts_with($cachedPath, $path)) {
378 378
 				// getting the node by path is significantly cheaper than finding it by id
379 379
 				try {
@@ -383,7 +383,7 @@  discard block
 block discarded – undo
383 383
 					if ($node && $node->getId() === $id) {
384 384
 						return $node;
385 385
 					}
386
-				} catch (NotFoundException|NotPermittedException) {
386
+				} catch (NotFoundException | NotPermittedException) {
387 387
 					// The file may be moved but the old path still in cache
388 388
 				}
389 389
 			}
@@ -394,7 +394,7 @@  discard block
 block discarded – undo
394 394
 		}
395 395
 
396 396
 		if ($this->user) {
397
-			$this->pathByIdCache->set($this->user->getUID() . '::' . $id, $node->getPath());
397
+			$this->pathByIdCache->set($this->user->getUID().'::'.$id, $node->getPath());
398 398
 		}
399 399
 		return $node;
400 400
 	}
@@ -425,20 +425,20 @@  discard block
 block discarded – undo
425 425
 		//
426 426
 		// so instead of using the cached entries directly, we instead filter the current mounts by the rootid of the cache entry
427 427
 
428
-		$mountRootIds = array_map(function ($mount) {
428
+		$mountRootIds = array_map(function($mount) {
429 429
 			return $mount->getRootId();
430 430
 		}, $mountsContainingFile);
431
-		$mountRootPaths = array_map(function ($mount) {
431
+		$mountRootPaths = array_map(function($mount) {
432 432
 			return $mount->getRootInternalPath();
433 433
 		}, $mountsContainingFile);
434
-		$mountProviders = array_unique(array_map(function ($mount) {
434
+		$mountProviders = array_unique(array_map(function($mount) {
435 435
 			return $mount->getMountProvider();
436 436
 		}, $mountsContainingFile));
437 437
 		$mountRoots = array_combine($mountRootIds, $mountRootPaths);
438 438
 
439 439
 		$mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders);
440 440
 
441
-		$mountsContainingFile = array_filter($mounts, function ($mount) use ($mountRoots) {
441
+		$mountsContainingFile = array_filter($mounts, function($mount) use ($mountRoots) {
442 442
 			return isset($mountRoots[$mount->getStorageRootId()]);
443 443
 		});
444 444
 
@@ -454,7 +454,7 @@  discard block
 block discarded – undo
454 454
 			return [];
455 455
 		}
456 456
 
457
-		$nodes = array_map(function (IMountPoint $mount) use ($id, $mountRoots) {
457
+		$nodes = array_map(function(IMountPoint $mount) use ($id, $mountRoots) {
458 458
 			$rootInternalPath = $mountRoots[$mount->getStorageRootId()];
459 459
 			$cacheEntry = $mount->getStorage()->getCache()->get($id);
460 460
 			if (!$cacheEntry) {
@@ -462,10 +462,10 @@  discard block
 block discarded – undo
462 462
 			}
463 463
 
464 464
 			// cache jails will hide the "true" internal path
465
-			$internalPath = ltrim($rootInternalPath . '/' . $cacheEntry->getPath(), '/');
465
+			$internalPath = ltrim($rootInternalPath.'/'.$cacheEntry->getPath(), '/');
466 466
 			$pathRelativeToMount = substr($internalPath, strlen($rootInternalPath));
467 467
 			$pathRelativeToMount = ltrim($pathRelativeToMount, '/');
468
-			$absolutePath = rtrim($mount->getMountPoint() . $pathRelativeToMount, '/');
468
+			$absolutePath = rtrim($mount->getMountPoint().$pathRelativeToMount, '/');
469 469
 			$storage = $mount->getStorage();
470 470
 			if ($storage === null) {
471 471
 				return null;
@@ -488,10 +488,10 @@  discard block
 block discarded – undo
488 488
 
489 489
 		$nodes = array_filter($nodes);
490 490
 
491
-		$folders = array_filter($nodes, function (Node $node) use ($path) {
491
+		$folders = array_filter($nodes, function(Node $node) use ($path) {
492 492
 			return PathHelper::getRelativePath($path, $node->getPath()) !== null;
493 493
 		});
494
-		usort($folders, function ($a, $b) {
494
+		usort($folders, function($a, $b) {
495 495
 			return $b->getPath() <=> $a->getPath();
496 496
 		});
497 497
 		return $folders;
@@ -499,11 +499,11 @@  discard block
 block discarded – undo
499 499
 
500 500
 	public function getNodeFromCacheEntryAndMount(ICacheEntry $cacheEntry, IMountPoint $mountPoint): INode {
501 501
 		$path = $cacheEntry->getPath();
502
-		$fullPath = $mountPoint->getMountPoint() . $path;
502
+		$fullPath = $mountPoint->getMountPoint().$path;
503 503
 		// todo: LazyNode?
504 504
 		$info = new FileInfo($fullPath, $mountPoint->getStorage(), $path, $cacheEntry, $mountPoint);
505 505
 		$parentPath = dirname($fullPath);
506
-		$parent = new LazyFolder($this, function () use ($parentPath) {
506
+		$parent = new LazyFolder($this, function() use ($parentPath) {
507 507
 			$parent = $this->get($parentPath);
508 508
 			if ($parent instanceof \OCP\Files\Folder) {
509 509
 				return $parent;
Please login to merge, or discard this patch.
lib/private/Files/Node/LazyUserFolder.php 2 patches
Indentation   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -19,60 +19,60 @@
 block discarded – undo
19 19
 use Psr\Log\LoggerInterface;
20 20
 
21 21
 class LazyUserFolder extends LazyFolder {
22
-	private string $path;
22
+    private string $path;
23 23
 
24
-	public function __construct(
25
-		IRootFolder $rootFolder,
26
-		private IUser $user,
27
-		private IMountManager $mountManager,
28
-		bool $useDefaultHomeFoldersPermissions = true,
29
-	) {
30
-		$this->path = '/' . $user->getUID() . '/files';
31
-		$data = [
32
-			'path' => $this->path,
33
-			'type' => FileInfo::TYPE_FOLDER,
34
-			'mimetype' => FileInfo::MIMETYPE_FOLDER,
35
-		];
24
+    public function __construct(
25
+        IRootFolder $rootFolder,
26
+        private IUser $user,
27
+        private IMountManager $mountManager,
28
+        bool $useDefaultHomeFoldersPermissions = true,
29
+    ) {
30
+        $this->path = '/' . $user->getUID() . '/files';
31
+        $data = [
32
+            'path' => $this->path,
33
+            'type' => FileInfo::TYPE_FOLDER,
34
+            'mimetype' => FileInfo::MIMETYPE_FOLDER,
35
+        ];
36 36
 
37
-		// By default, we assume the permissions for the users' home folders.
38
-		// If a mount point is mounted on a user's home folder, the permissions cannot be assumed.
39
-		if ($useDefaultHomeFoldersPermissions) {
40
-			// Sharing user root folder is not allowed
41
-			$data['permissions'] = Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE;
42
-		}
37
+        // By default, we assume the permissions for the users' home folders.
38
+        // If a mount point is mounted on a user's home folder, the permissions cannot be assumed.
39
+        if ($useDefaultHomeFoldersPermissions) {
40
+            // Sharing user root folder is not allowed
41
+            $data['permissions'] = Constants::PERMISSION_ALL ^ Constants::PERMISSION_SHARE;
42
+        }
43 43
 
44
-		parent::__construct(
45
-			$rootFolder,
46
-			function () use ($user): Folder {
47
-				try {
48
-					$node = $this->getRootFolder()->get($this->path);
49
-					if ($node instanceof File) {
50
-						$e = new \RuntimeException();
51
-						\OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [
52
-							'exception' => $e,
53
-						]);
54
-						throw $e;
55
-					}
56
-					return $node;
57
-				} catch (NotFoundException $e) {
58
-					if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) {
59
-						$this->getRootFolder()->newFolder('/' . $user->getUID());
60
-					}
61
-					return $this->getRootFolder()->newFolder($this->path);
62
-				}
63
-			},
64
-			$data,
65
-		);
66
-	}
44
+        parent::__construct(
45
+            $rootFolder,
46
+            function () use ($user): Folder {
47
+                try {
48
+                    $node = $this->getRootFolder()->get($this->path);
49
+                    if ($node instanceof File) {
50
+                        $e = new \RuntimeException();
51
+                        \OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [
52
+                            'exception' => $e,
53
+                        ]);
54
+                        throw $e;
55
+                    }
56
+                    return $node;
57
+                } catch (NotFoundException $e) {
58
+                    if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) {
59
+                        $this->getRootFolder()->newFolder('/' . $user->getUID());
60
+                    }
61
+                    return $this->getRootFolder()->newFolder($this->path);
62
+                }
63
+            },
64
+            $data,
65
+        );
66
+    }
67 67
 
68
-	public function getMountPoint() {
69
-		if ($this->folder !== null) {
70
-			return $this->folder->getMountPoint();
71
-		}
72
-		$mountPoint = $this->mountManager->find('/' . $this->user->getUID());
73
-		if (is_null($mountPoint)) {
74
-			throw new \Exception('No mountpoint for user folder');
75
-		}
76
-		return $mountPoint;
77
-	}
68
+    public function getMountPoint() {
69
+        if ($this->folder !== null) {
70
+            return $this->folder->getMountPoint();
71
+        }
72
+        $mountPoint = $this->mountManager->find('/' . $this->user->getUID());
73
+        if (is_null($mountPoint)) {
74
+            throw new \Exception('No mountpoint for user folder');
75
+        }
76
+        return $mountPoint;
77
+    }
78 78
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -27,7 +27,7 @@  discard block
 block discarded – undo
27 27
 		private IMountManager $mountManager,
28 28
 		bool $useDefaultHomeFoldersPermissions = true,
29 29
 	) {
30
-		$this->path = '/' . $user->getUID() . '/files';
30
+		$this->path = '/'.$user->getUID().'/files';
31 31
 		$data = [
32 32
 			'path' => $this->path,
33 33
 			'type' => FileInfo::TYPE_FOLDER,
@@ -43,20 +43,20 @@  discard block
 block discarded – undo
43 43
 
44 44
 		parent::__construct(
45 45
 			$rootFolder,
46
-			function () use ($user): Folder {
46
+			function() use ($user): Folder {
47 47
 				try {
48 48
 					$node = $this->getRootFolder()->get($this->path);
49 49
 					if ($node instanceof File) {
50 50
 						$e = new \RuntimeException();
51
-						\OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: ' . $this->path, [
51
+						\OCP\Server::get(LoggerInterface::class)->error('User root storage is not a folder: '.$this->path, [
52 52
 							'exception' => $e,
53 53
 						]);
54 54
 						throw $e;
55 55
 					}
56 56
 					return $node;
57 57
 				} catch (NotFoundException $e) {
58
-					if (!$this->getRootFolder()->nodeExists('/' . $user->getUID())) {
59
-						$this->getRootFolder()->newFolder('/' . $user->getUID());
58
+					if (!$this->getRootFolder()->nodeExists('/'.$user->getUID())) {
59
+						$this->getRootFolder()->newFolder('/'.$user->getUID());
60 60
 					}
61 61
 					return $this->getRootFolder()->newFolder($this->path);
62 62
 				}
@@ -69,7 +69,7 @@  discard block
 block discarded – undo
69 69
 		if ($this->folder !== null) {
70 70
 			return $this->folder->getMountPoint();
71 71
 		}
72
-		$mountPoint = $this->mountManager->find('/' . $this->user->getUID());
72
+		$mountPoint = $this->mountManager->find('/'.$this->user->getUID());
73 73
 		if (is_null($mountPoint)) {
74 74
 			throw new \Exception('No mountpoint for user folder');
75 75
 		}
Please login to merge, or discard this patch.
apps/files_external/lib/Migration/Version1025Date20250228162604.php 1 patch
Indentation   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -20,16 +20,16 @@
 block discarded – undo
20 20
  * Check for any external storage overwriting the home folder
21 21
  */
22 22
 class Version1025Date20250228162604 extends SimpleMigrationStep {
23
-	public function __construct(
24
-		private GlobalStoragesService $globalStoragesServices,
25
-		private IAppConfig $appConfig,
26
-	) {
27
-	}
23
+    public function __construct(
24
+        private GlobalStoragesService $globalStoragesServices,
25
+        private IAppConfig $appConfig,
26
+    ) {
27
+    }
28 28
 
29
-	/**
30
-	 * @param Closure(): ISchemaWrapper $schemaClosure
31
-	 */
32
-	public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
33
-		$this->globalStoragesServices->updateOverwriteHomeFolders();
34
-	}
29
+    /**
30
+     * @param Closure(): ISchemaWrapper $schemaClosure
31
+     */
32
+    public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
33
+        $this->globalStoragesServices->updateOverwriteHomeFolders();
34
+    }
35 35
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Service/StoragesService.php 1 patch
Indentation   +468 added lines, -468 removed lines patch added patch discarded remove patch
@@ -33,472 +33,472 @@
 block discarded – undo
33 33
  */
34 34
 abstract class StoragesService {
35 35
 
36
-	/**
37
-	 * @param BackendService $backendService
38
-	 * @param DBConfigService $dbConfig
39
-	 * @param IUserMountCache $userMountCache
40
-	 * @param IEventDispatcher $eventDispatcher
41
-	 */
42
-	public function __construct(
43
-		protected BackendService $backendService,
44
-		protected DBConfigService $dbConfig,
45
-		protected IUserMountCache $userMountCache,
46
-		protected IEventDispatcher $eventDispatcher,
47
-		protected IAppConfig $appConfig,
48
-	) {
49
-	}
50
-
51
-	protected function readDBConfig() {
52
-		return $this->dbConfig->getAdminMounts();
53
-	}
54
-
55
-	protected function getStorageConfigFromDBMount(array $mount) {
56
-		$applicableUsers = array_filter($mount['applicable'], function ($applicable) {
57
-			return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_USER;
58
-		});
59
-		$applicableUsers = array_map(function ($applicable) {
60
-			return $applicable['value'];
61
-		}, $applicableUsers);
62
-
63
-		$applicableGroups = array_filter($mount['applicable'], function ($applicable) {
64
-			return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_GROUP;
65
-		});
66
-		$applicableGroups = array_map(function ($applicable) {
67
-			return $applicable['value'];
68
-		}, $applicableGroups);
69
-
70
-		try {
71
-			$config = $this->createStorage(
72
-				$mount['mount_point'],
73
-				$mount['storage_backend'],
74
-				$mount['auth_backend'],
75
-				$mount['config'],
76
-				$mount['options'],
77
-				array_values($applicableUsers),
78
-				array_values($applicableGroups),
79
-				$mount['priority']
80
-			);
81
-			$config->setType($mount['type']);
82
-			$config->setId((int)$mount['mount_id']);
83
-			return $config;
84
-		} catch (\UnexpectedValueException $e) {
85
-			// don't die if a storage backend doesn't exist
86
-			Server::get(LoggerInterface::class)->error('Could not load storage.', [
87
-				'app' => 'files_external',
88
-				'exception' => $e,
89
-			]);
90
-			return null;
91
-		} catch (\InvalidArgumentException $e) {
92
-			Server::get(LoggerInterface::class)->error('Could not load storage.', [
93
-				'app' => 'files_external',
94
-				'exception' => $e,
95
-			]);
96
-			return null;
97
-		}
98
-	}
99
-
100
-	/**
101
-	 * Read the external storage config
102
-	 *
103
-	 * @return array map of storage id to storage config
104
-	 */
105
-	protected function readConfig() {
106
-		$mounts = $this->readDBConfig();
107
-		$configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
108
-		$configs = array_filter($configs, function ($config) {
109
-			return $config instanceof StorageConfig;
110
-		});
111
-
112
-		$keys = array_map(function (StorageConfig $config) {
113
-			return $config->getId();
114
-		}, $configs);
115
-
116
-		return array_combine($keys, $configs);
117
-	}
118
-
119
-	/**
120
-	 * Get a storage with status
121
-	 *
122
-	 * @param int $id storage id
123
-	 *
124
-	 * @return StorageConfig
125
-	 * @throws NotFoundException if the storage with the given id was not found
126
-	 */
127
-	public function getStorage(int $id) {
128
-		$mount = $this->dbConfig->getMountById($id);
129
-
130
-		if (!is_array($mount)) {
131
-			throw new NotFoundException('Storage with ID "' . $id . '" not found');
132
-		}
133
-
134
-		$config = $this->getStorageConfigFromDBMount($mount);
135
-		if ($this->isApplicable($config)) {
136
-			return $config;
137
-		} else {
138
-			throw new NotFoundException('Storage with ID "' . $id . '" not found');
139
-		}
140
-	}
141
-
142
-	/**
143
-	 * Check whether this storage service should provide access to a storage
144
-	 *
145
-	 * @param StorageConfig $config
146
-	 * @return bool
147
-	 */
148
-	abstract protected function isApplicable(StorageConfig $config);
149
-
150
-	/**
151
-	 * Gets all storages, valid or not
152
-	 *
153
-	 * @return StorageConfig[] array of storage configs
154
-	 */
155
-	public function getAllStorages() {
156
-		return $this->readConfig();
157
-	}
158
-
159
-	/**
160
-	 * Gets all valid storages
161
-	 *
162
-	 * @return StorageConfig[]
163
-	 */
164
-	public function getStorages() {
165
-		return array_filter($this->getAllStorages(), [$this, 'validateStorage']);
166
-	}
167
-
168
-	/**
169
-	 * Validate storage
170
-	 * FIXME: De-duplicate with StoragesController::validate()
171
-	 *
172
-	 * @param StorageConfig $storage
173
-	 * @return bool
174
-	 */
175
-	protected function validateStorage(StorageConfig $storage) {
176
-		/** @var Backend */
177
-		$backend = $storage->getBackend();
178
-		/** @var AuthMechanism */
179
-		$authMechanism = $storage->getAuthMechanism();
180
-
181
-		if (!$backend->isVisibleFor($this->getVisibilityType())) {
182
-			// not permitted to use backend
183
-			return false;
184
-		}
185
-		if (!$authMechanism->isVisibleFor($this->getVisibilityType())) {
186
-			// not permitted to use auth mechanism
187
-			return false;
188
-		}
189
-
190
-		return true;
191
-	}
192
-
193
-	/**
194
-	 * Get the visibility type for this controller, used in validation
195
-	 *
196
-	 * @return int BackendService::VISIBILITY_* constants
197
-	 */
198
-	abstract public function getVisibilityType();
199
-
200
-	/**
201
-	 * @return integer
202
-	 */
203
-	protected function getType() {
204
-		return DBConfigService::MOUNT_TYPE_ADMIN;
205
-	}
206
-
207
-	/**
208
-	 * Add new storage to the configuration
209
-	 *
210
-	 * @param StorageConfig $newStorage storage attributes
211
-	 *
212
-	 * @return StorageConfig storage config, with added id
213
-	 */
214
-	public function addStorage(StorageConfig $newStorage) {
215
-		$allStorages = $this->readConfig();
216
-
217
-		$configId = $this->dbConfig->addMount(
218
-			$newStorage->getMountPoint(),
219
-			$newStorage->getBackend()->getIdentifier(),
220
-			$newStorage->getAuthMechanism()->getIdentifier(),
221
-			$newStorage->getPriority(),
222
-			$this->getType()
223
-		);
224
-
225
-		$newStorage->setId($configId);
226
-
227
-		foreach ($newStorage->getApplicableUsers() as $user) {
228
-			$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_USER, $user);
229
-		}
230
-		foreach ($newStorage->getApplicableGroups() as $group) {
231
-			$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
232
-		}
233
-		foreach ($newStorage->getBackendOptions() as $key => $value) {
234
-			$this->dbConfig->setConfig($configId, $key, $value);
235
-		}
236
-		foreach ($newStorage->getMountOptions() as $key => $value) {
237
-			$this->dbConfig->setOption($configId, $key, $value);
238
-		}
239
-
240
-		if (count($newStorage->getApplicableUsers()) === 0 && count($newStorage->getApplicableGroups()) === 0) {
241
-			$this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
242
-		}
243
-
244
-		// add new storage
245
-		$allStorages[$configId] = $newStorage;
246
-
247
-		$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
248
-
249
-		$newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS);
250
-
251
-		$this->updateOverwriteHomeFolders();
252
-
253
-		return $newStorage;
254
-	}
255
-
256
-	/**
257
-	 * Create a storage from its parameters
258
-	 *
259
-	 * @param string $mountPoint storage mount point
260
-	 * @param string $backendIdentifier backend identifier
261
-	 * @param string $authMechanismIdentifier authentication mechanism identifier
262
-	 * @param array $backendOptions backend-specific options
263
-	 * @param array|null $mountOptions mount-specific options
264
-	 * @param array|null $applicableUsers users for which to mount the storage
265
-	 * @param array|null $applicableGroups groups for which to mount the storage
266
-	 * @param int|null $priority priority
267
-	 *
268
-	 * @return StorageConfig
269
-	 */
270
-	public function createStorage(
271
-		$mountPoint,
272
-		$backendIdentifier,
273
-		$authMechanismIdentifier,
274
-		$backendOptions,
275
-		$mountOptions = null,
276
-		$applicableUsers = null,
277
-		$applicableGroups = null,
278
-		$priority = null,
279
-	) {
280
-		$backend = $this->backendService->getBackend($backendIdentifier);
281
-		if (!$backend) {
282
-			$backend = new InvalidBackend($backendIdentifier);
283
-		}
284
-		$authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
285
-		if (!$authMechanism) {
286
-			$authMechanism = new InvalidAuth($authMechanismIdentifier);
287
-		}
288
-		$newStorage = new StorageConfig();
289
-		$newStorage->setMountPoint($mountPoint);
290
-		$newStorage->setBackend($backend);
291
-		$newStorage->setAuthMechanism($authMechanism);
292
-		$newStorage->setBackendOptions($backendOptions);
293
-		if (isset($mountOptions)) {
294
-			$newStorage->setMountOptions($mountOptions);
295
-		}
296
-		if (isset($applicableUsers)) {
297
-			$newStorage->setApplicableUsers($applicableUsers);
298
-		}
299
-		if (isset($applicableGroups)) {
300
-			$newStorage->setApplicableGroups($applicableGroups);
301
-		}
302
-		if (isset($priority)) {
303
-			$newStorage->setPriority($priority);
304
-		}
305
-
306
-		return $newStorage;
307
-	}
308
-
309
-	/**
310
-	 * Triggers the given hook signal for all the applicables given
311
-	 *
312
-	 * @param string $signal signal
313
-	 * @param string $mountPoint hook mount point param
314
-	 * @param string $mountType hook mount type param
315
-	 * @param array $applicableArray array of applicable users/groups for which to trigger the hook
316
-	 */
317
-	protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray): void {
318
-		$this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent(null));
319
-		foreach ($applicableArray as $applicable) {
320
-			Util::emitHook(
321
-				Filesystem::CLASSNAME,
322
-				$signal,
323
-				[
324
-					Filesystem::signal_param_path => $mountPoint,
325
-					Filesystem::signal_param_mount_type => $mountType,
326
-					Filesystem::signal_param_users => $applicable,
327
-				]
328
-			);
329
-		}
330
-	}
331
-
332
-	/**
333
-	 * Triggers $signal for all applicable users of the given
334
-	 * storage
335
-	 *
336
-	 * @param StorageConfig $storage storage data
337
-	 * @param string $signal signal to trigger
338
-	 */
339
-	abstract protected function triggerHooks(StorageConfig $storage, $signal);
340
-
341
-	/**
342
-	 * Triggers signal_create_mount or signal_delete_mount to
343
-	 * accommodate for additions/deletions in applicableUsers
344
-	 * and applicableGroups fields.
345
-	 *
346
-	 * @param StorageConfig $oldStorage old storage data
347
-	 * @param StorageConfig $newStorage new storage data
348
-	 */
349
-	abstract protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage);
350
-
351
-	/**
352
-	 * Update storage to the configuration
353
-	 *
354
-	 * @param StorageConfig $updatedStorage storage attributes
355
-	 *
356
-	 * @return StorageConfig storage config
357
-	 * @throws NotFoundException if the given storage does not exist in the config
358
-	 */
359
-	public function updateStorage(StorageConfig $updatedStorage) {
360
-		$id = $updatedStorage->getId();
361
-
362
-		$existingMount = $this->dbConfig->getMountById($id);
363
-
364
-		if (!is_array($existingMount)) {
365
-			throw new NotFoundException('Storage with ID "' . $id . '" not found while updating storage');
366
-		}
367
-
368
-		$oldStorage = $this->getStorageConfigFromDBMount($existingMount);
369
-
370
-		if ($oldStorage->getBackend() instanceof InvalidBackend) {
371
-			throw new NotFoundException('Storage with id "' . $id . '" cannot be edited due to missing backend');
372
-		}
373
-
374
-		$removedUsers = array_diff($oldStorage->getApplicableUsers(), $updatedStorage->getApplicableUsers());
375
-		$removedGroups = array_diff($oldStorage->getApplicableGroups(), $updatedStorage->getApplicableGroups());
376
-		$addedUsers = array_diff($updatedStorage->getApplicableUsers(), $oldStorage->getApplicableUsers());
377
-		$addedGroups = array_diff($updatedStorage->getApplicableGroups(), $oldStorage->getApplicableGroups());
378
-
379
-		$oldUserCount = count($oldStorage->getApplicableUsers());
380
-		$oldGroupCount = count($oldStorage->getApplicableGroups());
381
-		$newUserCount = count($updatedStorage->getApplicableUsers());
382
-		$newGroupCount = count($updatedStorage->getApplicableGroups());
383
-		$wasGlobal = ($oldUserCount + $oldGroupCount) === 0;
384
-		$isGlobal = ($newUserCount + $newGroupCount) === 0;
385
-
386
-		foreach ($removedUsers as $user) {
387
-			$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
388
-		}
389
-		foreach ($removedGroups as $group) {
390
-			$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
391
-		}
392
-		foreach ($addedUsers as $user) {
393
-			$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
394
-		}
395
-		foreach ($addedGroups as $group) {
396
-			$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
397
-		}
398
-
399
-		if ($wasGlobal && !$isGlobal) {
400
-			$this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
401
-		} elseif (!$wasGlobal && $isGlobal) {
402
-			$this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
403
-		}
404
-
405
-		$changedConfig = array_diff_assoc($updatedStorage->getBackendOptions(), $oldStorage->getBackendOptions());
406
-		$changedOptions = array_diff_assoc($updatedStorage->getMountOptions(), $oldStorage->getMountOptions());
407
-
408
-		foreach ($changedConfig as $key => $value) {
409
-			if ($value !== DefinitionParameter::UNMODIFIED_PLACEHOLDER) {
410
-				$this->dbConfig->setConfig($id, $key, $value);
411
-			}
412
-		}
413
-		foreach ($changedOptions as $key => $value) {
414
-			$this->dbConfig->setOption($id, $key, $value);
415
-		}
416
-
417
-		if ($updatedStorage->getMountPoint() !== $oldStorage->getMountPoint()) {
418
-			$this->dbConfig->setMountPoint($id, $updatedStorage->getMountPoint());
419
-		}
420
-
421
-		if ($updatedStorage->getAuthMechanism()->getIdentifier() !== $oldStorage->getAuthMechanism()->getIdentifier()) {
422
-			$this->dbConfig->setAuthBackend($id, $updatedStorage->getAuthMechanism()->getIdentifier());
423
-		}
424
-
425
-		$this->triggerChangeHooks($oldStorage, $updatedStorage);
426
-
427
-		if (($wasGlobal && !$isGlobal) || count($removedGroups) > 0) { // to expensive to properly handle these on the fly
428
-			$this->userMountCache->remoteStorageMounts($this->getStorageId($updatedStorage));
429
-		} else {
430
-			$storageId = $this->getStorageId($updatedStorage);
431
-			foreach ($removedUsers as $userId) {
432
-				$this->userMountCache->removeUserStorageMount($storageId, $userId);
433
-			}
434
-		}
435
-
436
-		$this->updateOverwriteHomeFolders();
437
-
438
-		return $this->getStorage($id);
439
-	}
440
-
441
-	/**
442
-	 * Delete the storage with the given id.
443
-	 *
444
-	 * @param int $id storage id
445
-	 *
446
-	 * @throws NotFoundException if no storage was found with the given id
447
-	 */
448
-	public function removeStorage(int $id) {
449
-		$existingMount = $this->dbConfig->getMountById($id);
450
-
451
-		if (!is_array($existingMount)) {
452
-			throw new NotFoundException('Storage with ID "' . $id . '" not found');
453
-		}
454
-
455
-		$this->dbConfig->removeMount($id);
456
-
457
-		$deletedStorage = $this->getStorageConfigFromDBMount($existingMount);
458
-		$this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount);
459
-
460
-		// delete oc_storages entries and oc_filecache
461
-		Storage::cleanByMountId($id);
462
-
463
-		$this->updateOverwriteHomeFolders();
464
-	}
465
-
466
-	/**
467
-	 * Construct the storage implementation
468
-	 *
469
-	 * @param StorageConfig $storageConfig
470
-	 * @return int
471
-	 */
472
-	private function getStorageId(StorageConfig $storageConfig) {
473
-		try {
474
-			$class = $storageConfig->getBackend()->getStorageClass();
475
-			/** @var \OC\Files\Storage\Storage $storage */
476
-			$storage = new $class($storageConfig->getBackendOptions());
477
-
478
-			// auth mechanism should fire first
479
-			$storage = $storageConfig->getBackend()->wrapStorage($storage);
480
-			$storage = $storageConfig->getAuthMechanism()->wrapStorage($storage);
481
-
482
-			/** @var \OC\Files\Storage\Storage $storage */
483
-			return $storage->getStorageCache()->getNumericId();
484
-		} catch (\Exception $e) {
485
-			return -1;
486
-		}
487
-	}
488
-
489
-	public function updateOverwriteHomeFolders(): void {
490
-		$appIdsList = $this->appConfig->getValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS);
491
-
492
-		if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
493
-			if (!in_array(Application::APP_ID, $appIdsList)) {
494
-				$appIdsList[] = Application::APP_ID;
495
-				$this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
496
-			}
497
-		} else {
498
-			if (in_array(Application::APP_ID, $appIdsList)) {
499
-				$appIdsList = array_values(array_filter($appIdsList, fn ($v) => $v !== Application::APP_ID));
500
-				$this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
501
-			}
502
-		}
503
-	}
36
+    /**
37
+     * @param BackendService $backendService
38
+     * @param DBConfigService $dbConfig
39
+     * @param IUserMountCache $userMountCache
40
+     * @param IEventDispatcher $eventDispatcher
41
+     */
42
+    public function __construct(
43
+        protected BackendService $backendService,
44
+        protected DBConfigService $dbConfig,
45
+        protected IUserMountCache $userMountCache,
46
+        protected IEventDispatcher $eventDispatcher,
47
+        protected IAppConfig $appConfig,
48
+    ) {
49
+    }
50
+
51
+    protected function readDBConfig() {
52
+        return $this->dbConfig->getAdminMounts();
53
+    }
54
+
55
+    protected function getStorageConfigFromDBMount(array $mount) {
56
+        $applicableUsers = array_filter($mount['applicable'], function ($applicable) {
57
+            return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_USER;
58
+        });
59
+        $applicableUsers = array_map(function ($applicable) {
60
+            return $applicable['value'];
61
+        }, $applicableUsers);
62
+
63
+        $applicableGroups = array_filter($mount['applicable'], function ($applicable) {
64
+            return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_GROUP;
65
+        });
66
+        $applicableGroups = array_map(function ($applicable) {
67
+            return $applicable['value'];
68
+        }, $applicableGroups);
69
+
70
+        try {
71
+            $config = $this->createStorage(
72
+                $mount['mount_point'],
73
+                $mount['storage_backend'],
74
+                $mount['auth_backend'],
75
+                $mount['config'],
76
+                $mount['options'],
77
+                array_values($applicableUsers),
78
+                array_values($applicableGroups),
79
+                $mount['priority']
80
+            );
81
+            $config->setType($mount['type']);
82
+            $config->setId((int)$mount['mount_id']);
83
+            return $config;
84
+        } catch (\UnexpectedValueException $e) {
85
+            // don't die if a storage backend doesn't exist
86
+            Server::get(LoggerInterface::class)->error('Could not load storage.', [
87
+                'app' => 'files_external',
88
+                'exception' => $e,
89
+            ]);
90
+            return null;
91
+        } catch (\InvalidArgumentException $e) {
92
+            Server::get(LoggerInterface::class)->error('Could not load storage.', [
93
+                'app' => 'files_external',
94
+                'exception' => $e,
95
+            ]);
96
+            return null;
97
+        }
98
+    }
99
+
100
+    /**
101
+     * Read the external storage config
102
+     *
103
+     * @return array map of storage id to storage config
104
+     */
105
+    protected function readConfig() {
106
+        $mounts = $this->readDBConfig();
107
+        $configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
108
+        $configs = array_filter($configs, function ($config) {
109
+            return $config instanceof StorageConfig;
110
+        });
111
+
112
+        $keys = array_map(function (StorageConfig $config) {
113
+            return $config->getId();
114
+        }, $configs);
115
+
116
+        return array_combine($keys, $configs);
117
+    }
118
+
119
+    /**
120
+     * Get a storage with status
121
+     *
122
+     * @param int $id storage id
123
+     *
124
+     * @return StorageConfig
125
+     * @throws NotFoundException if the storage with the given id was not found
126
+     */
127
+    public function getStorage(int $id) {
128
+        $mount = $this->dbConfig->getMountById($id);
129
+
130
+        if (!is_array($mount)) {
131
+            throw new NotFoundException('Storage with ID "' . $id . '" not found');
132
+        }
133
+
134
+        $config = $this->getStorageConfigFromDBMount($mount);
135
+        if ($this->isApplicable($config)) {
136
+            return $config;
137
+        } else {
138
+            throw new NotFoundException('Storage with ID "' . $id . '" not found');
139
+        }
140
+    }
141
+
142
+    /**
143
+     * Check whether this storage service should provide access to a storage
144
+     *
145
+     * @param StorageConfig $config
146
+     * @return bool
147
+     */
148
+    abstract protected function isApplicable(StorageConfig $config);
149
+
150
+    /**
151
+     * Gets all storages, valid or not
152
+     *
153
+     * @return StorageConfig[] array of storage configs
154
+     */
155
+    public function getAllStorages() {
156
+        return $this->readConfig();
157
+    }
158
+
159
+    /**
160
+     * Gets all valid storages
161
+     *
162
+     * @return StorageConfig[]
163
+     */
164
+    public function getStorages() {
165
+        return array_filter($this->getAllStorages(), [$this, 'validateStorage']);
166
+    }
167
+
168
+    /**
169
+     * Validate storage
170
+     * FIXME: De-duplicate with StoragesController::validate()
171
+     *
172
+     * @param StorageConfig $storage
173
+     * @return bool
174
+     */
175
+    protected function validateStorage(StorageConfig $storage) {
176
+        /** @var Backend */
177
+        $backend = $storage->getBackend();
178
+        /** @var AuthMechanism */
179
+        $authMechanism = $storage->getAuthMechanism();
180
+
181
+        if (!$backend->isVisibleFor($this->getVisibilityType())) {
182
+            // not permitted to use backend
183
+            return false;
184
+        }
185
+        if (!$authMechanism->isVisibleFor($this->getVisibilityType())) {
186
+            // not permitted to use auth mechanism
187
+            return false;
188
+        }
189
+
190
+        return true;
191
+    }
192
+
193
+    /**
194
+     * Get the visibility type for this controller, used in validation
195
+     *
196
+     * @return int BackendService::VISIBILITY_* constants
197
+     */
198
+    abstract public function getVisibilityType();
199
+
200
+    /**
201
+     * @return integer
202
+     */
203
+    protected function getType() {
204
+        return DBConfigService::MOUNT_TYPE_ADMIN;
205
+    }
206
+
207
+    /**
208
+     * Add new storage to the configuration
209
+     *
210
+     * @param StorageConfig $newStorage storage attributes
211
+     *
212
+     * @return StorageConfig storage config, with added id
213
+     */
214
+    public function addStorage(StorageConfig $newStorage) {
215
+        $allStorages = $this->readConfig();
216
+
217
+        $configId = $this->dbConfig->addMount(
218
+            $newStorage->getMountPoint(),
219
+            $newStorage->getBackend()->getIdentifier(),
220
+            $newStorage->getAuthMechanism()->getIdentifier(),
221
+            $newStorage->getPriority(),
222
+            $this->getType()
223
+        );
224
+
225
+        $newStorage->setId($configId);
226
+
227
+        foreach ($newStorage->getApplicableUsers() as $user) {
228
+            $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_USER, $user);
229
+        }
230
+        foreach ($newStorage->getApplicableGroups() as $group) {
231
+            $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
232
+        }
233
+        foreach ($newStorage->getBackendOptions() as $key => $value) {
234
+            $this->dbConfig->setConfig($configId, $key, $value);
235
+        }
236
+        foreach ($newStorage->getMountOptions() as $key => $value) {
237
+            $this->dbConfig->setOption($configId, $key, $value);
238
+        }
239
+
240
+        if (count($newStorage->getApplicableUsers()) === 0 && count($newStorage->getApplicableGroups()) === 0) {
241
+            $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
242
+        }
243
+
244
+        // add new storage
245
+        $allStorages[$configId] = $newStorage;
246
+
247
+        $this->triggerHooks($newStorage, Filesystem::signal_create_mount);
248
+
249
+        $newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS);
250
+
251
+        $this->updateOverwriteHomeFolders();
252
+
253
+        return $newStorage;
254
+    }
255
+
256
+    /**
257
+     * Create a storage from its parameters
258
+     *
259
+     * @param string $mountPoint storage mount point
260
+     * @param string $backendIdentifier backend identifier
261
+     * @param string $authMechanismIdentifier authentication mechanism identifier
262
+     * @param array $backendOptions backend-specific options
263
+     * @param array|null $mountOptions mount-specific options
264
+     * @param array|null $applicableUsers users for which to mount the storage
265
+     * @param array|null $applicableGroups groups for which to mount the storage
266
+     * @param int|null $priority priority
267
+     *
268
+     * @return StorageConfig
269
+     */
270
+    public function createStorage(
271
+        $mountPoint,
272
+        $backendIdentifier,
273
+        $authMechanismIdentifier,
274
+        $backendOptions,
275
+        $mountOptions = null,
276
+        $applicableUsers = null,
277
+        $applicableGroups = null,
278
+        $priority = null,
279
+    ) {
280
+        $backend = $this->backendService->getBackend($backendIdentifier);
281
+        if (!$backend) {
282
+            $backend = new InvalidBackend($backendIdentifier);
283
+        }
284
+        $authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
285
+        if (!$authMechanism) {
286
+            $authMechanism = new InvalidAuth($authMechanismIdentifier);
287
+        }
288
+        $newStorage = new StorageConfig();
289
+        $newStorage->setMountPoint($mountPoint);
290
+        $newStorage->setBackend($backend);
291
+        $newStorage->setAuthMechanism($authMechanism);
292
+        $newStorage->setBackendOptions($backendOptions);
293
+        if (isset($mountOptions)) {
294
+            $newStorage->setMountOptions($mountOptions);
295
+        }
296
+        if (isset($applicableUsers)) {
297
+            $newStorage->setApplicableUsers($applicableUsers);
298
+        }
299
+        if (isset($applicableGroups)) {
300
+            $newStorage->setApplicableGroups($applicableGroups);
301
+        }
302
+        if (isset($priority)) {
303
+            $newStorage->setPriority($priority);
304
+        }
305
+
306
+        return $newStorage;
307
+    }
308
+
309
+    /**
310
+     * Triggers the given hook signal for all the applicables given
311
+     *
312
+     * @param string $signal signal
313
+     * @param string $mountPoint hook mount point param
314
+     * @param string $mountType hook mount type param
315
+     * @param array $applicableArray array of applicable users/groups for which to trigger the hook
316
+     */
317
+    protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray): void {
318
+        $this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent(null));
319
+        foreach ($applicableArray as $applicable) {
320
+            Util::emitHook(
321
+                Filesystem::CLASSNAME,
322
+                $signal,
323
+                [
324
+                    Filesystem::signal_param_path => $mountPoint,
325
+                    Filesystem::signal_param_mount_type => $mountType,
326
+                    Filesystem::signal_param_users => $applicable,
327
+                ]
328
+            );
329
+        }
330
+    }
331
+
332
+    /**
333
+     * Triggers $signal for all applicable users of the given
334
+     * storage
335
+     *
336
+     * @param StorageConfig $storage storage data
337
+     * @param string $signal signal to trigger
338
+     */
339
+    abstract protected function triggerHooks(StorageConfig $storage, $signal);
340
+
341
+    /**
342
+     * Triggers signal_create_mount or signal_delete_mount to
343
+     * accommodate for additions/deletions in applicableUsers
344
+     * and applicableGroups fields.
345
+     *
346
+     * @param StorageConfig $oldStorage old storage data
347
+     * @param StorageConfig $newStorage new storage data
348
+     */
349
+    abstract protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage);
350
+
351
+    /**
352
+     * Update storage to the configuration
353
+     *
354
+     * @param StorageConfig $updatedStorage storage attributes
355
+     *
356
+     * @return StorageConfig storage config
357
+     * @throws NotFoundException if the given storage does not exist in the config
358
+     */
359
+    public function updateStorage(StorageConfig $updatedStorage) {
360
+        $id = $updatedStorage->getId();
361
+
362
+        $existingMount = $this->dbConfig->getMountById($id);
363
+
364
+        if (!is_array($existingMount)) {
365
+            throw new NotFoundException('Storage with ID "' . $id . '" not found while updating storage');
366
+        }
367
+
368
+        $oldStorage = $this->getStorageConfigFromDBMount($existingMount);
369
+
370
+        if ($oldStorage->getBackend() instanceof InvalidBackend) {
371
+            throw new NotFoundException('Storage with id "' . $id . '" cannot be edited due to missing backend');
372
+        }
373
+
374
+        $removedUsers = array_diff($oldStorage->getApplicableUsers(), $updatedStorage->getApplicableUsers());
375
+        $removedGroups = array_diff($oldStorage->getApplicableGroups(), $updatedStorage->getApplicableGroups());
376
+        $addedUsers = array_diff($updatedStorage->getApplicableUsers(), $oldStorage->getApplicableUsers());
377
+        $addedGroups = array_diff($updatedStorage->getApplicableGroups(), $oldStorage->getApplicableGroups());
378
+
379
+        $oldUserCount = count($oldStorage->getApplicableUsers());
380
+        $oldGroupCount = count($oldStorage->getApplicableGroups());
381
+        $newUserCount = count($updatedStorage->getApplicableUsers());
382
+        $newGroupCount = count($updatedStorage->getApplicableGroups());
383
+        $wasGlobal = ($oldUserCount + $oldGroupCount) === 0;
384
+        $isGlobal = ($newUserCount + $newGroupCount) === 0;
385
+
386
+        foreach ($removedUsers as $user) {
387
+            $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
388
+        }
389
+        foreach ($removedGroups as $group) {
390
+            $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
391
+        }
392
+        foreach ($addedUsers as $user) {
393
+            $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user);
394
+        }
395
+        foreach ($addedGroups as $group) {
396
+            $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group);
397
+        }
398
+
399
+        if ($wasGlobal && !$isGlobal) {
400
+            $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
401
+        } elseif (!$wasGlobal && $isGlobal) {
402
+            $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
403
+        }
404
+
405
+        $changedConfig = array_diff_assoc($updatedStorage->getBackendOptions(), $oldStorage->getBackendOptions());
406
+        $changedOptions = array_diff_assoc($updatedStorage->getMountOptions(), $oldStorage->getMountOptions());
407
+
408
+        foreach ($changedConfig as $key => $value) {
409
+            if ($value !== DefinitionParameter::UNMODIFIED_PLACEHOLDER) {
410
+                $this->dbConfig->setConfig($id, $key, $value);
411
+            }
412
+        }
413
+        foreach ($changedOptions as $key => $value) {
414
+            $this->dbConfig->setOption($id, $key, $value);
415
+        }
416
+
417
+        if ($updatedStorage->getMountPoint() !== $oldStorage->getMountPoint()) {
418
+            $this->dbConfig->setMountPoint($id, $updatedStorage->getMountPoint());
419
+        }
420
+
421
+        if ($updatedStorage->getAuthMechanism()->getIdentifier() !== $oldStorage->getAuthMechanism()->getIdentifier()) {
422
+            $this->dbConfig->setAuthBackend($id, $updatedStorage->getAuthMechanism()->getIdentifier());
423
+        }
424
+
425
+        $this->triggerChangeHooks($oldStorage, $updatedStorage);
426
+
427
+        if (($wasGlobal && !$isGlobal) || count($removedGroups) > 0) { // to expensive to properly handle these on the fly
428
+            $this->userMountCache->remoteStorageMounts($this->getStorageId($updatedStorage));
429
+        } else {
430
+            $storageId = $this->getStorageId($updatedStorage);
431
+            foreach ($removedUsers as $userId) {
432
+                $this->userMountCache->removeUserStorageMount($storageId, $userId);
433
+            }
434
+        }
435
+
436
+        $this->updateOverwriteHomeFolders();
437
+
438
+        return $this->getStorage($id);
439
+    }
440
+
441
+    /**
442
+     * Delete the storage with the given id.
443
+     *
444
+     * @param int $id storage id
445
+     *
446
+     * @throws NotFoundException if no storage was found with the given id
447
+     */
448
+    public function removeStorage(int $id) {
449
+        $existingMount = $this->dbConfig->getMountById($id);
450
+
451
+        if (!is_array($existingMount)) {
452
+            throw new NotFoundException('Storage with ID "' . $id . '" not found');
453
+        }
454
+
455
+        $this->dbConfig->removeMount($id);
456
+
457
+        $deletedStorage = $this->getStorageConfigFromDBMount($existingMount);
458
+        $this->triggerHooks($deletedStorage, Filesystem::signal_delete_mount);
459
+
460
+        // delete oc_storages entries and oc_filecache
461
+        Storage::cleanByMountId($id);
462
+
463
+        $this->updateOverwriteHomeFolders();
464
+    }
465
+
466
+    /**
467
+     * Construct the storage implementation
468
+     *
469
+     * @param StorageConfig $storageConfig
470
+     * @return int
471
+     */
472
+    private function getStorageId(StorageConfig $storageConfig) {
473
+        try {
474
+            $class = $storageConfig->getBackend()->getStorageClass();
475
+            /** @var \OC\Files\Storage\Storage $storage */
476
+            $storage = new $class($storageConfig->getBackendOptions());
477
+
478
+            // auth mechanism should fire first
479
+            $storage = $storageConfig->getBackend()->wrapStorage($storage);
480
+            $storage = $storageConfig->getAuthMechanism()->wrapStorage($storage);
481
+
482
+            /** @var \OC\Files\Storage\Storage $storage */
483
+            return $storage->getStorageCache()->getNumericId();
484
+        } catch (\Exception $e) {
485
+            return -1;
486
+        }
487
+    }
488
+
489
+    public function updateOverwriteHomeFolders(): void {
490
+        $appIdsList = $this->appConfig->getValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS);
491
+
492
+        if ($this->dbConfig->hasHomeFolderOverwriteMount()) {
493
+            if (!in_array(Application::APP_ID, $appIdsList)) {
494
+                $appIdsList[] = Application::APP_ID;
495
+                $this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
496
+            }
497
+        } else {
498
+            if (in_array(Application::APP_ID, $appIdsList)) {
499
+                $appIdsList = array_values(array_filter($appIdsList, fn ($v) => $v !== Application::APP_ID));
500
+                $this->appConfig->setValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS, $appIdsList);
501
+            }
502
+        }
503
+    }
504 504
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Service/UserStoragesService.php 1 patch
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -21,110 +21,110 @@
 block discarded – undo
21 21
  * (aka personal storages)
22 22
  */
23 23
 class UserStoragesService extends StoragesService {
24
-	use UserTrait;
24
+    use UserTrait;
25 25
 
26
-	/**
27
-	 * Create a user storages service
28
-	 */
29
-	public function __construct(
30
-		BackendService $backendService,
31
-		DBConfigService $dbConfig,
32
-		IUserSession $userSession,
33
-		IUserMountCache $userMountCache,
34
-		IEventDispatcher $eventDispatcher,
35
-		IAppConfig $appConfig,
36
-	) {
37
-		$this->userSession = $userSession;
38
-		parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
39
-	}
26
+    /**
27
+     * Create a user storages service
28
+     */
29
+    public function __construct(
30
+        BackendService $backendService,
31
+        DBConfigService $dbConfig,
32
+        IUserSession $userSession,
33
+        IUserMountCache $userMountCache,
34
+        IEventDispatcher $eventDispatcher,
35
+        IAppConfig $appConfig,
36
+    ) {
37
+        $this->userSession = $userSession;
38
+        parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
39
+    }
40 40
 
41
-	protected function readDBConfig() {
42
-		return $this->dbConfig->getUserMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
43
-	}
41
+    protected function readDBConfig() {
42
+        return $this->dbConfig->getUserMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
43
+    }
44 44
 
45
-	/**
46
-	 * Triggers $signal for all applicable users of the given
47
-	 * storage
48
-	 *
49
-	 * @param StorageConfig $storage storage data
50
-	 * @param string $signal signal to trigger
51
-	 */
52
-	protected function triggerHooks(StorageConfig $storage, $signal) {
53
-		$user = $this->getUser()->getUID();
45
+    /**
46
+     * Triggers $signal for all applicable users of the given
47
+     * storage
48
+     *
49
+     * @param StorageConfig $storage storage data
50
+     * @param string $signal signal to trigger
51
+     */
52
+    protected function triggerHooks(StorageConfig $storage, $signal) {
53
+        $user = $this->getUser()->getUID();
54 54
 
55
-		// trigger hook for the current user
56
-		$this->triggerApplicableHooks(
57
-			$signal,
58
-			$storage->getMountPoint(),
59
-			MountConfig::MOUNT_TYPE_USER,
60
-			[$user]
61
-		);
62
-	}
55
+        // trigger hook for the current user
56
+        $this->triggerApplicableHooks(
57
+            $signal,
58
+            $storage->getMountPoint(),
59
+            MountConfig::MOUNT_TYPE_USER,
60
+            [$user]
61
+        );
62
+    }
63 63
 
64
-	/**
65
-	 * Triggers signal_create_mount or signal_delete_mount to
66
-	 * accommodate for additions/deletions in applicableUsers
67
-	 * and applicableGroups fields.
68
-	 *
69
-	 * @param StorageConfig $oldStorage old storage data
70
-	 * @param StorageConfig $newStorage new storage data
71
-	 */
72
-	protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) {
73
-		// if mount point changed, it's like a deletion + creation
74
-		if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) {
75
-			$this->triggerHooks($oldStorage, Filesystem::signal_delete_mount);
76
-			$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
77
-		}
78
-	}
64
+    /**
65
+     * Triggers signal_create_mount or signal_delete_mount to
66
+     * accommodate for additions/deletions in applicableUsers
67
+     * and applicableGroups fields.
68
+     *
69
+     * @param StorageConfig $oldStorage old storage data
70
+     * @param StorageConfig $newStorage new storage data
71
+     */
72
+    protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) {
73
+        // if mount point changed, it's like a deletion + creation
74
+        if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) {
75
+            $this->triggerHooks($oldStorage, Filesystem::signal_delete_mount);
76
+            $this->triggerHooks($newStorage, Filesystem::signal_create_mount);
77
+        }
78
+    }
79 79
 
80
-	protected function getType() {
81
-		return DBConfigService::MOUNT_TYPE_PERSONAL;
82
-	}
80
+    protected function getType() {
81
+        return DBConfigService::MOUNT_TYPE_PERSONAL;
82
+    }
83 83
 
84
-	/**
85
-	 * Add new storage to the configuration
86
-	 *
87
-	 * @param StorageConfig $newStorage storage attributes
88
-	 *
89
-	 * @return StorageConfig storage config, with added id
90
-	 */
91
-	public function addStorage(StorageConfig $newStorage) {
92
-		$newStorage->setApplicableUsers([$this->getUser()->getUID()]);
93
-		return parent::addStorage($newStorage);
94
-	}
84
+    /**
85
+     * Add new storage to the configuration
86
+     *
87
+     * @param StorageConfig $newStorage storage attributes
88
+     *
89
+     * @return StorageConfig storage config, with added id
90
+     */
91
+    public function addStorage(StorageConfig $newStorage) {
92
+        $newStorage->setApplicableUsers([$this->getUser()->getUID()]);
93
+        return parent::addStorage($newStorage);
94
+    }
95 95
 
96
-	/**
97
-	 * Update storage to the configuration
98
-	 *
99
-	 * @param StorageConfig $updatedStorage storage attributes
100
-	 *
101
-	 * @return StorageConfig storage config
102
-	 * @throws NotFoundException if the given storage does not exist in the config
103
-	 */
104
-	public function updateStorage(StorageConfig $updatedStorage) {
105
-		// verify ownership through $this->isApplicable() and otherwise throws an exception
106
-		$this->getStorage($updatedStorage->getId());
96
+    /**
97
+     * Update storage to the configuration
98
+     *
99
+     * @param StorageConfig $updatedStorage storage attributes
100
+     *
101
+     * @return StorageConfig storage config
102
+     * @throws NotFoundException if the given storage does not exist in the config
103
+     */
104
+    public function updateStorage(StorageConfig $updatedStorage) {
105
+        // verify ownership through $this->isApplicable() and otherwise throws an exception
106
+        $this->getStorage($updatedStorage->getId());
107 107
 
108
-		$updatedStorage->setApplicableUsers([$this->getUser()->getUID()]);
109
-		return parent::updateStorage($updatedStorage);
110
-	}
108
+        $updatedStorage->setApplicableUsers([$this->getUser()->getUID()]);
109
+        return parent::updateStorage($updatedStorage);
110
+    }
111 111
 
112
-	/**
113
-	 * Get the visibility type for this controller, used in validation
114
-	 *
115
-	 * @return int BackendService::VISIBILITY_* constants
116
-	 */
117
-	public function getVisibilityType() {
118
-		return BackendService::VISIBILITY_PERSONAL;
119
-	}
112
+    /**
113
+     * Get the visibility type for this controller, used in validation
114
+     *
115
+     * @return int BackendService::VISIBILITY_* constants
116
+     */
117
+    public function getVisibilityType() {
118
+        return BackendService::VISIBILITY_PERSONAL;
119
+    }
120 120
 
121
-	protected function isApplicable(StorageConfig $config) {
122
-		return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAL;
123
-	}
121
+    protected function isApplicable(StorageConfig $config) {
122
+        return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAL;
123
+    }
124 124
 
125
-	public function removeStorage($id) {
126
-		// verify ownership through $this->isApplicable() and otherwise throws an exception
127
-		$this->getStorage($id);
128
-		parent::removeStorage($id);
129
-	}
125
+    public function removeStorage($id) {
126
+        // verify ownership through $this->isApplicable() and otherwise throws an exception
127
+        $this->getStorage($id);
128
+        parent::removeStorage($id);
129
+    }
130 130
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Service/UserGlobalStoragesService.php 1 patch
Indentation   +158 added lines, -158 removed lines patch added patch discarded remove patch
@@ -20,162 +20,162 @@
 block discarded – undo
20 20
  * Read-only access available, attempting to write will throw DomainException
21 21
  */
22 22
 class UserGlobalStoragesService extends GlobalStoragesService {
23
-	use UserTrait;
24
-
25
-	public function __construct(
26
-		BackendService $backendService,
27
-		DBConfigService $dbConfig,
28
-		IUserSession $userSession,
29
-		protected IGroupManager $groupManager,
30
-		IUserMountCache $userMountCache,
31
-		IEventDispatcher $eventDispatcher,
32
-		IAppConfig $appConfig,
33
-	) {
34
-		parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
35
-		$this->userSession = $userSession;
36
-	}
37
-
38
-	/**
39
-	 * Replace config hash ID with real IDs, for migrating legacy storages
40
-	 *
41
-	 * @param StorageConfig[] $storages Storages with real IDs
42
-	 * @param StorageConfig[] $storagesWithConfigHash Storages with config hash IDs
43
-	 */
44
-	protected function setRealStorageIds(array &$storages, array $storagesWithConfigHash) {
45
-		// as a read-only view, storage IDs don't need to be real
46
-		foreach ($storagesWithConfigHash as $storage) {
47
-			$storages[$storage->getId()] = $storage;
48
-		}
49
-	}
50
-
51
-	protected function readDBConfig() {
52
-		$userMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
53
-		$globalMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
54
-		$groups = $this->groupManager->getUserGroupIds($this->getUser());
55
-		if (count($groups) !== 0) {
56
-			$groupMounts = $this->dbConfig->getAdminMountsForMultiple(DBConfigService::APPLICABLE_TYPE_GROUP, $groups);
57
-		} else {
58
-			$groupMounts = [];
59
-		}
60
-		return array_merge($userMounts, $groupMounts, $globalMounts);
61
-	}
62
-
63
-	public function addStorage(StorageConfig $newStorage) {
64
-		throw new \DomainException('UserGlobalStoragesService writing disallowed');
65
-	}
66
-
67
-	public function updateStorage(StorageConfig $updatedStorage) {
68
-		throw new \DomainException('UserGlobalStoragesService writing disallowed');
69
-	}
70
-
71
-	/**
72
-	 * @param integer $id
73
-	 */
74
-	public function removeStorage($id) {
75
-		throw new \DomainException('UserGlobalStoragesService writing disallowed');
76
-	}
77
-
78
-	/**
79
-	 * Get unique storages, in case two are defined with the same mountpoint
80
-	 * Higher priority storages take precedence
81
-	 *
82
-	 * @return StorageConfig[]
83
-	 */
84
-	public function getUniqueStorages() {
85
-		$storages = $this->getStorages();
86
-
87
-		$storagesByMountpoint = [];
88
-		foreach ($storages as $storage) {
89
-			$storagesByMountpoint[$storage->getMountPoint()][] = $storage;
90
-		}
91
-
92
-		$result = [];
93
-		foreach ($storagesByMountpoint as $storageList) {
94
-			$storage = array_reduce($storageList, function ($carry, $item) {
95
-				if (isset($carry)) {
96
-					$carryPriorityType = $this->getPriorityType($carry);
97
-					$itemPriorityType = $this->getPriorityType($item);
98
-					if ($carryPriorityType > $itemPriorityType) {
99
-						return $carry;
100
-					} elseif ($carryPriorityType === $itemPriorityType) {
101
-						if ($carry->getPriority() > $item->getPriority()) {
102
-							return $carry;
103
-						}
104
-					}
105
-				}
106
-				return $item;
107
-			});
108
-			$result[$storage->getID()] = $storage;
109
-		}
110
-
111
-		return $result;
112
-	}
113
-
114
-	/**
115
-	 * Get a priority 'type', where a bigger number means higher priority
116
-	 * user applicable > group applicable > 'all'
117
-	 *
118
-	 * @param StorageConfig $storage
119
-	 * @return int
120
-	 */
121
-	protected function getPriorityType(StorageConfig $storage) {
122
-		$applicableUsers = $storage->getApplicableUsers();
123
-		$applicableGroups = $storage->getApplicableGroups();
124
-
125
-		if ($applicableUsers && $applicableUsers[0] !== 'all') {
126
-			return 2;
127
-		}
128
-		if ($applicableGroups) {
129
-			return 1;
130
-		}
131
-		return 0;
132
-	}
133
-
134
-	protected function isApplicable(StorageConfig $config) {
135
-		$applicableUsers = $config->getApplicableUsers();
136
-		$applicableGroups = $config->getApplicableGroups();
137
-
138
-		if (count($applicableUsers) === 0 && count($applicableGroups) === 0) {
139
-			return true;
140
-		}
141
-		if (in_array($this->getUser()->getUID(), $applicableUsers, true)) {
142
-			return true;
143
-		}
144
-		$groupIds = $this->groupManager->getUserGroupIds($this->getUser());
145
-		foreach ($groupIds as $groupId) {
146
-			if (in_array($groupId, $applicableGroups, true)) {
147
-				return true;
148
-			}
149
-		}
150
-		return false;
151
-	}
152
-
153
-
154
-	/**
155
-	 * Gets all storages for the user, admin, personal, global, etc
156
-	 *
157
-	 * @param IUser|null $user user to get the storages for, if not set the currently logged in user will be used
158
-	 * @return StorageConfig[] array of storage configs
159
-	 */
160
-	public function getAllStoragesForUser(?IUser $user = null) {
161
-		if (is_null($user)) {
162
-			$user = $this->getUser();
163
-		}
164
-		if (is_null($user)) {
165
-			return [];
166
-		}
167
-		$groupIds = $this->groupManager->getUserGroupIds($user);
168
-		$mounts = $this->dbConfig->getMountsForUser($user->getUID(), $groupIds);
169
-		$configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
170
-		$configs = array_filter($configs, function ($config) {
171
-			return $config instanceof StorageConfig;
172
-		});
173
-
174
-		$keys = array_map(function (StorageConfig $config) {
175
-			return $config->getId();
176
-		}, $configs);
177
-
178
-		$storages = array_combine($keys, $configs);
179
-		return array_filter($storages, [$this, 'validateStorage']);
180
-	}
23
+    use UserTrait;
24
+
25
+    public function __construct(
26
+        BackendService $backendService,
27
+        DBConfigService $dbConfig,
28
+        IUserSession $userSession,
29
+        protected IGroupManager $groupManager,
30
+        IUserMountCache $userMountCache,
31
+        IEventDispatcher $eventDispatcher,
32
+        IAppConfig $appConfig,
33
+    ) {
34
+        parent::__construct($backendService, $dbConfig, $userMountCache, $eventDispatcher, $appConfig);
35
+        $this->userSession = $userSession;
36
+    }
37
+
38
+    /**
39
+     * Replace config hash ID with real IDs, for migrating legacy storages
40
+     *
41
+     * @param StorageConfig[] $storages Storages with real IDs
42
+     * @param StorageConfig[] $storagesWithConfigHash Storages with config hash IDs
43
+     */
44
+    protected function setRealStorageIds(array &$storages, array $storagesWithConfigHash) {
45
+        // as a read-only view, storage IDs don't need to be real
46
+        foreach ($storagesWithConfigHash as $storage) {
47
+            $storages[$storage->getId()] = $storage;
48
+        }
49
+    }
50
+
51
+    protected function readDBConfig() {
52
+        $userMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID());
53
+        $globalMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null);
54
+        $groups = $this->groupManager->getUserGroupIds($this->getUser());
55
+        if (count($groups) !== 0) {
56
+            $groupMounts = $this->dbConfig->getAdminMountsForMultiple(DBConfigService::APPLICABLE_TYPE_GROUP, $groups);
57
+        } else {
58
+            $groupMounts = [];
59
+        }
60
+        return array_merge($userMounts, $groupMounts, $globalMounts);
61
+    }
62
+
63
+    public function addStorage(StorageConfig $newStorage) {
64
+        throw new \DomainException('UserGlobalStoragesService writing disallowed');
65
+    }
66
+
67
+    public function updateStorage(StorageConfig $updatedStorage) {
68
+        throw new \DomainException('UserGlobalStoragesService writing disallowed');
69
+    }
70
+
71
+    /**
72
+     * @param integer $id
73
+     */
74
+    public function removeStorage($id) {
75
+        throw new \DomainException('UserGlobalStoragesService writing disallowed');
76
+    }
77
+
78
+    /**
79
+     * Get unique storages, in case two are defined with the same mountpoint
80
+     * Higher priority storages take precedence
81
+     *
82
+     * @return StorageConfig[]
83
+     */
84
+    public function getUniqueStorages() {
85
+        $storages = $this->getStorages();
86
+
87
+        $storagesByMountpoint = [];
88
+        foreach ($storages as $storage) {
89
+            $storagesByMountpoint[$storage->getMountPoint()][] = $storage;
90
+        }
91
+
92
+        $result = [];
93
+        foreach ($storagesByMountpoint as $storageList) {
94
+            $storage = array_reduce($storageList, function ($carry, $item) {
95
+                if (isset($carry)) {
96
+                    $carryPriorityType = $this->getPriorityType($carry);
97
+                    $itemPriorityType = $this->getPriorityType($item);
98
+                    if ($carryPriorityType > $itemPriorityType) {
99
+                        return $carry;
100
+                    } elseif ($carryPriorityType === $itemPriorityType) {
101
+                        if ($carry->getPriority() > $item->getPriority()) {
102
+                            return $carry;
103
+                        }
104
+                    }
105
+                }
106
+                return $item;
107
+            });
108
+            $result[$storage->getID()] = $storage;
109
+        }
110
+
111
+        return $result;
112
+    }
113
+
114
+    /**
115
+     * Get a priority 'type', where a bigger number means higher priority
116
+     * user applicable > group applicable > 'all'
117
+     *
118
+     * @param StorageConfig $storage
119
+     * @return int
120
+     */
121
+    protected function getPriorityType(StorageConfig $storage) {
122
+        $applicableUsers = $storage->getApplicableUsers();
123
+        $applicableGroups = $storage->getApplicableGroups();
124
+
125
+        if ($applicableUsers && $applicableUsers[0] !== 'all') {
126
+            return 2;
127
+        }
128
+        if ($applicableGroups) {
129
+            return 1;
130
+        }
131
+        return 0;
132
+    }
133
+
134
+    protected function isApplicable(StorageConfig $config) {
135
+        $applicableUsers = $config->getApplicableUsers();
136
+        $applicableGroups = $config->getApplicableGroups();
137
+
138
+        if (count($applicableUsers) === 0 && count($applicableGroups) === 0) {
139
+            return true;
140
+        }
141
+        if (in_array($this->getUser()->getUID(), $applicableUsers, true)) {
142
+            return true;
143
+        }
144
+        $groupIds = $this->groupManager->getUserGroupIds($this->getUser());
145
+        foreach ($groupIds as $groupId) {
146
+            if (in_array($groupId, $applicableGroups, true)) {
147
+                return true;
148
+            }
149
+        }
150
+        return false;
151
+    }
152
+
153
+
154
+    /**
155
+     * Gets all storages for the user, admin, personal, global, etc
156
+     *
157
+     * @param IUser|null $user user to get the storages for, if not set the currently logged in user will be used
158
+     * @return StorageConfig[] array of storage configs
159
+     */
160
+    public function getAllStoragesForUser(?IUser $user = null) {
161
+        if (is_null($user)) {
162
+            $user = $this->getUser();
163
+        }
164
+        if (is_null($user)) {
165
+            return [];
166
+        }
167
+        $groupIds = $this->groupManager->getUserGroupIds($user);
168
+        $mounts = $this->dbConfig->getMountsForUser($user->getUID(), $groupIds);
169
+        $configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
170
+        $configs = array_filter($configs, function ($config) {
171
+            return $config instanceof StorageConfig;
172
+        });
173
+
174
+        $keys = array_map(function (StorageConfig $config) {
175
+            return $config->getId();
176
+        }, $configs);
177
+
178
+        $storages = array_combine($keys, $configs);
179
+        return array_filter($storages, [$this, 'validateStorage']);
180
+    }
181 181
 }
Please login to merge, or discard this patch.
apps/files_external/lib/Service/DBConfigService.php 1 patch
Indentation   +504 added lines, -504 removed lines patch added patch discarded remove patch
@@ -17,508 +17,508 @@
 block discarded – undo
17 17
  * Stores the mount config in the database
18 18
  */
19 19
 class DBConfigService {
20
-	public const MOUNT_TYPE_ADMIN = 1;
21
-	public const MOUNT_TYPE_PERSONAL = 2;
22
-	/** @deprecated use MOUNT_TYPE_PERSONAL (full uppercase) instead */
23
-	public const MOUNT_TYPE_PERSONAl = 2;
24
-
25
-	public const APPLICABLE_TYPE_GLOBAL = 1;
26
-	public const APPLICABLE_TYPE_GROUP = 2;
27
-	public const APPLICABLE_TYPE_USER = 3;
28
-
29
-	public function __construct(
30
-		private IDBConnection $connection,
31
-		private ICrypto $crypto,
32
-	) {
33
-	}
34
-
35
-	public function getMountById(int $mountId): ?array {
36
-		$builder = $this->connection->getQueryBuilder();
37
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
38
-			->from('external_mounts', 'm')
39
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
40
-		$mounts = $this->getMountsFromQuery($query);
41
-		if (count($mounts) > 0) {
42
-			return $mounts[0];
43
-		} else {
44
-			return null;
45
-		}
46
-	}
47
-
48
-	/**
49
-	 * Get all configured mounts
50
-	 *
51
-	 * @return array
52
-	 */
53
-	public function getAllMounts() {
54
-		$builder = $this->connection->getQueryBuilder();
55
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
56
-			->from('external_mounts');
57
-		return $this->getMountsFromQuery($query);
58
-	}
59
-
60
-	public function getMountsForUser($userId, $groupIds) {
61
-		$builder = $this->connection->getQueryBuilder();
62
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
63
-			->from('external_mounts', 'm')
64
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
65
-			->where($builder->expr()->orX(
66
-				$builder->expr()->andX( // global mounts
67
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
68
-					$builder->expr()->isNull('a.value'),
69
-				),
70
-				$builder->expr()->andX( // mounts for user
71
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
72
-					$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
73
-				),
74
-				$builder->expr()->andX( // mounts for group
75
-					$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
76
-					$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
77
-				),
78
-			));
79
-
80
-		return $this->getMountsFromQuery($query);
81
-	}
82
-
83
-	public function modifyMountsOnUserDelete(string $uid): void {
84
-		$this->modifyMountsOnDelete($uid, self::APPLICABLE_TYPE_USER);
85
-	}
86
-
87
-	public function modifyMountsOnGroupDelete(string $gid): void {
88
-		$this->modifyMountsOnDelete($gid, self::APPLICABLE_TYPE_GROUP);
89
-	}
90
-
91
-	protected function modifyMountsOnDelete(string $applicableId, int $applicableType): void {
92
-		$builder = $this->connection->getQueryBuilder();
93
-		$query = $builder->select(['a.mount_id', $builder->func()->count('a.mount_id', 'count')])
94
-			->from('external_applicable', 'a')
95
-			->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id'))
96
-			->where($builder->expr()->andX(
97
-				$builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)),
98
-				$builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)),
99
-			),
100
-			)
101
-			->groupBy(['a.mount_id']);
102
-		$stmt = $query->executeQuery();
103
-		$result = $stmt->fetchAll();
104
-		$stmt->closeCursor();
105
-
106
-		foreach ($result as $row) {
107
-			if ((int)$row['count'] > 1) {
108
-				$this->removeApplicable($row['mount_id'], $applicableType, $applicableId);
109
-			} else {
110
-				$this->removeMount($row['mount_id']);
111
-			}
112
-		}
113
-	}
114
-
115
-	/**
116
-	 * Get admin defined mounts
117
-	 *
118
-	 * @return array
119
-	 */
120
-	public function getAdminMounts() {
121
-		$builder = $this->connection->getQueryBuilder();
122
-		$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
123
-			->from('external_mounts')
124
-			->where($builder->expr()->eq('type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
125
-		return $this->getMountsFromQuery($query);
126
-	}
127
-
128
-	protected function getForQuery(IQueryBuilder $builder, $type, $value) {
129
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
130
-			->from('external_mounts', 'm')
131
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
132
-			->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
133
-
134
-		if (is_null($value)) {
135
-			$query = $query->andWhere($builder->expr()->isNull('a.value'));
136
-		} else {
137
-			$query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
138
-		}
139
-
140
-		return $query;
141
-	}
142
-
143
-	/**
144
-	 * Get mounts by applicable
145
-	 *
146
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
147
-	 * @param string|null $value user_id, group_id or null for global mounts
148
-	 * @return array
149
-	 */
150
-	public function getMountsFor($type, $value) {
151
-		$builder = $this->connection->getQueryBuilder();
152
-		$query = $this->getForQuery($builder, $type, $value);
153
-
154
-		return $this->getMountsFromQuery($query);
155
-	}
156
-
157
-	/**
158
-	 * Get admin defined mounts by applicable
159
-	 *
160
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
161
-	 * @param string|null $value user_id, group_id or null for global mounts
162
-	 * @return array
163
-	 */
164
-	public function getAdminMountsFor($type, $value) {
165
-		$builder = $this->connection->getQueryBuilder();
166
-		$query = $this->getForQuery($builder, $type, $value);
167
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
168
-
169
-		return $this->getMountsFromQuery($query);
170
-	}
171
-
172
-	/**
173
-	 * Get admin defined mounts for multiple applicable
174
-	 *
175
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
176
-	 * @param string[] $values user_ids or group_ids
177
-	 * @return array
178
-	 */
179
-	public function getAdminMountsForMultiple($type, array $values) {
180
-		$builder = $this->connection->getQueryBuilder();
181
-		$params = array_map(function ($value) use ($builder) {
182
-			return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
183
-		}, $values);
184
-
185
-		$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
186
-			->from('external_mounts', 'm')
187
-			->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
188
-			->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
189
-			->andWhere($builder->expr()->in('a.value', $params));
190
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
191
-
192
-		return $this->getMountsFromQuery($query);
193
-	}
194
-
195
-	/**
196
-	 * Get user defined mounts by applicable
197
-	 *
198
-	 * @param int $type any of the self::APPLICABLE_TYPE_ constants
199
-	 * @param string|null $value user_id, group_id or null for global mounts
200
-	 * @return array
201
-	 */
202
-	public function getUserMountsFor($type, $value) {
203
-		$builder = $this->connection->getQueryBuilder();
204
-		$query = $this->getForQuery($builder, $type, $value);
205
-		$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAL, IQueryBuilder::PARAM_INT)));
206
-
207
-		return $this->getMountsFromQuery($query);
208
-	}
209
-
210
-	/**
211
-	 * Add a mount to the database
212
-	 *
213
-	 * @param string $mountPoint
214
-	 * @param string $storageBackend
215
-	 * @param string $authBackend
216
-	 * @param int $priority
217
-	 * @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
218
-	 * @return int the id of the new mount
219
-	 */
220
-	public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
221
-		if (!$priority) {
222
-			$priority = 100;
223
-		}
224
-		$builder = $this->connection->getQueryBuilder();
225
-		$query = $builder->insert('external_mounts')
226
-			->values([
227
-				'mount_point' => $builder->createNamedParameter($mountPoint, IQueryBuilder::PARAM_STR),
228
-				'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
229
-				'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
230
-				'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
231
-				'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT),
232
-			]);
233
-		$query->executeStatement();
234
-		return $query->getLastInsertId();
235
-	}
236
-
237
-	/**
238
-	 * Remove a mount from the database
239
-	 *
240
-	 * @param int $mountId
241
-	 */
242
-	public function removeMount($mountId) {
243
-		$builder = $this->connection->getQueryBuilder();
244
-		$query = $builder->delete('external_mounts')
245
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
246
-		$query->executeStatement();
247
-
248
-		$builder = $this->connection->getQueryBuilder();
249
-		$query = $builder->delete('external_applicable')
250
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
251
-		$query->executeStatement();
252
-
253
-		$builder = $this->connection->getQueryBuilder();
254
-		$query = $builder->delete('external_config')
255
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
256
-		$query->executeStatement();
257
-
258
-		$builder = $this->connection->getQueryBuilder();
259
-		$query = $builder->delete('external_options')
260
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
261
-		$query->executeStatement();
262
-	}
263
-
264
-	/**
265
-	 * @param int $mountId
266
-	 * @param string $newMountPoint
267
-	 */
268
-	public function setMountPoint($mountId, $newMountPoint) {
269
-		$builder = $this->connection->getQueryBuilder();
270
-
271
-		$query = $builder->update('external_mounts')
272
-			->set('mount_point', $builder->createNamedParameter($newMountPoint))
273
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
274
-
275
-		$query->executeStatement();
276
-	}
277
-
278
-	/**
279
-	 * @param int $mountId
280
-	 * @param string $newAuthBackend
281
-	 */
282
-	public function setAuthBackend($mountId, $newAuthBackend) {
283
-		$builder = $this->connection->getQueryBuilder();
284
-
285
-		$query = $builder->update('external_mounts')
286
-			->set('auth_backend', $builder->createNamedParameter($newAuthBackend))
287
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
288
-
289
-		$query->executeStatement();
290
-	}
291
-
292
-	/**
293
-	 * @param int $mountId
294
-	 * @param string $key
295
-	 * @param string $value
296
-	 */
297
-	public function setConfig($mountId, $key, $value) {
298
-		if ($key === 'password') {
299
-			$value = $this->encryptValue($value);
300
-		}
301
-
302
-		try {
303
-			$builder = $this->connection->getQueryBuilder();
304
-			$builder->insert('external_config')
305
-				->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))
306
-				->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))
307
-				->setValue('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
308
-				->executeStatement();
309
-		} catch (Exception $e) {
310
-			if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
311
-				throw $e;
312
-			}
313
-			$builder = $this->connection->getQueryBuilder();
314
-			$query = $builder->update('external_config')
315
-				->set('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
316
-				->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
317
-				->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
318
-			$query->executeStatement();
319
-		}
320
-	}
321
-
322
-	/**
323
-	 * @param int $mountId
324
-	 * @param string $key
325
-	 * @param string $value
326
-	 */
327
-	public function setOption($mountId, $key, $value) {
328
-		try {
329
-			$builder = $this->connection->getQueryBuilder();
330
-			$builder->insert('external_options')
331
-				->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))
332
-				->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))
333
-				->setValue('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
334
-				->executeStatement();
335
-		} catch (Exception $e) {
336
-			if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
337
-				throw $e;
338
-			}
339
-			$builder = $this->connection->getQueryBuilder();
340
-			$query = $builder->update('external_options')
341
-				->set('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
342
-				->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
343
-				->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
344
-			$query->executeStatement();
345
-		}
346
-	}
347
-
348
-	public function addApplicable($mountId, $type, $value) {
349
-		try {
350
-			$builder = $this->connection->getQueryBuilder();
351
-			$builder->insert('external_applicable')
352
-				->setValue('mount_id', $builder->createNamedParameter($mountId))
353
-				->setValue('type', $builder->createNamedParameter($type))
354
-				->setValue('value', $builder->createNamedParameter($value))
355
-				->executeStatement();
356
-		} catch (Exception $e) {
357
-			// applicable exists already
358
-			if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
359
-				throw $e;
360
-			}
361
-		}
362
-	}
363
-
364
-	public function removeApplicable($mountId, $type, $value) {
365
-		$builder = $this->connection->getQueryBuilder();
366
-		$query = $builder->delete('external_applicable')
367
-			->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
368
-			->andWhere($builder->expr()->eq('type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
369
-
370
-		if (is_null($value)) {
371
-			$query = $query->andWhere($builder->expr()->isNull('value'));
372
-		} else {
373
-			$query = $query->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)));
374
-		}
375
-
376
-		$query->executeStatement();
377
-	}
378
-
379
-	private function getMountsFromQuery(IQueryBuilder $query) {
380
-		$result = $query->executeQuery();
381
-		$mounts = $result->fetchAll();
382
-		$uniqueMounts = [];
383
-		foreach ($mounts as $mount) {
384
-			$id = $mount['mount_id'];
385
-			if (!isset($uniqueMounts[$id])) {
386
-				$uniqueMounts[$id] = $mount;
387
-			}
388
-		}
389
-		$uniqueMounts = array_values($uniqueMounts);
390
-
391
-		$mountIds = array_map(function ($mount) {
392
-			return $mount['mount_id'];
393
-		}, $uniqueMounts);
394
-		$mountIds = array_values(array_unique($mountIds));
395
-
396
-		$applicable = $this->getApplicableForMounts($mountIds);
397
-		$config = $this->getConfigForMounts($mountIds);
398
-		$options = $this->getOptionsForMounts($mountIds);
399
-
400
-		return array_map(function ($mount, $applicable, $config, $options) {
401
-			$mount['type'] = (int)$mount['type'];
402
-			$mount['priority'] = (int)$mount['priority'];
403
-			$mount['applicable'] = $applicable;
404
-			$mount['config'] = $config;
405
-			$mount['options'] = $options;
406
-			return $mount;
407
-		}, $uniqueMounts, $applicable, $config, $options);
408
-	}
409
-
410
-	/**
411
-	 * Get mount options from a table grouped by mount id
412
-	 *
413
-	 * @param string $table
414
-	 * @param string[] $fields
415
-	 * @param int[] $mountIds
416
-	 * @return array [$mountId => [['field1' => $value1, ...], ...], ...]
417
-	 */
418
-	private function selectForMounts($table, array $fields, array $mountIds) {
419
-		if (count($mountIds) === 0) {
420
-			return [];
421
-		}
422
-		$builder = $this->connection->getQueryBuilder();
423
-		$fields[] = 'mount_id';
424
-		$placeHolders = array_map(function ($id) use ($builder) {
425
-			return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
426
-		}, $mountIds);
427
-		$query = $builder->select($fields)
428
-			->from($table)
429
-			->where($builder->expr()->in('mount_id', $placeHolders));
430
-
431
-		$result = $query->executeQuery();
432
-		$rows = $result->fetchAll();
433
-		$result->closeCursor();
434
-
435
-		$result = [];
436
-		foreach ($mountIds as $mountId) {
437
-			$result[$mountId] = [];
438
-		}
439
-		foreach ($rows as $row) {
440
-			if (isset($row['type'])) {
441
-				$row['type'] = (int)$row['type'];
442
-			}
443
-			$result[$row['mount_id']][] = $row;
444
-		}
445
-		return $result;
446
-	}
447
-
448
-	/**
449
-	 * @param int[] $mountIds
450
-	 * @return array [$id => [['type' => $type, 'value' => $value], ...], ...]
451
-	 */
452
-	public function getApplicableForMounts($mountIds) {
453
-		return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
454
-	}
455
-
456
-	/**
457
-	 * @param int[] $mountIds
458
-	 * @return array [$id => ['key1' => $value1, ...], ...]
459
-	 */
460
-	public function getConfigForMounts($mountIds) {
461
-		$mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
462
-		return array_map([$this, 'createKeyValueMap'], $mountConfigs);
463
-	}
464
-
465
-	/**
466
-	 * @param int[] $mountIds
467
-	 * @return array [$id => ['key1' => $value1, ...], ...]
468
-	 */
469
-	public function getOptionsForMounts($mountIds) {
470
-		$mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
471
-		$optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
472
-		return array_map(function (array $options) {
473
-			return array_map(function ($option) {
474
-				return json_decode($option);
475
-			}, $options);
476
-		}, $optionsMap);
477
-	}
478
-
479
-	/**
480
-	 * @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
481
-	 * @return array ['key1' => $value1, ...]
482
-	 */
483
-	private function createKeyValueMap(array $keyValuePairs) {
484
-		$decryptedPairts = array_map(function ($pair) {
485
-			if ($pair['key'] === 'password') {
486
-				$pair['value'] = $this->decryptValue($pair['value']);
487
-			}
488
-			return $pair;
489
-		}, $keyValuePairs);
490
-		$keys = array_map(function ($pair) {
491
-			return $pair['key'];
492
-		}, $decryptedPairts);
493
-		$values = array_map(function ($pair) {
494
-			return $pair['value'];
495
-		}, $decryptedPairts);
496
-
497
-		return array_combine($keys, $values);
498
-	}
499
-
500
-	private function encryptValue($value) {
501
-		return $this->crypto->encrypt($value);
502
-	}
503
-
504
-	private function decryptValue($value) {
505
-		try {
506
-			return $this->crypto->decrypt($value);
507
-		} catch (\Exception $e) {
508
-			return $value;
509
-		}
510
-	}
511
-
512
-	/**
513
-	 * Check if any mountpoint is configured that overwrite the home folder
514
-	 */
515
-	public function hasHomeFolderOverwriteMount(): bool {
516
-		$builder = $this->connection->getQueryBuilder();
517
-		$query = $builder->select('mount_id')
518
-			->from('external_mounts')
519
-			->where($builder->expr()->eq('mount_point', $builder->createNamedParameter('/')))
520
-			->setMaxResults(1);
521
-		$result = $query->executeQuery();
522
-		return count($result->fetchAll()) > 0;
523
-	}
20
+    public const MOUNT_TYPE_ADMIN = 1;
21
+    public const MOUNT_TYPE_PERSONAL = 2;
22
+    /** @deprecated use MOUNT_TYPE_PERSONAL (full uppercase) instead */
23
+    public const MOUNT_TYPE_PERSONAl = 2;
24
+
25
+    public const APPLICABLE_TYPE_GLOBAL = 1;
26
+    public const APPLICABLE_TYPE_GROUP = 2;
27
+    public const APPLICABLE_TYPE_USER = 3;
28
+
29
+    public function __construct(
30
+        private IDBConnection $connection,
31
+        private ICrypto $crypto,
32
+    ) {
33
+    }
34
+
35
+    public function getMountById(int $mountId): ?array {
36
+        $builder = $this->connection->getQueryBuilder();
37
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
38
+            ->from('external_mounts', 'm')
39
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
40
+        $mounts = $this->getMountsFromQuery($query);
41
+        if (count($mounts) > 0) {
42
+            return $mounts[0];
43
+        } else {
44
+            return null;
45
+        }
46
+    }
47
+
48
+    /**
49
+     * Get all configured mounts
50
+     *
51
+     * @return array
52
+     */
53
+    public function getAllMounts() {
54
+        $builder = $this->connection->getQueryBuilder();
55
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
56
+            ->from('external_mounts');
57
+        return $this->getMountsFromQuery($query);
58
+    }
59
+
60
+    public function getMountsForUser($userId, $groupIds) {
61
+        $builder = $this->connection->getQueryBuilder();
62
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
63
+            ->from('external_mounts', 'm')
64
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
65
+            ->where($builder->expr()->orX(
66
+                $builder->expr()->andX( // global mounts
67
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
68
+                    $builder->expr()->isNull('a.value'),
69
+                ),
70
+                $builder->expr()->andX( // mounts for user
71
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
72
+                    $builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
73
+                ),
74
+                $builder->expr()->andX( // mounts for group
75
+                    $builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
76
+                    $builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
77
+                ),
78
+            ));
79
+
80
+        return $this->getMountsFromQuery($query);
81
+    }
82
+
83
+    public function modifyMountsOnUserDelete(string $uid): void {
84
+        $this->modifyMountsOnDelete($uid, self::APPLICABLE_TYPE_USER);
85
+    }
86
+
87
+    public function modifyMountsOnGroupDelete(string $gid): void {
88
+        $this->modifyMountsOnDelete($gid, self::APPLICABLE_TYPE_GROUP);
89
+    }
90
+
91
+    protected function modifyMountsOnDelete(string $applicableId, int $applicableType): void {
92
+        $builder = $this->connection->getQueryBuilder();
93
+        $query = $builder->select(['a.mount_id', $builder->func()->count('a.mount_id', 'count')])
94
+            ->from('external_applicable', 'a')
95
+            ->leftJoin('a', 'external_applicable', 'b', $builder->expr()->eq('a.mount_id', 'b.mount_id'))
96
+            ->where($builder->expr()->andX(
97
+                $builder->expr()->eq('b.type', $builder->createNamedParameter($applicableType, IQueryBuilder::PARAM_INT)),
98
+                $builder->expr()->eq('b.value', $builder->createNamedParameter($applicableId)),
99
+            ),
100
+            )
101
+            ->groupBy(['a.mount_id']);
102
+        $stmt = $query->executeQuery();
103
+        $result = $stmt->fetchAll();
104
+        $stmt->closeCursor();
105
+
106
+        foreach ($result as $row) {
107
+            if ((int)$row['count'] > 1) {
108
+                $this->removeApplicable($row['mount_id'], $applicableType, $applicableId);
109
+            } else {
110
+                $this->removeMount($row['mount_id']);
111
+            }
112
+        }
113
+    }
114
+
115
+    /**
116
+     * Get admin defined mounts
117
+     *
118
+     * @return array
119
+     */
120
+    public function getAdminMounts() {
121
+        $builder = $this->connection->getQueryBuilder();
122
+        $query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
123
+            ->from('external_mounts')
124
+            ->where($builder->expr()->eq('type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
125
+        return $this->getMountsFromQuery($query);
126
+    }
127
+
128
+    protected function getForQuery(IQueryBuilder $builder, $type, $value) {
129
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
130
+            ->from('external_mounts', 'm')
131
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
132
+            ->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
133
+
134
+        if (is_null($value)) {
135
+            $query = $query->andWhere($builder->expr()->isNull('a.value'));
136
+        } else {
137
+            $query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
138
+        }
139
+
140
+        return $query;
141
+    }
142
+
143
+    /**
144
+     * Get mounts by applicable
145
+     *
146
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
147
+     * @param string|null $value user_id, group_id or null for global mounts
148
+     * @return array
149
+     */
150
+    public function getMountsFor($type, $value) {
151
+        $builder = $this->connection->getQueryBuilder();
152
+        $query = $this->getForQuery($builder, $type, $value);
153
+
154
+        return $this->getMountsFromQuery($query);
155
+    }
156
+
157
+    /**
158
+     * Get admin defined mounts by applicable
159
+     *
160
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
161
+     * @param string|null $value user_id, group_id or null for global mounts
162
+     * @return array
163
+     */
164
+    public function getAdminMountsFor($type, $value) {
165
+        $builder = $this->connection->getQueryBuilder();
166
+        $query = $this->getForQuery($builder, $type, $value);
167
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
168
+
169
+        return $this->getMountsFromQuery($query);
170
+    }
171
+
172
+    /**
173
+     * Get admin defined mounts for multiple applicable
174
+     *
175
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
176
+     * @param string[] $values user_ids or group_ids
177
+     * @return array
178
+     */
179
+    public function getAdminMountsForMultiple($type, array $values) {
180
+        $builder = $this->connection->getQueryBuilder();
181
+        $params = array_map(function ($value) use ($builder) {
182
+            return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
183
+        }, $values);
184
+
185
+        $query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
186
+            ->from('external_mounts', 'm')
187
+            ->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
188
+            ->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
189
+            ->andWhere($builder->expr()->in('a.value', $params));
190
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
191
+
192
+        return $this->getMountsFromQuery($query);
193
+    }
194
+
195
+    /**
196
+     * Get user defined mounts by applicable
197
+     *
198
+     * @param int $type any of the self::APPLICABLE_TYPE_ constants
199
+     * @param string|null $value user_id, group_id or null for global mounts
200
+     * @return array
201
+     */
202
+    public function getUserMountsFor($type, $value) {
203
+        $builder = $this->connection->getQueryBuilder();
204
+        $query = $this->getForQuery($builder, $type, $value);
205
+        $query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAL, IQueryBuilder::PARAM_INT)));
206
+
207
+        return $this->getMountsFromQuery($query);
208
+    }
209
+
210
+    /**
211
+     * Add a mount to the database
212
+     *
213
+     * @param string $mountPoint
214
+     * @param string $storageBackend
215
+     * @param string $authBackend
216
+     * @param int $priority
217
+     * @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
218
+     * @return int the id of the new mount
219
+     */
220
+    public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
221
+        if (!$priority) {
222
+            $priority = 100;
223
+        }
224
+        $builder = $this->connection->getQueryBuilder();
225
+        $query = $builder->insert('external_mounts')
226
+            ->values([
227
+                'mount_point' => $builder->createNamedParameter($mountPoint, IQueryBuilder::PARAM_STR),
228
+                'storage_backend' => $builder->createNamedParameter($storageBackend, IQueryBuilder::PARAM_STR),
229
+                'auth_backend' => $builder->createNamedParameter($authBackend, IQueryBuilder::PARAM_STR),
230
+                'priority' => $builder->createNamedParameter($priority, IQueryBuilder::PARAM_INT),
231
+                'type' => $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT),
232
+            ]);
233
+        $query->executeStatement();
234
+        return $query->getLastInsertId();
235
+    }
236
+
237
+    /**
238
+     * Remove a mount from the database
239
+     *
240
+     * @param int $mountId
241
+     */
242
+    public function removeMount($mountId) {
243
+        $builder = $this->connection->getQueryBuilder();
244
+        $query = $builder->delete('external_mounts')
245
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
246
+        $query->executeStatement();
247
+
248
+        $builder = $this->connection->getQueryBuilder();
249
+        $query = $builder->delete('external_applicable')
250
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
251
+        $query->executeStatement();
252
+
253
+        $builder = $this->connection->getQueryBuilder();
254
+        $query = $builder->delete('external_config')
255
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
256
+        $query->executeStatement();
257
+
258
+        $builder = $this->connection->getQueryBuilder();
259
+        $query = $builder->delete('external_options')
260
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
261
+        $query->executeStatement();
262
+    }
263
+
264
+    /**
265
+     * @param int $mountId
266
+     * @param string $newMountPoint
267
+     */
268
+    public function setMountPoint($mountId, $newMountPoint) {
269
+        $builder = $this->connection->getQueryBuilder();
270
+
271
+        $query = $builder->update('external_mounts')
272
+            ->set('mount_point', $builder->createNamedParameter($newMountPoint))
273
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
274
+
275
+        $query->executeStatement();
276
+    }
277
+
278
+    /**
279
+     * @param int $mountId
280
+     * @param string $newAuthBackend
281
+     */
282
+    public function setAuthBackend($mountId, $newAuthBackend) {
283
+        $builder = $this->connection->getQueryBuilder();
284
+
285
+        $query = $builder->update('external_mounts')
286
+            ->set('auth_backend', $builder->createNamedParameter($newAuthBackend))
287
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
288
+
289
+        $query->executeStatement();
290
+    }
291
+
292
+    /**
293
+     * @param int $mountId
294
+     * @param string $key
295
+     * @param string $value
296
+     */
297
+    public function setConfig($mountId, $key, $value) {
298
+        if ($key === 'password') {
299
+            $value = $this->encryptValue($value);
300
+        }
301
+
302
+        try {
303
+            $builder = $this->connection->getQueryBuilder();
304
+            $builder->insert('external_config')
305
+                ->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))
306
+                ->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))
307
+                ->setValue('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
308
+                ->executeStatement();
309
+        } catch (Exception $e) {
310
+            if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
311
+                throw $e;
312
+            }
313
+            $builder = $this->connection->getQueryBuilder();
314
+            $query = $builder->update('external_config')
315
+                ->set('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR))
316
+                ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
317
+                ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
318
+            $query->executeStatement();
319
+        }
320
+    }
321
+
322
+    /**
323
+     * @param int $mountId
324
+     * @param string $key
325
+     * @param string $value
326
+     */
327
+    public function setOption($mountId, $key, $value) {
328
+        try {
329
+            $builder = $this->connection->getQueryBuilder();
330
+            $builder->insert('external_options')
331
+                ->setValue('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))
332
+                ->setValue('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR))
333
+                ->setValue('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
334
+                ->executeStatement();
335
+        } catch (Exception $e) {
336
+            if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
337
+                throw $e;
338
+            }
339
+            $builder = $this->connection->getQueryBuilder();
340
+            $query = $builder->update('external_options')
341
+                ->set('value', $builder->createNamedParameter(json_encode($value), IQueryBuilder::PARAM_STR))
342
+                ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
343
+                ->andWhere($builder->expr()->eq('key', $builder->createNamedParameter($key, IQueryBuilder::PARAM_STR)));
344
+            $query->executeStatement();
345
+        }
346
+    }
347
+
348
+    public function addApplicable($mountId, $type, $value) {
349
+        try {
350
+            $builder = $this->connection->getQueryBuilder();
351
+            $builder->insert('external_applicable')
352
+                ->setValue('mount_id', $builder->createNamedParameter($mountId))
353
+                ->setValue('type', $builder->createNamedParameter($type))
354
+                ->setValue('value', $builder->createNamedParameter($value))
355
+                ->executeStatement();
356
+        } catch (Exception $e) {
357
+            // applicable exists already
358
+            if ($e->getReason() !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
359
+                throw $e;
360
+            }
361
+        }
362
+    }
363
+
364
+    public function removeApplicable($mountId, $type, $value) {
365
+        $builder = $this->connection->getQueryBuilder();
366
+        $query = $builder->delete('external_applicable')
367
+            ->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
368
+            ->andWhere($builder->expr()->eq('type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
369
+
370
+        if (is_null($value)) {
371
+            $query = $query->andWhere($builder->expr()->isNull('value'));
372
+        } else {
373
+            $query = $query->andWhere($builder->expr()->eq('value', $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR)));
374
+        }
375
+
376
+        $query->executeStatement();
377
+    }
378
+
379
+    private function getMountsFromQuery(IQueryBuilder $query) {
380
+        $result = $query->executeQuery();
381
+        $mounts = $result->fetchAll();
382
+        $uniqueMounts = [];
383
+        foreach ($mounts as $mount) {
384
+            $id = $mount['mount_id'];
385
+            if (!isset($uniqueMounts[$id])) {
386
+                $uniqueMounts[$id] = $mount;
387
+            }
388
+        }
389
+        $uniqueMounts = array_values($uniqueMounts);
390
+
391
+        $mountIds = array_map(function ($mount) {
392
+            return $mount['mount_id'];
393
+        }, $uniqueMounts);
394
+        $mountIds = array_values(array_unique($mountIds));
395
+
396
+        $applicable = $this->getApplicableForMounts($mountIds);
397
+        $config = $this->getConfigForMounts($mountIds);
398
+        $options = $this->getOptionsForMounts($mountIds);
399
+
400
+        return array_map(function ($mount, $applicable, $config, $options) {
401
+            $mount['type'] = (int)$mount['type'];
402
+            $mount['priority'] = (int)$mount['priority'];
403
+            $mount['applicable'] = $applicable;
404
+            $mount['config'] = $config;
405
+            $mount['options'] = $options;
406
+            return $mount;
407
+        }, $uniqueMounts, $applicable, $config, $options);
408
+    }
409
+
410
+    /**
411
+     * Get mount options from a table grouped by mount id
412
+     *
413
+     * @param string $table
414
+     * @param string[] $fields
415
+     * @param int[] $mountIds
416
+     * @return array [$mountId => [['field1' => $value1, ...], ...], ...]
417
+     */
418
+    private function selectForMounts($table, array $fields, array $mountIds) {
419
+        if (count($mountIds) === 0) {
420
+            return [];
421
+        }
422
+        $builder = $this->connection->getQueryBuilder();
423
+        $fields[] = 'mount_id';
424
+        $placeHolders = array_map(function ($id) use ($builder) {
425
+            return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
426
+        }, $mountIds);
427
+        $query = $builder->select($fields)
428
+            ->from($table)
429
+            ->where($builder->expr()->in('mount_id', $placeHolders));
430
+
431
+        $result = $query->executeQuery();
432
+        $rows = $result->fetchAll();
433
+        $result->closeCursor();
434
+
435
+        $result = [];
436
+        foreach ($mountIds as $mountId) {
437
+            $result[$mountId] = [];
438
+        }
439
+        foreach ($rows as $row) {
440
+            if (isset($row['type'])) {
441
+                $row['type'] = (int)$row['type'];
442
+            }
443
+            $result[$row['mount_id']][] = $row;
444
+        }
445
+        return $result;
446
+    }
447
+
448
+    /**
449
+     * @param int[] $mountIds
450
+     * @return array [$id => [['type' => $type, 'value' => $value], ...], ...]
451
+     */
452
+    public function getApplicableForMounts($mountIds) {
453
+        return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
454
+    }
455
+
456
+    /**
457
+     * @param int[] $mountIds
458
+     * @return array [$id => ['key1' => $value1, ...], ...]
459
+     */
460
+    public function getConfigForMounts($mountIds) {
461
+        $mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
462
+        return array_map([$this, 'createKeyValueMap'], $mountConfigs);
463
+    }
464
+
465
+    /**
466
+     * @param int[] $mountIds
467
+     * @return array [$id => ['key1' => $value1, ...], ...]
468
+     */
469
+    public function getOptionsForMounts($mountIds) {
470
+        $mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
471
+        $optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
472
+        return array_map(function (array $options) {
473
+            return array_map(function ($option) {
474
+                return json_decode($option);
475
+            }, $options);
476
+        }, $optionsMap);
477
+    }
478
+
479
+    /**
480
+     * @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
481
+     * @return array ['key1' => $value1, ...]
482
+     */
483
+    private function createKeyValueMap(array $keyValuePairs) {
484
+        $decryptedPairts = array_map(function ($pair) {
485
+            if ($pair['key'] === 'password') {
486
+                $pair['value'] = $this->decryptValue($pair['value']);
487
+            }
488
+            return $pair;
489
+        }, $keyValuePairs);
490
+        $keys = array_map(function ($pair) {
491
+            return $pair['key'];
492
+        }, $decryptedPairts);
493
+        $values = array_map(function ($pair) {
494
+            return $pair['value'];
495
+        }, $decryptedPairts);
496
+
497
+        return array_combine($keys, $values);
498
+    }
499
+
500
+    private function encryptValue($value) {
501
+        return $this->crypto->encrypt($value);
502
+    }
503
+
504
+    private function decryptValue($value) {
505
+        try {
506
+            return $this->crypto->decrypt($value);
507
+        } catch (\Exception $e) {
508
+            return $value;
509
+        }
510
+    }
511
+
512
+    /**
513
+     * Check if any mountpoint is configured that overwrite the home folder
514
+     */
515
+    public function hasHomeFolderOverwriteMount(): bool {
516
+        $builder = $this->connection->getQueryBuilder();
517
+        $query = $builder->select('mount_id')
518
+            ->from('external_mounts')
519
+            ->where($builder->expr()->eq('mount_point', $builder->createNamedParameter('/')))
520
+            ->setMaxResults(1);
521
+        $result = $query->executeQuery();
522
+        return count($result->fetchAll()) > 0;
523
+    }
524 524
 }
Please login to merge, or discard this patch.
apps/files_external/tests/Service/StoragesServiceTestCase.php 1 patch
Indentation   +455 added lines, -455 removed lines patch added patch discarded remove patch
@@ -38,465 +38,465 @@
 block discarded – undo
38 38
 use PHPUnit\Framework\MockObject\MockObject;
39 39
 
40 40
 class CleaningDBConfig extends DBConfigService {
41
-	private array $mountIds = [];
42
-
43
-	public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
44
-		$id = parent::addMount($mountPoint, $storageBackend, $authBackend, $priority, $type); // TODO: Change the autogenerated stub
45
-		$this->mountIds[] = $id;
46
-		return $id;
47
-	}
48
-
49
-	public function clean() {
50
-		foreach ($this->mountIds as $id) {
51
-			$this->removeMount($id);
52
-		}
53
-	}
41
+    private array $mountIds = [];
42
+
43
+    public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
44
+        $id = parent::addMount($mountPoint, $storageBackend, $authBackend, $priority, $type); // TODO: Change the autogenerated stub
45
+        $this->mountIds[] = $id;
46
+        return $id;
47
+    }
48
+
49
+    public function clean() {
50
+        foreach ($this->mountIds as $id) {
51
+            $this->removeMount($id);
52
+        }
53
+    }
54 54
 }
55 55
 
56 56
 /**
57 57
  * @group DB
58 58
  */
59 59
 abstract class StoragesServiceTestCase extends \Test\TestCase {
60
-	protected StoragesService $service;
61
-	protected BackendService&MockObject $backendService;
62
-	protected string $dataDir;
63
-	protected CleaningDBConfig $dbConfig;
64
-	protected static array $hookCalls;
65
-	protected IUserMountCache&MockObject $mountCache;
66
-	protected IEventDispatcher&MockObject $eventDispatcher;
67
-	protected IAppConfig&MockObject $appConfig;
68
-
69
-	protected function setUp(): void {
70
-		parent::setUp();
71
-		$this->dbConfig = new CleaningDBConfig(Server::get(IDBConnection::class), Server::get(ICrypto::class));
72
-		self::$hookCalls = [];
73
-		$config = Server::get(IConfig::class);
74
-		$this->dataDir = $config->getSystemValue(
75
-			'datadirectory',
76
-			\OC::$SERVERROOT . '/data/'
77
-		);
78
-		MountConfig::$skipTest = true;
79
-
80
-		$this->mountCache = $this->createMock(IUserMountCache::class);
81
-		$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
82
-		$this->appConfig = $this->createMock(IAppConfig::class);
83
-
84
-		// prepare BackendService mock
85
-		$this->backendService = $this->createMock(BackendService::class);
86
-
87
-		$authMechanisms = [
88
-			'identifier:\Auth\Mechanism' => $this->getAuthMechMock('null', '\Auth\Mechanism'),
89
-			'identifier:\Other\Auth\Mechanism' => $this->getAuthMechMock('null', '\Other\Auth\Mechanism'),
90
-			'identifier:\OCA\Files_External\Lib\Auth\NullMechanism' => $this->getAuthMechMock(),
91
-		];
92
-		$this->backendService->method('getAuthMechanism')
93
-			->willReturnCallback(function ($class) use ($authMechanisms) {
94
-				if (isset($authMechanisms[$class])) {
95
-					return $authMechanisms[$class];
96
-				}
97
-				return null;
98
-			});
99
-		$this->backendService->method('getAuthMechanismsByScheme')
100
-			->willReturnCallback(function ($schemes) use ($authMechanisms) {
101
-				return array_filter($authMechanisms, function ($authMech) use ($schemes) {
102
-					return in_array($authMech->getScheme(), $schemes, true);
103
-				});
104
-			});
105
-		$this->backendService->method('getAuthMechanisms')
106
-			->willReturn($authMechanisms);
107
-
108
-		$sftpBackend = $this->getBackendMock('\OCA\Files_External\Lib\Backend\SFTP', '\OCA\Files_External\Lib\Storage\SFTP');
109
-		$backends = [
110
-			'identifier:\OCA\Files_External\Lib\Backend\DAV' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\DAV', '\OC\Files\Storage\DAV'),
111
-			'identifier:\OCA\Files_External\Lib\Backend\SMB' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\SMB', '\OCA\Files_External\Lib\Storage\SMB'),
112
-			'identifier:\OCA\Files_External\Lib\Backend\SFTP' => $sftpBackend,
113
-			'identifier:sftp_alias' => $sftpBackend,
114
-		];
115
-		$backends['identifier:\OCA\Files_External\Lib\Backend\SFTP']->method('getLegacyAuthMechanism')
116
-			->willReturn($authMechanisms['identifier:\Other\Auth\Mechanism']);
117
-		$this->backendService->method('getBackend')
118
-			->willReturnCallback(function ($backendClass) use ($backends) {
119
-				if (isset($backends[$backendClass])) {
120
-					return $backends[$backendClass];
121
-				}
122
-				return null;
123
-			});
124
-		$this->backendService->method('getBackends')
125
-			->willReturn($backends);
126
-		$this->overwriteService(BackendService::class, $this->backendService);
127
-
128
-		Util::connectHook(
129
-			Filesystem::CLASSNAME,
130
-			Filesystem::signal_create_mount,
131
-			get_class($this), 'createHookCallback');
132
-		Util::connectHook(
133
-			Filesystem::CLASSNAME,
134
-			Filesystem::signal_delete_mount,
135
-			get_class($this), 'deleteHookCallback');
136
-
137
-		$containerMock = $this->createMock(IAppContainer::class);
138
-		$containerMock->method('query')
139
-			->willReturnCallback(function ($name) {
140
-				if ($name === 'OCA\Files_External\Service\BackendService') {
141
-					return $this->backendService;
142
-				}
143
-			});
144
-	}
145
-
146
-	protected function tearDown(): void {
147
-		MountConfig::$skipTest = false;
148
-		self::$hookCalls = [];
149
-		if ($this->dbConfig) {
150
-			$this->dbConfig->clean();
151
-		}
152
-		parent::tearDown();
153
-	}
154
-
155
-	protected function getBackendMock($class = SMB::class, $storageClass = \OCA\Files_External\Lib\Storage\SMB::class) {
156
-		$backend = $this->createMock(Backend::class);
157
-		$backend->method('getStorageClass')
158
-			->willReturn($storageClass);
159
-		$backend->method('getIdentifier')
160
-			->willReturn('identifier:' . $class);
161
-		return $backend;
162
-	}
163
-
164
-	protected function getAuthMechMock($scheme = 'null', $class = NullMechanism::class) {
165
-		$authMech = $this->createMock(AuthMechanism::class);
166
-		$authMech->method('getScheme')
167
-			->willReturn($scheme);
168
-		$authMech->method('getIdentifier')
169
-			->willReturn('identifier:' . $class);
170
-
171
-		return $authMech;
172
-	}
173
-
174
-	/**
175
-	 * Creates a StorageConfig instance based on array data
176
-	 */
177
-	protected function makeStorageConfig(array $data): StorageConfig {
178
-		$storage = new StorageConfig();
179
-		if (isset($data['id'])) {
180
-			$storage->setId($data['id']);
181
-		}
182
-		$storage->setMountPoint($data['mountPoint']);
183
-		if (!isset($data['backend'])) {
184
-			// data providers are run before $this->backendService is initialised
185
-			// so $data['backend'] can be specified directly
186
-			$data['backend'] = $this->backendService->getBackend($data['backendIdentifier']);
187
-		}
188
-		if (!isset($data['backend'])) {
189
-			throw new \Exception('oops, no backend');
190
-		}
191
-		if (!isset($data['authMechanism'])) {
192
-			$data['authMechanism'] = $this->backendService->getAuthMechanism($data['authMechanismIdentifier']);
193
-		}
194
-		if (!isset($data['authMechanism'])) {
195
-			throw new \Exception('oops, no auth mechanism');
196
-		}
197
-		$storage->setBackend($data['backend']);
198
-		$storage->setAuthMechanism($data['authMechanism']);
199
-		$storage->setBackendOptions($data['backendOptions']);
200
-		if (isset($data['applicableUsers'])) {
201
-			$storage->setApplicableUsers($data['applicableUsers']);
202
-		}
203
-		if (isset($data['applicableGroups'])) {
204
-			$storage->setApplicableGroups($data['applicableGroups']);
205
-		}
206
-		if (isset($data['priority'])) {
207
-			$storage->setPriority($data['priority']);
208
-		}
209
-		if (isset($data['mountOptions'])) {
210
-			$storage->setMountOptions($data['mountOptions']);
211
-		}
212
-		return $storage;
213
-	}
214
-
215
-
216
-	protected function ActualNonExistingStorageTest() {
217
-		$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
218
-		$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
219
-		$storage = new StorageConfig(255);
220
-		$storage->setMountPoint('mountpoint');
221
-		$storage->setBackend($backend);
222
-		$storage->setAuthMechanism($authMechanism);
223
-		$this->service->updateStorage($storage);
224
-	}
225
-
226
-	public function testNonExistingStorage(): void {
227
-		$this->expectException(NotFoundException::class);
228
-
229
-		$this->ActualNonExistingStorageTest();
230
-	}
231
-
232
-	public static function deleteStorageDataProvider(): array {
233
-		return [
234
-			// regular case, can properly delete the oc_storages entry
235
-			[
236
-				[
237
-					'host' => 'example.com',
238
-					'user' => 'test',
239
-					'password' => 'testPassword',
240
-					'root' => 'someroot',
241
-				],
242
-				'webdav::[email protected]//someroot/'
243
-			],
244
-			[
245
-				[
246
-					'host' => 'example.com',
247
-					'user' => '$user',
248
-					'password' => 'testPassword',
249
-					'root' => 'someroot',
250
-				],
251
-				'webdav::[email protected]//someroot/'
252
-			],
253
-		];
254
-	}
255
-
256
-	#[\PHPUnit\Framework\Attributes\DataProvider('deleteStorageDataProvider')]
257
-	public function testDeleteStorage(array $backendOptions, string $rustyStorageId): void {
258
-		$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\DAV');
259
-		$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
260
-		$storage = new StorageConfig(255);
261
-		$storage->setMountPoint('mountpoint');
262
-		$storage->setBackend($backend);
263
-		$storage->setAuthMechanism($authMechanism);
264
-		$storage->setBackendOptions($backendOptions);
265
-
266
-		$newStorage = $this->service->addStorage($storage);
267
-		$id = $newStorage->getId();
268
-
269
-		// manually trigger storage entry because normally it happens on first
270
-		// access, which isn't possible within this test
271
-		$storageCache = new Storage($rustyStorageId, true, Server::get(IDBConnection::class));
272
-
273
-		/** @var IUserMountCache $mountCache */
274
-		$mountCache = Server::get(IUserMountCache::class);
275
-		$mountCache->clear();
276
-		$user = $this->createMock(IUser::class);
277
-		$user->method('getUID')->willReturn('test');
278
-		$cache = $this->createMock(ICache::class);
279
-		$storage = $this->createMock(IStorage::class);
280
-		$storage->method('getCache')->willReturn($cache);
281
-		$mount = $this->createMock(IMountPoint::class);
282
-		$mount->method('getStorage')
283
-			->willReturn($storage);
284
-		$mount->method('getStorageId')
285
-			->willReturn($rustyStorageId);
286
-		$mount->method('getNumericStorageId')
287
-			->willReturn($storageCache->getNumericId());
288
-		$mount->method('getStorageRootId')
289
-			->willReturn(1);
290
-		$mount->method('getMountPoint')
291
-			->willReturn('dummy');
292
-		$mount->method('getMountId')
293
-			->willReturn($id);
294
-		$mountCache->registerMounts($user, [
295
-			$mount
296
-		]);
297
-
298
-		// get numeric id for later check
299
-		$numericId = $storageCache->getNumericId();
300
-
301
-		$this->service->removeStorage($id);
302
-
303
-		$caught = false;
304
-		try {
305
-			$this->service->getStorage(1);
306
-		} catch (NotFoundException $e) {
307
-			$caught = true;
308
-		}
309
-
310
-		$this->assertTrue($caught);
311
-
312
-		// storage id was removed from oc_storages
313
-		$qb = Server::get(IDBConnection::class)->getQueryBuilder();
314
-		$storageCheckQuery = $qb->select('*')
315
-			->from('storages')
316
-			->where($qb->expr()->eq('numeric_id', $qb->expr()->literal($numericId)));
317
-
318
-		$result = $storageCheckQuery->execute();
319
-		$storages = $result->fetchAll();
320
-		$result->closeCursor();
321
-		$this->assertCount(0, $storages, 'expected 0 storages, got ' . json_encode($storages));
322
-	}
323
-
324
-	protected function actualDeletedUnexistingStorageTest() {
325
-		$this->service->removeStorage(255);
326
-	}
327
-
328
-	public function testDeleteUnexistingStorage(): void {
329
-		$this->expectException(NotFoundException::class);
330
-
331
-		$this->actualDeletedUnexistingStorageTest();
332
-	}
333
-
334
-	public function testCreateStorage(): void {
335
-		$mountPoint = 'mount';
336
-		$backendIdentifier = 'identifier:\OCA\Files_External\Lib\Backend\SMB';
337
-		$authMechanismIdentifier = 'identifier:\Auth\Mechanism';
338
-		$backendOptions = ['param' => 'foo', 'param2' => 'bar'];
339
-		$mountOptions = ['option' => 'foobar'];
340
-		$applicableUsers = ['user1', 'user2'];
341
-		$applicableGroups = ['group'];
342
-		$priority = 123;
343
-
344
-		$backend = $this->backendService->getBackend($backendIdentifier);
345
-		$authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
346
-
347
-		$storage = $this->service->createStorage(
348
-			$mountPoint,
349
-			$backendIdentifier,
350
-			$authMechanismIdentifier,
351
-			$backendOptions,
352
-			$mountOptions,
353
-			$applicableUsers,
354
-			$applicableGroups,
355
-			$priority
356
-		);
357
-
358
-		$this->assertEquals('/' . $mountPoint, $storage->getMountPoint());
359
-		$this->assertEquals($backend, $storage->getBackend());
360
-		$this->assertEquals($authMechanism, $storage->getAuthMechanism());
361
-		$this->assertEquals($backendOptions, $storage->getBackendOptions());
362
-		$this->assertEquals($mountOptions, $storage->getMountOptions());
363
-		$this->assertEquals($applicableUsers, $storage->getApplicableUsers());
364
-		$this->assertEquals($applicableGroups, $storage->getApplicableGroups());
365
-		$this->assertEquals($priority, $storage->getPriority());
366
-	}
367
-
368
-	public function testCreateStorageInvalidClass(): void {
369
-		$storage = $this->service->createStorage(
370
-			'mount',
371
-			'identifier:\OC\Not\A\Backend',
372
-			'identifier:\Auth\Mechanism',
373
-			[]
374
-		);
375
-		$this->assertInstanceOf(InvalidBackend::class, $storage->getBackend());
376
-	}
377
-
378
-	public function testCreateStorageInvalidAuthMechanismClass(): void {
379
-		$storage = $this->service->createStorage(
380
-			'mount',
381
-			'identifier:\OCA\Files_External\Lib\Backend\SMB',
382
-			'identifier:\Not\An\Auth\Mechanism',
383
-			[]
384
-		);
385
-		$this->assertInstanceOf(InvalidAuth::class, $storage->getAuthMechanism());
386
-	}
387
-
388
-	public function testGetStoragesBackendNotVisible(): void {
389
-		$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
390
-		$backend->expects($this->once())
391
-			->method('isVisibleFor')
392
-			->with($this->service->getVisibilityType())
393
-			->willReturn(false);
394
-		$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
395
-		$authMechanism->method('isVisibleFor')
396
-			->with($this->service->getVisibilityType())
397
-			->willReturn(true);
398
-
399
-		$storage = new StorageConfig(255);
400
-		$storage->setMountPoint('mountpoint');
401
-		$storage->setBackend($backend);
402
-		$storage->setAuthMechanism($authMechanism);
403
-		$storage->setBackendOptions(['password' => 'testPassword']);
404
-
405
-		$newStorage = $this->service->addStorage($storage);
406
-
407
-		$this->assertCount(1, $this->service->getAllStorages());
408
-		$this->assertEmpty($this->service->getStorages());
409
-	}
410
-
411
-	public function testGetStoragesAuthMechanismNotVisible(): void {
412
-		$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
413
-		$backend->method('isVisibleFor')
414
-			->with($this->service->getVisibilityType())
415
-			->willReturn(true);
416
-		$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
417
-		$authMechanism->expects($this->once())
418
-			->method('isVisibleFor')
419
-			->with($this->service->getVisibilityType())
420
-			->willReturn(false);
421
-
422
-		$storage = new StorageConfig(255);
423
-		$storage->setMountPoint('mountpoint');
424
-		$storage->setBackend($backend);
425
-		$storage->setAuthMechanism($authMechanism);
426
-		$storage->setBackendOptions(['password' => 'testPassword']);
427
-
428
-		$newStorage = $this->service->addStorage($storage);
429
-
430
-		$this->assertCount(1, $this->service->getAllStorages());
431
-		$this->assertEmpty($this->service->getStorages());
432
-	}
433
-
434
-	public static function createHookCallback($params): void {
435
-		self::$hookCalls[] = [
436
-			'signal' => Filesystem::signal_create_mount,
437
-			'params' => $params
438
-		];
439
-	}
440
-
441
-	public static function deleteHookCallback($params): void {
442
-		self::$hookCalls[] = [
443
-			'signal' => Filesystem::signal_delete_mount,
444
-			'params' => $params
445
-		];
446
-	}
447
-
448
-	/**
449
-	 * Asserts hook call
450
-	 *
451
-	 * @param array $callData hook call data to check
452
-	 * @param string $signal signal name
453
-	 * @param string $mountPath mount path
454
-	 * @param string $mountType mount type
455
-	 * @param string $applicable applicable users
456
-	 */
457
-	protected function assertHookCall($callData, $signal, $mountPath, $mountType, $applicable) {
458
-		$this->assertEquals($signal, $callData['signal']);
459
-		$params = $callData['params'];
460
-		$this->assertEquals(
461
-			$mountPath,
462
-			$params[Filesystem::signal_param_path]
463
-		);
464
-		$this->assertEquals(
465
-			$mountType,
466
-			$params[Filesystem::signal_param_mount_type]
467
-		);
468
-		$this->assertEquals(
469
-			$applicable,
470
-			$params[Filesystem::signal_param_users]
471
-		);
472
-	}
473
-
474
-	public function testUpdateStorageMountPoint(): void {
475
-		$backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
476
-		$authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
477
-
478
-		$storage = new StorageConfig();
479
-		$storage->setMountPoint('mountpoint');
480
-		$storage->setBackend($backend);
481
-		$storage->setAuthMechanism($authMechanism);
482
-		$storage->setBackendOptions(['password' => 'testPassword']);
483
-
484
-		$savedStorage = $this->service->addStorage($storage);
485
-
486
-		$newAuthMechanism = $this->backendService->getAuthMechanism('identifier:\Other\Auth\Mechanism');
487
-
488
-		$updatedStorage = new StorageConfig($savedStorage->getId());
489
-		$updatedStorage->setMountPoint('mountpoint2');
490
-		$updatedStorage->setBackend($backend);
491
-		$updatedStorage->setAuthMechanism($newAuthMechanism);
492
-		$updatedStorage->setBackendOptions(['password' => 'password2']);
493
-
494
-		$this->service->updateStorage($updatedStorage);
495
-
496
-		$savedStorage = $this->service->getStorage($updatedStorage->getId());
497
-
498
-		$this->assertEquals('/mountpoint2', $savedStorage->getMountPoint());
499
-		$this->assertEquals($newAuthMechanism, $savedStorage->getAuthMechanism());
500
-		$this->assertEquals('password2', $savedStorage->getBackendOption('password'));
501
-	}
60
+    protected StoragesService $service;
61
+    protected BackendService&MockObject $backendService;
62
+    protected string $dataDir;
63
+    protected CleaningDBConfig $dbConfig;
64
+    protected static array $hookCalls;
65
+    protected IUserMountCache&MockObject $mountCache;
66
+    protected IEventDispatcher&MockObject $eventDispatcher;
67
+    protected IAppConfig&MockObject $appConfig;
68
+
69
+    protected function setUp(): void {
70
+        parent::setUp();
71
+        $this->dbConfig = new CleaningDBConfig(Server::get(IDBConnection::class), Server::get(ICrypto::class));
72
+        self::$hookCalls = [];
73
+        $config = Server::get(IConfig::class);
74
+        $this->dataDir = $config->getSystemValue(
75
+            'datadirectory',
76
+            \OC::$SERVERROOT . '/data/'
77
+        );
78
+        MountConfig::$skipTest = true;
79
+
80
+        $this->mountCache = $this->createMock(IUserMountCache::class);
81
+        $this->eventDispatcher = $this->createMock(IEventDispatcher::class);
82
+        $this->appConfig = $this->createMock(IAppConfig::class);
83
+
84
+        // prepare BackendService mock
85
+        $this->backendService = $this->createMock(BackendService::class);
86
+
87
+        $authMechanisms = [
88
+            'identifier:\Auth\Mechanism' => $this->getAuthMechMock('null', '\Auth\Mechanism'),
89
+            'identifier:\Other\Auth\Mechanism' => $this->getAuthMechMock('null', '\Other\Auth\Mechanism'),
90
+            'identifier:\OCA\Files_External\Lib\Auth\NullMechanism' => $this->getAuthMechMock(),
91
+        ];
92
+        $this->backendService->method('getAuthMechanism')
93
+            ->willReturnCallback(function ($class) use ($authMechanisms) {
94
+                if (isset($authMechanisms[$class])) {
95
+                    return $authMechanisms[$class];
96
+                }
97
+                return null;
98
+            });
99
+        $this->backendService->method('getAuthMechanismsByScheme')
100
+            ->willReturnCallback(function ($schemes) use ($authMechanisms) {
101
+                return array_filter($authMechanisms, function ($authMech) use ($schemes) {
102
+                    return in_array($authMech->getScheme(), $schemes, true);
103
+                });
104
+            });
105
+        $this->backendService->method('getAuthMechanisms')
106
+            ->willReturn($authMechanisms);
107
+
108
+        $sftpBackend = $this->getBackendMock('\OCA\Files_External\Lib\Backend\SFTP', '\OCA\Files_External\Lib\Storage\SFTP');
109
+        $backends = [
110
+            'identifier:\OCA\Files_External\Lib\Backend\DAV' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\DAV', '\OC\Files\Storage\DAV'),
111
+            'identifier:\OCA\Files_External\Lib\Backend\SMB' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\SMB', '\OCA\Files_External\Lib\Storage\SMB'),
112
+            'identifier:\OCA\Files_External\Lib\Backend\SFTP' => $sftpBackend,
113
+            'identifier:sftp_alias' => $sftpBackend,
114
+        ];
115
+        $backends['identifier:\OCA\Files_External\Lib\Backend\SFTP']->method('getLegacyAuthMechanism')
116
+            ->willReturn($authMechanisms['identifier:\Other\Auth\Mechanism']);
117
+        $this->backendService->method('getBackend')
118
+            ->willReturnCallback(function ($backendClass) use ($backends) {
119
+                if (isset($backends[$backendClass])) {
120
+                    return $backends[$backendClass];
121
+                }
122
+                return null;
123
+            });
124
+        $this->backendService->method('getBackends')
125
+            ->willReturn($backends);
126
+        $this->overwriteService(BackendService::class, $this->backendService);
127
+
128
+        Util::connectHook(
129
+            Filesystem::CLASSNAME,
130
+            Filesystem::signal_create_mount,
131
+            get_class($this), 'createHookCallback');
132
+        Util::connectHook(
133
+            Filesystem::CLASSNAME,
134
+            Filesystem::signal_delete_mount,
135
+            get_class($this), 'deleteHookCallback');
136
+
137
+        $containerMock = $this->createMock(IAppContainer::class);
138
+        $containerMock->method('query')
139
+            ->willReturnCallback(function ($name) {
140
+                if ($name === 'OCA\Files_External\Service\BackendService') {
141
+                    return $this->backendService;
142
+                }
143
+            });
144
+    }
145
+
146
+    protected function tearDown(): void {
147
+        MountConfig::$skipTest = false;
148
+        self::$hookCalls = [];
149
+        if ($this->dbConfig) {
150
+            $this->dbConfig->clean();
151
+        }
152
+        parent::tearDown();
153
+    }
154
+
155
+    protected function getBackendMock($class = SMB::class, $storageClass = \OCA\Files_External\Lib\Storage\SMB::class) {
156
+        $backend = $this->createMock(Backend::class);
157
+        $backend->method('getStorageClass')
158
+            ->willReturn($storageClass);
159
+        $backend->method('getIdentifier')
160
+            ->willReturn('identifier:' . $class);
161
+        return $backend;
162
+    }
163
+
164
+    protected function getAuthMechMock($scheme = 'null', $class = NullMechanism::class) {
165
+        $authMech = $this->createMock(AuthMechanism::class);
166
+        $authMech->method('getScheme')
167
+            ->willReturn($scheme);
168
+        $authMech->method('getIdentifier')
169
+            ->willReturn('identifier:' . $class);
170
+
171
+        return $authMech;
172
+    }
173
+
174
+    /**
175
+     * Creates a StorageConfig instance based on array data
176
+     */
177
+    protected function makeStorageConfig(array $data): StorageConfig {
178
+        $storage = new StorageConfig();
179
+        if (isset($data['id'])) {
180
+            $storage->setId($data['id']);
181
+        }
182
+        $storage->setMountPoint($data['mountPoint']);
183
+        if (!isset($data['backend'])) {
184
+            // data providers are run before $this->backendService is initialised
185
+            // so $data['backend'] can be specified directly
186
+            $data['backend'] = $this->backendService->getBackend($data['backendIdentifier']);
187
+        }
188
+        if (!isset($data['backend'])) {
189
+            throw new \Exception('oops, no backend');
190
+        }
191
+        if (!isset($data['authMechanism'])) {
192
+            $data['authMechanism'] = $this->backendService->getAuthMechanism($data['authMechanismIdentifier']);
193
+        }
194
+        if (!isset($data['authMechanism'])) {
195
+            throw new \Exception('oops, no auth mechanism');
196
+        }
197
+        $storage->setBackend($data['backend']);
198
+        $storage->setAuthMechanism($data['authMechanism']);
199
+        $storage->setBackendOptions($data['backendOptions']);
200
+        if (isset($data['applicableUsers'])) {
201
+            $storage->setApplicableUsers($data['applicableUsers']);
202
+        }
203
+        if (isset($data['applicableGroups'])) {
204
+            $storage->setApplicableGroups($data['applicableGroups']);
205
+        }
206
+        if (isset($data['priority'])) {
207
+            $storage->setPriority($data['priority']);
208
+        }
209
+        if (isset($data['mountOptions'])) {
210
+            $storage->setMountOptions($data['mountOptions']);
211
+        }
212
+        return $storage;
213
+    }
214
+
215
+
216
+    protected function ActualNonExistingStorageTest() {
217
+        $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
218
+        $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
219
+        $storage = new StorageConfig(255);
220
+        $storage->setMountPoint('mountpoint');
221
+        $storage->setBackend($backend);
222
+        $storage->setAuthMechanism($authMechanism);
223
+        $this->service->updateStorage($storage);
224
+    }
225
+
226
+    public function testNonExistingStorage(): void {
227
+        $this->expectException(NotFoundException::class);
228
+
229
+        $this->ActualNonExistingStorageTest();
230
+    }
231
+
232
+    public static function deleteStorageDataProvider(): array {
233
+        return [
234
+            // regular case, can properly delete the oc_storages entry
235
+            [
236
+                [
237
+                    'host' => 'example.com',
238
+                    'user' => 'test',
239
+                    'password' => 'testPassword',
240
+                    'root' => 'someroot',
241
+                ],
242
+                'webdav::[email protected]//someroot/'
243
+            ],
244
+            [
245
+                [
246
+                    'host' => 'example.com',
247
+                    'user' => '$user',
248
+                    'password' => 'testPassword',
249
+                    'root' => 'someroot',
250
+                ],
251
+                'webdav::[email protected]//someroot/'
252
+            ],
253
+        ];
254
+    }
255
+
256
+    #[\PHPUnit\Framework\Attributes\DataProvider('deleteStorageDataProvider')]
257
+    public function testDeleteStorage(array $backendOptions, string $rustyStorageId): void {
258
+        $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\DAV');
259
+        $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
260
+        $storage = new StorageConfig(255);
261
+        $storage->setMountPoint('mountpoint');
262
+        $storage->setBackend($backend);
263
+        $storage->setAuthMechanism($authMechanism);
264
+        $storage->setBackendOptions($backendOptions);
265
+
266
+        $newStorage = $this->service->addStorage($storage);
267
+        $id = $newStorage->getId();
268
+
269
+        // manually trigger storage entry because normally it happens on first
270
+        // access, which isn't possible within this test
271
+        $storageCache = new Storage($rustyStorageId, true, Server::get(IDBConnection::class));
272
+
273
+        /** @var IUserMountCache $mountCache */
274
+        $mountCache = Server::get(IUserMountCache::class);
275
+        $mountCache->clear();
276
+        $user = $this->createMock(IUser::class);
277
+        $user->method('getUID')->willReturn('test');
278
+        $cache = $this->createMock(ICache::class);
279
+        $storage = $this->createMock(IStorage::class);
280
+        $storage->method('getCache')->willReturn($cache);
281
+        $mount = $this->createMock(IMountPoint::class);
282
+        $mount->method('getStorage')
283
+            ->willReturn($storage);
284
+        $mount->method('getStorageId')
285
+            ->willReturn($rustyStorageId);
286
+        $mount->method('getNumericStorageId')
287
+            ->willReturn($storageCache->getNumericId());
288
+        $mount->method('getStorageRootId')
289
+            ->willReturn(1);
290
+        $mount->method('getMountPoint')
291
+            ->willReturn('dummy');
292
+        $mount->method('getMountId')
293
+            ->willReturn($id);
294
+        $mountCache->registerMounts($user, [
295
+            $mount
296
+        ]);
297
+
298
+        // get numeric id for later check
299
+        $numericId = $storageCache->getNumericId();
300
+
301
+        $this->service->removeStorage($id);
302
+
303
+        $caught = false;
304
+        try {
305
+            $this->service->getStorage(1);
306
+        } catch (NotFoundException $e) {
307
+            $caught = true;
308
+        }
309
+
310
+        $this->assertTrue($caught);
311
+
312
+        // storage id was removed from oc_storages
313
+        $qb = Server::get(IDBConnection::class)->getQueryBuilder();
314
+        $storageCheckQuery = $qb->select('*')
315
+            ->from('storages')
316
+            ->where($qb->expr()->eq('numeric_id', $qb->expr()->literal($numericId)));
317
+
318
+        $result = $storageCheckQuery->execute();
319
+        $storages = $result->fetchAll();
320
+        $result->closeCursor();
321
+        $this->assertCount(0, $storages, 'expected 0 storages, got ' . json_encode($storages));
322
+    }
323
+
324
+    protected function actualDeletedUnexistingStorageTest() {
325
+        $this->service->removeStorage(255);
326
+    }
327
+
328
+    public function testDeleteUnexistingStorage(): void {
329
+        $this->expectException(NotFoundException::class);
330
+
331
+        $this->actualDeletedUnexistingStorageTest();
332
+    }
333
+
334
+    public function testCreateStorage(): void {
335
+        $mountPoint = 'mount';
336
+        $backendIdentifier = 'identifier:\OCA\Files_External\Lib\Backend\SMB';
337
+        $authMechanismIdentifier = 'identifier:\Auth\Mechanism';
338
+        $backendOptions = ['param' => 'foo', 'param2' => 'bar'];
339
+        $mountOptions = ['option' => 'foobar'];
340
+        $applicableUsers = ['user1', 'user2'];
341
+        $applicableGroups = ['group'];
342
+        $priority = 123;
343
+
344
+        $backend = $this->backendService->getBackend($backendIdentifier);
345
+        $authMechanism = $this->backendService->getAuthMechanism($authMechanismIdentifier);
346
+
347
+        $storage = $this->service->createStorage(
348
+            $mountPoint,
349
+            $backendIdentifier,
350
+            $authMechanismIdentifier,
351
+            $backendOptions,
352
+            $mountOptions,
353
+            $applicableUsers,
354
+            $applicableGroups,
355
+            $priority
356
+        );
357
+
358
+        $this->assertEquals('/' . $mountPoint, $storage->getMountPoint());
359
+        $this->assertEquals($backend, $storage->getBackend());
360
+        $this->assertEquals($authMechanism, $storage->getAuthMechanism());
361
+        $this->assertEquals($backendOptions, $storage->getBackendOptions());
362
+        $this->assertEquals($mountOptions, $storage->getMountOptions());
363
+        $this->assertEquals($applicableUsers, $storage->getApplicableUsers());
364
+        $this->assertEquals($applicableGroups, $storage->getApplicableGroups());
365
+        $this->assertEquals($priority, $storage->getPriority());
366
+    }
367
+
368
+    public function testCreateStorageInvalidClass(): void {
369
+        $storage = $this->service->createStorage(
370
+            'mount',
371
+            'identifier:\OC\Not\A\Backend',
372
+            'identifier:\Auth\Mechanism',
373
+            []
374
+        );
375
+        $this->assertInstanceOf(InvalidBackend::class, $storage->getBackend());
376
+    }
377
+
378
+    public function testCreateStorageInvalidAuthMechanismClass(): void {
379
+        $storage = $this->service->createStorage(
380
+            'mount',
381
+            'identifier:\OCA\Files_External\Lib\Backend\SMB',
382
+            'identifier:\Not\An\Auth\Mechanism',
383
+            []
384
+        );
385
+        $this->assertInstanceOf(InvalidAuth::class, $storage->getAuthMechanism());
386
+    }
387
+
388
+    public function testGetStoragesBackendNotVisible(): void {
389
+        $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
390
+        $backend->expects($this->once())
391
+            ->method('isVisibleFor')
392
+            ->with($this->service->getVisibilityType())
393
+            ->willReturn(false);
394
+        $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
395
+        $authMechanism->method('isVisibleFor')
396
+            ->with($this->service->getVisibilityType())
397
+            ->willReturn(true);
398
+
399
+        $storage = new StorageConfig(255);
400
+        $storage->setMountPoint('mountpoint');
401
+        $storage->setBackend($backend);
402
+        $storage->setAuthMechanism($authMechanism);
403
+        $storage->setBackendOptions(['password' => 'testPassword']);
404
+
405
+        $newStorage = $this->service->addStorage($storage);
406
+
407
+        $this->assertCount(1, $this->service->getAllStorages());
408
+        $this->assertEmpty($this->service->getStorages());
409
+    }
410
+
411
+    public function testGetStoragesAuthMechanismNotVisible(): void {
412
+        $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
413
+        $backend->method('isVisibleFor')
414
+            ->with($this->service->getVisibilityType())
415
+            ->willReturn(true);
416
+        $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
417
+        $authMechanism->expects($this->once())
418
+            ->method('isVisibleFor')
419
+            ->with($this->service->getVisibilityType())
420
+            ->willReturn(false);
421
+
422
+        $storage = new StorageConfig(255);
423
+        $storage->setMountPoint('mountpoint');
424
+        $storage->setBackend($backend);
425
+        $storage->setAuthMechanism($authMechanism);
426
+        $storage->setBackendOptions(['password' => 'testPassword']);
427
+
428
+        $newStorage = $this->service->addStorage($storage);
429
+
430
+        $this->assertCount(1, $this->service->getAllStorages());
431
+        $this->assertEmpty($this->service->getStorages());
432
+    }
433
+
434
+    public static function createHookCallback($params): void {
435
+        self::$hookCalls[] = [
436
+            'signal' => Filesystem::signal_create_mount,
437
+            'params' => $params
438
+        ];
439
+    }
440
+
441
+    public static function deleteHookCallback($params): void {
442
+        self::$hookCalls[] = [
443
+            'signal' => Filesystem::signal_delete_mount,
444
+            'params' => $params
445
+        ];
446
+    }
447
+
448
+    /**
449
+     * Asserts hook call
450
+     *
451
+     * @param array $callData hook call data to check
452
+     * @param string $signal signal name
453
+     * @param string $mountPath mount path
454
+     * @param string $mountType mount type
455
+     * @param string $applicable applicable users
456
+     */
457
+    protected function assertHookCall($callData, $signal, $mountPath, $mountType, $applicable) {
458
+        $this->assertEquals($signal, $callData['signal']);
459
+        $params = $callData['params'];
460
+        $this->assertEquals(
461
+            $mountPath,
462
+            $params[Filesystem::signal_param_path]
463
+        );
464
+        $this->assertEquals(
465
+            $mountType,
466
+            $params[Filesystem::signal_param_mount_type]
467
+        );
468
+        $this->assertEquals(
469
+            $applicable,
470
+            $params[Filesystem::signal_param_users]
471
+        );
472
+    }
473
+
474
+    public function testUpdateStorageMountPoint(): void {
475
+        $backend = $this->backendService->getBackend('identifier:\OCA\Files_External\Lib\Backend\SMB');
476
+        $authMechanism = $this->backendService->getAuthMechanism('identifier:\Auth\Mechanism');
477
+
478
+        $storage = new StorageConfig();
479
+        $storage->setMountPoint('mountpoint');
480
+        $storage->setBackend($backend);
481
+        $storage->setAuthMechanism($authMechanism);
482
+        $storage->setBackendOptions(['password' => 'testPassword']);
483
+
484
+        $savedStorage = $this->service->addStorage($storage);
485
+
486
+        $newAuthMechanism = $this->backendService->getAuthMechanism('identifier:\Other\Auth\Mechanism');
487
+
488
+        $updatedStorage = new StorageConfig($savedStorage->getId());
489
+        $updatedStorage->setMountPoint('mountpoint2');
490
+        $updatedStorage->setBackend($backend);
491
+        $updatedStorage->setAuthMechanism($newAuthMechanism);
492
+        $updatedStorage->setBackendOptions(['password' => 'password2']);
493
+
494
+        $this->service->updateStorage($updatedStorage);
495
+
496
+        $savedStorage = $this->service->getStorage($updatedStorage->getId());
497
+
498
+        $this->assertEquals('/mountpoint2', $savedStorage->getMountPoint());
499
+        $this->assertEquals($newAuthMechanism, $savedStorage->getAuthMechanism());
500
+        $this->assertEquals('password2', $savedStorage->getBackendOption('password'));
501
+    }
502 502
 }
Please login to merge, or discard this patch.