diff --git a/typo3/sysext/backend/Classes/Form/Container/PaletteAndSingleContainer.php b/typo3/sysext/backend/Classes/Form/Container/PaletteAndSingleContainer.php index 288c6733c81180a6bae76bb2734c522350c963bb..006c44f444a6e87c1d135ec0095586f2b6d86fbb 100644 --- a/typo3/sysext/backend/Classes/Form/Container/PaletteAndSingleContainer.php +++ b/typo3/sysext/backend/Classes/Form/Container/PaletteAndSingleContainer.php @@ -137,10 +137,14 @@ class PaletteAndSingleContainer extends AbstractContainer if (!empty($childResultArray['html'])) { $mainStructureCounter ++; + $fieldLabel = ''; + if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) { + $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label']; + } $targetStructure[$mainStructureCounter] = array( 'type' => 'single', 'fieldName' => $fieldConfiguration['fieldName'], - 'fieldLabel' => $this->getSingleFieldLabel($fieldName, $fieldConfiguration['fieldLabel']), + 'fieldLabel' => $fieldLabel, 'fieldHtml' => $childResultArray['html'], ); } @@ -212,10 +216,14 @@ class PaletteAndSingleContainer extends AbstractContainer if (!empty($singleFieldContentArray['html'])) { $foundRealElement = true; + $fieldLabel = ''; + if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) { + $fieldLabel = $this->data['processedTca']['columns'][$fieldName]['label']; + } $resultStructure[] = array( 'type' => 'single', 'fieldName' => $fieldName, - 'fieldLabel' => $this->getSingleFieldLabel($fieldName, $fieldArray['fieldLabel']), + 'fieldLabel' => $fieldLabel, 'fieldHtml' => $singleFieldContentArray['html'], ); $singleFieldContentArray['html'] = ''; @@ -375,41 +383,6 @@ class PaletteAndSingleContainer extends AbstractContainer return implode(LF, $content); } - /** - * Determine label of a single field (not a palette label) - * - * @param string $fieldName The field name to calculate the label for - * @param string $labelFromShowItem Given label, typically from show item configuration - * @return string Field label - */ - protected function getSingleFieldLabel($fieldName, $labelFromShowItem) - { - $languageService = $this->getLanguageService(); - $table = $this->data['tableName']; - $label = $labelFromShowItem; - if (!empty($this->data['processedTca']['columns'][$fieldName]['label'])) { - $label = $this->data['processedTca']['columns'][$fieldName]['label']; - } - if (!empty($labelFromShowItem)) { - $label = $labelFromShowItem; - } - - $fieldTSConfig = []; - if (isset($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']) - && is_array($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']) - ) { - $fieldTSConfig = $this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']; - } - - if (!empty($fieldTSConfig['label'])) { - $label = $fieldTSConfig['label']; - } - if (!empty($fieldTSConfig['label.'][$languageService->lang])) { - $label = $fieldTSConfig['label.'][$languageService->lang]; - } - return $languageService->sL($label); - } - /** * TRUE if field is of type user and to wrapping is requested * diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessFieldLabels.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessFieldLabels.php new file mode 100644 index 0000000000000000000000000000000000000000..dad824229299f82ec26042912533564880e4f061 --- /dev/null +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessFieldLabels.php @@ -0,0 +1,162 @@ +<?php +namespace TYPO3\CMS\Backend\Form\FormDataProvider; + +/* + * 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! + */ + +use TYPO3\CMS\Backend\Form\FormDataProviderInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Lang\LanguageService; + +/** + * Works on processedTca to determine the final value of field labels. + * + * processedTca['columns]['aField']['label'] + */ +class TcaColumnsProcessFieldLabels implements FormDataProviderInterface +{ + /** + * Iterate over all processedTca columns fields + * + * @param array $result Result array + * @return array Modified result array + */ + public function addData(array $result) + { + $result = $this->setLabelFromShowitemAndPalettes($result); + $result = $this->setLabelFromPageTsConfig($result); + $result = $this->translatelabels($result); + return $result; + } + + /** + * The label of a single field can be set in the showitem configuration + * of the record type and as palettes showitem as second ";" separated argument: + * + * processedTca['types']['aType']['showitem'] = 'aFieldName;aLabelOverride, --palette--;;aPaletteName' + * processedTca['palettes']['aPaletteName']['showitem'] = 'anotherFieldName;anotherLabelOverride' + * + * + * @param array $result Result array + * @return array Modified result array + */ + protected function setLabelFromShowitemAndPalettes(array $result) + { + $recordTypeValue = $result['recordTypeValue']; + // flex forms don't have a showitem / palettes configuration - early return + if (!isset($result['processedTca']['types'][$recordTypeValue]['showitem'])) { + return $result; + } + $showItemArray = GeneralUtility::trimExplode(',', $result['processedTca']['types'][$recordTypeValue]['showitem']); + foreach ($showItemArray as $aShowItemFieldString) { + $aShowItemFieldArray = GeneralUtility::trimExplode(';', $aShowItemFieldString); + $aShowItemFieldArray = [ + 'fieldName' => $aShowItemFieldArray[0], + 'fieldLabel' => $aShowItemFieldArray[1] ?: null, + 'paletteName' => $aShowItemFieldArray[2] ?: null, + ]; + if ($aShowItemFieldArray['fieldName'] === '--div--') { + // tabs are not of interest here + continue; + } elseif ($aShowItemFieldArray['fieldName'] === '--palette--') { + // showitem references to a palette field. unpack the palette and process + // label overrides that may be in there. + if (!isset($result['processedTca']['palettes'][$aShowItemFieldArray['paletteName']]['showitem'])) { + // No palette with this name found? Skip it. + continue; + } + $palettesArray = GeneralUtility::trimExplode( + ',', + $result['processedTca']['palettes'][$aShowItemFieldArray['paletteName']]['showitem'] + ); + foreach ($palettesArray as $aPalettesString) { + $aPalettesArray = GeneralUtility::trimExplode(';', $aPalettesString); + $aPalettesArray = [ + 'fieldName' => $aPalettesArray[0], + 'fieldLabel' => $aPalettesArray[1] ?: null, + ]; + if (!empty($aPalettesArray['fieldLabel']) + && isset($result['processedTca']['columns'][$aPalettesArray['fieldName']]) + ) { + $result['processedTca']['columns'][$aPalettesArray['fieldName']]['label'] = $aPalettesArray['fieldLabel']; + } + } + } else { + // If the field has a label in the showitem configuration of this record type, use it. + // showitem = 'aField, aFieldWithLabelOverride;theLabel, anotherField' + if (!empty($aShowItemFieldArray['fieldLabel']) + && isset($result['processedTca']['columns'][$aShowItemFieldArray['fieldName']]) + ) { + $result['processedTca']['columns'][$aShowItemFieldArray['fieldName']]['label'] = $aShowItemFieldArray['fieldLabel']; + } + } + } + return $result; + } + + /** + * pageTsConfig can override labels: + * + * TCEFORM.aTable.aField.label = 'override' + * TCEFORM.aTable.aField.label.en = 'override' + * + * @param array $result Result array + * @return array Modified result array + */ + protected function setLabelFromPageTsConfig(array $result) + { + $languageService = $this->getLanguageService(); + $table = $result['tableName']; + foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfiguration) { + $fieldTSConfig = []; + if (isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']) + && is_array($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']) + ) { + $fieldTSConfig = $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']; + } + if (!empty($fieldTSConfig['label'])) { + $result['processedTca']['columns'][$fieldName]['label'] = $fieldTSConfig['label']; + } + if (!empty($fieldTSConfig['label.'][$languageService->lang])) { + $result['processedTca']['columns'][$fieldName]['label'] = $fieldTSConfig['label.'][$languageService->lang]; + } + } + return $result; + } + + /** + * Translate all labels if needed. + * + * @param array $result Result array + * @return array Modified result array + */ + protected function translateLabels(array $result) + { + $languageService = $this->getLanguageService(); + foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfiguration) { + if (!isset($fieldConfiguration['label'])) { + continue; + } + $result['processedTca']['columns'][$fieldName]['label'] = $languageService->sL($fieldConfiguration['label']); + } + return $result; + } + + /** + * @return LanguageService + */ + protected function getLanguageService() + { + return $GLOBALS['LANG']; + } +} diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaTypesShowitem.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaTypesShowitem.php index c674c8e4078326502bef8ee77a1e76865ab1d10a..40d325e40a8a86c4e4ee5297b6fb037116900e00 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaTypesShowitem.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaTypesShowitem.php @@ -21,7 +21,7 @@ use TYPO3\CMS\Core\Utility\MathUtility; /** * Create final showitem configuration in processedTca for types and palette * fields - * Handles all the nasty defails like subtypes_addlist and friends. + * Handles all the nasty details like subtypes_addlist and friends. */ class TcaTypesShowitem implements FormDataProviderInterface { diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php index 5af0e0919af760e879540d8147e2e36b205bbf1b..597a42830402f128a82ddb9f61503aadc86f4014 100644 --- a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php +++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/DatabaseRowInitializeNewTest.php @@ -90,7 +90,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormUserTsIfColumnIsDefinedInTca() + public function addDataSetsDefaultDataFromUserTsIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -121,7 +121,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataDoesNotSetDefaultDataFormUserTsIfColumnIsMissingInTca() + public function addDataDoesNotSetDefaultDataFromUserTsIfColumnIsMissingInTca() { $input = [ 'command' => 'new', @@ -149,7 +149,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormPageTsIfColumnIsDefinedInTca() + public function addDataSetsDefaultDataFromPageTsIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -180,7 +180,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataDoesNotSetDefaultDataFormPageTsIfColumnIsMissingInTca() + public function addDataDoesNotSetDefaultDataFromPageTsIfColumnIsMissingInTca() { $input = [ 'command' => 'new', @@ -208,7 +208,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataOverrulingFormPageTs() + public function addDataSetsDefaultDataOverrulingFromPageTs() { $input = [ 'command' => 'new', @@ -320,7 +320,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFormGetIfColumnIsDenfinedInTca() + public function addDataSetsDefaultDataFromGetIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -351,7 +351,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataSetsDefaultDataFromPostIfColumnIsDenfinedInTca() + public function addDataSetsDefaultDataFromPostIfColumnIsDefinedInTca() { $input = [ 'command' => 'new', @@ -420,7 +420,7 @@ class DatabaseRowInitializeNewTest extends UnitTestCase /** * @test */ - public function addDataDoesNotSetDefaultDataFormGetPostIfColumnIsMissingInTca() + public function addDataDoesNotSetDefaultDataFromGetPostIfColumnIsMissingInTca() { $input = [ 'command' => 'new', diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaColumnsProcessFieldLabelsTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaColumnsProcessFieldLabelsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7e79cd0a11efa7577548d713050634d7ce1d7fce --- /dev/null +++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaColumnsProcessFieldLabelsTest.php @@ -0,0 +1,189 @@ +<?php +namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider; + +/* + * 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! + */ + +use TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsProcessFieldLabels; +use TYPO3\CMS\Core\Tests\UnitTestCase; +use TYPO3\CMS\Lang\LanguageService; + +/** + * Test case + */ +class TcaColumnsProcessFieldLabelsTest extends UnitTestCase +{ + /** + * @var TcaColumnsProcessFieldLabels + */ + protected $subject; + + protected function setUp() + { + $this->subject = new TcaColumnsProcessFieldLabels(); + } + + /** + * @test + */ + public function addDataKeepsLabelAsIsIfNoOverrideIsGiven() + { + $input = [ + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'label' => 'foo', + ], + ], + ], + ]; + $languageServiceProphecy = $this->prophesize(LanguageService::class); + $languageServiceProphecy->sL('foo')->shouldBeCalled()->willReturnArgument(0); + $GLOBALS['LANG'] = $languageServiceProphecy->reveal(); + + $expected = $input; + $this->assertSame($expected, $this->subject->addData($input)); + } + + /** + * @test + */ + public function addDataSetsLabelFromShowitem() + { + $input = [ + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'label' => 'origLabel', + ], + ], + 'types' => [ + 'aType' => [ + 'showitem' => 'aField;aLabelOverride', + ], + ], + ], + 'recordTypeValue' => 'aType', + ]; + $languageServiceProphecy = $this->prophesize(LanguageService::class); + $languageServiceProphecy->sL('aLabelOverride')->shouldBeCalled()->willReturnArgument(0); + $GLOBALS['LANG'] = $languageServiceProphecy->reveal(); + + $expected = $input; + $expected['processedTca']['columns']['aField']['label'] = 'aLabelOverride'; + $this->assertSame($expected, $this->subject->addData($input)); + } + + /** + * @test + */ + public function addDataSetsLabelFromPalettesShowitem() + { + $input = [ + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'label' => 'origLabel', + ], + ], + 'types' => [ + 'aType' => [ + 'showitem' => '--palette--;;aPalette', + ], + ], + 'palettes' => [ + 'aPalette' => [ + 'showitem' => 'aField;aLabelOverride', + ], + ], + ], + 'recordTypeValue' => 'aType', + ]; + $languageServiceProphecy = $this->prophesize(LanguageService::class); + $languageServiceProphecy->sL('aLabelOverride')->shouldBeCalled()->willReturnArgument(0); + $GLOBALS['LANG'] = $languageServiceProphecy->reveal(); + + $expected = $input; + $expected['processedTca']['columns']['aField']['label'] = 'aLabelOverride'; + $this->assertSame($expected, $this->subject->addData($input)); + } + + /** + * @test + */ + public function addDataSetsLabelFromPageTsConfig() + { + $input = [ + 'tableName' => 'aTable', + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'label' => 'origLabel', + ], + ], + ], + 'pageTsConfig' => [ + 'TCEFORM.' => [ + 'aTable.' => [ + 'aField.' => [ + 'label' => 'aLabelOverride', + ], + ], + ], + ], + ]; + $languageServiceProphecy = $this->prophesize(LanguageService::class); + $languageServiceProphecy->sL('aLabelOverride')->shouldBeCalled()->willReturnArgument(0); + $GLOBALS['LANG'] = $languageServiceProphecy->reveal(); + + $expected = $input; + $expected['processedTca']['columns']['aField']['label'] = 'aLabelOverride'; + $this->assertSame($expected, $this->subject->addData($input)); + } + + /** + * @test + */ + public function addDataSetsLabelFromPageTsConfigForSpecificLanguage() + { + $input = [ + 'tableName' => 'aTable', + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'label' => 'origLabel', + ], + ], + ], + 'pageTsConfig' => [ + 'TCEFORM.' => [ + 'aTable.' => [ + 'aField.' => [ + 'label.' => [ + 'fr' => 'aLabelOverride', + ], + ], + ], + ], + ], + ]; + $languageServiceProphecy = $this->prophesize(LanguageService::class); + $languageServiceProphecy->lang = 'fr'; + $languageServiceProphecy->sL('aLabelOverride')->shouldBeCalled()->willReturnArgument(0); + $GLOBALS['LANG'] = $languageServiceProphecy->reveal(); + + $expected = $input; + $expected['processedTca']['columns']['aField']['label'] = 'aLabelOverride'; + $this->assertSame($expected, $this->subject->addData($input)); + } +} diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php index 2fd8b997a2da12ea5ec6d60395d0bb2f25eb327d..e723eda17541ceee964b695585ca0555bd8a1eb6 100644 --- a/typo3/sysext/core/Configuration/DefaultConfiguration.php +++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php @@ -447,7 +447,12 @@ return array( \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRecordTypeValue::class, \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseSystemLanguageRows::class, \TYPO3\CMS\Backend\Form\FormDataProvider\InitializeProcessedTca::class, - \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsRemoveUnused::class + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsRemoveUnused::class, + ), + ), + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsProcessFieldLabels::class => array( + 'depends' => array( + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaTypesShowitem::class, ), ), \TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexFetch::class => array( @@ -456,6 +461,7 @@ return array( \TYPO3\CMS\Backend\Form\FormDataProvider\UserTsConfig::class, \TYPO3\CMS\Backend\Form\FormDataProvider\PageTsConfigMerged::class, \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsRemoveUnused::class, + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsProcessFieldLabels::class, ), ), \TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexPrepare::class => array( @@ -531,11 +537,16 @@ return array( ), 'flexFormSegment' => array( \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class => array(), - \TYPO3\CMS\Backend\Form\FormDataProvider\TcaGroup::class => array( + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsProcessFieldLabels::class => array( 'depends' => array( \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class, ), ), + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaGroup::class => array( + 'depends' => array( + \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsProcessFieldLabels::class, + ), + ), \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => array( 'depends' => array( \TYPO3\CMS\Backend\Form\FormDataProvider\DatabaseRowDefaultValues::class,