[TASK] Enhance DataHandler translation and synchronization handling 14/51714/10
authorOliver Hader <oliver@typo3.org>
Wed, 15 Feb 2017 21:47:15 +0000 (22:47 +0100)
committerSusanne Moog <susanne.moog@typo3.org>
Mon, 20 Feb 2017 06:22:00 +0000 (07:22 +0100)
* add more tests for allowLanguageSynchronization & l10n_mode=exclude
* enhance inline children synchronization for non-translatable tables
  using $GLOBALS['TCA'][$tableName]['ctrl']['origUid'] if defined
* bugfix for copying records instead of localizing them - the target
  page-id was missing
* integrate handling of l10n_mode=prefixLangTitle for cloning data
  in memory - DataHandler hooks are not process in that regard

Resolves: #79856
Releases: master
Change-Id: I7f5ef7edba9e80deba6025fe1394d10ee8e2d78c
Reviewed-on: https://review.typo3.org/51714
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
12 files changed:
typo3/sysext/core/Classes/DataHandling/Localization/DataMapProcessor.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/ActionTest.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/Modify/DataSet/localizeParentContentWAllChildrenSelectNLanguageSynchronization.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/localizeNCopyPageWSynchronization.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeParentContentWAllChildrenSelectNLanguageSynchronization.csv

index 661ab3b..a01fb14 100644 (file)
@@ -25,6 +25,7 @@ use TYPO3\CMS\Core\DataHandling\DataHandler;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
+use TYPO3\CMS\Lang\LanguageService;
 
 /**
  * This processor analyses the provided data-map before actually being process
@@ -402,17 +403,22 @@ class DataMapProcessor
      * @param string $fieldName
      * @param array $fromRecord
      * @param array $forRecord
+     * @throws \RuntimeException
      */
     protected function synchronizeInlineRelations(DataMapItem $item, string $fieldName, array $fromRecord, array $forRecord)
     {
         $fromId = $fromRecord['uid'];
         $configuration = $GLOBALS['TCA'][$item->getFromTableName()]['columns'][$fieldName];
+        $isLocalizationModeExclude = ($configuration['l10n_mode'] ?? null) === 'exclude';
         $foreignTableName = $configuration['config']['foreign_table'];
         $manyToManyTable = ($configuration['config']['MM'] ?? '');
 
-        $languageFieldName = ($GLOBALS['TCA'][$foreignTableName]['ctrl']['languageField'] ?? null);
-        $parentFieldName = ($GLOBALS['TCA'][$foreignTableName]['ctrl']['transOrigPointerField'] ?? null);
-        $sourceFieldName = ($GLOBALS['TCA'][$foreignTableName]['ctrl']['translationSource'] ?? null);
+        $fieldNames = [
+            'language' => ($GLOBALS['TCA'][$foreignTableName]['ctrl']['languageField'] ?? null),
+            'parent' => ($GLOBALS['TCA'][$foreignTableName]['ctrl']['transOrigPointerField'] ?? null),
+            'source' => ($GLOBALS['TCA'][$foreignTableName]['ctrl']['translationSource'] ?? null),
+        ];
+        $isTranslatable = (!empty($fieldNames['language']) && !empty($fieldNames['parent']));
 
         // determine suggested elements of either translation parent or source record
         // from data-map, in case the accordant language parent/source record was modified
@@ -463,19 +469,19 @@ class DataMapProcessor
         $createAncestorIds = $this->filterNumericIds($missingAncestorIds, true);
         // non-persisted elements that should be duplicated in data-map directly
         $populateAncestorIds = $this->filterNumericIds($missingAncestorIds, false);
-        // this desired state map defines the final result of child elements of the translation
-        $desiredLocalizationIdMap = array_combine($suggestedAncestorIds, $suggestedAncestorIds);
+        // this desired state map defines the final result of child elements in their parent translation
+        $desiredIdMap = array_combine($suggestedAncestorIds, $suggestedAncestorIds);
         // update existing translations in the desired state map
         foreach ($dependentIdMap as $ancestorId => $translationId) {
-            if (isset($desiredLocalizationIdMap[$ancestorId])) {
-                $desiredLocalizationIdMap[$ancestorId] = $translationId;
+            if (isset($desiredIdMap[$ancestorId])) {
+                $desiredIdMap[$ancestorId] = $translationId;
             }
         }
         // nothing to synchronize, but element order could have been changed
         if (empty($removeAncestorIds) && empty($missingAncestorIds)) {
             $this->dataMap[$item->getTableName()][$item->getId()][$fieldName] = implode(
                 ',',
-                array_values($desiredLocalizationIdMap)
+                array_values($desiredIdMap)
             );
             return;
         }
@@ -490,8 +496,8 @@ class DataMapProcessor
         }
         foreach ($createAncestorIds as $createAncestorId) {
             // if child table is not aware of localization, just copy
-            if (empty($languageFieldName) || empty($parentFieldName)) {
-                $localCommandMap[$foreignTableName][$createAncestorId]['copy'] = true;
+            if ($isLocalizationModeExclude || !$isTranslatable) {
+                $localCommandMap[$foreignTableName][$createAncestorId]['copy'] = -$createAncestorId;
             // otherwise, trigger the localization process
             } else {
                 $localCommandMap[$foreignTableName][$createAncestorId]['localize'] = $item->getLanguage();
@@ -505,33 +511,37 @@ class DataMapProcessor
             // update copied or localized ids
             foreach ($createAncestorIds as $createAncestorId) {
                 if (empty($localDataHandler->copyMappingArray_merged[$foreignTableName][$createAncestorId])) {
-                    throw new \RuntimeException('Child record was not processed', 1486233164);
+                    $additionalInformation = '';
+                    if (!empty($localDataHandler->errorLog)) {
+                        $additionalInformation = ', reason "'
+                        . implode(', ', $localDataHandler->errorLog) . '"';
+                    }
+                    throw new \RuntimeException(
+                        'Child record was not processed' . $additionalInformation,
+                        1486233164);
                 }
                 $newLocalizationId = $localDataHandler->copyMappingArray_merged[$foreignTableName][$createAncestorId];
                 $newLocalizationId = $localDataHandler->getAutoVersionId($foreignTableName, $newLocalizationId) ?? $newLocalizationId;
-                $desiredLocalizationIdMap[$createAncestorId] = $newLocalizationId;
+                $desiredIdMap[$createAncestorId] = $newLocalizationId;
             }
         }
         // populate new child records in data-map
         if (!empty($populateAncestorIds)) {
-            foreach ($populateAncestorIds as $populateId) {
+            foreach ($populateAncestorIds as $populateAncestorId) {
                 $newLocalizationId = StringUtility::getUniqueId('NEW');
-                $desiredLocalizationIdMap[$populateId] = $newLocalizationId;
-                // @todo l10n_mode=prefixLangTitle is not applied to this "in-memory translation"
-                $this->dataMap[$foreignTableName][$newLocalizationId] = $this->dataMap[$foreignTableName][$populateId];
-                $this->dataMap[$foreignTableName][$newLocalizationId][$languageFieldName] = $item->getLanguage();
-                // @todo Only $populatedIs used in TCA type 'select' is resolved in DataHandler's remapStack
-                $this->dataMap[$foreignTableName][$newLocalizationId][$parentFieldName] = $populateId;
-                if ($sourceFieldName !== null) {
-                    // @todo Not sure, whether $populateId is resolved in DataHandler's remapStack
-                    $this->dataMap[$foreignTableName][$newLocalizationId][$sourceFieldName] = $populateId;
-                }
+                $desiredIdMap[$populateAncestorId] = $newLocalizationId;
+                $this->dataMap[$foreignTableName][$newLocalizationId] = $this->duplicateFromDataMap(
+                    $foreignTableName,
+                    $populateAncestorId,
+                    $item->getLanguage(),
+                    $fieldNames
+                );
             }
         }
         // update inline parent field references - required to update pointer fields
         $this->dataMap[$item->getTableName()][$item->getId()][$fieldName] = implode(
             ',',
-            array_values($desiredLocalizationIdMap)
+            array_values($desiredIdMap)
         );
     }
 
@@ -622,8 +632,9 @@ class DataMapProcessor
     }
 
     /**
-     * Fetch dependent records that depend on given record id's in their parent or source field and
-     * create an id map as further lookup array
+     * 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.
      *
      * @param string $tableName
      * @param array $ids
@@ -635,48 +646,67 @@ class DataMapProcessor
             $tableName = 'pages_language_overlay';
         }
 
-        if (!BackendUtility::isTableLocalizable($tableName)) {
+        $isTranslatable = BackendUtility::isTableLocalizable($tableName);
+        $originFieldName = ($GLOBALS['TCA'][$tableName]['ctrl']['origUid'] ?? null);
+
+        if (!$isTranslatable && $originFieldName === null) {
             return [];
         }
 
-        $fieldNames = [
-            'uid' => 'uid',
-            'l10n_state' => 'l10n_state',
-            'language' => $GLOBALS['TCA'][$tableName]['ctrl']['languageField'],
-            'parent' => $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'],
-        ];
-        if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['translationSource'])) {
-            $fieldNames['source'] = $GLOBALS['TCA'][$tableName]['ctrl']['translationSource'];
+        if ($isTranslatable) {
+            $fieldNames = [
+                'uid' => 'uid',
+                'l10n_state' => 'l10n_state',
+                'language' => $GLOBALS['TCA'][$tableName]['ctrl']['languageField'],
+                'parent' => $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'],
+            ];
+            if (!empty($GLOBALS['TCA'][$tableName]['ctrl']['translationSource'])) {
+                $fieldNames['source'] = $GLOBALS['TCA'][$tableName]['ctrl']['translationSource'];
+            }
+        } else {
+            $fieldNames = [
+                'uid' => 'uid',
+                'origin' => $originFieldName,
+            ];
         }
 
         $dependentElements = $this->fetchDependentElements($tableName, $ids, $fieldNames);
 
         $dependentIdMap = [];
         foreach ($dependentElements as $dependentElement) {
+            $dependentId = $dependentElement['uid'];
+            // implicit: use origin pointer if table cannot be translated
+            if (!$isTranslatable) {
+                $dependentIdMap[$dependentElement[$fieldNames['origin']]] = $dependentId;
             // implicit: having source value different to parent value, use source pointer
-            if (
+            } elseif (
                 !empty($fieldNames['source'])
                 && $dependentElement[$fieldNames['source']] !== $dependentElement[$fieldNames['parent']]
             ) {
-                $dependentIdMap[$dependentElement[$fieldNames['source']]] = $dependentElement['uid'];
+                $dependentIdMap[$dependentElement[$fieldNames['source']]] = $dependentId;
             // implicit: otherwise, use parent pointer
             } else {
-                $dependentIdMap[$dependentElement[$fieldNames['parent']]] = $dependentElement['uid'];
+                $dependentIdMap[$dependentElement[$fieldNames['parent']]] = $dependentId;
             }
         }
         return $dependentIdMap;
     }
 
     /**
-     * Fetch all elements that depend on given record id's in their parent or source field
+     * 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.
      *
      * @param string $tableName
      * @param array $ids
      * @param array $fieldNames
      * @return array
+     * @throws \InvalidArgumentException
      */
     protected function fetchDependentElements(string $tableName, array $ids, array $fieldNames)
     {
+        $ids = $this->filterNumericIds($ids, true);
+
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable($tableName);
         $queryBuilder->getRestrictions()
@@ -688,24 +718,21 @@ class DataMapProcessor
         $ids = array_filter($ids, [MathUtility::class, 'canBeInterpretedAsInteger']);
         $idsParameter = $queryBuilder->createNamedParameter($ids, Connection::PARAM_INT_ARRAY);
 
-        $predicates = [
-            $queryBuilder->expr()->in(
-                $fieldNames['parent'],
-                $idsParameter
-            )
-        ];
-
-        if (!empty($fieldNames['source'])) {
-            $predicates[] = $queryBuilder->expr()->in(
-                $fieldNames['source'],
-                $idsParameter
-            );
-        }
-
-        $statement = $queryBuilder
-            ->select(...array_values($fieldNames))
-            ->from($tableName)
-            ->andWhere(
+        // fetch by language dependency
+        if (!empty($fieldNames['language']) && !empty($fieldNames['parent'])) {
+            $ancestorPredicates = [
+                $queryBuilder->expr()->in(
+                    $fieldNames['parent'],
+                    $idsParameter
+                )
+            ];
+            if (!empty($fieldNames['source'])) {
+                $ancestorPredicates[] = $queryBuilder->expr()->in(
+                    $fieldNames['source'],
+                    $idsParameter
+                );
+            }
+            $predicates = [
                 // must be any kind of localization
                 $queryBuilder->expr()->gt(
                     $fieldNames['language'],
@@ -717,8 +744,28 @@ class DataMapProcessor
                     $zeroParameter
                 ),
                 // any parent or source pointers
-                $queryBuilder->expr()->orX(...$predicates)
-            )
+                $queryBuilder->expr()->orX(...$ancestorPredicates),
+            ];
+        // fetch by origin dependency ("copied from")
+        } elseif (!empty($fieldNames['origin'])) {
+            $predicates = [
+                $queryBuilder->expr()->eq(
+                    $fieldNames['origin'],
+                    $idsParameter
+                )
+            ];
+        // otherwise: stop execution
+        } else {
+            throw new \InvalidArgumentException(
+                'Invalid combination of query field names given',
+                1487192370
+            );
+        }
+
+        $statement = $queryBuilder
+            ->select(...array_values($fieldNames))
+            ->from($tableName)
+            ->andWhere(...$predicates)
             ->execute();
 
         $dependentElements = [];
@@ -790,6 +837,68 @@ class DataMapProcessor
     }
 
     /**
+     * Duplicates an item from data-map and prefixed language title,
+     * if applicable for the accordant field name.
+     *
+     * @param string $tableName
+     * @param string|int $id
+     * @param int $language
+     * @param array $fieldNames
+     * @return array
+     */
+    protected function duplicateFromDataMap(string $tableName, $id, int $language, array $fieldNames)
+    {
+        $data = $this->dataMap[$tableName][$id];
+        $isTranslatable = (!empty($fieldNames['language']) && !empty($fieldNames['parent']));
+
+        if (empty($language) || !$isTranslatable) {
+            return $data;
+        }
+
+        $data[$fieldNames['language']] = $language;
+        // @todo Only $id used in TCA type 'select' is resolved in DataHandler's remapStack
+        $data[$fieldNames['parent']] = $id;
+        if (!empty($fieldNames['source'])) {
+            // @todo Not sure, whether $id is resolved in DataHandler's remapStack
+            $data[$fieldNames['source']] = $id;
+        }
+
+        $prefixFieldNames = array_intersect(
+            array_keys($data),
+            $this->getPrefixLanguageTitleFieldNames($tableName)
+        );
+        if (empty($prefixFieldNames)) {
+            return $data;
+        }
+
+        $languageService = $this->getLanguageService();
+        $languageRecord = BackendUtility::getRecord('sys_language', $language, 'title');
+        list($pageId) = BackendUtility::getTSCpid($tableName, $id, $data['pid'] ?? null);
+
+        $TSconfig =  $this->backendUser->getTSConfig(
+            'TCEMAIN',
+            BackendUtility::getPagesTSconfig($pageId)
+        );
+        if (!empty($TSconfig['translateToMessage'])) {
+            $prefix = $TSconfig['translateToMessage'];
+            if ($languageService !== null) {
+                $prefix = $languageService->sL($prefix);
+            }
+            $prefix = sprintf($prefix, $languageRecord['title']);
+        }
+        if (empty($prefix)) {
+            $prefix = 'Translate to ' . $languageRecord['title'] . ':';
+        }
+
+        foreach ($prefixFieldNames as $prefixFieldName) {
+            // @todo The hook in DataHandler is not applied here
+            $data[$prefixFieldName] = '[' . $prefix . '] ' . $data[$prefixFieldName];
+        }
+
+        return $data;
+    }
+
+    /**
      * Field names we have to deal with
      *
      * @param DataMapItem $item
@@ -842,6 +951,36 @@ class DataMapProcessor
     }
 
     /**
+     * Field names of TCA table with columns having l10n_mode=prefixLangTitle
+     *
+     * @param string $tableName
+     * @return array
+     */
+    protected function getPrefixLanguageTitleFieldNames(string $tableName)
+    {
+        if ($tableName === 'pages') {
+            $tableName = 'pages_language_overlay';
+        }
+
+        $prefixLanguageTitleFieldNames = [];
+        if (empty($GLOBALS['TCA'][$tableName]['columns'])) {
+            return $prefixLanguageTitleFieldNames;
+        }
+
+        foreach ($GLOBALS['TCA'][$tableName]['columns'] as $fieldName => $configuration) {
+            $type = $configuration['config']['type'] ?? null;
+            if (
+                ($configuration['l10n_mode'] ?? null) === 'prefixLangTitle'
+                && ($type === 'input' || $type === 'text')
+            ) {
+                $prefixLanguageTitleFieldNames[] = $fieldName;
+            }
+        }
+
+        return $prefixLanguageTitleFieldNames;
+    }
+
+    /**
      * True if we're dealing with a field that has foreign db relations
      *
      * @param string $tableName
@@ -917,4 +1056,12 @@ class DataMapProcessor
         $relationHandler->setWorkspaceId($this->backendUser->workspace);
         return $relationHandler;
     }
+
+    /**
+     * @return null|LanguageService
+     */
+    protected function getLanguageService()
+    {
+        return $GLOBALS['LANG'] ?? null;
+    }
 }
index 02255f6..fd4840c 100644 (file)
@@ -239,8 +239,7 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
         $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections();
         $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
             ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
-            // @todo Actually Hotel #2 should be prefixed as well
-            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1', 'Hotel #2'));
+            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1', '[Translate to Dansk:] Hotel #2'));
     }
 
     /**
index 4c3d1c0..f9ac899 100644 (file)
@@ -1,30 +1,30 @@
-"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"
+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,7"
 ,299,89,768,0,1,298,298,0,0,0,0,0,"[Translate to Dansk:] Regular Element #2","6,8"
-"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"
+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
 ,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,96,0,1,5,5,0,0,0,0,0,"[Translate to Dansk:] Hotel #1",9
-,7,89,32,0,0,0,0,0,0,0,0,0,"Hotel #2",""
-,8,89,16,0,1,7,0,0,0,0,0,0,"Hotel #2",""
-"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"
+,7,89,32,0,0,0,0,0,0,0,0,0,"Hotel #2",
+,8,89,16,0,1,7,0,0,0,0,0,0,"[Translate to Dansk:] Hotel #2",
+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
 ,9,89,48,0,1,8,8,0,0,0,0,0,"[Translate to Dansk:] Offer #1.1",14
-"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",
-,14,89,6,0,1,13,13,0,0,0,0,0,"[Translate to Dansk:] Price #1.1.1",
+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"
+,14,89,6,0,1,13,13,0,0,0,0,0,"[Translate to Dansk:] Price #1.1.1"
index 8252c7c..69c279e 100644 (file)
@@ -30,10 +30,12 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
     const VALUE_LanguageId = 1;
 
     const TABLE_Page = 'pages';
+    const TABLE_PageOverlay = 'pages_language_overlay';
     const TABLE_Content = 'tt_content';
     const TABLE_Hotel = 'tx_irretutorial_1nff_hotel';
     const TABLE_Offer = 'tx_irretutorial_1nff_offer';
 
+    const FIELD_PageHotel = 'tx_irretutorial_hotels';
     const FIELD_ContentHotel = 'tx_irretutorial_1nff_hotels';
     const FIELD_HotelOffer = 'offers';
 
@@ -429,4 +431,80 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
             [self::TABLE_Hotel => [4]]
         );
     }
+
+    public function localizePageWithLocalizationExclude()
+    {
+        $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+    }
+
+    public function localizePageAndAddHotelChildWithLocalizationExclude()
+    {
+        $GLOBALS['TCA'][self::TABLE_Page]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['l10n_mode'] = 'exclude';
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+        $this->actionService->modifyRecords(
+            self::VALUE_PageId,
+            [
+                self::TABLE_Page => ['uid' => self::VALUE_PageId, self::FIELD_PageHotel => '2,__nextUid'],
+                self::TABLE_Hotel => ['uid' => '__NEW', 'title' => 'Hotel #007'],
+            ]
+        );
+    }
+
+    public function localizePageWithLanguageSynchronization()
+    {
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+    }
+
+    public function localizePageAndAddHotelChildWithLanguageSynchronization()
+    {
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+        $this->actionService->modifyRecords(
+            self::VALUE_PageId,
+            [
+                self::TABLE_Page => ['uid' => self::VALUE_PageId, self::FIELD_PageHotel => '2,__nextUid'],
+                self::TABLE_Hotel => ['uid' => '__NEW', 'title' => 'Hotel #007'],
+            ]
+        );
+    }
+
+    public function localizePageAndAddMonoglotHotelChildWithLanguageSynchronization()
+    {
+        unset($GLOBALS['TCA'][self::TABLE_Hotel]['ctrl']['languageField']);
+        unset($GLOBALS['TCA'][self::TABLE_Hotel]['ctrl']['transOrigPointerField']);
+        unset($GLOBALS['TCA'][self::TABLE_Hotel]['ctrl']['transOrigDiffSourceField']);
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+        $this->actionService->modifyRecords(
+            self::VALUE_PageId,
+            [
+                self::TABLE_Page => ['uid' => self::VALUE_PageId, self::FIELD_PageHotel => '2,__nextUid'],
+                self::TABLE_Hotel => ['uid' => '__NEW', 'title' => 'Hotel #007'],
+            ]
+        );
+    }
+
+    public function localizeAndCopyPageWithLanguageSynchronization()
+    {
+        $GLOBALS['TCA'][self::TABLE_PageOverlay]['columns'][self::FIELD_PageHotel]['config']['behaviour']['allowLanguageSynchronization'] = true;
+        $localizedTableIds = $this->actionService->localizeRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_LanguageId);
+        $this->recordIds['localizedPageId'] = $localizedTableIds[self::TABLE_Page][self::VALUE_PageId];
+        $this->recordIds['localizedPageOverlayId'] = $localizedTableIds[self::TABLE_PageOverlay][self::VALUE_PageId];
+        $newTableIds = $this->actionService->copyRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_PageIdTarget);
+        $this->recordIds['newPageId'] = $newTableIds[self::TABLE_Page][self::VALUE_PageId];
+    }
 }
index ff28c1a..a8cde50 100644 (file)
@@ -240,8 +240,7 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
         $responseSections = $this->getFrontendResponse(self::VALUE_PageId, self::VALUE_LanguageId)->getResponseSections('Default', 'Extbase:list()');
         $this->assertThat($responseSections, $this->getRequestSectionStructureHasRecordConstraint()
             ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
-            // @todo Actually Hotel #2 should be prefixed as well
-            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1', 'Hotel #2'));
+            ->setTable(self::TABLE_Hotel)->setField('title')->setValues('[Translate to Dansk:] Hotel #1', '[Translate to Dansk:] Hotel #2'));
     }
 
     /**
@@ -517,4 +516,94 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
             ->setRecordIdentifier(self::TABLE_Content . ':' . self::VALUE_ContentIdLast)->setRecordField(self::FIELD_ContentHotel)
             ->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #2'));
     }
+
+    /**
+     * @test
+     * @see DataSet/localizePageWExclude.csv
+     */
+    public function localizePageWithLocalizationExclude()
+    {
+        parent::localizePageWithLocalizationExclude();
+        $this->assertAssertionDataSet('localizePageWExclude');
+
+        $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()
+    {
+        parent::localizePageAndAddHotelChildWithLocalizationExclude();
+        $this->assertAssertionDataSet('localizePageNAddHotelChildWExclude');
+
+        $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', 'Hotel #007'));
+    }
+
+    /**
+     * @test
+     * @see DataSet/localizePageWSynchronization.csv
+     */
+    public function localizePageWithLanguageSynchronization()
+    {
+        parent::localizePageWithLanguageSynchronization();
+        $this->assertAssertionDataSet('localizePageWSynchronization');
+
+        $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('[Translate to Dansk:] Hotel #0'));
+    }
+
+    /**
+     * @test
+     * @see DataSet/localizePageNAddHotelChildWSynchronization.csv
+     */
+    public function localizePageAndAddHotelChildWithLanguageSynchronization()
+    {
+        parent::localizePageAndAddHotelChildWithLanguageSynchronization();
+        $this->assertAssertionDataSet('localizePageNAddHotelChildWSynchronization');
+
+        $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('[Translate to Dansk:] Hotel #0', '[Translate to Dansk:] Hotel #007'));
+    }
+
+    /**
+     * @test
+     * @see DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv
+     */
+    public function localizePageAndAddMonoglotHotelChildWithLanguageSynchronization()
+    {
+        parent::localizePageAndAddMonoglotHotelChildWithLanguageSynchronization();
+        $this->assertAssertionDataSet('localizePageNAddMonoglotHotelChildWSynchronization');
+
+        $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', 'Hotel #007'));
+    }
+
+    /**
+     * @test
+     * @see DataSet/localizeNCopyPageWSynchronization.csv
+     */
+    public function localizeAndCopyPageWithLanguageSynchronization()
+    {
+        parent::localizeAndCopyPageWithLanguageSynchronization();
+        $this->assertAssertionDataSet('localizeNCopyPageWSynchronization');
+
+        $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('[Translate to Dansk:] Hotel #0'));
+    }
 }
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizeNCopyPageWSynchronization.csv
new file mode 100644 (file)
index 0000000..d7647fb
--- /dev/null
@@ -0,0 +1,56 @@
+pages
+,uid,pid,sorting,deleted,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,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,1
+,90,88,512,0,0,0,0,0,0,0,Target,0
+,91,90,256,0,89,0,0,0,0,0,Relations,1
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}"
+,2,91,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}"
+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
+,299,91,256,0,0,0,298,0,0,0,0,0,"Regular Element #2",1
+,300,91,128,0,0,0,297,0,0,0,0,0,"Regular Element #1",2
+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,512,0,0,0,0,0,0,0,0,0,"Hotel #0",89,pages,,0
+,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1280,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,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,0
+,7,91,1,0,0,0,2,0,0,0,0,0,"Hotel #0",91,pages,,0
+,8,91,1,0,1,7,6,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",2,pages_language_overlay,,0
+,9,90,1,0,1,7,7,0,0,0,0,0,"[Translate to Dansk:] Hotel #0",2,pages_language_overlay,,0
+,10,91,1,0,0,0,5,0,0,0,0,0,"Hotel #1",299,tt_content,,1
+,11,91,1,0,0,0,3,0,0,0,0,0,"Hotel #1",300,tt_content,,2
+,12,91,2,0,0,0,4,0,0,0,0,0,"Hotel #2",300,tt_content,,1
+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
+,9,91,1,0,0,0,8,0,0,0,0,0,"Offer #1.1",10,tx_irretutorial_1nff_hotel,,1
+,10,91,1,0,0,0,5,0,0,0,0,0,"Offer #1.1",11,tx_irretutorial_1nff_hotel,,3
+,11,91,2,0,0,0,6,0,0,0,0,0,"Offer #1.2",11,tx_irretutorial_1nff_hotel,,2
+,12,91,1,0,0,0,7,0,0,0,0,0,"Offer #2.1",12,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,
+,14,91,1,0,0,0,13,0,0,0,0,0,"Price #1.1.1",9,tx_irretutorial_1nff_offer,
+,15,91,1,0,0,0,7,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer,
+,16,91,2,0,0,0,8,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer,
+,17,91,3,0,0,0,9,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer,
+,18,91,1,0,0,0,10,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer,
+,19,91,2,0,0,0,11,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer,
+,20,91,1,0,0,0,12,0,0,0,0,0,"Price #2.1.1",12,tx_irretutorial_1nff_offer,
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWExclude.csv
new file mode 100644 (file)
index 0000000..376ecdc
--- /dev/null
@@ -0,0 +1,36 @@
+pages
+,uid,pid,sorting,deleted,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,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,2
+,90,88,512,0,0,0,0,0,0,0,Target,0
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] 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,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1280,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",1,pages_language_overlay,,0
+,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,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,
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddHotelChildWSynchronization.csv
new file mode 100644 (file)
index 0000000..065db28
--- /dev/null
@@ -0,0 +1,37 @@
+pages
+,uid,pid,sorting,deleted,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,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,2
+,90,88,512,0,0,0,0,0,0,0,Target,0
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}"
+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,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1792,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1536,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,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,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,"[Translate to Dansk:] Hotel #007",1,pages_language_overlay,,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,
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageNAddMonoglotHotelChildWSynchronization.csv
new file mode 100644 (file)
index 0000000..7c07fb3
--- /dev/null
@@ -0,0 +1,37 @@
+pages
+,uid,pid,sorting,deleted,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,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,2
+,90,88,512,0,0,0,0,0,0,0,Target,0
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",2,"{""tx_irretutorial_hotels"":""parent""}"
+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,1280,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1792,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1536,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",1,pages_language_overlay,,0
+,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",89,pages,,0
+,8,89,2,0,0,0,0,0,0,0,0,0,"Hotel #007",1,pages_language_overlay,,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,
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWExclude.csv
new file mode 100644 (file)
index 0000000..0fee9b8
--- /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_hotels
+,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,1
+,90,88,512,0,0,0,0,0,0,0,Target,0
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] 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,512,0,0,0,0,0,0,0,0,0,"Hotel #0",89,pages,,0
+,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1280,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",1,pages_language_overlay,,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,
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/Modify/DataSet/localizePageWSynchronization.csv
new file mode 100644 (file)
index 0000000..3ab8e50
--- /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_hotels
+,1,0,256,0,0,0,0,0,0,0,FunctionalTest,0
+,88,1,256,0,0,0,0,0,0,0,DataHandlerTest,0
+,89,88,256,0,0,0,0,0,0,0,Relations,1
+,90,88,512,0,0,0,0,0,0,0,Target,0
+pages_language_overlay
+,uid,pid,deleted,sys_language_uid,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,title,tx_irretutorial_hotels,l10n_state
+,1,89,0,1,0,0,0,0,"[Translate to Dansk:] Relations",1,"{""tx_irretutorial_hotels"":""parent""}"
+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,512,0,0,0,0,0,0,0,0,0,"Hotel #0",89,pages,,0
+,3,89,1024,0,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,1536,0,0,0,0,0,0,0,0,0,"Hotel #2",297,tt_content,,1
+,5,89,1280,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,"[Translate to Dansk:] Hotel #0",1,pages_language_overlay,,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 c1de5cb..37fe4ef 100644 (file)
@@ -11,7 +11,7 @@ tx_irretutorial_1nff_hotel
 ,5,89,1,0,0,0,0,0,0,0,0,0,"Hotel #1",298,tt_content,,1
 ,6,89,1,0,1,5,5,0,0,0,0,0,"[Translate to Dansk:] Hotel #1",299,tt_content,,1
 ,7,89,2,0,0,0,0,0,0,0,0,0,"Hotel #2",298,tt_content,,0
-,8,89,2,0,1,7,0,0,0,0,0,0,"Hotel #2",299,tt_content,,0
+,8,89,2,0,1,7,0,0,0,0,0,0,"[Translate to Dansk:] Hotel #2",299,tt_content,,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,512,0,0,0,0,0,0,0,0,0,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3