From 3cb72e5d72d17e05464dbb842208c6ca3ff91cb2 Mon Sep 17 00:00:00 2001 From: ciastektk Date: Mon, 11 Dec 2023 13:17:44 +0100 Subject: [PATCH] IBX-7275: Exposed base admin UI configuration in REST API (#1027) * Added ApplicationConfig REST Value * Added ApplicationConfigController * Added ApplicationConfigRestResolver * Added ApplicationConfigVisitor * [PHPStan] Regenerated baseline * Fixed Resolvers service definition * Fixed phpdoc for ApplicationConfig::getConfig * Fixes after review * Fixed variables name * Reworked generating custom output --- .../ApplicationConfigController.php | 28 ++++++ src/bundle/Resources/config/routing_rest.yaml | 11 +++ .../config/services/controllers.yaml | 5 ++ .../Resources/config/services/rest.yaml | 10 +++ .../config/services/ui_config/common.yaml | 16 ++++ ...pplicationConfigRestGeneratorInterface.php | 24 +++++ ...onConfigRestGeneratorRegistryInterface.php | 23 +++++ ...ApplicationConfigRestGeneratorRegistry.php | 90 +++++++++++++++++++ ...ProfilePictureFieldConfigRestGenerator.php | 43 +++++++++ .../Generator/UserConfigRestGenerator.php | 43 +++++++++ .../ApplicationConfigVisitor.php | 80 +++++++++++++++++ src/lib/REST/Value/ApplicationConfig.php | 33 +++++++ 12 files changed, 406 insertions(+) create mode 100644 src/bundle/Controller/ApplicationConfigController.php create mode 100644 src/contracts/REST/ApplicationConfigRestGeneratorInterface.php create mode 100644 src/contracts/REST/ApplicationConfigRestGeneratorRegistryInterface.php create mode 100644 src/lib/REST/Generator/ApplicationConfigRestGeneratorRegistry.php create mode 100644 src/lib/REST/Generator/ProfilePictureFieldConfigRestGenerator.php create mode 100644 src/lib/REST/Generator/UserConfigRestGenerator.php create mode 100644 src/lib/REST/Output/ValueObjectVisitor/ApplicationConfigVisitor.php create mode 100644 src/lib/REST/Value/ApplicationConfig.php diff --git a/src/bundle/Controller/ApplicationConfigController.php b/src/bundle/Controller/ApplicationConfigController.php new file mode 100644 index 0000000000..d4551e9902 --- /dev/null +++ b/src/bundle/Controller/ApplicationConfigController.php @@ -0,0 +1,28 @@ +aggregator = $aggregator; + } + + public function loadConfigAction(): ApplicationConfig + { + return new ApplicationConfig($this->aggregator->getConfig()); + } +} diff --git a/src/bundle/Resources/config/routing_rest.yaml b/src/bundle/Resources/config/routing_rest.yaml index e6ddb5e3de..a88d44de15 100644 --- a/src/bundle/Resources/config/routing_rest.yaml +++ b/src/bundle/Resources/config/routing_rest.yaml @@ -101,3 +101,14 @@ ibexa.udw.accordion.gridview.data: methods: [GET] options: expose: true + +# +# ApplicationConfig +# + +ibexa.rest.application_config: + path: /application-config + controller: 'Ibexa\Bundle\AdminUi\Controller\ApplicationConfigController::loadConfigAction' + methods: [GET] + options: + expose: true diff --git a/src/bundle/Resources/config/services/controllers.yaml b/src/bundle/Resources/config/services/controllers.yaml index ccdb984f56..9b6b07bff2 100644 --- a/src/bundle/Resources/config/services/controllers.yaml +++ b/src/bundle/Resources/config/services/controllers.yaml @@ -222,5 +222,10 @@ services: Ibexa\Bundle\AdminUi\Controller\Permission\LanguageLimitationController: parent: Ibexa\Contracts\AdminUi\Controller\Controller autowire: true + + + Ibexa\Bundle\AdminUi\Controller\ApplicationConfigController: + parent: Ibexa\Rest\Server\Controller + autowire: true tags: - controller.service_arguments diff --git a/src/bundle/Resources/config/services/rest.yaml b/src/bundle/Resources/config/services/rest.yaml index 70e51cd652..e57132ce18 100644 --- a/src/bundle/Resources/config/services/rest.yaml +++ b/src/bundle/Resources/config/services/rest.yaml @@ -77,3 +77,13 @@ services: parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor tags: - { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\UniversalDiscovery\AccordionData } + + # + # ApplicationConfig + # + Ibexa\AdminUi\REST\Output\ValueObjectVisitor\ApplicationConfigVisitor: + parent: Ibexa\Contracts\Rest\Output\ValueObjectVisitor + arguments: + $applicationConfigRestGeneratorRegistry: '@Ibexa\Contracts\AdminUi\REST\ApplicationConfigRestGeneratorRegistryInterface' + tags: + - { name: ibexa.rest.output.value_object.visitor, type: Ibexa\AdminUi\REST\Value\ApplicationConfig } diff --git a/src/bundle/Resources/config/services/ui_config/common.yaml b/src/bundle/Resources/config/services/ui_config/common.yaml index 06d8621f62..15f198bfea 100644 --- a/src/bundle/Resources/config/services/ui_config/common.yaml +++ b/src/bundle/Resources/config/services/ui_config/common.yaml @@ -134,3 +134,19 @@ services: $resultLimit: '%ibexa.site_access.config.default.search.suggestion.result_limit%' tags: - { name: ibexa.admin_ui.config.provider, key: 'suggestions' } + + # Resolvers + Ibexa\AdminUi\REST\Generator\ApplicationConfigRestGeneratorRegistry: + arguments: + $generators: !tagged_iterator { tag: ibexa.admin_ui.config.provider.rest.generator } + + Ibexa\Contracts\AdminUi\REST\ApplicationConfigRestGeneratorRegistryInterface: + alias: Ibexa\AdminUi\REST\Generator\ApplicationConfigRestGeneratorRegistry + + Ibexa\AdminUi\REST\Generator\UserConfigRestGenerator: + tags: + - { name: ibexa.admin_ui.config.provider.rest.generator, priority: -10 } + + Ibexa\AdminUi\REST\Generator\ProfilePictureFieldConfigRestGenerator: + tags: + - { name: ibexa.admin_ui.config.provider.rest.generator, priority: -10 } diff --git a/src/contracts/REST/ApplicationConfigRestGeneratorInterface.php b/src/contracts/REST/ApplicationConfigRestGeneratorInterface.php new file mode 100644 index 0000000000..eedeb7dca9 --- /dev/null +++ b/src/contracts/REST/ApplicationConfigRestGeneratorInterface.php @@ -0,0 +1,24 @@ + + */ + public function getGenerators(string $namespace): iterable; +} diff --git a/src/lib/REST/Generator/ApplicationConfigRestGeneratorRegistry.php b/src/lib/REST/Generator/ApplicationConfigRestGeneratorRegistry.php new file mode 100644 index 0000000000..ab3110c6b2 --- /dev/null +++ b/src/lib/REST/Generator/ApplicationConfigRestGeneratorRegistry.php @@ -0,0 +1,90 @@ + */ + private iterable $generators; + + /** + * @param iterable<\Ibexa\Contracts\AdminUi\REST\ApplicationConfigRestGeneratorInterface> $generators + */ + public function __construct(iterable $generators) + { + $this->generators = $generators; + } + + public function hasGenerator( + string $namespace, + string $parameter + ): bool { + foreach ($this->generators as $generator) { + if ( + $generator->supportsNamespace($namespace) + && $generator->supportsParameter($parameter) + ) { + return true; + } + } + + return false; + } + + public function hasGenerators(string $namespace): bool + { + foreach ($this->generators as $generator) { + if ($generator->supportsNamespace($namespace)) { + return true; + } + } + + return false; + } + + public function getGenerator(string $namespace, string $parameter): ApplicationConfigRestGeneratorInterface + { + foreach ($this->generators as $generator) { + if ( + $generator->supportsNamespace($namespace) + && $generator->supportsParameter($parameter) + ) { + return $generator; + } + } + + throw new RuntimeException( + sprintf( + 'No Generator found for Configuration in namespace \'%s\' and parameter \'%s\'', + $namespace, + $parameter + ) + ); + } + + /** + * @return iterable<\Ibexa\Contracts\AdminUi\REST\ApplicationConfigRestGeneratorInterface> + */ + public function getGenerators(string $namespace): iterable + { + foreach ($this->generators as $generator) { + if ($generator->supportsNamespace($namespace)) { + yield $generator; + } + } + + throw new RuntimeException( + 'No Generators found for Configuration in namespace \'' . $namespace . '\'', + ); + } +} diff --git a/src/lib/REST/Generator/ProfilePictureFieldConfigRestGenerator.php b/src/lib/REST/Generator/ProfilePictureFieldConfigRestGenerator.php new file mode 100644 index 0000000000..c969589e53 --- /dev/null +++ b/src/lib/REST/Generator/ProfilePictureFieldConfigRestGenerator.php @@ -0,0 +1,43 @@ +startHashElement(self::PARAMETER); + $visitor->visitValueObject($parameter); + $generator->endHashElement(self::PARAMETER); + + return; + } + + $generator->generateFieldTypeHash(self::PARAMETER, $parameter); + } +} diff --git a/src/lib/REST/Generator/UserConfigRestGenerator.php b/src/lib/REST/Generator/UserConfigRestGenerator.php new file mode 100644 index 0000000000..fa7012755c --- /dev/null +++ b/src/lib/REST/Generator/UserConfigRestGenerator.php @@ -0,0 +1,43 @@ +startHashElement(self::PARAMETER); + $visitor->visitValueObject($parameter); + $generator->endHashElement(self::PARAMETER); + + return; + } + + $generator->generateFieldTypeHash(self::PARAMETER, $parameter); + } +} diff --git a/src/lib/REST/Output/ValueObjectVisitor/ApplicationConfigVisitor.php b/src/lib/REST/Output/ValueObjectVisitor/ApplicationConfigVisitor.php new file mode 100644 index 0000000000..eb8a26b4d4 --- /dev/null +++ b/src/lib/REST/Output/ValueObjectVisitor/ApplicationConfigVisitor.php @@ -0,0 +1,80 @@ +applicationConfigRestGeneratorRegistry = $applicationConfigRestGeneratorRegistry; + } + + /** + * @param \Ibexa\AdminUi\REST\Value\ApplicationConfig $data + */ + public function visit(Visitor $visitor, Generator $generator, $data): void + { + $generator->startObjectElement('ApplicationConfig'); + $visitor->setHeader('Content-Type', $generator->getMediaType('ApplicationConfig')); + + foreach ($data->getConfig() as $namespace => $config) { + // Checks if namespace has internal generators to generate custom output. + if ($this->applicationConfigRestGeneratorRegistry->hasGenerators($namespace)) { + $this->visitInternalGenerator( + $visitor, + $generator, + $namespace, + $config + ); + + continue; + } + + $generator->generateFieldTypeHash($namespace, $config); + } + + $generator->endObjectElement('ApplicationConfig'); + } + + /** + * @param array $config + */ + private function visitInternalGenerator( + Visitor $visitor, + Generator $generator, + string $namespace, + array $config + ): void { + $generator->startHashElement($namespace); + + foreach ($config as $name => $value) { + if (!$this->applicationConfigRestGeneratorRegistry->hasGenerator($namespace, $name)) { + $generator->generateFieldTypeHash($name, $value); + + continue; + } + + $this->applicationConfigRestGeneratorRegistry + ->getGenerator($namespace, $name) + ->generate($value, $generator, $visitor); + } + + $generator->endHashElement($namespace); + } +} diff --git a/src/lib/REST/Value/ApplicationConfig.php b/src/lib/REST/Value/ApplicationConfig.php new file mode 100644 index 0000000000..5d8742d719 --- /dev/null +++ b/src/lib/REST/Value/ApplicationConfig.php @@ -0,0 +1,33 @@ + */ + private array $config; + + /** + * @param array $config + */ + public function __construct(array $config) + { + $this->config = $config; + } + + /** + * @return array + */ + public function getConfig(): array + { + return $this->config; + } +}