diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php index c52c28d78e7d5b5569881a6340e6cb263d74e702..113556477d6d8c69509bad7cc01408f53346d0d5 100644 --- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php +++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php @@ -755,6 +755,35 @@ class DataHandler implements LoggerAwareInterface } } + /** + * When a new record is created, all values that haven't been set but are set via PageTSconfig / UserTSconfig + * get applied here. + * + * This is only executed for new records. The most important part is that the pageTS of the actual resolved $pid + * is taken, and a new field array with empty defaults is set again. + * + * @param string $table + * @param int $pageId + * @param array $prepopulatedFieldArray + * @return array + */ + protected function applyDefaultsForFieldArray(string $table, int $pageId, array $prepopulatedFieldArray): array + { + // First set TCAdefaults respecting the given PageID + $tcaDefaults = BackendUtility::getPagesTSconfig($pageId)['TCAdefaults.'] ?? null; + // Re-apply $this->defaultValues settings + $this->setDefaultsFromUserTS($tcaDefaults); + $cleanFieldArray = $this->newFieldArray($table); + if (isset($prepopulatedFieldArray['pid'])) { + $cleanFieldArray['pid'] = $prepopulatedFieldArray['pid']; + } + $sortColumn = $GLOBALS['TCA'][$table]['ctrl']['sortby'] ?? null; + if ($sortColumn !== null && isset($prepopulatedFieldArray[$sortColumn])) { + $cleanFieldArray[$sortColumn] = $prepopulatedFieldArray[$sortColumn]; + } + return $cleanFieldArray; + } + /** * Dummy method formerly used for file handling. * @@ -1049,13 +1078,18 @@ class DataHandler implements LoggerAwareInterface // Here the "pid" is set IF NOT the old pid was a string pointing to a place in the subst-id array. [$tscPID] = BackendUtility::getTSCpid($table, $id, $old_pid_value ?: $fieldArray['pid']); - if ($status === 'new' && $table === 'pages') { - $fieldArray = $this->pagePermissionAssembler->applyDefaults( - $fieldArray, - (int)$tscPID, - (int)$this->userid, - (int)$this->BE_USER->firstMainGroup - ); + if ($status === 'new') { + // Apply TCAdefaults from pageTS + $fieldArray = $this->applyDefaultsForFieldArray($table, (int)$tscPID, $fieldArray); + // Apply page permissions as well + if ($table === 'pages') { + $fieldArray = $this->pagePermissionAssembler->applyDefaults( + $fieldArray, + (int)$tscPID, + (int)$this->userid, + (int)$this->BE_USER->firstMainGroup + ); + } } // Processing of all fields in incomingFieldArray and setting them in $fieldArray $fieldArray = $this->fillInFieldArray($table, $id, $fieldArray, $incomingFieldArray, $theRealPid, $status, $tscPID); diff --git a/typo3/sysext/core/Tests/Functional/DataHandling/DataHandler/DefaultValuesTest.php b/typo3/sysext/core/Tests/Functional/DataHandling/DataHandler/DefaultValuesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..698cc70afa95938b2c6e00428b43e2c0082f5129 --- /dev/null +++ b/typo3/sysext/core/Tests/Functional/DataHandling/DataHandler/DefaultValuesTest.php @@ -0,0 +1,147 @@ +<?php +declare(strict_types = 1); + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +namespace TYPO3\CMS\Core\Tests\Functional\DataHandling\DataHandler; + +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Tests\Functional\DataHandling\AbstractDataHandlerActionTestCase; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; + +/** + * Tests various places to set default values properly for new records + */ +class DefaultValuesTest extends AbstractDataHandlerActionTestCase +{ + /** + * @var int + */ + const PAGE_DATAHANDLER = 88; + + /** + * @var string + */ + protected $scenarioDataSetDirectory = 'typo3/sysext/core/Tests/Functional/DataHandling/DataHandler/DataSet/'; + + protected function setUp(): void + { + parent::setUp(); + $this->importScenarioDataSet('LiveDefaultPages'); + $this->importScenarioDataSet('LiveDefaultElements'); + $this->backendUser->workspace = 0; + } + + /** + * @test + */ + public function defaultValuesFromTCAForNewRecordsIsRespected(): void + { + $GLOBALS['TCA']['pages']['columns']['keywords']['config']['default'] = 'a few,random,keywords'; + $map = $this->actionService->createNewRecord('pages', self::PAGE_DATAHANDLER, [ + 'title' => 'A new age' + ]); + $newPageId = reset($map['pages']); + $newPageRecord = BackendUtility::getRecord('pages', $newPageId); + self::assertEquals($newPageRecord['keywords'], $GLOBALS['TCA']['pages']['columns']['keywords']['config']['default']); + + $GLOBALS['TCA']['tt_content']['columns']['header']['config']['default'] = 'Pre-set header'; + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'header' => '', + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + // Empty header is used, because it was handed in + self::assertEquals($newContentRecord['header'], ''); + + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + self::assertEquals($newContentRecord['header'], $GLOBALS['TCA']['tt_content']['columns']['header']['config']['default']); + } + + /** + * @test + */ + public function defaultValuesFromGlobalTSconfigForNewRecordsIsRespected(): void + { + ExtensionManagementUtility::addPageTSConfig(' +TCAdefaults.pages.keywords = from pagets, with love +TCAdefaults.tt_content.header = global space'); + $map = $this->actionService->createNewRecord('pages', self::PAGE_DATAHANDLER, [ + 'title' => 'A new age' + ]); + $newPageId = reset($map['pages']); + $newPageRecord = BackendUtility::getRecord('pages', $newPageId); + self::assertEquals($newPageRecord['keywords'], 'from pagets, with love'); + + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'header' => '', + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + // Empty header is used, because it was handed in + self::assertEquals($newContentRecord['header'], ''); + + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + self::assertEquals($newContentRecord['header'], 'global space'); + } + + /** + * @test + */ + public function defaultValuesFromPageSpecificTSconfigForNewRecordsIsRespected(): void + { + ExtensionManagementUtility::addPageTSConfig(' +TCAdefaults.pages.keywords = from pagets, with love +TCAdefaults.tt_content.header = global space'); + $this->actionService->modifyRecord('pages', self::PAGE_DATAHANDLER, [ + 'TSconfig' => ' + +TCAdefaults.pages.keywords = I am specific, not generic +TCAdefaults.tt_content.header = local space + +']); + $map = $this->actionService->createNewRecord('pages', self::PAGE_DATAHANDLER, [ + 'title' => 'A new age' + ]); + $newPageId = reset($map['pages']); + $newPageRecord = BackendUtility::getRecord('pages', $newPageId); + self::assertEquals($newPageRecord['keywords'], 'I am specific, not generic'); + + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'header' => '', + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + // Empty header is used, because it was handed in + self::assertEquals($newContentRecord['header'], ''); + + $map = $this->actionService->createNewRecord('tt_content', $newPageId, [ + 'bodytext' => 'Random bodytext' + ]); + $newContentId = reset($map['tt_content']); + $newContentRecord = BackendUtility::getRecord('tt_content', $newContentId); + self::assertEquals($newContentRecord['header'], 'local space'); + } +}