Commit 3669742d authored by Ioulia Kondratovitch's avatar Ioulia Kondratovitch Committed by Benni Mack
Browse files

[BUGFIX] Respect richtextConfiguration set via TCA

If richtextConfiguration is set via TCA for a specific text field
(e.g. for custom elements or within TCA-overrides),
respect the richtextConfiguration and prefer it over the general
RTE.default.preset

Removed 'richtextConfiguration' => 'default' from tt_content, since it is obsolete and breaks the logic of fallback.

New fallback order:
1. preset defined for a specific field via PageTS
2. richtextConfiguration defined for a specific field via TCA
3. general preset defined via PageTS
4. default

Resolves: #88655
Releases: master
Change-Id: I54271732ba862be4c05ccf62352ee685d72fb985
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/61193


Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Susanne Moog's avatarSusanne Moog <look@susi.dev>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
parent 39dd66d8
......@@ -57,10 +57,12 @@ class Richtext
$pageTs = $this->getPageTsConfiguration($table, $field, $pid, $recordType);
// determine which preset to use
$usePreset = $pageTs['preset'] ?? $tcaFieldConf['richtextConfiguration'] ?? 'default';
$pageTs['preset'] = $pageTs['fieldSpecificPreset'] ?? $tcaFieldConf['richtextConfiguration'] ?? $pageTs['generalPreset'] ?? 'default';
unset($pageTs['fieldSpecificPreset']);
unset($pageTs['generalPreset']);
// load configuration from preset
$configuration = $this->loadConfigurationFromPreset($usePreset);
$configuration = $this->loadConfigurationFromPreset($pageTs['preset']);
// overlay preset configuration with pageTs
ArrayUtility::mergeRecursiveWithOverrule(
......@@ -170,6 +172,9 @@ class Richtext
// Load PageTSconfig configuration
$fullPageTsConfig = $this->getRtePageTsConfigOfPid($pid);
$defaultPageTsConfigOverrides = $fullPageTsConfig['default.'] ?? null;
$defaultPageTsConfigOverrides['generalPreset'] = $fullPageTsConfig['default.']['preset'] ?? null;
$fieldSpecificPageTsConfigOverrides = $fullPageTsConfig['config.'][$table . '.'][$field . '.'] ?? null;
unset($fullPageTsConfig['default.'], $fullPageTsConfig['config.']);
......@@ -181,6 +186,9 @@ class Richtext
ArrayUtility::mergeRecursiveWithOverrule($rtePageTsConfiguration, $defaultPageTsConfigOverrides);
}
$rtePageTsConfiguration['fieldSpecificPreset'] = $fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.']['preset'] ??
$fieldSpecificPageTsConfigOverrides['preset'] ?? null;
// Then overload with RTE.config.tt_content.bodytext
if (is_array($fieldSpecificPageTsConfigOverrides)) {
$fieldSpecificPageTsConfigOverridesWithoutType = $fieldSpecificPageTsConfigOverrides;
......@@ -200,6 +208,8 @@ class Richtext
}
}
unset($rtePageTsConfiguration['preset']);
return $rtePageTsConfiguration;
}
}
......@@ -76,7 +76,6 @@ return [
'cols' => 48,
'rows' => 5,
'enableRichtext' => true,
'richtextConfiguration' => 'default',
],
]
],
......
.. include:: ../../Includes.txt
==============================================================
Important: #88655 - Changed loading order of RTE Configuration
==============================================================
See :issue:`88655`
Description
===========
The order in which RTE Configuration is loaded has been changed.
The new order is:
1. preset defined for a specific field via PageTS
2. richtextConfiguration defined for a specific field via TCA
3. general preset defined via PageTS
4. default
This results in a change if you were used to using `RTE.default.preset` to overwrite _all_ RTE
configuration presets - as those with specific configuration in TCA now use their specific settings
instead of falling back to the default. Please make sure, that this new behavior is fitting for your
use cases.
If you are an extension author and you want your RTE fields to use the systems default configuration
(the one configured for the complete web site) please do not set a specific preset for your fields.
If you as an extension author want to provide a specific preset - for example because you are
providing a custom parseFunc - set the property `richtextConfiguration` in TCA.
If an extension provides a custom preset for a specific field and you as an integrator want to
override that configuration (for example to use "your" default), set it specifically for that field
in TSConfig or overwrite the TCA configuration.
For example:
If the blog extension configures `'richtextConfiguration' => 'blog'` for the tag description and
you want the tag description to use the default preset, set
`RTE.config.tx_blog_domain_model_tag.content.types.text.preset = default`.
.. index:: RTE, TCA, TSConfig, ext:core
\ No newline at end of file
<?php
declare(strict_types = 1);
namespace TYPO3\CMS\Core\Tests\Unit\Configuration;
/*
......@@ -61,6 +62,7 @@ class RichtextTest extends UnitTestCase
'proc.' => [
'overruleMode' => 'myTransformation',
],
'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
......@@ -110,6 +112,7 @@ class RichtextTest extends UnitTestCase
'proc.' => [
'overruleMode' => 'myTransformation',
],
'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
......@@ -147,6 +150,7 @@ class RichtextTest extends UnitTestCase
'aClass' => 'aConfig',
],
'removeComments' => '1',
'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
......@@ -195,6 +199,7 @@ class RichtextTest extends UnitTestCase
'contentsCss' => 'my.css'
]
],
'preset' => 'default',
'classes' => [
'aClass' => 'anotherConfig',
],
......@@ -258,6 +263,7 @@ class RichtextTest extends UnitTestCase
'contentsCss' => 'my.css'
]
],
'preset' => 'default',
// Config without pagets dots
'classes' => [
'aClass' => 'aThirdConfig',
......@@ -334,6 +340,7 @@ class RichtextTest extends UnitTestCase
'contentsCss' => 'your.css'
]
],
'preset' => 'default',
// Config without pagets dots
'classes' => [
'aClass' => 'aTypeSpecifcConfig',
......@@ -398,17 +405,338 @@ class RichtextTest extends UnitTestCase
'width' => 200
],
],
'preset' => 'default',
'editor.' => [
'config.' => [
'width' => 200
],
],
'preset' => 'default',
'proc.' => [
'overruleMode' => 'default',
],
];
self::assertSame($expected, $output);
}
/**
* @return array
*/
public function dataProviderGetConfigurationFindPresetInPageTsOverridesPreset()
{
return [
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
'richtextConfiguration' => 'testRteConfigTca'
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'default.' => [
'preset' => 'testRteConfigTsconfigDefault',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField'
]
]
]
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigAField',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'Preset of testRteConfig* in three place TCA',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'default.' => [
'preset' => 'testRteConfigTsconfigDefault',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField'
]
]
]
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigAField',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'Preset of testRteConfig* in two place TCA, lowest is pagetsconfig definition for field of table',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
'richtextConfiguration' => 'testRteConfigTca'
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'default.' => [
'preset' => 'testRteConfigTsconfigDefault',
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTca',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'Preset of testRteConfig* in two place TCA, lowest is definition in tca',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
'richtextConfiguration' => 'testRteConfigTca'
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTca',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'single Preset of testRteConfig* defined in TCA',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'default.' => [
'preset' => 'testRteConfigTsconfigDefault',
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigDefault',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'single Preset of testRteConfig* defined in Pagetesconfig for default of RTE',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
'richtextConfiguration' => 'testRteConfigTca'
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField'
]
]
]
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigAField',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'single Preset of testRteConfig* defined in Pagetesconfig for field of table ',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
'richtextConfiguration' => 'testRteConfigTca'
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'default.' => [
'preset' => 'testRteConfigTsconfigDefault',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField',
'types.' => [
'textmedia.' => [
'preset' => 'testRteConfigTsconfigATypes',
],
],
]
]
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigATypes',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'Preset of testRteConfigTsconfigA* in four place TCA',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField',
'types.' => [
'textmedia.' => [
'preset' => 'testRteConfigTsconfigATypes',
],
],
]
]
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigATypes',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'the preset for CType in pagetsconfig is more reliable than preset for field of tables',
],
[
'fieldConfig' => [
'type' => 'text',
'enableRichtext' => true,
],
'pageTsConfig' => [
'classes.' => [
'aClass' => 'aConfig',
],
'config.' => [
'aTable.' => [
'aField.' => [
'preset' => 'testRteConfigTsconfigAField',
'types.' => [
'textmedia.' => [
'preset' => 'testRteConfigTsconfigATypes',
],
],
]
],
],
],
'expected' => [
'classes.' => [
'aClass' => 'aConfig',
],
'preset' => 'testRteConfigTsconfigATypes',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'default',
],
],
'message' => 'the recordtype overrules the definition of an table-field',
],
];
}
/**
* @dataProvider dataProviderGetConfigurationFindPresetInPageTsOverridesPreset
* @test
*/
public function getConfigurationFindPresetInPageTsOverridesPreset($fieldConfig, $pageTsConfig, $expected, $message)
{
// Accessible mock to $subject since getRtePageTsConfigOfPid calls BackendUtility::getPagesTSconfig()
// which can't be mocked in a sane way
$subject = $this->getAccessibleMock(Richtext::class, ['getRtePageTsConfigOfPid'], [], '', false);
$subject->expects(self::once())->method('getRtePageTsConfigOfPid')->with(42)->willReturn($pageTsConfig);
$output = $subject->getConfiguration('aTable', 'aField', 42, 'textmedia', $fieldConfig);
self::assertSame($expected, $output);
}
}
......@@ -1388,7 +1388,6 @@ return [
'bodytext' => [
'config' => [
'enableRichtext' => true,
'richtextConfiguration' => 'default'
]
]
]
......@@ -1422,7 +1421,6 @@ return [
'bodytext' => [
'config' => [
'enableRichtext' => true,
'richtextConfiguration' => 'default'
]
]
]
......@@ -1456,7 +1454,6 @@ return [
'bodytext' => [
'config' => [
'enableRichtext' => true,
'richtextConfiguration' => 'default'
]
]
]
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment