mirror of
https://github.com/nextcloud/server.git
synced 2026-06-10 09:13:19 -04:00
Merge pull request #55072 from nextcloud/feature/54562/pathSpecificFSSetup
Introduces support for mount providers that can provide a partial list of mount points based on a path and the information related to mounts present in that path.
This commit is contained in:
commit
aaf07ab73e
9 changed files with 300 additions and 51 deletions
|
|
@ -3641,12 +3641,6 @@
|
|||
<InvalidOperand>
|
||||
<code><![CDATA[$user]]></code>
|
||||
</InvalidOperand>
|
||||
<RedundantCondition>
|
||||
<code><![CDATA[get_class($provider) !== 'OCA\Files_Sharing\MountProvider']]></code>
|
||||
</RedundantCondition>
|
||||
<TypeDoesNotContainType>
|
||||
<code><![CDATA[get_class($provider) === 'OCA\Files_Sharing\MountProvider']]></code>
|
||||
</TypeDoesNotContainType>
|
||||
</file>
|
||||
<file src="lib/private/Files/Config/UserMountCache.php">
|
||||
<InvalidReturnType>
|
||||
|
|
|
|||
|
|
@ -7,3 +7,6 @@
|
|||
// PHP 8.4
|
||||
function array_find(array $array, callable $callback) {}
|
||||
|
||||
// PHP 8.5
|
||||
function array_any(array $array, callable $callback): bool {}
|
||||
|
||||
|
|
|
|||
|
|
@ -420,7 +420,9 @@ return array(
|
|||
'OCP\\Files\\Config\\ICachedMountInfo' => $baseDir . '/lib/public/Files/Config/ICachedMountInfo.php',
|
||||
'OCP\\Files\\Config\\IHomeMountProvider' => $baseDir . '/lib/public/Files/Config/IHomeMountProvider.php',
|
||||
'OCP\\Files\\Config\\IMountProvider' => $baseDir . '/lib/public/Files/Config/IMountProvider.php',
|
||||
'OCP\\Files\\Config\\IMountProviderArgs' => $baseDir . '/lib/public/Files/Config/IMountProviderArgs.php',
|
||||
'OCP\\Files\\Config\\IMountProviderCollection' => $baseDir . '/lib/public/Files/Config/IMountProviderCollection.php',
|
||||
'OCP\\Files\\Config\\IPartialMountProvider' => $baseDir . '/lib/public/Files/Config/IPartialMountProvider.php',
|
||||
'OCP\\Files\\Config\\IRootMountProvider' => $baseDir . '/lib/public/Files/Config/IRootMountProvider.php',
|
||||
'OCP\\Files\\Config\\IUserMountCache' => $baseDir . '/lib/public/Files/Config/IUserMountCache.php',
|
||||
'OCP\\Files\\ConnectionLostException' => $baseDir . '/lib/public/Files/ConnectionLostException.php',
|
||||
|
|
|
|||
|
|
@ -461,7 +461,9 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\Files\\Config\\ICachedMountInfo' => __DIR__ . '/../../..' . '/lib/public/Files/Config/ICachedMountInfo.php',
|
||||
'OCP\\Files\\Config\\IHomeMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IHomeMountProvider.php',
|
||||
'OCP\\Files\\Config\\IMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IMountProvider.php',
|
||||
'OCP\\Files\\Config\\IMountProviderArgs' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IMountProviderArgs.php',
|
||||
'OCP\\Files\\Config\\IMountProviderCollection' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IMountProviderCollection.php',
|
||||
'OCP\\Files\\Config\\IPartialMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IPartialMountProvider.php',
|
||||
'OCP\\Files\\Config\\IRootMountProvider' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IRootMountProvider.php',
|
||||
'OCP\\Files\\Config\\IUserMountCache' => __DIR__ . '/../../..' . '/lib/public/Files/Config/IUserMountCache.php',
|
||||
'OCP\\Files\\ConnectionLostException' => __DIR__ . '/../../..' . '/lib/public/Files/ConnectionLostException.php',
|
||||
|
|
|
|||
|
|
@ -9,16 +9,21 @@ namespace OC\Files\Config;
|
|||
|
||||
use OC\Hooks\Emitter;
|
||||
use OC\Hooks\EmitterTrait;
|
||||
use OCA\Files_Sharing\MountProvider;
|
||||
use OCP\Diagnostics\IEventLogger;
|
||||
use OCP\Files\Config\IHomeMountProvider;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
use OCP\Files\Config\IMountProviderArgs;
|
||||
use OCP\Files\Config\IMountProviderCollection;
|
||||
use OCP\Files\Config\IPartialMountProvider;
|
||||
use OCP\Files\Config\IRootMountProvider;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Mount\IMountManager;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
use OCP\IUser;
|
||||
use function get_class;
|
||||
use function in_array;
|
||||
|
||||
class MountProviderCollection implements IMountProviderCollection, Emitter {
|
||||
use EmitterTrait;
|
||||
|
|
@ -29,7 +34,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
private array $homeProviders = [];
|
||||
|
||||
/**
|
||||
* @var list<IMountProvider>
|
||||
* @var array<class-string<IMountProvider>, IMountProvider>
|
||||
*/
|
||||
private array $providers = [];
|
||||
|
||||
|
|
@ -67,9 +72,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
$mounts = array_map(function (IMountProvider $provider) use ($user, $loader) {
|
||||
return $this->getMountsFromProvider($provider, $user, $loader);
|
||||
}, $providers);
|
||||
$mounts = array_reduce($mounts, function (array $mounts, array $providerMounts) {
|
||||
return array_merge($mounts, $providerMounts);
|
||||
}, []);
|
||||
$mounts = array_merge(...$mounts);
|
||||
return $this->filterMounts($user, $mounts);
|
||||
}
|
||||
|
||||
|
|
@ -77,18 +80,53 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
* @return list<IMountPoint>
|
||||
*/
|
||||
public function getMountsForUser(IUser $user): array {
|
||||
return $this->getUserMountsForProviders($user, $this->providers);
|
||||
return $this->getUserMountsForProviders($user, array_values($this->providers));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IMountProviderArgs[] $mountProviderArgs
|
||||
* @return array<string, IMountPoint> IMountPoint array indexed by mount
|
||||
* point.
|
||||
*/
|
||||
public function getUserMountsFromProviderByPath(
|
||||
string $providerClass,
|
||||
string $path,
|
||||
array $mountProviderArgs,
|
||||
): array {
|
||||
$provider = $this->providers[$providerClass] ?? null;
|
||||
if ($provider === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!is_a($providerClass, IPartialMountProvider::class, true)) {
|
||||
throw new \LogicException(
|
||||
'Mount provider does not support partial mounts'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var IPartialMountProvider $provider */
|
||||
return $provider->getMountsForPath(
|
||||
$path,
|
||||
$mountProviderArgs,
|
||||
$this->loader,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mounts for the user from the specified provider classes.
|
||||
* Providers not registered in the MountProviderCollection will be skipped.
|
||||
*
|
||||
* @inheritdoc
|
||||
*
|
||||
* @return list<IMountPoint>
|
||||
*/
|
||||
public function getUserMountsForProviderClasses(IUser $user, array $mountProviderClasses): array {
|
||||
$providers = array_filter(
|
||||
$this->providers,
|
||||
fn (IMountProvider $mountProvider) => (in_array(get_class($mountProvider), $mountProviderClasses))
|
||||
fn (string $providerClass) => in_array($providerClass, $mountProviderClasses),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
return $this->getUserMountsForProviders($user, $providers);
|
||||
return $this->getUserMountsForProviders($user, array_values($providers));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,16 +137,21 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
// to check for name collisions
|
||||
$firstMounts = [];
|
||||
if ($providerFilter) {
|
||||
$providers = array_filter($this->providers, $providerFilter);
|
||||
$providers = array_filter($this->providers, $providerFilter, ARRAY_FILTER_USE_KEY);
|
||||
} else {
|
||||
$providers = $this->providers;
|
||||
}
|
||||
$firstProviders = array_filter($providers, function (IMountProvider $provider) {
|
||||
return (get_class($provider) !== 'OCA\Files_Sharing\MountProvider');
|
||||
});
|
||||
$lastProviders = array_filter($providers, function (IMountProvider $provider) {
|
||||
return (get_class($provider) === 'OCA\Files_Sharing\MountProvider');
|
||||
});
|
||||
$firstProviders
|
||||
= array_filter(
|
||||
$providers,
|
||||
fn (string $providerClass) => ($providerClass !== MountProvider::class),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
$lastProviders = array_filter(
|
||||
$providers,
|
||||
fn (string $providerClass) => $providerClass === MountProvider::class,
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
foreach ($firstProviders as $provider) {
|
||||
$mounts = $this->getMountsFromProvider($provider, $user, $this->loader);
|
||||
$firstMounts = array_merge($firstMounts, $mounts);
|
||||
|
|
@ -150,7 +193,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
* Add a provider for mount points
|
||||
*/
|
||||
public function registerProvider(IMountProvider $provider): void {
|
||||
$this->providers[] = $provider;
|
||||
$this->providers[get_class($provider)] = $provider;
|
||||
|
||||
$this->emit('\OC\Files\Config', 'registerMountProvider', [$provider]);
|
||||
}
|
||||
|
|
@ -228,7 +271,7 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
|
|||
* @return list<IMountProvider>
|
||||
*/
|
||||
public function getProviders(): array {
|
||||
return $this->providers;
|
||||
return array_values($this->providers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OC\Files;
|
||||
|
||||
use OC\Files\Cache\FileAccess;
|
||||
use OC\Files\Config\MountProviderCollection;
|
||||
use OC\Files\Mount\HomeMountPoint;
|
||||
use OC\Files\Mount\MountPoint;
|
||||
|
|
@ -33,6 +34,8 @@ use OCP\EventDispatcher\IEventDispatcher;
|
|||
use OCP\Files\Config\ICachedMountInfo;
|
||||
use OCP\Files\Config\IHomeMountProvider;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
use OCP\Files\Config\IMountProviderArgs;
|
||||
use OCP\Files\Config\IPartialMountProvider;
|
||||
use OCP\Files\Config\IRootMountProvider;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\Events\BeforeFileSystemSetupEvent;
|
||||
|
|
@ -53,6 +56,10 @@ use OCP\IUserSession;
|
|||
use OCP\Lockdown\ILockdownManager;
|
||||
use OCP\Share\Events\ShareCreatedEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use function array_key_exists;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function in_array;
|
||||
|
||||
class SetupManager {
|
||||
private bool $rootSetup = false;
|
||||
|
|
@ -60,13 +67,25 @@ class SetupManager {
|
|||
private array $setupUsers = [];
|
||||
// List of users for which all mounts are setup
|
||||
private array $setupUsersComplete = [];
|
||||
/** @var array<string, string[]> */
|
||||
/**
|
||||
* An array of provider classes that have been set up, indexed by UserUID.
|
||||
*
|
||||
* @var array<string, class-string<IMountProvider>[]>
|
||||
*/
|
||||
private array $setupUserMountProviders = [];
|
||||
/**
|
||||
* An array of paths that have already been set up
|
||||
*
|
||||
* @var array<string, int>
|
||||
*/
|
||||
private array $setupMountProviderPaths = [];
|
||||
private ICache $cache;
|
||||
private bool $listeningForProviders;
|
||||
private array $fullSetupRequired = [];
|
||||
private bool $setupBuiltinWrappersDone = false;
|
||||
private bool $forceFullSetup = false;
|
||||
private const SETUP_WITH_CHILDREN = 1;
|
||||
private const SETUP_WITHOUT_CHILDREN = 0;
|
||||
|
||||
public function __construct(
|
||||
private IEventLogger $eventLogger,
|
||||
|
|
@ -82,6 +101,7 @@ class SetupManager {
|
|||
private IConfig $config,
|
||||
private ShareDisableChecker $shareDisableChecker,
|
||||
private IAppManager $appManager,
|
||||
private FileAccess $fileAccess,
|
||||
) {
|
||||
$this->cache = $cacheFactory->createDistributed('setupmanager::');
|
||||
$this->listeningForProviders = false;
|
||||
|
|
@ -98,6 +118,27 @@ class SetupManager {
|
|||
return in_array($user->getUID(), $this->setupUsersComplete, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a path has been cached either directly or through a full setup
|
||||
* of one of its parents.
|
||||
*/
|
||||
private function isPathSetup(string $path): bool {
|
||||
// if the exact path was already setup with or without children
|
||||
if (array_key_exists($path, $this->setupMountProviderPaths)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// or if any of the ancestors was fully setup
|
||||
while (($path = dirname($path)) !== '/') {
|
||||
$setupPath = $this->setupMountProviderPaths[$path] ?? null;
|
||||
if ($setupPath === self::SETUP_WITH_CHILDREN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function setupBuiltinWrappers() {
|
||||
if ($this->setupBuiltinWrappersDone) {
|
||||
return;
|
||||
|
|
@ -195,17 +236,14 @@ class SetupManager {
|
|||
|
||||
$this->eventLogger->start('fs:setup:user:full', 'Setup full filesystem for user');
|
||||
|
||||
if (!isset($this->setupUserMountProviders[$user->getUID()])) {
|
||||
$this->setupUserMountProviders[$user->getUID()] = [];
|
||||
}
|
||||
|
||||
$this->setupUserMountProviders[$user->getUID()] ??= [];
|
||||
$previouslySetupProviders = $this->setupUserMountProviders[$user->getUID()];
|
||||
|
||||
$this->setupForUserWith($user, function () use ($user) {
|
||||
$this->mountProviderCollection->addMountForUser($user, $this->mountManager, function (
|
||||
IMountProvider $provider,
|
||||
string $providerClass,
|
||||
) use ($user) {
|
||||
return !in_array(get_class($provider), $this->setupUserMountProviders[$user->getUID()]);
|
||||
return !in_array($providerClass, $this->setupUserMountProviders[$user->getUID()]);
|
||||
});
|
||||
});
|
||||
$this->afterUserFullySetup($user, $previouslySetupProviders);
|
||||
|
|
@ -213,7 +251,7 @@ class SetupManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* part of the user setup that is run only once per user
|
||||
* Part of the user setup that is run only once per user.
|
||||
*/
|
||||
private function oneTimeUserSetup(IUser $user) {
|
||||
if ($this->isSetupStarted($user)) {
|
||||
|
|
@ -303,11 +341,16 @@ class SetupManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Executes the one-time user setup and, if the user can access the
|
||||
* filesystem, executes $mountCallback.
|
||||
*
|
||||
* @param IUser $user
|
||||
* @param IMountPoint $mounts
|
||||
* @return void
|
||||
* @throws \OCP\HintException
|
||||
* @throws \OC\ServerNotAvailableException
|
||||
* @see self::oneTimeUserSetup()
|
||||
*
|
||||
*/
|
||||
private function setupForUserWith(IUser $user, callable $mountCallback): void {
|
||||
$this->oneTimeUserSetup($user);
|
||||
|
|
@ -373,7 +416,8 @@ class SetupManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set up the filesystem for the specified path
|
||||
* Set up the filesystem for the specified path, optionally including all
|
||||
* children mounts.
|
||||
*/
|
||||
public function setupForPath(string $path, bool $includeChildren = false): void {
|
||||
$user = $this->getUserForPath($path);
|
||||
|
|
@ -415,51 +459,141 @@ class SetupManager {
|
|||
$this->eventLogger->start('fs:setup:user:path', "Setup $path filesystem for user");
|
||||
$this->eventLogger->start('fs:setup:user:path:find', "Find mountpoint for $path");
|
||||
|
||||
$mounts = [];
|
||||
if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
|
||||
$currentProviders[] = $cachedMount->getMountProvider();
|
||||
if ($cachedMount->getMountProvider()) {
|
||||
$setupProviders[] = $cachedMount->getMountProvider();
|
||||
$mounts = $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]);
|
||||
} else {
|
||||
$fullProviderMounts = [];
|
||||
$authoritativeMounts = [];
|
||||
|
||||
$mountProvider = $cachedMount->getMountProvider();
|
||||
$mountPoint = $cachedMount->getMountPoint();
|
||||
$isMountProviderSetup = in_array($mountProvider, $setupProviders);
|
||||
$isPathSetupAsAuthoritative
|
||||
= $this->isPathSetup($mountPoint);
|
||||
if (!$isMountProviderSetup && !$isPathSetupAsAuthoritative) {
|
||||
if ($mountProvider === '') {
|
||||
$this->logger->debug('mount at ' . $cachedMount->getMountPoint() . ' has no provider set, performing full setup');
|
||||
$this->eventLogger->end('fs:setup:user:path:find');
|
||||
$this->setupForUser($user);
|
||||
$this->eventLogger->end('fs:setup:user:path');
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_a($mountProvider, IPartialMountProvider::class, true)) {
|
||||
$rootId = $cachedMount->getRootId();
|
||||
$rootMetadata = $this->fileAccess->getByFileId($rootId);
|
||||
$providerArgs = new IMountProviderArgs($cachedMount, $rootMetadata);
|
||||
// mark the path as cached (without children for now...)
|
||||
$cacheKey = rtrim($mountPoint, '/');
|
||||
$this->setupMountProviderPaths[$cacheKey] = self::SETUP_WITHOUT_CHILDREN;
|
||||
$authoritativeMounts[] = array_values(
|
||||
$this->mountProviderCollection->getUserMountsFromProviderByPath(
|
||||
$mountProvider,
|
||||
$path,
|
||||
[$providerArgs]
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$currentProviders[] = $mountProvider;
|
||||
$setupProviders[] = $mountProvider;
|
||||
$fullProviderMounts[]
|
||||
= $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$mountProvider]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($includeChildren) {
|
||||
$subCachedMounts = $this->userMountCache->getMountsInPath($user, $path);
|
||||
$this->eventLogger->end('fs:setup:user:path:find');
|
||||
|
||||
$needsFullSetup = array_reduce($subCachedMounts, function (bool $needsFullSetup, ICachedMountInfo $cachedMountInfo) {
|
||||
return $needsFullSetup || $cachedMountInfo->getMountProvider() === '';
|
||||
}, false);
|
||||
$needsFullSetup
|
||||
= array_any(
|
||||
$subCachedMounts,
|
||||
fn (ICachedMountInfo $info) => $info->getMountProvider() === ''
|
||||
);
|
||||
|
||||
if ($needsFullSetup) {
|
||||
$this->logger->debug('mount has no provider set, performing full setup');
|
||||
$this->setupForUser($user);
|
||||
$this->eventLogger->end('fs:setup:user:path');
|
||||
return;
|
||||
} else {
|
||||
foreach ($subCachedMounts as $cachedMount) {
|
||||
if (!in_array($cachedMount->getMountProvider(), $setupProviders)) {
|
||||
$currentProviders[] = $cachedMount->getMountProvider();
|
||||
$setupProviders[] = $cachedMount->getMountProvider();
|
||||
$mounts = array_merge($mounts, $this->mountProviderCollection->getUserMountsForProviderClasses($user, [$cachedMount->getMountProvider()]));
|
||||
}
|
||||
|
||||
/** @var array<class-string<IMountProvider>, ICachedMountInfo[]> $authoritativeCachedMounts */
|
||||
$authoritativeCachedMounts = [];
|
||||
foreach ($subCachedMounts as $cachedMount) {
|
||||
/** @var class-string<IMountProvider> $mountProvider */
|
||||
$mountProvider = $cachedMount->getMountProvider();
|
||||
|
||||
// skip setup for already set up providers
|
||||
if (in_array($mountProvider, $setupProviders)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_a($mountProvider, IPartialMountProvider::class, true)) {
|
||||
// skip setup if path was set up as authoritative before
|
||||
if ($this->isPathSetup($cachedMount->getMountPoint())) {
|
||||
continue;
|
||||
}
|
||||
// collect cached mount points for authoritative providers
|
||||
$authoritativeCachedMounts[$mountProvider] ??= [];
|
||||
$authoritativeCachedMounts[$mountProvider][] = $cachedMount;
|
||||
continue;
|
||||
}
|
||||
|
||||
$currentProviders[] = $mountProvider;
|
||||
$setupProviders[] = $mountProvider;
|
||||
$fullProviderMounts[]
|
||||
= $this->mountProviderCollection->getUserMountsForProviderClasses(
|
||||
$user,
|
||||
[$mountProvider]
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($authoritativeCachedMounts)) {
|
||||
$rootIds = array_map(
|
||||
fn (ICachedMountInfo $mount) => $mount->getRootId(),
|
||||
array_merge(...array_values($authoritativeCachedMounts)),
|
||||
);
|
||||
|
||||
$rootsMetadata = [];
|
||||
foreach (array_chunk($rootIds, 1000) as $chunk) {
|
||||
foreach ($this->fileAccess->getByFileIds($chunk) as $id => $fileMetadata) {
|
||||
$rootsMetadata[$id] = $fileMetadata;
|
||||
}
|
||||
}
|
||||
$cacheKey = rtrim($mountPoint, '/');
|
||||
$this->setupMountProviderPaths[$cacheKey] = self::SETUP_WITH_CHILDREN;
|
||||
foreach ($authoritativeCachedMounts as $providerClass => $cachedMounts) {
|
||||
$providerArgs = array_filter(array_map(
|
||||
static function (ICachedMountInfo $info) use ($rootsMetadata) {
|
||||
$rootMetadata = $rootsMetadata[$info->getRootId()] ?? null;
|
||||
|
||||
return $rootMetadata
|
||||
? new IMountProviderArgs($info, $rootMetadata)
|
||||
: null;
|
||||
},
|
||||
$cachedMounts
|
||||
));
|
||||
$authoritativeMounts[]
|
||||
= $this->mountProviderCollection->getUserMountsFromProviderByPath(
|
||||
$providerClass,
|
||||
$path,
|
||||
$providerArgs,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->eventLogger->end('fs:setup:user:path:find');
|
||||
}
|
||||
|
||||
if (count($mounts)) {
|
||||
$this->registerMounts($user, $mounts, $currentProviders);
|
||||
$this->setupForUserWith($user, function () use ($mounts) {
|
||||
array_walk($mounts, [$this->mountManager, 'addMount']);
|
||||
$fullProviderMounts = array_merge(...$fullProviderMounts);
|
||||
$authoritativeMounts = array_merge(...$authoritativeMounts);
|
||||
|
||||
if (count($fullProviderMounts) || count($authoritativeMounts)) {
|
||||
if (count($fullProviderMounts)) {
|
||||
$this->registerMounts($user, $fullProviderMounts, $currentProviders);
|
||||
}
|
||||
|
||||
$this->setupForUserWith($user, function () use ($fullProviderMounts, $authoritativeMounts) {
|
||||
$allMounts = [...$fullProviderMounts, ...$authoritativeMounts];
|
||||
array_walk($allMounts, $this->mountManager->addMount(...));
|
||||
});
|
||||
} elseif (!$this->isSetupStarted($user)) {
|
||||
$this->oneTimeUserSetup($user);
|
||||
|
|
@ -539,6 +673,7 @@ class SetupManager {
|
|||
$this->setupUsers = [];
|
||||
$this->setupUsersComplete = [];
|
||||
$this->setupUserMountProviders = [];
|
||||
$this->setupMountProviderPaths = [];
|
||||
$this->fullSetupRequired = [];
|
||||
$this->rootSetup = false;
|
||||
$this->mountManager->clear();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace OC\Files;
|
||||
|
||||
use OC\Files\Cache\FileAccess;
|
||||
use OC\Share20\ShareDisableChecker;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Diagnostics\IEventLogger;
|
||||
|
|
@ -38,6 +39,7 @@ class SetupManagerFactory {
|
|||
private IConfig $config,
|
||||
private ShareDisableChecker $shareDisableChecker,
|
||||
private IAppManager $appManager,
|
||||
private FileAccess $fileAccess,
|
||||
) {
|
||||
$this->setupManager = null;
|
||||
}
|
||||
|
|
@ -58,6 +60,7 @@ class SetupManagerFactory {
|
|||
$this->config,
|
||||
$this->shareDisableChecker,
|
||||
$this->appManager,
|
||||
$this->fileAccess,
|
||||
);
|
||||
}
|
||||
return $this->setupManager;
|
||||
|
|
|
|||
24
lib/public/Files/Config/IMountProviderArgs.php
Normal file
24
lib/public/Files/Config/IMountProviderArgs.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Files\Config;
|
||||
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
|
||||
/**
|
||||
* Data-class containing information related to a mount and its root.
|
||||
*
|
||||
* @since 33.0.0
|
||||
*/
|
||||
class IMountProviderArgs {
|
||||
public function __construct(
|
||||
public ICachedMountInfo $mountInfo,
|
||||
public ICacheEntry $cacheEntry,
|
||||
) {
|
||||
}
|
||||
}
|
||||
43
lib/public/Files/Config/IPartialMountProvider.php
Normal file
43
lib/public/Files/Config/IPartialMountProvider.php
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCP\Files\Config;
|
||||
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\Storage\IStorageFactory;
|
||||
|
||||
/**
|
||||
* This interface marks mount providers that can provide IMountPoints related to
|
||||
* a path based on the provided mount and root metadata.
|
||||
*
|
||||
* @since 33.0.0
|
||||
*/
|
||||
interface IPartialMountProvider extends IMountProvider {
|
||||
|
||||
/**
|
||||
* Called during the Filesystem setup of a specific path.
|
||||
*
|
||||
* The provided arguments give information about the path being set up,
|
||||
* as well as information about mount points known to be provided by the
|
||||
* mount provider and contained in the path or in its sub-paths.
|
||||
*
|
||||
* Implementations should verify the IMountProviderArgs and return the
|
||||
* corresponding IMountPoint instances.
|
||||
*
|
||||
* @param string $path path for which the mounts are set up
|
||||
* @param IMountProviderArgs[] $mountProviderArgs
|
||||
* @param IStorageFactory $loader
|
||||
* @return array<string, IMountPoint> IMountPoint instances, indexed by
|
||||
* mount-point
|
||||
*/
|
||||
public function getMountsForPath(
|
||||
string $path,
|
||||
array $mountProviderArgs,
|
||||
IStorageFactory $loader,
|
||||
): array;
|
||||
}
|
||||
Loading…
Reference in a new issue