From b62b6e312e42d5e4936fd8852620c1f2409fc78e Mon Sep 17 00:00:00 2001 From: Oliver Bartsch <bo@cedev.de> Date: Tue, 17 Aug 2021 21:35:13 +0200 Subject: [PATCH] [BUGFIX] Do not transform text when RTE is disabled The TcaText data provider transforms a given database field value with the RteHtmlParser as soon as `enableRichtext` is set for the field in TCA. This means, the data provider did previously not checked, whether RTE is disabled for the user in general or for this specific field by configuration (e.g. page TSconfig). This therefore led, among others, to "normal" text being falsely wrapped with `<p>` tags. This is now fixed by checking all relevant settings before actually transforming the database field value. Resolves: #94915 Releases: master, 10.4 Change-Id: I5af4e9997c28269be959ea9e63e12cfee5e991af Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/70674 Tested-by: core-ci <typo3@b13.com> Tested-by: Benni Mack <benni@typo3.org> Tested-by: Daniel Goerz <daniel.goerz@posteo.de> Tested-by: Oliver Bartsch <bo@cedev.de> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Daniel Goerz <daniel.goerz@posteo.de> Reviewed-by: Oliver Bartsch <bo@cedev.de> --- .../Classes/Form/FormDataProvider/TcaText.php | 31 +++-- .../Form/FormDataProvider/TcaTextTest.php | 125 +++++++++++++++++- .../BackendUserAuthentication.php | 4 +- 3 files changed, 145 insertions(+), 15 deletions(-) diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaText.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaText.php index bd38598f5df3..c296e339a9f9 100644 --- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaText.php +++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaText.php @@ -18,6 +18,7 @@ declare(strict_types=1); namespace TYPO3\CMS\Backend\Form\FormDataProvider; use TYPO3\CMS\Backend\Form\FormDataProviderInterface; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Configuration\Richtext; use TYPO3\CMS\Core\Html\RteHtmlParser; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -41,7 +42,8 @@ class TcaText implements FormDataProviderInterface continue; } - if (isset($fieldConfig['config']['enableRichtext']) && (bool)$fieldConfig['config']['enableRichtext'] === true) { + // Check if richtext is enabled for the field and the user did not disable RTE in general + if (($fieldConfig['config']['enableRichtext'] ?? false) && $this->getBackendUser()->isRTE()) { $richtextConfigurationProvider = GeneralUtility::makeInstance(Richtext::class); $richtextConfiguration = $richtextConfigurationProvider->getConfiguration( $result['tableName'], @@ -50,20 +52,27 @@ class TcaText implements FormDataProviderInterface (string)$result['recordTypeValue'], $fieldConfig['config'] ); - // remember RTE preset name - $result['processedTca']['columns'][$fieldName]['config']['richtextConfigurationName'] = $fieldConfig['config']['richtextConfiguration'] ?? ''; - // Add final resolved configuration to TCA array - $result['processedTca']['columns'][$fieldName]['config']['richtextConfiguration'] = $richtextConfiguration; - - // If eval=null is set for field, value might be null ... don't transform anything in this case. - if ($result['databaseRow'][$fieldName] !== null) { - // Process "from-db-to-rte" on current value - $richTextParser = GeneralUtility::makeInstance(RteHtmlParser::class); - $result['databaseRow'][$fieldName] = $richTextParser->transformTextForRichTextEditor($result['databaseRow'][$fieldName], $richtextConfiguration['proc.'] ?? []); + // Transform if richtext is not disabled in configuration + if (!($richtextConfiguration['disabled'] ?? false)) { + // remember RTE preset name + $result['processedTca']['columns'][$fieldName]['config']['richtextConfigurationName'] = $fieldConfig['config']['richtextConfiguration'] ?? ''; + // Add final resolved configuration to TCA array + $result['processedTca']['columns'][$fieldName]['config']['richtextConfiguration'] = $richtextConfiguration; + // If eval=null is set for field, value might be null ... don't transform anything in this case. + if ($result['databaseRow'][$fieldName] !== null) { + // Process "from-db-to-rte" on current value + $richTextParser = GeneralUtility::makeInstance(RteHtmlParser::class); + $result['databaseRow'][$fieldName] = $richTextParser->transformTextForRichTextEditor($result['databaseRow'][$fieldName], $richtextConfiguration['proc.'] ?? []); + } } } } return $result; } + + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } } diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaTextTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaTextTest.php index 73b55116e44b..1ae930ae7285 100644 --- a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaTextTest.php +++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaTextTest.php @@ -17,7 +17,9 @@ declare(strict_types=1); namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider; +use Prophecy\PhpUnit\ProphecyTrait; use TYPO3\CMS\Backend\Form\FormDataProvider\TcaText; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Configuration\Richtext; use TYPO3\CMS\Core\Html\RteHtmlParser; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -28,12 +30,17 @@ use TYPO3\TestingFramework\Core\Unit\UnitTestCase; */ class TcaTextTest extends UnitTestCase { - use \Prophecy\PhpUnit\ProphecyTrait; + use ProphecyTrait; + /** * @test */ - public function addDataSetsRichtextConfigurationAndTransformsContent() + public function addDataSetsRichtextConfigurationAndTransformsContent(): void { + $beUserProphecy = $this->prophesize(BackendUserAuthentication::class); + $beUserProphecy->isRTE()->willReturn(true); + $GLOBALS['BE_USER'] = $beUserProphecy->reveal(); + $input = [ 'tableName' => 'aTable', 'effectivePid' => 42, @@ -101,4 +108,118 @@ class TcaTextTest extends UnitTestCase self::assertSame($expected, (new TcaText())->addData($input)); } + + /** + * @test + */ + public function addDataDoesNotTransformsContentWhenRichtextIsNotSet(): void + { + $beUserProphecy = $this->prophesize(BackendUserAuthentication::class); + $beUserProphecy->isRTE()->willReturn(true); + $GLOBALS['BE_USER'] = $beUserProphecy->reveal(); + + $input = [ + 'tableName' => 'aTable', + 'effectivePid' => 42, + 'recordTypeValue' => 23, + 'databaseRow' => [ + 'aField' => 'notProcessedContent', + ], + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'config' => [ + 'type' => 'text', + ] + ], + ], + ], + ]; + + // No processing should be performed + $expected = $input; + self::assertSame($expected, (new TcaText())->addData($input)); + } + + /** + * @test + */ + public function addDataDoesNotTransformsContentWhenRichtextIsDisabledInConfiguration(): void + { + $beUserProphecy = $this->prophesize(BackendUserAuthentication::class); + $beUserProphecy->isRTE()->willReturn(true); + $GLOBALS['BE_USER'] = $beUserProphecy->reveal(); + + $input = [ + 'tableName' => 'aTable', + 'effectivePid' => 42, + 'recordTypeValue' => 23, + 'databaseRow' => [ + 'aField' => 'notProcessedContent', + ], + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'config' => [ + 'type' => 'text', + 'enableRichtext' => true, + ], + ], + ], + ], + ]; + + $richtextConfigurationProphecy = $this->prophesize(Richtext::class); + GeneralUtility::addInstance(Richtext::class, $richtextConfigurationProphecy->reveal()); + + $richtextConfigurationProphecy + ->getConfiguration( + 'aTable', + 'aField', + 42, + 23, + [ + 'type' => 'text', + 'enableRichtext' => true, + ] + ) + ->willReturn(['disabled' => '1']); + + // No processing should be performed + $expected = $input; + self::assertSame($expected, (new TcaText())->addData($input)); + } + + /** + * @test + */ + public function addDataDoesNotTransformsContentWhenRichtextIsDisabledForUser(): void + { + $beUserProphecy = $this->prophesize(BackendUserAuthentication::class); + $beUserProphecy->isRTE()->willReturn(false); + $GLOBALS['BE_USER'] = $beUserProphecy->reveal(); + + $input = [ + 'tableName' => 'aTable', + 'effectivePid' => 42, + 'recordTypeValue' => 23, + 'databaseRow' => [ + 'aField' => 'notProcessedContent', + ], + 'processedTca' => [ + 'columns' => [ + 'aField' => [ + 'config' => [ + 'type' => 'text', + 'enableRichtext' => true, + ], + ], + ], + ], + ]; + + // No processing should be performed + $expected = $input; + self::assertSame($expected, (new TcaText())->addData($input)); + } } diff --git a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php index 232371384176..da119f2e40c3 100644 --- a/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php +++ b/typo3/sysext/core/Classes/Authentication/BackendUserAuthentication.php @@ -586,9 +586,9 @@ class BackendUserAuthentication extends AbstractUserAuthentication * @return bool * @internal should only be used from within TYPO3 Core */ - public function isRTE() + public function isRTE(): bool { - return (bool)$this->uc['edit_RTE']; + return (bool)($this->uc['edit_RTE'] ?? false); } /** -- GitLab