[BUGFIX] Avoid superfluous IRRE child record duplication 52/26552/4
authorAlexander Stehlik <alexander.stehlik@googlemail.com>
Mon, 23 Dec 2013 16:47:20 +0000 (17:47 +0100)
committerOliver Hader <oliver.hader@typo3.org>
Mon, 17 Mar 2014 19:48:24 +0000 (20:48 +0100)
If copying a page, all records on that page will be copied to
the accordant destination page. IRRE parent-child structures
are cloned along the way as well. However, if a table (that is
defined a IRRE child) is processed before the accordant parent
record, the parent itself will duplicate its children again.
This behaviour leads to superfluous duplicates and is wrong.

A check in DataHandler::copyRecord_procBasedOnFieldType() now
ensures that records are only copied once during the accordant
DataHander copy process.

Resolves: #44795
Releases: 6.2
Change-Id: Ia1e4129432f37c0dd6bfedb5fd69394e2c244d34
Reviewed-on: https://review.typo3.org/26552
Reviewed-by: Oliver Hader
Tested-by: Oliver Hader
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/AbstractActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv [new file with mode: 0644]
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/AbstractActionTestCase.php
typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv [new file with mode: 0644]

index 96c0d12..7db57c7 100644 (file)
@@ -3395,7 +3395,13 @@ class DataHandler {
                                                                $newId = $workspaceVersion['uid'];
                                                        }
                                                } else {
-                                                       $newId = $this->copyRecord_raw($v['table'], $v['id'], $realDestPid, array(), $workspaceOptions);
+                                                       // If a record has been copied already during this request,
+                                                       // prevent superfluous duplication and use the existing copy
+                                                       if (isset($this->copyMappingArray[$v['table']][$v['id']])) {
+                                                               $newId = $this->copyMappingArray[$v['table']][$v['id']];
+                                                       } else {
+                                                               $newId = $this->copyRecord_raw($v['table'], $v['id'], $realDestPid, array(), $workspaceOptions);
+                                                       }
                                                }
                                        }
                                        // If the current field is set on a page record, update the pid of related child records:
index 1ee0805..5c3c882 100644 (file)
@@ -237,6 +237,25 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
        }
 
        /**
+        * @test
+        * @see DataSet/Assertion/copyPageRecord.csv
+        */
+       public function copyPageWithHotelBeforeParentContent() {
+               // Ensure hotels get processed first
+               $GLOBALS['TCA'] = array_merge(
+                       array(self::TABLE_Hotel => $GLOBALS['TCA'][self::TABLE_Hotel]),
+                       $GLOBALS['TCA']
+               );
+
+               $newTableIds = $this->actionService->copyRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_PageIdTarget);
+               $this->assertAssertionDataSet('copyPageWHotelBeforeParentContent');
+
+               $newPageId = $newTableIds[self::TABLE_Page][self::VALUE_PageId];
+               $responseContent = $this->getFrontendResponse($newPageId)->getResponseContent();
+               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+       }
+
+       /**
         * IRRE Child Records
         */
 
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/CSV/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv
new file mode 100644 (file)
index 0000000..8d588b9
--- /dev/null
@@ -0,0 +1,47 @@
+pages
+,uid,pid,sorting,deleted,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title
+,1,0,256,0,0,0,0,0,0,FunctionalTest
+,88,1,256,0,0,0,0,0,0,DataHandlerTest
+,89,88,256,0,0,0,0,0,0,Relations
+,90,88,512,0,0,0,0,0,0,Target
+,91,90,256,0,0,0,0,0,0,Relations
+tt_content
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,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,"Regular Element #1","3,4"
+,298,89,512,0,0,0,0,0,0,0,0,"Regular Element #2",5
+,299,91,256,0,0,0,0,0,0,0,0,"Regular Element #2",8
+,300,91,128,0,0,0,0,0,0,0,0,"Regular Element #1","6,7"
+tx_irretutorial_1ncsv_hotel
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,offers
+,3,89,256,0,0,0,0,0,0,0,0,"Hotel #1","5,6"
+,4,89,128,0,0,0,0,0,0,0,0,"Hotel #2",7
+,5,89,64,0,0,0,0,0,0,0,0,"Hotel #1",8
+,6,91,256,0,0,0,0,0,0,0,0,"Hotel #1","9,10"
+,7,91,128,0,0,0,0,0,0,0,0,"Hotel #2",11
+,8,91,64,0,0,0,0,0,0,0,0,"Hotel #1",12
+tx_irretutorial_1ncsv_offer
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,prices
+,5,89,256,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,"Offer #1.2","10,11"
+,7,89,64,0,0,0,0,0,0,0,0,"Offer #2.1",12
+,8,89,32,0,0,0,0,0,0,0,0,"Offer #1.1",13
+,9,91,256,0,0,0,0,0,0,0,0,"Offer #1.1","14,15,16"
+,10,91,128,0,0,0,0,0,0,0,0,"Offer #1.2","17,18"
+,11,91,64,0,0,0,0,0,0,0,0,"Offer #2.1",19
+,12,91,32,0,0,0,0,0,0,0,0,"Offer #1.1",20
+tx_irretutorial_1ncsv_price
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title
+,7,89,256,0,0,0,0,0,0,0,0,"Price #1.1.1"
+,8,89,128,0,0,0,0,0,0,0,0,"Price #1.1.2"
+,9,89,64,0,0,0,0,0,0,0,0,"Price #1.1.3"
+,10,89,32,0,0,0,0,0,0,0,0,"Price #1.2.1"
+,11,89,16,0,0,0,0,0,0,0,0,"Price #1.2.2"
+,12,89,8,0,0,0,0,0,0,0,0,"Price #2.1.1"
+,13,89,4,0,0,0,0,0,0,0,0,"Price #1.1.1"
+,14,91,256,0,0,0,0,0,0,0,0,"Price #1.1.1"
+,15,91,128,0,0,0,0,0,0,0,0,"Price #1.1.2"
+,16,91,64,0,0,0,0,0,0,0,0,"Price #1.1.3"
+,17,91,32,0,0,0,0,0,0,0,0,"Price #1.2.1"
+,18,91,16,0,0,0,0,0,0,0,0,"Price #1.2.2"
+,19,91,8,0,0,0,0,0,0,0,0,"Price #2.1.1"
+,20,91,4,0,0,0,0,0,0,0,0,"Price #1.1.1"
index 148c7c6..bcb4ebb 100644 (file)
@@ -237,6 +237,25 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
        }
 
        /**
+        * @test
+        * @see DataSet/Assertion/copyPageRecord.csv
+        */
+       public function copyPageWithHotelBeforeParentContent() {
+               // Ensure hotels get processed first
+               $GLOBALS['TCA'] = array_merge(
+                       array(self::TABLE_Hotel => $GLOBALS['TCA'][self::TABLE_Hotel]),
+                       $GLOBALS['TCA']
+               );
+
+               $newTableIds = $this->actionService->copyRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_PageIdTarget);
+               $this->assertAssertionDataSet('copyPageWHotelBeforeParentContent');
+
+               $newPageId = $newTableIds[self::TABLE_Page][self::VALUE_PageId];
+               $responseContent = $this->getFrontendResponse($newPageId)->getResponseContent();
+               $this->assertResponseContentHasRecords($responseContent, self::TABLE_Hotel, 'title', array('Hotel #1', 'Hotel #2', 'Hotel #1'));
+       }
+
+       /**
         * IRRE Child Records
         */
 
diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv b/typo3/sysext/core/Tests/Functional/DataHandling/IRRE/ForeignField/DataSet/Assertion/copyPageWHotelBeforeParentContent.csv
new file mode 100644 (file)
index 0000000..cebc6c5
--- /dev/null
@@ -0,0 +1,47 @@
+pages
+,uid,pid,sorting,deleted,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title
+,1,0,256,0,0,0,0,0,0,FunctionalTest
+,88,1,256,0,0,0,0,0,0,DataHandlerTest
+,89,88,256,0,0,0,0,0,0,Relations
+,90,88,512,0,0,0,0,0,0,Target
+,91,90,256,0,0,0,0,0,0,Relations
+tt_content
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,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,"Regular Element #1",2
+,298,89,512,0,0,0,0,0,0,0,0,"Regular Element #2",1
+,299,91,256,0,0,0,0,0,0,0,0,"Regular Element #2",1
+,300,91,128,0,0,0,0,0,0,0,0,"Regular Element #1",2
+tx_irretutorial_1nff_hotel
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,t3ver_wsid,t3ver_state,t3ver_stage,t3ver_oid,t3ver_move_id,title,parentid,parenttable,parentidentifier,offers
+,3,89,1,0,0,0,0,0,0,0,0,"Hotel #1",297,tt_content,,2
+,4,89,2,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,"Hotel #1",298,tt_content,,1
+,6,91,2,0,0,0,0,0,0,0,0,"Hotel #2",300,tt_content,,1
+,7,91,1,0,0,0,0,0,0,0,0,"Hotel #1",300,tt_content,,2
+,8,91,1,0,0,0,0,0,0,0,0,"Hotel #1",299,tt_content,,1
+tx_irretutorial_1nff_offer
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,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,"Offer #1.1",3,tx_irretutorial_1nff_hotel,,3
+,6,89,2,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,"Offer #2.1",4,tx_irretutorial_1nff_hotel,,1
+,8,89,1,0,0,0,0,0,0,0,0,"Offer #1.1",5,tx_irretutorial_1nff_hotel,,1
+,9,91,1,0,0,0,0,0,0,0,0,"Offer #2.1",6,tx_irretutorial_1nff_hotel,,1
+,10,91,1,0,0,0,0,0,0,0,0,"Offer #1.1",7,tx_irretutorial_1nff_hotel,,3
+,11,91,2,0,0,0,0,0,0,0,0,"Offer #1.2",7,tx_irretutorial_1nff_hotel,,2
+,12,91,1,0,0,0,0,0,0,0,0,"Offer #1.1",8,tx_irretutorial_1nff_hotel,,1
+tx_irretutorial_1nff_price
+,uid,pid,sorting,deleted,sys_language_uid,l18n_parent,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,"Price #1.1.1",5,tx_irretutorial_1nff_offer,
+,8,89,2,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,"Price #1.1.3",5,tx_irretutorial_1nff_offer,
+,10,89,1,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,"Price #1.2.2",6,tx_irretutorial_1nff_offer,
+,12,89,1,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,"Price #1.1.1",8,tx_irretutorial_1nff_offer,
+,14,91,1,0,0,0,0,0,0,0,0,"Price #2.1.1",9,tx_irretutorial_1nff_offer,
+,15,91,1,0,0,0,0,0,0,0,0,"Price #1.1.1",10,tx_irretutorial_1nff_offer,
+,16,91,2,0,0,0,0,0,0,0,0,"Price #1.1.2",10,tx_irretutorial_1nff_offer,
+,17,91,3,0,0,0,0,0,0,0,0,"Price #1.1.3",10,tx_irretutorial_1nff_offer,
+,18,91,1,0,0,0,0,0,0,0,0,"Price #1.2.1",11,tx_irretutorial_1nff_offer,
+,19,91,2,0,0,0,0,0,0,0,0,"Price #1.2.2",11,tx_irretutorial_1nff_offer,
+,20,91,1,0,0,0,0,0,0,0,0,"Price #1.1.1",12,tx_irretutorial_1nff_offer,