Skip to content

Commit

Permalink
Add locator for TCA types
Browse files Browse the repository at this point in the history
  • Loading branch information
nhovratov committed Oct 2, 2024
1 parent 8c12d46 commit d0f7007
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 44 deletions.
13 changes: 0 additions & 13 deletions Classes/Definition/Factory/ContentBlockCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
29 changes: 8 additions & 21 deletions Classes/FieldType/FieldTypeRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,38 +25,26 @@
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
{
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<FieldTypeInterface>
*/
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;
}
}
39 changes: 39 additions & 0 deletions Classes/FieldType/TcaFieldTypeRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

namespace TYPO3\CMS\ContentBlocks\FieldType;

use Symfony\Component\DependencyInjection\Attribute\AutowireLocator;
use Symfony\Component\DependencyInjection\ServiceLocator;

final readonly class TcaFieldTypeRegistry
{
public function __construct(
#[AutowireLocator(FieldType::TAG_NAME, indexAttribute: 'tcaType')]
private ServiceLocator $types,
) {}

public function has(string $type): bool
{
return $this->types->has($type);
}

public function get(string $type): FieldTypeInterface
{
return $this->types->get($type);
}
}
4 changes: 2 additions & 2 deletions Classes/Generator/TcaGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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'])) {
Expand Down
17 changes: 9 additions & 8 deletions Classes/Schema/FieldTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
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.
*/
class FieldTypeResolver
{
public function __construct(
protected FieldTypeRegistry $fieldTypeRegistry,
protected TcaFieldTypeRegistry $fieldTypeRegistry,
) {}

public function resolve(array $configuration): FieldTypeInterface
Expand All @@ -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;
}
}

0 comments on commit d0f7007

Please sign in to comment.