DataMapProcessor
This processor analyzes and enriches the provided data-map before it is actually processed by the calling DataHandler instance. Fields configured with "allowLanguageSynchronization" or "l10n_mode=exclude" are synchronized either from their parent/source record into the translation, or pushed downwards from a default-language record to all its dependent translations.
Except for inline relational record editing (IRRE), all modifications are applied to the data-map directly, which ensures proper history entries as a side-effect. For IRRE fields, this processor triggers copy or localize actions by instantiating a local DataHandler instance.
Processing flow in process(): The while loop implements a dirty queue that processes records one IRRE nesting level at a time. On each iteration it processes the records in $modifiedDataMap:
-
collectItems() — turns each data-map entry into a typed DataMapItem (DataMapItem::TYPE_PARENT for default-language records, DataMapItem::TYPE_DIRECT_CHILD for first-level translations, DataMapItem::TYPE_GRAND_CHILD for translations of translations) and resolves their dependency graph (which parent/source record each translation points to). Items are accumulated in $allItems across iterations; $nextItems holds only the batch of the current iteration.
-
sanitize() — run once on the first iteration only. Strips fields from translation data-map entries that are subject to parent/source synchronization and not explicitly marked as "custom" in l10n_state. The stripped values are stashed in $sanitizationMap so that synchronizeReferences() can later detect child relations already created by DataHandler::copyRecord_procBasedOnFieldType() during copy operations, and avoid duplicating them.
-
enrich() — applies synchronized field values from the parent/source record into the translation via synchronizeTranslationItem(), and pushes values downwards from a parent item to its dependent translation items via populateTranslationItem(). For IRRE fields, synchronizeReferences() diffs the parent's child list against the translation's child list, then issues localize/copy/delete commands to a sub-DataHandler.
The dirty queue: modifyDataMap() writes every field-value change to both $allDataMap (the canonical, growing data-map) and $modifiedDataMap (the queue for the next iteration). When enrich() localizes IRRE children via a sub-DataHandler, those newly created records are fed back into $modifiedDataMap. The while loop then picks them up in the next iteration, so that their own inline children can be synchronized in turn. This is necessary because the UIDs of newly localized IRRE records are unknown before the sub-DataHandler runs - the tree cannot be pre-traversed. The loop terminates when no new records were added to $modifiedDataMap during an enrich() pass.
The mutable properties carry temporary state across internal method calls during a single process() run and are reset at the end of process(). The class must be non-shared (shared: false) in the DI container because IRRE synchronization spawns nested DataHandler instances that each trigger their own process() call, resulting in DH->DMP->DH->DMP nesting chains. A shared instance would have its temporary state corrupted by the inner call.
should only be used by the TYPO3 Core
Attributes
- #[Autoconfigure]
- $public: true
- $shared: false
Table of Contents
Properties
- $allDataMap : array<string|int, mixed>
- $allItems : array<string|int, DataMapItem>
- $modifiedDataMap : array<string, array<string|int, mixed>>
- $nextItems : array<string|int, DataMapItem>
- $sanitizationMap : array<string, array<int, array<string|int, mixed>>>
Methods
- __construct() : mixed
- process() : array<string|int, mixed>
- Processes the submitted data-map and returns the sanitized and enriched version depending on accordant localization states and dependencies.
- addNextItem() : void
- applyLocalizationReferences() : array<string|int, mixed>
- Applies localization references to given raw data-map item.
- buildElementAncestorIdMap() : array<string|int, mixed>
- Builds a map from ancestor ids to accordant localization dependents.
- collectItems() : void
- Create data map items of all affected rows
- createRelationHandler() : RelationHandler
- enrich() : void
- Handle synchronization of an item list
- fetchDependencies() : array<int|string, array<string, array<int, DataMapItem>>>
- Fetches translation dependencies for a given parent/source record ids.
- fetchDependentElements() : array<string|int, mixed>
- Fetch all elements that depend on given record id's in either their parent or source field for translatable tables or their origin field for non-translatable tables.
- fetchDependentIdMap() : array<string|int, mixed>
- Fetches dependent records that depend on given record id's in in either their parent or source field for translatable tables or their origin field for non-translatable tables and creates an id mapping.
- fetchTranslationValues() : array<string|int, mixed>
- Fetches translation related field values for the items submitted in the data-map.
- filterItemsByType() : array<string|int, DataMapItem>
- Return array of data map items that are of given type
- filterNewItemIds() : array<string|int, mixed>
- Return only ids that don't have an item equivalent in $this->allItems.
- filterNumericIds() : array<string|int, int>
- Return only ids that are integer - so no "NEW..." values
- finishTranslationItem() : array<string|int, mixed>
- Finishes a translation item by updating states to be persisted.
- getFieldNamesForItemScope() : array<string|int, string>
- Field names we have to deal with
- getFieldNamesToBeHandled() : array<string|int, string>
- Gets a list of field names which have to be handled. Basically this includes fields using allowLanguageSynchronization or l10n_mode=exclude.
- getLanguageService() : LanguageService|null
- getLocalizationModeExcludeFieldNames() : array<string|int, string>
- Field names of TCA table with columns having l10n_mode=exclude
- getPrefixLanguageTitleFieldNames() : array<string|int, mixed>
- Field names of TCA table with columns having l10n_mode=prefixLangTitle
- getSchema() : TcaSchema|null
- isApplicable() : bool
- Determines whether the table can be localized and either has fields with allowLanguageSynchronization enabled or l10n_mode set to exclude.
- isReferenceField() : bool
- True if we're dealing with a reference field (either "inline" or "file") with foreign_table set.
- isRelationField() : bool
- True if we're dealing with a field that has foreign db relations (type=group or select with foreign_table).
- isSetInDataMap() : bool
- Determines whether a combination of table name, id and field name is set in data-map. This method considers null values as well, that would not be considered by a plain isset() invocation.
- mapRelationItemId() : array<string|int, int>
- Flatten array
- modifyDataMap() : void
- Applies modifications to the data-map, calling this method is essential to determine new data-map items to be process for synchronizing chained record localizations.
- populateTranslationItem() : void
- Populates values downwards, either from a parent language item or a source language item to an accordant dependent translation item.
- prefixLanguageTitle() : array<string|int, mixed>
- Prefixes language title if applicable for the accordant field name in raw data-map item.
- purgeDataMap() : array<string|int, mixed>
- Purges superfluous empty data-map sections.
- resolveAncestorId() : int|null
- resolveSuggestedInlineRelations() : array<string|int, int>|array<string|int, string>
- Determines suggest inline relations of either translation parent or source record from data-map or storage in case records have been persisted already.
- sanitize() : void
- Sanitizes the submitted data-map items and removes fields which are not defined as custom and thus rely on either parent or source values.
- sanitizeTranslationItem() : void
- Sanitizes the submitted data-map for a particular item and removes fields which are not defined as custom and thus rely on either parent or source values.
- synchronizeDirectRelations() : void
- Synchronize select and group field localizations
- synchronizeFieldValues() : void
- Synchronize simple values like text and similar
- synchronizeReferences() : void
- Handle synchronization of references (inline or file).
- synchronizeTranslationItem() : void
- Synchronize a single item
Properties
$allDataMap
protected
array<string|int, mixed>
$allDataMap
= []
$allItems
protected
array<string|int, DataMapItem>
$allItems
= []
$modifiedDataMap
protected
array<string, array<string|int, mixed>>
$modifiedDataMap
= []
$nextItems
protected
array<string|int, DataMapItem>
$nextItems
= []
$sanitizationMap
protected
array<string, array<int, array<string|int, mixed>>>
$sanitizationMap
= []
Methods
__construct()
public
__construct(TcaSchemaFactory $tcaSchemaFactory, ConnectionPool $connectionPool, SiteFinder $siteFinder) : mixed
Parameters
- $tcaSchemaFactory : TcaSchemaFactory
- $connectionPool : ConnectionPool
- $siteFinder : SiteFinder
process()
Processes the submitted data-map and returns the sanitized and enriched version depending on accordant localization states and dependencies.
public
process(array<string|int, mixed> $dataMap, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : array<string|int, mixed>
Parameters
- $dataMap : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater
Return values
array<string|int, mixed>addNextItem()
protected
addNextItem(DataMapItem $item) : void
Parameters
- $item : DataMapItem
applyLocalizationReferences()
Applies localization references to given raw data-map item.
protected
applyLocalizationReferences(string $tableName, string|int $fromId, int $language, array<string|int, mixed> $fieldNames, array<string|int, mixed> $data) : array<string|int, mixed>
Parameters
- $tableName : string
- $fromId : string|int
- $language : int
- $fieldNames : array<string|int, mixed>
- $data : array<string|int, mixed>
Return values
array<string|int, mixed>buildElementAncestorIdMap()
Builds a map from ancestor ids to accordant localization dependents.
protected
buildElementAncestorIdMap(array<string|int, mixed> $fieldNames, array<string|int, mixed> $elements) : array<string|int, mixed>
The result of e.g. [5 => [6, 7]] refers to ids 6 and 7 being dependents (either used in parent or source field) of the ancestor with id 5.
Parameters
- $fieldNames : array<string|int, mixed>
- $elements : array<string|int, mixed>
Return values
array<string|int, mixed>collectItems()
Create data map items of all affected rows
protected
collectItems(string $tableName, array<string|int, mixed> $idValues, BackendUserAuthentication $backendUser) : void
Parameters
- $tableName : string
- $idValues : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
createRelationHandler()
protected
createRelationHandler(BackendUserAuthentication $backendUser) : RelationHandler
Parameters
- $backendUser : BackendUserAuthentication
Return values
RelationHandlerenrich()
Handle synchronization of an item list
protected
enrich(array<string|int, DataMapItem> $items, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : void
Parameters
- $items : array<string|int, DataMapItem>
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater
fetchDependencies()
Fetches translation dependencies for a given parent/source record ids.
protected
fetchDependencies(string $tableName, array<string|int, int>|array<string|int, string> $ids, BackendUserAuthentication $backendUser, array<string|int, mixed> $allDataMap) : array<int|string, array<string, array<int, DataMapItem>>>
Existing records in database:
- [uid:5, l10n_parent=0, l10n_source=0, sys_language_uid=0]
- [uid:6, l10n_parent=5, l10n_source=5, sys_language_uid=1]
- [uid:7, l10n_parent=5, l10n_source=6, sys_language_uid=2]
Input $ids and their results:
- [5] -> [DataMapItem(6), DataMapItem(7)] # since 5 is parent/source
- [6] -> [DataMapItem(7)] # since 6 is source
- [7] -> [] # since there's nothing
Parameters
- $tableName : string
- $ids : array<string|int, int>|array<string|int, string>
- $backendUser : BackendUserAuthentication
- $allDataMap : array<string|int, mixed>
Return values
array<int|string, array<string, array<int, DataMapItem>>>fetchDependentElements()
Fetch all elements that depend on given record id's in either their parent or source field for translatable tables or their origin field for non-translatable tables.
protected
fetchDependentElements(string $tableName, array<string|int, mixed> $ids, array<string|int, mixed> $fieldNames, BackendUserAuthentication $backendUser) : array<string|int, mixed>
Parameters
- $tableName : string
- $ids : array<string|int, mixed>
- $fieldNames : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
Tags
Return values
array<string|int, mixed>fetchDependentIdMap()
Fetches dependent records that depend on given record id's in in either their parent or source field for translatable tables or their origin field for non-translatable tables and creates an id mapping.
protected
fetchDependentIdMap(string $tableName, array<string|int, mixed> $ids, int $desiredLanguage, BackendUserAuthentication $backendUser) : array<string|int, mixed>
This method expands the search criteria by expanding to ancestors.
Existing records in database:
- [uid:5, l10n_parent=0, l10n_source=0, sys_language_uid=0]
- [uid:6, l10n_parent=5, l10n_source=5, sys_language_uid=1]
- [uid:7, l10n_parent=5, l10n_source=6, sys_language_uid=2]
Input $ids and $desiredLanguage and their results:
- $ids=[5], $lang=1 -> [5 => 6] # since 5 is source of 6
- $ids=[5], $lang=2 -> [] # since 5 is parent of 7, but different language
- $ids=[6], $lang=1 -> [] # since there's nothing
- $ids=[6], $lang=2 -> [6 => 7] # since 6 has source 5, which is ancestor of 7
- $ids=[7], $lang=* -> [] # since there's nothing
Parameters
- $tableName : string
- $ids : array<string|int, mixed>
- $desiredLanguage : int
- $backendUser : BackendUserAuthentication
Return values
array<string|int, mixed>fetchTranslationValues()
Fetches translation related field values for the items submitted in the data-map.
protected
fetchTranslationValues(string $tableName, array<string|int, mixed> $fieldNames, array<string|int, mixed> $ids, BackendUserAuthentication $backendUser) : array<string|int, mixed>
Parameters
- $tableName : string
- $fieldNames : array<string|int, mixed>
- $ids : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
Return values
array<string|int, mixed>filterItemsByType()
Return array of data map items that are of given type
protected
filterItemsByType(string $type, array<string|int, DataMapItem> $items) : array<string|int, DataMapItem>
Parameters
- $type : string
- $items : array<string|int, DataMapItem>
Return values
array<string|int, DataMapItem>filterNewItemIds()
Return only ids that don't have an item equivalent in $this->allItems.
protected
filterNewItemIds(string $tableName, array<string|int, int> $ids, array<string|int, mixed> $allItems) : array<string|int, mixed>
Parameters
- $tableName : string
- $ids : array<string|int, int>
- $allItems : array<string|int, mixed>
Return values
array<string|int, mixed>filterNumericIds()
Return only ids that are integer - so no "NEW..." values
protected
filterNumericIds(array<string|int, string>|array<string|int, int> $ids) : array<string|int, int>
Parameters
- $ids : array<string|int, string>|array<string|int, int>
Return values
array<string|int, int>finishTranslationItem()
Finishes a translation item by updating states to be persisted.
protected
finishTranslationItem(DataMapItem $item, array<string|int, mixed> $allDataMap) : array<string|int, mixed>
Parameters
- $item : DataMapItem
- $allDataMap : array<string|int, mixed>
Return values
array<string|int, mixed>getFieldNamesForItemScope()
Field names we have to deal with
protected
getFieldNamesForItemScope(DataMapItem $item, string $scope, bool $modified) : array<string|int, string>
Parameters
- $item : DataMapItem
- $scope : string
- $modified : bool
Return values
array<string|int, string>getFieldNamesToBeHandled()
Gets a list of field names which have to be handled. Basically this includes fields using allowLanguageSynchronization or l10n_mode=exclude.
protected
getFieldNamesToBeHandled(string $tableName) : array<string|int, string>
Parameters
- $tableName : string
Return values
array<string|int, string>getLanguageService()
protected
getLanguageService() : LanguageService|null
Return values
LanguageService|nullgetLocalizationModeExcludeFieldNames()
Field names of TCA table with columns having l10n_mode=exclude
protected
getLocalizationModeExcludeFieldNames(string $tableName) : array<string|int, string>
Parameters
- $tableName : string
Return values
array<string|int, string>getPrefixLanguageTitleFieldNames()
Field names of TCA table with columns having l10n_mode=prefixLangTitle
protected
getPrefixLanguageTitleFieldNames(string $tableName) : array<string|int, mixed>
Parameters
- $tableName : string
Return values
array<string|int, mixed>getSchema()
protected
getSchema(string $table) : TcaSchema|null
Parameters
- $table : string
Return values
TcaSchema|nullisApplicable()
Determines whether the table can be localized and either has fields with allowLanguageSynchronization enabled or l10n_mode set to exclude.
protected
isApplicable(string $tableName) : bool
Parameters
- $tableName : string
Return values
boolisReferenceField()
True if we're dealing with a reference field (either "inline" or "file") with foreign_table set.
protected
isReferenceField(string $tableName, string $fieldName) : bool
Parameters
- $tableName : string
- $fieldName : string
Return values
boolisRelationField()
True if we're dealing with a field that has foreign db relations (type=group or select with foreign_table).
protected
isRelationField(string $tableName, string $fieldName) : bool
Parameters
- $tableName : string
- $fieldName : string
Return values
boolisSetInDataMap()
Determines whether a combination of table name, id and field name is set in data-map. This method considers null values as well, that would not be considered by a plain isset() invocation.
protected
isSetInDataMap(string $tableName, string|int $id, string $fieldName, array<string|int, mixed> $allDataMap) : bool
Parameters
- $tableName : string
- $id : string|int
- $fieldName : string
- $allDataMap : array<string|int, mixed>
Return values
boolmapRelationItemId()
Flatten array
protected
mapRelationItemId(array<string|int, mixed> $relationItems) : array<string|int, int>
Parameters
- $relationItems : array<string|int, mixed>
Return values
array<string|int, int>modifyDataMap()
Applies modifications to the data-map, calling this method is essential to determine new data-map items to be process for synchronizing chained record localizations.
protected
modifyDataMap(string $tableName, string|int $id, array<string|int, mixed> $values) : void
Parameters
- $tableName : string
- $id : string|int
- $values : array<string|int, mixed>
Tags
populateTranslationItem()
Populates values downwards, either from a parent language item or a source language item to an accordant dependent translation item.
protected
populateTranslationItem(DataMapItem $item, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : void
Parameters
- $item : DataMapItem
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater
prefixLanguageTitle()
Prefixes language title if applicable for the accordant field name in raw data-map item.
protected
prefixLanguageTitle(string $tableName, string|int $fromId, int $language, array<string|int, mixed> $data) : array<string|int, mixed>
Parameters
- $tableName : string
- $fromId : string|int
- $language : int
- $data : array<string|int, mixed>
Return values
array<string|int, mixed>purgeDataMap()
Purges superfluous empty data-map sections.
protected
purgeDataMap(array<string|int, mixed> $dataMap) : array<string|int, mixed>
Parameters
- $dataMap : array<string|int, mixed>
Return values
array<string|int, mixed>resolveAncestorId()
protected
resolveAncestorId(array<string, string> $fieldNames, array<string, mixed> $element) : int|null
Parameters
- $fieldNames : array<string, string>
- $element : array<string, mixed>
Return values
int|null —either a (non-empty) ancestor uid, or null if unresolved
resolveSuggestedInlineRelations()
Determines suggest inline relations of either translation parent or source record from data-map or storage in case records have been persisted already.
protected
resolveSuggestedInlineRelations(DataMapItem $item, string $fieldName, array<string|int, mixed> $fromRecord, BackendUserAuthentication $backendUser, array<string|int, mixed> $allDataMap) : array<string|int, int>|array<string|int, string>
Parameters
- $item : DataMapItem
- $fieldName : string
- $fromRecord : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
- $allDataMap : array<string|int, mixed>
Return values
array<string|int, int>|array<string|int, string>sanitize()
Sanitizes the submitted data-map items and removes fields which are not defined as custom and thus rely on either parent or source values.
protected
sanitize(array<string|int, DataMapItem> $items) : void
Parameters
- $items : array<string|int, DataMapItem>
sanitizeTranslationItem()
Sanitizes the submitted data-map for a particular item and removes fields which are not defined as custom and thus rely on either parent or source values.
protected
sanitizeTranslationItem(DataMapItem $item) : void
Parameters
- $item : DataMapItem
synchronizeDirectRelations()
Synchronize select and group field localizations
protected
synchronizeDirectRelations(DataMapItem $item, string $fieldName, array<string|int, mixed> $fromRecord, BackendUserAuthentication $backendUser) : void
Parameters
- $item : DataMapItem
- $fieldName : string
- $fromRecord : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
synchronizeFieldValues()
Synchronize simple values like text and similar
protected
synchronizeFieldValues(DataMapItem $item, string $fieldName, array<string|int, mixed> $fromRecord, array<string|int, mixed> $forRecord, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : void
Parameters
- $item : DataMapItem
- $fieldName : string
- $fromRecord : array<string|int, mixed>
- $forRecord : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater
synchronizeReferences()
Handle synchronization of references (inline or file).
protected
synchronizeReferences(DataMapItem $item, string $fieldName, array<string|int, mixed> $fromRecord, array<string|int, mixed> $forRecord, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : void
References are always modelled as 1:n composite relation - which means that direct(!) children cannot exist without their parent. Removing a relative parent results in cascaded removal of all direct(!) children as well.
Parameters
- $item : DataMapItem
- $fieldName : string
- $fromRecord : array<string|int, mixed>
- $forRecord : array<string|int, mixed>
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater
Tags
synchronizeTranslationItem()
Synchronize a single item
protected
synchronizeTranslationItem(DataMapItem $item, array<string|int, mixed> $fieldNames, string|int $fromId, BackendUserAuthentication $backendUser, ReferenceIndexUpdater $referenceIndexUpdater) : void
Parameters
- $item : DataMapItem
- $fieldNames : array<string|int, mixed>
- $fromId : string|int
- $backendUser : BackendUserAuthentication
- $referenceIndexUpdater : ReferenceIndexUpdater