From d0f700769a67e9259a325a9b5f1d92c75bb6cf75 Mon Sep 17 00:00:00 2001 From: Nikita Hovratov Date: Wed, 2 Oct 2024 16:01:26 +0200 Subject: [PATCH] Add locator for TCA types --- .../Factory/ContentBlockCompiler.php | 13 ------- Classes/FieldType/FieldTypeRegistry.php | 29 ++++---------- Classes/FieldType/TcaFieldTypeRegistry.php | 39 +++++++++++++++++++ Classes/Generator/TcaGenerator.php | 4 +- Classes/Schema/FieldTypeResolver.php | 17 ++++---- 5 files changed, 58 insertions(+), 44 deletions(-) create mode 100644 Classes/FieldType/TcaFieldTypeRegistry.php diff --git a/Classes/Definition/Factory/ContentBlockCompiler.php b/Classes/Definition/Factory/ContentBlockCompiler.php index 678e35ae..97b55e43 100644 --- a/Classes/Definition/Factory/ContentBlockCompiler.php +++ b/Classes/Definition/Factory/ContentBlockCompiler.php @@ -893,19 +893,6 @@ private function resolveType(ProcessingInput $input, array $field): FieldTypeInt } $this->assertTypeExists($field, $input); $fieldTypeName = $field['type']; - if (!$this->fieldTypeRegistry->has($fieldTypeName)) { - $validTypesList = array_map( - fn(FieldTypeInterface $fieldType): string => (new \ReflectionClass($fieldType::class))->getAttributes(FieldType::class)[0]->name, - $this->fieldTypeRegistry->toArray() - ); - sort($validTypesList); - $validTypes = implode(', ', $validTypesList); - throw new \InvalidArgumentException( - 'The type "' . $field['type'] . '" is not a valid type in Content Block "' - . $input->contentBlock->getName() . '". Valid types are: ' . $validTypes . '.', - 1697625849 - ); - } $fieldType = $this->fieldTypeRegistry->get($fieldTypeName); $fieldTypeEnum = SpecialFieldType::tryFrom($fieldTypeName); if ($fieldTypeEnum !== SpecialFieldType::LINEBREAK) { diff --git a/Classes/FieldType/FieldTypeRegistry.php b/Classes/FieldType/FieldTypeRegistry.php index eb9f2a12..268f702a 100644 --- a/Classes/FieldType/FieldTypeRegistry.php +++ b/Classes/FieldType/FieldTypeRegistry.php @@ -17,7 +17,6 @@ namespace TYPO3\CMS\ContentBlocks\FieldType; -use Symfony\Component\DependencyInjection\Attribute\AutowireIterator; use Symfony\Component\DependencyInjection\Attribute\AutowireLocator; use Symfony\Component\DependencyInjection\ServiceLocator; @@ -26,8 +25,6 @@ public function __construct( #[AutowireLocator(FieldType::TAG_NAME, indexAttribute: 'name')] private ServiceLocator $types, - #[AutowireIterator(FieldType::TAG_NAME)] - private iterable $fieldTypes, ) {} public function has(string $type): bool @@ -35,29 +32,19 @@ public function has(string $type): bool return $this->types->has($type); } - // @todo is it possible to retrieve the service by FQCN and "name" at the same time? public function get(string $type): FieldTypeInterface { + if (!$this->has($type) && class_exists($type)) { + $type = $this->getNameFromAttribute($type); + } return $this->types->get($type); } - /** - * @return iterable - */ - public function all(): iterable + private function getNameFromAttribute(string $fieldType): string { - return $this->fieldTypes; - } - - /** - * @return FieldTypeInterface[] - */ - public function toArray(): array - { - $allFieldTypes = []; - foreach ($this->fieldTypes as $fieldType) { - $allFieldTypes[] = $fieldType; - } - return $allFieldTypes; + $reflectionClass = new \ReflectionClass($fieldType); + $attribute = $reflectionClass->getAttributes(FieldType::class)[0]; + $instance = $attribute->newInstance(); + return $instance->name; } } diff --git a/Classes/FieldType/TcaFieldTypeRegistry.php b/Classes/FieldType/TcaFieldTypeRegistry.php new file mode 100644 index 00000000..340efafb --- /dev/null +++ b/Classes/FieldType/TcaFieldTypeRegistry.php @@ -0,0 +1,39 @@ +types->has($type); + } + + public function get(string $type): FieldTypeInterface + { + return $this->types->get($type); + } +} diff --git a/Classes/Generator/TcaGenerator.php b/Classes/Generator/TcaGenerator.php index 6276167d..11f67f2b 100644 --- a/Classes/Generator/TcaGenerator.php +++ b/Classes/Generator/TcaGenerator.php @@ -588,7 +588,7 @@ protected function cleanupEmptyArrays(array &$configuration, string $optionKey): protected function determineLabelAndDescription(ContentTypeInterface $typeDefinition, TcaFieldDefinition $overrideColumn, array $column): array { $fieldType = $overrideColumn->getFieldType(); - $fieldTypeService = $this->fieldTypeRegistry->get($fieldType); + $fieldTypeService = $this->fieldTypeRegistry->get($fieldType::class); if ($fieldTypeService->getTcaType() === 'passthrough') { return $column; } @@ -602,7 +602,7 @@ protected function determineLabelAndDescription(ContentTypeInterface $typeDefini $column['description'] = $descriptionPath; } $itemsFieldTypes = ['select', 'radio', 'check']; - if (in_array($fieldTypeService->tcaType, $itemsFieldTypes, true)) { + if (in_array($fieldTypeService->getTcaType(), $itemsFieldTypes, true)) { $items = $column['config']['items'] ?? []; foreach ($items as $index => $item) { if (!isset($item['labelPath'])) { diff --git a/Classes/Schema/FieldTypeResolver.php b/Classes/Schema/FieldTypeResolver.php index 0b115a87..8e687f1b 100644 --- a/Classes/Schema/FieldTypeResolver.php +++ b/Classes/Schema/FieldTypeResolver.php @@ -18,7 +18,7 @@ namespace TYPO3\CMS\ContentBlocks\Schema; use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeInterface; -use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeRegistry; +use TYPO3\CMS\ContentBlocks\FieldType\TcaFieldTypeRegistry; /** * @internal Not part of TYPO3's public API. @@ -26,7 +26,7 @@ class FieldTypeResolver { public function __construct( - protected FieldTypeRegistry $fieldTypeRegistry, + protected TcaFieldTypeRegistry $fieldTypeRegistry, ) {} public function resolve(array $configuration): FieldTypeInterface @@ -35,12 +35,13 @@ public function resolve(array $configuration): FieldTypeInterface throw new \InvalidArgumentException('Tried to resolve type of non-existing field.', 1680110446); } $tcaType = $configuration['config']['type']; - foreach ($this->fieldTypeRegistry->all() as $fieldType) { - $fieldTypeService = $this->fieldTypeRegistry->get($fieldType::class); - if ($fieldTypeService->getTcaType() === $tcaType) { - return $fieldType; - } + if (!$this->fieldTypeRegistry->has($tcaType)) { + throw new \InvalidArgumentException( + 'Field type "' . $tcaType . '" is either not implemented or cannot be shared in Content Blocks.', + 1680110918 + ); } - throw new \InvalidArgumentException('Field type "' . $tcaType . '" is either not implemented or cannot be shared in Content Blocks.', 1680110918); + $fieldType = $this->fieldTypeRegistry->get($tcaType); + return $fieldType; } }