[BUGFIX] Language label and css loading in inline and flex sections 89/52089/3
authorChristian Kuhn <lolli@schwarzbu.ch>
Fri, 17 Mar 2017 17:53:30 +0000 (18:53 +0100)
committerSusanne Moog <susanne.moog@typo3.org>
Wed, 22 Mar 2017 12:05:20 +0000 (13:05 +0100)
Loading additional stylesheets from elements in inline scope fails if using
'EXT:' syntax, for flex section containers, this was not evaluated at all.
The patch adds code to resolve an EXT: prefix stylesheet file from an element
result array ['stylesheetFiles'] to properly handle loading of this CSS in
JS, and uses it in both inline and flex ajax controller. This issue is easily
reproducible with ext:styleguide 'elements_t3editor', which registers
t3editor.css to load. Without patch, This fail (404) in 'in inline'
't3editor_inline_1' 'Create New'.
Additionally, additional language file handling was not implemented for
flex section container ajax calls, which is also added by the patch,
similar to the solution done in inline ajax.

Change-Id: I617b9f1ed3e0c4718fb0867a42f2c37b604d7afe
Resolves: #80335
Releases: master
Reviewed-on: https://review.typo3.org/52089
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Frank Nägler <frank.naegler@typo3.org>
Tested-by: Frank Nägler <frank.naegler@typo3.org>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/backend/Classes/Controller/AbstractFormEngineAjaxController.php
typo3/sysext/backend/Classes/Controller/FormFlexAjaxController.php
typo3/sysext/backend/Classes/Controller/FormInlineAjaxController.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js

index 028ed08..8135d76 100644 (file)
@@ -15,6 +15,11 @@ namespace TYPO3\CMS\Backend\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Localization\LocalizationFactory;
+use TYPO3\CMS\Core\Utility\ArrayUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\PathUtility;
+
 /**
  * Abstract class for a couple of FormEngine controllers triggered by
  * ajax calls. The class containers some helpers to for instance prepare
@@ -65,4 +70,61 @@ abstract class AbstractFormEngineAjaxController
         }
         return $requireJs;
     }
+
+    /**
+     * Resolve a CSS file position, possibly prefixed with 'EXT:'
+     *
+     * @param string $stylesheetFile Given file, possibly prefixed with EXT:
+     * @return string Web root relative position to file
+     */
+    protected function getRelativePathToStylesheetFile(string $stylesheetFile): string
+    {
+        if (strpos($stylesheetFile, 'EXT:') === 0) {
+            $stylesheetFile = GeneralUtility::getFileAbsFileName($stylesheetFile);
+            $stylesheetFile = PathUtility::getRelativePathTo($stylesheetFile);
+            $stylesheetFile = rtrim($stylesheetFile, '/');
+        } else {
+            $stylesheetFile = GeneralUtility::resolveBackPath($stylesheetFile);
+        }
+        $stylesheetFile = GeneralUtility::createVersionNumberedFilename($stylesheetFile);
+        return PathUtility::getAbsoluteWebPath($stylesheetFile);
+    }
+
+    /**
+     * Parse a language file and get a label/value array from it.
+     *
+     * @param string $file EXT:path/to/file
+     * @return array Label/value array
+     */
+    protected function getLabelsFromLocalizationFile($file)
+    {
+        /** @var $languageFactory LocalizationFactory */
+        $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
+        $language = $GLOBALS['LANG']->lang;
+        $localizationArray = $languageFactory->getParsedData(
+            $file,
+            $language,
+            'utf-8',
+            1
+        );
+        if (is_array($localizationArray) && !empty($localizationArray)) {
+            if (!empty($localizationArray[$language])) {
+                $xlfLabelArray = $localizationArray['default'];
+                ArrayUtility::mergeRecursiveWithOverrule($xlfLabelArray, $localizationArray[$language], true, false);
+            } else {
+                $xlfLabelArray = $localizationArray['default'];
+            }
+        } else {
+            $xlfLabelArray = [];
+        }
+        $labelArray = [];
+        foreach ($xlfLabelArray as $key => $value) {
+            if (isset($value[0]['target'])) {
+                $labelArray[$key] = $value[0]['target'];
+            } else {
+                $labelArray[$key] = '';
+            }
+        }
+        return $labelArray;
+    }
 }
index 5eba4d0..7606c92 100644 (file)
@@ -21,6 +21,7 @@ use TYPO3\CMS\Backend\Form\FormDataCompiler;
 use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
 use TYPO3\CMS\Backend\Form\NodeFactory;
 use TYPO3\CMS\Core\Configuration\FlexForm\FlexFormTools;
+use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\StringUtility;
 
@@ -113,6 +114,7 @@ class FormFlexAjaxController extends AbstractFormEngineAjaxController
 
         $jsonResult = [
             'html' => $newContainerResult['html'],
+            'stylesheetFiles' => [],
             'scriptCall' => [],
         ];
 
@@ -124,7 +126,30 @@ class FormFlexAjaxController extends AbstractFormEngineAjaxController
         foreach ($newContainerResult['additionalJavaScriptPost'] as $singleAdditionalJavaScriptPost) {
             $jsonResult['scriptCall'][] = $singleAdditionalJavaScriptPost;
         }
-        // @todo: handle stylesheetFiles, additionalInlineLanguageLabelFiles
+        foreach ($newContainerResult['stylesheetFiles'] as $stylesheetFile) {
+            $jsonResult['stylesheetFiles'][] = $this->getRelativePathToStylesheetFile($stylesheetFile);
+        }
+        if (!empty($newContainerResult['additionalInlineLanguageLabelFiles'])) {
+            $labels = [];
+            foreach ($newContainerResult['additionalInlineLanguageLabelFiles'] as $additionalInlineLanguageLabelFile) {
+                ArrayUtility::mergeRecursiveWithOverrule(
+                    $labels,
+                    $this->getLabelsFromLocalizationFile($additionalInlineLanguageLabelFile)
+                );
+            }
+            $javaScriptCode = [];
+            $javaScriptCode[] = 'if (typeof TYPO3 === \'undefined\' || typeof TYPO3.lang === \'undefined\') {';
+            $javaScriptCode[] = '   TYPO3.lang = {}';
+            $javaScriptCode[] = '}';
+            $javaScriptCode[] = 'var additionalInlineLanguageLabels = ' . json_encode($labels) . ';';
+            $javaScriptCode[] = 'for (var attributeName in additionalInlineLanguageLabels) {';
+            $javaScriptCode[] = '   if (typeof TYPO3.lang[attributeName] === \'undefined\') {';
+            $javaScriptCode[] = '       TYPO3.lang[attributeName] = additionalInlineLanguageLabels[attributeName]';
+            $javaScriptCode[] = '   }';
+            $javaScriptCode[] = '}';
+
+            $jsonResult['scriptCall'][] = implode(LF, $javaScriptCode);
+        }
 
         $requireJsModule = $this->createExecutableStringRepresentationOfRegisteredRequireJsModules($newContainerResult);
         $jsonResult['scriptCall'] = array_merge($requireJsModule, $jsonResult['scriptCall']);
index 9e273e2..97a8e44 100644 (file)
@@ -23,7 +23,6 @@ use TYPO3\CMS\Backend\Form\InlineStackProcessor;
 use TYPO3\CMS\Backend\Form\NodeFactory;
 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
-use TYPO3\CMS\Core\Localization\LocalizationFactory;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
@@ -576,7 +575,10 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController
     protected function mergeChildResultIntoJsonResult(array $jsonResult, array $childResult)
     {
         $jsonResult['data'] .= $childResult['html'];
-        $jsonResult['stylesheetFiles'] = $childResult['stylesheetFiles'];
+        $jsonResult['stylesheetFiles'] = [];
+        foreach ($childResult['stylesheetFiles'] as $stylesheetFile) {
+            $jsonResult['stylesheetFiles'][] = $this->getRelativePathToStylesheetFile($stylesheetFile);
+        }
         if (!empty($childResult['inlineData'])) {
             $jsonResult['scriptCall'][] = 'inline.addToDataArray(' . json_encode($childResult['inlineData']) . ');';
         }
@@ -593,7 +595,7 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController
             foreach ($childResult['additionalInlineLanguageLabelFiles'] as $additionalInlineLanguageLabelFile) {
                 ArrayUtility::mergeRecursiveWithOverrule(
                     $labels,
-                    $this->addInlineLanguageLabelFile($additionalInlineLanguageLabelFile)
+                    $this->getLabelsFromLocalizationFile($additionalInlineLanguageLabelFile)
                 );
             }
             $javaScriptCode = [];
@@ -616,43 +618,6 @@ class FormInlineAjaxController extends AbstractFormEngineAjaxController
     }
 
     /**
-     * @param string $file
-     *
-     * @return array
-     */
-    protected function addInlineLanguageLabelFile($file)
-    {
-        /** @var $languageFactory LocalizationFactory */
-        $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
-        $language = $GLOBALS['LANG']->lang;
-        $localizationArray = $languageFactory->getParsedData(
-            $file,
-            $language,
-            'utf-8',
-            1
-        );
-        if (is_array($localizationArray) && !empty($localizationArray)) {
-            if (!empty($localizationArray[$language])) {
-                $xlfLabelArray = $localizationArray['default'];
-                ArrayUtility::mergeRecursiveWithOverrule($xlfLabelArray, $localizationArray[$language], true, false);
-            } else {
-                $xlfLabelArray = $localizationArray['default'];
-            }
-        } else {
-            $xlfLabelArray = [];
-        }
-        $labelArray = [];
-        foreach ($xlfLabelArray as $key => $value) {
-            if (isset($value[0]['target'])) {
-                $labelArray[$key] = $value[0]['target'];
-            } else {
-                $labelArray[$key] = '';
-            }
-        }
-        return $labelArray;
-    }
-
-    /**
      * Gets an array with the uids of related records out of a list of items.
      * This list could contain more information than required. This methods just
      * extracts the uids.
index 3d62778..458b3d1 100644 (file)
@@ -264,6 +264,15 @@ define(['jquery',
                                                        eval(value);
                                                });
                                        }
+                                       if (response.stylesheetFiles && response.stylesheetFiles.length > 0) {
+                                               $.each(response.stylesheetFiles, function (index, stylesheetFile) {
+                                                       var element = document.createElement('link');
+                                                       element['rel'] = 'stylesheet';
+                                                       element['type'] = 'text/css';
+                                                       element['href'] = stylesheetFile;
+                                                       document.head.appendChild(element);
+                                               });
+                                       }
                                        TYPO3.FormEngine.reinitialize();
                                        TYPO3.FormEngine.Validation.initializeInputFields();
                                        TYPO3.FormEngine.Validation.validate();