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:

  1. 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.

  2. 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.

  3. 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.

Internal

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 = []

$modifiedDataMap

protected array<string, array<string|int, mixed>> $modifiedDataMap = []

$sanitizationMap

protected array<string, array<int, array<string|int, mixed>>> $sanitizationMap = []

Methods

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>

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

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
throws
InvalidArgumentException
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>

getLocalizationModeExcludeFieldNames()

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>

isApplicable()

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
bool

isReferenceField()

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
bool

isRelationField()

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
bool

isSetInDataMap()

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
bool

mapRelationItemId()

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
throws
RuntimeException

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

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
throws
RuntimeException

        
On this page

Search results