nextcloud/apps/files_versions/lib/AppInfo/Application.php
Ferdinand Thiessen 4e816f70d1 feat(files_versions): allow to block version creation using WFE
This allows users to create workflows to block the versions creation
for some files, based on tags or other conditions using the workflow
engine.
The usecase would be compliance to allow configure some rules to prevent
versioning.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
2026-06-01 16:06:46 +00:00

136 lines
5.9 KiB
PHP

<?php
/**
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OCA\Files_Versions\AppInfo;
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\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;
use OCA\Files_Versions\Versions\VersionManager;
use OCP\App\IAppManager;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\Files\Events\Node\BeforeNodeCopiedEvent;
use OCP\Files\Events\Node\BeforeNodeDeletedEvent;
use OCP\Files\Events\Node\BeforeNodeRenamedEvent;
use OCP\Files\Events\Node\BeforeNodeTouchedEvent;
use OCP\Files\Events\Node\BeforeNodeWrittenEvent;
use OCP\Files\Events\Node\NodeCopiedEvent;
use OCP\Files\Events\Node\NodeCreatedEvent;
use OCP\Files\Events\Node\NodeDeletedEvent;
use OCP\Files\Events\Node\NodeRenamedEvent;
use OCP\Files\Events\Node\NodeTouchedEvent;
use OCP\Files\Events\Node\NodeWrittenEvent;
use OCP\WorkflowEngine\Events\LoadSettingsScriptsEvent;
use OCP\WorkflowEngine\Events\RegisterOperationsEvent;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
class Application extends App implements IBootstrap {
public const APP_ID = 'files_versions';
public function __construct(array $urlParams = []) {
parent::__construct(self::APP_ID, $urlParams);
}
#[\Override]
public function register(IRegistrationContext $context): void {
/**
* Register capabilities
*/
$context->registerCapability(Capabilities::class);
/**
* Register $principalBackend for the DAV collection
*/
$context->registerServiceAlias('principalBackend', Principal::class);
$context->registerServiceAlias(IVersionManager::class, VersionManager::class);
/**
* Register Events
*/
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
$context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class);
$context->registerEventListener(BeforeNodeRenamedEvent::class, VersionStorageMoveListener::class);
$context->registerEventListener(NodeRenamedEvent::class, VersionStorageMoveListener::class);
$context->registerEventListener(BeforeNodeCopiedEvent::class, VersionStorageMoveListener::class);
$context->registerEventListener(NodeCopiedEvent::class, VersionStorageMoveListener::class);
$context->registerEventListener(NodeCreatedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeTouchedEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeTouchedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeWrittenEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeWrittenEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeDeletedEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeDeletedEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeRenamedEvent::class, FileEventsListener::class);
$context->registerEventListener(NodeCopiedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeRenamedEvent::class, FileEventsListener::class);
$context->registerEventListener(BeforeNodeCopiedEvent::class, FileEventsListener::class);
// 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);
}
#[\Override]
public function boot(IBootContext $context): void {
$context->injectFn(\Closure::fromCallable([$this, 'registerVersionBackends']));
}
public function registerVersionBackends(ContainerInterface $container, IAppManager $appManager, LoggerInterface $logger): void {
foreach ($appManager->getEnabledApps() as $app) {
$appInfo = $appManager->getAppInfo($app);
if (isset($appInfo['versions'])) {
$backends = $appInfo['versions'];
foreach ($backends as $backend) {
if (isset($backend['@value'])) {
$this->loadBackend($backend, $container, $logger);
} else {
foreach ($backend as $singleBackend) {
$this->loadBackend($singleBackend, $container, $logger);
}
}
}
}
}
}
private function loadBackend(array $backend, ContainerInterface $container, LoggerInterface $logger): void {
/** @var IVersionManager $versionManager */
$versionManager = $container->get(IVersionManager::class);
$class = $backend['@value'];
$for = $backend['@attributes']['for'];
try {
$backendObject = $container->get($class);
$versionManager->registerBackend($for, $backendObject);
} catch (\Exception $e) {
$logger->error($e->getMessage(), ['exception' => $e]);
}
}
}