Passed
Push — master ( a40db9...fb5987 )
by Julius
14:20 queued 12s
created
lib/private/Files/SetupManager.php 2 patches
Indentation   +500 added lines, -500 removed lines patch added patch discarded remove patch
@@ -62,506 +62,506 @@
 block discarded – undo
62 62
 use Psr\Log\LoggerInterface;
63 63
 
64 64
 class SetupManager {
65
-	private bool $rootSetup = false;
66
-	private IEventLogger $eventLogger;
67
-	private MountProviderCollection $mountProviderCollection;
68
-	private IMountManager $mountManager;
69
-	private IUserManager $userManager;
70
-	// List of users for which at least one mount is setup
71
-	private array $setupUsers = [];
72
-	// List of users for which all mounts are setup
73
-	private array $setupUsersComplete = [];
74
-	/** @var array<string, string[]> */
75
-	private array $setupUserMountProviders = [];
76
-	private IEventDispatcher $eventDispatcher;
77
-	private IUserMountCache $userMountCache;
78
-	private ILockdownManager $lockdownManager;
79
-	private IUserSession $userSession;
80
-	private ICache $cache;
81
-	private LoggerInterface $logger;
82
-	private IConfig $config;
83
-	private bool $listeningForProviders;
84
-	private array $fullSetupRequired = [];
85
-
86
-	public function __construct(
87
-		IEventLogger $eventLogger,
88
-		MountProviderCollection $mountProviderCollection,
89
-		IMountManager $mountManager,
90
-		IUserManager $userManager,
91
-		IEventDispatcher $eventDispatcher,
92
-		IUserMountCache $userMountCache,
93
-		ILockdownManager $lockdownManager,
94
-		IUserSession $userSession,
95
-		ICacheFactory $cacheFactory,
96
-		LoggerInterface $logger,
97
-		IConfig $config
98
-	) {
99
-		$this->eventLogger = $eventLogger;
100
-		$this->mountProviderCollection = $mountProviderCollection;
101
-		$this->mountManager = $mountManager;
102
-		$this->userManager = $userManager;
103
-		$this->eventDispatcher = $eventDispatcher;
104
-		$this->userMountCache = $userMountCache;
105
-		$this->lockdownManager = $lockdownManager;
106
-		$this->logger = $logger;
107
-		$this->userSession = $userSession;
108
-		$this->cache = $cacheFactory->createDistributed('setupmanager::');
109
-		$this->listeningForProviders = false;
110
-		$this->config = $config;
111
-
112
-		$this->setupListeners();
113
-	}
114
-
115
-	private function isSetupStarted(IUser $user): bool {
116
-		return in_array($user->getUID(), $this->setupUsers, true);
117
-	}
118
-
119
-	public function isSetupComplete(IUser $user): bool {
120
-		return in_array($user->getUID(), $this->setupUsersComplete, true);
121
-	}
122
-
123
-	private function setupBuiltinWrappers() {
124
-		Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
125
-			if ($storage->instanceOfStorage(Common::class)) {
126
-				$storage->setMountOptions($mount->getOptions());
127
-			}
128
-			return $storage;
129
-		});
130
-
131
-		Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
132
-			if (!$mount->getOption('enable_sharing', true)) {
133
-				return new PermissionsMask([
134
-					'storage' => $storage,
135
-					'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
136
-				]);
137
-			}
138
-			return $storage;
139
-		});
140
-
141
-		// install storage availability wrapper, before most other wrappers
142
-		Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
143
-			if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
144
-				return new Availability(['storage' => $storage]);
145
-			}
146
-			return $storage;
147
-		});
148
-
149
-		Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
150
-			if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
151
-				return new Encoding(['storage' => $storage]);
152
-			}
153
-			return $storage;
154
-		});
155
-
156
-		Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
157
-			// set up quota for home storages, even for other users
158
-			// which can happen when using sharing
159
-
160
-			/**
161
-			 * @var Storage $storage
162
-			 */
163
-			if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
164
-				if (is_object($storage->getUser())) {
165
-					$quota = OC_Util::getUserQuota($storage->getUser());
166
-					if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
167
-						return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
168
-					}
169
-				}
170
-			}
171
-
172
-			return $storage;
173
-		});
174
-
175
-		Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
176
-			/*
65
+    private bool $rootSetup = false;
66
+    private IEventLogger $eventLogger;
67
+    private MountProviderCollection $mountProviderCollection;
68
+    private IMountManager $mountManager;
69
+    private IUserManager $userManager;
70
+    // List of users for which at least one mount is setup
71
+    private array $setupUsers = [];
72
+    // List of users for which all mounts are setup
73
+    private array $setupUsersComplete = [];
74
+    /** @var array<string, string[]> */
75
+    private array $setupUserMountProviders = [];
76
+    private IEventDispatcher $eventDispatcher;
77
+    private IUserMountCache $userMountCache;
78
+    private ILockdownManager $lockdownManager;
79
+    private IUserSession $userSession;
80
+    private ICache $cache;
81
+    private LoggerInterface $logger;
82
+    private IConfig $config;
83
+    private bool $listeningForProviders;
84
+    private array $fullSetupRequired = [];
85
+
86
+    public function __construct(
87
+        IEventLogger $eventLogger,
88
+        MountProviderCollection $mountProviderCollection,
89
+        IMountManager $mountManager,
90
+        IUserManager $userManager,
91
+        IEventDispatcher $eventDispatcher,
92
+        IUserMountCache $userMountCache,
93
+        ILockdownManager $lockdownManager,
94
+        IUserSession $userSession,
95
+        ICacheFactory $cacheFactory,
96
+        LoggerInterface $logger,
97
+        IConfig $config
98
+    ) {
99
+        $this->eventLogger = $eventLogger;
100
+        $this->mountProviderCollection = $mountProviderCollection;
101
+        $this->mountManager = $mountManager;
102
+        $this->userManager = $userManager;
103
+        $this->eventDispatcher = $eventDispatcher;
104
+        $this->userMountCache = $userMountCache;
105
+        $this->lockdownManager = $lockdownManager;
106
+        $this->logger = $logger;
107
+        $this->userSession = $userSession;
108
+        $this->cache = $cacheFactory->createDistributed('setupmanager::');
109
+        $this->listeningForProviders = false;
110
+        $this->config = $config;
111
+
112
+        $this->setupListeners();
113
+    }
114
+
115
+    private function isSetupStarted(IUser $user): bool {
116
+        return in_array($user->getUID(), $this->setupUsers, true);
117
+    }
118
+
119
+    public function isSetupComplete(IUser $user): bool {
120
+        return in_array($user->getUID(), $this->setupUsersComplete, true);
121
+    }
122
+
123
+    private function setupBuiltinWrappers() {
124
+        Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
125
+            if ($storage->instanceOfStorage(Common::class)) {
126
+                $storage->setMountOptions($mount->getOptions());
127
+            }
128
+            return $storage;
129
+        });
130
+
131
+        Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
132
+            if (!$mount->getOption('enable_sharing', true)) {
133
+                return new PermissionsMask([
134
+                    'storage' => $storage,
135
+                    'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
136
+                ]);
137
+            }
138
+            return $storage;
139
+        });
140
+
141
+        // install storage availability wrapper, before most other wrappers
142
+        Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
143
+            if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
144
+                return new Availability(['storage' => $storage]);
145
+            }
146
+            return $storage;
147
+        });
148
+
149
+        Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
150
+            if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
151
+                return new Encoding(['storage' => $storage]);
152
+            }
153
+            return $storage;
154
+        });
155
+
156
+        Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
157
+            // set up quota for home storages, even for other users
158
+            // which can happen when using sharing
159
+
160
+            /**
161
+             * @var Storage $storage
162
+             */
163
+            if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
164
+                if (is_object($storage->getUser())) {
165
+                    $quota = OC_Util::getUserQuota($storage->getUser());
166
+                    if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
167
+                        return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
168
+                    }
169
+                }
170
+            }
171
+
172
+            return $storage;
173
+        });
174
+
175
+        Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
176
+            /*
177 177
 			 * Do not allow any operations that modify the storage
178 178
 			 */
179
-			if ($mount->getOption('readonly', false)) {
180
-				return new PermissionsMask([
181
-					'storage' => $storage,
182
-					'mask' => Constants::PERMISSION_ALL & ~(
183
-							Constants::PERMISSION_UPDATE |
184
-							Constants::PERMISSION_CREATE |
185
-							Constants::PERMISSION_DELETE
186
-						),
187
-				]);
188
-			}
189
-			return $storage;
190
-		});
191
-	}
192
-
193
-	/**
194
-	 * Setup the full filesystem for the specified user
195
-	 */
196
-	public function setupForUser(IUser $user): void {
197
-		if ($this->isSetupComplete($user)) {
198
-			return;
199
-		}
200
-		$this->setupUsersComplete[] = $user->getUID();
201
-
202
-		if (!isset($this->setupUserMountProviders[$user->getUID()])) {
203
-			$this->setupUserMountProviders[$user->getUID()] = [];
204
-		}
205
-
206
-		$previouslySetupProviders = $this->setupUserMountProviders[$user->getUID()];
207
-
208
-		$this->setupForUserWith($user, function () use ($user) {
209
-			$this->mountProviderCollection->addMountForUser($user, $this->mountManager, function (
210
-				IMountProvider $provider
211
-			) use ($user) {
212
-				return !in_array(get_class($provider), $this->setupUserMountProviders[$user->getUID()]);
213
-			});
214
-		});
215
-		$this->afterUserFullySetup($user, $previouslySetupProviders);
216
-	}
217
-
218
-	/**
219
-	 * part of the user setup that is run only once per user
220
-	 */
221
-	private function oneTimeUserSetup(IUser $user) {
222
-		if (in_array($user->getUID(), $this->setupUsers, true)) {
223
-			return;
224
-		}
225
-		$this->setupUsers[] = $user->getUID();
226
-		$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
227
-
228
-		OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
229
-
230
-		Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
231
-
232
-		$userDir = '/' . $user->getUID() . '/files';
233
-
234
-		Filesystem::initInternal($userDir);
235
-
236
-		if ($this->lockdownManager->canAccessFilesystem()) {
237
-			// home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
238
-			$homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
239
-			$this->mountManager->addMount($homeMount);
240
-
241
-			if ($homeMount->getStorageRootId() === -1) {
242
-				$homeMount->getStorage()->mkdir('');
243
-				$homeMount->getStorage()->getScanner()->scan('');
244
-			}
245
-		} else {
246
-			$this->mountManager->addMount(new MountPoint(
247
-				new NullStorage([]),
248
-				'/' . $user->getUID()
249
-			));
250
-			$this->mountManager->addMount(new MountPoint(
251
-				new NullStorage([]),
252
-				'/' . $user->getUID() . '/files'
253
-			));
254
-			$this->setupUsersComplete[] = $user->getUID();
255
-		}
256
-
257
-		$this->listenForNewMountProviders();
258
-	}
259
-
260
-	/**
261
-	 * Final housekeeping after a user has been fully setup
262
-	 */
263
-	private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
264
-		$userRoot = '/' . $user->getUID() . '/';
265
-		$mounts = $this->mountManager->getAll();
266
-		$mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
267
-			return strpos($mount->getMountPoint(), $userRoot) === 0;
268
-		});
269
-		$allProviders = array_map(function (IMountProvider $provider) {
270
-			return get_class($provider);
271
-		}, $this->mountProviderCollection->getProviders());
272
-		$newProviders = array_diff($allProviders, $previouslySetupProviders);
273
-		$mounts = array_filter($mounts, function (IMountPoint $mount) use ($previouslySetupProviders) {
274
-			return !in_array($mount->getMountProvider(), $previouslySetupProviders);
275
-		});
276
-		$this->userMountCache->registerMounts($user, $mounts, $newProviders);
277
-
278
-		$cacheDuration = $this->config->getSystemValueInt('fs_mount_cache_duration', 5 * 60);
279
-		if ($cacheDuration > 0) {
280
-			$this->cache->set($user->getUID(), true, $cacheDuration);
281
-			$this->fullSetupRequired[$user->getUID()] = false;
282
-		}
283
-	}
284
-
285
-	/**
286
-	 * @param IUser $user
287
-	 * @param IMountPoint $mounts
288
-	 * @return void
289
-	 * @throws \OCP\HintException
290
-	 * @throws \OC\ServerNotAvailableException
291
-	 */
292
-	private function setupForUserWith(IUser $user, callable $mountCallback): void {
293
-		$this->setupRoot();
294
-
295
-		if (!$this->isSetupStarted($user)) {
296
-			$this->oneTimeUserSetup($user);
297
-		}
298
-
299
-		$this->eventLogger->start('setup_fs', 'Setup filesystem');
300
-
301
-		if ($this->lockdownManager->canAccessFilesystem()) {
302
-			$mountCallback();
303
-		}
304
-		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
305
-
306
-		$userDir = '/' . $user->getUID() . '/files';
307
-		OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
308
-
309
-		$this->eventLogger->end('setup_fs');
310
-	}
311
-
312
-	/**
313
-	 * Set up the root filesystem
314
-	 */
315
-	public function setupRoot(): void {
316
-		//setting up the filesystem twice can only lead to trouble
317
-		if ($this->rootSetup) {
318
-			return;
319
-		}
320
-		$this->rootSetup = true;
321
-
322
-		$this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
323
-
324
-		// load all filesystem apps before, so no setup-hook gets lost
325
-		OC_App::loadApps(['filesystem']);
326
-		$prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
327
-
328
-		$this->setupBuiltinWrappers();
329
-
330
-		Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
331
-
332
-		$rootMounts = $this->mountProviderCollection->getRootMounts();
333
-		foreach ($rootMounts as $rootMountProvider) {
334
-			$this->mountManager->addMount($rootMountProvider);
335
-		}
336
-
337
-		$this->eventLogger->end('setup_root_fs');
338
-	}
339
-
340
-	/**
341
-	 * Get the user to setup for a path or `null` if the root needs to be setup
342
-	 *
343
-	 * @param string $path
344
-	 * @return IUser|null
345
-	 */
346
-	private function getUserForPath(string $path) {
347
-		if (substr_count($path, '/') < 2) {
348
-			if ($user = $this->userSession->getUser()) {
349
-				return $user;
350
-			} else {
351
-				return null;
352
-			}
353
-		} elseif (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
354
-			return null;
355
-		} else {
356
-			[, $userId] = explode('/', $path);
357
-		}
358
-
359
-		return $this->userManager->get($userId);
360
-	}
361
-
362
-	/**
363
-	 * Set up the filesystem for the specified path
364
-	 */
365
-	public function setupForPath(string $path, bool $includeChildren = false): void {
366
-		$user = $this->getUserForPath($path);
367
-		if (!$user) {
368
-			$this->setupRoot();
369
-			return;
370
-		}
371
-
372
-		if ($this->isSetupComplete($user)) {
373
-			return;
374
-		}
375
-
376
-		if ($this->fullSetupRequired($user)) {
377
-			$this->setupForUser($user);
378
-			return;
379
-		}
380
-
381
-		// for the user's home folder, it's always the home mount
382
-		if (rtrim($path) === "/" . $user->getUID() . "/files") {
383
-			if ($includeChildren) {
384
-				$this->setupForUser($user);
385
-			} else {
386
-				$this->oneTimeUserSetup($user);
387
-			}
388
-			return;
389
-		}
390
-
391
-		if (!isset($this->setupUserMountProviders[$user->getUID()])) {
392
-			$this->setupUserMountProviders[$user->getUID()] = [];
393
-		}
394
-		$setupProviders = &$this->setupUserMountProviders[$user->getUID()];
395
-		$currentProviders = [];
396
-
397
-		try {
398
-			$cachedMount = $this->userMountCache->getMountForPath($user, $path);
399
-		} catch (NotFoundException $e) {
400
-			$this->setupForUser($user);
401
-			return;
402
-		}
403
-
404
-		$mounts = [];
405
-		if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
406
-			$setupProviders[] = $cachedMount->getMountProvider();
407
-			$currentProviders[] = $cachedMount->getMountProvider();
408
-			if ($cachedMount->getMountProvider()) {
409
-				$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
410
-			} else {
411
-				$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
412
-				$this->setupForUser($user);
413
-				return;
414
-			}
415
-		}
416
-
417
-		if ($includeChildren) {
418
-			$subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
419
-			foreach ($subCachedMounts as $cachedMount) {
420
-				if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
421
-					$setupProviders[] = $cachedMount->getMountProvider();
422
-					$currentProviders[] = $cachedMount->getMountProvider();
423
-					if ($cachedMount->getMountProvider()) {
424
-						$mounts = array_merge($mounts, $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]));
425
-					} else {
426
-						$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
427
-						$this->setupForUser($user);
428
-						return;
429
-					}
430
-				}
431
-			}
432
-		}
433
-
434
-		if (count($mounts)) {
435
-			$this->userMountCache->registerMounts($user, $mounts, $currentProviders);
436
-			$this->setupForUserWith($user, function () use ($mounts) {
437
-				array_walk($mounts, [$this->mountManager, 'addMount']);
438
-			});
439
-		} elseif (!$this->isSetupStarted($user)) {
440
-			$this->oneTimeUserSetup($user);
441
-		}
442
-	}
443
-
444
-	private function fullSetupRequired(IUser $user): bool {
445
-		// we perform a "cached" setup only after having done the full setup recently
446
-		// this is also used to trigger a full setup after handling events that are likely
447
-		// to change the available mounts
448
-		if (!isset($this->fullSetupRequired[$user->getUID()])) {
449
-			$this->fullSetupRequired[$user->getUID()] = !$this->cache->get($user->getUID());
450
-		}
451
-		return $this->fullSetupRequired[$user->getUID()];
452
-	}
453
-
454
-	/**
455
-	 * @param string $path
456
-	 * @param string[] $providers
457
-	 */
458
-	public function setupForProvider(string $path, array $providers): void {
459
-		$user = $this->getUserForPath($path);
460
-		if (!$user) {
461
-			$this->setupRoot();
462
-			return;
463
-		}
464
-
465
-		if ($this->isSetupComplete($user)) {
466
-			return;
467
-		}
468
-
469
-		if ($this->fullSetupRequired($user)) {
470
-			$this->setupForUser($user);
471
-			return;
472
-		}
473
-
474
-		// home providers are always used
475
-		$providers = array_filter($providers, function (string $provider) {
476
-			return !is_subclass_of($provider, IHomeMountProvider::class);
477
-		});
478
-
479
-		if (in_array('', $providers)) {
480
-			$this->setupForUser($user);
481
-			return;
482
-		}
483
-		$setupProviders = $this->setupUserMountProviders[$user->getUID()] ?? [];
484
-
485
-		$providers = array_diff($providers, $setupProviders);
486
-		if (count($providers) === 0) {
487
-			if (!$this->isSetupStarted($user)) {
488
-				$this->oneTimeUserSetup($user);
489
-			}
490
-			return;
491
-		} else {
492
-			$this->setupUserMountProviders[$user->getUID()] = array_merge($setupProviders, $providers);
493
-			$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, $providers);
494
-		}
495
-
496
-		$this->userMountCache->registerMounts($user, $mounts, $providers);
497
-		$this->setupForUserWith($user, function () use ($mounts) {
498
-			array_walk($mounts, [$this->mountManager, 'addMount']);
499
-		});
500
-	}
501
-
502
-	public function tearDown() {
503
-		$this->setupUsers = [];
504
-		$this->setupUsersComplete = [];
505
-		$this->setupUserMountProviders = [];
506
-		$this->fullSetupRequired = [];
507
-		$this->rootSetup = false;
508
-		$this->mountManager->clear();
509
-		$this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());
510
-	}
511
-
512
-	/**
513
-	 * Get mounts from mount providers that are registered after setup
514
-	 */
515
-	private function listenForNewMountProviders() {
516
-		if (!$this->listeningForProviders) {
517
-			$this->listeningForProviders = true;
518
-			$this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (
519
-				IMountProvider $provider
520
-			) {
521
-				foreach ($this->setupUsers as $userId) {
522
-					$user = $this->userManager->get($userId);
523
-					if ($user) {
524
-						$mounts = $provider->getMountsForUser($user, Filesystem::getLoader());
525
-						array_walk($mounts, [$this->mountManager, 'addMount']);
526
-					}
527
-				}
528
-			});
529
-		}
530
-	}
531
-
532
-	private function setupListeners() {
533
-		// note that this event handling is intentionally pessimistic
534
-		// clearing the cache to often is better than not enough
535
-
536
-		$this->eventDispatcher->addListener(UserAddedEvent::class, function (UserAddedEvent $event) {
537
-			$this->cache->remove($event->getUser()->getUID());
538
-		});
539
-		$this->eventDispatcher->addListener(UserRemovedEvent::class, function (UserRemovedEvent $event) {
540
-			$this->cache->remove($event->getUser()->getUID());
541
-		});
542
-		$this->eventDispatcher->addListener(ShareCreatedEvent::class, function (ShareCreatedEvent $event) {
543
-			$this->cache->remove($event->getShare()->getSharedWith());
544
-		});
545
-		$this->eventDispatcher->addListener(InvalidateMountCacheEvent::class, function (InvalidateMountCacheEvent $event
546
-		) {
547
-			if ($user = $event->getUser()) {
548
-				$this->cache->remove($user->getUID());
549
-			} else {
550
-				$this->cache->clear();
551
-			}
552
-		});
553
-
554
-		$genericEvents = [
555
-			'\OCA\Circles::onCircleCreation',
556
-			'\OCA\Circles::onCircleDestruction',
557
-			'\OCA\Circles::onMemberNew',
558
-			'\OCA\Circles::onMemberLeaving',
559
-		];
560
-
561
-		foreach ($genericEvents as $genericEvent) {
562
-			$this->eventDispatcher->addListener($genericEvent, function ($event) {
563
-				$this->cache->clear();
564
-			});
565
-		}
566
-	}
179
+            if ($mount->getOption('readonly', false)) {
180
+                return new PermissionsMask([
181
+                    'storage' => $storage,
182
+                    'mask' => Constants::PERMISSION_ALL & ~(
183
+                            Constants::PERMISSION_UPDATE |
184
+                            Constants::PERMISSION_CREATE |
185
+                            Constants::PERMISSION_DELETE
186
+                        ),
187
+                ]);
188
+            }
189
+            return $storage;
190
+        });
191
+    }
192
+
193
+    /**
194
+     * Setup the full filesystem for the specified user
195
+     */
196
+    public function setupForUser(IUser $user): void {
197
+        if ($this->isSetupComplete($user)) {
198
+            return;
199
+        }
200
+        $this->setupUsersComplete[] = $user->getUID();
201
+
202
+        if (!isset($this->setupUserMountProviders[$user->getUID()])) {
203
+            $this->setupUserMountProviders[$user->getUID()] = [];
204
+        }
205
+
206
+        $previouslySetupProviders = $this->setupUserMountProviders[$user->getUID()];
207
+
208
+        $this->setupForUserWith($user, function () use ($user) {
209
+            $this->mountProviderCollection->addMountForUser($user, $this->mountManager, function (
210
+                IMountProvider $provider
211
+            ) use ($user) {
212
+                return !in_array(get_class($provider), $this->setupUserMountProviders[$user->getUID()]);
213
+            });
214
+        });
215
+        $this->afterUserFullySetup($user, $previouslySetupProviders);
216
+    }
217
+
218
+    /**
219
+     * part of the user setup that is run only once per user
220
+     */
221
+    private function oneTimeUserSetup(IUser $user) {
222
+        if (in_array($user->getUID(), $this->setupUsers, true)) {
223
+            return;
224
+        }
225
+        $this->setupUsers[] = $user->getUID();
226
+        $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
227
+
228
+        OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
229
+
230
+        Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
231
+
232
+        $userDir = '/' . $user->getUID() . '/files';
233
+
234
+        Filesystem::initInternal($userDir);
235
+
236
+        if ($this->lockdownManager->canAccessFilesystem()) {
237
+            // home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
238
+            $homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
239
+            $this->mountManager->addMount($homeMount);
240
+
241
+            if ($homeMount->getStorageRootId() === -1) {
242
+                $homeMount->getStorage()->mkdir('');
243
+                $homeMount->getStorage()->getScanner()->scan('');
244
+            }
245
+        } else {
246
+            $this->mountManager->addMount(new MountPoint(
247
+                new NullStorage([]),
248
+                '/' . $user->getUID()
249
+            ));
250
+            $this->mountManager->addMount(new MountPoint(
251
+                new NullStorage([]),
252
+                '/' . $user->getUID() . '/files'
253
+            ));
254
+            $this->setupUsersComplete[] = $user->getUID();
255
+        }
256
+
257
+        $this->listenForNewMountProviders();
258
+    }
259
+
260
+    /**
261
+     * Final housekeeping after a user has been fully setup
262
+     */
263
+    private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
264
+        $userRoot = '/' . $user->getUID() . '/';
265
+        $mounts = $this->mountManager->getAll();
266
+        $mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
267
+            return strpos($mount->getMountPoint(), $userRoot) === 0;
268
+        });
269
+        $allProviders = array_map(function (IMountProvider $provider) {
270
+            return get_class($provider);
271
+        }, $this->mountProviderCollection->getProviders());
272
+        $newProviders = array_diff($allProviders, $previouslySetupProviders);
273
+        $mounts = array_filter($mounts, function (IMountPoint $mount) use ($previouslySetupProviders) {
274
+            return !in_array($mount->getMountProvider(), $previouslySetupProviders);
275
+        });
276
+        $this->userMountCache->registerMounts($user, $mounts, $newProviders);
277
+
278
+        $cacheDuration = $this->config->getSystemValueInt('fs_mount_cache_duration', 5 * 60);
279
+        if ($cacheDuration > 0) {
280
+            $this->cache->set($user->getUID(), true, $cacheDuration);
281
+            $this->fullSetupRequired[$user->getUID()] = false;
282
+        }
283
+    }
284
+
285
+    /**
286
+     * @param IUser $user
287
+     * @param IMountPoint $mounts
288
+     * @return void
289
+     * @throws \OCP\HintException
290
+     * @throws \OC\ServerNotAvailableException
291
+     */
292
+    private function setupForUserWith(IUser $user, callable $mountCallback): void {
293
+        $this->setupRoot();
294
+
295
+        if (!$this->isSetupStarted($user)) {
296
+            $this->oneTimeUserSetup($user);
297
+        }
298
+
299
+        $this->eventLogger->start('setup_fs', 'Setup filesystem');
300
+
301
+        if ($this->lockdownManager->canAccessFilesystem()) {
302
+            $mountCallback();
303
+        }
304
+        \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
305
+
306
+        $userDir = '/' . $user->getUID() . '/files';
307
+        OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
308
+
309
+        $this->eventLogger->end('setup_fs');
310
+    }
311
+
312
+    /**
313
+     * Set up the root filesystem
314
+     */
315
+    public function setupRoot(): void {
316
+        //setting up the filesystem twice can only lead to trouble
317
+        if ($this->rootSetup) {
318
+            return;
319
+        }
320
+        $this->rootSetup = true;
321
+
322
+        $this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
323
+
324
+        // load all filesystem apps before, so no setup-hook gets lost
325
+        OC_App::loadApps(['filesystem']);
326
+        $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
327
+
328
+        $this->setupBuiltinWrappers();
329
+
330
+        Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
331
+
332
+        $rootMounts = $this->mountProviderCollection->getRootMounts();
333
+        foreach ($rootMounts as $rootMountProvider) {
334
+            $this->mountManager->addMount($rootMountProvider);
335
+        }
336
+
337
+        $this->eventLogger->end('setup_root_fs');
338
+    }
339
+
340
+    /**
341
+     * Get the user to setup for a path or `null` if the root needs to be setup
342
+     *
343
+     * @param string $path
344
+     * @return IUser|null
345
+     */
346
+    private function getUserForPath(string $path) {
347
+        if (substr_count($path, '/') < 2) {
348
+            if ($user = $this->userSession->getUser()) {
349
+                return $user;
350
+            } else {
351
+                return null;
352
+            }
353
+        } elseif (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
354
+            return null;
355
+        } else {
356
+            [, $userId] = explode('/', $path);
357
+        }
358
+
359
+        return $this->userManager->get($userId);
360
+    }
361
+
362
+    /**
363
+     * Set up the filesystem for the specified path
364
+     */
365
+    public function setupForPath(string $path, bool $includeChildren = false): void {
366
+        $user = $this->getUserForPath($path);
367
+        if (!$user) {
368
+            $this->setupRoot();
369
+            return;
370
+        }
371
+
372
+        if ($this->isSetupComplete($user)) {
373
+            return;
374
+        }
375
+
376
+        if ($this->fullSetupRequired($user)) {
377
+            $this->setupForUser($user);
378
+            return;
379
+        }
380
+
381
+        // for the user's home folder, it's always the home mount
382
+        if (rtrim($path) === "/" . $user->getUID() . "/files") {
383
+            if ($includeChildren) {
384
+                $this->setupForUser($user);
385
+            } else {
386
+                $this->oneTimeUserSetup($user);
387
+            }
388
+            return;
389
+        }
390
+
391
+        if (!isset($this->setupUserMountProviders[$user->getUID()])) {
392
+            $this->setupUserMountProviders[$user->getUID()] = [];
393
+        }
394
+        $setupProviders = &$this->setupUserMountProviders[$user->getUID()];
395
+        $currentProviders = [];
396
+
397
+        try {
398
+            $cachedMount = $this->userMountCache->getMountForPath($user, $path);
399
+        } catch (NotFoundException $e) {
400
+            $this->setupForUser($user);
401
+            return;
402
+        }
403
+
404
+        $mounts = [];
405
+        if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
406
+            $setupProviders[] = $cachedMount->getMountProvider();
407
+            $currentProviders[] = $cachedMount->getMountProvider();
408
+            if ($cachedMount->getMountProvider()) {
409
+                $mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
410
+            } else {
411
+                $this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
412
+                $this->setupForUser($user);
413
+                return;
414
+            }
415
+        }
416
+
417
+        if ($includeChildren) {
418
+            $subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
419
+            foreach ($subCachedMounts as $cachedMount) {
420
+                if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
421
+                    $setupProviders[] = $cachedMount->getMountProvider();
422
+                    $currentProviders[] = $cachedMount->getMountProvider();
423
+                    if ($cachedMount->getMountProvider()) {
424
+                        $mounts = array_merge($mounts, $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]));
425
+                    } else {
426
+                        $this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
427
+                        $this->setupForUser($user);
428
+                        return;
429
+                    }
430
+                }
431
+            }
432
+        }
433
+
434
+        if (count($mounts)) {
435
+            $this->userMountCache->registerMounts($user, $mounts, $currentProviders);
436
+            $this->setupForUserWith($user, function () use ($mounts) {
437
+                array_walk($mounts, [$this->mountManager, 'addMount']);
438
+            });
439
+        } elseif (!$this->isSetupStarted($user)) {
440
+            $this->oneTimeUserSetup($user);
441
+        }
442
+    }
443
+
444
+    private function fullSetupRequired(IUser $user): bool {
445
+        // we perform a "cached" setup only after having done the full setup recently
446
+        // this is also used to trigger a full setup after handling events that are likely
447
+        // to change the available mounts
448
+        if (!isset($this->fullSetupRequired[$user->getUID()])) {
449
+            $this->fullSetupRequired[$user->getUID()] = !$this->cache->get($user->getUID());
450
+        }
451
+        return $this->fullSetupRequired[$user->getUID()];
452
+    }
453
+
454
+    /**
455
+     * @param string $path
456
+     * @param string[] $providers
457
+     */
458
+    public function setupForProvider(string $path, array $providers): void {
459
+        $user = $this->getUserForPath($path);
460
+        if (!$user) {
461
+            $this->setupRoot();
462
+            return;
463
+        }
464
+
465
+        if ($this->isSetupComplete($user)) {
466
+            return;
467
+        }
468
+
469
+        if ($this->fullSetupRequired($user)) {
470
+            $this->setupForUser($user);
471
+            return;
472
+        }
473
+
474
+        // home providers are always used
475
+        $providers = array_filter($providers, function (string $provider) {
476
+            return !is_subclass_of($provider, IHomeMountProvider::class);
477
+        });
478
+
479
+        if (in_array('', $providers)) {
480
+            $this->setupForUser($user);
481
+            return;
482
+        }
483
+        $setupProviders = $this->setupUserMountProviders[$user->getUID()] ?? [];
484
+
485
+        $providers = array_diff($providers, $setupProviders);
486
+        if (count($providers) === 0) {
487
+            if (!$this->isSetupStarted($user)) {
488
+                $this->oneTimeUserSetup($user);
489
+            }
490
+            return;
491
+        } else {
492
+            $this->setupUserMountProviders[$user->getUID()] = array_merge($setupProviders, $providers);
493
+            $mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, $providers);
494
+        }
495
+
496
+        $this->userMountCache->registerMounts($user, $mounts, $providers);
497
+        $this->setupForUserWith($user, function () use ($mounts) {
498
+            array_walk($mounts, [$this->mountManager, 'addMount']);
499
+        });
500
+    }
501
+
502
+    public function tearDown() {
503
+        $this->setupUsers = [];
504
+        $this->setupUsersComplete = [];
505
+        $this->setupUserMountProviders = [];
506
+        $this->fullSetupRequired = [];
507
+        $this->rootSetup = false;
508
+        $this->mountManager->clear();
509
+        $this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());
510
+    }
511
+
512
+    /**
513
+     * Get mounts from mount providers that are registered after setup
514
+     */
515
+    private function listenForNewMountProviders() {
516
+        if (!$this->listeningForProviders) {
517
+            $this->listeningForProviders = true;
518
+            $this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (
519
+                IMountProvider $provider
520
+            ) {
521
+                foreach ($this->setupUsers as $userId) {
522
+                    $user = $this->userManager->get($userId);
523
+                    if ($user) {
524
+                        $mounts = $provider->getMountsForUser($user, Filesystem::getLoader());
525
+                        array_walk($mounts, [$this->mountManager, 'addMount']);
526
+                    }
527
+                }
528
+            });
529
+        }
530
+    }
531
+
532
+    private function setupListeners() {
533
+        // note that this event handling is intentionally pessimistic
534
+        // clearing the cache to often is better than not enough
535
+
536
+        $this->eventDispatcher->addListener(UserAddedEvent::class, function (UserAddedEvent $event) {
537
+            $this->cache->remove($event->getUser()->getUID());
538
+        });
539
+        $this->eventDispatcher->addListener(UserRemovedEvent::class, function (UserRemovedEvent $event) {
540
+            $this->cache->remove($event->getUser()->getUID());
541
+        });
542
+        $this->eventDispatcher->addListener(ShareCreatedEvent::class, function (ShareCreatedEvent $event) {
543
+            $this->cache->remove($event->getShare()->getSharedWith());
544
+        });
545
+        $this->eventDispatcher->addListener(InvalidateMountCacheEvent::class, function (InvalidateMountCacheEvent $event
546
+        ) {
547
+            if ($user = $event->getUser()) {
548
+                $this->cache->remove($user->getUID());
549
+            } else {
550
+                $this->cache->clear();
551
+            }
552
+        });
553
+
554
+        $genericEvents = [
555
+            '\OCA\Circles::onCircleCreation',
556
+            '\OCA\Circles::onCircleDestruction',
557
+            '\OCA\Circles::onMemberNew',
558
+            '\OCA\Circles::onMemberLeaving',
559
+        ];
560
+
561
+        foreach ($genericEvents as $genericEvent) {
562
+            $this->eventDispatcher->addListener($genericEvent, function ($event) {
563
+                $this->cache->clear();
564
+            });
565
+        }
566
+    }
567 567
 }
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -121,14 +121,14 @@  discard block
 block discarded – undo
121 121
 	}
122 122
 
123 123
 	private function setupBuiltinWrappers() {
124
-		Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
124
+		Filesystem::addStorageWrapper('mount_options', function($mountPoint, IStorage $storage, IMountPoint $mount) {
125 125
 			if ($storage->instanceOfStorage(Common::class)) {
126 126
 				$storage->setMountOptions($mount->getOptions());
127 127
 			}
128 128
 			return $storage;
129 129
 		});
130 130
 
131
-		Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
131
+		Filesystem::addStorageWrapper('enable_sharing', function($mountPoint, IStorage $storage, IMountPoint $mount) {
132 132
 			if (!$mount->getOption('enable_sharing', true)) {
133 133
 				return new PermissionsMask([
134 134
 					'storage' => $storage,
@@ -139,21 +139,21 @@  discard block
 block discarded – undo
139 139
 		});
140 140
 
141 141
 		// install storage availability wrapper, before most other wrappers
142
-		Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
142
+		Filesystem::addStorageWrapper('oc_availability', function($mountPoint, IStorage $storage) {
143 143
 			if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
144 144
 				return new Availability(['storage' => $storage]);
145 145
 			}
146 146
 			return $storage;
147 147
 		});
148 148
 
149
-		Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
149
+		Filesystem::addStorageWrapper('oc_encoding', function($mountPoint, IStorage $storage, IMountPoint $mount) {
150 150
 			if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
151 151
 				return new Encoding(['storage' => $storage]);
152 152
 			}
153 153
 			return $storage;
154 154
 		});
155 155
 
156
-		Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
156
+		Filesystem::addStorageWrapper('oc_quota', function($mountPoint, $storage) {
157 157
 			// set up quota for home storages, even for other users
158 158
 			// which can happen when using sharing
159 159
 
@@ -172,7 +172,7 @@  discard block
 block discarded – undo
172 172
 			return $storage;
173 173
 		});
174 174
 
175
-		Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
175
+		Filesystem::addStorageWrapper('readonly', function($mountPoint, IStorage $storage, IMountPoint $mount) {
176 176
 			/*
177 177
 			 * Do not allow any operations that modify the storage
178 178
 			 */
@@ -205,8 +205,8 @@  discard block
 block discarded – undo
205 205
 
206 206
 		$previouslySetupProviders = $this->setupUserMountProviders[$user->getUID()];
207 207
 
208
-		$this->setupForUserWith($user, function () use ($user) {
209
-			$this->mountProviderCollection->addMountForUser($user, $this->mountManager, function (
208
+		$this->setupForUserWith($user, function() use ($user) {
209
+			$this->mountProviderCollection->addMountForUser($user, $this->mountManager, function(
210 210
 				IMountProvider $provider
211 211
 			) use ($user) {
212 212
 				return !in_array(get_class($provider), $this->setupUserMountProviders[$user->getUID()]);
@@ -229,7 +229,7 @@  discard block
 block discarded – undo
229 229
 
230 230
 		Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
231 231
 
232
-		$userDir = '/' . $user->getUID() . '/files';
232
+		$userDir = '/'.$user->getUID().'/files';
233 233
 
234 234
 		Filesystem::initInternal($userDir);
235 235
 
@@ -245,11 +245,11 @@  discard block
 block discarded – undo
245 245
 		} else {
246 246
 			$this->mountManager->addMount(new MountPoint(
247 247
 				new NullStorage([]),
248
-				'/' . $user->getUID()
248
+				'/'.$user->getUID()
249 249
 			));
250 250
 			$this->mountManager->addMount(new MountPoint(
251 251
 				new NullStorage([]),
252
-				'/' . $user->getUID() . '/files'
252
+				'/'.$user->getUID().'/files'
253 253
 			));
254 254
 			$this->setupUsersComplete[] = $user->getUID();
255 255
 		}
@@ -261,16 +261,16 @@  discard block
 block discarded – undo
261 261
 	 * Final housekeeping after a user has been fully setup
262 262
 	 */
263 263
 	private function afterUserFullySetup(IUser $user, array $previouslySetupProviders): void {
264
-		$userRoot = '/' . $user->getUID() . '/';
264
+		$userRoot = '/'.$user->getUID().'/';
265 265
 		$mounts = $this->mountManager->getAll();
266
-		$mounts = array_filter($mounts, function (IMountPoint $mount) use ($userRoot) {
266
+		$mounts = array_filter($mounts, function(IMountPoint $mount) use ($userRoot) {
267 267
 			return strpos($mount->getMountPoint(), $userRoot) === 0;
268 268
 		});
269
-		$allProviders = array_map(function (IMountProvider $provider) {
269
+		$allProviders = array_map(function(IMountProvider $provider) {
270 270
 			return get_class($provider);
271 271
 		}, $this->mountProviderCollection->getProviders());
272 272
 		$newProviders = array_diff($allProviders, $previouslySetupProviders);
273
-		$mounts = array_filter($mounts, function (IMountPoint $mount) use ($previouslySetupProviders) {
273
+		$mounts = array_filter($mounts, function(IMountPoint $mount) use ($previouslySetupProviders) {
274 274
 			return !in_array($mount->getMountProvider(), $previouslySetupProviders);
275 275
 		});
276 276
 		$this->userMountCache->registerMounts($user, $mounts, $newProviders);
@@ -303,7 +303,7 @@  discard block
 block discarded – undo
303 303
 		}
304 304
 		\OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
305 305
 
306
-		$userDir = '/' . $user->getUID() . '/files';
306
+		$userDir = '/'.$user->getUID().'/files';
307 307
 		OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
308 308
 
309 309
 		$this->eventLogger->end('setup_fs');
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
 			} else {
351 351
 				return null;
352 352
 			}
353
-		} elseif (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
353
+		} elseif (strpos($path, '/appdata_'.\OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
354 354
 			return null;
355 355
 		} else {
356 356
 			[, $userId] = explode('/', $path);
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 		}
380 380
 
381 381
 		// for the user's home folder, it's always the home mount
382
-		if (rtrim($path) === "/" . $user->getUID() . "/files") {
382
+		if (rtrim($path) === "/".$user->getUID()."/files") {
383 383
 			if ($includeChildren) {
384 384
 				$this->setupForUser($user);
385 385
 			} else {
@@ -408,7 +408,7 @@  discard block
 block discarded – undo
408 408
 			if ($cachedMount->getMountProvider()) {
409 409
 				$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
410 410
 			} else {
411
-				$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
411
+				$this->logger->debug("mount at ".$cachedMount->getMountPoint()." has no provider set, performing full setup");
412 412
 				$this->setupForUser($user);
413 413
 				return;
414 414
 			}
@@ -423,7 +423,7 @@  discard block
 block discarded – undo
423 423
 					if ($cachedMount->getMountProvider()) {
424 424
 						$mounts = array_merge($mounts, $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]));
425 425
 					} else {
426
-						$this->logger->debug("mount at " . $cachedMount->getMountPoint() . " has no provider set, performing full setup");
426
+						$this->logger->debug("mount at ".$cachedMount->getMountPoint()." has no provider set, performing full setup");
427 427
 						$this->setupForUser($user);
428 428
 						return;
429 429
 					}
@@ -433,7 +433,7 @@  discard block
 block discarded – undo
433 433
 
434 434
 		if (count($mounts)) {
435 435
 			$this->userMountCache->registerMounts($user, $mounts, $currentProviders);
436
-			$this->setupForUserWith($user, function () use ($mounts) {
436
+			$this->setupForUserWith($user, function() use ($mounts) {
437 437
 				array_walk($mounts, [$this->mountManager, 'addMount']);
438 438
 			});
439 439
 		} elseif (!$this->isSetupStarted($user)) {
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
 		}
473 473
 
474 474
 		// home providers are always used
475
-		$providers = array_filter($providers, function (string $provider) {
475
+		$providers = array_filter($providers, function(string $provider) {
476 476
 			return !is_subclass_of($provider, IHomeMountProvider::class);
477 477
 		});
478 478
 
@@ -494,7 +494,7 @@  discard block
 block discarded – undo
494 494
 		}
495 495
 
496 496
 		$this->userMountCache->registerMounts($user, $mounts, $providers);
497
-		$this->setupForUserWith($user, function () use ($mounts) {
497
+		$this->setupForUserWith($user, function() use ($mounts) {
498 498
 			array_walk($mounts, [$this->mountManager, 'addMount']);
499 499
 		});
500 500
 	}
@@ -515,7 +515,7 @@  discard block
 block discarded – undo
515 515
 	private function listenForNewMountProviders() {
516 516
 		if (!$this->listeningForProviders) {
517 517
 			$this->listeningForProviders = true;
518
-			$this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (
518
+			$this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function(
519 519
 				IMountProvider $provider
520 520
 			) {
521 521
 				foreach ($this->setupUsers as $userId) {
@@ -533,16 +533,16 @@  discard block
 block discarded – undo
533 533
 		// note that this event handling is intentionally pessimistic
534 534
 		// clearing the cache to often is better than not enough
535 535
 
536
-		$this->eventDispatcher->addListener(UserAddedEvent::class, function (UserAddedEvent $event) {
536
+		$this->eventDispatcher->addListener(UserAddedEvent::class, function(UserAddedEvent $event) {
537 537
 			$this->cache->remove($event->getUser()->getUID());
538 538
 		});
539
-		$this->eventDispatcher->addListener(UserRemovedEvent::class, function (UserRemovedEvent $event) {
539
+		$this->eventDispatcher->addListener(UserRemovedEvent::class, function(UserRemovedEvent $event) {
540 540
 			$this->cache->remove($event->getUser()->getUID());
541 541
 		});
542
-		$this->eventDispatcher->addListener(ShareCreatedEvent::class, function (ShareCreatedEvent $event) {
542
+		$this->eventDispatcher->addListener(ShareCreatedEvent::class, function(ShareCreatedEvent $event) {
543 543
 			$this->cache->remove($event->getShare()->getSharedWith());
544 544
 		});
545
-		$this->eventDispatcher->addListener(InvalidateMountCacheEvent::class, function (InvalidateMountCacheEvent $event
545
+		$this->eventDispatcher->addListener(InvalidateMountCacheEvent::class, function(InvalidateMountCacheEvent $event
546 546
 		) {
547 547
 			if ($user = $event->getUser()) {
548 548
 				$this->cache->remove($user->getUID());
@@ -559,7 +559,7 @@  discard block
 block discarded – undo
559 559
 		];
560 560
 
561 561
 		foreach ($genericEvents as $genericEvent) {
562
-			$this->eventDispatcher->addListener($genericEvent, function ($event) {
562
+			$this->eventDispatcher->addListener($genericEvent, function($event) {
563 563
 				$this->cache->clear();
564 564
 			});
565 565
 		}
Please login to merge, or discard this patch.
lib/private/Files/Config/MountProviderCollection.php 1 patch
Indentation   +201 added lines, -201 removed lines patch added patch discarded remove patch
@@ -37,205 +37,205 @@
 block discarded – undo
37 37
 use OCP\IUser;
38 38
 
39 39
 class MountProviderCollection implements IMountProviderCollection, Emitter {
40
-	use EmitterTrait;
41
-
42
-	/**
43
-	 * @var \OCP\Files\Config\IHomeMountProvider[]
44
-	 */
45
-	private $homeProviders = [];
46
-
47
-	/**
48
-	 * @var \OCP\Files\Config\IMountProvider[]
49
-	 */
50
-	private $providers = [];
51
-
52
-	/** @var \OCP\Files\Config\IRootMountProvider[] */
53
-	private $rootProviders = [];
54
-
55
-	/**
56
-	 * @var \OCP\Files\Storage\IStorageFactory
57
-	 */
58
-	private $loader;
59
-
60
-	/**
61
-	 * @var \OCP\Files\Config\IUserMountCache
62
-	 */
63
-	private $mountCache;
64
-
65
-	/** @var callable[] */
66
-	private $mountFilters = [];
67
-
68
-	/**
69
-	 * @param \OCP\Files\Storage\IStorageFactory $loader
70
-	 * @param IUserMountCache $mountCache
71
-	 */
72
-	public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
73
-		$this->loader = $loader;
74
-		$this->mountCache = $mountCache;
75
-	}
76
-
77
-	/**
78
-	 * @param IUser $user
79
-	 * @param IMountProvider[] $providers
80
-	 * @return IMountPoint[]
81
-	 */
82
-	private function getUserMountsForProviders(IUser $user, array $providers): array {
83
-		$loader = $this->loader;
84
-		$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
85
-			return $provider->getMountsForUser($user, $loader);
86
-		}, $providers);
87
-		$mounts = array_filter($mounts, function ($result) {
88
-			return is_array($result);
89
-		});
90
-		$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
91
-			return array_merge($mounts, $providerMounts);
92
-		}, []);
93
-		return $this->filterMounts($user, $mounts);
94
-	}
95
-
96
-	public function getMountsForUser(IUser $user): array {
97
-		return $this->getUserMountsForProviders($user, $this->providers);
98
-	}
99
-
100
-	public function getUserMountsForProviderClasses(IUser $user, array $mountProviderClasses): array {
101
-		$providers = array_filter(
102
-			$this->providers,
103
-			fn (IMountProvider $mountProvider) => (in_array(get_class($mountProvider), $mountProviderClasses))
104
-		);
105
-		return $this->getUserMountsForProviders($user, $providers);
106
-	}
107
-
108
-	public function addMountForUser(IUser $user, IMountManager $mountManager, callable $providerFilter = null) {
109
-		// shared mount provider gets to go last since it needs to know existing files
110
-		// to check for name collisions
111
-		$firstMounts = [];
112
-		if ($providerFilter) {
113
-			$providers = array_filter($this->providers, $providerFilter);
114
-		} else {
115
-			$providers = $this->providers;
116
-		}
117
-		$firstProviders = array_filter($providers, function (IMountProvider $provider) {
118
-			return (get_class($provider) !== 'OCA\Files_Sharing\MountProvider');
119
-		});
120
-		$lastProviders = array_filter($providers, function (IMountProvider $provider) {
121
-			return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
122
-		});
123
-		foreach ($firstProviders as $provider) {
124
-			$mounts = $provider->getMountsForUser($user, $this->loader);
125
-			if (is_array($mounts)) {
126
-				$firstMounts = array_merge($firstMounts, $mounts);
127
-			}
128
-		}
129
-		$firstMounts = $this->filterMounts($user, $firstMounts);
130
-		array_walk($firstMounts, [$mountManager, 'addMount']);
131
-
132
-		$lateMounts = [];
133
-		foreach ($lastProviders as $provider) {
134
-			$mounts = $provider->getMountsForUser($user, $this->loader);
135
-			if (is_array($mounts)) {
136
-				$lateMounts = array_merge($lateMounts, $mounts);
137
-			}
138
-		}
139
-
140
-		$lateMounts = $this->filterMounts($user, $lateMounts);
141
-		array_walk($lateMounts, [$mountManager, 'addMount']);
142
-
143
-		return array_merge($lateMounts, $firstMounts);
144
-	}
145
-
146
-	/**
147
-	 * Get the configured home mount for this user
148
-	 *
149
-	 * @param \OCP\IUser $user
150
-	 * @return \OCP\Files\Mount\IMountPoint
151
-	 * @since 9.1.0
152
-	 */
153
-	public function getHomeMountForUser(IUser $user) {
154
-		/** @var \OCP\Files\Config\IHomeMountProvider[] $providers */
155
-		$providers = array_reverse($this->homeProviders); // call the latest registered provider first to give apps an opportunity to overwrite builtin
156
-		foreach ($providers as $homeProvider) {
157
-			if ($mount = $homeProvider->getHomeMountForUser($user, $this->loader)) {
158
-				$mount->setMountPoint('/' . $user->getUID()); //make sure the mountpoint is what we expect
159
-				return $mount;
160
-			}
161
-		}
162
-		throw new \Exception('No home storage configured for user ' . $user);
163
-	}
164
-
165
-	/**
166
-	 * Add a provider for mount points
167
-	 *
168
-	 * @param \OCP\Files\Config\IMountProvider $provider
169
-	 */
170
-	public function registerProvider(IMountProvider $provider) {
171
-		$this->providers[] = $provider;
172
-
173
-		$this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
174
-	}
175
-
176
-	public function registerMountFilter(callable $filter) {
177
-		$this->mountFilters[] = $filter;
178
-	}
179
-
180
-	private function filterMounts(IUser $user, array $mountPoints) {
181
-		return array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) {
182
-			foreach ($this->mountFilters as $filter) {
183
-				if ($filter($mountPoint, $user) === false) {
184
-					return false;
185
-				}
186
-			}
187
-			return true;
188
-		});
189
-	}
190
-
191
-	/**
192
-	 * Add a provider for home mount points
193
-	 *
194
-	 * @param \OCP\Files\Config\IHomeMountProvider $provider
195
-	 * @since 9.1.0
196
-	 */
197
-	public function registerHomeProvider(IHomeMountProvider $provider) {
198
-		$this->homeProviders[] = $provider;
199
-		$this->emit('\OC\Files\Config', 'registerHomeMountProvider', [$provider]);
200
-	}
201
-
202
-	/**
203
-	 * Get the mount cache which can be used to search for mounts without setting up the filesystem
204
-	 *
205
-	 * @return IUserMountCache
206
-	 */
207
-	public function getMountCache() {
208
-		return $this->mountCache;
209
-	}
210
-
211
-	public function registerRootProvider(IRootMountProvider $provider) {
212
-		$this->rootProviders[] = $provider;
213
-	}
214
-
215
-	/**
216
-	 * Get all root mountpoints
217
-	 *
218
-	 * @return \OCP\Files\Mount\IMountPoint[]
219
-	 * @since 20.0.0
220
-	 */
221
-	public function getRootMounts(): array {
222
-		$loader = $this->loader;
223
-		$mounts = array_map(function (IRootMountProvider $provider) use ($loader) {
224
-			return $provider->getRootMounts($loader);
225
-		}, $this->rootProviders);
226
-		$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
227
-			return array_merge($mounts, $providerMounts);
228
-		}, []);
229
-		return $mounts;
230
-	}
231
-
232
-	public function clearProviders() {
233
-		$this->providers = [];
234
-		$this->homeProviders = [];
235
-		$this->rootProviders = [];
236
-	}
237
-
238
-	public function getProviders(): array {
239
-		return $this->providers;
240
-	}
40
+    use EmitterTrait;
41
+
42
+    /**
43
+     * @var \OCP\Files\Config\IHomeMountProvider[]
44
+     */
45
+    private $homeProviders = [];
46
+
47
+    /**
48
+     * @var \OCP\Files\Config\IMountProvider[]
49
+     */
50
+    private $providers = [];
51
+
52
+    /** @var \OCP\Files\Config\IRootMountProvider[] */
53
+    private $rootProviders = [];
54
+
55
+    /**
56
+     * @var \OCP\Files\Storage\IStorageFactory
57
+     */
58
+    private $loader;
59
+
60
+    /**
61
+     * @var \OCP\Files\Config\IUserMountCache
62
+     */
63
+    private $mountCache;
64
+
65
+    /** @var callable[] */
66
+    private $mountFilters = [];
67
+
68
+    /**
69
+     * @param \OCP\Files\Storage\IStorageFactory $loader
70
+     * @param IUserMountCache $mountCache
71
+     */
72
+    public function __construct(IStorageFactory $loader, IUserMountCache $mountCache) {
73
+        $this->loader = $loader;
74
+        $this->mountCache = $mountCache;
75
+    }
76
+
77
+    /**
78
+     * @param IUser $user
79
+     * @param IMountProvider[] $providers
80
+     * @return IMountPoint[]
81
+     */
82
+    private function getUserMountsForProviders(IUser $user, array $providers): array {
83
+        $loader = $this->loader;
84
+        $mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
85
+            return $provider->getMountsForUser($user, $loader);
86
+        }, $providers);
87
+        $mounts = array_filter($mounts, function ($result) {
88
+            return is_array($result);
89
+        });
90
+        $mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
91
+            return array_merge($mounts, $providerMounts);
92
+        }, []);
93
+        return $this->filterMounts($user, $mounts);
94
+    }
95
+
96
+    public function getMountsForUser(IUser $user): array {
97
+        return $this->getUserMountsForProviders($user, $this->providers);
98
+    }
99
+
100
+    public function getUserMountsForProviderClasses(IUser $user, array $mountProviderClasses): array {
101
+        $providers = array_filter(
102
+            $this->providers,
103
+            fn (IMountProvider $mountProvider) => (in_array(get_class($mountProvider), $mountProviderClasses))
104
+        );
105
+        return $this->getUserMountsForProviders($user, $providers);
106
+    }
107
+
108
+    public function addMountForUser(IUser $user, IMountManager $mountManager, callable $providerFilter = null) {
109
+        // shared mount provider gets to go last since it needs to know existing files
110
+        // to check for name collisions
111
+        $firstMounts = [];
112
+        if ($providerFilter) {
113
+            $providers = array_filter($this->providers, $providerFilter);
114
+        } else {
115
+            $providers = $this->providers;
116
+        }
117
+        $firstProviders = array_filter($providers, function (IMountProvider $provider) {
118
+            return (get_class($provider) !== 'OCA\Files_Sharing\MountProvider');
119
+        });
120
+        $lastProviders = array_filter($providers, function (IMountProvider $provider) {
121
+            return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
122
+        });
123
+        foreach ($firstProviders as $provider) {
124
+            $mounts = $provider->getMountsForUser($user, $this->loader);
125
+            if (is_array($mounts)) {
126
+                $firstMounts = array_merge($firstMounts, $mounts);
127
+            }
128
+        }
129
+        $firstMounts = $this->filterMounts($user, $firstMounts);
130
+        array_walk($firstMounts, [$mountManager, 'addMount']);
131
+
132
+        $lateMounts = [];
133
+        foreach ($lastProviders as $provider) {
134
+            $mounts = $provider->getMountsForUser($user, $this->loader);
135
+            if (is_array($mounts)) {
136
+                $lateMounts = array_merge($lateMounts, $mounts);
137
+            }
138
+        }
139
+
140
+        $lateMounts = $this->filterMounts($user, $lateMounts);
141
+        array_walk($lateMounts, [$mountManager, 'addMount']);
142
+
143
+        return array_merge($lateMounts, $firstMounts);
144
+    }
145
+
146
+    /**
147
+     * Get the configured home mount for this user
148
+     *
149
+     * @param \OCP\IUser $user
150
+     * @return \OCP\Files\Mount\IMountPoint
151
+     * @since 9.1.0
152
+     */
153
+    public function getHomeMountForUser(IUser $user) {
154
+        /** @var \OCP\Files\Config\IHomeMountProvider[] $providers */
155
+        $providers = array_reverse($this->homeProviders); // call the latest registered provider first to give apps an opportunity to overwrite builtin
156
+        foreach ($providers as $homeProvider) {
157
+            if ($mount = $homeProvider->getHomeMountForUser($user, $this->loader)) {
158
+                $mount->setMountPoint('/' . $user->getUID()); //make sure the mountpoint is what we expect
159
+                return $mount;
160
+            }
161
+        }
162
+        throw new \Exception('No home storage configured for user ' . $user);
163
+    }
164
+
165
+    /**
166
+     * Add a provider for mount points
167
+     *
168
+     * @param \OCP\Files\Config\IMountProvider $provider
169
+     */
170
+    public function registerProvider(IMountProvider $provider) {
171
+        $this->providers[] = $provider;
172
+
173
+        $this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
174
+    }
175
+
176
+    public function registerMountFilter(callable $filter) {
177
+        $this->mountFilters[] = $filter;
178
+    }
179
+
180
+    private function filterMounts(IUser $user, array $mountPoints) {
181
+        return array_filter($mountPoints, function (IMountPoint $mountPoint) use ($user) {
182
+            foreach ($this->mountFilters as $filter) {
183
+                if ($filter($mountPoint, $user) === false) {
184
+                    return false;
185
+                }
186
+            }
187
+            return true;
188
+        });
189
+    }
190
+
191
+    /**
192
+     * Add a provider for home mount points
193
+     *
194
+     * @param \OCP\Files\Config\IHomeMountProvider $provider
195
+     * @since 9.1.0
196
+     */
197
+    public function registerHomeProvider(IHomeMountProvider $provider) {
198
+        $this->homeProviders[] = $provider;
199
+        $this->emit('\OC\Files\Config', 'registerHomeMountProvider', [$provider]);
200
+    }
201
+
202
+    /**
203
+     * Get the mount cache which can be used to search for mounts without setting up the filesystem
204
+     *
205
+     * @return IUserMountCache
206
+     */
207
+    public function getMountCache() {
208
+        return $this->mountCache;
209
+    }
210
+
211
+    public function registerRootProvider(IRootMountProvider $provider) {
212
+        $this->rootProviders[] = $provider;
213
+    }
214
+
215
+    /**
216
+     * Get all root mountpoints
217
+     *
218
+     * @return \OCP\Files\Mount\IMountPoint[]
219
+     * @since 20.0.0
220
+     */
221
+    public function getRootMounts(): array {
222
+        $loader = $this->loader;
223
+        $mounts = array_map(function (IRootMountProvider $provider) use ($loader) {
224
+            return $provider->getRootMounts($loader);
225
+        }, $this->rootProviders);
226
+        $mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
227
+            return array_merge($mounts, $providerMounts);
228
+        }, []);
229
+        return $mounts;
230
+    }
231
+
232
+    public function clearProviders() {
233
+        $this->providers = [];
234
+        $this->homeProviders = [];
235
+        $this->rootProviders = [];
236
+    }
237
+
238
+    public function getProviders(): array {
239
+        return $this->providers;
240
+    }
241 241
 }
Please login to merge, or discard this patch.