Breaking: #107047 - Remove pointer field functionality of TCA flex
See forge#107047
Description
One of the main features of TCA is the concept of 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_ table. For every specific type, it is
possible to define which fields to display and to customize their
configuration.
A special case historically has been plugin registration, which for a long
time used the so-called subtypes feature of TCA. This was an additional layer
below record types, configured using subtype_ (commonly
list_), and optionally subtypes_ and
subtypes_ to add or remove fields depending on the selected
subtype.
FlexForms attached to such subtypes were configured using
ds_ (typically pointing to list_). This came in
combination with the corresponding ds configuration, which was an array
with keys combining the pointer fields, for example:
'ds_pointerField' => 'list_type,CType',
'ds' => [
'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
'default' => 'FILE:...'
],
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_ have been deprecated in
Deprecation: #105076 - Plugin content element and plugin sub types and removed in
Breaking: #105377 - Deprecated functionality removed.
See also Important: #105538 - Plugin subtypes removed: Changes to configurePlugin() and TCA handling for related information about
Extension and
Extension.
With this change, support for ds_ 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 columns.
This also affects the data structure identifier, which in the commonly used
tca type is the data. It is now set to default if the
table does not support record types or no record type-specific configuration
exists. Otherwise, the data is set to the corresponding
record type value, for example textpic.
This change affects the following PSR-14 events:
AfterFlex Form Data Structure Identifier Initialized Event AfterFlex Form Data Structure Parsed Event BeforeFlex Form Data Structure Identifier Initialized Event BeforeFlex Form Data Structure Parsed Event
A fallback for TYPO3 v14 resolves comma-separated data
values (for example, list_) to CType.
To address circular dependencies during schema building,
Flex now supports
both TCA Schema objects and raw TCA configuration arrays as input. The
following methods accept a union type
array for the new
$schema parameter:
getData Structure Identifier () parseData Structure By Identifier () cleanFlex Form XML ()
Previously, these methods relied on
$GLOBALS internally, which
caused architectural issues. They now operate directly on the provided schema.
All calls to these methods should provide the
$schema parameter with
either a
Tca instance or a raw TCA
configuration array. Since data structure resolution can be customized by
extensions, the parameter is not strictly mandatory, but it is strongly
recommended to provide it in most cases. An
Invalid
will be thrown if schema resolution is required but no schema is passed.
This change also enables components like
Relation to use
Flex during schema
building, even when only raw TCA is available.
For further details on the enhanced FlexFormTools functionality, see Feature: #107047 - FlexForm enhancements: Direct plugin registration and raw TCA support.
The following class has been removed as it is no longer required:
\InvalidCombined Pointer Field Exception
Impact
FlexForm Pointer Field Removal
Any TCA definition that still uses
ds_ or a ds
array with multiple entries (for example news_) will no longer work
and might cause rendering errors.
FlexFormTools Schema Parameter
All code calling
Flex
methods (
get,
parse,
clean) must be
updated to provide the required
$schema parameter.
Affected installations
FlexForm Pointer Field Removal
All installations using
ds_ (as the pointer field
functionality has been removed entirely) or an array-like structure for
ds in their TCA field type flex configuration.
FlexFormTools Schema Parameter
All installations with custom code that directly call
Flex methods
without providing the
$schema parameter.
This includes custom extensions or TYPO3 Core patches using these methods.
A TCA migration automatically converts single-entry ds arrays.
Multi-entry definitions require manual migration, as they must be aligned with
the correct record type configuration, which may require additional
configuration changes beforehand.
Example for single-entry migration:
Before:
'ds' => [
'default' => '<T3DataStructure>...',
],
After:
'ds' => '<T3DataStructure>...',
Migration
FlexForm Pointer Field Migration
Before:
'ds_pointerField' => 'list_type,CType',
'ds' => [
'news_pi1,list' => 'FILE:EXT:news/Configuration/FlexForm.xml',
'default' => '<T3DataStructure>...',
],
After:
'columns' => [
'pi_flexform' => [
'config' => [
'ds' => '<T3DataStructure>...',
],
],
],
'types' => [
'news_pi1' => [
'columnsOverrides' => [
'pi_flexform' => [
'config' => [
'ds' => 'FILE:EXT:news/Configuration/FlexForm.xml',
],
],
],
],
],
If no columns is defined, the default ds value of the
field configuration will be used as before.
FlexFormTools Schema Parameter Migration
Before:
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
$identifier = $flexFormTools->getDataStructureIdentifier(
$fieldTca,
'tt_content',
'pi_flexform',
$row
);
After:
use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
use TYPO3\CMS\Core\Schema\TcaSchemaFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
$flexFormTools = GeneralUtility::makeInstance(FlexFormTools::class);
// Option 1: Using TCA Schema object (recommended for normal usage)
$tcaSchemaFactory = GeneralUtility::makeInstance(TcaSchemaFactory::class);
$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
);