Breaking: #107047 - Remove pointer field functionality of TCA flex

See forge#107047

Description

One of the main features of TCA are the record types. This allows using a single table for different purposes and in different contexts. The most well-known examples are the "Page Types" of the pages table and the "Content Types" of the tt_content table. For every specific type, it's possible to define which fields to display and customize their configuration.

A special case historically has been the plugin registration, which for a long time used the so-called sub types feature of TCA. This was an additional layer below record types, configured using subtype_value_field (commonly list_type), and optionally subtypes_addlist and subtypes_excludelist to add or remove fields depending on the selected subtype.

FlexForms attached to such subtypes were configured using ds_pointerField (typically pointing to list_type,CType). This came in combination with corresponding ds configuration, which was an array with keys combining the pointer fields, e.g.:

'ds_pointerField' => 'list_type,CType',
'ds' => [
    'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
    'default' => 'FILE:...'
],
Copied!

Over recent TYPO3 versions, this approach has been deprecated in favor of using record types exclusively for plugin registration via the CType field, making configuration cleaner and easier to understand.

The special plugin content element (CType=list) and the corresponding plugin subtype field list_type have been deprecated in Deprecation: #105076 - Plugin content element and plugin sub types and have been removed in Breaking: #105377 - Deprecated functionality removed. You should also check corresponding information regarding the usage of ExtensionUtility::configurePlugin() and ExtensionManagementUtility::addTcaSelectItemGroup(), see Important: #105538 - list_type and sub types.

With this change, support for ds_pointerField and the multi-entry ds array format has now been removed. The ds option now points to a single FlexForm, either directly or via a FILE: reference.

FlexForms must instead be assigned via standard types configuration using columnsOverrides.

This also affects the "data structure identifier", which in the commonly used "tca" type the dataStructureKey, which is now set to default in case the table does not support record types or no record type specific configuration exists. Otherwise the dataStructureKey is set to the corresponding record type value, e.g. textpic.

This affects the related PSR-14 events:

  • \TYPO3\CMS\Core\Configuration\Event\AfterFlexFormDataStructureIdentifierInitializedEvent
  • \TYPO3\CMS\Core\Configuration\Event\AfterFlexFormDataStructureParsedEvent
  • \TYPO3\CMS\Core\Configuration\Event\BeforeFlexFormDataStructureIdentifierInitializedEvent
  • \TYPO3\CMS\Core\Configuration\Event\BeforeFlexFormDataStructureParsedEvent

There is a fallback for v14 in place, resolving a comma-separated dataStructureKey, e.g. list_type,CType to CType.

To address circular dependencies during schema building, FlexFormTools has been enhanced to support both TCA Schema objects and raw TCA configuration arrays as input. The following methods now accept a union type array|TcaSchema for the new $schema parameter:

  • getDataStructureIdentifier()
  • parseDataStructureByIdentifier()
  • cleanFlexFormXML()

These methods previously relied on $GLOBALS['TCA'] internally, which caused architectural issues and is resolved now by working with the given schema directly.

Therefore, all calls to these methods should provide the $schema with either a TcaSchema or raw TCA configuration array. However, since data structure resolution can be customized by extensions, the $schema parameter is not strictly mandatory. But, it is strongly recommended to provide it in most cases, as an InvalidTcaSchemaException will be thrown if schema resolution is required but no schema is passed.

This change further allows components like RelationMapBuilder to use FlexFormTools during schema building processes where only raw TCA is available.

For more details on the enhanced FlexFormTools functionality, see Feature: #107047 - FlexForm enhancements: Direct plugin registration and raw TCA support.

The following classes have been removed as they serve no further purpose:

  • \TYPO3\CMS\Core\Configuration\FlexForm\Exception\InvalidCombinedPointerFieldException

Impact

FlexForm Pointer Field Removal

Any TCA definition that still uses ds_pointerField or a ds array with multiple entries (e.g., like news_pi1,list) will no longer work and might cause errors on rendering.

FlexFormTools Schema Parameter

All code calling FlexFormTools methods ( getDataStructureIdentifier(), parseDataStructureByIdentifier(), cleanFlexFormXML()) must be updated to provide the required $schema parameter.

Affected installations

FlexForm Pointer Field Removal

All installations using ds_pointerField and array-like structure for ds in their TCA type flex configuration.

FlexFormTools Schema Parameter

All installations with custom code that directly calls FlexFormTools methods without providing the schema parameter. This includes custom extensions or TYPO3 Core patches that use these methods directly.

A TcaMigration converts single-entry ds arrays automatically. Multi-entry definitions require manual migration, since they have to be matched with the correct record type configuration, which might require additional configuration changes beforehand.

Example for the single-entry migration:

// before
'ds' => [
    'default' => '<T3DataStructure>...',
],

// after
'ds' => '<T3DataStructure>...',
Copied!

Migration

FlexForm Pointer Field Migration

Before:

'ds_pointerField' => 'list_type,CType',
'ds' => [
    'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
    'default' => '<T3DataStructure>...',
],
Copied!

After:

'columns' => [
    'pi_flexform' => [
        'config' => [
            'ds' => '<T3DataStructure>...',
        ],
    ],
],
'types' => [
    'news_pi1' => [
        'columnsOverrides' => [
            'pi_flexform' => [
                'config' => [
                    'ds' => 'FILE:EXT:news/Configuration/FlexForm.xml',
                ],
            ],
        ],
    ],
],
Copied!

If no columnsOverrides is defined, the default ds value of the field configuration will be used, as usual behaviour.

FlexFormTools Schema Parameter Migration

Before:

$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
$identifier = $flexFormTools->getDataStructureIdentifier(
    $fieldTca,
    'tt_content',
    'pi_flexform',
    $row
);
Copied!

After:

$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);

// Option 1: Using TCA Schema object (recommended for normal usage)
$tcaSchema = $tcaSchemaFactory->get('tt_content');
$identifier = $flexFormTools->getDataStructureIdentifier(
    $fieldTca,
    'tt_content',
    'pi_flexform',
    $row,
    $tcaSchema
);

// Option 2: Using raw TCA array (for schema building contexts)
$rawTca = $fullTca['tt_content'];
$identifier = $flexFormTools->getDataStructureIdentifier(
    $fieldTca,
    'tt_content',
    'pi_flexform',
    $row,
    $rawTca
);
Copied!