Skip to content

Commit

Permalink
[BUGFIX] Handle localizeReferencesAtParentLocalization for group/db
Browse files Browse the repository at this point in the history
TCA config property 'localizeReferencesAtParentLocalization'
for database relations is only handled with type=select
having a 'foreign_table' defined.

With the similar type=group, this is only handled if
'foreign_table' is set, which is odd since group is based
on 'allowed' over 'foreign_table'.

The change adapts DataHandler to consider 'allowed' with
type=group tables and checks whether at least one of them
is localizable.

This solves an @todo from #94570 in the group DataHandling
tests. The test set is completed by adding a similar set
for type=select.

Resolves: #41713
Related: #94570
Releases: master
Change-Id: I33df58fd4c9bdf31e27f64532c371c74b3f52627
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/72102
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benni Mack <benni@typo3.org>
  • Loading branch information
andreaswolf authored and bmack committed Nov 10, 2021
1 parent 4709cc5 commit 7b6502f
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 12 deletions.
32 changes: 22 additions & 10 deletions typo3/sysext/core/Classes/DataHandling/DataHandler.php
Expand Up @@ -3753,33 +3753,45 @@ public function copyRecord_procBasedOnFieldType($table, $uid, $field, $value, $r
protected function copyRecord_processManyToMany($table, $uid, $field, $value, $conf, $language)
{
$allowedTables = $conf['type'] === 'group' ? $conf['allowed'] : $conf['foreign_table'];
$allowedTablesArray = GeneralUtility::trimExplode(',', $allowedTables, true);
$prependName = $conf['type'] === 'group' ? ($conf['prepend_tname'] ?? '') : '';
$mmTable = isset($conf['MM']) && $conf['MM'] ? $conf['MM'] : '';
$localizeForeignTable = isset($conf['foreign_table']) && BackendUtility::isTableLocalizable($conf['foreign_table']);
// Localize referenced records of select fields:
$localizingNonManyToManyFieldReferences = empty($mmTable) && $localizeForeignTable && isset($conf['localizeReferencesAtParentLocalization']) && $conf['localizeReferencesAtParentLocalization'];
/** @var RelationHandler $dbAnalysis */
$mmTable = !empty($conf['MM']) ? $conf['MM'] : '';

$dbAnalysis = $this->createRelationHandlerInstance();
$dbAnalysis->start($value, $allowedTables, $mmTable, $uid, $table, $conf);
$purgeItems = false;
if ($language > 0 && $localizingNonManyToManyFieldReferences) {

// Check if referenced records of select or group fields should also be localized in general.
// A further check is done in the loop below for each table name.
if ($language > 0 && $mmTable === '' && !empty($conf['localizeReferencesAtParentLocalization'])) {
// Check whether allowed tables can be localized.
$localizeTables = [];
foreach ($allowedTablesArray as $allowedTable) {
$localizeTables[$allowedTable] = BackendUtility::isTableLocalizable($allowedTable);
}

foreach ($dbAnalysis->itemArray as $index => $item) {
// Since select fields can reference many records, check whether there's already a localization:
// No action required, if referenced tables cannot be localized (current value will be used).
if (empty($localizeTables[$item['table']])) {
continue;
}

// Since select or group fields can reference many records, check whether there's already a localization.
$recordLocalization = BackendUtility::getRecordLocalization($item['table'], $item['id'], $language);
if ($recordLocalization) {
$dbAnalysis->itemArray[$index]['id'] = $recordLocalization[0]['uid'];
} elseif ($this->isNestedElementCallRegistered($item['table'], $item['id'], 'localize-' . (string)$language) === false) {
} elseif ($this->isNestedElementCallRegistered($item['table'], $item['id'], 'localize-' . $language) === false) {
$dbAnalysis->itemArray[$index]['id'] = $this->localize($item['table'], $item['id'], $language);
}
}
$purgeItems = true;
}

if ($purgeItems || $mmTable) {
if ($purgeItems || $mmTable !== '') {
$dbAnalysis->purgeItemArray();
$value = implode(',', $dbAnalysis->getValueArray($prependName));
}
// Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected
// Setting the value in this array will notify the remapListedDBRecords() function that this field MAY need references to be corrected.
if ($value) {
$this->registerDBList[$table][$uid][$field] = $value;
}
Expand Down
Expand Up @@ -210,8 +210,6 @@ public function localizeContentChainOfRelationWithLanguageSynchronizationSource(
public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
$GLOBALS['TCA']['tt_content']['columns'][self::FIELD_ContentElement]['config']['localizeReferencesAtParentLocalization'] = true;
// @todo: https://forge.typo3.org/issues/41713 - localizeReferencesAtParentLocalization in type=group relies on foreign_table being set
$GLOBALS['TCA']['tt_content']['columns'][self::FIELD_ContentElement]['config']['foreign_table'] = self::TABLE_Element;
$newTableIds = $this->actionService->localizeRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_LanguageId);
$this->recordIds['localizedContentId'] = $newTableIds[self::TABLE_Content][self::VALUE_ContentIdLast];
}
Expand Down
Expand Up @@ -179,6 +179,13 @@ public function localizeElementOfRelation(): void
$this->recordIds['localizedElementId'] = $newTableIds[self::TABLE_Element][self::VALUE_ElementIdFirst];
}

public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
$GLOBALS['TCA']['tt_content']['columns'][self::FIELD_ContentElement]['config']['localizeReferencesAtParentLocalization'] = true;
$newTableIds = $this->actionService->localizeRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_LanguageId);
$this->recordIds['localizedContentId'] = $newTableIds[self::TABLE_Content][self::VALUE_ContentIdLast];
}

public function moveContentOfRelationToDifferentPage(): void
{
$this->actionService->moveRecord(self::TABLE_Content, self::VALUE_ContentIdLast, self::VALUE_PageIdTarget);
Expand Down
Expand Up @@ -327,6 +327,15 @@ public function localizeElementOfRelation(): void
->setTable(self::TABLE_Element)->setField('title')->setValues('[Translate to Dansk:] Element #1', 'Element #2'));
}

/**
* @test
*/
public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
parent::localizeContentOfRelationWithLocalizeReferencesAtParentLocalization();
$this->assertAssertionDataSet('localizeContentOfRelationWLocalizeReferencesAtParentLocalization');
}

/**
* @test
* See DataSet/moveContentOfRelationToDifferentPage.csv
Expand Down
@@ -0,0 +1,33 @@
"pages",,,,,,,,,,,,,
,"uid","pid","sorting","deleted","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title",,,
,1,0,256,0,0,0,0,0,0,"FunctionalTest",,,
,88,1,256,0,0,0,0,0,0,"DataHandlerTest",,,
,89,88,256,0,0,0,0,0,0,"Relations",,,
,90,88,512,0,0,0,0,0,0,"Target",,,
"sys_language",,,,,,,,,,,,,
,"uid","pid","hidden","title","flag",,,,,,,,
,1,0,0,"Dansk","dk",,,,,,,,
,2,0,0,"Deutsch","de",,,,,,,,
"tt_content",,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","tx_testdatahandler_select"
,297,89,256,0,0,0,0,0,0,0,0,"Regular Element #1","1,2"
,298,89,512,0,0,0,0,0,0,0,0,"Regular Element #2","2,3"
,299,89,768,0,1,298,298,0,0,0,0,"[Translate to Dansk:] Regular Element #2","4,5"
"tx_testdatahandler_element",,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l10n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title",
,1,89,256,0,0,0,0,0,0,0,0,"Element #1",
,2,89,512,0,0,0,0,0,0,0,0,"Element #2",
,3,89,768,0,0,0,0,0,0,0,0,"Element #3",
,4,89,640,0,1,2,2,0,0,0,0,"[Translate to Dansk:] Element #2",
,5,89,704,0,1,3,3,0,0,0,0,"[Translate to Dansk:] Element #3",
"sys_refindex",,,,,,,,,,,,,
,"hash","tablename","recuid","field","flexpointer","softref_key","softref_id","sorting","workspace","ref_table","ref_uid","ref_string",
,"d7065184b2d510f3fada875169bc8c57","tt_content",297,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",1,,
,"d333521843e8774369e112581bd4643b","tt_content",297,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",2,,
,"fb9a4c46d91b175ee7503de71523c849","tt_content",298,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",2,,
,"f54bf3a4ddc51685c0586b31015312cb","tt_content",298,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",3,,
,"6dc66af7d395e5be3c87fc4e13c0455c","tt_content",299,"l18n_parent",,,,0,0,"tt_content",298,,
,"a5a8bb1991a2c199cbe80e3e37844190","tx_testdatahandler_element",4,"l10n_parent",,,,0,0,"tx_irretutorial_1nff_hotel",2,,
,"b76b4fe0aa225d718110c5d667c1d8b1","tt_content",299,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",4,,
,"d6055b07069ed11ff1463f05f096bf6a","tt_content",299,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",5,,
,"f32f8b540bfad29e0cc31794bb04c948","tx_testdatahandler_element",5,"l10n_parent",,,,0,0,"tx_irretutorial_1nff_hotel",3,,
Expand Up @@ -205,4 +205,14 @@ public function moveContentOfRelationToDifferentPage(): void
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, self::VALUE_ContentIdLast);
$this->assertAssertionDataSet('moveContentOfRelationToDifferentPage');
}

/**
* @test
*/
public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
parent::localizeContentOfRelationWithLocalizeReferencesAtParentLocalization();
$this->actionService->clearWorkspaceRecord(self::TABLE_Content, $this->recordIds['localizedContentId']);
$this->assertAssertionDataSet('localizeContentOfRelationWLocalizeReferencesAtParentLocalization');
}
}
@@ -0,0 +1,39 @@
"pages",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title",,,,,,,,
,1,0,256,0,0,0,0,0,"FunctionalTest",,,,,,,,
,88,1,256,0,0,0,0,0,"DataHandlerTest",,,,,,,,
,89,88,256,0,0,0,0,0,"Relations",,,,,,,,
,90,88,512,0,0,0,0,0,"Target",,,,,,,,
"sys_workspace",,,,,,,,,,,,,,,,,
,"uid","pid","deleted","title","adminusers","members","db_mountpoints","file_mountpoints","freeze","live_edit","publish_access","custom_stages","stagechg_notification","edit_notification_defaults","edit_allow_notificaton_settings","publish_notification_defaults","publish_allow_notificaton_settings"
,1,0,0,"Workspace #1",,,,,0,0,0,0,0,0,0,0,0
,2,0,0,"Workspace #2",,,,,0,0,0,0,0,0,0,0,0
"sys_workspace_stage",,,,,,,,,,,,,,,,,
,"uid","pid","tstamp","deleted","sorting","title","responsible_persons","default_mailcomment","parentid","parenttable","notification_defaults","allow_notificaton_settings",,,,,
,1,0,1290048921,0,1,"Stage 1","be_users_3",,1,"sys_workspace",0,0,,,,,
"sys_language",,,,,,,,,,,,,,,,,
,"uid","pid","hidden","title","flag",,,,,,,,,,,,
,1,0,0,"Dansk","dk",,,,,,,,,,,,
,2,0,0,"Deutsch","de",,,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","tx_testdatahandler_select",,,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1","1,2",,,,,
,298,89,512,0,0,0,0,0,0,0,"Regular Element #2","2,3",,,,,
"tx_testdatahandler_element",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l10n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title","l10n_diffsource",,,,,
,1,89,256,0,0,0,0,0,0,0,"Element #1",,,,,,
,2,89,512,0,0,0,0,0,0,0,"Element #2",,,,,,
,3,89,768,0,0,0,0,0,0,0,"Element #3",,,,,,
# @todo: Note these two are *not* discarded when parent is discarded. Probably not intended since they are now orphan?!
,4,89,640,0,1,2,1,1,0,0,"[Translate to Dansk:] Element #2",,,,,,
,5,89,704,0,1,3,1,1,0,0,"[Translate to Dansk:] Element #3",,,,,,
"sys_refindex",,,,,,,,,,,,,,,,,
,"hash","tablename","recuid","field","flexpointer","softref_key","softref_id","sorting","workspace","ref_table","ref_uid","ref_string",,,,,
,"d7065184b2d510f3fada875169bc8c57","tt_content",297,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",1,,,,,,
,"d333521843e8774369e112581bd4643b","tt_content",297,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",2,,,,,,
,"fb9a4c46d91b175ee7503de71523c849","tt_content",298,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",2,,,,,,
,"f54bf3a4ddc51685c0586b31015312cb","tt_content",298,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",3,,,,,,
,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",,,,0,0,"sys_workspace_stage",1,,,,,,
,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",,,,0,0,"be_users",3,,,,,,
,"1ebdaf9cf728f19cd80c563e4c63a22e","tx_testdatahandler_element",4,"l10n_parent",,,,0,1,"tx_irretutorial_1nff_hotel",2,,,,,,
,"4ff10724a18d4ed5323ad19158f4e807","tx_testdatahandler_element",5,"l10n_parent",,,,0,1,"tx_irretutorial_1nff_hotel",3,,,,,,
Expand Up @@ -342,4 +342,13 @@ public function moveContentOfRelationToDifferentPage(): void
->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
}

/**
* @test
*/
public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
parent::localizeContentOfRelationWithLocalizeReferencesAtParentLocalization();
$this->assertAssertionDataSet('localizeContentOfRelationWLocalizeReferencesAtParentLocalization');
}
}
@@ -0,0 +1,42 @@
"pages",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title",,,,,,,,
,1,0,256,0,0,0,0,0,"FunctionalTest",,,,,,,,
,88,1,256,0,0,0,0,0,"DataHandlerTest",,,,,,,,
,89,88,256,0,0,0,0,0,"Relations",,,,,,,,
,90,88,512,0,0,0,0,0,"Target",,,,,,,,
"sys_workspace",,,,,,,,,,,,,,,,,
,"uid","pid","deleted","title","adminusers","members","db_mountpoints","file_mountpoints","freeze","live_edit","publish_access","custom_stages","stagechg_notification","edit_notification_defaults","edit_allow_notificaton_settings","publish_notification_defaults","publish_allow_notificaton_settings"
,1,0,0,"Workspace #1",,,,,0,0,0,0,0,0,0,0,0
,2,0,0,"Workspace #2",,,,,0,0,0,0,0,0,0,0,0
"sys_workspace_stage",,,,,,,,,,,,,,,,,
,"uid","pid","tstamp","deleted","sorting","title","responsible_persons","default_mailcomment","parentid","parenttable","notification_defaults","allow_notificaton_settings",,,,,
,1,0,1290048921,0,1,"Stage 1","be_users_3",,1,"sys_workspace",0,0,,,,,
"sys_language",,,,,,,,,,,,,,,,,
,"uid","pid","hidden","title","flag",,,,,,,,,,,,
,1,0,0,"Dansk","dk",,,,,,,,,,,,
,2,0,0,"Deutsch","de",,,,,,,,,,,,
"tt_content",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","header","tx_testdatahandler_select",,,,,
,297,89,256,0,0,0,0,0,0,0,"Regular Element #1","1,2",,,,,
,298,89,512,0,0,0,0,0,0,0,"Regular Element #2","2,3",,,,,
,299,89,768,0,1,298,1,1,0,0,"[Translate to Dansk:] Regular Element #2","4,5",,,,,
"tx_testdatahandler_element",,,,,,,,,,,,,,,,,
,"uid","pid","sorting","deleted","sys_language_uid","l10n_parent","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","title","l10n_diffsource",,,,,
,1,89,256,0,0,0,0,0,0,0,"Element #1",,,,,,
,2,89,512,0,0,0,0,0,0,0,"Element #2",,,,,,
,3,89,768,0,0,0,0,0,0,0,"Element #3",,,,,,
,4,89,640,0,1,2,1,1,0,0,"[Translate to Dansk:] Element #2",,,,,,
,5,89,704,0,1,3,1,1,0,0,"[Translate to Dansk:] Element #3",,,,,,
"sys_refindex",,,,,,,,,,,,,,,,,
,"hash","tablename","recuid","field","flexpointer","softref_key","softref_id","sorting","workspace","ref_table","ref_uid","ref_string",,,,,
,"d7065184b2d510f3fada875169bc8c57","tt_content",297,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",1,,,,,,
,"d333521843e8774369e112581bd4643b","tt_content",297,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",2,,,,,,
,"fb9a4c46d91b175ee7503de71523c849","tt_content",298,"tx_testdatahandler_select",,,,0,0,"tx_testdatahandler_element",2,,,,,,
,"f54bf3a4ddc51685c0586b31015312cb","tt_content",298,"tx_testdatahandler_select",,,,1,0,"tx_testdatahandler_element",3,,,,,,
,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",,,,0,0,"sys_workspace_stage",1,,,,,,
,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",,,,0,0,"be_users",3,,,,,,
,"1ebdaf9cf728f19cd80c563e4c63a22e","tx_testdatahandler_element",4,"l10n_parent",,,,0,1,"tx_irretutorial_1nff_hotel",2,,,,,,
,"4ff10724a18d4ed5323ad19158f4e807","tx_testdatahandler_element",5,"l10n_parent",,,,0,1,"tx_irretutorial_1nff_hotel",3,,,,,,
,"e4afda9b67d6ad42e03f5c797250235d","tt_content",299,"l18n_parent",,,,0,1,"tt_content",298,,,,,,
,"de7643278f82017bce926bf4565c4cb9","tt_content",299,"tx_testdatahandler_select",,,,0,1,"tx_testdatahandler_element",4,,,,,,
,"af5b779dd2258037770a0febe6d0054f","tt_content",299,"tx_testdatahandler_select",,,,1,1,"tx_testdatahandler_element",5,,,,,,
Expand Up @@ -316,4 +316,14 @@ public function moveContentOfRelationToDifferentPage(): void
->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentElement)
->setTable(self::TABLE_Element)->setField('title')->setValues('Element #2', 'Element #3'));
}

/**
* @test
*/
public function localizeContentOfRelationWithLocalizeReferencesAtParentLocalization()
{
parent::localizeContentOfRelationWithLocalizeReferencesAtParentLocalization();
$this->actionService->publishRecord(self::TABLE_Content, 299);
$this->assertAssertionDataSet('localizeContentOfRelationWLocalizeReferencesAtParentLocalization');
}
}

0 comments on commit 7b6502f

Please sign in to comment.