diff --git a/typo3/sysext/core/Classes/Database/RelationHandler.php b/typo3/sysext/core/Classes/Database/RelationHandler.php index 7dcd830ab8385aee363b470a3593c5c6199df9d3..3923835a540ccb1c271e79b583fb6a04b13989d2 100644 --- a/typo3/sysext/core/Classes/Database/RelationHandler.php +++ b/typo3/sysext/core/Classes/Database/RelationHandler.php @@ -134,6 +134,8 @@ class RelationHandler /** * Array of fields and value pairs used for insert in MM table + * + * @deprecated since v12. Remove in v13 with other MM_insert_fields places. */ protected array $MM_insert_fields = []; @@ -243,6 +245,7 @@ class RelationHandler $this->MM_table_where = $conf['MM_table_where'] ?? null; $this->MM_hasUidField = $conf['MM_hasUidField'] ?? null; $this->MM_match_fields = (isset($conf['MM_match_fields']) && is_array($conf['MM_match_fields'])) ? $conf['MM_match_fields'] : []; + // @deprecated since v12. Remove in v13 with other MM_insert_fields places. $this->MM_insert_fields = (isset($conf['MM_insert_fields']) && is_array($conf['MM_insert_fields'])) ? $conf['MM_insert_fields'] : []; $this->currentTable = $currentTable; if (!empty($conf['MM_oppositeUsage']) && is_array($conf['MM_oppositeUsage'])) { @@ -722,6 +725,8 @@ class RelationHandler // foreach loop only the ones that need to be deleted are in there. unset($oldMMs_inclUid[$oldMMs_index]); } else { + // @deprecated since v12. Remove in v13 with other MM_insert_fields places. + // Simplify to $insertFields = $this->MM_match_fields; $insertFields = $this->MM_insert_fields; $insertFields = array_merge($insertFields, $this->MM_match_fields); $insertFields[$uidLocal_field] = $uid; @@ -1531,9 +1536,8 @@ class RelationHandler $configuration = $GLOBALS['TCA'][$tableName]['columns'][$fieldName]['config']; if (!empty($configuration['MM_insert_fields'])) { - // @todo: MM_insert_fields does not make sense and should be probably dropped altogether. - // No core usages, not even with sys_category. There is no point in having data fields that - // are filled with static content, especially since the mm table can't be edited directly. + // @deprecated since v12. Remove in v13 with other MM_insert_fields places. + // Remove if() and change elseif() to if(). $referenceValues = array_merge($configuration['MM_insert_fields'], $referenceValues); } elseif (!empty($configuration['MM_match_fields'])) { // @todo: In the end, MM_match_fields does not make sense. The 'tablename' and 'fieldname' restriction diff --git a/typo3/sysext/core/Classes/Migrations/TcaMigration.php b/typo3/sysext/core/Classes/Migrations/TcaMigration.php index 869bbd948c18c24011a8ff5755683ce269bb767e..a1523f1999b1528c7f20d32293f15169e8b4ad21 100644 --- a/typo3/sysext/core/Classes/Migrations/TcaMigration.php +++ b/typo3/sysext/core/Classes/Migrations/TcaMigration.php @@ -87,6 +87,7 @@ class TcaMigration $tca = $this->removeFalRelatedOptionsFromTypeInline($tca); $tca = $this->removePassContentFromTypeNone($tca); $tca = $this->migrateItemsToAssociativeArray($tca); + $tca = $this->removeMmInsertFields($tca); return $tca; } @@ -1446,4 +1447,25 @@ class TcaMigration } return $tca; } + + protected function removeMmInsertFields(array $tca): array + { + foreach ($tca as $table => $tableDefinition) { + if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'] ?? false)) { + continue; + } + foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) { + if (isset($fieldConfig['config']['MM_insert_fields'])) { + // @deprecated since v12. + // *Enable* the commented unset line in v13 when removing MM_insert_fields deprecations. + // *Enable* the disabled unit test set. + // unset($tca[$table]['columns'][$fieldName]['config']['MM_insert_fields']); + $this->messages[] = 'The TCA field \'' . $fieldName . '\' of table \'' . $table . '\' uses ' + . '\'MM_insert_fields\'. This config key is obsolete and should be removed. ' + . 'Please adjust your TCA accordingly.'; + } + } + } + return $tca; + } } diff --git a/typo3/sysext/core/Documentation/Changelog/12.4/Deprecation-100335-TCAConfigMM_insert_fields.rst b/typo3/sysext/core/Documentation/Changelog/12.4/Deprecation-100335-TCAConfigMM_insert_fields.rst new file mode 100644 index 0000000000000000000000000000000000000000..8ffbcd5cb847991346caf4e9f5b820b43de205da --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/12.4/Deprecation-100335-TCAConfigMM_insert_fields.rst @@ -0,0 +1,77 @@ +.. include:: /Includes.rst.txt + +.. _deprecation-100335-1679998903: + +================================================== +Deprecation: #100335 - TCA config MM_insert_fields +================================================== + +See :issue:`100335` + +Description +=========== + +The TCA option :php:`MM_insert_fields` has been marked +as deprecated and should not be used anymore. + + +Impact +====== + +Using :php:`MM_insert_fields` raises a deprecation level log message +during TCA cache warmup. Its functionality is kept in TYPO3 v12 but will +be removed in v13. + + +Affected installations +====================== + +There may be extensions that use this option when configuring database +MM relations. In most cases, the option can be removed. The migration +section gives more details. + + +Migration +========= + +General scope: :php:`MM_insert_fields` is used in combination with "true" +database MM intermediate tables to allow many-to-many relations between +two tables for :php:`group`, :php:`select` and sometimes even :php:`inline` +type fields. + +A core example is the :sql:`sys_category` to :sql:`tt_content` +relation, with :sql:`sys_category_record_mm` as intermediate table: The +intermediate table has field :sql:`uid_local` (pointing to a uid of +the "left" :sql:`sys_category` table), and :sql:`uid_foreign` (pointing to a +uid of the "right" :sql:`tt_content` table). Note this specific relation also +allows multiple different "right-side" table-field combinations, using the two +additional fields :sql:`tablenames` and :sql:`fieldname`. All this is configured +with TCA on the "left" and the "right" side table field, while table +:sql:`sys_category_record_mm` has no TCA itself. Rows within the intermediate +table are transparently handled by TYPO3 by the :php:`RelationHandler` and +extbase TCA-aware domain logic. + +The :php:`MM_insert_fields` now allows to configure a hard coded value for +an additional column within the intermediate table. This is obsolete: There is +no API to retrieve this value again, having a "stable" value in an additional +column is useless. This config option should be removed from TCA +definition. + +Note on the related option :php:`MM_match_fields`: This is important when an +MM relation allows multiple "right" sides. In the example above, when a category +is added to a tt_content record using the :sql:`categories` field, and when editing +this relation from the "right" side (editing a tt_content record), then this option +is used to select only relations for this tt_content/categories combination. The +TCA column :sql:`categories` thus uses :sql:`MM_match_fields` to restrict the +query. Note :sql:`MM_match_fields` is *not* set for the "left-side" :sql:`sys_category` +:sql:`items` fields, this would indicate a TCA misconfiguration. + +Various extensions in the wild did not get these details right, and often simply +set *both* :php:`MM_insert_fields` and :php:`MM_match_fields` to the same values. +Removing :php:`MM_insert_fields` helps reducing confusion and simplifies this +construct a bit. Affected extensions can simply remove the :php:`MM_insert_fields` +configuration and keep the :php:`MM_match_fields`. Note the core strives to further +simplify these options and :php:`MM_match_fields` may become fully obsolete in the +future as well. + +.. index:: TCA, NotScanned, ext:core diff --git a/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php b/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php index 5b33d527145eab12af57d7efa25a189b4e4d8e4a..bcd463a043411622d580a6bd44d93c9307d8a568 100644 --- a/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php +++ b/typo3/sysext/core/Tests/Unit/Migrations/TcaMigrationTest.php @@ -3655,4 +3655,37 @@ class TcaMigrationTest extends UnitTestCase self::assertSame($expected, (new TcaMigration())->migrate($input)); } + + /** + * @deprecated since v12. Add @test when removing MM_insert_fields in v13. + */ + public function migrationRemovesMmInsertFields(): void + { + $input = [ + 'aTable' => [ + 'columns' => [ + 'aColumn' => [ + 'config' => [ + 'type' => 'group', + 'MM_insert_fields' => [ + 'aField' => 'aValue', + ], + ], + ], + ], + ], + ]; + $expected = [ + 'aTable' => [ + 'columns' => [ + 'aColumn' => [ + 'config' => [ + 'type' => 'group', + ], + ], + ], + ], + ]; + self::assertSame($expected, (new TcaMigration())->migrate($input)); + } } diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php index 02bbb0ecee8a39f3d51e4a66d816f887274239ef..2521ed6d20e9c802820b23e41a748961ee899ca8 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php @@ -679,6 +679,7 @@ class Backend implements BackendInterface, SingletonInterface if (is_array($relationTableMatchFields)) { $row = array_merge($relationTableMatchFields, $row); } + // @deprecated since v12. Remove in v13 with other MM_insert_fields places. $relationTableInsertFields = $columnMap->getRelationTableInsertFields(); if (is_array($relationTableInsertFields)) { $row = array_merge($relationTableInsertFields, $row); diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMap.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMap.php index 898ca767e566a68a25f90b7cee1c2faffbff95c4..598fff7e14a146f078f2ac5642ac9ebb0a0c3e63 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMap.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMap.php @@ -84,6 +84,7 @@ class ColumnMap * * @see https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ColumnsConfig/Type/Group/Properties/Mm.html#confval-MM_insert_fields(type=%3Egroup) * @var array|null + * @deprecated since v12. Remove in v13 with other MM_insert_fields places. */ private $relationTableInsertFields; @@ -202,11 +203,17 @@ class ColumnMap return $this->relationTableMatchFields; } + /** + * @deprecated since v12. Remove in v13 with other MM_insert_fields places. + */ public function setRelationTableInsertFields(array $relationTableInsertFields): void { $this->relationTableInsertFields = $relationTableInsertFields; } + /** + * @deprecated since v12. Remove in v13 with other MM_insert_fields places. + */ public function getRelationTableInsertFields(): ?array { return $this->relationTableInsertFields; diff --git a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php index bf6a17dfcd5b834ac8b09f94f53d7fdebce4a534..fba78847a3de0744259d68e569a1607bc9ab77c3 100644 --- a/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php +++ b/typo3/sysext/extbase/Classes/Persistence/Generic/Mapper/ColumnMapFactory.php @@ -228,6 +228,7 @@ class ColumnMapFactory if (isset($columnConfiguration['MM_match_fields']) && is_array($columnConfiguration['MM_match_fields'])) { $columnMap->setRelationTableMatchFields($columnConfiguration['MM_match_fields']); } + // @deprecated since v12. Remove in v13 with other MM_insert_fields places. if (isset($columnConfiguration['MM_insert_fields']) && is_array($columnConfiguration['MM_insert_fields'])) { $columnMap->setRelationTableInsertFields($columnConfiguration['MM_insert_fields']); }