From 691545ddd1806ad730ffda4c6b0ff97dcec66773 Mon Sep 17 00:00:00 2001 From: Christian Kuhn <lolli@schwarzbu.ch> Date: Mon, 25 Apr 2016 17:37:12 +0200 Subject: [PATCH] [BUGFIX] Respect page TSConfig pid overrides for new inline children TCAdefaults.<table>.pid = <page id> in page TSConfig can be used for new inline children to define a pid new records should be located at, even if the parent record is on a different page. This can be useful when having special storage folders on a per-table-basis. The patch fixes this feature that broke during FormEngine refactoring. Change-Id: I8e60155612397e72f1b11a068617f88e3793384b Resolves: #70780 Releases: master, 7.6 Reviewed-on: https://review.typo3.org/47903 Reviewed-by: Susanne Moog <typo3@susannemoog.de> Tested-by: Susanne Moog <typo3@susannemoog.de> Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl> Tested-by: Wouter Wolters <typo3@wouterwolters.nl> Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch> Tested-by: Christian Kuhn <lolli@schwarzbu.ch> --- .../DatabaseRowInitializeNew.php | 39 ++++++-- .../DatabaseRowInitializeNewTest.php | 90 +++++++++++++++++-- 2 files changed, 117 insertions(+), 12 deletions(-) diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRowInitializeNew.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRowInitializeNew.php index 348629f863cb..6e8c7e2ccffa 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRowInitializeNew.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRowInitializeNew.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Backend\Form\FormDataProvider; use TYPO3\CMS\Backend\Form\FormDataProviderInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Core\Utility\MathUtility; /** * On "new" command, initialize new database row with default data @@ -47,11 +48,7 @@ class DatabaseRowInitializeNew implements FormDataProviderInterface $result = $this->setDefaultsFromNeighborRow($result); $result = $this->setDefaultsFromDevVals($result); $result = $this->setDefaultsFromInlineRelations($result); - - // Set pid to vanillaUid. This means, it *can* be negative, if the record is added relative to another record - // @todo: For inline records it should be possible to set the pid here via TCAdefaults, but - // @todo: those values would be overwritten by this 'pid' setter - $result['databaseRow']['pid'] = $result['vanillaUid']; + $result = $this->setPid($result); return $result; } @@ -194,4 +191,36 @@ class DatabaseRowInitializeNew implements FormDataProviderInterface return $result; } + + /** + * Set the pid. This is either the vanillaUid (see description in FormDataCompiler), + * or a pid given by pageTsConfig for inline children. + * + * @param array $result Result array + * @return array Modified result array + * @throws \UnexpectedValueException + */ + protected function setPid(array $result) + { + // Set pid to vanillaUid. This can be a negative value + // if the record is added relative to another record. + $result['databaseRow']['pid'] = $result['vanillaUid']; + + // In case a new inline record is created, the pid can be set to a different value + // by pageTsConfig, but not by userTsConfig. This overrides the above pid selection + // and forces the pid of new inline children. + $tableNameWithDot = $result['tableName'] . '.'; + if ($result['isInlineChild'] && isset($result['pageTsConfig']['TCAdefaults.'][$tableNameWithDot]['pid'])) { + if (!MathUtility::canBeInterpretedAsInteger($result['pageTsConfig']['TCAdefaults.'][$tableNameWithDot]['pid'])) { + throw new \UnexpectedValueException( + 'page TSConfig setting TCAdefaults.' . $tableNameWithDot . 'pid must be a number, but given string ' + . $result['pageTsConfig']['TCAdefaults.'][$tableNameWithDot]['pid'] . ' can not be interpreted as integer', + 1461598332 + ); + } + $result['databaseRow']['pid'] = (int)$result['pageTsConfig']['TCAdefaults.'][$tableNameWithDot]['pid']; + } + + return $result; + } } diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php index cf7f347d9155..5af0e0919af7 100644 --- a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php +++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php @@ -64,7 +64,8 @@ class DatabaseRowInitializeNewTest extends UnitTestCase 'command' => 'new', 'databaseRow' => 'not-an-array', ]; - $this->setExpectedException(\UnexpectedValueException::class, '', 1444431128); + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionCode(1444431128); $this->subject->addData($input); } @@ -89,7 +90,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormUserTsIfColumnIsDenfinedInTca() + public function addDataSetsDefaultDataFormUserTsIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -148,7 +149,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormPageTsIfColumnIsDenfinedInTca() + public function addDataSetsDefaultDataFormPageTsIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -350,7 +351,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormPostIfColumnIsDenfinedInTca() + public function addDataSetsDefaultDataFromPostIfColumnIsDenfinedInTca() { $input = [ 'command' => 'new', @@ -519,7 +520,8 @@ class DatabaseRowInitializeNewTest extends UnitTestCase 'databaseRow' => [], 'inlineChildChildUid' => 42, ]; - $this->setExpectedException(\UnexpectedValueException::class, '', 1444434102); + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionCode(1444434102); $this->subject->addData($input); } @@ -533,7 +535,8 @@ class DatabaseRowInitializeNewTest extends UnitTestCase 'databaseRow' => [], 'inlineChildChildUid' => '42', ]; - $this->setExpectedException(\UnexpectedValueException::class, '', 1444434103); + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionCode(1444434103); $this->subject->addData($input); } @@ -589,7 +592,8 @@ class DatabaseRowInitializeNewTest extends UnitTestCase ], ], ]; - $this->setExpectedException(\UnexpectedValueException::class, '', 1444434104); + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionCode(1444434104); $this->subject->addData($input); } @@ -608,4 +612,76 @@ class DatabaseRowInitializeNewTest extends UnitTestCase $result = $this->subject->addData($input); $this->assertSame($expected, $result['databaseRow']); } + + /** + * @test + */ + public function addDataDoesNotUsePageTsValueForPidIfRecordIsNotInlineChild() + { + $input = [ + 'command' => 'new', + 'tableName' => 'aTable', + 'vanillaUid' => 23, + 'databaseRow' => [], + 'pageTsConfig' => [ + 'TCAdefaults.' => [ + 'aTable.' => [ + 'pid' => '42', + ], + ], + ], + 'isInlineChild' => false, + ]; + $expected = $input; + $expected['databaseRow']['pid'] = 23; + $this->assertSame($expected, $this->subject->addData($input)); + } + + /** + * @test + */ + public function addDataThrowsExceptionIfPageTsConfigPidValueCanNotBeInterpretedAsInteger() + { + $input = [ + 'command' => 'new', + 'tableName' => 'aTable', + 'vanillaUid' => 23, + 'databaseRow' => [], + 'pageTsConfig' => [ + 'TCAdefaults.' => [ + 'aTable.' => [ + 'pid' => 'notAnInteger', + ], + ], + ], + 'isInlineChild' => true, + ]; + $this->expectException(\UnexpectedValueException::class); + $this->expectExceptionCode(1461598332); + $this->subject->addData($input); + } + + /** + * @test + */ + public function addDataDoesUsePageTsValueForPidIfRecordIsInlineChild() + { + $input = [ + 'command' => 'new', + 'tableName' => 'aTable', + 'vanillaUid' => 23, + 'databaseRow' => [], + 'pageTsConfig' => [ + 'TCAdefaults.' => [ + 'aTable.' => [ + 'pid' => '42', + ], + ], + ], + 'isInlineChild' => true, + ]; + $expected = $input; + $expected['databaseRow']['pid'] = 42; + $this->assertSame($expected, $this->subject->addData($input)); + } } -- GitLab