From 16cb944f43a72da9115023d24690a4becff4d440 Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Wed, 23 Sep 2020 17:01:11 +0200
Subject: [PATCH] [BUGFIX] Do not translate move pointers in workspace

When a moved content element in a workspace got copied
(or the whole page that the content element is put),
then the content element is added twice to the target
page.

This patch skips moved placeholders completely.

Resolves: #92388
Releases: master, 10.4
Change-Id: I8c1b4631627eef80b1740c77b63e541d36ab5f53
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/65838
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
---
 .../core/Classes/DataHandling/DataHandler.php | 11 +++++
 .../Regular/AbstractActionTestCase.php        |  3 +-
 .../changeContentSortingAndCopyDraftPage.csv  | 11 ++---
 .../Regular/Publish/ActionTest.php            | 13 +++++
 .../changeContentSortingAndCopyDraftPage.csv  | 48 +++++++++++++++++++
 .../changeContentSortingAndCopyDraftPage.csv  |  7 +--
 6 files changed, 79 insertions(+), 14 deletions(-)
 create mode 100644 typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv

diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index b4a871a13591..4d1872724fa4 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -3880,6 +3880,17 @@ class DataHandler implements LoggerAwareInterface
                 )
             );
 
+        // Never copy the actual move placeholders around, as the newly copied records are
+        // Always created as new record / new placeholder pairs
+        if (BackendUtility::isTableWorkspaceEnabled($table)) {
+            $queryBuilder->andWhere(
+                $queryBuilder->expr()->notIn(
+                    't3ver_state',
+                    [VersionState::MOVE_PLACEHOLDER, VersionState::DELETE_PLACEHOLDER]
+                )
+            );
+        }
+
         // If $destPid is < 0, get the pid of the record with uid equal to abs($destPid)
         $tscPID = BackendUtility::getTSconfig_pidValue($table, $uid, $destPid);
         // Get the localized records to be copied
diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php
index b3d82c34e213..35bd6a691d30 100644
--- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php
+++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/AbstractActionTestCase.php
@@ -237,7 +237,8 @@ abstract class AbstractActionTestCase extends \TYPO3\CMS\Core\Tests\Functional\D
      */
     public function changeContentSortingAndCopyDraftPage()
     {
-        $this->actionService->moveRecord(self::TABLE_Content, self::VALUE_ContentIdFirst, -self::VALUE_ContentIdSecond);
+        $newTableIds = $this->actionService->moveRecord(self::TABLE_Content, self::VALUE_ContentIdFirst, -self::VALUE_ContentIdSecond);
+        $this->recordIds['newContentId'] = $newTableIds[self::TABLE_Content][0];
         $newTableIds = $this->actionService->copyRecord(self::TABLE_Page, self::VALUE_PageId, self::VALUE_PageIdTarget);
         $this->recordIds['copiedPageId'] = $newTableIds[self::TABLE_Page][self::VALUE_PageId];
     }
diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/changeContentSortingAndCopyDraftPage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/changeContentSortingAndCopyDraftPage.csv
index 6b6deec37650..0dd6f93d8e46 100644
--- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/changeContentSortingAndCopyDraftPage.csv
+++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Modify/DataSet/changeContentSortingAndCopyDraftPage.csv
@@ -26,6 +26,7 @@
 ,325,89,448,0,2,321,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
 ,326,89,544,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]"
 ,327,91,256,0,0,0,0,299,1,1,0,0,0,"Regular Element #3"
+# @todo: Sorting is not correct here: should be Element 2 then Element 1 then Element 3
 ,328,91,256,0,0,0,0,299,1,-1,0,327,0,"Regular Element #3"
 ,329,91,128,0,1,327,327,300,1,1,0,0,0,"[Translate to Dansk:] Regular Element #3"
 ,330,91,128,0,1,327,327,300,1,-1,0,329,0,"[Translate to Dansk:] Regular Element #3"
@@ -35,12 +36,8 @@
 ,334,91,32,0,0,0,0,297,1,-1,0,333,0,"Regular Element #1"
 ,335,91,16,0,1,333,333,301,1,1,0,0,0,"[Translate to Dansk:] Regular Element #1"
 ,336,91,16,0,1,333,333,301,1,-1,0,335,0,"[Translate to Dansk:] Regular Element #1"
-,337,91,8,0,1,333,333,324,1,1,0,0,0,"[Translate to Dansk:] Regular Element #1"
-,338,91,8,0,1,333,333,324,1,-1,0,337,0,"[Translate to Dansk:] Regular Element #1"
-,339,91,4,0,2,333,335,302,1,1,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
-,340,91,4,0,2,333,335,302,1,-1,0,339,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
-,341,91,2,0,2,333,333,326,1,1,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
-,342,91,2,0,2,333,333,326,1,-1,0,341,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,337,91,8,0,2,333,335,302,1,1,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,338,91,8,0,2,333,335,302,1,-1,0,337,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
 "sys_refindex",,,,,,,,,,,,,,
 ,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,,
 ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,,
@@ -51,5 +48,3 @@
 ,"893ed65ba064539a74c6c86b2dd3a9ed","tt_content",330,"l18n_parent",0,0,1,"tt_content",327,,,,,
 ,"7d48ba6e36389495b8eb362a9f8f8d78","tt_content",336,"l18n_parent",0,0,1,"tt_content",333,,,,,
 ,"3f864e649c25f88940bd245f6895b5cf","tt_content",338,"l18n_parent",0,0,1,"tt_content",333,,,,,
-,"23f10bd36507a7b73454ccc0c18e2b51","tt_content",340,"l18n_parent",0,0,1,"tt_content",333,,,,,
-,"3c2f50596b3c6b13d5d36b22223357fd","tt_content",342,"l18n_parent",0,0,1,"tt_content",333,,,,,
diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php
index 29cf28f17e3d..b56a07cfe341 100644
--- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php
+++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/ActionTest.php
@@ -568,6 +568,19 @@ class ActionTest extends AbstractActionTestCase
             ->setTable(self::TABLE_Page)->setField('title')->setValues('Target', 'Testing #1', 'DataHandlerTest'));
     }
 
+    /**
+     * @test
+     * @group not-postgres
+     * @group not-mssql
+     * @todo Analyze PostgreSQL issues further, which is a generic issue
+     */
+    public function changeContentSortingAndCopyDraftPage()
+    {
+        parent::changeContentSortingAndCopyDraftPage();
+        $this->actionService->publishRecord(self::TABLE_Content, self::VALUE_ContentIdFirst);
+        $this->assertAssertionDataSet('changeContentSortingAndCopyDraftPage');
+    }
+
     /**
      * @test
      */
diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv
new file mode 100644
index 000000000000..5ffa7da31865
--- /dev/null
+++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/Publish/DataSet/changeContentSortingAndCopyDraftPage.csv
@@ -0,0 +1,48 @@
+"pages",,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","title",,,
+,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",,,
+,90,88,512,0,0,0,0,0,0,0,"Target",,,
+,91,90,256,0,89,1,1,0,0,0,"Relations",,,
+,92,90,256,0,89,1,-1,0,91,0,"Relations",,,
+"tt_content",,,,,,,,,,,,,,
+,"uid","pid","sorting","deleted","sys_language_uid","l18n_parent","l10n_source","t3_origuid","t3ver_wsid","t3ver_state","t3ver_stage","t3ver_oid","t3ver_move_id","header"
+,296,88,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #0"
+,297,89,640,0,0,0,0,297,0,0,0,0,0,"Regular Element #1"
+,298,89,512,0,0,0,0,0,0,0,0,0,0,"Regular Element #2"
+,299,89,768,0,0,0,0,0,0,0,0,0,0,"Regular Element #3"
+,300,89,1024,0,1,299,299,299,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3"
+,301,89,384,0,1,297,297,297,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1"
+,302,89,448,0,2,297,301,301,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,310,90,256,0,0,0,0,0,0,0,0,0,0,"Regular Element #10"
+,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10"
+,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10"
+,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2"
+,323,89,384,0,1,321,297,301,1,4,0,301,0,"[Translate to Dansk:] Regular Element #1"
+,324,89,576,0,1,297,0,0,1,3,0,0,301,"[MOVE-TO PLACEHOLDER for #301, WS#1]"
+,325,89,448,0,2,321,301,302,1,4,0,302,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,326,89,544,0,2,297,0,0,1,3,0,0,302,"[MOVE-TO PLACEHOLDER for #302, WS#1]"
+,327,91,256,0,0,0,0,299,1,1,0,0,0,"Regular Element #3"
+# @todo: Sorting is not correct here: should be Element 2 then Element 1 then Element 3
+,328,91,256,0,0,0,0,299,1,-1,0,327,0,"Regular Element #3"
+,329,91,128,0,1,327,327,300,1,1,0,0,0,"[Translate to Dansk:] Regular Element #3"
+,330,91,128,0,1,327,327,300,1,-1,0,329,0,"[Translate to Dansk:] Regular Element #3"
+,331,91,64,0,0,0,0,298,1,1,0,0,0,"Regular Element #2"
+,332,91,64,0,0,0,0,298,1,-1,0,331,0,"Regular Element #2"
+,333,91,32,0,0,0,0,297,1,1,0,0,0,"Regular Element #1"
+,334,91,32,0,0,0,0,297,1,-1,0,333,0,"Regular Element #1"
+,335,91,16,0,1,333,333,301,1,1,0,0,0,"[Translate to Dansk:] Regular Element #1"
+,336,91,16,0,1,333,333,301,1,-1,0,335,0,"[Translate to Dansk:] Regular Element #1"
+,337,91,8,0,2,333,335,302,1,1,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,338,91,8,0,2,333,335,302,1,-1,0,337,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+"sys_refindex",,,,,,,,,,,,,,
+,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,,
+,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,,
+,"01a3ce8c4e3b2bb1aa439dc29081f996","sys_workspace_stage",1,"responsible_persons",0,0,0,"be_users",3,,,,,
+,"1b70a8e25c22645f7a49a79f57f3cf3f","sys_category",31,"parent",0,0,0,"sys_category",28,,,,,
+,"cd92ab3ab5798dc139f98107e7c28cb7","tt_content",323,"l18n_parent",0,0,1,"tt_content",321,,,,,
+,"1c8013278ae997181374e3c76322e114","tt_content",325,"l18n_parent",0,0,1,"tt_content",321,,,,,
+,"893ed65ba064539a74c6c86b2dd3a9ed","tt_content",330,"l18n_parent",0,0,1,"tt_content",327,,,,,
+,"7d48ba6e36389495b8eb362a9f8f8d78","tt_content",336,"l18n_parent",0,0,1,"tt_content",333,,,,,
+,"3f864e649c25f88940bd245f6895b5cf","tt_content",338,"l18n_parent",0,0,1,"tt_content",333,,,,,
diff --git a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/changeContentSortingAndCopyDraftPage.csv b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/changeContentSortingAndCopyDraftPage.csv
index de2a1a93fcb4..07a002bf6c31 100644
--- a/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/changeContentSortingAndCopyDraftPage.csv
+++ b/typo3/sysext/workspaces/Tests/Functional/DataHandling/Regular/PublishAll/DataSet/changeContentSortingAndCopyDraftPage.csv
@@ -18,14 +18,13 @@
 ,311,90,512,0,1,0,310,310,0,0,0,0,0,"[Translate to Dansk:] Regular Element #10"
 ,312,90,768,0,2,0,311,311,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #10"
 ,320,89,512,0,0,0,0,298,2,2,0,298,0,"Regular Element #2"
+# @todo: Sorting is not correct here: should be Element 2 then Element 1 then Element 3
 ,327,91,256,0,0,0,0,299,0,0,0,0,0,"Regular Element #3"
 ,329,91,128,0,1,327,327,300,0,0,0,0,0,"[Translate to Dansk:] Regular Element #3"
 ,331,91,64,0,0,0,0,298,0,0,0,0,0,"Regular Element #2"
 ,333,91,32,0,0,0,0,297,0,0,0,0,0,"Regular Element #1"
 ,335,91,16,0,1,333,333,301,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1"
-,337,91,8,0,1,333,333,324,0,0,0,0,0,"[Translate to Dansk:] Regular Element #1"
-,339,91,4,0,2,333,335,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
-,341,91,2,0,2,333,333,326,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
+,337,91,8,0,2,333,335,302,0,0,0,0,0,"[Translate to Deutsch:] [Translate to Dansk:] Regular Element #1"
 "sys_refindex",,,,,,,,,,,,,,
 ,"hash","tablename","recuid","field","sorting","deleted","workspace","ref_table","ref_uid",,,,,
 ,"25426f92d44dd2ccf416108462b446e3","sys_workspace",1,"custom_stages",0,0,0,"sys_workspace_stage",1,,,,,
@@ -34,7 +33,5 @@
 ,"691bd3ea92e56cae98fbcd3320abab16","tt_content",329,"l18n_parent",0,0,0,"tt_content",327,,,,,
 ,"29336c6601631206b91ab727e3afd3ab","tt_content",335,"l18n_parent",0,0,0,"tt_content",333,,,,,
 ,"06ef094e3198da6562845ccf7264c617","tt_content",337,"l18n_parent",0,0,0,"tt_content",333,,,,,
-,"89e509472052635bae64551256ad2719","tt_content",339,"l18n_parent",0,0,0,"tt_content",333,,,,,
-,"2d556167d00accc4b89015a39314dc08","tt_content",341,"l18n_parent",0,0,0,"tt_content",333,,,,,
 ,"eb360eb09940bbb656509c7f6fda9b05","tt_content",301,"l18n_parent",0,0,0,"tt_content",297,,,,,
 ,"b6e55a3d99888c9a7007226ad685306c","tt_content",302,"l18n_parent",0,0,0,"tt_content",297,,,,,
-- 
GitLab