From e8d52ae7ad728d4a63a6770a849ec7f041442973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Niedzielski?= Date: Wed, 3 Jul 2024 14:33:25 +0200 Subject: [PATCH] IBX-8434: Added ProviderConfiguratorInterface to allow configuration post-processing --- phpstan-baseline.neon | 90 ++----------------- .../Resources/config/configuration.yaml | 24 +++++ src/bundle/Resources/config/ui/mappers.yaml | 2 +- .../ProviderConfiguratorInterface.php | 19 ++++ .../Provider/ConfigurableProvider.php | 48 ++++++++++ src/lib/Configuration/Provider/CustomTag.php | 24 +++-- src/lib/Configuration/UI/Mapper/CustomTag.php | 67 +++++++------- .../UI/Mapper/CustomTag/AttributeMapper.php | 13 ++- .../CustomTag/ChoiceAttributeMapper.php | 2 +- 9 files changed, 158 insertions(+), 131 deletions(-) create mode 100644 src/contracts/Configuration/ProviderConfiguratorInterface.php create mode 100644 src/lib/Configuration/Provider/ConfigurableProvider.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2e3dffb8..db03e3f1 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -315,16 +315,6 @@ parameters: count: 1 path: src/lib/Configuration/Provider/CustomStyle.php - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\Provider\\\\CustomTag\\:\\:getConfiguration\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/Provider/CustomTag.php - - - - message: "#^Property Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\Provider\\\\CustomTag\\:\\:\\$customTagConfigurationMapper \\(Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\) does not accept Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTemplateConfigMapper\\.$#" - count: 1 - path: src/lib/Configuration/Provider/CustomTag.php - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomStyle\\:\\:__construct\\(\\) has parameter \\$customStylesConfiguration with no value type specified in iterable type array\\.$#" count: 1 @@ -350,76 +340,6 @@ parameters: count: 1 path: src/lib/Configuration/UI/Mapper/CustomStyle.php - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:__construct\\(\\) has parameter \\$customTagAttributeMappers with no value type specified in iterable type Traversable\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:__construct\\(\\) has parameter \\$customTagsConfiguration with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:mapConfig\\(\\) has parameter \\$enabledCustomTags with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:mapConfig\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:translateLabels\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:translateLabels\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Property Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:\\$customTagAttributeMappers \\(array\\\\) does not accept Traversable\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Property Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\:\\:\\$customTagsConfiguration type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\AttributeMapper\\:\\:mapConfig\\(\\) has parameter \\$customTagAttributeProperties with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\AttributeMapper\\:\\:mapConfig\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\ChoiceAttributeMapper\\:\\:mapConfig\\(\\) has parameter \\$customTagAttributeProperties with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\ChoiceAttributeMapper\\:\\:mapConfig\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\CommonAttributeMapper\\:\\:mapConfig\\(\\) has parameter \\$customTagAttributeProperties with no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/CommonAttributeMapper.php - - - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTag\\\\CommonAttributeMapper\\:\\:mapConfig\\(\\) return type has no value type specified in iterable type array\\.$#" - count: 1 - path: src/lib/Configuration/UI/Mapper/CustomTag/CommonAttributeMapper.php - - message: "#^Method Ibexa\\\\FieldTypeRichText\\\\Configuration\\\\UI\\\\Mapper\\\\CustomTemplateConfigMapper\\:\\:mapConfig\\(\\) has parameter \\$enabledCustomTemplates with no value type specified in iterable type array\\.$#" count: 1 @@ -1394,10 +1314,7 @@ parameters: message: "#^Cannot access property \\$id on Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Field\\|null\\.$#" count: 1 path: tests/integration/Repository/RichTextFieldTypeIntegrationTest.php - - - message: "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\ForwardCompatibility\\\\Result\\|int\\|string\\.$#" - count: 1 - path: tests/integration/Repository/RichTextFieldTypeIntegrationTest.php + - message: "#^Cannot access property \\$value on Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Field\\|null\\.$#" count: 1 @@ -1413,6 +1330,11 @@ parameters: count: 1 path: tests/integration/Repository/RichTextFieldTypeIntegrationTest.php + - + message: "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\ForwardCompatibility\\\\Result\\|int\\|string\\.$#" + count: 1 + path: tests/integration/Repository/RichTextFieldTypeIntegrationTest.php + - message: "#^Method Ibexa\\\\Tests\\\\Integration\\\\FieldTypeRichText\\\\Repository\\\\RichTextFieldTypeIntegrationTest\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#" count: 1 diff --git a/src/bundle/Resources/config/configuration.yaml b/src/bundle/Resources/config/configuration.yaml index 1ac392cb..d355f20a 100644 --- a/src/bundle/Resources/config/configuration.yaml +++ b/src/bundle/Resources/config/configuration.yaml @@ -15,18 +15,42 @@ services: arguments: $customStyleConfigurationMapper: '@Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomStyle' + ibexa.field_type_rich_text.configuration.provider.custom_style.configurable: + class: Ibexa\FieldTypeRichText\Configuration\Provider\ConfigurableProvider + decorates: Ibexa\FieldTypeRichText\Configuration\Provider\CustomStyle + arguments: + $configurators: !tagged_iterator ibexa.field_type.richtext.configuration.custom_style.configurator + Ibexa\FieldTypeRichText\Configuration\Provider\CustomTag: arguments: $customTagConfigurationMapper: '@Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag' + ibexa.field_type_rich_text.configuration.provider.custom_tag.configurable: + class: Ibexa\FieldTypeRichText\Configuration\Provider\ConfigurableProvider + decorates: Ibexa\FieldTypeRichText\Configuration\Provider\CustomTag + arguments: + $configurators: !tagged_iterator ibexa.field_type.richtext.configuration.custom_tag.configurator + Ibexa\FieldTypeRichText\Configuration\Provider\AlloyEditor: arguments: $alloyEditorConfiguration: '%ibexa.field_type.richtext.alloy_editor%' + ibexa.field_type_rich_text.configuration.provider.alloy_editor.configurable: + class: Ibexa\FieldTypeRichText\Configuration\Provider\ConfigurableProvider + decorates: Ibexa\FieldTypeRichText\Configuration\Provider\AlloyEditor + arguments: + $configurators: !tagged_iterator ibexa.field_type.richtext.configuration.alloy_editor.configurator + Ibexa\FieldTypeRichText\Configuration\Provider\CKEditor: arguments: $customStylesConfiguration: '%ibexa.field_type.richtext.custom_styles%' + ibexa.field_type_rich_text.configuration.provider.ck_editor.configurable: + class: Ibexa\FieldTypeRichText\Configuration\Provider\ConfigurableProvider + decorates: Ibexa\FieldTypeRichText\Configuration\Provider\CKEditor + arguments: + $configurators: !tagged_iterator ibexa.field_type.richtext.configuration.ck_editor.configurator + Ibexa\FieldTypeRichText\Configuration\AggregateProvider: arguments: $providers: !tagged ibexa.field_type.richtext.configuration.provider diff --git a/src/bundle/Resources/config/ui/mappers.yaml b/src/bundle/Resources/config/ui/mappers.yaml index 098e2ece..0452f927 100644 --- a/src/bundle/Resources/config/ui/mappers.yaml +++ b/src/bundle/Resources/config/ui/mappers.yaml @@ -26,7 +26,7 @@ services: $customTagsConfiguration: '%ibexa.field_type.richtext.custom_tags%' $translatorBag: '@translator' $translationDomain: '%ibexa.field_type.richtext.custom_tags.translation_domain%' - $customTagAttributeMappers: !tagged ibexa.field_type.richtext.configuration.custom_tag.mapper + $customTagAttributeMappers: !tagged_iterator ibexa.field_type.richtext.configuration.custom_tag.mapper # RichText Custom Styles UI config mapper Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomStyle: diff --git a/src/contracts/Configuration/ProviderConfiguratorInterface.php b/src/contracts/Configuration/ProviderConfiguratorInterface.php new file mode 100644 index 00000000..b4edcf19 --- /dev/null +++ b/src/contracts/Configuration/ProviderConfiguratorInterface.php @@ -0,0 +1,19 @@ + $configuration + * + * @return array + */ + public function getConfiguration(array $configuration): array; +} diff --git a/src/lib/Configuration/Provider/ConfigurableProvider.php b/src/lib/Configuration/Provider/ConfigurableProvider.php new file mode 100644 index 00000000..6ed5a6b4 --- /dev/null +++ b/src/lib/Configuration/Provider/ConfigurableProvider.php @@ -0,0 +1,48 @@ + */ + private iterable $configurators; + + /** + * @param iterable<\Ibexa\Contracts\FieldTypeRichText\Configuration\ProviderConfiguratorInterface> $configurators + */ + public function __construct( + Provider $inner, + iterable $configurators + ) { + $this->inner = $inner; + $this->configurators = $configurators; + } + + public function getName(): string + { + return $this->inner->getName(); + } + + /** + * @return array + */ + public function getConfiguration(): array + { + $configuration = $this->inner->getConfiguration(); + foreach ($this->configurators as $configurator) { + $configuration = $configurator->getConfiguration($configuration); + } + + return $configuration; + } +} diff --git a/src/lib/Configuration/Provider/CustomTag.php b/src/lib/Configuration/Provider/CustomTag.php index 0962ce0d..aa3973f9 100644 --- a/src/lib/Configuration/Provider/CustomTag.php +++ b/src/lib/Configuration/Provider/CustomTag.php @@ -16,14 +16,28 @@ * Custom Tags configuration provider. * * @internal For internal use by RichText package + * + * @phpstan-type TConfigOutput array{ + * label: string, + * description: string, + * isInline: bool, + * icon?: string, + * attributes?: array + * } + * @phpstan-type TConfigAttributeOutput array{ + * type: string, + * required: bool, + * defaultValue: mixed, + * label: string, + * choices?: array, + * choicesLabel?: array, + * } */ final class CustomTag implements Provider { - /** @var \Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface */ - private $configResolver; + private ConfigResolverInterface $configResolver; - /** @var \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag */ - private $customTagConfigurationMapper; + private CustomTemplateConfigMapper $customTagConfigurationMapper; public function __construct( ConfigResolverInterface $configResolver, @@ -39,7 +53,7 @@ public function getName(): string } /** - * @return array RichText Custom Tags config + * @phpstan-return array RichText Custom Tags config */ public function getConfiguration(): array { diff --git a/src/lib/Configuration/UI/Mapper/CustomTag.php b/src/lib/Configuration/UI/Mapper/CustomTag.php index a9dcec69..e470945b 100644 --- a/src/lib/Configuration/UI/Mapper/CustomTag.php +++ b/src/lib/Configuration/UI/Mapper/CustomTag.php @@ -13,35 +13,47 @@ use Symfony\Component\Asset\Packages; use Symfony\Component\Translation\TranslatorBagInterface; use Symfony\Contracts\Translation\TranslatorInterface; -use Traversable; /** * RichText Custom Tag configuration mapper. * * @internal For internal use by RichText package + * + * @phpstan-type TConfig array{ + * label: string, + * description: string, + * is_inline: bool, + * icon?: string, + * attributes: array + * } + * @phpstan-type TConfigAttribute array{ + * type: string, + * required: bool, + * default_value: mixed, + * choices?: array, + * } + * + * @phpstan-import-type TConfigOutput from \Ibexa\FieldTypeRichText\Configuration\Provider\CustomTag + * @phpstan-import-type TConfigAttributeOutput from \Ibexa\FieldTypeRichText\Configuration\Provider\CustomTag */ final class CustomTag implements CustomTemplateConfigMapper { - /** @var array */ - private $customTagsConfiguration; + /** @phpstan-var array */ + private array $customTagsConfiguration; - /** @var \Symfony\Contracts\Translation\TranslatorInterface */ - private $translator; + private TranslatorInterface $translator; - /** @var \Symfony\Component\Translation\TranslatorBagInterface */ - private $translatorBag; + private TranslatorBagInterface $translatorBag; - /** @var \Symfony\Component\Asset\Packages */ - private $packages; + private Packages $packages; - /** @var \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper[] */ - private $customTagAttributeMappers; + /** @var iterable<\Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper> */ + private iterable $customTagAttributeMappers; - /** @var \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper[] */ - private $supportedTagAttributeMappersCache; + /** @var array<\Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper> */ + private array $supportedTagAttributeMappersCache; - /** @var string */ - private $translationDomain; + private string $translationDomain; /** * CustomTag configuration mapper constructor. @@ -49,12 +61,9 @@ final class CustomTag implements CustomTemplateConfigMapper * Note: type-hinting Translator to have an instance which implements * both TranslatorInterface and TranslatorBagInterface. * - * @param array $customTagsConfiguration - * @param \Symfony\Contracts\Translation\TranslatorInterface $translator - * @param \Symfony\Component\Translation\TranslatorBagInterface $translatorBag - * @param string $translationDomain - * @param \Symfony\Component\Asset\Packages $packages - * @param \Traversable $customTagAttributeMappers + * @phpstan-param array $customTagsConfiguration + * + * @param iterable<\Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper> $customTagAttributeMappers */ public function __construct( array $customTagsConfiguration, @@ -62,7 +71,7 @@ public function __construct( TranslatorBagInterface $translatorBag, string $translationDomain, Packages $packages, - Traversable $customTagAttributeMappers + iterable $customTagAttributeMappers ) { $this->customTagsConfiguration = $customTagsConfiguration; $this->translator = $translator; @@ -76,9 +85,9 @@ public function __construct( /** * Map Configuration for the given list of enabled Custom Tags. * - * @param array $enabledCustomTags + * @phpstan-param array $enabledCustomTags * - * @return array Mapped configuration + * @phpstan-return array Mapped configuration */ public function mapConfig(array $enabledCustomTags): array { @@ -123,12 +132,6 @@ public function mapConfig(array $enabledCustomTags): array /** * Get first available Custom Tag Attribute Type mapper. - * - * @param string $tagName - * @param string $attributeName - * @param string $attributeType - * - * @return \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag\AttributeMapper */ private function getAttributeTypeMapper( string $tagName, @@ -154,9 +157,9 @@ private function getAttributeTypeMapper( /** * Process Custom Tags config and translate labels for UI. * - * @param array $config + * @param array $config * - * @return array processed Custom Tags config with translated labels + * @return array processed Custom Tags config with translated labels */ private function translateLabels(array $config): array { diff --git a/src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php b/src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php index 17060bad..e2b49fb9 100644 --- a/src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php +++ b/src/lib/Configuration/UI/Mapper/CustomTag/AttributeMapper.php @@ -12,26 +12,23 @@ * Map RichText Custom Tag attribute of supported type to proper UI config. * * @internal For internal use by RichText package + * + * @phpstan-import-type TConfigAttribute from \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag + * @phpstan-import-type TConfigAttributeOutput from \Ibexa\FieldTypeRichText\Configuration\UI\Mapper\CustomTag */ interface AttributeMapper { /** * Check if mapper supports given Custom Tag attribute type. - * - * @param string $attributeType - * - * @return bool */ public function supports(string $attributeType): bool; /** * Map Configuration for the given Custom Tag attribute type. * - * @param string $tagName - * @param string $attributeName - * @param array $customTagAttributeProperties + * @phpstan-param TConfigAttribute $customTagAttributeProperties * - * @return array Mapped attribute configuration + * @phpstan-return TConfigAttributeOutput Mapped attribute configuration */ public function mapConfig( string $tagName, diff --git a/src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php b/src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php index 48ac6ad4..aa49ba4d 100644 --- a/src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php +++ b/src/lib/Configuration/UI/Mapper/CustomTag/ChoiceAttributeMapper.php @@ -30,7 +30,7 @@ public function mapConfig( ): array { $parentConfig = parent::mapConfig($tagName, $attributeName, $customTagAttributeProperties); - $parentConfig['choices'] = $customTagAttributeProperties['choices']; + $parentConfig['choices'] = $customTagAttributeProperties['choices'] ?? []; $parentConfig['choicesLabel'] = []; foreach ($parentConfig['choices'] as $choice) {