[FEATURE] Use FormEngine in Template and Filelist modules 61/49661/9
authorAndreas Fernandez <a.fernandez@scripting-base.de>
Tue, 30 Aug 2016 15:22:55 +0000 (17:22 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 4 Sep 2016 09:38:46 +0000 (11:38 +0200)
The backend modules "Template" and "Filelist" have been updated to use
the FormEngine to render the forms. This eases the manipulation of the
form by hooks, e.g.  to integrate the t3editor.

Resolves: #77727
Releases: master
Change-Id: Ibc7cc19684e4c6ef8479967dbf3b77be513acda6
Reviewed-on: https://review.typo3.org/49661
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/backend/Classes/Controller/File/EditFileController.php
typo3/sysext/backend/Classes/Controller/File/FileController.php
typo3/sysext/core/Documentation/Changelog/master/Feature-77727-UseFormEngineInTemplateAndFilelistModules.rst [new file with mode: 0644]
typo3/sysext/t3editor/Classes/Form/Element/T3editorElement.php
typo3/sysext/t3editor/Classes/Hook/FileEditHook.php
typo3/sysext/t3editor/Classes/Hook/TypoScriptTemplateInfoHook.php
typo3/sysext/t3editor/Classes/T3editor.php
typo3/sysext/t3editor/ext_localconf.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateInformationModuleFunctionController.php
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateModuleController.php

index e3fa473..a178291 100644 (file)
@@ -16,6 +16,8 @@ namespace TYPO3\CMS\Backend\Controller\File;
 
 use Psr\Http\Message\ResponseInterface;
 use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Backend\Form\FormResultCompiler;
+use TYPO3\CMS\Backend\Form\NodeFactory;
 use TYPO3\CMS\Backend\Module\AbstractModule;
 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
 use TYPO3\CMS\Backend\Template\DocumentTemplate;
@@ -146,13 +148,27 @@ class EditFileController extends AbstractModule
     public function main()
     {
         $this->getButtons();
-        // Hook        before compiling the output
+
+        $dataColumnDefinition = [
+            'label' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_common.xlf:file'))
+                . ' ' . htmlspecialchars($this->target),
+            'config' => [
+                'type' => 'text',
+                'cols' => 48,
+                'wrap' => 'OFF',
+                'softref' => 'email[subst],url[subst]'
+            ],
+            'defaultExtras' => 'fixed-font: enable-tab'
+        ];
+
+        // Hook before compiling the output
         if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'])) {
             $preOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'];
             if (is_array($preOutputProcessingHook)) {
                 $hookParameters = [
                     'content' => &$this->content,
-                    'target' => &$this->target
+                    'target' => &$this->target,
+                    'dataColumnDefinition' => &$dataColumnDefinition
                 ];
                 foreach ($preOutputProcessingHook as $hookFunction) {
                     GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
@@ -180,13 +196,48 @@ class EditFileController extends AbstractModule
                 'target' => $this->origTarget,
                 'returnUrl' => $this->returnUrl
             ]);
-            $code .= '
-                <div id="c-edit">
-                                       <textarea rows="30" name="file[editfile][0][data]" wrap="off"  class="form-control text-monospace t3js-enable-tab">' . htmlspecialchars($fileContent) . '</textarea>
-                                       <input type="hidden" name="file[editfile][0][target]" value="' . $this->fileObject->getUid() . '" />
-                                       <input type="hidden" name="redirect" value="' . htmlspecialchars($hValue) . '" />
-                               </div>
-                               <br />';
+            $formData = [
+                'databaseRow' => [
+                    'uid' => 0,
+                    'data' => $fileContent,
+                    'target' => $this->fileObject->getUid(),
+                    'redirect' => $hValue
+                ],
+                'tableName' => 'editfile',
+                'processedTca' => [
+                    'columns' => [
+                        'data' => $dataColumnDefinition,
+                        'target' => [
+                            'config' => [
+                                'type' => 'input',
+                                'renderType' => 'hidden'
+                            ]
+                        ],
+                        'redirect' => [
+                            'config' => [
+                                'type' => 'input',
+                                'renderType' => 'hidden'
+                            ]
+                        ]
+                    ],
+                    'types' => [
+                        1 => [
+                            'showitem' => 'data,target,redirect',
+                        ],
+                    ],
+                ],
+                'recordTypeValue' => 1,
+                'inlineStructure' => [],
+                'renderType' => 'fullRecordContainer'
+            ];
+
+            $resultArray = GeneralUtility::makeInstance(NodeFactory::class)->create($formData)->render();
+            $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
+            $formResultCompiler->mergeResult($resultArray);
+
+            $code .= $formResultCompiler->JStop()
+                . $formResultCompiler->printNeededJSFunctions()
+                . $resultArray['html'];
         } catch (\Exception $e) {
             $code .= sprintf(
                 $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:file_edit.php.coundNot'),
@@ -197,7 +248,7 @@ class EditFileController extends AbstractModule
         // Ending of section and outputting editing form:
         $pageContent .= $code;
 
-        // Hook        after compiling the output
+        // Hook after compiling the output
         if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'])) {
             $postOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'];
             if (is_array($postOutputProcessingHook)) {
index 1b577c8..cc75579 100644 (file)
@@ -102,11 +102,11 @@ class FileController
     protected function init()
     {
         // Set the GPvars from outside
-        $this->file = GeneralUtility::_GP('file');
+        $this->file = GeneralUtility::_GP('data');
         $this->CB = GeneralUtility::_GP('CB');
         $this->overwriteExistingFiles = DuplicationBehavior::cast(GeneralUtility::_GP('overwriteExistingFiles'));
         $this->vC = GeneralUtility::_GP('vC');
-        $this->redirect = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('redirect'));
+        $this->redirect = $this->file['editfile'][0]['redirect'];
         $this->initClipboard();
         $this->fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
     }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-77727-UseFormEngineInTemplateAndFilelistModules.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-77727-UseFormEngineInTemplateAndFilelistModules.rst
new file mode 100644 (file)
index 0000000..9784271
--- /dev/null
@@ -0,0 +1,24 @@
+=================================================================
+Feature: #77727 - Use FormEngine in Template and Filelist modules
+=================================================================
+
+Description
+===========
+
+The backend modules "Template" and "Filelist" have been migrated
+to use the FormEngine for rendering the forms.
+
+
+Impact
+======
+
+The class ``\TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController`` received a new hook
+:php:`$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['preOutputProcessingHook']`
+which takes two parameters:
+* :php:`$parameters` (array)
+* :php:`$pObj` (TypoScriptTemplateInformationModuleFunctionController)
+
+The ``formData`` element of the array ``$parameters`` contains the form structure for FormEngine, which may be
+extended in a hook.
+
+The TCA for t3editor fields has received a new configuration option ``ajaxSaveType`` required for saving hooks.
index fe30393..d445736 100644 (file)
@@ -87,6 +87,11 @@ class T3editorElement extends AbstractFormElement
     protected $codeCompletionComponents = ['TsRef', 'CompletionResult', 'TsParser', 'TsCodeCompletion'];
 
     /**
+     * @var string
+     */
+    protected $ajaxSaveType = '';
+
+    /**
      * Render t3editor element
      *
      * @return array As defined in initializeResultArray() of AbstractNode
@@ -102,7 +107,8 @@ class T3editorElement extends AbstractFormElement
         $parameterArray = $this->data['parameterArray'];
 
         $rows = MathUtility::forceIntegerInRange($parameterArray['fieldConf']['config']['rows'] ?: 10, 1, 40);
-        $this->setMode(isset($parameterArray['fieldConf']['config']['format']) ? $parameterArray['fieldConf']['config']['format'] : T3editor::MODE_MIXED);
+        $this->setMode($parameterArray['fieldConf']['config']['format'] ?? T3editor::MODE_MIXED);
+        $this->ajaxSaveType = $parameterArray['fieldConf']['config']['ajaxSaveType'] ?? '';
 
         $attributes = [];
         $attributes['rows'] = $rows;
@@ -121,7 +127,10 @@ class T3editorElement extends AbstractFormElement
             $parameterArray['itemFormElValue'],
             $attributeString,
             $this->data['tableName'] . ' > ' . $this->data['fieldName'],
-            ['target' => 0]
+            [
+                'target' => 0,
+                'id' => (int)$this->data['databaseRow']['pageId']
+            ]
         );
         $this->resultArray['additionalJavaScriptPost'][] = 'require(["TYPO3/CMS/T3editor/T3editor"], function(T3editor) {T3editor.findAndInitializeEditors();});';
 
@@ -189,7 +198,7 @@ class T3editorElement extends AbstractFormElement
         $attributes['data-instance-number'] =  $this->editorCounter;
         $attributes['data-editor-path'] =  $this->relExtPath;
         $attributes['data-codemirror-path'] =  $this->codemirrorPath;
-        $attributes['data-ajaxsavetype'] = ''; // no ajax save in FormEngine at the moment
+        $attributes['data-ajaxsavetype'] = htmlspecialchars($this->ajaxSaveType);
         $attributes['data-parserfile'] = $this->getParserfileByMode($this->mode);
         $attributes['data-stylesheet'] = $this->getStylesheetByMode($this->mode);
 
index f2bc3b0..d3eff40 100644 (file)
@@ -14,8 +14,10 @@ namespace TYPO3\CMS\T3editor\Hook;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Controller\File\FileController;
 use TYPO3\CMS\Core\Page\PageRenderer;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\T3editor\T3editor;
 
 /**
  * File edit hook for t3editor
@@ -23,7 +25,7 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 class FileEditHook
 {
     /**
-     * @var \TYPO3\CMS\T3editor\T3editor
+     * @var T3editor
      */
     protected $t3editor = null;
 
@@ -33,12 +35,12 @@ class FileEditHook
     protected $ajaxSaveType = 'TypoScriptTemplateInformationModuleFunctionController';
 
     /**
-     * @return \TYPO3\CMS\T3editor\T3editor
+     * @return T3editor
      */
     protected function getT3editor()
     {
         if ($this->t3editor === null) {
-            $this->t3editor = GeneralUtility::makeInstance(\TYPO3\CMS\T3editor\T3editor::class)->setAjaxSaveType($this->ajaxSaveType);
+            $this->t3editor = GeneralUtility::makeInstance(T3editor::class);
         }
         return $this->t3editor;
     }
@@ -50,67 +52,29 @@ class FileEditHook
      * @param array $parameters
      * @param \TYPO3\CMS\Backend\Controller\File\EditFileController $pObj
      */
-    public function preOutputProcessingHook($parameters, $pObj)
+    public function preOutputProcessingHook(&$parameters, $pObj)
     {
         $t3editor = $this->getT3editor();
         $t3editor->setModeByFile($parameters['target']);
         if (!$t3editor->getMode()) {
             return;
         }
-        $t3editor->getJavascriptCode();
-        $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/T3editor/FileEdit');
-    }
-
-    /**
-     * Hook-function: inject t3editor JavaScript code before the page is compiled
-     * called in \TYPO3\CMS\Backend\Template\DocumentTemplate:startPage
-     *
-     * @see \TYPO3\CMS\Backend\Template\DocumentTemplate::startPage
-     */
-    public function preStartPageHook()
-    {
-        // @todo: this is a workaround. Ideally the document template holds the current request so we can match the route
-        // against the name of the route and not the GET parameter
-        if (GeneralUtility::_GET('route') === '/file/editcontent') {
-            $t3editor = $this->getT3editor();
-            $t3editor->getJavascriptCode();
-            $this->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/T3editor/FileEdit');
-        }
-    }
-
-    /**
-     * Hook-function:
-     * called in file_edit module
-     *
-     * @param array $parameters
-     * @param \TYPO3\CMS\Backend\Controller\File\EditFileController $pObj
-     */
-    public function postOutputProcessingHook($parameters, $pObj)
-    {
-        $t3editor = $this->getT3editor();
-        if (!$t3editor->getMode()) {
-            return;
-        }
-        $attributes = 'rows="30" ' . 'wrap="off"' . $pObj->doc->formWidth(48, true, 'width:98%;height:60%');
-        $title = $GLOBALS['LANG']->getLL('file') . ' ' . htmlspecialchars($pObj->target);
-        $outCode = $t3editor->getCodeEditor('file[editfile][0][data]', 'text-monospace enable-tab', '$1', $attributes, $title, [
-            'target' => (int)$pObj->target
-        ]);
-        $parameters['pageContent'] = preg_replace('/\\<textarea .*name="file\\[editfile\\]\\[0\\]\\[data\\]".*\\>([^\\<]*)\\<\\/textarea\\>/mi', $outCode, $parameters['pageContent']);
+        $parameters['dataColumnDefinition']['config']['renderType'] = 't3editor';
+        $parameters['dataColumnDefinition']['config']['format'] = $t3editor->getMode();
+        $parameters['dataColumnDefinition']['config']['ajaxSaveType'] = $this->ajaxSaveType;
     }
 
     /**
      * @param array $parameters
-     * @param mixed $pObj
-     *
+     * @param T3editor $pObj
      * @return bool TRUE if successful
      */
     public function save($parameters, $pObj)
     {
         $savingsuccess = false;
         if ($parameters['type'] === $this->ajaxSaveType) {
-            /** @var \TYPO3\CMS\Backend\Controller\File\FileController $tceFile */
-            $tceFile = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Controller\File\FileController::class);
+            /** @var FileController $tceFile */
+            $tceFile = GeneralUtility::makeInstance(FileController::class);
             $response = $tceFile->processAjaxRequest($parameters['request'], $parameters['response']);
             $result = json_decode((string)$response->getBody(), true);
             $savingsuccess = is_array($result) && $result['editfile'][0];
index c565e2b..1d10310 100644 (file)
@@ -13,6 +13,12 @@ namespace TYPO3\CMS\T3editor\Hook;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\DataHandling\DataHandler;
+use TYPO3\CMS\Core\TypoScript\ExtendedTemplateService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\T3editor\T3editor;
+use TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController;
 
 /**
  * Hook for tstemplate info
@@ -20,63 +26,25 @@ namespace TYPO3\CMS\T3editor\Hook;
 class TypoScriptTemplateInfoHook
 {
     /**
-     * @var \TYPO3\CMS\T3editor\T3editor
-     */
-    protected $t3editor = null;
-
-    /**
      * @var string
      */
     protected $ajaxSaveType = 'TypoScriptTemplateInformationModuleFunctionController';
 
     /**
-     * @return \TYPO3\CMS\T3editor\T3editor
-     */
-    protected function getT3editor()
-    {
-        if ($this->t3editor == null) {
-            $this->t3editor = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\T3editor\T3editor::class)->setMode(\TYPO3\CMS\T3editor\T3editor::MODE_TYPOSCRIPT)->setAjaxSaveType($this->ajaxSaveType);
-        }
-        return $this->t3editor;
-    }
-
-    /**
-     * Hook-function: inject t3editor JavaScript code before the page is compiled
-     * called in \TYPO3\CMS\Backend\Template\DocumentTemplate:startPage
-     *
-     * @return void
-     * @see \TYPO3\CMS\Backend\Template\DocumentTemplate::startPage
-     */
-    public function preStartPageHook()
-    {
-        // Enable editor in Template-Modul
-        if (\TYPO3\CMS\Core\Utility\GeneralUtility::_GET('M') === 'web_ts') {
-            $t3editor = $this->getT3editor();
-            // Insert javascript code
-            $t3editor->getJavascriptCode();
-        }
-    }
-
-    /**
      * Hook-function:
      * called in typo3/sysext/tstemplate_info/Classes/Controller/TypoScriptTemplateInformationModuleFunctionController.php
      *
      * @param array $parameters
-     * @param \TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController $pObj
+     * @param TypoScriptTemplateInformationModuleFunctionController $pObj
      * @return void
      */
-    public function postOutputProcessingHook($parameters, $pObj)
+    public function preOutputProcessingHook(&$parameters, $pObj)
     {
-        $t3editor = $this->getT3editor();
-        $t3editor->getJavascriptCode();
-        foreach (['constants', 'config'] as $type) {
-            if ($parameters['e'][$type]) {
-                $attributes = 'rows="' . (int)$parameters['numberOfRows'] . '" wrap="off" style="width:98%;height:60%"';
-                $title = $GLOBALS['LANG']->getLL('template') . ' ' . $parameters['tplRow']['title'] . $GLOBALS['LANG']->getLL('delimiter') . ' ' . $GLOBALS['LANG']->getLL($type);
-                $outCode = $t3editor->getCodeEditor('data[' . $type . ']', 'text-monospace enable-tab', '$1', $attributes, $title, [
-                    'pageId' => (int)$pObj->pObj->id
-                ]);
-                $parameters['theOutput'] = preg_replace('/\\<textarea name="data\\[' . $type . '\\]".*\\>([^\\<]*)\\<\\/textarea\\>/mi', $outCode, $parameters['theOutput']);
+        foreach ($parameters['formData']['processedTca']['columns'] as $column => &$definition) {
+            if ($definition['config']['type'] === 'text') {
+                $definition['config']['renderType'] = 't3editor';
+                $definition['config']['format'] = 'typoscript';
+                $definition['config']['ajaxSaveType'] = $this->ajaxSaveType;
             }
         }
     }
@@ -84,22 +52,24 @@ class TypoScriptTemplateInfoHook
     /**
      * Process saving request like in class.tstemplateinfo.php (TCE processing)
      *
+     * @param array $parameters
+     * @param T3editor $pObj
      * @return bool TRUE if successful
      */
     public function save($parameters, $pObj)
     {
         $savingsuccess = false;
         if ($parameters['type'] == $this->ajaxSaveType) {
-            $pageId = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('pageId');
+            $pageId = (int)GeneralUtility::_GP('id');
             if (!is_numeric($pageId) || $pageId < 1) {
                 return false;
             }
             // If given use the requested template_uid
             // if not, use the first template-record on the page (in this case there should only be one record!)
-            $set = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('SET');
+            $set = GeneralUtility::_GP('SET');
             $template_uid = $set['templatesOnPage'] ?: 0;
             // Defined global here!
-            $tmpl = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\ExtendedTemplateService::class);
+            $tmpl = GeneralUtility::makeInstance(ExtendedTemplateService::class);
             $tmpl->init();
             // Get the first template record on the page, which might be hidden as well
             // (for instance the TypoScript constant editor is persisting to the first template)
@@ -108,32 +78,23 @@ class TypoScriptTemplateInfoHook
             if ($existTemplate) {
                 $saveId = $tplRow['_ORIG_uid'] ?: $tplRow['uid'];
                 // Update template ?
-                $POST = \TYPO3\CMS\Core\Utility\GeneralUtility::_POST();
+                $POST = GeneralUtility::_POST();
                 if ($POST['submit']) {
                     // Set the data to be saved
                     $recData = [];
                     if (is_array($POST['data'])) {
-                        foreach ($POST['data'] as $field => $val) {
-                            switch ($field) {
-                                case 'constants':
-                                case 'config':
-                                    // Replace Windows- and Mac linebreaks
-                                    $val = str_replace([CRLF, CR], LF, $val);
-                                    $recData['sys_template'][$saveId][$field] = $val;
-                                    break;
-                            }
-                        }
+                        $recData = $POST['data'];
                     }
                     if (!empty($recData)) {
                         // process template row before saving
-                        $tstemplateinfo = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController::class);
-                        /* @var $tstemplateinfo \TYPO3\CMS\Tstemplate\Controller\TypoScriptTemplateInformationModuleFunctionController */
+                        $tstemplateinfo = GeneralUtility::makeInstance(TypoScriptTemplateInformationModuleFunctionController::class);
+                        /* @var $tstemplateinfo TypoScriptTemplateInformationModuleFunctionController */
                         // load the MOD_SETTINGS in order to check if the includeTypoScriptFileContent is set
                         $tstemplateinfo->pObj = $pObj;
-                        $tstemplateinfo->pObj->MOD_SETTINGS = \TYPO3\CMS\Backend\Utility\BackendUtility::getModuleData(['includeTypoScriptFileContent' => true], [], 'web_ts');
+                        $tstemplateinfo->pObj->MOD_SETTINGS = BackendUtility::getModuleData(['includeTypoScriptFileContent' => true], [], 'web_ts');
                         $recData['sys_template'][$saveId] = $tstemplateinfo->processTemplateRowBeforeSaving($recData['sys_template'][$saveId]);
                         // Create new tce-object
-                        $tce = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
+                        $tce = GeneralUtility::makeInstance(DataHandler::class);
                         // Initialize
                         $tce->start($recData, []);
                         // Saved the stuff
index 4a78aed..8dc6249 100644 (file)
@@ -99,13 +99,12 @@ class T3editor implements \TYPO3\CMS\Core\SingletonInterface
      * Set mode by file
      *
      * @param string $file
-     * @return string
+     * @return void
      */
     public function setModeByFile($file)
     {
         $fileInfo = GeneralUtility::split_fileref($file);
-        // @TODO: @FIXME: the method setModeByType returns void, so this method will never return a string
-        return $this->setModeByType($fileInfo['fileext']);
+        $this->setModeByType($fileInfo['fileext']);
     }
 
     /**
index 4dfb77c..25f42b8 100644 (file)
@@ -3,13 +3,10 @@ defined('TYPO3_MODE') or die();
 
 if (TYPO3_MODE === 'BE') {
     // Register hooks for tstemplate module
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'][] = \TYPO3\CMS\T3editor\Hook\TypoScriptTemplateInfoHook::class . '->preStartPageHook';
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['postOutputProcessingHook'][] = \TYPO3\CMS\T3editor\Hook\TypoScriptTemplateInfoHook::class . '->postOutputProcessingHook';
+    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['preOutputProcessingHook'][] = \TYPO3\CMS\T3editor\Hook\TypoScriptTemplateInfoHook::class . '->preOutputProcessingHook';
+    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'][] = \TYPO3\CMS\T3editor\Hook\FileEditHook::class . '->preOutputProcessingHook';
     $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode']['tx_tstemplateinfo'] = \TYPO3\CMS\T3editor\Hook\TypoScriptTemplateInfoHook::class . '->save';
     $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/t3editor/classes/class.tx_t3editor.php']['ajaxSaveCode']['file_edit'] = \TYPO3\CMS\T3editor\Hook\FileEditHook::class . '->save';
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preStartPageHook'][] = \TYPO3\CMS\T3editor\Hook\FileEditHook::class . '->preStartPageHook';
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['preOutputProcessingHook'][] = \TYPO3\CMS\T3editor\Hook\FileEditHook::class . '->preOutputProcessingHook';
-    $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/file_edit.php']['postOutputProcessingHook'][] = \TYPO3\CMS\T3editor\Hook\FileEditHook::class . '->postOutputProcessingHook';
 }
 
 $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1433089350] = [
index 72715c5..904e31d 100644 (file)
@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Tstemplate\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Backend\Form\FormResultCompiler;
+use TYPO3\CMS\Backend\Form\NodeFactory;
 use TYPO3\CMS\Backend\Module\AbstractFunctionModule;
 use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\DataHandling\DataHandler;
@@ -211,14 +213,7 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
                 $recData = [];
                 $alternativeFileName = [];
                 if (is_array($POST['data'])) {
-                    foreach ($POST['data'] as $field => $val) {
-                        switch ($field) {
-                            case 'constants':
-                            case 'config':
-                                $recData['sys_template'][$saveId][$field] = $val;
-                            break;
-                        }
-                    }
+                    $recData = $POST['data'];
                 }
                 if (!empty($recData)) {
                     $recData['sys_template'][$saveId] = $this->processTemplateRowBeforeSaving($recData['sys_template'][$saveId]);
@@ -258,31 +253,96 @@ class TypoScriptTemplateInformationModuleFunctionController extends AbstractFunc
             if ($manyTemplatesMenu) {
                 $theOutput .= '<div>' . $manyTemplatesMenu . '</div>';
             }
-            $theOutput .= '<div style="padding-top: 10px;"></div>';
             $numberOfRows = 35;
             // If abort pressed, nothing should be edited:
             if (isset($POST['_saveandclosedok'])) {
                 unset($e);
             }
+            $textareaFieldConfig = [
+                'config' => [
+                    'type' => 'text',
+                    'cols' => 48,
+                    'wrap' => 'OFF',
+                    'softref' => 'email[subst],url[subst]'
+                ],
+                'defaultExtras' => 'fixed-font: enable-tab'
+            ];
+            $formData = [
+                'databaseRow' => [
+                    'uid' => $tplRow['uid'],
+                    'pageId' => $this->pObj->id
+                ],
+                'tableName' => 'sys_template',
+                'processedTca' => [
+                    'columns' => [
+                        'pageId' => [
+                            'config' => [
+                                'type' => 'passthrough'
+                            ]
+                        ]
+                    ],
+                    'types' => [
+                        1 => [
+                            'showitem' => '',
+                        ],
+                    ],
+                ],
+                'recordTypeValue' => 1,
+                'inlineStructure' => [],
+                'renderType' => 'fullRecordContainer'
+            ];
             if (isset($e['constants'])) {
-                $outCode = '<textarea name="data[constants]" rows="' . $numberOfRows . '" wrap="off" class="text-monospace enable-tab" style="width:98%;height:70%" class="text-monospace">' . htmlspecialchars($tplRow['constants']) . '</textarea>';
-                $outCode .= '<input type="hidden" name="e[constants]" value="1">';
-                // Display "Include TypoScript file content?" checkbox
-                $outCode .= '<div class="checkbox"><label for="checkIncludeTypoScriptFileContent">' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[includeTypoScriptFileContent]', $this->pObj->MOD_SETTINGS['includeTypoScriptFileContent'], '', '&e[constants]=1', 'id="checkIncludeTypoScriptFileContent"');
-                $outCode .= $lang->getLL('includeTypoScriptFileContent') . '</label></div><br />';
-                $theOutput .= '<div style="padding-top: 15px;"></div>';
-                $theOutput .= '<h3>' . htmlspecialchars($lang->getLL('constants')) . '</h3>';
-                $theOutput .= $outCode;
+                $formData['databaseRow']['constants'] = $tplRow['constants'];
+                $formData['processedTca']['columns']['constants'] = array_merge_recursive(
+                    $textareaFieldConfig,
+                    [
+                        'label' => $lang->getLL('constants'),
+                        'config' => [
+                            'rows' => min($numberOfRows, substr_count($tplRow['constants'], LF))
+                        ]
+                    ]
+                );
             }
             if (isset($e['config'])) {
-                $outCode = '<textarea name="data[config]" rows="' . $numberOfRows . '" wrap="off" class="text-monospace enable-tab" style="width:98%;height:70%" class="text-monospace">' . htmlspecialchars($tplRow['config']) . '</textarea>';
-                $outCode .= '<input type="hidden" name="e[config]" value="1">';
-                // Display "Include TypoScript file content?" checkbox
-                $outCode .= '<div class="checkbox"><label for="checkIncludeTypoScriptFileContent">' . BackendUtility::getFuncCheck($this->pObj->id, 'SET[includeTypoScriptFileContent]', $this->pObj->MOD_SETTINGS['includeTypoScriptFileContent'], '', '&e[config]=1', 'id="checkIncludeTypoScriptFileContent"');
-                $outCode .= $lang->getLL('includeTypoScriptFileContent') . '</label></div><br />';
-                $theOutput .= '<div style="padding-top: 15px;"></div>';
-                $theOutput .= '<h3>' . htmlspecialchars($lang->getLL('setup')) . '</h3>';
-                $theOutput .= $outCode;
+                $formData['databaseRow']['config'] = $tplRow['config'];
+                $formData['processedTca']['columns']['config'] = array_merge_recursive(
+                    $textareaFieldConfig,
+                    [
+                        'label' => $lang->getLL('setup'),
+                        'config' => [
+                            'rows' => min($numberOfRows, substr_count($tplRow['config'], LF))
+                        ]
+                    ]
+                );
+            }
+
+            // Hook before compiling the output
+            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['preOutputProcessingHook'])) {
+                $preOutputProcessingHook = &$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/tstemplate_info/class.tx_tstemplateinfo.php']['preOutputProcessingHook'];
+                if (is_array($preOutputProcessingHook)) {
+                    $hookParameters = [
+                        'formData' => &$formData
+                    ];
+                    foreach ($preOutputProcessingHook as $hookFunction) {
+                        GeneralUtility::callUserFunction($hookFunction, $hookParameters, $this);
+                    }
+                }
+            }
+
+            if (!empty($formData['processedTca']['columns'])) {
+                $formData['processedTca']['types'][1]['showitem'] = implode(',', array_keys($formData['processedTca']['columns']));
+
+                $resultArray = GeneralUtility::makeInstance(NodeFactory::class)->create($formData)->render();
+                $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
+                $formResultCompiler->mergeResult($resultArray);
+
+                $theOutput .= $formResultCompiler->JStop()
+                    . $formResultCompiler->printNeededJSFunctions()
+                    . $resultArray['html'];
+                $theOutput .= '<div class="checkbox"><label for="checkIncludeTypoScriptFileContent">' . BackendUtility::getFuncCheck($this->pObj->id,
+                    'SET[includeTypoScriptFileContent]', $this->pObj->MOD_SETTINGS['includeTypoScriptFileContent'],
+                    '', GeneralUtility::implodeArrayForUrl('', ['e' => $this->pObj->e]), 'id="checkIncludeTypoScriptFileContent"');
+                $theOutput .= $lang->getLL('includeTypoScriptFileContent') . '</label></div><br />';
             }
 
             // Processing:
index 84a3b31..4bdc4da 100644 (file)
@@ -168,7 +168,8 @@ class TypoScriptTemplateModuleController extends BaseScriptClass
         if ($this->id && $this->access) {
             $urlParameters = [
                 'id' => $this->id,
-                'template' => 'all'
+                'template' => 'all',
+                'e' => $this->e
             ];
             $aHref = BackendUtility::getModuleUrl('web_ts', $urlParameters);