diff options
author | Stephan Orbaugh <62374139+sorbaugh@users.noreply.github.com> | 2025-02-27 15:03:37 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-27 15:03:37 +0100 |
commit | ef099806a4d24327bfa9e70e7e55fe1bde8b2c47 (patch) | |
tree | 6d65530da4f7b5d34ae7fcf051fc29e2255f4bff | |
parent | 7bab703dff8b44f7f8b15c5658351f7aa1aa3742 (diff) | |
parent | 9b3424f60711bd4b171f71a6994df2ba66e3aec9 (diff) | |
download | nextcloud-server-ef099806a4d24327bfa9e70e7e55fe1bde8b2c47.tar.gz nextcloud-server-ef099806a4d24327bfa9e70e7e55fe1bde8b2c47.zip |
Merge pull request #50990 from AIlkiv/refactor/version-rollback-to-event
refactor: move version rollback hook to event
7 files changed, 158 insertions, 12 deletions
diff --git a/apps/files_versions/composer/composer/autoload_classmap.php b/apps/files_versions/composer/composer/autoload_classmap.php index 94256f79da1..9c83924ab7c 100644 --- a/apps/files_versions/composer/composer/autoload_classmap.php +++ b/apps/files_versions/composer/composer/autoload_classmap.php @@ -17,8 +17,10 @@ return array( 'OCA\\Files_Versions\\Db\\VersionEntity' => $baseDir . '/../lib/Db/VersionEntity.php', 'OCA\\Files_Versions\\Db\\VersionsMapper' => $baseDir . '/../lib/Db/VersionsMapper.php', 'OCA\\Files_Versions\\Events\\CreateVersionEvent' => $baseDir . '/../lib/Events/CreateVersionEvent.php', + 'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => $baseDir . '/../lib/Events/VersionRestoredEvent.php', 'OCA\\Files_Versions\\Expiration' => $baseDir . '/../lib/Expiration.php', 'OCA\\Files_Versions\\Listener\\FileEventsListener' => $baseDir . '/../lib/Listener/FileEventsListener.php', + 'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => $baseDir . '/../lib/Listener/LegacyRollbackListener.php', 'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => $baseDir . '/../lib/Listener/LoadAdditionalListener.php', 'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => $baseDir . '/../lib/Listener/VersionAuthorListener.php', diff --git a/apps/files_versions/composer/composer/autoload_static.php b/apps/files_versions/composer/composer/autoload_static.php index 1ac235d936d..1d95663ac55 100644 --- a/apps/files_versions/composer/composer/autoload_static.php +++ b/apps/files_versions/composer/composer/autoload_static.php @@ -32,8 +32,10 @@ class ComposerStaticInitFiles_Versions 'OCA\\Files_Versions\\Db\\VersionEntity' => __DIR__ . '/..' . '/../lib/Db/VersionEntity.php', 'OCA\\Files_Versions\\Db\\VersionsMapper' => __DIR__ . '/..' . '/../lib/Db/VersionsMapper.php', 'OCA\\Files_Versions\\Events\\CreateVersionEvent' => __DIR__ . '/..' . '/../lib/Events/CreateVersionEvent.php', + 'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/VersionRestoredEvent.php', 'OCA\\Files_Versions\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php', 'OCA\\Files_Versions\\Listener\\FileEventsListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventsListener.php', + 'OCA\\Files_Versions\\Listener\\LegacyRollbackListener' => __DIR__ . '/..' . '/../lib/Listener/LegacyRollbackListener.php', 'OCA\\Files_Versions\\Listener\\LoadAdditionalListener' => __DIR__ . '/..' . '/../lib/Listener/LoadAdditionalListener.php', 'OCA\\Files_Versions\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => __DIR__ . '/..' . '/../lib/Listener/VersionAuthorListener.php', diff --git a/apps/files_versions/lib/AppInfo/Application.php b/apps/files_versions/lib/AppInfo/Application.php index 80f85b50073..dcc446d1ff6 100644 --- a/apps/files_versions/lib/AppInfo/Application.php +++ b/apps/files_versions/lib/AppInfo/Application.php @@ -12,7 +12,9 @@ use OCA\DAV\Connector\Sabre\Principal; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\Files\Event\LoadSidebar; use OCA\Files_Versions\Capabilities; +use OCA\Files_Versions\Events\VersionRestoredEvent; use OCA\Files_Versions\Listener\FileEventsListener; +use OCA\Files_Versions\Listener\LegacyRollbackListener; use OCA\Files_Versions\Listener\LoadAdditionalListener; use OCA\Files_Versions\Listener\LoadSidebarListener; use OCA\Files_Versions\Listener\VersionAuthorListener; @@ -80,9 +82,7 @@ class Application extends App implements IBootstrap { ); }); - $context->registerService(IVersionManager::class, function () { - return new VersionManager(); - }); + $context->registerServiceAlias(IVersionManager::class, VersionManager::class); /** * Register Events @@ -108,6 +108,8 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeNodeCopiedEvent::class, FileEventsListener::class); $context->registerEventListener(NodeWrittenEvent::class, VersionAuthorListener::class); + + $context->registerEventListener(VersionRestoredEvent::class, LegacyRollbackListener::class); } public function boot(IBootContext $context): void { diff --git a/apps/files_versions/lib/Events/VersionRestoredEvent.php b/apps/files_versions/lib/Events/VersionRestoredEvent.php new file mode 100644 index 00000000000..12e91bd258d --- /dev/null +++ b/apps/files_versions/lib/Events/VersionRestoredEvent.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Files_Versions\Events; + +use OCA\Files_Versions\Versions\IVersion; +use OCP\EventDispatcher\Event; + +/** + * Class VersionRestoredEvent + * + * Event that is called after a successful restore of a previous version + * + * @package OCA\Files_Versions + */ +class VersionRestoredEvent extends Event { + public function __construct( + private IVersion $version, + ) { + } + + /** + * Version that was restored + */ + public function getVersion(): IVersion { + return $this->version; + } +} diff --git a/apps/files_versions/lib/Listener/LegacyRollbackListener.php b/apps/files_versions/lib/Listener/LegacyRollbackListener.php new file mode 100644 index 00000000000..072c1511caa --- /dev/null +++ b/apps/files_versions/lib/Listener/LegacyRollbackListener.php @@ -0,0 +1,35 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +namespace OCA\Files_Versions\Listener; + +use OCA\Files_Versions\Events\VersionRestoredEvent; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; + +/** + * This listener is designed to be compatible with third-party code + * that can still use a hook. This listener will be removed in + * the next version and the rollback hook will stop working. + * + * @deprecated 32.0.0 + * @template-implements IEventListener<VersionRestoredEvent> + */ +class LegacyRollbackListener implements IEventListener { + public function handle(Event $event): void { + if (!($event instanceof VersionRestoredEvent)) { + return; + } + $version = $event->getVersion(); + \OC_Hook::emit('\OCP\Versions', 'rollback', [ + 'path' => $version->getVersionPath(), + 'revision' => $version->getRevisionId(), + 'node' => $version->getSourceFile(), + ]); + } +} diff --git a/apps/files_versions/lib/Versions/VersionManager.php b/apps/files_versions/lib/Versions/VersionManager.php index 2bf7f5241fe..eb53f04d388 100644 --- a/apps/files_versions/lib/Versions/VersionManager.php +++ b/apps/files_versions/lib/Versions/VersionManager.php @@ -8,6 +8,8 @@ declare(strict_types=1); */ namespace OCA\Files_Versions\Versions; +use OCA\Files_Versions\Events\VersionRestoredEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\File; use OCP\Files\FileInfo; use OCP\Files\IRootFolder; @@ -21,9 +23,15 @@ use OCP\Lock\ManuallyLockedException; use OCP\Server; class VersionManager implements IVersionManager, IDeletableVersionBackend, INeedSyncVersionBackend, IMetadataVersionBackend { + /** @var (IVersionBackend[])[] */ private $backends = []; + public function __construct( + private IEventDispatcher $dispatcher, + ) { + } + public function registerBackend(string $storageType, IVersionBackend $backend) { if (!isset($this->backends[$storageType])) { $this->backends[$storageType] = []; @@ -87,11 +95,7 @@ class VersionManager implements IVersionManager, IDeletableVersionBackend, INeed $result = self::handleAppLocks(fn (): ?bool => $backend->rollback($version)); // rollback doesn't have a return type yet and some implementations don't return anything if ($result === null || $result === true) { - \OC_Hook::emit('\OCP\Versions', 'rollback', [ - 'path' => $version->getVersionPath(), - 'revision' => $version->getRevisionId(), - 'node' => $version->getSourceFile(), - ]); + $this->dispatcher->dispatchTyped(new VersionRestoredEvent($version)); } return $result; } diff --git a/apps/files_versions/tests/Versions/VersionManagerTest.php b/apps/files_versions/tests/Versions/VersionManagerTest.php index a50781b899d..8001d9fbf0e 100644 --- a/apps/files_versions/tests/Versions/VersionManagerTest.php +++ b/apps/files_versions/tests/Versions/VersionManagerTest.php @@ -9,8 +9,11 @@ declare(strict_types=1); namespace OCA\files_versions\tests\Versions; use OC\Files\Storage\Local; +use OCA\Files_Versions\Events\VersionRestoredEvent; +use OCA\Files_Versions\Versions\IVersion; use OCA\Files_Versions\Versions\IVersionBackend; use OCA\Files_Versions\Versions\VersionManager; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Storage\IStorage; use Test\TestCase; @@ -30,7 +33,8 @@ class VersionManagerTest extends TestCase { } public function testGetBackendSingle(): void { - $manager = new VersionManager(); + $dispatcher = $this->createMock(IEventDispatcher::class); + $manager = new VersionManager($dispatcher); $backend = $this->getBackend(); $manager->registerBackend(IStorage::class, $backend); @@ -38,7 +42,8 @@ class VersionManagerTest extends TestCase { } public function testGetBackendMoreSpecific(): void { - $manager = new VersionManager(); + $dispatcher = $this->createMock(IEventDispatcher::class); + $manager = new VersionManager($dispatcher); $backend1 = $this->getBackend(); $backend2 = $this->getBackend(); $manager->registerBackend(IStorage::class, $backend1); @@ -48,7 +53,8 @@ class VersionManagerTest extends TestCase { } public function testGetBackendNoUse(): void { - $manager = new VersionManager(); + $dispatcher = $this->createMock(IEventDispatcher::class); + $manager = new VersionManager($dispatcher); $backend1 = $this->getBackend(); $backend2 = $this->getBackend(false); $manager->registerBackend(IStorage::class, $backend1); @@ -58,7 +64,8 @@ class VersionManagerTest extends TestCase { } public function testGetBackendMultiple(): void { - $manager = new VersionManager(); + $dispatcher = $this->createMock(IEventDispatcher::class); + $manager = new VersionManager($dispatcher); $backend1 = $this->getBackend(); $backend2 = $this->getBackend(false); $backend3 = $this->getBackend(); @@ -68,4 +75,65 @@ class VersionManagerTest extends TestCase { $this->assertEquals($backend3, $manager->getBackendForStorage($this->getStorage(Local::class))); } + + public function testRollbackSuccess(): void { + $versionMock = $this->createMock(IVersion::class); + $backendMock = $this->createMock(IVersionBackend::class); + + $backendMock->expects($this->once()) + ->method('rollback') + ->with($versionMock) + ->willReturn(true); + + $versionMock->method('getBackend')->willReturn($backendMock); + + $dispatcherMock = $this->createMock(IEventDispatcher::class); + $dispatcherMock->expects($this->once()) + ->method('dispatchTyped') + ->with($this->isInstanceOf(VersionRestoredEvent::class)); + + $manager = new VersionManager($dispatcherMock); + + $this->assertTrue($manager->rollback($versionMock)); + } + + public function testRollbackNull(): void { + $versionMock = $this->createMock(IVersion::class); + $backendMock = $this->createMock(IVersionBackend::class); + + $backendMock->expects($this->once()) + ->method('rollback') + ->with($versionMock) + ->willReturn(null); + + $versionMock->method('getBackend')->willReturn($backendMock); + + $dispatcherMock = $this->createMock(IEventDispatcher::class); + $dispatcherMock->expects($this->once()) + ->method('dispatchTyped') + ->with($this->isInstanceOf(VersionRestoredEvent::class)); + + $manager = new VersionManager($dispatcherMock); + + $this->assertNull($manager->rollback($versionMock)); + } + + public function testRollbackFailure(): void { + $versionMock = $this->createMock(IVersion::class); + $backendMock = $this->createMock(IVersionBackend::class); + + $backendMock->expects($this->once()) + ->method('rollback') + ->with($versionMock) + ->willReturn(false); + + $versionMock->method('getBackend')->willReturn($backendMock); + + $dispatcherMock = $this->createMock(IEventDispatcher::class); + $dispatcherMock->expects($this->never())->method('dispatchTyped'); + + $manager = new VersionManager($dispatcherMock); + + $this->assertFalse($manager->rollback($versionMock)); + } } |