commit
15ef354ace
@ -0,0 +1,26 @@ |
||||
<?php |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
class BackendNotFoundException extends \Exception { |
||||
|
||||
} |
||||
@ -0,0 +1,99 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
use OCP\Files\FileInfo; |
||||
use OCP\IUser; |
||||
|
||||
/** |
||||
* @since 15.0.0 |
||||
*/ |
||||
interface IVersion { |
||||
/** |
||||
* @return IVersionBackend |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getBackend(): IVersionBackend; |
||||
|
||||
/** |
||||
* Get the file info of the source file |
||||
* |
||||
* @return FileInfo |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getSourceFile(): FileInfo; |
||||
|
||||
/** |
||||
* Get the id of the revision for the file |
||||
* |
||||
* @return int |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getRevisionId(): int; |
||||
|
||||
/** |
||||
* Get the timestamp this version was created |
||||
* |
||||
* @return int |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getTimestamp(): int; |
||||
|
||||
/** |
||||
* Get the size of this version |
||||
* |
||||
* @return int |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getSize(): int; |
||||
|
||||
/** |
||||
* Get the name of the source file at the time of making this version |
||||
* |
||||
* @return string |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getSourceFileName(): string; |
||||
|
||||
/** |
||||
* Get the mimetype of this version |
||||
* |
||||
* @return string |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getMimeType(): string; |
||||
|
||||
/** |
||||
* Get the path of this version |
||||
* |
||||
* @return string |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getVersionPath(): string; |
||||
|
||||
/** |
||||
* @return IUser |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getUser(): IUser; |
||||
} |
||||
@ -0,0 +1,81 @@ |
||||
<?php declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
use OCP\Files\File; |
||||
use OCP\Files\FileInfo; |
||||
use OCP\Files\NotFoundException; |
||||
use OCP\Files\SimpleFS\ISimpleFile; |
||||
use OCP\IUser; |
||||
|
||||
/** |
||||
* @since 15.0.0 |
||||
*/ |
||||
interface IVersionBackend { |
||||
/** |
||||
* Get all versions for a file |
||||
* |
||||
* @param IUser $user |
||||
* @param FileInfo $file |
||||
* @return IVersion[] |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getVersionsForFile(IUser $user, FileInfo $file): array; |
||||
|
||||
/** |
||||
* Create a new version for a file |
||||
* |
||||
* @param IUser $user |
||||
* @param FileInfo $file |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function createVersion(IUser $user, FileInfo $file); |
||||
|
||||
/** |
||||
* Restore this version |
||||
* |
||||
* @param IVersion $version |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function rollback(IVersion $version); |
||||
|
||||
/** |
||||
* Open the file for reading |
||||
* |
||||
* @param IVersion $version |
||||
* @return resource |
||||
* @throws NotFoundException |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function read(IVersion $version); |
||||
|
||||
/** |
||||
* Get the preview for a specific version of a file |
||||
* |
||||
* @param IUser $user |
||||
* @param FileInfo $sourceFile |
||||
* @param int $revision |
||||
* @return ISimpleFile |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File; |
||||
} |
||||
@ -0,0 +1,36 @@ |
||||
<?php declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
/** |
||||
* @since 15.0.0 |
||||
*/ |
||||
interface IVersionManager extends IVersionBackend { |
||||
/** |
||||
* Register a new backend |
||||
* |
||||
* @param string $storageType |
||||
* @param IVersionBackend $backend |
||||
* @since 15.0.0 |
||||
*/ |
||||
public function registerBackend(string $storageType, IVersionBackend $backend); |
||||
} |
||||
@ -0,0 +1,105 @@ |
||||
<?php declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
use OC\Files\View; |
||||
use OCA\Files_Versions\Storage; |
||||
use OCP\Files\File; |
||||
use OCP\Files\FileInfo; |
||||
use OCP\Files\Folder; |
||||
use OCP\Files\IRootFolder; |
||||
use OCP\Files\NotFoundException; |
||||
use OCP\IUser; |
||||
|
||||
class LegacyVersionsBackend implements IVersionBackend { |
||||
/** @var IRootFolder */ |
||||
private $rootFolder; |
||||
|
||||
public function __construct(IRootFolder $rootFolder) { |
||||
$this->rootFolder = $rootFolder; |
||||
} |
||||
|
||||
public function getVersionsForFile(IUser $user, FileInfo $file): array { |
||||
$userFolder = $this->rootFolder->getUserFolder($user->getUID()); |
||||
$versions = Storage::getVersions($user->getUID(), $userFolder->getRelativePath($file->getPath())); |
||||
|
||||
return array_map(function (array $data) use ($file, $user) { |
||||
return new Version( |
||||
(int)$data['version'], |
||||
(int)$data['version'], |
||||
$data['name'], |
||||
(int)$data['size'], |
||||
$data['mimetype'], |
||||
$data['path'], |
||||
$file, |
||||
$this, |
||||
$user |
||||
); |
||||
}, $versions); |
||||
} |
||||
|
||||
public function createVersion(IUser $user, FileInfo $file) { |
||||
$userFolder = $this->rootFolder->getUserFolder($user->getUID()); |
||||
$relativePath = $userFolder->getRelativePath($file->getPath()); |
||||
$userView = new View('/' . $user->getUID()); |
||||
// create all parent folders |
||||
Storage::createMissingDirectories($relativePath, $userView); |
||||
|
||||
Storage::scheduleExpire($user->getUID(), $relativePath); |
||||
|
||||
// store a new version of a file |
||||
$userView->copy('files/' . $relativePath, 'files_versions/' . $relativePath . '.v' . $file->getMtime()); |
||||
// ensure the file is scanned |
||||
$userView->getFileInfo('files_versions/' . $relativePath . '.v' . $file->getMtime()); |
||||
} |
||||
|
||||
public function rollback(IVersion $version) { |
||||
return Storage::rollback($version->getVersionPath(), $version->getRevisionId()); |
||||
} |
||||
|
||||
private function getVersionFolder(IUser $user): Folder { |
||||
$userRoot = $this->rootFolder->getUserFolder($user->getUID()) |
||||
->getParent(); |
||||
try { |
||||
/** @var Folder $folder */ |
||||
$folder = $userRoot->get('files_versions'); |
||||
return $folder; |
||||
} catch (NotFoundException $e) { |
||||
return $userRoot->newFolder('files_versions'); |
||||
} |
||||
} |
||||
|
||||
public function read(IVersion $version) { |
||||
$versions = $this->getVersionFolder($version->getUser()); |
||||
/** @var File $file */ |
||||
$file = $versions->get($version->getVersionPath() . '.v' . $version->getRevisionId()); |
||||
return $file->fopen('r'); |
||||
} |
||||
|
||||
public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File { |
||||
$userFolder = $this->rootFolder->getUserFolder($user->getUID()); |
||||
$versionFolder = $this->getVersionFolder($user); |
||||
/** @var File $file */ |
||||
$file = $versionFolder->get($userFolder->getRelativePath($sourceFile->getPath()) . '.v' . $revision); |
||||
return $file; |
||||
} |
||||
} |
||||
@ -0,0 +1,113 @@ |
||||
<?php |
||||
declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
use OCP\Files\FileInfo; |
||||
use OCP\IUser; |
||||
|
||||
class Version implements IVersion { |
||||
/** @var int */ |
||||
private $timestamp; |
||||
|
||||
/** @var int */ |
||||
private $revisionId; |
||||
|
||||
/** @var string */ |
||||
private $name; |
||||
|
||||
/** @var int */ |
||||
private $size; |
||||
|
||||
/** @var string */ |
||||
private $mimetype; |
||||
|
||||
/** @var string */ |
||||
private $path; |
||||
|
||||
/** @var FileInfo */ |
||||
private $sourceFileInfo; |
||||
|
||||
/** @var IVersionBackend */ |
||||
private $backend; |
||||
|
||||
/** @var IUser */ |
||||
private $user; |
||||
|
||||
public function __construct( |
||||
int $timestamp, |
||||
int $revisionId, |
||||
string $name, |
||||
int $size, |
||||
string $mimetype, |
||||
string $path, |
||||
FileInfo $sourceFileInfo, |
||||
IVersionBackend $backend, |
||||
IUser $user |
||||
) { |
||||
$this->timestamp = $timestamp; |
||||
$this->revisionId = $revisionId; |
||||
$this->name = $name; |
||||
$this->size = $size; |
||||
$this->mimetype = $mimetype; |
||||
$this->path = $path; |
||||
$this->sourceFileInfo = $sourceFileInfo; |
||||
$this->backend = $backend; |
||||
$this->user = $user; |
||||
} |
||||
|
||||
public function getBackend(): IVersionBackend { |
||||
return $this->backend; |
||||
} |
||||
|
||||
public function getSourceFile(): FileInfo { |
||||
return $this->sourceFileInfo; |
||||
} |
||||
|
||||
public function getRevisionId(): int { |
||||
return $this->revisionId; |
||||
} |
||||
|
||||
public function getTimestamp(): int { |
||||
return $this->timestamp; |
||||
} |
||||
|
||||
public function getSize(): int { |
||||
return $this->size; |
||||
} |
||||
|
||||
public function getSourceFileName(): string { |
||||
return $this->name; |
||||
} |
||||
|
||||
public function getMimeType(): string { |
||||
return $this->mimetype; |
||||
} |
||||
|
||||
public function getVersionPath(): string { |
||||
return $this->path; |
||||
} |
||||
|
||||
public function getUser(): IUser { |
||||
return $this->user; |
||||
} |
||||
} |
||||
@ -0,0 +1,93 @@ |
||||
<?php declare(strict_types=1); |
||||
/** |
||||
* @copyright Copyright (c) 2018 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\Versions; |
||||
|
||||
use OCP\Files\File; |
||||
use OCP\Files\FileInfo; |
||||
use OCP\Files\Storage\IStorage; |
||||
use OCP\IUser; |
||||
|
||||
class VersionManager implements IVersionManager { |
||||
/** @var IVersionBackend[] */ |
||||
private $backends = []; |
||||
|
||||
public function registerBackend(string $storageType, IVersionBackend $backend) { |
||||
$this->backends[$storageType] = $backend; |
||||
} |
||||
|
||||
/** |
||||
* @return IVersionBackend[] |
||||
*/ |
||||
private function getBackends(): array { |
||||
return $this->backends; |
||||
} |
||||
|
||||
/** |
||||
* @param IStorage $storage |
||||
* @return IVersionBackend |
||||
* @throws BackendNotFoundException |
||||
*/ |
||||
public function getBackendForStorage(IStorage $storage): IVersionBackend { |
||||
$fullType = get_class($storage); |
||||
$backends = $this->getBackends(); |
||||
$foundType = array_reduce(array_keys($backends), function ($type, $registeredType) use ($storage) { |
||||
if ( |
||||
$storage->instanceOfStorage($registeredType) && |
||||
($type === '' || is_subclass_of($registeredType, $type)) |
||||
) { |
||||
return $registeredType; |
||||
} else { |
||||
return $type; |
||||
} |
||||
}, ''); |
||||
if ($foundType === '') { |
||||
throw new BackendNotFoundException("Version backend for $fullType not found"); |
||||
} else { |
||||
return $backends[$foundType]; |
||||
} |
||||
} |
||||
|
||||
public function getVersionsForFile(IUser $user, FileInfo $file): array { |
||||
$backend = $this->getBackendForStorage($file->getStorage()); |
||||
return $backend->getVersionsForFile($user, $file); |
||||
} |
||||
|
||||
public function createVersion(IUser $user, FileInfo $file) { |
||||
$backend = $this->getBackendForStorage($file->getStorage()); |
||||
$backend->createVersion($user, $file); |
||||
} |
||||
|
||||
public function rollback(IVersion $version) { |
||||
$backend = $version->getBackend(); |
||||
return $backend->rollback($version); |
||||
} |
||||
|
||||
public function read(IVersion $version) { |
||||
$backend = $version->getBackend(); |
||||
return $backend->read($version); |
||||
} |
||||
|
||||
public function getVersionFile(IUser $user, FileInfo $sourceFile, int $revision): File { |
||||
$backend = $this->getBackendForStorage($sourceFile->getStorage()); |
||||
return $backend->getVersionFile($user, $sourceFile, $revision); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue