add way for version backends to programmatically specify if they should be used

this allows for backends that should only be used if specific conditions are met

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2019-05-21 17:14:47 +02:00
parent a3b4410283
commit ccfbee2af9
No known key found for this signature in database
GPG Key ID: 42B69D8A64526EFB
4 changed files with 129 additions and 12 deletions

View File

@ -25,12 +25,24 @@ use OCP\Files\File;
use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
/**
* @since 15.0.0
*/
interface IVersionBackend {
/**
* Whether or not this version backend should be used for a storage
*
* If false is returned then the next applicable backend will be used
*
* @param IStorage $storage
* @return bool
* @since 17.0.0
*/
public function useBackendForStorage(IStorage $storage): bool;
/**
* Get all versions for a file
*

View File

@ -29,6 +29,7 @@ use OCP\Files\FileInfo;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\IUser;
use OCP\IUserManager;
@ -43,6 +44,10 @@ class LegacyVersionsBackend implements IVersionBackend {
$this->userManager = $userManager;
}
public function useBackendForStorage(IStorage $storage): bool {
return true;
}
public function getVersionsForFile(IUser $user, FileInfo $file): array {
$storage = $file->getStorage();
if ($storage->instanceOfStorage(SharedStorage::class)) {

View File

@ -27,15 +27,18 @@ use OCP\Files\Storage\IStorage;
use OCP\IUser;
class VersionManager implements IVersionManager {
/** @var IVersionBackend[] */
/** @var (IVersionBackend[])[] */
private $backends = [];
public function registerBackend(string $storageType, IVersionBackend $backend) {
$this->backends[$storageType] = $backend;
if (!isset($this->backends[$storageType])) {
$this->backends[$storageType] = [];
}
$this->backends[$storageType][] = $backend;
}
/**
* @return IVersionBackend[]
* @return (IVersionBackend[])[]
*/
private function getBackends(): array {
return $this->backends;
@ -49,20 +52,29 @@ class VersionManager implements IVersionManager {
public function getBackendForStorage(IStorage $storage): IVersionBackend {
$fullType = get_class($storage);
$backends = $this->getBackends();
$foundType = array_reduce(array_keys($backends), function ($type, $registeredType) use ($storage) {
$foundType = '';
$foundBackend = null;
foreach ($backends as $type => $backendsForType) {
if (
$storage->instanceOfStorage($registeredType) &&
($type === '' || is_subclass_of($registeredType, $type))
$storage->instanceOfStorage($type) &&
($foundType === '' || is_subclass_of($type, $foundType))
) {
return $registeredType;
} else {
return $type;
foreach ($backendsForType as $backend) {
/** @var IVersionBackend $backend */
if ($backend->useBackendForStorage($storage)) {
$foundBackend = $backend;
$foundType = $type;
}
}
}
}, '');
if ($foundType === '') {
}
if ($foundType === '' || $foundBackend === null) {
throw new BackendNotFoundException("Version backend for $fullType not found");
} else {
return $backends[$foundType];
return $foundBackend;
}
}
@ -90,4 +102,8 @@ class VersionManager implements IVersionManager {
$backend = $this->getBackendForStorage($sourceFile->getStorage());
return $backend->getVersionFile($user, $sourceFile, $revision);
}
public function useBackendForStorage(IStorage $storage): bool {
return false;
}
}

View File

@ -0,0 +1,84 @@
<?php declare(strict_types=1);
/**
* @copyright Copyright (c) 2019 Robin Appelman <robin@icewind.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\files_versions\tests\Versions;
use OC\Files\Storage\Local;
use OCA\Files_Versions\Versions\IVersionBackend;
use OCA\Files_Versions\Versions\VersionManager;
use OCP\Files\Storage\IStorage;
use Test\TestCase;
class VersionManagerTest extends TestCase {
private function getBackend(bool $shouldUse = true): IVersionBackend {
$backend = $this->createMock(IVersionBackend::class);
$backend->method('useBackendForStorage')
->willReturn($shouldUse);
return $backend;
}
private function getStorage(string $class): IStorage {
return $this->getMockBuilder($class)
->disableOriginalConstructor()
->setMethodsExcept(['instanceOfStorage'])
->getMock();
}
public function testGetBackendSingle() {
$manager = new VersionManager();
$backend = $this->getBackend();
$manager->registerBackend(IStorage::class, $backend);
$this->assertEquals($backend, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
public function testGetBackendMoreSpecific() {
$manager = new VersionManager();
$backend1 = $this->getBackend();
$backend2 = $this->getBackend();
$manager->registerBackend(IStorage::class, $backend1);
$manager->registerBackend(Local::class, $backend2);
$this->assertEquals($backend2, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
public function testGetBackendNoUse() {
$manager = new VersionManager();
$backend1 = $this->getBackend();
$backend2 = $this->getBackend(false);
$manager->registerBackend(IStorage::class, $backend1);
$manager->registerBackend(Local::class, $backend2);
$this->assertEquals($backend1, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
public function testGetBackendMultiple() {
$manager = new VersionManager();
$backend1 = $this->getBackend();
$backend2 = $this->getBackend(false);
$backend3 = $this->getBackend();
$manager->registerBackend(IStorage::class, $backend1);
$manager->registerBackend(Local::class, $backend2);
$manager->registerBackend(Local::class, $backend3);
$this->assertEquals($backend3, $manager->getBackendForStorage($this->getStorage(Local::class)));
}
}