[BUGFIX] Ensure pageTS is overriding on top-level RTE syntax 17/51917/4
authorBenni Mack <benni@typo3.org>
Wed, 1 Mar 2017 11:51:10 +0000 (12:51 +0100)
committerHelmut Hummel <typo3@helhum.io>
Thu, 2 Mar 2017 12:45:25 +0000 (13:45 +0100)
If using RTE.classesAnchor before, the new Richtext class
did not merge the values together. This is now solved by
doing proper overlays.

Resolves: #80078
Releases: master
Change-Id: Ia76696065a22207ed40974cc0da8b2842120c45d
Reviewed-on: https://review.typo3.org/51917
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Helmut Hummel <typo3@helhum.io>
Tested-by: Helmut Hummel <typo3@helhum.io>
typo3/sysext/core/Classes/Configuration/Richtext.php
typo3/sysext/core/Tests/Unit/Configuration/RichtextTest.php

index a8795b5..202906a 100644 (file)
@@ -61,27 +61,41 @@ class Richtext
         $configuration = $this->loadConfigurationFromPreset($tcaFieldConf['richtextConfiguration']);
 
         // Overload with PageTSconfig configuration
-        // First use RTE.default
+        // First use RTE.*
+        // Then overload with RTE.default
         // Then overload with RTE.config.tt_content.bodytext
         // Then overload with RTE.config.tt_content.bodytext.types.textmedia
         $fullPageTsConfig = $this->getRtePageTsConfigOfPid($pid);
-
-        if (is_array($fullPageTsConfig['properties']['default.'])) {
-            ArrayUtility::mergeRecursiveWithOverrule($configuration, $fullPageTsConfig['properties']['default.']);
+        $fullPageTsConfig = !empty($fullPageTsConfig['properties']) ? $fullPageTsConfig['properties'] : [];
+        $defaultPageTsConfigOverrides = isset($fullPageTsConfig['default.']) ? $fullPageTsConfig['default.'] : null;
+        $fieldSpecificPageTsConfigOverrides = isset($fullPageTsConfig['config.'][$table . '.'][$field . '.']) ? $fullPageTsConfig['config.'][$table . '.'][$field . '.'] : null;
+        unset($fullPageTsConfig['default.'], $fullPageTsConfig['config.']);
+        // RTE.* (used for RTE.classesAnchor or similar in RTEHtmlArea)
+        if (!empty($fullPageTsConfig)) {
+            ArrayUtility::mergeRecursiveWithOverrule($configuration, $fullPageTsConfig);
         }
-        $rtePageTsField = $fullPageTsConfig['properties']['config.'][$table . '.'][$field . '.'];
-        if (is_array($rtePageTsField)) {
-            unset($rtePageTsField['types.']);
-            ArrayUtility::mergeRecursiveWithOverrule($configuration, $rtePageTsField);
+        // RTE.default.*
+        if (is_array($defaultPageTsConfigOverrides)) {
+            ArrayUtility::mergeRecursiveWithOverrule($configuration, $defaultPageTsConfigOverrides);
         }
-        if ($recordType && is_array($fullPageTsConfig['properties']['config.'][$table . '.'][$field . '.']['types.'][$recordType . '.'])) {
-            ArrayUtility::mergeRecursiveWithOverrule(
-                $configuration,
-                $fullPageTsConfig['properties']['config.'][$table . '.'][$field . '.']['types.'][$recordType . '.']
-            );
+        // RTE.config.tt_content.bodytext and based on type as well
+        if (is_array($fieldSpecificPageTsConfigOverrides)) {
+            $fieldSpecificPageTsConfigOverridesWithoutType = $fieldSpecificPageTsConfigOverrides;
+            unset($fieldSpecificPageTsConfigOverridesWithoutType['types.']);
+            ArrayUtility::mergeRecursiveWithOverrule($configuration, $fieldSpecificPageTsConfigOverridesWithoutType);
+            if ($recordType
+                && isset($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])
+                && is_array($fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.'])) {
+                ArrayUtility::mergeRecursiveWithOverrule(
+                    $configuration,
+                    $fieldSpecificPageTsConfigOverrides['types.'][$recordType . '.']
+                );
+            }
         }
 
         // Reload the base configuration, if overridden via PageTS "RTE.default.preset = Minimal" for instance
+        // However, if a preset is chosen via TSconfig, then it is not possible to override anything else again
+        // via TSconfig (endless loop).
         if (isset($configuration['preset']) && $usePreset !== $configuration['preset']) {
             $configuration = $this->loadConfigurationFromPreset($configuration['preset']);
         }
index b05530d..d872a98 100644 (file)
@@ -32,10 +32,10 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             'enableRichtext' => true,
         ];
         $pageTsConfig = [
-            'classes.' => [
-                'aClass.' => 'aConfig',
-            ],
             'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
                 'default.' => [
                     'removeComments' => '1',
                 ],
@@ -55,6 +55,9 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             ]
         ];
         $expected = [
+            'classes.' => [
+                'aClass.' => 'aConfig',
+            ],
             'removeComments' => '1',
             'proc.' => [
                 'overruleMode' => 'myTransformation',
@@ -78,10 +81,10 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             'enableRichtext' => true,
         ];
         $pageTsConfig = [
-            'classes.' => [
-                'aClass.' => 'aConfig',
-            ],
             'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
                 'default.' => [
                     'removeComments' => '1',
                 ],
@@ -97,6 +100,9 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             ]
         ];
         $expected = [
+            'classes.' => [
+                'aClass.' => 'aConfig',
+            ],
             'removeComments' => '1',
             'proc.' => [
                 'overruleMode' => 'myTransformation',
@@ -120,16 +126,19 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             'enableRichtext' => true,
         ];
         $pageTsConfig = [
-            'classes.' => [
-                'aClass.' => 'aConfig',
-            ],
             'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
                 'default.' => [
                     'removeComments' => '1',
                 ],
             ]
         ];
         $expected = [
+            'classes.' => [
+                'aClass.' => 'aConfig',
+            ],
             'removeComments' => '1',
             'proc.' => [
                 'overruleMode' => 'default',
@@ -153,18 +162,157 @@ class RichtextTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase
             'enableRichtext' => true,
         ];
         $pageTsConfig = [
+            'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
+                'default.' => [
+                    'proc.' => [
+                        'overruleMode' => 'ts_css',
+                    ],
+                ],
+            ],
+        ];
+        $expected = [
             'classes.' => [
                 'aClass.' => 'aConfig',
             ],
+            'proc.' => [
+                'overruleMode' => 'default',
+            ],
+        ];
+        // 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($this->once())->method('getRtePageTsConfigOfPid')->with(42)->willReturn($pageTsConfig);
+        $output = $subject->getConfiguration('aTable', 'aField', 42, 'textmedia', $fieldConfig);
+        $this->assertSame($expected, $output);
+    }
+
+    /**
+     * @test
+     */
+    public function getConfigurationOverridesByDefault()
+    {
+        $fieldConfig = [
+            'type' => 'text',
+            'enableRichtext' => true,
+        ];
+        $pageTsConfig = [
             'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
                 'default.' => [
-                    'proc.' => [
-                        'overruleMode' => 'ts_css',
+                    'classes.' => [
+                        'aClass.' => 'anotherConfig',
+                    ],
+                ],
+            ],
+        ];
+        $expected = [
+            'classes.' => [
+                'aClass.' => 'anotherConfig',
+            ],
+            'proc.' => [
+                'overruleMode' => 'default',
+            ],
+        ];
+        // 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($this->once())->method('getRtePageTsConfigOfPid')->with(42)->willReturn($pageTsConfig);
+        $output = $subject->getConfiguration('aTable', 'aField', 42, 'textmedia', $fieldConfig);
+        $this->assertSame($expected, $output);
+    }
+
+    /**
+     * @test
+     */
+    public function getConfigurationOverridesByFieldSpecificConfig()
+    {
+        $fieldConfig = [
+            'type' => 'text',
+            'enableRichtext' => true,
+        ];
+        $pageTsConfig = [
+            'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
+                'default.' => [
+                    'classes.' => [
+                        'aClass.' => 'anotherConfig',
+                    ],
+                ],
+                'config.' => [
+                    'aTable.' => [
+                        'aField.' => [
+                            'classes.' => [
+                                'aClass.' => 'aThirdConfig',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        $expected = [
+            'classes.' => [
+                'aClass.' => 'aThirdConfig',
+            ],
+            'proc.' => [
+                'overruleMode' => 'default',
+            ],
+        ];
+        // 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($this->once())->method('getRtePageTsConfigOfPid')->with(42)->willReturn($pageTsConfig);
+        $output = $subject->getConfiguration('aTable', 'aField', 42, 'textmedia', $fieldConfig);
+        $this->assertSame($expected, $output);
+    }
+
+    /**
+     * @test
+     */
+    public function getConfigurationOverridesByFieldAndTypeSpecificConfig()
+    {
+        $fieldConfig = [
+            'type' => 'text',
+            'enableRichtext' => true,
+        ];
+        $pageTsConfig = [
+            'properties' => [
+                'classes.' => [
+                    'aClass.' => 'aConfig',
+                ],
+                'default.' => [
+                    'classes.' => [
+                        'aClass.' => 'anotherConfig',
+                    ],
+                ],
+                'config.' => [
+                    'aTable.' => [
+                        'aField.' => [
+                            'classes.' => [
+                                'aClass.' => 'aThirdConfig',
+                            ],
+                            'types.' => [
+                                'textmedia.' => [
+                                    'classes.' => [
+                                        'aClass.' => 'aTypeSpecifcConfig',
+                                    ],
+                                ]
+                            ]
+                        ],
                     ],
                 ],
             ],
         ];
         $expected = [
+            'classes.' => [
+                'aClass.' => 'aTypeSpecifcConfig',
+            ],
             'proc.' => [
                 'overruleMode' => 'default',
             ],