[BUGFIX] Keep language reference for children using l10n_mode=exclude 29/59629/8
authorOliver Hader <oliver@typo3.org>
Mon, 4 Feb 2019 12:51:37 +0000 (13:51 +0100)
committerBenni Mack <benni@typo3.org>
Fri, 8 Feb 2019 08:33:15 +0000 (09:33 +0100)
Having 1:n child associations being defined as l10n_mode=exclude on their
parent side, currently leads to deleting and recreating the child entity
(re-synchronization). For composite relations (children can only exist
with their parent - usually accessed through their parent as aggregate
root) this is "okay" in terms of domain-driven design.

However having large data-sets leads to performance impact during the
re-synchronization process.

In the current scenario children processed with l10n_mode=exclude did not
have any pointer to their language origin (due to l10n_parent not being
set). This change copies these children and applies the same values as
used for localizations - without actually invoking the localization
process.

For l10n_mode=exclude children this means, the sys_language_uid and
l10n_parent values are now set - which have been empty before.

Resolves: #87640
Releases: master, 9.5
Change-Id: I3d862f536603b9e49c7a5d3205ccfc2b4e2e9532
Reviewed-on: https://review.typo3.org/59629
Tested-by: TYPO3com <noreply@typo3.com>
Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de>
Tested-by: Daniel Goerz <daniel.goerz@posteo.de>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
12 files changed:
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/AbstractActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizePageNAddHotelChildWExclude.csv
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizePageTwiceWExclude.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizePageWExclude.csv
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageTwiceWExclude.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv

index 6e55910..4a68673 100644 (file)
@@ -3014,10 +3014,12 @@ class DataHandler implements LoggerAwareInterface
                                 $this->moveRecord($table, $id, $value);
                                 break;
                             case 'copy':
+                                $target = $value['target'] ?? $value;
+                                $ignoreLocalization = (bool)($value['ignoreLocalization'] ?? false);
                                 if ($table === 'pages') {
-                                    $this->copyPages($id, $value);
+                                    $this->copyPages($id, $target);
                                 } else {
-                                    $this->copyRecord($table, $id, $value, true);
+                                    $this->copyRecord($table, $id, $target, true, [], '', 0, $ignoreLocalization);
                                 }
                                 $procId = $this->copyMappingArray[$table][$id];
                                 break;
@@ -3208,7 +3210,9 @@ class DataHandler implements LoggerAwareInterface
         if (!$ignoreLocalization && $language == 0) {
             //repointing the new translation records to the parent record we just created
             $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['transOrigPointerField']] = $theNewSQLID;
-            $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['translationSource']] = 0;
+            if (isset($GLOBALS['TCA'][$table]['ctrl']['translationSource'])) {
+                $overrideValues[$GLOBALS['TCA'][$table]['ctrl']['translationSource']] = 0;
+            }
             $this->copyL10nOverlayRecords($table, $uid, $destPid, $first, $overrideValues, $excludeFields);
         }
 
index 78ea340..ed51e0e 100644 (file)
@@ -499,7 +499,10 @@ class DataMapProcessor
     }
 
     /**
-     * Handle synchronization of inline relations
+     * Handle synchronization of inline relations.
+     * Inline Relational Record Editong ("IRRE") always is 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.
      *
      * @param DataMapItem $item
      * @param string $fieldName
@@ -519,6 +522,7 @@ class DataMapProcessor
             'source' => $GLOBALS['TCA'][$foreignTableName]['ctrl']['translationSource'] ?? null,
         ];
         $isTranslatable = (!empty($fieldNames['language']) && !empty($fieldNames['parent']));
+        $isLocalized = !empty($item->getLanguage());
 
         $suggestedAncestorIds = $this->resolveSuggestedInlineRelations(
             $item,
@@ -597,7 +601,10 @@ class DataMapProcessor
         foreach ($createAncestorIds as $createAncestorId) {
             // if child table is not aware of localization, just copy
             if ($isLocalizationModeExclude || !$isTranslatable) {
-                $localCommandMap[$foreignTableName][$createAncestorId]['copy'] = -$createAncestorId;
+                $localCommandMap[$foreignTableName][$createAncestorId]['copy'] = [
+                    'target' => -$createAncestorId,
+                    'ignoreLocalization' => true,
+                ];
             } else {
                 // otherwise, trigger the localization process
                 $localCommandMap[$foreignTableName][$createAncestorId]['localize'] = $item->getLanguage();
@@ -624,6 +631,22 @@ class DataMapProcessor
                 $newLocalizationId = $localDataHandler->copyMappingArray_merged[$foreignTableName][$createAncestorId];
                 $newLocalizationId = $localDataHandler->getAutoVersionId($foreignTableName, $newLocalizationId) ?? $newLocalizationId;
                 $desiredIdMap[$createAncestorId] = $newLocalizationId;
+                // apply localization references to l10n_mode=exclude children
+                // (without keeping their reference to their origin, synchronization is not possible)
+                if ($isLocalizationModeExclude && $isTranslatable && $isLocalized) {
+                    $adjustCopiedValues = $this->applyLocalizationReferences(
+                        $foreignTableName,
+                        $createAncestorId,
+                        $item->getLanguage(),
+                        $fieldNames,
+                        []
+                    );
+                    $this->modifyDataMap(
+                        $foreignTableName,
+                        $newLocalizationId,
+                        $adjustCopiedValues
+                    );
+                }
             }
         }
         // populate new child records in data-map
@@ -631,13 +654,26 @@ class DataMapProcessor
             foreach ($populateAncestorIds as $populateAncestorId) {
                 $newLocalizationId = StringUtility::getUniqueId('NEW');
                 $desiredIdMap[$populateAncestorId] = $newLocalizationId;
-                $duplicatedValues = $this->duplicateFromDataMap(
-                    $foreignTableName,
-                    $populateAncestorId,
-                    $item->getLanguage(),
-                    $fieldNames,
-                    !$isLocalizationModeExclude && $isTranslatable
-                );
+                $duplicatedValues = $this->allDataMap[$foreignTableName][$populateAncestorId] ?? [];
+                // applies localization references to given raw data-map item
+                if ($isTranslatable && $isLocalized) {
+                    $duplicatedValues = $this->applyLocalizationReferences(
+                        $foreignTableName,
+                        $populateAncestorId,
+                        $item->getLanguage(),
+                        $fieldNames,
+                        $duplicatedValues
+                    );
+                }
+                // prefixes language title if applicable for the accordant field name in raw data-map item
+                if ($isTranslatable && $isLocalized && !$isLocalizationModeExclude) {
+                    $duplicatedValues = $this->prefixLanguageTitle(
+                        $foreignTableName,
+                        $populateAncestorId,
+                        $item->getLanguage(),
+                        $duplicatedValues
+                    );
+                }
                 $this->modifyDataMap(
                     $foreignTableName,
                     $newLocalizationId,
@@ -938,6 +974,7 @@ class DataMapProcessor
         $originFieldName = ($GLOBALS['TCA'][$tableName]['ctrl']['origUid'] ?? null);
 
         if (!$isTranslatable && $originFieldName === null) {
+            // @todo Possibly throw an error, since pointing to original entity is not possible (via origin/parent)
             return [];
         }
 
@@ -1205,7 +1242,7 @@ class DataMapProcessor
     }
 
     /**
-     * Duplicates an item from data-map and prefixed language title,
+     * Duplicates an item from data-map and prefixes language title,
      * if applicable for the accordant field name.
      *
      * @param string $tableName
@@ -1214,20 +1251,45 @@ class DataMapProcessor
      * @param array $fieldNames
      * @param bool $localize
      * @return array
+     * @deprecated Not used anymore, split into applyLocalizationReferences() and prefixLanguageTitle()
      */
-    protected function duplicateFromDataMap(string $tableName, $fromId, int $language, array $fieldNames, bool $localize)
+    protected function duplicateFromDataMap(string $tableName, $fromId, int $language, array $fieldNames, bool $localize): array
     {
-        $data = $this->allDataMap[$tableName][$fromId];
-        // just return duplicated item if localization cannot be applied
+        $data = $this->allDataMap[$tableName][$fromId] ?? [];
+        // just return if localization cannot be applied
         if (empty($language) || !$localize) {
             return $data;
         }
+        $data = $this->applyLocalizationReferences($tableName, $fromId, $language, $fieldNames, $data);
+        $data = $this->prefixLanguageTitle($tableName, $fromId, $language, $data);
+        return $data;
+    }
 
+    /**
+     * Applies localization references to given raw data-map item.
+     *
+     * @param string $tableName
+     * @param string|int $fromId
+     * @param int $language
+     * @param array $fieldNames
+     * @param array $data
+     * @return array
+     */
+    protected function applyLocalizationReferences(string $tableName, $fromId, int $language, array $fieldNames, array $data): array
+    {
+        // just return if localization cannot be applied
+        if (empty($language)) {
+            return $data;
+        }
+
+        // apply `languageField`, e.g. `sys_language_uid`
         $data[$fieldNames['language']] = $language;
+        // apply `transOrigPointerField`, e.g. `l10n_parent`
         if (empty($data[$fieldNames['parent']])) {
             // @todo Only $id used in TCA type 'select' is resolved in DataHandler's remapStack
             $data[$fieldNames['parent']] = $fromId;
         }
+        // apply `translationSource`, e.g. `l10n_source`
         if (!empty($fieldNames['source'])) {
             // @todo Not sure, whether $id is resolved in DataHandler's remapStack
             $data[$fieldNames['source']] = $fromId;
@@ -1237,6 +1299,20 @@ class DataMapProcessor
             unset($data[$fieldName]);
         }
 
+        return $data;
+    }
+
+    /**
+     * Prefixes language title if applicable for the accordant field name in raw data-map item.
+     *
+     * @param string $tableName
+     * @param $fromId
+     * @param int $language
+     * @param array $data
+     * @return array
+     */
+    protected function prefixLanguageTitle(string $tableName, $fromId, int $language, array $data): array
+    {
         $prefixFieldNames = array_intersect(
             array_keys($data),
             $this->getPrefixLanguageTitleFieldNames($tableName)
index db75567..15add58 100644 (file)
@@ -28,6 +28,7 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
     const VALUE_HotelIdSecond = 4;
     const VALUE_HotelIdThird = 5;
     const VALUE_LanguageId = 1;
+    const VALUE_LanguageIdSecond = 2;
 
     const TABLE_Page = 'pages';
     const TABLE_Content = 'tt_content';
@@ -332,6 +333,18 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
         $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
     }
 
+    public function localizePageTwiceWithLocalizationExclude()
+    {
+        $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        // in these test cases we expect new pages not to be hidden in order to
+        // verify proper overlaying behavior during the frontend render process
+        $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageIdFirst'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageIdSecond);
+        $this->recordIds['localizedPageIdSecond'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+    }
+
     public function localizePageAndAddHotelChildWithLocalizationExclude()
     {
         $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
index f831b7f..41bef5a 100644 (file)
@@ -423,6 +423,21 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
 
     /**
      * @test
+     * @see DataSet/localizePageTwiceWExclude.csv
+     */
+    public function localizePageTwiceWithLocalizationExclude()
+    {
+        parent::localizePageTwiceWithLocalizationExclude();
+        $this->assertAssertionDataSet('localizePageTwiceWExclude');
+
+        $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+            ->setRecordIdentifier(self::TABLE_Page . ':' . self::VALUE_PageId)->setRecordField(self::FIELD_PageHotel)
+            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #0'));
+    }
+
+    /**
+     * @test
      * @see DataSet/localizePageNAddHotelChildWExclude.csv
      */
     public function localizePageAndAddHotelChildWithLocalizationExclude()
index 777aac1..d15e8d2 100644 (file)
@@ -2,9 +2,9 @@ pages,,,,,,,,,,,,,,
 ,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_1ncsv_hotels,,
 ,1,0,256,0,0,0,0,0,0,0,FunctionalTest,,,
 ,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,,,
-,89,88,256,0,0,0,0,0,0,0,Relations,"2,8",,
+,89,88,256,0,0,0,0,0,0,0,Relations,"2,7",,
 ,90,88,512,0,0,0,0,0,0,0,Target,,,
-,91,88,256,0,0,0,0,0,0,0,"[Translate to Dansk:] Relations","7,9",,
+,91,88,256,0,0,0,0,0,0,0,"[Translate to Dansk:] Relations","6,8",,
 tt_content,,,,,,,,,,,,,,
 ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1ncsv_hotels
 ,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1","3,4"
@@ -15,10 +15,9 @@ tx_irretutorial_1ncsv_hotel,,,,,,,,,,,,,,
 ,3,89,768,0,0,0,0,0,0,0,0,0,"Hotel #1","5,6"
 ,4,89,640,0,0,0,0,0,0,0,0,0,"Hotel #2",7
 ,5,89,576,0,0,0,0,0,0,0,0,0,"Hotel #1",8
-,6,89,32,1,0,0,2,0,0,0,0,0,"Hotel #0",
-,7,89,544,0,0,0,2,0,0,0,0,0,"Hotel #0",
-,8,89,0,0,0,0,0,0,0,0,0,0,"Hotel #007",
-,9,89,256,0,0,0,0,0,0,0,0,0,"Hotel #007",
+,6,89,544,0,1,2,2,0,0,0,0,0,"Hotel #0",
+,7,89,0,0,0,0,0,0,0,0,0,0,"Hotel #007",
+,8,89,256,0,1,7,0,0,0,0,0,0,"Hotel #007",
 tx_irretutorial_1ncsv_offer,,,,,,,,,,,,,,
 ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,prices
 ,5,89,256,0,0,0,0,0,0,0,0,0,"Offer #1.1","7,8,9"
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizePageTwiceWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizePageTwiceWExclude.csv
new file mode 100644 (file)
index 0000000..ab7fa7f
--- /dev/null
@@ -0,0 +1,35 @@
+pages,,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,tx_irretutorial_1ncsv_hotels,,
+,1,0,256,0,0,0,0,0,0,0,FunctionalTest,,,
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,,,
+,89,88,256,0,0,0,0,0,0,0,Relations,2,,
+,90,88,512,0,0,0,0,0,0,0,Target,,,
+,91,88,256,0,0,0,0,0,0,0,"[Translate to Dansk:] Relations",6,,
+,92,88,256,0,0,0,0,0,0,0,"[Translate to Deutsch:] Relations",7,,
+tt_content,,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,header,tx_irretutorial_1ncsv_hotels
+,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1","3,4"
+,298,89,512,0,0,0,0,0,0,0,0,0,"Regular Element #2",5
+tx_irretutorial_1ncsv_hotel,,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,offers
+,2,89,1,0,0,0,0,0,0,0,0,0,"Hotel #0",
+,3,89,256,0,0,0,0,0,0,0,0,0,"Hotel #1","5,6"
+,4,89,128,0,0,0,0,0,0,0,0,0,"Hotel #2",7
+,5,89,64,0,0,0,0,0,0,0,0,0,"Hotel #1",8
+,6,89,32,0,1,2,2,0,0,0,0,0,"Hotel #0",
+,7,89,16,0,2,2,2,0,0,0,0,0,"Hotel #0",
+tx_irretutorial_1ncsv_offer,,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,prices
+,5,89,256,0,0,0,0,0,0,0,0,0,"Offer #1.1","7,8,9"
+,6,89,128,0,0,0,0,0,0,0,0,0,"Offer #1.2","10,11"
+,7,89,64,0,0,0,0,0,0,0,0,0,"Offer #2.1",12
+,8,89,32,0,0,0,0,0,0,0,0,0,"Offer #1.1",13
+tx_irretutorial_1ncsv_price,,,,,,,,,,,,,,
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,
+,7,89,256,0,0,0,0,0,0,0,0,0,"Price #1.1.1",
+,8,89,128,0,0,0,0,0,0,0,0,0,"Price #1.1.2",
+,9,89,64,0,0,0,0,0,0,0,0,0,"Price #1.1.3",
+,10,89,32,0,0,0,0,0,0,0,0,0,"Price #1.2.1",
+,11,89,16,0,0,0,0,0,0,0,0,0,"Price #1.2.2",
+,12,89,8,0,0,0,0,0,0,0,0,0,"Price #2.1.1",
+,13,89,4,0,0,0,0,0,0,0,0,0,"Price #1.1.1",
index 411d331..c9f7733 100644 (file)
@@ -15,7 +15,7 @@ tx_irretutorial_1ncsv_hotel,,,,,,,,,,,,,,
 ,3,89,256,0,0,0,0,0,0,0,0,0,"Hotel #1","5,6"
 ,4,89,128,0,0,0,0,0,0,0,0,0,"Hotel #2",7
 ,5,89,64,0,0,0,0,0,0,0,0,0,"Hotel #1",8
-,6,89,32,0,0,0,2,0,0,0,0,0,"Hotel #0",
+,6,89,32,0,1,2,2,0,0,0,0,0,"Hotel #0",
 tx_irretutorial_1ncsv_offer,,,,,,,,,,,,,,
 ,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3_origuid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,prices
 ,5,89,256,0,0,0,0,0,0,0,0,0,"Offer #1.1","7,8,9"
index b47e17d..d272f40 100644 (file)
@@ -461,6 +461,18 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
         $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
     }
 
+    public function localizePageTwiceWithLocalizationExclude()
+    {
+        $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        // in these test cases we expect new pages not to be hidden in order to
+        // verify proper overlaying behavior during the frontend render process
+        $GLOBALS['TCA'][self::TABLE_Page]['columns']['hidden']['config']['default'] = 0;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageIdFirst'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageIdSecond);
+        $this->recordIds['localizedPageIdSecond'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+    }
+
     public function localizePageAndAddHotelChildWithLocalizationExclude()
     {
         $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
index 46d0db5..6631bcc 100644 (file)
@@ -506,6 +506,21 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
 
     /**
      * @test
+     * @see DataSet/localizePageTwiceWExclude.csv
+     */
+    public function localizePageTwiceWithLocalizationExclude()
+    {
+        parent::localizePageTwiceWithLocalizationExclude();
+        $this->assertAssertionDataSet('localizePageTwiceWExclude');
+
+        $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
+        $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
+            ->setRecordIdentifier(self::TABLE_Page . ':' . self::VALUE_PageId)->setRecordField(self::FIELD_PageHotel)
+            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #0'));
+    }
+
+    /**
+     * @test
      * @see DataSet/localizePageNAddHotelChildWExclude.csv
      */
     public function localizePageAndAddHotelChildWithLocalizationExclude()
index 19acf7d..196c1b7 100644 (file)
 ,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier","offers"
 ,2,89,1,0,0,0,0,0,0,0,0,0,"Hotel #0",89,"pages",,0
 ,3,89,513,0,0,0,0,0,0,0,0,0,"Hotel #1",297,"tt_content",,2
-,4,89,1538,0,0,0,0,0,0,0,0,0,"Hotel #2",297,"tt_content",,1
+,4,89,1026,0,0,0,0,0,0,0,0,0,"Hotel #2",297,"tt_content",,1
 ,5,89,513,0,0,0,0,0,0,0,0,0,"Hotel #1",298,"tt_content",,1
-,6,89,1,1,0,0,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
-,7,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
-,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,"pages",,0
-,9,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",91,"pages",,0
+,6,89,1,0,1,2,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
+,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,"pages",,0
+,8,89,2,0,1,7,0,0,0,0,0,0,"Hotel #007",91,"pages",,0
 "tx_irretutorial_1nff_offer",,,,,,,,,,,,,,,,,
 ,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier","prices"
 ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,"tx_irretutorial_1nff_hotel",,3
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageTwiceWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageTwiceWExclude.csv
new file mode 100644 (file)
index 0000000..e717797
--- /dev/null
@@ -0,0 +1,35 @@
+"pages",,,,,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l10n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","tx_irretutorial_hotels",,,
+,1,0,256,0,0,0,0,0,0,0,0,0,"FunctionalTest",0,,,
+,88,1,256,0,0,0,0,0,0,0,0,0,"DataHandlerTest",0,,,
+,89,88,256,0,0,0,0,0,0,0,0,0,"Relations",1,,,
+,90,88,512,0,0,0,0,0,0,0,0,0,"Target",0,,,
+,91,88,256,0,1,89,0,0,0,0,0,0,"[Translate to Dansk:] Relations",1,,,
+,92,88,256,0,2,89,0,0,0,0,0,0,"[Translate to Deutsch:] Relations",1,,,
+"tt_content",,,,,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","header","tx_irretutorial_1nff_hotels",,,
+,297,89,256,0,0,0,0,0,0,0,0,0,"Regular Element #1",2,,,
+,298,89,512,0,0,0,0,0,0,0,0,0,"Regular Element #2",1,,,
+"tx_irretutorial_1nff_hotel",,,,,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier","offers"
+,2,89,1,0,0,0,0,0,0,0,0,0,"Hotel #0",89,"pages",,0
+,3,89,1,0,0,0,0,0,0,0,0,0,"Hotel #1",297,"tt_content",,2
+,4,89,1026,0,0,0,0,0,0,0,0,0,"Hotel #2",297,"tt_content",,1
+,5,89,1,0,0,0,0,0,0,0,0,0,"Hotel #1",298,"tt_content",,1
+,6,89,1,0,1,2,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
+,7,89,1,0,2,2,2,0,0,0,0,0,"Hotel #0",92,"pages",,0
+"tx_irretutorial_1nff_offer",,,,,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier","prices"
+,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,"tx_irretutorial_1nff_hotel",,3
+,6,89,2,0,0,0,0,0,0,0,0,0,"Offer #1.2",3,"tx_irretutorial_1nff_hotel",,2
+,7,89,1,0,0,0,0,0,0,0,0,0,"Offer #2.1",4,"tx_irretutorial_1nff_hotel",,1
+,8,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",5,"tx_irretutorial_1nff_hotel",,1
+"tx_irretutorial_1nff_price",,,,,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier",
+,7,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",5,"tx_irretutorial_1nff_offer",,
+,8,89,2,0,0,0,0,0,0,0,0,0,"Price #1.1.2",5,"tx_irretutorial_1nff_offer",,
+,9,89,3,0,0,0,0,0,0,0,0,0,"Price #1.1.3",5,"tx_irretutorial_1nff_offer",,
+,10,89,1,0,0,0,0,0,0,0,0,0,"Price #1.2.1",6,"tx_irretutorial_1nff_offer",,
+,11,89,2,0,0,0,0,0,0,0,0,0,"Price #1.2.2",6,"tx_irretutorial_1nff_offer",,
+,12,89,1,0,0,0,0,0,0,0,0,0,"Price #2.1.1",7,"tx_irretutorial_1nff_offer",,
+,13,89,1,0,0,0,0,0,0,0,0,0,"Price #1.1.1",8,"tx_irretutorial_1nff_offer",,
index cc4db24..2f5de0d 100644 (file)
@@ -15,7 +15,7 @@
 ,3,89,1,0,0,0,0,0,0,0,0,0,"Hotel #1",297,"tt_content",,2
 ,4,89,514,0,0,0,0,0,0,0,0,0,"Hotel #2",297,"tt_content",,1
 ,5,89,1,0,0,0,0,0,0,0,0,0,"Hotel #1",298,"tt_content",,1
-,6,89,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
+,6,89,1,0,1,2,2,0,0,0,0,0,"Hotel #0",91,"pages",,0
 "tx_irretutorial_1nff_offer",,,,,,,,,,,,,,,,,
 ,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title","parentid","parenttable","parentidentifier","prices"
 ,5,89,1,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,"tx_irretutorial_1nff_hotel",,3