diff --git a/apps/files_external/lib/Service/GlobalStoragesService.php b/apps/files_external/lib/Service/GlobalStoragesService.php index 2694058c96845..d6bcd81306586 100644 --- a/apps/files_external/lib/Service/GlobalStoragesService.php +++ b/apps/files_external/lib/Service/GlobalStoragesService.php @@ -14,19 +14,14 @@ use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\MountConfig; use OCP\IGroup; +use Override; /** * Service class to manage global external storage */ class GlobalStoragesService extends StoragesService { - /** - * Triggers $signal for all applicable users of the given - * storage - * - * @param StorageConfig $storage storage data - * @param string $signal signal to trigger - */ - protected function triggerHooks(StorageConfig $storage, $signal) { + #[Override] + protected function triggerHooks(StorageConfig $storage, $signal): void { // FIXME: Use as expression in empty once PHP 5.4 support is dropped $applicableUsers = $storage->getApplicableUsers(); $applicableGroups = $storage->getApplicableGroups(); @@ -55,15 +50,8 @@ protected function triggerHooks(StorageConfig $storage, $signal) { ); } - /** - * Triggers signal_create_mount or signal_delete_mount to - * accommodate for additions/deletions in applicableUsers - * and applicableGroups fields. - * - * @param StorageConfig $oldStorage old storage config - * @param StorageConfig $newStorage new storage config - */ - protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { + #[Override] + protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage): void { // if mount point changed, it's like a deletion + creation if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { $this->eventDispatcher->dispatchTyped(new StorageDeletedEvent($oldStorage)); @@ -139,16 +127,13 @@ protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $ } } - /** - * Get the visibility type for this controller, used in validation - * - * @return int BackendService::VISIBILITY_* constants - */ - public function getVisibilityType() { + #[Override] + public function getVisibilityType(): int { return BackendService::VISIBILITY_ADMIN; } - protected function isApplicable(StorageConfig $config) { + #[Override] + protected function isApplicable(StorageConfig $config): bool { return true; } @@ -157,16 +142,14 @@ protected function isApplicable(StorageConfig $config) { * * @return StorageConfig[] map of storage id to storage config */ - public function getStorageForAllUsers() { + public function getStorageForAllUsers(): array { $mounts = $this->dbConfig->getAllMounts(); $configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts); $configs = array_filter($configs, function ($config) { return $config instanceof StorageConfig; }); - $keys = array_map(function (StorageConfig $config) { - return $config->getId(); - }, $configs); + $keys = array_map(static fn (StorageConfig $config) => $config->getId(), $configs); return array_combine($keys, $configs); } diff --git a/apps/files_external/lib/Service/StoragesService.php b/apps/files_external/lib/Service/StoragesService.php index 30dc5b7b941b3..828d91d2987e0 100644 --- a/apps/files_external/lib/Service/StoragesService.php +++ b/apps/files_external/lib/Service/StoragesService.php @@ -31,14 +31,10 @@ /** * Service class to manage external storage + * + * @psalm-import-type ExternalMountInfo from DBConfigService */ abstract class StoragesService { - - /** - * @param BackendService $backendService - * @param DBConfigService $dbConfig - * @param IEventDispatcher $eventDispatcher - */ public function __construct( protected BackendService $backendService, protected DBConfigService $dbConfig, @@ -47,24 +43,21 @@ public function __construct( ) { } - protected function readDBConfig() { + /** + * @return list + */ + protected function readDBConfig(): array { return $this->dbConfig->getAdminMounts(); } - protected function getStorageConfigFromDBMount(array $mount) { - $applicableUsers = array_filter($mount['applicable'], function ($applicable) { - return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_USER; - }); - $applicableUsers = array_map(function ($applicable) { - return $applicable['value']; - }, $applicableUsers); - - $applicableGroups = array_filter($mount['applicable'], function ($applicable) { - return $applicable['type'] === DBConfigService::APPLICABLE_TYPE_GROUP; - }); - $applicableGroups = array_map(function ($applicable) { - return $applicable['value']; - }, $applicableGroups); + protected function getStorageConfigFromDBMount(array $mount): ?StorageConfig { + $applicableUsers = array_filter($mount['applicable'], static fn (array $applicable): bool + => $applicable['type'] === DBConfigService::APPLICABLE_TYPE_USER); + $applicableUsers = array_map(static fn (array $applicable) => $applicable['value'], $applicableUsers); + + $applicableGroups = array_filter($mount['applicable'], static fn (array $applicable): bool + => $applicable['type'] === DBConfigService::APPLICABLE_TYPE_GROUP); + $applicableGroups = array_map(static fn (array $applicable) => $applicable['value'], $applicableGroups); try { $config = $this->createStorage( @@ -99,18 +92,14 @@ protected function getStorageConfigFromDBMount(array $mount) { /** * Read the external storage config * - * @return array map of storage id to storage config + * @return array map of storage id to storage config */ - protected function readConfig() { + protected function readConfig(): array { $mounts = $this->readDBConfig(); - $configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts); - $configs = array_filter($configs, function ($config) { - return $config instanceof StorageConfig; - }); + $configs = array_map($this->getStorageConfigFromDBMount(...), $mounts); + $configs = array_filter($configs); - $keys = array_map(function (StorageConfig $config) { - return $config->getId(); - }, $configs); + $keys = array_map(static fn (StorageConfig $config): int => $config->getId(), $configs); return array_combine($keys, $configs); } @@ -139,18 +128,15 @@ public function getStorage(int $id): StorageConfig { /** * Check whether this storage service should provide access to a storage - * - * @param StorageConfig $config - * @return bool */ - abstract protected function isApplicable(StorageConfig $config); + abstract protected function isApplicable(StorageConfig $config): bool; /** * Gets all storages, valid or not * * @return StorageConfig[] array of storage configs */ - public function getAllStorages() { + public function getAllStorages(): array { return $this->readConfig(); } @@ -159,18 +145,16 @@ public function getAllStorages() { * * @return StorageConfig[] */ - public function getStorages() { - return array_filter($this->getAllStorages(), [$this, 'validateStorage']); + public function getStorages(): array { + return array_filter($this->getAllStorages(), $this->validateStorage(...)); } /** * Validate storage * FIXME: De-duplicate with StoragesController::validate() * - * @param StorageConfig $storage - * @return bool */ - protected function validateStorage(StorageConfig $storage) { + protected function validateStorage(StorageConfig $storage): bool { /** @var Backend */ $backend = $storage->getBackend(); /** @var AuthMechanism */ @@ -180,25 +164,19 @@ protected function validateStorage(StorageConfig $storage) { // not permitted to use backend return false; } - if (!$authMechanism->isVisibleFor($this->getVisibilityType())) { - // not permitted to use auth mechanism - return false; - } - return true; + // permitted to use auth mechanism + return $authMechanism->isVisibleFor($this->getVisibilityType()); } /** * Get the visibility type for this controller, used in validation * - * @return int BackendService::VISIBILITY_* constants + * @return BackendService::VISIBILITY_* */ - abstract public function getVisibilityType(); + abstract public function getVisibilityType(): int; - /** - * @return integer - */ - protected function getType() { + protected function getType(): int { return DBConfigService::MOUNT_TYPE_ADMIN; } @@ -209,7 +187,7 @@ protected function getType() { * * @return StorageConfig storage config, with added id */ - public function addStorage(StorageConfig $newStorage) { + public function addStorage(StorageConfig $newStorage): StorageConfig { $allStorages = $this->readConfig(); $configId = $this->dbConfig->addMount( @@ -275,7 +253,7 @@ public function createStorage( ?array $applicableUsers = null, ?array $applicableGroups = null, ?int $priority = null, - ) { + ): StorageConfig { $backend = $this->backendService->getBackend($backendIdentifier); if (!$backend) { $backend = new InvalidBackend($backendIdentifier); @@ -313,7 +291,7 @@ public function createStorage( * @param string $mountType hook mount type param * @param array $applicableArray array of applicable users/groups for which to trigger the hook */ - protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $applicableArray): void { + protected function triggerApplicableHooks(string $signal, string $mountPoint, string $mountType, array $applicableArray): void { $this->eventDispatcher->dispatchTyped(new InvalidateMountCacheEvent(null)); foreach ($applicableArray as $applicable) { Util::emitHook( @@ -335,7 +313,7 @@ protected function triggerApplicableHooks($signal, $mountPoint, $mountType, $app * @param StorageConfig $storage storage data * @param string $signal signal to trigger */ - abstract protected function triggerHooks(StorageConfig $storage, $signal); + abstract protected function triggerHooks(StorageConfig $storage, string $signal): void; /** * Triggers signal_create_mount or signal_delete_mount to @@ -345,7 +323,7 @@ abstract protected function triggerHooks(StorageConfig $storage, $signal); * @param StorageConfig $oldStorage old storage data * @param StorageConfig $newStorage new storage data */ - abstract protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage); + abstract protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage): void; /** * Update storage to the configuration @@ -355,7 +333,7 @@ abstract protected function triggerChangeHooks(StorageConfig $oldStorage, Storag * @return StorageConfig storage config * @throws NotFoundException if the given storage does not exist in the config */ - public function updateStorage(StorageConfig $updatedStorage) { + public function updateStorage(StorageConfig $updatedStorage): StorageConfig { $id = $updatedStorage->getId(); $existingMount = $this->dbConfig->getMountById($id); @@ -435,7 +413,7 @@ public function updateStorage(StorageConfig $updatedStorage) { * * @throws NotFoundException if no storage was found with the given id */ - public function removeStorage(int $id) { + public function removeStorage(int $id): void { $existingMount = $this->dbConfig->getMountById($id); if (!is_array($existingMount)) { @@ -454,29 +432,6 @@ public function removeStorage(int $id) { $this->updateOverwriteHomeFolders(); } - /** - * Construct the storage implementation - * - * @param StorageConfig $storageConfig - * @return int - */ - private function getStorageId(StorageConfig $storageConfig) { - try { - $class = $storageConfig->getBackend()->getStorageClass(); - /** @var \OC\Files\Storage\Storage $storage */ - $storage = new $class($storageConfig->getBackendOptions()); - - // auth mechanism should fire first - $storage = $storageConfig->getBackend()->wrapStorage($storage); - $storage = $storageConfig->getAuthMechanism()->wrapStorage($storage); - - /** @var \OC\Files\Storage\Storage $storage */ - return $storage->getStorageCache()->getNumericId(); - } catch (\Exception $e) { - return -1; - } - } - public function updateOverwriteHomeFolders(): void { $appIdsList = $this->appConfig->getValueArray(FilesApplication::APP_ID, ConfigLexicon::OVERWRITES_HOME_FOLDERS); diff --git a/apps/files_external/lib/Service/UserGlobalStoragesService.php b/apps/files_external/lib/Service/UserGlobalStoragesService.php index 65fff40af9048..c76862996ae18 100644 --- a/apps/files_external/lib/Service/UserGlobalStoragesService.php +++ b/apps/files_external/lib/Service/UserGlobalStoragesService.php @@ -13,6 +13,7 @@ use OCP\IGroupManager; use OCP\IUser; use OCP\IUserSession; +use Override; /** * Service class to read global storages applicable to the user @@ -33,20 +34,8 @@ public function __construct( $this->userSession = $userSession; } - /** - * Replace config hash ID with real IDs, for migrating legacy storages - * - * @param StorageConfig[] $storages Storages with real IDs - * @param StorageConfig[] $storagesWithConfigHash Storages with config hash IDs - */ - protected function setRealStorageIds(array &$storages, array $storagesWithConfigHash) { - // as a read-only view, storage IDs don't need to be real - foreach ($storagesWithConfigHash as $storage) { - $storages[$storage->getId()] = $storage; - } - } - - protected function readDBConfig() { + #[Override] + protected function readDBConfig(): array { $userMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID()); $globalMounts = $this->dbConfig->getAdminMountsFor(DBConfigService::APPLICABLE_TYPE_GLOBAL, null); $groups = $this->groupManager->getUserGroupIds($this->getUser()); @@ -58,18 +47,18 @@ protected function readDBConfig() { return array_merge($userMounts, $groupMounts, $globalMounts); } + #[Override] public function addStorage(StorageConfig $newStorage): never { throw new \DomainException('UserGlobalStoragesService writing disallowed'); } + #[Override] public function updateStorage(StorageConfig $updatedStorage): never { throw new \DomainException('UserGlobalStoragesService writing disallowed'); } - /** - * @param integer $id - */ - public function removeStorage($id): never { + #[Override] + public function removeStorage(int $id): never { throw new \DomainException('UserGlobalStoragesService writing disallowed'); } @@ -79,7 +68,7 @@ public function removeStorage($id): never { * * @return StorageConfig[] */ - public function getUniqueStorages() { + public function getUniqueStorages(): array { $storages = $this->getStorages(); $storagesByMountpoint = []; @@ -116,20 +105,17 @@ public function getUniqueStorages() { * @param StorageConfig $storage * @return int */ - protected function getPriorityType(StorageConfig $storage) { + protected function getPriorityType(StorageConfig $storage): int { $applicableUsers = $storage->getApplicableUsers(); $applicableGroups = $storage->getApplicableGroups(); if ($applicableUsers && $applicableUsers[0] !== 'all') { return 2; } - if ($applicableGroups) { - return 1; - } - return 0; + return $applicableGroups ? 1 : 0; } - protected function isApplicable(StorageConfig $config) { + protected function isApplicable(StorageConfig $config): bool { $applicableUsers = $config->getApplicableUsers(); $applicableGroups = $config->getApplicableGroups(); @@ -155,7 +141,7 @@ protected function isApplicable(StorageConfig $config) { * @param IUser|null $user user to get the storages for, if not set the currently logged in user will be used * @return StorageConfig[] array of storage configs */ - public function getAllStoragesForUser(?IUser $user = null) { + public function getAllStoragesForUser(?IUser $user = null): array { if (is_null($user)) { $user = $this->getUser(); } diff --git a/apps/files_external/lib/Service/UserStoragesService.php b/apps/files_external/lib/Service/UserStoragesService.php index d03ceb52b1959..ccd064df797db 100644 --- a/apps/files_external/lib/Service/UserStoragesService.php +++ b/apps/files_external/lib/Service/UserStoragesService.php @@ -12,10 +12,10 @@ use OCA\Files_External\Event\StorageDeletedEvent; use OCA\Files_External\Lib\StorageConfig; use OCA\Files_External\MountConfig; -use OCA\Files_External\NotFoundException; use OCP\EventDispatcher\IEventDispatcher; use OCP\IAppConfig; use OCP\IUserSession; +use Override; /** * Service class to manage user external storage @@ -38,7 +38,8 @@ public function __construct( parent::__construct($backendService, $dbConfig, $eventDispatcher, $appConfig); } - protected function readDBConfig() { + #[Override] + protected function readDBConfig(): array { return $this->dbConfig->getUserMountsFor(DBConfigService::APPLICABLE_TYPE_USER, $this->getUser()->getUID()); } @@ -49,7 +50,7 @@ protected function readDBConfig() { * @param StorageConfig $storage storage data * @param string $signal signal to trigger */ - protected function triggerHooks(StorageConfig $storage, $signal) { + protected function triggerHooks(StorageConfig $storage, string $signal): void { $user = $this->getUser()->getUID(); // trigger hook for the current user @@ -69,7 +70,7 @@ protected function triggerHooks(StorageConfig $storage, $signal) { * @param StorageConfig $oldStorage old storage data * @param StorageConfig $newStorage new storage data */ - protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { + protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage): void { // if mount point changed, it's like a deletion + creation if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { $this->eventDispatcher->dispatchTyped(new StorageDeletedEvent($oldStorage)); @@ -79,31 +80,19 @@ protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $ } } - protected function getType() { + #[Override] + protected function getType(): int { return DBConfigService::MOUNT_TYPE_PERSONAL; } - /** - * Add new storage to the configuration - * - * @param StorageConfig $newStorage storage attributes - * - * @return StorageConfig storage config, with added id - */ - public function addStorage(StorageConfig $newStorage) { + #[Override] + public function addStorage(StorageConfig $newStorage): StorageConfig { $newStorage->setApplicableUsers([$this->getUser()->getUID()]); return parent::addStorage($newStorage); } - /** - * Update storage to the configuration - * - * @param StorageConfig $updatedStorage storage attributes - * - * @return StorageConfig storage config - * @throws NotFoundException if the given storage does not exist in the config - */ - public function updateStorage(StorageConfig $updatedStorage) { + #[Override] + public function updateStorage(StorageConfig $updatedStorage): StorageConfig { // verify ownership through $this->isApplicable() and otherwise throws an exception $this->getStorage($updatedStorage->getId()); @@ -111,20 +100,18 @@ public function updateStorage(StorageConfig $updatedStorage) { return parent::updateStorage($updatedStorage); } - /** - * Get the visibility type for this controller, used in validation - * - * @return int BackendService::VISIBILITY_* constants - */ + #[Override] public function getVisibilityType(): int { return BackendService::VISIBILITY_PERSONAL; } + #[Override] protected function isApplicable(StorageConfig $config): bool { return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAL; } - public function removeStorage($id) { + #[Override] + public function removeStorage(int $id): void { // verify ownership through $this->isApplicable() and otherwise throws an exception $this->getStorage($id); parent::removeStorage($id); diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml index cbe08c0b2b458..d7cac4461d695 100644 --- a/build/psalm-baseline.xml +++ b/build/psalm-baseline.xml @@ -3480,14 +3480,6 @@ - - - - - - getStorageInfo($storageId)]]> - - diff --git a/build/rector-strict.php b/build/rector-strict.php index 6df2c93be55a1..3bc07860bd373 100644 --- a/build/rector-strict.php +++ b/build/rector-strict.php @@ -18,6 +18,8 @@ $nextcloudDir . '/lib/private/Settings/AuthorizedGroupMapper.php', $nextcloudDir . '/apps/settings/lib/Service/AuthorizedGroupService.php', $nextcloudDir . '/lib/private/Files/Storage/Storage.php', + $nextcloudDir . '/lib/private/Files/Cache/Storage.php', + $nextcloudDir . '/lib/private/Files/Cache/StorageGlobal.php', $nextcloudDir . '/lib/private/Files/Storage/Wrapper/Wrapper.php', $nextcloudDir . '/build/psalm/ITypedQueryBuilderTest.php', $nextcloudDir . '/lib/private/DB/QueryBuilder/TypedQueryBuilder.php', diff --git a/lib/private/Files/Cache/Storage.php b/lib/private/Files/Cache/Storage.php index 51def43a4dcee..49b24ec8b34f9 100644 --- a/lib/private/Files/Cache/Storage.php +++ b/lib/private/Files/Cache/Storage.php @@ -1,5 +1,7 @@ storageId = $storage->getId(); - } else { - $this->storageId = $storage; - } + public function __construct( + IStorage|string $storage, + bool $isAvailable, + IDBConnection $connection, + ) { + $this->storageId = $storage instanceof IStorage ? $storage->getId() : $storage; + $this->storageId = self::adjustStorageId($this->storageId); if ($row = self::getStorageById($this->storageId)) { - $this->numericId = (int)$row['numeric_id']; + $this->numericId = $row['numeric_id']; } else { $available = $isAvailable ? 1 : 0; - if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId, 'available' => $available])) { - $this->numericId = $connection->lastInsertId('*PREFIX*storages'); - } else { - if ($row = self::getStorageById($this->storageId)) { - $this->numericId = (int)$row['numeric_id']; - } else { - throw new \RuntimeException('Storage could neither be inserted nor be selected from the database: ' . $this->storageId); + + try { + $qb = $connection->getQueryBuilder(); + $qb->insert('storages') + ->values([ + 'id' => $qb->createNamedParameter($this->storageId), + 'available' => $qb->createNamedParameter($available), + ]) + ->executeStatement(); + $this->numericId = $qb->getLastInsertId(); + } catch (DbalException $e) { + if ($e->getReason() === DbalException::REASON_UNIQUE_CONSTRAINT_VIOLATION) { + $qb = $connection->getQueryBuilder(); + $result = $qb->select('numeric_id') + ->from('storages') + ->where($qb->expr()->eq('id', $qb->createNamedParameter($this->storageId))) + ->executeQuery(); + /** @var false|string|int $row */ + $row = $result->fetchOne(); + if ($row === false) { + throw new \RuntimeException('Storage could neither be inserted nor be selected from the database: ' . $this->storageId, $e->getCode(), $e); + } + + $this->numericId = (int)$row; } + + throw $e; } } } /** - * @param string $storageId - * @return array + * @return array{id: string, numeric_id: int, available: bool, last_checked: int}|null */ - public static function getStorageById($storageId) { + public static function getStorageById(string $storageId): ?array { return self::getGlobalCache()->getStorageInfo($storageId); } @@ -83,26 +102,24 @@ public static function getStorageById($storageId) { * @return string unchanged $storageId if its length is less than 64 characters, * else returns the md5 of $storageId */ - public static function adjustStorageId($storageId) { + public static function adjustStorageId(string $storageId): string { if (strlen($storageId) > 64) { return md5($storageId); } + return $storageId; } /** * Get the numeric id for the storage - * - * @return int */ - public function getNumericId() { + public function getNumericId(): int { return $this->numericId; } /** * Get the string id for the storage * - * @param int $numericId * @return string|null either the storage id string or null if the numeric id is not known */ public static function getStorageId(int $numericId): ?string { @@ -110,44 +127,27 @@ public static function getStorageId(int $numericId): ?string { return $storage['id'] ?? null; } - /** - * Get the numeric of the storage with the provided string id - * - * @param $storageId - * @return int|null either the numeric storage id or null if the storage id is not known - */ - public static function getNumericStorageId($storageId) { - $storageId = self::adjustStorageId($storageId); - - if ($row = self::getStorageById($storageId)) { - return (int)$row['numeric_id']; - } else { - return null; - } - } - /** * @return array{available: bool, last_checked: int} */ - public function getAvailability() { + public function getAvailability(): array { if ($row = self::getStorageById($this->storageId)) { return [ 'available' => (int)$row['available'] === 1, 'last_checked' => $row['last_checked'] ]; - } else { - return [ - 'available' => true, - 'last_checked' => time(), - ]; } + + return [ + 'available' => true, + 'last_checked' => time(), + ]; } /** - * @param bool $isAvailable * @param int $delay amount of seconds to delay reconsidering that storage further */ - public function setAvailability($isAvailable, int $delay = 0) { + public function setAvailability(bool $isAvailable, int $delay = 0): void { $available = $isAvailable ? 1 : 0; if (!$isAvailable) { Server::get(LoggerInterface::class)->info('Storage with ' . $this->storageId . ' marked as unavailable', ['app' => 'lib']); @@ -162,43 +162,9 @@ public function setAvailability($isAvailable, int $delay = 0) { } /** - * Check if a string storage id is known - * - * @param string $storageId - * @return bool + * Remove the entry for the storage by the mount id. */ - public static function exists($storageId) { - return !is_null(self::getNumericStorageId($storageId)); - } - - /** - * remove the entry for the storage - * - * @param string $storageId - */ - public static function remove($storageId) { - $storageId = self::adjustStorageId($storageId); - $numericId = self::getNumericStorageId($storageId); - - $query = Server::get(IDBConnection::class)->getQueryBuilder(); - $query->delete('storages') - ->where($query->expr()->eq('id', $query->createNamedParameter($storageId))); - $query->executeStatement(); - - if (!is_null($numericId)) { - $query = Server::get(IDBConnection::class)->getQueryBuilder(); - $query->delete('filecache') - ->where($query->expr()->eq('storage', $query->createNamedParameter($numericId))); - $query->executeStatement(); - } - } - - /** - * remove the entry for the storage by the mount id - * - * @param int $mountId - */ - public static function cleanByMountId(int $mountId) { + public static function cleanByMountId(int $mountId): void { $db = Server::get(IDBConnection::class); try { @@ -213,24 +179,24 @@ public static function cleanByMountId(int $mountId) { $query = $db->getQueryBuilder(); $query->delete('filecache') - ->where($query->expr()->in('storage', $query->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY))); - $query->runAcrossAllShards(); - $query->executeStatement(); + ->where($query->expr()->in('storage', $query->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY))) + ->runAcrossAllShards() + ->executeStatement(); $query = $db->getQueryBuilder(); $query->delete('storages') - ->where($query->expr()->in('numeric_id', $query->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY))); - $query->executeStatement(); + ->where($query->expr()->in('numeric_id', $query->createNamedParameter($storageIds, IQueryBuilder::PARAM_INT_ARRAY))) + ->executeStatement(); $query = $db->getQueryBuilder(); $query->delete('mounts') - ->where($query->expr()->eq('mount_id', $query->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))); - $query->executeStatement(); + ->where($query->expr()->eq('mount_id', $query->createNamedParameter($mountId, IQueryBuilder::PARAM_INT))) + ->executeStatement(); $db->commit(); - } catch (\Exception $e) { + } catch (\Exception $exception) { $db->rollBack(); - throw $e; + throw $exception; } } } diff --git a/lib/private/Files/Cache/StorageGlobal.php b/lib/private/Files/Cache/StorageGlobal.php index bab31b1db9115..336f136509dfe 100644 --- a/lib/private/Files/Cache/StorageGlobal.php +++ b/lib/private/Files/Cache/StorageGlobal.php @@ -1,5 +1,7 @@ */ - private $cache = []; - /** @var array */ - private $numericIdCache = []; + /** @var array */ + private array $cache = []; + + /** @var array */ + private array $numericIdCache = []; public function __construct( - private IDBConnection $connection, + private readonly IDBConnection $connection, ) { } /** * @param string[] $storageIds */ - public function loadForStorageIds(array $storageIds) { + public function loadForStorageIds(array $storageIds): void { $builder = $this->connection->getQueryBuilder(); $query = $builder->select(['id', 'numeric_id', 'available', 'last_checked']) ->from('storages') ->where($builder->expr()->in('id', $builder->createNamedParameter(array_values($storageIds), IQueryBuilder::PARAM_STR_ARRAY))); $result = $query->executeQuery(); - while ($row = $result->fetch()) { - $this->cache[$row['id']] = $row; + while (($row = $result->fetch()) !== false) { + $normalizedRow = [ + 'id' => (string)$row['id'], + 'numeric_id' => (int)$row['numeric_id'], + 'available' => (bool)$row['available'], + 'last_checked' => (int)$row['last_checked'], + ]; + + $this->cache[$normalizedRow['id']] = $normalizedRow; } + $result->closeCursor(); } /** - * @param string $storageId - * @return array|null + * @return array{id: string, numeric_id: int, available: bool, last_checked: int}|null */ public function getStorageInfo(string $storageId): ?array { if (!isset($this->cache[$storageId])) { @@ -62,17 +72,24 @@ public function getStorageInfo(string $storageId): ?array { $row = $result->fetch(); $result->closeCursor(); - if ($row) { - $this->cache[$storageId] = $row; - $this->numericIdCache[(int)$row['numeric_id']] = $row; + if ($row !== false) { + $normalizedRow = [ + 'id' => (string)$row['id'], + 'numeric_id' => (int)$row['numeric_id'], + 'available' => (bool)$row['available'], + 'last_checked' => (int)$row['last_checked'], + ]; + + $this->cache[$storageId] = $normalizedRow; + $this->numericIdCache[$normalizedRow['numeric_id']] = $normalizedRow; } } + return $this->cache[$storageId] ?? null; } /** - * @param int $numericId - * @return array|null + * @return array{id: string, numeric_id: int, available: bool, last_checked: int}|null */ public function getStorageInfoByNumericId(int $numericId): ?array { if (!isset($this->numericIdCache[$numericId])) { @@ -85,15 +102,23 @@ public function getStorageInfoByNumericId(int $numericId): ?array { $row = $result->fetch(); $result->closeCursor(); - if ($row) { - $this->numericIdCache[$numericId] = $row; - $this->cache[$row['id']] = $row; + if ($row !== false) { + $normalizedRow = [ + 'id' => (string)$row['id'], + 'numeric_id' => (int)$row['numeric_id'], + 'available' => (bool)$row['available'], + 'last_checked' => (int)$row['last_checked'], + ]; + + $this->numericIdCache[$numericId] = $normalizedRow; + $this->cache[$normalizedRow['id']] = $normalizedRow; } } + return $this->numericIdCache[$numericId] ?? null; } - public function clearCache() { + public function clearCache(): void { $this->cache = []; } } diff --git a/psalm-strict.xml b/psalm-strict.xml index 23cd2081c0b70..d91fdc697904f 100644 --- a/psalm-strict.xml +++ b/psalm-strict.xml @@ -24,6 +24,8 @@ + +