Commit 20715ad2 authored by Oliver Hader's avatar Oliver Hader Committed by Benni Mack
Browse files

[BUGFIX] Keep language reference for children using l10n_mode=exclude

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/59667


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent ac25cdc9
......@@ -3471,10 +3471,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;
......@@ -3666,7 +3668,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);
}
......
......@@ -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)
......
......@@ -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';
......
......@@ -421,6 +421,21 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\CSV\
->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #0'));
}
/**
* @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
......
......@@ -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"
......
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",
......@@ -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"
......
......@@ -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';
......
......@@ -504,6 +504,21 @@ class ActionTest extends \TYPO3\CMS\Core\Tests\Functional\DataHandling\IRRE\Fore
->setTable(self::TABLE_Hotel)->setField('title')->setValues('Hotel #0'));
}
/**
* @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
......
......@@ -13,12 +13,11 @@
,"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
......
"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",,
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment