$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(
// 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.']);
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;
}
}
+ unset($rtePageTsConfiguration['preset']);
+
return $rtePageTsConfiguration;
}
}
--- /dev/null
+.. 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;
/*
'proc.' => [
'overruleMode' => 'myTransformation',
],
+ 'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
'proc.' => [
'overruleMode' => 'myTransformation',
],
+ 'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
'aClass' => 'aConfig',
],
'removeComments' => '1',
+ 'preset' => 'default',
'classes' => [
'aClass' => 'aConfig',
],
'contentsCss' => 'my.css'
]
],
+ 'preset' => 'default',
'classes' => [
'aClass' => 'anotherConfig',
],
'contentsCss' => 'my.css'
]
],
+ 'preset' => 'default',
// Config without pagets dots
'classes' => [
'aClass' => 'aThirdConfig',
'contentsCss' => 'your.css'
]
],
+ 'preset' => 'default',
// Config without pagets dots
'classes' => [
'aClass' => 'aTypeSpecifcConfig',
'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);
+ }
}