Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/files_versions/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => $baseDir . '/../lib/Events/VersionCreatedEvent.php',
'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => $baseDir . '/../lib/Events/VersionRestoredEvent.php',
'OCA\\Files_Versions\\Expiration' => $baseDir . '/../lib/Expiration.php',
'OCA\\Files_Versions\\Listener\\CreateVersionListenerForWorkflow' => $baseDir . '/../lib/Listener/CreateVersionListenerForWorkflow.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\\RegisterWorkflowIntegrationListener' => $baseDir . '/../lib/Listener/RegisterWorkflowIntegrationListener.php',
'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => $baseDir . '/../lib/Listener/VersionAuthorListener.php',
'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => $baseDir . '/../lib/Listener/VersionStorageMoveListener.php',
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => $baseDir . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Operation' => $baseDir . '/../lib/Operation.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => $baseDir . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => $baseDir . '/../lib/Sabre/RestoreFolder.php',
'OCA\\Files_Versions\\Sabre\\RootCollection' => $baseDir . '/../lib/Sabre/RootCollection.php',
Expand Down
3 changes: 3 additions & 0 deletions apps/files_versions/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ class ComposerStaticInitFiles_Versions
'OCA\\Files_Versions\\Events\\VersionCreatedEvent' => __DIR__ . '/..' . '/../lib/Events/VersionCreatedEvent.php',
'OCA\\Files_Versions\\Events\\VersionRestoredEvent' => __DIR__ . '/..' . '/../lib/Events/VersionRestoredEvent.php',
'OCA\\Files_Versions\\Expiration' => __DIR__ . '/..' . '/../lib/Expiration.php',
'OCA\\Files_Versions\\Listener\\CreateVersionListenerForWorkflow' => __DIR__ . '/..' . '/../lib/Listener/CreateVersionListenerForWorkflow.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\\RegisterWorkflowIntegrationListener' => __DIR__ . '/..' . '/../lib/Listener/RegisterWorkflowIntegrationListener.php',
'OCA\\Files_Versions\\Listener\\VersionAuthorListener' => __DIR__ . '/..' . '/../lib/Listener/VersionAuthorListener.php',
'OCA\\Files_Versions\\Listener\\VersionStorageMoveListener' => __DIR__ . '/..' . '/../lib/Listener/VersionStorageMoveListener.php',
'OCA\\Files_Versions\\Migration\\Version1020Date20221114144058' => __DIR__ . '/..' . '/../lib/Migration/Version1020Date20221114144058.php',
'OCA\\Files_Versions\\Operation' => __DIR__ . '/..' . '/../lib/Operation.php',
'OCA\\Files_Versions\\Sabre\\Plugin' => __DIR__ . '/..' . '/../lib/Sabre/Plugin.php',
'OCA\\Files_Versions\\Sabre\\RestoreFolder' => __DIR__ . '/..' . '/../lib/Sabre/RestoreFolder.php',
'OCA\\Files_Versions\\Sabre\\RootCollection' => __DIR__ . '/..' . '/../lib/Sabre/RootCollection.php',
Expand Down
11 changes: 10 additions & 1 deletion apps/files_versions/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCA\Files\Event\LoadSidebar;
use OCA\Files_Versions\Capabilities;
use OCA\Files_Versions\Events\CreateVersionEvent;
use OCA\Files_Versions\Events\VersionRestoredEvent;
use OCA\Files_Versions\Listener\CreateVersionListenerForWorkflow;
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\RegisterWorkflowIntegrationListener;
use OCA\Files_Versions\Listener\VersionAuthorListener;
use OCA\Files_Versions\Listener\VersionStorageMoveListener;
use OCA\Files_Versions\Versions\IVersionManager;
Expand Down Expand Up @@ -47,6 +50,8 @@
use OCP\L10N\IFactory;
use OCP\Server;
use OCP\Share\IManager as IShareManager;
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;

Expand Down Expand Up @@ -110,8 +115,12 @@ public function register(IRegistrationContext $context): void {

// we add the version author listener with lower priority to make sure new versions already are created by FileEventsListener
$context->registerEventListener(NodeWrittenEvent::class, VersionAuthorListener::class, -1);

$context->registerEventListener(VersionRestoredEvent::class, LegacyRollbackListener::class);

// WFE integration
$context->registerEventListener(RegisterOperationsEvent::class, RegisterWorkflowIntegrationListener::class);
$context->registerEventListener(LoadSettingsScriptsEvent::class, RegisterWorkflowIntegrationListener::class);
$context->registerEventListener(CreateVersionEvent::class, CreateVersionListenerForWorkflow::class);
}

public function boot(IBootContext $context): void {
Expand Down
95 changes: 95 additions & 0 deletions apps/files_versions/lib/BlockVersioningOperation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions;

use OCA\Files_Versions\Events\CreateVersionEvent;
use OCA\WorkflowEngine\Entity\File as FileEntity;
use OCP\EventDispatcher\Event;
use OCP\Files\Folder;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\WorkflowEngine\IComplexOperation;
use OCP\WorkflowEngine\IManager;
use OCP\WorkflowEngine\IRuleMatcher;
use OCP\WorkflowEngine\ISpecificOperation;
use Psr\Log\LoggerInterface;

class BlockVersioningOperation implements ISpecificOperation, IComplexOperation {

public function __construct(
private readonly IL10N $l10n,
private readonly FileEntity $fileEntity,
private readonly LoggerInterface $logger,
private readonly IURLGenerator $urlGenerator,
) {
}

#[\Override]
public function getEntityId(): string {
return FileEntity::class;
}

#[\Override]
public function getDisplayName(): string {
return $this->l10n->t('Block versioning');
}

#[\Override]
public function getDescription(): string {
return $this->l10n->t('Automatic tag based blocking of files version creation.');
}

#[\Override]
public function getIcon(): string {
return $this->urlGenerator->imagePath('files_versions', 'app.svg');
}

#[\Override]
public function isAvailableForScope(int $scope): bool {
return $scope === IManager::SCOPE_ADMIN;
}

#[\Override]
public function validateOperation(string $name, array $checks, string $operation): void {
if (empty($checks)) {
throw new \UnexpectedValueException($this->l10n->t('No rule given'));
}
}

#[\Override]
public function onEvent(string $eventName, Event $event, IRuleMatcher $ruleMatcher): void {
if ($eventName !== CreateVersionEvent::class || !($event instanceof CreateVersionEvent)) {
return;
}

$node = $event->getNode();
$path = $node->getInternalPath();

$ruleMatcher->setFileInfo(
$node->getStorage(),
$path,
$node instanceof Folder,
);
$ruleMatcher->setEntitySubject($this->fileEntity, $node);
$ruleMatcher->setOperation($this);
$flows = $ruleMatcher->getFlows();

if ($flows !== []) {
$this->logger->debug('Blocking version creation due to matching workflow rules', [
'path' => $path,
]);
$event->disableVersions();
}
}

#[\Override]
public function getTriggerHint(): string {
return $this->l10n->t('A new version is created'); // TRANSLATORS: This will be shown as "When: " "A new version is created"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Listener;

use OCA\Files_Versions\BlockVersioningOperation;
use OCA\Files_Versions\Events\CreateVersionEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\WorkflowEngine\IManager;

/** @template-implements IEventListener<CreateVersionEvent> */
class CreateVersionListenerForWorkflow implements IEventListener {

public function __construct(
private IManager $manager,
private BlockVersioningOperation $operation,
) {
}

public function handle(Event $event): void {
if (!($event instanceof CreateVersionEvent)) {
return;
}

$this->operation->onEvent(
$event::class,
$event,
$this->manager->getRuleMatcher(),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace OCA\Files_Versions\Listener;

use OCA\Files_Versions\BlockVersioningOperation;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\Util;
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;

/** @template-implements IEventListener<RegisterOperationsEvent|LoadSettingsScriptsEvent> */
class RegisterWorkflowIntegrationListener implements IEventListener {

public function __construct(
private readonly BlockVersioningOperation $operation,
) {
}

public function handle(Event $event): void {
if ($event instanceof RegisterOperationsEvent) {
$event->registerOperation($this->operation);
} elseif ($event instanceof LoadSettingsScriptsEvent) {
Util::addScript('files_versions', 'workflow', 'workflowengine');
}
}
}
1 change: 1 addition & 0 deletions apps/files_versions/lib/Storage.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ public static function store($filename) {
}

$event = new CreateVersionEvent($file);
$eventDispatcher->dispatchTyped($event);
$eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
if ($event->shouldCreateVersion() === false) {
return false;
Expand Down
12 changes: 12 additions & 0 deletions apps/files_versions/src/workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*!
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

window.addEventListener('DOMContentLoaded', () => {
globalThis.OCA.WorkflowEngine.registerOperator({
id: 'OCA\\Files_Versions\\BlockVersioningOperation',
color: '#ff5900',
operation: 'deny',
})
})
1 change: 1 addition & 0 deletions build/frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const modules = {
},
files_versions: {
'sidebar-tab': resolve(import.meta.dirname, 'apps/files_versions/src', 'sidebar_tab.ts'),
workflow: resolve(import.meta.dirname, 'apps/files_versions/src', 'workflow.ts'),
},
oauth2: {
'settings-admin': resolve(import.meta.dirname, 'apps/oauth2/src', 'settings-admin.ts'),
Expand Down
Loading