diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index 351483d59c..eef7612531 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -201,11 +201,13 @@ class Filesystem { private static $loader; /** + * @param string $wrapperName * @param callable $wrapper + * @param int $priority */ - public static function addStorageWrapper($wrapperName, $wrapper) { + public static function addStorageWrapper($wrapperName, $wrapper, $priority = 50) { $mounts = self::getMountManager()->getAll(); - if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $mounts)) { + if (!self::getLoader()->addStorageWrapper($wrapperName, $wrapper, $priority, $mounts)) { // do not re-wrap if storage with this name already existed return; } diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index ed8852cb68..21883d0413 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -37,7 +37,6 @@ namespace OC\Files\Storage; use OC\Files\Cache\Cache; use OC\Files\Cache\Scanner; -use OC\Files\Cache\Storage; use OC\Files\Filesystem; use OC\Files\Cache\Watcher; use OCP\Files\FileNameTooLongException; @@ -56,7 +55,7 @@ use OCP\Files\ReservedWordException; * Some \OC\Files\Storage\Common methods call functions which are first defined * in classes which extend it, e.g. $this->stat() . */ -abstract class Common implements \OC\Files\Storage\Storage { +abstract class Common implements Storage { protected $cache; protected $scanner; protected $watcher; @@ -370,7 +369,7 @@ abstract class Common implements \OC\Files\Storage\Storage { $storage = $this; } if (!isset($this->storageCache)) { - $this->storageCache = new Storage($storage); + $this->storageCache = new \OC\Files\Cache\Storage($storage); } return $this->storageCache; } diff --git a/lib/private/files/storage/storagefactory.php b/lib/private/files/storage/storagefactory.php index 5da192e4c7..31b4090eda 100644 --- a/lib/private/files/storage/storagefactory.php +++ b/lib/private/files/storage/storagefactory.php @@ -31,9 +31,9 @@ use OCP\Files\Storage\IStorageFactory; class StorageFactory implements IStorageFactory { /** - * @var callable[] $storageWrappers + * @var array[] [$name=>['priority'=>$priority, 'wrapper'=>$callable] $storageWrappers */ - private $storageWrappers = array(); + private $storageWrappers = []; /** * allow modifier storage behaviour by adding wrappers around storages @@ -42,11 +42,12 @@ class StorageFactory implements IStorageFactory { * * @param string $wrapperName name of the wrapper * @param callable $callback callback + * @param int $priority wrappers with the lower priority are applied last (meaning they get called first) * @param \OCP\Files\Mount\IMountPoint[] $existingMounts existing mount points to apply the wrapper to * @return bool true if the wrapper was added, false if there was already a wrapper with this * name registered */ - public function addStorageWrapper($wrapperName, $callback, $existingMounts = []) { + public function addStorageWrapper($wrapperName, $callback, $priority = 50, $existingMounts = []) { if (isset($this->storageWrappers[$wrapperName])) { return false; } @@ -56,7 +57,7 @@ class StorageFactory implements IStorageFactory { $mount->wrapStorage($callback); } - $this->storageWrappers[$wrapperName] = $callback; + $this->storageWrappers[$wrapperName] = ['wrapper' => $callback, 'priority' => $priority]; return true; } @@ -89,7 +90,15 @@ class StorageFactory implements IStorageFactory { * @return \OCP\Files\Storage */ public function wrap(IMountPoint $mountPoint, $storage) { - foreach ($this->storageWrappers as $wrapper) { + $wrappers = array_values($this->storageWrappers); + usort($wrappers, function ($a, $b) { + return $b['priority'] - $a['priority']; + }); + /** @var callable[] $wrappers */ + $wrappers = array_map(function ($wrapper) { + return $wrapper['wrapper']; + }, $wrappers); + foreach ($wrappers as $wrapper) { $storage = $wrapper($mountPoint->getMountPoint(), $storage, $mountPoint); } return $storage; diff --git a/tests/lib/files/storage/storagefactory.php b/tests/lib/files/storage/storagefactory.php index 15519ef83f..fcdff577dd 100644 --- a/tests/lib/files/storage/storagefactory.php +++ b/tests/lib/files/storage/storagefactory.php @@ -15,7 +15,14 @@ use Test\TestCase; use OC\Files\Storage\Wrapper\Wrapper; class DummyWrapper extends Wrapper { + public $data; + public function __construct($arguments) { + parent::__construct($arguments); + if (isset($arguments['data'])) { + $this->data = $arguments['data']; + } + } } class StorageFactory extends TestCase { @@ -42,4 +49,24 @@ class StorageFactory extends TestCase { $wrapped = $mount->getStorage(); $this->assertInstanceOf('\OC\Files\Storage\Temporary', $wrapped); } + + public function testWrapperPriority() { + $instance = new \OC\Files\Storage\StorageFactory(); + $mount = new MountPoint('\OC\Files\Storage\Temporary', '/foo', [[]], $instance); + $instance->addStorageWrapper('dummy1', function ($mountPoint, IStorage $storage) { + return new DummyWrapper(['storage' => $storage, 'data' => 1]); + }, 1); + $instance->addStorageWrapper('dummy2', function ($mountPoint, IStorage $storage) { + return new DummyWrapper(['storage' => $storage, 'data' => 100]); + }, 100); + $instance->addStorageWrapper('dummy3', function ($mountPoint, IStorage $storage) { + return new DummyWrapper(['storage' => $storage, 'data' => 50]); + }, 50); + /** @var \Test\Files\Storage\DummyWrapper $wrapped */ + $wrapped = $mount->getStorage(); + $this->assertInstanceOf('\Test\Files\Storage\DummyWrapper', $wrapped); + $this->assertEquals(1, $wrapped->data);// lowest priority is applied last, called first + $this->assertEquals(50, $wrapped->getWrapperStorage()->data); + $this->assertEquals(100, $wrapped->getWrapperStorage()->getWrapperStorage()->data); + } }