Skip to content
Snippets Groups Projects
Unverified Commit 553543e8 authored by Morris Jobke's avatar Morris Jobke Committed by GitHub
Browse files

Merge pull request #15659 from nextcloud/version-backend-use

add way for version backends to programmatically specify if they should be used
parents 9daee196 ccfbee2a
No related branches found
No related tags found
No related merge requests found
...@@ -25,12 +25,24 @@ use OCP\Files\File; ...@@ -25,12 +25,24 @@ use OCP\Files\File;
use OCP\Files\FileInfo; use OCP\Files\FileInfo;
use OCP\Files\NotFoundException; use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\Storage\IStorage;
use OCP\IUser; use OCP\IUser;
/** /**
* @since 15.0.0 * @since 15.0.0
*/ */
interface IVersionBackend { 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 * Get all versions for a file
* *
......
...@@ -29,6 +29,7 @@ use OCP\Files\FileInfo; ...@@ -29,6 +29,7 @@ use OCP\Files\FileInfo;
use OCP\Files\Folder; use OCP\Files\Folder;
use OCP\Files\IRootFolder; use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException; use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\IUser; use OCP\IUser;
use OCP\IUserManager; use OCP\IUserManager;
...@@ -43,6 +44,10 @@ class LegacyVersionsBackend implements IVersionBackend { ...@@ -43,6 +44,10 @@ class LegacyVersionsBackend implements IVersionBackend {
$this->userManager = $userManager; $this->userManager = $userManager;
} }
public function useBackendForStorage(IStorage $storage): bool {
return true;
}
public function getVersionsForFile(IUser $user, FileInfo $file): array { public function getVersionsForFile(IUser $user, FileInfo $file): array {
$storage = $file->getStorage(); $storage = $file->getStorage();
if ($storage->instanceOfStorage(SharedStorage::class)) { if ($storage->instanceOfStorage(SharedStorage::class)) {
......
...@@ -27,15 +27,18 @@ use OCP\Files\Storage\IStorage; ...@@ -27,15 +27,18 @@ use OCP\Files\Storage\IStorage;
use OCP\IUser; use OCP\IUser;
class VersionManager implements IVersionManager { class VersionManager implements IVersionManager {
/** @var IVersionBackend[] */ /** @var (IVersionBackend[])[] */
private $backends = []; private $backends = [];
public function registerBackend(string $storageType, IVersionBackend $backend) { 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 { private function getBackends(): array {
return $this->backends; return $this->backends;
...@@ -49,20 +52,29 @@ class VersionManager implements IVersionManager { ...@@ -49,20 +52,29 @@ class VersionManager implements IVersionManager {
public function getBackendForStorage(IStorage $storage): IVersionBackend { public function getBackendForStorage(IStorage $storage): IVersionBackend {
$fullType = get_class($storage); $fullType = get_class($storage);
$backends = $this->getBackends(); $backends = $this->getBackends();
$foundType = array_reduce(array_keys($backends), function ($type, $registeredType) use ($storage) {
$foundType = '';
$foundBackend = null;
foreach ($backends as $type => $backendsForType) {
if ( if (
$storage->instanceOfStorage($registeredType) && $storage->instanceOfStorage($type) &&
($type === '' || is_subclass_of($registeredType, $type)) ($foundType === '' || is_subclass_of($type, $foundType))
) { ) {
return $registeredType; foreach ($backendsForType as $backend) {
} else { /** @var IVersionBackend $backend */
return $type; if ($backend->useBackendForStorage($storage)) {
$foundBackend = $backend;
$foundType = $type;
}
}
} }
}, ''); }
if ($foundType === '') {
if ($foundType === '' || $foundBackend === null) {
throw new BackendNotFoundException("Version backend for $fullType not found"); throw new BackendNotFoundException("Version backend for $fullType not found");
} else { } else {
return $backends[$foundType]; return $foundBackend;
} }
} }
...@@ -90,4 +102,8 @@ class VersionManager implements IVersionManager { ...@@ -90,4 +102,8 @@ class VersionManager implements IVersionManager {
$backend = $this->getBackendForStorage($sourceFile->getStorage()); $backend = $this->getBackendForStorage($sourceFile->getStorage());
return $backend->getVersionFile($user, $sourceFile, $revision); return $backend->getVersionFile($user, $sourceFile, $revision);
} }
public function useBackendForStorage(IStorage $storage): bool {
return false;
}
} }
<?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)));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment