StorageFactory.php 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OC\Files\Storage;
  8. use OCP\Files\Mount\IMountPoint;
  9. use OCP\Files\Storage\IConstructableStorage;
  10. use OCP\Files\Storage\IStorage;
  11. use OCP\Files\Storage\IStorageFactory;
  12. use Psr\Log\LoggerInterface;
  13. class StorageFactory implements IStorageFactory {
  14. /**
  15. * @var array[] [$name=>['priority'=>$priority, 'wrapper'=>$callable] $storageWrappers
  16. */
  17. private $storageWrappers = [];
  18. public function addStorageWrapper(string $wrapperName, callable $callback, int $priority = 50, array $existingMounts = []): bool {
  19. if (isset($this->storageWrappers[$wrapperName])) {
  20. return false;
  21. }
  22. // apply to existing mounts before registering it to prevent applying it double in MountPoint::createStorage
  23. foreach ($existingMounts as $mount) {
  24. $mount->wrapStorage($callback);
  25. }
  26. $this->storageWrappers[$wrapperName] = ['wrapper' => $callback, 'priority' => $priority];
  27. return true;
  28. }
  29. /**
  30. * Remove a storage wrapper by name.
  31. * Note: internal method only to be used for cleanup
  32. *
  33. * @internal
  34. */
  35. public function removeStorageWrapper(string $wrapperName): void {
  36. unset($this->storageWrappers[$wrapperName]);
  37. }
  38. /**
  39. * Create an instance of a storage and apply the registered storage wrappers
  40. */
  41. public function getInstance(IMountPoint $mountPoint, string $class, array $arguments): IStorage {
  42. if (!is_a($class, IConstructableStorage::class, true)) {
  43. \OCP\Server::get(LoggerInterface::class)->warning('Building a storage not implementing IConstructableStorage is deprecated since 31.0.0', ['class' => $class]);
  44. }
  45. return $this->wrap($mountPoint, new $class($arguments));
  46. }
  47. public function wrap(IMountPoint $mountPoint, IStorage $storage): IStorage {
  48. $wrappers = array_values($this->storageWrappers);
  49. usort($wrappers, function ($a, $b) {
  50. return $b['priority'] - $a['priority'];
  51. });
  52. /** @var callable[] $wrappers */
  53. $wrappers = array_map(function ($wrapper) {
  54. return $wrapper['wrapper'];
  55. }, $wrappers);
  56. foreach ($wrappers as $wrapper) {
  57. $storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint);
  58. if (!($storage instanceof IStorage)) {
  59. throw new \Exception('Invalid result from storage wrapper');
  60. }
  61. }
  62. return $storage;
  63. }
  64. }