[BUGFIX] Respect richtextConfiguration set via TCA 93/61193/12
authorIoulia Kondratovitch <ik@plan2.net>
Sat, 29 Jun 2019 19:48:59 +0000 (21:48 +0200)
committerBenni Mack <benni@typo3.org>
Sat, 9 Nov 2019 12:43:13 +0000 (13:43 +0100)
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: TYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog <look@susi.dev>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Susanne Moog <look@susi.dev>
Reviewed-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Configuration/Richtext.php
typo3/sysext/core/Configuration/TCA/sys_news.php
typo3/sysext/core/Documentation/Changelog/master/Important-88655-ChangedLoadingOrderOfRTEConfiguration.rst [new file with mode: 0644]
typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php
typo3/sysext/frontend/Configuration/TCA/tt_content.php

index 5a92bc9..3563bb7 100644 (file)
@@ -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;
     }
 }
index 285f2bd..99c57c3 100644 (file)
@@ -76,7 +76,6 @@ return [
                 'cols' => 48,
                 'rows' => 5,
                 'enableRichtext' => true,
-                'richtextConfiguration' => 'default',
             ],
         ]
     ],
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Important-88655-ChangedLoadingOrderOfRTEConfiguration.rst b/typo3/sysext/core/Documentation/Changelog/master/Important-88655-ChangedLoadingOrderOfRTEConfiguration.rst
new file mode 100644 (file)
index 0000000..0dcb7da
--- /dev/null
@@ -0,0 +1,39 @@
+.. 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
index 3e5ad70..ce22d4b 100644 (file)
@@ -1,5 +1,6 @@
 <?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,12 +405,12 @@ class RichtextTest extends UnitTestCase
                     'width' => 200
                 ],
             ],
-            'preset' => 'default',
             'editor.' => [
                 'config.' => [
                     'width' => 200
                 ],
             ],
+            'preset' => 'default',
             'proc.' => [
                 'overruleMode' => 'default',
             ],
@@ -411,4 +418,325 @@ class RichtextTest extends UnitTestCase
 
         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);
+    }
 }
index 854479b..e3436db 100644 (file)
@@ -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'
                     ]
                 ]
             ]