Skip to content

Commit

Permalink
[WIP][FEATURE] FieldTypeRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
nhovratov committed Mar 10, 2024
1 parent 4c9bb52 commit 2632775
Show file tree
Hide file tree
Showing 71 changed files with 1,112 additions and 513 deletions.
3 changes: 3 additions & 0 deletions Classes/Builder/ContentBlockBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Symfony\Component\Yaml\Yaml;
use TYPO3\CMS\ContentBlocks\Definition\ContentType\ContentType;
use TYPO3\CMS\ContentBlocks\Definition\Factory\TableDefinitionCollectionFactory;
use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeRegistry;
use TYPO3\CMS\ContentBlocks\Generator\HtmlTemplateCodeGenerator;
use TYPO3\CMS\ContentBlocks\Generator\LanguageFileGenerator;
use TYPO3\CMS\ContentBlocks\Loader\LoadedContentBlock;
Expand All @@ -38,6 +39,7 @@ public function __construct(
protected readonly HtmlTemplateCodeGenerator $htmlTemplateCodeGenerator,
protected readonly LanguageFileGenerator $languageFileGenerator,
protected readonly ContentBlockRegistry $contentBlockRegistry,
protected readonly FieldTypeRegistry $fieldTypeRegistry,
protected readonly TableDefinitionCollectionFactory $tableDefinitionCollectionFactory,
protected readonly SimpleTcaSchemaFactory $simpleTcaSchemaFactory,
) {}
Expand Down Expand Up @@ -87,6 +89,7 @@ protected function initializeRegistries(LoadedContentBlock $contentBlock): void
$this->contentBlockRegistry->register($contentBlock);
$tableDefinitionCollection = $this->tableDefinitionCollectionFactory->createUncached(
$this->contentBlockRegistry,
$this->fieldTypeRegistry,
$this->simpleTcaSchemaFactory,
);
$automaticLanguageKeysRegistry = $tableDefinitionCollection->getAutomaticLanguageKeysRegistry();
Expand Down
9 changes: 5 additions & 4 deletions Classes/DataProcessing/ContentBlockDataDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use TYPO3\CMS\ContentBlocks\Definition\TableDefinition;
use TYPO3\CMS\ContentBlocks\Definition\TableDefinitionCollection;
use TYPO3\CMS\ContentBlocks\Definition\TcaFieldDefinition;
use TYPO3\CMS\ContentBlocks\FieldConfiguration\FieldType;
use TYPO3\CMS\ContentBlocks\FieldType\FieldType;
use TYPO3\CMS\ContentBlocks\Schema\Exception\UndefinedFieldException;
use TYPO3\CMS\ContentBlocks\Schema\Exception\UndefinedSchemaException;
use TYPO3\CMS\ContentBlocks\Schema\SimpleTcaSchemaFactory;
Expand Down Expand Up @@ -72,8 +72,7 @@ private function buildContentBlockDataObjectRecursive(
$grids = [];
foreach ($contentTypeDefinition->getColumns() as $column) {
$tcaFieldDefinition = $tableDefinition->getTcaFieldDefinitionCollection()->getField($column);
$fieldType = $tcaFieldDefinition->getFieldType();
if (!$fieldType->isRenderable()) {
if (!$tcaFieldDefinition->getFieldType()->isRenderable()) {
continue;
}
$resolvedField = $resolvedRelation->resolved[$tcaFieldDefinition->getUniqueIdentifier()];
Expand Down Expand Up @@ -111,7 +110,9 @@ private function handleRelation(
?PageLayoutContext $context = null,
): mixed {
$resolvedField = $resolvedRelation->resolved[$tcaFieldDefinition->getUniqueIdentifier()];
$resolvedField = match ($tcaFieldDefinition->getFieldType()) {
$fieldTypeName = $tcaFieldDefinition->getFieldType()->getName();
$fieldTypeEnum = FieldType::tryFrom($fieldTypeName);
$resolvedField = match ($fieldTypeEnum) {
FieldType::COLLECTION,
FieldType::RELATION => $this->transformMultipleRelation(
$resolvedField,
Expand Down
29 changes: 15 additions & 14 deletions Classes/DataProcessing/RelationResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
use TYPO3\CMS\ContentBlocks\Definition\TableDefinition;
use TYPO3\CMS\ContentBlocks\Definition\TableDefinitionCollection;
use TYPO3\CMS\ContentBlocks\Definition\TcaFieldDefinition;
use TYPO3\CMS\ContentBlocks\FieldConfiguration\FieldType;
use TYPO3\CMS\ContentBlocks\FieldConfiguration\FolderFieldConfiguration;
use TYPO3\CMS\ContentBlocks\FieldType\FieldType;
use TYPO3\CMS\ContentBlocks\FieldType\FolderFieldType;
use TYPO3\CMS\ContentBlocks\Schema\SimpleTcaSchemaFactory;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\RelationHandler;
Expand Down Expand Up @@ -80,7 +80,8 @@ public function processField(
array $record,
string $table
): mixed {
$fieldType = $tcaFieldDefinition->getFieldType();
$fieldTypeName = $tcaFieldDefinition->getFieldType()->getName();
$fieldTypeEnum = FieldType::tryFrom($fieldTypeName);
$recordIdentifier = $tcaFieldDefinition->getUniqueIdentifier();
if (!array_key_exists($recordIdentifier, $record)) {
throw new \RuntimeException(
Expand All @@ -90,35 +91,35 @@ public function processField(
);
}
$data = $record[$recordIdentifier];
if ($fieldType === FieldType::FILE) {
if ($fieldTypeEnum === FieldType::FILE) {
$fileCollector = GeneralUtility::makeInstance(FileCollector::class);
$fileCollector->addFilesFromRelation($table, $recordIdentifier, $record);
return $fileCollector->getFiles();
}
if ($fieldType === FieldType::COLLECTION) {
if ($fieldTypeEnum === FieldType::COLLECTION) {
return $this->processCollection($table, $record, $tcaFieldDefinition, $typeDefinition);
}
if ($fieldType === FieldType::CATEGORY) {
if ($fieldTypeEnum === FieldType::CATEGORY) {
return $this->processCategory($tcaFieldDefinition, $typeDefinition, $table, $record);
}
if ($fieldType === FieldType::RELATION) {
if ($fieldTypeEnum === FieldType::RELATION) {
return $this->processRelation($tcaFieldDefinition, $typeDefinition, $table, $record);
}
if ($fieldType === FieldType::FOLDER) {
if ($fieldTypeEnum === FieldType::FOLDER) {
$fileCollector = GeneralUtility::makeInstance(FileCollector::class);
$folders = GeneralUtility::trimExplode(',', (string)$data, true);
/** @var FolderFieldConfiguration $folderFieldConfiguration */
$folderFieldConfiguration = $tcaFieldDefinition->getFieldConfiguration();
$fileCollector->addFilesFromFolders($folders, $folderFieldConfiguration->isRecursive());
/** @var FolderFieldType $folderFieldType */
$folderFieldType = $tcaFieldDefinition->getFieldType();
$fileCollector->addFilesFromFolders($folders, $folderFieldType->isRecursive());
return $fileCollector->getFiles();
}
if ($fieldType === FieldType::SELECT) {
if ($fieldTypeEnum === FieldType::SELECT) {
return $this->processSelect($tcaFieldDefinition, $typeDefinition, $table, $record);
}
if ($fieldType === FieldType::FLEXFORM) {
if ($fieldTypeEnum === FieldType::FLEXFORM) {
return $this->flexFormService->convertFlexFormContentToArray($data);
}
if ($fieldType === FieldType::JSON) {
if ($fieldTypeEnum === FieldType::JSON) {
$platform = GeneralUtility::makeInstance(ConnectionPool::class)
->getConnectionForTable($table)
->getDatabasePlatform();
Expand Down
70 changes: 43 additions & 27 deletions Classes/Definition/Factory/ContentBlockCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
use TYPO3\CMS\ContentBlocks\Definition\TCA\LinebreakDefinition;
use TYPO3\CMS\ContentBlocks\Definition\TCA\TabDefinition;
use TYPO3\CMS\ContentBlocks\Definition\TcaFieldDefinition;
use TYPO3\CMS\ContentBlocks\FieldConfiguration\FieldType;
use TYPO3\CMS\ContentBlocks\FieldType\FieldType;
use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeInterface;
use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeRegistry;
use TYPO3\CMS\ContentBlocks\Loader\LoadedContentBlock;
use TYPO3\CMS\ContentBlocks\Registry\AutomaticLanguageKeysRegistry;
use TYPO3\CMS\ContentBlocks\Registry\AutomaticLanguageSource;
Expand Down Expand Up @@ -72,6 +74,7 @@ final class ContentBlockCompiler
{
private AutomaticLanguageKeysRegistry $automaticLanguageKeysRegistry;
private SimpleTcaSchemaFactory $simpleTcaSchemaFactory;
private FieldTypeRegistry $fieldTypeRegistry;

/**
* This property tracks Collection foreign_table parent references.
Expand All @@ -87,9 +90,13 @@ final class ContentBlockCompiler
*/
private array $typeFieldPerTable = [];

public function compile(ContentBlockRegistry $contentBlockRegistry, SimpleTcaSchemaFactory $simpleTcaSchemaFactory): CompilationResult
{
public function compile(
ContentBlockRegistry $contentBlockRegistry,
FieldTypeRegistry $fieldTypeRegistry,
SimpleTcaSchemaFactory $simpleTcaSchemaFactory
): CompilationResult {
$this->simpleTcaSchemaFactory = $simpleTcaSchemaFactory;
$this->fieldTypeRegistry = $fieldTypeRegistry;
$this->automaticLanguageKeysRegistry = new AutomaticLanguageKeysRegistry();
$tableDefinitionList = [];
foreach ($contentBlockRegistry->getAll() as $contentBlock) {
Expand Down Expand Up @@ -127,6 +134,7 @@ private function resetState(): void
$this->typeFieldPerTable = [];
unset($this->automaticLanguageKeysRegistry);
unset($this->simpleTcaSchemaFactory);
unset($this->fieldTypeRegistry);
}

private function mergeProcessingResult(array $tableDefinitionList): array
Expand Down Expand Up @@ -160,16 +168,18 @@ private function processFields(ProcessingInput $input, ProcessedFieldsResult $re
{
foreach ($fields as $field) {
$this->initializeField($input, $result, $field);
$fieldTypeName = $result->fieldType::getName();
$fieldTypeEnum = FieldType::tryFrom($fieldTypeName);
$input->languagePath->addPathSegment($result->identifier);
$field = $this->initializeFieldLabelAndDescription($input, $result, $field);
if ($result->fieldType === FieldType::FLEXFORM) {
if ($fieldTypeEnum === FieldType::FLEXFORM) {
$field = $this->processFlexForm($input, $field);
}
if ($result->fieldType->hasItems()) {
$field = $this->collectItemLabels($input, $result, $field);
}
$result->tcaFieldDefinition = $this->buildTcaFieldDefinitionArray($input, $result, $field);
if ($result->fieldType === FieldType::COLLECTION) {
if ($fieldTypeEnum === FieldType::COLLECTION) {
$this->processCollection($input, $result, $field);
}
$this->collectProcessedField($result);
Expand Down Expand Up @@ -252,11 +262,12 @@ private function initializeFieldLabelAndDescription(ProcessingInput $input, Proc
private function collectItemLabels(ProcessingInput $input, ProcessedFieldsResult $result, array $field): array
{
$items = $field['items'] ?? [];
$fieldType = $result->fieldType;
$fieldTypeName = $result->fieldType::getName();
$fieldTypeEnum = FieldType::tryFrom($fieldTypeName);
foreach ($items as $index => $item) {
$label = (string)($item['label'] ?? '');
$currentPath = $input->languagePath->getCurrentPath();
if ($fieldType === FieldType::CHECKBOX) {
if ($fieldTypeEnum === FieldType::CHECKBOX) {
$labelPath = $currentPath . '.items.' . $index . '.label';
} else {
$value = (string)($item['value'] ?? '');
Expand Down Expand Up @@ -367,8 +378,11 @@ private function prependPagesTitlePalette(array $yamlFields): array
private function handleRootField(array $rootField, ProcessingInput $input, ProcessedFieldsResult $result): array
{
$rootFieldType = $this->resolveType($input, $rootField);
$this->assertNoLinebreakOutsideOfPalette($rootFieldType, $input->contentBlock);
$fields = match ($rootFieldType) {
$fieldTypeEnum = FieldType::tryFrom($rootFieldType::getName());
if ($fieldTypeEnum !== null) {
$this->assertNoLinebreakOutsideOfPalette($fieldTypeEnum, $input->contentBlock);
}
$fields = match ($fieldTypeEnum) {
Fieldtype::PALETTE => $this->handlePalette($input, $result, $rootField),
FieldType::TAB => $this->handleTab($input, $result, $rootField),
default => $this->handleDefault($input, $result, $rootField)
Expand All @@ -395,11 +409,14 @@ private function handlePalette(ProcessingInput $input, ProcessedFieldsResult $re
$paletteItems = [];
foreach ($rootPalette['fields'] as $paletteField) {
$paletteFieldType = $this->resolveType($input, $paletteField);
if ($paletteFieldType === FieldType::LINEBREAK) {
$fieldTypeEnum = FieldType::tryFrom($paletteFieldType::getName());
if ($fieldTypeEnum === FieldType::LINEBREAK) {
$paletteItems[] = new LinebreakDefinition();
} else {
$this->assertNoPaletteInPalette($paletteFieldType, $paletteField['identifier'], $rootPaletteIdentifier, $input->contentBlock);
$this->assertNoTabInPalette($paletteFieldType, $paletteField['identifier'], $rootPaletteIdentifier, $input->contentBlock);
if ($fieldTypeEnum !== null) {
$this->assertNoPaletteInPalette($fieldTypeEnum, $paletteField['identifier'], $rootPaletteIdentifier, $input->contentBlock);
$this->assertNoTabInPalette($fieldTypeEnum, $paletteField['identifier'], $rootPaletteIdentifier, $input->contentBlock);
}
$fields[] = $paletteField;
$paletteItems[] = $this->chooseIdentifier($input, $paletteField);
}
Expand Down Expand Up @@ -615,7 +632,7 @@ private function resolveFlexFormField(ProcessingInput $input, array $flexFormFie
$flexFormFieldArray = [
'uniqueIdentifier' => $identifier,
'config' => $flexFormField,
'type' => FieldType::from($flexFormField['type']),
'type' => $this->fieldTypeRegistry->get($flexFormField['type']),
'labelPath' => $labelPath,
'descriptionPath' => $descriptionPath,
];
Expand Down Expand Up @@ -803,7 +820,7 @@ private function getPrefixType(LoadedContentBlock $contentBlock, array $fieldCon
return $contentBlock->getPrefixType();
}

private function resolveType(ProcessingInput $input, array $field): FieldType
private function resolveType(ProcessingInput $input, array $field): FieldTypeInterface
{
$isExistingField = $this->isExistingField($field);
if ($isExistingField) {
Expand All @@ -813,24 +830,25 @@ private function resolveType(ProcessingInput $input, array $field): FieldType
if ($this->simpleTcaSchemaFactory->has($input->table)) {
$tcaSchema = $this->simpleTcaSchemaFactory->get($input->table);
if ($tcaSchema->hasField($identifier)) {
$tcaField = $tcaSchema->getField($identifier);
$fieldType = $tcaField->getType();
return $fieldType;
$fieldType = $tcaSchema->getField($identifier);
return $fieldType->getType();
}
}
}
$this->assertTypeExists($field, $input);
$fieldType = FieldType::tryFrom($field['type']);
if ($fieldType === null) {
$validTypesList = array_map(fn(FieldType $fieldType) => $fieldType->value, FieldType::cases());
$fieldTypeName = $field['type'];
if (!$this->fieldTypeRegistry->has($fieldTypeName)) {
$validTypesList = array_map(fn(FieldTypeInterface $fieldType) => $fieldType::getName(), $this->fieldTypeRegistry->getAll());
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
);
}
if ($fieldType !== FieldType::LINEBREAK) {
$fieldType = $this->fieldTypeRegistry->get($fieldTypeName);
$fieldTypeEnum = FieldType::tryFrom($fieldType::getName());
if ($fieldTypeEnum !== FieldType::LINEBREAK) {
$this->assertIdentifierExists($field, $input);
}
return $fieldType;
Expand Down Expand Up @@ -979,21 +997,19 @@ private function validateFlexFormContainsValidFieldTypes(array $field, LoadedCon
);
}
foreach ($container['fields'] as $containerField) {
$containerType = FieldType::from($containerField['type']);
if (!FieldType::isValidFlexFormField($containerType)) {
if ($this->fieldTypeRegistry->has($containerField['type']) || !FieldType::isValidFlexFormField($this->fieldTypeRegistry->get($containerField['type']))) {
throw new \InvalidArgumentException(
'FlexForm field "' . $field['identifier'] . '" has an invalid field of type "' . $containerType->value . '" inside of a "container" item. Please use valid field types in Content Block "' . $contentBlock->getName() . '".',
'FlexForm field "' . $field['identifier'] . '" has an invalid field of type "' . $containerField['type'] . '" inside of a "container" item. Please use valid field types in Content Block "' . $contentBlock->getName() . '".',
1686330594
);
}
}
}
continue;
}
$type = FieldType::from($flexField['type']);
if (!FieldType::isValidFlexFormField($type)) {
if (!$this->fieldTypeRegistry->has($flexField['type']) || !FieldType::isValidFlexFormField($this->fieldTypeRegistry->get($flexField['type']))) {
throw new \InvalidArgumentException(
'Field type "' . $type->value . '" with identifier "' . $flexField['identifier'] . '" is not allowed inside FlexForm in Content Block "' . $contentBlock->getName() . '".',
'Field type "' . $flexField['type'] . '" with identifier "' . $flexField['identifier'] . '" is not allowed inside FlexForm in Content Block "' . $contentBlock->getName() . '".',
1685220309
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

namespace TYPO3\CMS\ContentBlocks\Definition\Factory\Processing;

use TYPO3\CMS\ContentBlocks\FieldConfiguration\FieldType;
use TYPO3\CMS\ContentBlocks\FieldType\FieldTypeInterface;

/**
* @internal Not part of TYPO3's public API.
Expand All @@ -39,7 +39,7 @@ final class ProcessedFieldsResult
// Below are temporary properties for the scope of a root field.
public string $identifier;
public string $uniqueIdentifier;
public FieldType $fieldType;
public FieldTypeInterface $fieldType;
public array $tcaFieldDefinition;

public function __construct(ProcessingInput $input)
Expand Down
Loading

0 comments on commit 2632775

Please sign in to comment.