diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2024-11-06 08:54:40 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-06 08:54:40 +0100 |
commit | 8fab143aa486904f7a17c4f1c2f6364cd43bf9d9 (patch) | |
tree | 91381cb6382ea0d1b006ba00c9e4b7d7b418bb97 | |
parent | 01ad23aaaa3e18fa30fb6bef85e8bd2cc3c3e054 (diff) | |
parent | bcfb02f5d79796cae2fe45b9b64926eae51680a1 (diff) | |
download | nextcloud-server-8fab143aa486904f7a17c4f1c2f6364cd43bf9d9.tar.gz nextcloud-server-8fab143aa486904f7a17c4f1c2f6364cd43bf9d9.zip |
Merge pull request #48721 from nextcloud/feat/allow-getter-setter-decl-fors
-rw-r--r-- | apps/files/composer/composer/autoload_classmap.php | 4 | ||||
-rw-r--r-- | apps/files/composer/composer/autoload_static.php | 4 | ||||
-rw-r--r-- | apps/files/lib/AppInfo/Application.php | 12 | ||||
-rw-r--r-- | apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php | 39 | ||||
-rw-r--r-- | apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php | 40 | ||||
-rw-r--r-- | apps/files/lib/Settings/DeclarativeAdminSettings.php (renamed from apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php) | 36 | ||||
-rw-r--r-- | lib/composer/composer/autoload_classmap.php | 1 | ||||
-rw-r--r-- | lib/composer/composer/autoload_static.php | 1 | ||||
-rw-r--r-- | lib/private/Settings/DeclarativeManager.php | 53 | ||||
-rw-r--r-- | lib/public/Settings/DeclarativeSettingsTypes.php | 6 | ||||
-rw-r--r-- | lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php | 31 | ||||
-rw-r--r-- | tests/lib/Settings/DeclarativeManagerTest.php | 76 |
12 files changed, 183 insertions, 120 deletions
diff --git a/apps/files/composer/composer/autoload_classmap.php b/apps/files/composer/composer/autoload_classmap.php index 4be3f54c006..e9e45bbd84a 100644 --- a/apps/files/composer/composer/autoload_classmap.php +++ b/apps/files/composer/composer/autoload_classmap.php @@ -58,9 +58,6 @@ return array( 'OCA\\Files\\Event\\LoadSidebar' => $baseDir . '/../lib/Event/LoadSidebar.php', 'OCA\\Files\\Exception\\TransferOwnershipException' => $baseDir . '/../lib/Exception/TransferOwnershipException.php', 'OCA\\Files\\Helper' => $baseDir . '/../lib/Helper.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsGetValueEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsGetValueEventListener.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsRegisterFormEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsRegisterFormEventListener.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsSetValueEventListener' => $baseDir . '/../lib/Listener/DeclarativeSettingsSetValueEventListener.php', 'OCA\\Files\\Listener\\LoadSearchPluginsListener' => $baseDir . '/../lib/Listener/LoadSearchPluginsListener.php', 'OCA\\Files\\Listener\\LoadSidebarListener' => $baseDir . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files\\Listener\\RenderReferenceEventListener' => $baseDir . '/../lib/Listener/RenderReferenceEventListener.php', @@ -79,5 +76,6 @@ return array( 'OCA\\Files\\Service\\TagService' => $baseDir . '/../lib/Service/TagService.php', 'OCA\\Files\\Service\\UserConfig' => $baseDir . '/../lib/Service/UserConfig.php', 'OCA\\Files\\Service\\ViewConfig' => $baseDir . '/../lib/Service/ViewConfig.php', + 'OCA\\Files\\Settings\\DeclarativeAdminSettings' => $baseDir . '/../lib/Settings/DeclarativeAdminSettings.php', 'OCA\\Files\\Settings\\PersonalSettings' => $baseDir . '/../lib/Settings/PersonalSettings.php', ); diff --git a/apps/files/composer/composer/autoload_static.php b/apps/files/composer/composer/autoload_static.php index 292768fc64f..59695e60fc7 100644 --- a/apps/files/composer/composer/autoload_static.php +++ b/apps/files/composer/composer/autoload_static.php @@ -73,9 +73,6 @@ class ComposerStaticInitFiles 'OCA\\Files\\Event\\LoadSidebar' => __DIR__ . '/..' . '/../lib/Event/LoadSidebar.php', 'OCA\\Files\\Exception\\TransferOwnershipException' => __DIR__ . '/..' . '/../lib/Exception/TransferOwnershipException.php', 'OCA\\Files\\Helper' => __DIR__ . '/..' . '/../lib/Helper.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsGetValueEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsGetValueEventListener.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsRegisterFormEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsRegisterFormEventListener.php', - 'OCA\\Files\\Listener\\DeclarativeSettingsSetValueEventListener' => __DIR__ . '/..' . '/../lib/Listener/DeclarativeSettingsSetValueEventListener.php', 'OCA\\Files\\Listener\\LoadSearchPluginsListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSearchPluginsListener.php', 'OCA\\Files\\Listener\\LoadSidebarListener' => __DIR__ . '/..' . '/../lib/Listener/LoadSidebarListener.php', 'OCA\\Files\\Listener\\RenderReferenceEventListener' => __DIR__ . '/..' . '/../lib/Listener/RenderReferenceEventListener.php', @@ -94,6 +91,7 @@ class ComposerStaticInitFiles 'OCA\\Files\\Service\\TagService' => __DIR__ . '/..' . '/../lib/Service/TagService.php', 'OCA\\Files\\Service\\UserConfig' => __DIR__ . '/..' . '/../lib/Service/UserConfig.php', 'OCA\\Files\\Service\\ViewConfig' => __DIR__ . '/..' . '/../lib/Service/ViewConfig.php', + 'OCA\\Files\\Settings\\DeclarativeAdminSettings' => __DIR__ . '/..' . '/../lib/Settings/DeclarativeAdminSettings.php', 'OCA\\Files\\Settings\\PersonalSettings' => __DIR__ . '/..' . '/../lib/Settings/PersonalSettings.php', ); diff --git a/apps/files/lib/AppInfo/Application.php b/apps/files/lib/AppInfo/Application.php index 3d2d0527072..d50a8d14f5a 100644 --- a/apps/files/lib/AppInfo/Application.php +++ b/apps/files/lib/AppInfo/Application.php @@ -16,9 +16,6 @@ use OCA\Files\Controller\ApiController; use OCA\Files\DirectEditingCapabilities; use OCA\Files\Event\LoadSearchPlugins; use OCA\Files\Event\LoadSidebar; -use OCA\Files\Listener\DeclarativeSettingsGetValueEventListener; -use OCA\Files\Listener\DeclarativeSettingsRegisterFormEventListener; -use OCA\Files\Listener\DeclarativeSettingsSetValueEventListener; use OCA\Files\Listener\LoadSearchPluginsListener; use OCA\Files\Listener\LoadSidebarListener; use OCA\Files\Listener\RenderReferenceEventListener; @@ -28,6 +25,7 @@ use OCA\Files\Search\FilesSearchProvider; use OCA\Files\Service\TagService; use OCA\Files\Service\UserConfig; use OCA\Files\Service\ViewConfig; +use OCA\Files\Settings\DeclarativeAdminSettings; use OCP\Activity\IManager as IActivityManager; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -49,9 +47,6 @@ use OCP\IRequest; use OCP\IServerContainer; use OCP\ITagManager; use OCP\IUserSession; -use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; -use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent; -use OCP\Settings\Events\DeclarativeSettingsSetValueEvent; use OCP\Share\IManager as IShareManager; use OCP\Util; use Psr\Container\ContainerInterface; @@ -111,6 +106,8 @@ class Application extends App implements IBootstrap { $context->registerCapability(Capabilities::class); $context->registerCapability(DirectEditingCapabilities::class); + $context->registerDeclarativeSettings(DeclarativeAdminSettings::class); + $context->registerEventListener(LoadSidebar::class, LoadSidebarListener::class); $context->registerEventListener(RenderReferenceEvent::class, RenderReferenceEventListener::class); $context->registerEventListener(BeforeNodeRenamedEvent::class, SyncLivePhotosListener::class); @@ -119,9 +116,6 @@ class Application extends App implements IBootstrap { $context->registerEventListener(BeforeNodeCopiedEvent::class, SyncLivePhotosListener::class); $context->registerEventListener(NodeCopiedEvent::class, SyncLivePhotosListener::class); $context->registerEventListener(LoadSearchPlugins::class, LoadSearchPluginsListener::class); - $context->registerEventListener(DeclarativeSettingsRegisterFormEvent::class, DeclarativeSettingsRegisterFormEventListener::class); - $context->registerEventListener(DeclarativeSettingsGetValueEvent::class, DeclarativeSettingsGetValueEventListener::class); - $context->registerEventListener(DeclarativeSettingsSetValueEvent::class, DeclarativeSettingsSetValueEventListener::class); $context->registerSearchProvider(FilesSearchProvider::class); diff --git a/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php b/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php deleted file mode 100644 index b1d0ee3a395..00000000000 --- a/apps/files/lib/Listener/DeclarativeSettingsGetValueEventListener.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php - -declare(strict_types=1); -/** - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -namespace OCA\Files\Listener; - -use OCA\Files\AppInfo\Application; -use OCA\Files\Service\SettingsService; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventListener; -use OCP\Settings\Events\DeclarativeSettingsGetValueEvent; - -/** @template-implements IEventListener<DeclarativeSettingsGetValueEvent> */ -class DeclarativeSettingsGetValueEventListener implements IEventListener { - - public function __construct( - private SettingsService $service, - ) { - } - - public function handle(Event $event): void { - if (!($event instanceof DeclarativeSettingsGetValueEvent)) { - return; - } - - if ($event->getApp() !== Application::APP_ID) { - return; - } - - $event->setValue( - match($event->getFieldId()) { - 'windows_support' => $this->service->hasFilesWindowsSupport(), - } - ); - } -} diff --git a/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php b/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php deleted file mode 100644 index a3be2b9141e..00000000000 --- a/apps/files/lib/Listener/DeclarativeSettingsSetValueEventListener.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -declare(strict_types=1); -/** - * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ -namespace OCA\Files\Listener; - -use OCA\Files\AppInfo\Application; -use OCA\Files\Service\SettingsService; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventListener; -use OCP\Settings\Events\DeclarativeSettingsSetValueEvent; - -/** @template-implements IEventListener<DeclarativeSettingsSetValueEvent> */ -class DeclarativeSettingsSetValueEventListener implements IEventListener { - - public function __construct( - private SettingsService $service, - ) { - } - - public function handle(Event $event): void { - if (!($event instanceof DeclarativeSettingsSetValueEvent)) { - return; - } - - if ($event->getApp() !== Application::APP_ID) { - return; - } - - switch ($event->getFieldId()) { - case 'windows_support': - $this->service->setFilesWindowsSupport((bool)$event->getValue()); - $event->stopPropagation(); - break; - } - } -} diff --git a/apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php b/apps/files/lib/Settings/DeclarativeAdminSettings.php index 51832e89ecb..e509ad2233b 100644 --- a/apps/files/lib/Listener/DeclarativeSettingsRegisterFormEventListener.php +++ b/apps/files/lib/Settings/DeclarativeAdminSettings.php @@ -2,32 +2,42 @@ declare(strict_types=1); /** - * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -namespace OCA\Files\Listener; +namespace OCA\Files\Settings; -use OCA\Files\AppInfo\Application; -use OCP\EventDispatcher\Event; -use OCP\EventDispatcher\IEventListener; +use OCA\Files\Service\SettingsService; use OCP\IL10N; +use OCP\IUser; use OCP\Settings\DeclarativeSettingsTypes; -use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent; +use OCP\Settings\IDeclarativeSettingsFormWithHandlers; -/** @template-implements IEventListener<DeclarativeSettingsRegisterFormEvent> */ -class DeclarativeSettingsRegisterFormEventListener implements IEventListener { +class DeclarativeAdminSettings implements IDeclarativeSettingsFormWithHandlers { public function __construct( private IL10N $l, + private SettingsService $service, ) { } - public function handle(Event $event): void { - if (!($event instanceof DeclarativeSettingsRegisterFormEvent)) { - return; + public function getValue(string $fieldId, IUser $user): mixed { + return match($fieldId) { + 'windows_support' => $this->service->hasFilesWindowsSupport(), + default => throw new \InvalidArgumentException('Unexpected field id ' . $fieldId), + }; + } + + public function setValue(string $fieldId, mixed $value, IUser $user): void { + switch ($fieldId) { + case 'windows_support': + $this->service->setFilesWindowsSupport((bool)$value); + break; } + } - $event->registerSchema(Application::APP_ID, [ + public function getSchema(): array { + return [ 'id' => 'files-filename-support', 'priority' => 10, 'section_type' => DeclarativeSettingsTypes::SECTION_TYPE_ADMIN, @@ -45,6 +55,6 @@ class DeclarativeSettingsRegisterFormEventListener implements IEventListener { 'default' => false, ], ], - ]); + ]; } } diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index ef9af33414f..7265edfe95f 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -698,6 +698,7 @@ return array( 'OCP\\Settings\\Events\\DeclarativeSettingsSetValueEvent' => $baseDir . '/lib/public/Settings/Events/DeclarativeSettingsSetValueEvent.php', 'OCP\\Settings\\IDeclarativeManager' => $baseDir . '/lib/public/Settings/IDeclarativeManager.php', 'OCP\\Settings\\IDeclarativeSettingsForm' => $baseDir . '/lib/public/Settings/IDeclarativeSettingsForm.php', + 'OCP\\Settings\\IDeclarativeSettingsFormWithHandlers' => $baseDir . '/lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php', 'OCP\\Settings\\IDelegatedSettings' => $baseDir . '/lib/public/Settings/IDelegatedSettings.php', 'OCP\\Settings\\IIconSection' => $baseDir . '/lib/public/Settings/IIconSection.php', 'OCP\\Settings\\IManager' => $baseDir . '/lib/public/Settings/IManager.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index 99f8afb61f1..4bac34425ac 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -731,6 +731,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2 'OCP\\Settings\\Events\\DeclarativeSettingsSetValueEvent' => __DIR__ . '/../../..' . '/lib/public/Settings/Events/DeclarativeSettingsSetValueEvent.php', 'OCP\\Settings\\IDeclarativeManager' => __DIR__ . '/../../..' . '/lib/public/Settings/IDeclarativeManager.php', 'OCP\\Settings\\IDeclarativeSettingsForm' => __DIR__ . '/../../..' . '/lib/public/Settings/IDeclarativeSettingsForm.php', + 'OCP\\Settings\\IDeclarativeSettingsFormWithHandlers' => __DIR__ . '/../../..' . '/lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php', 'OCP\\Settings\\IDelegatedSettings' => __DIR__ . '/../../..' . '/lib/public/Settings/IDelegatedSettings.php', 'OCP\\Settings\\IIconSection' => __DIR__ . '/../../..' . '/lib/public/Settings/IIconSection.php', 'OCP\\Settings\\IManager' => __DIR__ . '/../../..' . '/lib/public/Settings/IManager.php', diff --git a/lib/private/Settings/DeclarativeManager.php b/lib/private/Settings/DeclarativeManager.php index d8c25c9a5c7..dea0c678f20 100644 --- a/lib/private/Settings/DeclarativeManager.php +++ b/lib/private/Settings/DeclarativeManager.php @@ -22,6 +22,7 @@ use OCP\Settings\Events\DeclarativeSettingsRegisterFormEvent; use OCP\Settings\Events\DeclarativeSettingsSetValueEvent; use OCP\Settings\IDeclarativeManager; use OCP\Settings\IDeclarativeSettingsForm; +use OCP\Settings\IDeclarativeSettingsFormWithHandlers; use Psr\Log\LoggerInterface; /** @@ -32,6 +33,15 @@ use Psr\Log\LoggerInterface; * @psalm-import-type DeclarativeSettingsFormSchemaWithoutValues from IDeclarativeSettingsForm */ class DeclarativeManager implements IDeclarativeManager { + + /** @var array<string, list<IDeclarativeSettingsForm>> */ + private array $declarativeForms = []; + + /** + * @var array<string, list<DeclarativeSettingsFormSchemaWithoutValues>> + */ + private array $appSchemas = []; + public function __construct( private IEventDispatcher $eventDispatcher, private IGroupManager $groupManager, @@ -43,11 +53,6 @@ class DeclarativeManager implements IDeclarativeManager { } /** - * @var array<string, list<DeclarativeSettingsFormSchemaWithoutValues>> - */ - private array $appSchemas = []; - - /** * @inheritdoc */ public function registerSchema(string $app, array $schema): void { @@ -77,11 +82,15 @@ class DeclarativeManager implements IDeclarativeManager { * @inheritdoc */ public function loadSchemas(): void { - $declarativeSettings = $this->coordinator->getRegistrationContext()->getDeclarativeSettings(); - foreach ($declarativeSettings as $declarativeSetting) { - /** @var IDeclarativeSettingsForm $declarativeSettingObject */ - $declarativeSettingObject = Server::get($declarativeSetting->getService()); - $this->registerSchema($declarativeSetting->getAppId(), $declarativeSettingObject->getSchema()); + if (empty($this->declarativeForms)) { + $declarativeSettings = $this->coordinator->getRegistrationContext()->getDeclarativeSettings(); + foreach ($declarativeSettings as $declarativeSetting) { + $app = $declarativeSetting->getAppId(); + /** @var IDeclarativeSettingsForm $declarativeForm */ + $declarativeForm = Server::get($declarativeSetting->getService()); + $this->registerSchema($app, $declarativeForm->getSchema()); + $this->declarativeForms[$app][] = $declarativeForm; + } } $this->eventDispatcher->dispatchTyped(new DeclarativeSettingsRegisterFormEvent($this)); @@ -224,6 +233,10 @@ class DeclarativeManager implements IDeclarativeManager { $storageType = $this->getStorageType($app, $fieldId); switch ($storageType) { case DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL: + $form = $this->getForm($app, $formId); + if ($form !== null && $form instanceof IDeclarativeSettingsFormWithHandlers) { + return $form->getValue($fieldId, $user); + } $event = new DeclarativeSettingsGetValueEvent($user, $app, $formId, $fieldId); $this->eventDispatcher->dispatchTyped($event); return $event->getValue(); @@ -244,6 +257,12 @@ class DeclarativeManager implements IDeclarativeManager { $storageType = $this->getStorageType($app, $fieldId); switch ($storageType) { case DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL: + $form = $this->getForm($app, $formId); + if ($form !== null && $form instanceof IDeclarativeSettingsFormWithHandlers) { + $form->setValue($fieldId, $value, $user); + break; + } + // fall back to event handling $this->eventDispatcher->dispatchTyped(new DeclarativeSettingsSetValueEvent($user, $app, $formId, $fieldId, $value)); break; case DeclarativeSettingsTypes::STORAGE_TYPE_INTERNAL: @@ -254,6 +273,20 @@ class DeclarativeManager implements IDeclarativeManager { } } + /** + * If a declarative setting was registered as a form and not just a schema + * then this will yield the registering form. + */ + private function getForm(string $app, string $formId): ?IDeclarativeSettingsForm { + $allForms = $this->declarativeForms[$app] ?? []; + foreach ($allForms as $form) { + if ($form->getSchema()['id'] === $formId) { + return $form; + } + } + return null; + } + private function getInternalValue(IUser $user, string $app, string $formId, string $fieldId): mixed { $sectionType = $this->getSectionType($app, $fieldId); $defaultValue = $this->getDefaultValue($app, $formId, $fieldId); diff --git a/lib/public/Settings/DeclarativeSettingsTypes.php b/lib/public/Settings/DeclarativeSettingsTypes.php index 82444af9b82..7edf0cbdd6e 100644 --- a/lib/public/Settings/DeclarativeSettingsTypes.php +++ b/lib/public/Settings/DeclarativeSettingsTypes.php @@ -32,8 +32,9 @@ final class DeclarativeSettingsTypes { /** * IDeclarativeSettingsForm storage_type which is determines where and how the config value is stored * - * - * For `external` storage_type the app implementing \OCP\Settings\SetDeclarativeSettingsValueEvent and \OCP\Settings\GetDeclarativeSettingsValueEvent events is responsible for storing and retrieving the config value. + * For `external` storage_type the app needs to either implement event listeners for \OCP\Settings\SetDeclarativeSettingsValueEvent + * and \OCP\Settings\GetDeclarativeSettingsValueEvent or the IDeclarativeSettingsForm also needs to implement + * IDeclarativeSettingsFormWithHandlers for storing and retrieving the config value. * * @since 29.0.0 */ @@ -43,7 +44,6 @@ final class DeclarativeSettingsTypes { * IDeclarativeSettingsForm storage_type which is determines where and how the config value is stored * * For `internal` storage_type the config value is stored in default `appconfig` and `preferences` tables. - * For `external` storage_type the app implementing \OCP\Settings\SetDeclarativeSettingsValueEvent and \OCP\Settings\GetDeclarativeSettingsValueEvent events is responsible for storing and retrieving the config value. * * @since 29.0.0 */ diff --git a/lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php b/lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php new file mode 100644 index 00000000000..180df73d995 --- /dev/null +++ b/lib/public/Settings/IDeclarativeSettingsFormWithHandlers.php @@ -0,0 +1,31 @@ +<?php + +declare(strict_types=1); + +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\Settings; + +use OCP\IUser; + +/** + * @since 31.0.0 + */ +interface IDeclarativeSettingsFormWithHandlers extends IDeclarativeSettingsForm { + + /** + * This function is called to get the current value of a specific forms field. + * @since 31.0.0 + */ + public function getValue(string $fieldId, IUser $user): mixed; + + /** + * This function is called when a user updated a form field to persist the setting. + * @since 31.0.0 + */ + public function setValue(string $fieldId, mixed $value, IUser $user): void; + +} diff --git a/tests/lib/Settings/DeclarativeManagerTest.php b/tests/lib/Settings/DeclarativeManagerTest.php index f0d97c7ea25..522264acd8c 100644 --- a/tests/lib/Settings/DeclarativeManagerTest.php +++ b/tests/lib/Settings/DeclarativeManagerTest.php @@ -10,6 +10,8 @@ declare(strict_types=1); namespace Test\Settings; use OC\AppFramework\Bootstrap\Coordinator; +use OC\AppFramework\Bootstrap\RegistrationContext; +use OC\AppFramework\Bootstrap\ServiceRegistration; use OC\Settings\DeclarativeManager; use OCP\EventDispatcher\IEventDispatcher; use OCP\IAppConfig; @@ -19,6 +21,8 @@ use OCP\IUser; use OCP\Settings\DeclarativeSettingsTypes; use OCP\Settings\Events\DeclarativeSettingsSetValueEvent; use OCP\Settings\IDeclarativeManager; +use OCP\Settings\IDeclarativeSettingsForm; +use OCP\Settings\IDeclarativeSettingsFormWithHandlers; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -52,6 +56,8 @@ class DeclarativeManagerTest extends TestCase { /** @var IUser|MockObject */ private $adminUser; + private IDeclarativeSettingsForm&MockObject $closureForm; + public const validSchemaAllFields = [ 'id' => 'test_form_1', 'priority' => 10, @@ -518,4 +524,74 @@ class DeclarativeManagerTest extends TestCase { $this->expectException(\Exception::class); $this->declarativeManager->getFormsWithValues($this->user, $schema['section_type'], $schema['section_id']); } + + /** + * Ensure that the `setValue` method is called if the form implements the handler interface. + */ + public function testSetValueWithHandler(): void { + $schema = self::validSchemaAllFields; + $schema['storage_type'] = DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL; + + $form = $this->createMock(IDeclarativeSettingsFormWithHandlers::class); + $form->expects(self::atLeastOnce()) + ->method('getSchema') + ->willReturn($schema); + // The setter should be called once! + $form->expects(self::once()) + ->method('setValue') + ->with('test_field_2', 'some password', $this->adminUser); + + \OC::$server->registerService('OCA\\Testing\\Settings\\DeclarativeForm', fn () => $form, false); + + $context = $this->createMock(RegistrationContext::class); + $context->expects(self::atLeastOnce()) + ->method('getDeclarativeSettings') + ->willReturn([new ServiceRegistration('testing', 'OCA\\Testing\\Settings\\DeclarativeForm')]); + + $this->coordinator->expects(self::atLeastOnce()) + ->method('getRegistrationContext') + ->willReturn($context); + + $this->declarativeManager->loadSchemas(); + + $this->eventDispatcher->expects(self::never()) + ->method('dispatchTyped'); + + $this->declarativeManager->setValue($this->adminUser, 'testing', 'test_form_1', 'test_field_2', 'some password'); + } + + public function testGetValueWithHandler(): void { + $schema = self::validSchemaAllFields; + $schema['storage_type'] = DeclarativeSettingsTypes::STORAGE_TYPE_EXTERNAL; + + $form = $this->createMock(IDeclarativeSettingsFormWithHandlers::class); + $form->expects(self::atLeastOnce()) + ->method('getSchema') + ->willReturn($schema); + // The setter should be called once! + $form->expects(self::once()) + ->method('getValue') + ->with('test_field_2', $this->adminUser) + ->willReturn('very secret password'); + + \OC::$server->registerService('OCA\\Testing\\Settings\\DeclarativeForm', fn () => $form, false); + + $context = $this->createMock(RegistrationContext::class); + $context->expects(self::atLeastOnce()) + ->method('getDeclarativeSettings') + ->willReturn([new ServiceRegistration('testing', 'OCA\\Testing\\Settings\\DeclarativeForm')]); + + $this->coordinator->expects(self::atLeastOnce()) + ->method('getRegistrationContext') + ->willReturn($context); + + $this->declarativeManager->loadSchemas(); + + $this->eventDispatcher->expects(self::never()) + ->method('dispatchTyped'); + + $password = $this->invokePrivate($this->declarativeManager, 'getValue', [$this->adminUser, 'testing', 'test_form_1', 'test_field_2']); + self::assertEquals('very secret password', $password); + } + } |