aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Orbaugh <62374139+sorbaugh@users.noreply.github.com>2025-02-27 15:03:37 +0100
committerGitHub <noreply@github.com>2025-02-27 15:03:37 +0100
commitef099806a4d24327bfa9e70e7e55fe1bde8b2c47 (patch)
tree6d65530da4f7b5d34ae7fcf051fc29e2255f4bff
parent7bab703dff8b44f7f8b15c5658351f7aa1aa3742 (diff)
parent9b3424f60711bd4b171f71a6994df2ba66e3aec9 (diff)
downloadnextcloud-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
-rw-r--r--apps/files_versions/composer/composer/autoload_classmap.php2
-rw-r--r--apps/files_versions/composer/composer/autoload_static.php2
-rw-r--r--apps/files_versions/lib/AppInfo/Application.php8
-rw-r--r--apps/files_versions/lib/Events/VersionRestoredEvent.php33
-rw-r--r--apps/files_versions/lib/Listener/LegacyRollbackListener.php35
-rw-r--r--apps/files_versions/lib/Versions/VersionManager.php14
-rw-r--r--apps/files_versions/tests/Versions/VersionManagerTest.php76
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));
+ }
}