From dbe425f91a81a10eda4d0fd7d26dd7ea2cfb368c Mon Sep 17 00:00:00 2001 From: Oliver Hader <oliver@typo3.org> Date: Thu, 29 Jun 2017 18:16:27 +0200 Subject: [PATCH] [BUGFIX] Copying workspace version record fails 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> --- .../Classes/Utility/BackendUtility.php | 46 ++++++++++++++++++- .../Tests/Unit/Utility/BackendUtilityTest.php | 32 +++++++++++++ .../core/Classes/DataHandling/DataHandler.php | 1 + 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index 6914a61081ef..da685056c684 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -180,6 +180,39 @@ class BackendUtility return $row; } + /** + * 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) @@ -3910,7 +3943,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: @@ -3978,7 +4016,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; } diff --git a/typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php b/typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php index 9a6de40e2cd1..12a700f85160 100644 --- a/typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php +++ b/typo3/sysext/backend/Tests/Unit/Utility/BackendUtilityTest.php @@ -1176,4 +1176,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); + } } diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php index 1254355e748e..99f052587239 100644 --- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php +++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php @@ -3395,6 +3395,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'); -- GitLab