[BUGFIX] Copying workspace version record fails 71/53371/3
authorOliver Hader <oliver@typo3.org>
Thu, 29 Jun 2017 16:16:27 +0000 (18:16 +0200)
committerOliver Hader <oliver.hader@typo3.org>
Fri, 30 Jun 2017 18:03:15 +0000 (20:03 +0200)
Copying workspace version records fails in Doctrine DBAL exception due to
using computed properties directly in the database - which do not exist.
This misbehavior has been introduced in issue #79515 which switched to
use BackendUtility:workspaceOL() without further sanitization.

Resolves: #81747
Releases: master, 8.7
Change-Id: Iabc67f9a7375d4246289e50205aac6dc8c750259
Reviewed-on: https://review.typo3.org/53357
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-on: https://review.typo3.org/53371

typo3/sysext/backend/Classes/Utility/BackendUtility.php
typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php
typo3/sysext/core/Classes/DataHandling/DataHandler.php

index 0e5359d..0e39b6c 100644 (file)
@@ -295,6 +295,39 @@ class BackendUtility
     }
 
     /**
+     * Purges computed properties starting with underscore character ('_').
+     *
+     * @param array $record
+     * @return array
+     */
+    public static function purgeComputedPropertiesFromRecord(array $record): array
+    {
+        return array_filter(
+            $record,
+            function (string $propertyName): bool {
+                return $propertyName[0] !== '_';
+            },
+            ARRAY_FILTER_USE_KEY
+        );
+    }
+
+    /**
+     * Purges computed property names starting with underscore character ('_').
+     *
+     * @param array $propertyNames
+     * @return array
+     */
+    public static function purgeComputedPropertyNames(array $propertyNames): array
+    {
+        return array_filter(
+            $propertyNames,
+            function (string $propertyName): bool {
+                return $propertyName[0] !== '_';
+            }
+        );
+    }
+
+    /**
      * Makes an backwards explode on the $str and returns an array with ($table, $uid).
      * Example: tt_content_45 => array('tt_content', 45)
      *
@@ -4502,7 +4535,12 @@ class BackendUtility
                 $orig_pid = $row['pid'];
                 $movePldSwap = self::movePlhOL($table, $row);
             }
-            $wsAlt = self::getWorkspaceVersionOfRecord($wsid, $table, $row['uid'], implode(',', array_keys($row)));
+            $wsAlt = self::getWorkspaceVersionOfRecord(
+                $wsid,
+                $table,
+                $row['uid'],
+                implode(',', static::purgeComputedPropertyNames(array_keys($row)))
+            );
             // If version was found, swap the default record with that one.
             if (is_array($wsAlt)) {
                 // Check if this is in move-state:
@@ -4570,7 +4608,11 @@ class BackendUtility
             }
             // Find pointed-to record.
             if ($versionState->equals(VersionState::MOVE_PLACEHOLDER) && $moveID) {
-                if ($origRow = self::getRecord($table, $moveID, implode(',', array_keys($row)))) {
+                if ($origRow = self::getRecord(
+                    $table,
+                    $moveID,
+                    implode(',', static::purgeComputedPropertyNames(array_keys($row)))
+                )) {
                     $row = $origRow;
                     return true;
                 }
index cadd2d0..0fc46f9 100644 (file)
@@ -1205,4 +1205,36 @@ class BackendUtilityTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
         $return = BackendUtility::getTCAtypes($table, $rec, $useFieldNameAsKey);
         $this->assertSame($expected, $return);
     }
+
+    /**
+     * @test
+     */
+    public function purgeComputedPropertyNamesRemovesPropertiesStartingWithUnderscore()
+    {
+        $propertyNames = [
+            'uid',
+            'pid',
+            '_ORIG_PID'
+        ];
+        $computedPropertyNames = BackendUtility::purgeComputedPropertyNames($propertyNames);
+        self::assertSame(['uid', 'pid'], $computedPropertyNames);
+    }
+
+    /**
+     * @test
+     */
+    public function purgeComputedPropertiesFromRecordRemovesPropertiesStartingWithUnderscore()
+    {
+        $record = [
+            'uid'       => 1,
+            'pid'       => 2,
+            '_ORIG_PID' => 1
+        ];
+        $expected = [
+            'uid' => 1,
+            'pid' => 2
+        ];
+        $computedProperties = BackendUtility::purgeComputedPropertiesFromRecord($record);
+        self::assertSame($expected, $computedProperties);
+    }
 }
index 019c913..619135e 100644 (file)
@@ -3416,6 +3416,7 @@ class DataHandler
         $data = [];
         $nonFields = array_unique(GeneralUtility::trimExplode(',', 'uid,perms_userid,perms_groupid,perms_user,perms_group,perms_everybody,t3ver_oid,t3ver_wsid,t3ver_id,t3ver_label,t3ver_state,t3ver_count,t3ver_stage,t3ver_tstamp,' . $excludeFields, true));
         BackendUtility::workspaceOL($table, $row, -99, false);
+        $row = BackendUtility::purgeComputedPropertiesFromRecord($row);
 
         // Initializing:
         $theNewID = StringUtility::getUniqueId('NEW');