[!!!][FEATURE] inline backend layout wizard 63/47563/5
authorFrank Naegler <frank.naegler@typo3.org>
Mon, 11 Apr 2016 10:37:47 +0000 (12:37 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Mon, 11 Apr 2016 20:53:30 +0000 (22:53 +0200)
A new renderType was added to render the backend layout wizard inline
in FormEngine.

Resolves: #75497
Releases: master
Change-Id: If26ff91e2c35a692f27b4fd55debbc69027d754a
Reviewed-on: https://review.typo3.org/47563
Tested-by: Susanne Moog <typo3@susannemoog.de>
Reviewed-by: Susanne Moog <typo3@susannemoog.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
12 files changed:
Build/Resources/Public/Less/TYPO3/_main_backend_layout_wizard.less
typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php [deleted file]
typo3/sysext/backend/Classes/View/Wizard/Element/BackendLayoutWizardElement.php [new file with mode: 0644]
typo3/sysext/backend/Configuration/Backend/Routes.php
typo3/sysext/backend/Resources/Private/Language/locallang.xlf
typo3/sysext/backend/Resources/Public/JavaScript/GridEditor.js
typo3/sysext/backend/ext_localconf.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-75497-InlineBackendLayoutWizard.rst [new file with mode: 0644]
typo3/sysext/core/Documentation/Changelog/master/Feature-75497-InlineBackendLayoutWizard.rst [new file with mode: 0644]
typo3/sysext/frontend/Configuration/TCA/backend_layout.php
typo3/sysext/frontend/Resources/Private/Language/locallang_tca.xlf
typo3/sysext/t3skin/Resources/Public/Css/backend.css

index 830d5aa..7761bf2 100644 (file)
                opacity: 0.5;
        }
 
+       .grideditor-preview {
+               margin-top: 5px;
+       }
+
        .link {
                display: block;
                position: absolute;
diff --git a/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php b/typo3/sysext/backend/Classes/Controller/BackendLayoutWizardController.php
deleted file mode 100644 (file)
index c54cc03..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-<?php
-namespace TYPO3\CMS\Backend\Controller;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use TYPO3\CMS\Backend\Module\AbstractModule;
-use TYPO3\CMS\Backend\Template\Components\ButtonBar;
-use TYPO3\CMS\Backend\Utility\BackendUtility;
-use TYPO3\CMS\Core\Imaging\Icon;
-use TYPO3\CMS\Core\Page\PageRenderer;
-use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-
-/**
- * Script Class for grid wizard
- */
-class BackendLayoutWizardController extends AbstractModule
-{
-    /**
-     * GET vars:
-     * Wizard parameters, coming from TCEforms linking to the wizard.
-     * @var array
-     */
-    public $P;
-
-    /**
-     * Accumulated content.
-     * @var string
-     */
-    public $content;
-
-    /**
-     * @var string
-     */
-    public $formName;
-
-    /**
-     * @var string
-     */
-    public $fieldName;
-
-    /**
-     * @var array
-     */
-    protected $rows;
-
-    /**
-     * @var int
-     */
-    protected $colCount;
-
-    /**
-     * @var int
-     */
-    protected $rowCount;
-
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        parent::__construct();
-        $this->init();
-    }
-
-    /**
-     * Initialises the Class
-     *
-     * @return void
-     * @throws \InvalidArgumentException
-     */
-    public function init()
-    {
-        $lang = $this->getLanguageService();
-        $lang->includeLLFile('EXT:lang/locallang_wizards.xlf');
-
-        // Setting GET vars (used in frameset script):
-        $this->P = GeneralUtility::_GP('P');
-        $this->formName = $this->P['formName'];
-        $this->fieldName = $this->P['itemName'];
-        $hmac_validate = GeneralUtility::hmac($this->formName . $this->fieldName, 'wizard_js');
-        if (!$this->P['hmac'] || ($this->P['hmac'] !== $hmac_validate)) {
-            throw new \InvalidArgumentException('Hmac Validation failed for backend_layout wizard', 1385811397);
-        }
-        $uid = (int)$this->P['uid'];
-
-        /** @var \TYPO3\CMS\Core\Page\PageRenderer $pageRenderer */
-        $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
-        $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/GridEditor');
-        $pageRenderer->addInlineSetting(
-            'ContextHelp',
-            'moduleUrl',
-            BackendUtility::getModuleUrl(
-                'help_CshmanualCshmanual',
-                array(
-                    'tx_cshmanual_help_cshmanualcshmanual' => array(
-                        'controller' => 'Help',
-                        'action' => 'detail'
-                    )
-                )
-            )
-        );
-        $pageRenderer->addJsInlineCode('storeData', '
-            function storeData(data) {
-                if (parent.opener && parent.opener.document && parent.opener.document.' . $this->formName
-                . ' && parent.opener.document.' . $this->formName . '['
-                    . GeneralUtility::quoteJSvalue($this->fieldName) . ']) {
-                    parent.opener.document.' . $this->formName . '['
-                    . GeneralUtility::quoteJSvalue($this->fieldName) . '].value = data;
-                    parent.opener.TBE_EDITOR.fieldChanged("backend_layout","' . $uid . '","config",'
-                    . '"data[backend_layout][' . $uid . '][config]");
-                }
-            }
-            ', false);
-        $languageLabels = array(
-            'save' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_labelSave')),
-            'title' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_windowTitle')),
-            'editCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_editCell')),
-            'mergeCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_mergeCell')),
-            'splitCell' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_splitCell')),
-            'name' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_name')),
-            'column' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_column')),
-            'notSet' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_notSet')),
-            'nameHelp' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_nameHelp')),
-            'columnHelp' => htmlspecialchars($lang->sL('LLL:EXT:lang/locallang_wizards.xlf:grid_columnHelp'))
-        );
-        $pageRenderer->addInlineLanguageLabelArray($languageLabels);
-        // Select record
-        $record = $this->getDatabaseConnection()->exec_SELECTgetRows(
-            $this->P['field'],
-            $this->P['table'],
-            'uid=' . (int)$this->P['uid']
-        );
-        if (trim($record[0][$this->P['field']]) == '') {
-            $rows = array(array(array('colspan' => 1, 'rowspan' => 1, 'spanned' => false, 'name' => '')));
-            $colCount = 1;
-            $rowCount = 1;
-        } else {
-            // load TS parser
-            $parser = GeneralUtility::makeInstance(TypoScriptParser::class);
-            $parser->parse($record[0][$this->P['field']]);
-            $data = $parser->setup['backend_layout.'];
-            $rows = array();
-            $colCount = $data['colCount'];
-            $rowCount = $data['rowCount'];
-            $dataRows = $data['rows.'];
-            $spannedMatrix = array();
-            for ($i = 1; $i <= $rowCount; $i++) {
-                $cells = array();
-                $row = array_shift($dataRows);
-                $columns = $row['columns.'];
-                for ($j = 1; $j <= $colCount; $j++) {
-                    $cellData = array();
-                    if (!$spannedMatrix[$i][$j]) {
-                        if (is_array($columns) && !empty($columns)) {
-                            $column = array_shift($columns);
-                            if (isset($column['colspan'])) {
-                                $cellData['colspan'] = (int)$column['colspan'];
-                                $columnColSpan = (int)$column['colspan'];
-                                if (isset($column['rowspan'])) {
-                                    $columnRowSpan = (int)$column['rowspan'];
-                                    for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
-                                        for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
-                                            $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1;
-                                        }
-                                    }
-                                } else {
-                                    for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
-                                        $spannedMatrix[$i][$j + $spanColumn] = 1;
-                                    }
-                                }
-                            } else {
-                                $cellData['colspan'] = 1;
-                                if (isset($column['rowspan'])) {
-                                    $columnRowSpan = (int)$column['rowspan'];
-                                    for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
-                                        $spannedMatrix[$i + $spanRow][$j] = 1;
-                                    }
-                                }
-                            }
-                            if (isset($column['rowspan'])) {
-                                $cellData['rowspan'] = (int)$column['rowspan'];
-                            } else {
-                                $cellData['rowspan'] = 1;
-                            }
-                            if (isset($column['name'])) {
-                                $cellData['name'] = $column['name'];
-                            }
-                            if (isset($column['colPos'])) {
-                                $cellData['column'] = (int)$column['colPos'];
-                            }
-                        }
-                    } else {
-                        $cellData = array('colspan' => 1, 'rowspan' => 1, 'spanned' => 1);
-                    }
-                    $cells[] = $cellData;
-                }
-                $rows[] = $cells;
-                if (!empty($spannedMatrix[$i]) && is_array($spannedMatrix[$i])) {
-                    ksort($spannedMatrix[$i]);
-                }
-            }
-        }
-        $this->rows = $rows;
-        $this->colCount = (int)$colCount;
-        $this->rowCount = (int)$rowCount;
-    }
-
-    /**
-     * Injects the request object for the current request or subrequest
-     * As this controller goes only through the main() method, it is rather simple for now
-     *
-     * @param ServerRequestInterface $request
-     * @param ResponseInterface $response
-     * @return ResponseInterface
-     */
-    public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
-    {
-        $this->main();
-
-        $this->setPagePath($this->P['table'], $this->P['uid']);
-
-        $this->moduleTemplate->setContent($this->content);
-        $response->getBody()->write($this->moduleTemplate->renderContent());
-        return $response;
-    }
-
-    /**
-     * Creates the correct path to the current record
-     *
-     * @param string $table
-     * @param int $uid
-     */
-    protected function setPagePath($table, $uid)
-    {
-        $uid = (int)$uid;
-
-        if ($table === 'pages') {
-            $pageId = $uid;
-        } else {
-            $record = BackendUtility::getRecord($table, $uid, '*', '', false);
-            $pageId = $record['pid'];
-        }
-
-        $pageAccess = BackendUtility::readPageAccess($pageId, $this->getBackendUser()->getPagePermsClause(1));
-        if (is_array($pageAccess)) {
-            $this->moduleTemplate->getDocHeaderComponent()->setMetaInformation($pageAccess);
-        }
-    }
-
-    /**
-     * Main Method, rendering either colorpicker or frameset depending on ->showPicker
-     *
-     * @return void
-     */
-    public function main()
-    {
-        $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
-        $lang = $this->getLanguageService();
-
-        $saveButton = $buttonBar->makeInputButton()
-            ->setName('_savedok')
-            ->setValue('1')
-            ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc'))
-            ->setClasses('t3js-grideditor-savedok')
-            ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL));
-
-        $saveAndCloseButton = $buttonBar->makeInputButton()
-            ->setName('_savedokandclose')
-            ->setValue('1')
-            ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc'))
-            ->setClasses('t3js-grideditor-savedokclose')
-            ->setIcon(
-                $this->moduleTemplate->getIconFactory()->getIcon('actions-document-save-close', Icon::SIZE_SMALL)
-            );
-
-        $splitButton = $buttonBar->makeSplitButton()
-            ->addItem($saveButton)
-            ->addItem($saveAndCloseButton);
-        $buttonBar->addButton($splitButton);
-
-        $closeButton = $buttonBar->makeLinkButton()
-            ->setHref('#')
-            ->setTitle($lang->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc'))
-            ->setOnClick('window.close();return true;')
-            ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL));
-        $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 30);
-
-        $markup = array();
-        $markup[] = '';
-        $markup[] = '<table class="grideditor table table-bordered"">';
-        $markup[] = '    <tr>';
-        $markup[] = '        <td class="editor_cell">';
-        $markup[] = '           <div id="editor" class="t3js-grideditor" data-data="' . htmlspecialchars(
-            json_encode(
-                $this->rows,
-                JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS
-            )
-        ) . '" '
-        . 'data-rowcount="' . (int)$this->rowCount . '" '
-        . 'data-colcount="' . (int)$this->colCount . '">';
-        $markup[] = '            </div>';
-        $markup[] = '        </td>';
-        $markup[] = '        <td>';
-        $markup[] = '            <div class="btn-group-vertical">';
-        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-addcolumn" href="#" title="'
-            . htmlspecialchars($lang->getLL('grid_addColumn')) . '">';
-        $markup[] = '                <i class="fa fa-fw fa-arrow-right"></i>';
-        $markup[] = '               </a>';
-        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-removecolumn" href="#" title="'
-            . htmlspecialchars($lang->getLL('grid_removeColumn')) . '">';
-        $markup[] = '                <i class="fa fa-fw fa-arrow-left"></i>';
-        $markup[] = '               </a>';
-        $markup[] = '            </div>';
-        $markup[] = '        </td>';
-        $markup[] = '    </tr>';
-        $markup[] = '    <tr>';
-        $markup[] = '        <td colspan="2" align="center">';
-        $markup[] = '            <div class="btn-group">';
-        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-addrow" href="#" title="'
-            . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
-        $markup[] = '                <i class="fa fa-fw fa-arrow-down"></i>';
-        $markup[] = '               </a>';
-        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-removerow" href="#" title="'
-            . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
-        $markup[] = '                <i class="fa fa-fw fa-arrow-up"></i>';
-        $markup[] = '               </a>';
-        $markup[] = '            </div>';
-        $markup[] = '        </td>';
-        $markup[] = '    </tr>';
-        $markup[] = '</table>';
-
-        $this->content .= implode(LF, $markup);
-    }
-
-    /**
-     * Returns LanguageService
-     *
-     * @return \TYPO3\CMS\Lang\LanguageService
-     */
-    protected function getLanguageService()
-    {
-        return $GLOBALS['LANG'];
-    }
-
-    /**
-     * Returns the database connection
-     *
-     * @return \TYPO3\CMS\Core\Database\DatabaseConnection
-     */
-    protected function getDatabaseConnection()
-    {
-        return $GLOBALS['TYPO3_DB'];
-    }
-
-    /**
-     * Gets the current backend user.
-     *
-     * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
-     */
-    protected function getBackendUser()
-    {
-        return $GLOBALS['BE_USER'];
-    }
-}
diff --git a/typo3/sysext/backend/Classes/View/Wizard/Element/BackendLayoutWizardElement.php b/typo3/sysext/backend/Classes/View/Wizard/Element/BackendLayoutWizardElement.php
new file mode 100644 (file)
index 0000000..fe395fb
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+namespace TYPO3\CMS\Backend\View\Wizard\Element;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
+use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Class BackendLayoutWizardElement
+ */
+class BackendLayoutWizardElement extends AbstractFormElement
+{
+
+    /**
+     * @var array
+     */
+    protected $resultArray = [];
+
+    /**
+     * @var array
+     */
+    protected $rows = [];
+
+    /**
+     * @var int
+     */
+    protected $colCount = 0;
+
+    /**
+     * @var int
+     */
+    protected $rowCount = 0;
+
+    /**
+     * @return array
+     */
+    public function render()
+    {
+        $this->resultArray = $this->initializeResultArray();
+        $this->init();
+
+        $lang = $this->getLanguageService();
+
+        $json = json_encode($this->rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS);
+        $markup = [];
+        $markup[] = '<input type="hidden" name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName'])
+            . '" value="' . htmlspecialchars($this->data['parameterArray']['itemFormElValue']) . '" />';
+        $markup[] = '<table class="grideditor table table-bordered">';
+        $markup[] = '    <tr>';
+        $markup[] = '        <td class="editor_cell">';
+        $markup[] = '           <div id="editor" class="t3js-grideditor" data-data="' . htmlspecialchars($json) . '" '
+            . 'data-rowcount="' . (int)$this->rowCount . '" '
+            . 'data-colcount="' . (int)$this->colCount . '" '
+            . 'data-field="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '" '
+            . '>';
+        $markup[] = '            </div>';
+        $markup[] = '        </td>';
+        $markup[] = '        <td>';
+        $markup[] = '            <div class="btn-group-vertical">';
+        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-addcolumn" href="#" title="'
+            . htmlspecialchars($lang->getLL('grid_addColumn')) . '">';
+        $markup[] = '                <i class="fa fa-fw fa-arrow-right"></i>';
+        $markup[] = '               </a>';
+        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-removecolumn" href="#" title="'
+            . htmlspecialchars($lang->getLL('grid_removeColumn')) . '">';
+        $markup[] = '                <i class="fa fa-fw fa-arrow-left"></i>';
+        $markup[] = '               </a>';
+        $markup[] = '            </div>';
+        $markup[] = '        </td>';
+        $markup[] = '    </tr>';
+        $markup[] = '    <tr>';
+        $markup[] = '        <td colspan="2" align="center">';
+        $markup[] = '            <div class="btn-group">';
+        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-addrow" href="#" title="'
+            . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
+        $markup[] = '                <i class="fa fa-fw fa-arrow-down"></i>';
+        $markup[] = '               </a>';
+        $markup[] = '               <a class="btn btn-default btn-sm t3js-grideditor-removerow" href="#" title="'
+            . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
+        $markup[] = '                <i class="fa fa-fw fa-arrow-up"></i>';
+        $markup[] = '               </a>';
+        $markup[] = '            </div>';
+        $markup[] = '        </td>';
+        $markup[] = '    </tr>';
+        $markup[] = '    <tr>';
+        $markup[] = '        <td colspan="2">';
+        $markup[] = '            <a href="#" class="btn btn-default btn-sm t3js-grideditor-preview-button"></a>';
+        $markup[] = '            <pre class="t3js-grideditor-preview-config grideditor-preview"><code></code></pre>';
+        $markup[] = '        </td>';
+        $markup[] = '    </tr>';
+        $markup[] = '</table>';
+
+        $content = implode(LF, $markup);
+        $this->resultArray['html'] = $content;
+        $this->resultArray['requireJsModules'][] = 'TYPO3/CMS/Backend/GridEditor';
+        $this->resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:lang/locallang_wizards.xlf';
+        $this->resultArray['additionalInlineLanguageLabelFiles'][]
+            = 'EXT:backend/Resources/Private/Language/locallang.xlf';
+
+        return $this->resultArray;
+    }
+
+    /**
+     * Initialize wizard
+     */
+    protected function init()
+    {
+        if (empty($this->data['databaseRow']['config'])) {
+            $rows = [[['colspan' => 1, 'rowspan' => 1, 'spanned' => false, 'name' => '']]];
+            $colCount = 1;
+            $rowCount = 1;
+        } else {
+            // load TS parser
+            $parser = GeneralUtility::makeInstance(TypoScriptParser::class);
+            $parser->parse($this->data['databaseRow']['config']);
+            $data = $parser->setup['backend_layout.'];
+            $rows = [];
+            $colCount = $data['colCount'];
+            $rowCount = $data['rowCount'];
+            $dataRows = $data['rows.'];
+            $spannedMatrix = [];
+            for ($i = 1; $i <= $rowCount; $i++) {
+                $cells = [];
+                $row = array_shift($dataRows);
+                $columns = $row['columns.'];
+                for ($j = 1; $j <= $colCount; $j++) {
+                    $cellData = [];
+                    if (!$spannedMatrix[$i][$j]) {
+                        if (is_array($columns) && !empty($columns)) {
+                            $column = array_shift($columns);
+                            if (isset($column['colspan'])) {
+                                $cellData['colspan'] = (int)$column['colspan'];
+                                $columnColSpan = (int)$column['colspan'];
+                                if (isset($column['rowspan'])) {
+                                    $columnRowSpan = (int)$column['rowspan'];
+                                    for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
+                                        for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
+                                            $spannedMatrix[$i + $spanRow][$j + $spanColumn] = 1;
+                                        }
+                                    }
+                                } else {
+                                    for ($spanColumn = 0; $spanColumn < $columnColSpan; $spanColumn++) {
+                                        $spannedMatrix[$i][$j + $spanColumn] = 1;
+                                    }
+                                }
+                            } else {
+                                $cellData['colspan'] = 1;
+                                if (isset($column['rowspan'])) {
+                                    $columnRowSpan = (int)$column['rowspan'];
+                                    for ($spanRow = 0; $spanRow < $columnRowSpan; $spanRow++) {
+                                        $spannedMatrix[$i + $spanRow][$j] = 1;
+                                    }
+                                }
+                            }
+                            if (isset($column['rowspan'])) {
+                                $cellData['rowspan'] = (int)$column['rowspan'];
+                            } else {
+                                $cellData['rowspan'] = 1;
+                            }
+                            if (isset($column['name'])) {
+                                $cellData['name'] = $column['name'];
+                            }
+                            if (isset($column['colPos'])) {
+                                $cellData['column'] = (int)$column['colPos'];
+                            }
+                        }
+                    } else {
+                        $cellData = ['colspan' => 1, 'rowspan' => 1, 'spanned' => 1];
+                    }
+                    $cells[] = $cellData;
+                }
+                $rows[] = $cells;
+                if (!empty($spannedMatrix[$i]) && is_array($spannedMatrix[$i])) {
+                    ksort($spannedMatrix[$i]);
+                }
+            }
+        }
+        $this->rows = $rows;
+        $this->colCount = (int)$colCount;
+        $this->rowCount = (int)$rowCount;
+    }
+}
index 60d1e8f..e622785 100644 (file)
@@ -38,12 +38,6 @@ return [
     ],
 
     /** Wizards */
-    // Register backend_layout wizard
-    'wizard_backend_layout' => [
-        'path' => '/wizard/backend_layout',
-        'target' => Controller\BackendLayoutWizardController::class . '::mainAction'
-    ],
-
     // Register colorpicker wizard
     'wizard_colorpicker' => [
         'path' => '/wizard/colorpicker',
index ef6538a..a40bd93 100644 (file)
@@ -85,6 +85,12 @@ Have a nice day.</source>
                        <trans-unit id="login.donate">
                                <source>Donate</source>
                        </trans-unit>
+                       <trans-unit id="button.showPageTsConfig">
+                               <source>Show PageTS-Config</source>
+                       </trans-unit>
+                       <trans-unit id="button.hidePageTsConfig">
+                               <source>Hide PageTS-Config</source>
+                       </trans-unit>
                </body>
        </file>
 </xliff>
index 8c94237..a558b43 100644 (file)
@@ -20,7 +20,7 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
        /**
         * The main ContextHelp object
         *
-        * @type {{colCount: number, rowCount: number, data: {}, nameLabel: string, columnLabel: string, targetElement: null}}
+        * @type {{selectorEditor: string, selectorAddColumn: string, selectorRemoveColumn: string, selectorAddRow: string, selectorRemoveRow: string, selectorLinkEditor: string, selectorLinkExpandRight: string, selectorLinkShrinkLeft: string, selectorLinkExpandDown: string, selectorLinkShrinkUp: string, selectorDocHeaderSave: string, selectorDocHeaderSaveClose: string, selectorConfigPreview: string, selectorConfigPreviewButton: string, colCount: number, rowCount: number, field: string, data: Array, nameLabel: string, columnLabel: string, targetElement: null}}
         * @exports TYPO3/CMS/Backend/GridEditor
         */
        var GridEditor = {
@@ -36,8 +36,11 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                selectorLinkShrinkUp: '.t3js-grideditor-link-shrink-up',
                selectorDocHeaderSave: '.t3js-grideditor-savedok',
                selectorDocHeaderSaveClose: '.t3js-grideditor-savedokclose',
+               selectorConfigPreview: '.t3js-grideditor-preview-config',
+               selectorConfigPreviewButton: '.t3js-grideditor-preview-button',
                colCount: 1,
                rowCount: 1,
+               field: '',
                data: [],
                nameLabel: 'name',
                columnLabel: 'columen label',
@@ -53,39 +56,36 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                var $element = $(GridEditor.selectorEditor);
                GridEditor.colCount = $element.data('colcount');
                GridEditor.rowCount = $element.data('rowcount');
+               GridEditor.field = $('input[name="' + $element.data('field') + '"]');
                GridEditor.data = $element.data('data');
                GridEditor.nameLabel = config.nameLabel || 'Name';
                GridEditor.columnLabel = config.columnLabel || 'Column';
                GridEditor.targetElement = $(GridEditor.selectorEditor);
+               $(GridEditor.selectorConfigPreview).hide();
 
-               $(document).on('click', GridEditor.selectorDocHeaderSave, function(e) {
-                       e.preventDefault();
-                       storeData(GridEditor.export2LayoutRecord());
-               });
-               $(document).on('click', GridEditor.selectorDocHeaderSaveClose, function(e) {
-                       e.preventDefault();
-                       storeData(GridEditor.export2LayoutRecord());
-                       window.close();
-               });
                $(document).on('click', GridEditor.selectorAddColumn, function(e) {
                        e.preventDefault();
                        GridEditor.addColumn();
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorRemoveColumn, function(e) {
                        e.preventDefault();
                        GridEditor.removeColumn();
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorAddRow, function(e) {
                        e.preventDefault();
                        GridEditor.addRow();
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorRemoveRow, function(e) {
                        e.preventDefault();
                        GridEditor.removeRow();
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorLinkEditor, function(e) {
                        e.preventDefault();
@@ -101,6 +101,7 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                        var row = $element.data('row');
                        GridEditor.addColspan(col, row);
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorLinkShrinkLeft, function(e) {
                        e.preventDefault();
@@ -109,6 +110,7 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                        var row = $element.data('row');
                        GridEditor.removeColspan(col, row);
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorLinkExpandDown, function(e) {
                        e.preventDefault();
@@ -117,6 +119,7 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                        var row = $element.data('row');
                        GridEditor.addRowspan(col, row);
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
                });
                $(document).on('click', GridEditor.selectorLinkShrinkUp, function(e) {
                        e.preventDefault();
@@ -125,9 +128,53 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                        var row = $element.data('row');
                        GridEditor.removeRowspan(col, row);
                        GridEditor.drawTable();
+                       GridEditor.writeConfig(GridEditor.export2LayoutRecord());
+               });
+
+               $(GridEditor.selectorConfigPreviewButton).empty().append(TYPO3.lang['button.showPageTsConfig']);
+               $(document).on('click', GridEditor.selectorConfigPreviewButton, function(e) {
+                       e.preventDefault();
+                       var $preview = $(GridEditor.selectorConfigPreview);
+                       var $button = $(GridEditor.selectorConfigPreviewButton);
+                       if ($preview.is(':visible')) {
+                               $button.empty().append(TYPO3.lang['button.showPageTsConfig']);
+                               $(GridEditor.selectorConfigPreview).slideUp();
+                       } else {
+                               $button.empty().append(TYPO3.lang['button.hidePageTsConfig']);
+                               $(GridEditor.selectorConfigPreview).slideDown();
+                       }
+
                });
 
                GridEditor.drawTable();
+               GridEditor.writeConfig(GridEditor.export2LayoutRecord());
+       };
+
+       /**
+        * write data back to hidden field
+        *
+        * @param data
+        */
+       GridEditor.writeConfig = function(data) {
+               GridEditor.field.val(data);
+               var configLines = data.split('\n');
+               var config = '';
+               for (var i=0; i<configLines.length; i++) {
+                       if (configLines[i].length) {
+                               config += '\t\t\t' + configLines[i] + '\n';
+                       }
+               }
+               $(GridEditor.selectorConfigPreview).find('code').empty().append(
+                       'mod.web_layout.BackendLayouts {\n' +
+                       '  exampleKey {\n' +
+                       '    title = Example\n' +
+                       '    icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif\n' +
+                       '    config {\n' +
+                       config.replace(new RegExp('\t', 'g'), '  ') +
+                       '    }\n' +
+                       '  }\n' +
+                       '}\n'
+               );
        };
 
        /**
@@ -285,22 +332,22 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                                var $container = $('<div class="cell_container">');
                                $cell.append($container);
                                var dataString = ' data-col="' + col + '" data-row="' + row + '"';
-                               $container.append($('<a class="t3js-grideditor-link-editor link link_editor" title="' + TYPO3.lang['editCell'] + '" ' + dataString + '  href="#"><!-- --></a>'));
+                               $container.append($('<a class="t3js-grideditor-link-editor link link_editor" title="' + TYPO3.lang['grid_editCell'] + '" ' + dataString + '  href="#"><!-- --></a>'));
                                if (GridEditor.cellCanSpanRight(col, row)) {
-                                       $container.append($('<a class="t3js-grideditor-link-expand-right link link_expand_right" href="#"  title="' + TYPO3.lang['mergeCell'] + '" ' + dataString + '><!-- --></a>'));
+                                       $container.append($('<a class="t3js-grideditor-link-expand-right link link_expand_right" href="#"  title="' + TYPO3.lang['grid_mergeCell'] + '" ' + dataString + '><!-- --></a>'));
                                }
                                if (GridEditor.cellCanShrinkLeft(col, row)) {
-                                       $container.append('<a class="t3js-grideditor-link-shrink-left link link_shrink_left" href="#" title="' + TYPO3.lang['splitCell'] + '" ' + dataString + '><!-- --></a>');
+                                       $container.append('<a class="t3js-grideditor-link-shrink-left link link_shrink_left" href="#" title="' + TYPO3.lang['grid_splitCell'] + '" ' + dataString + '><!-- --></a>');
                                }
                                if (GridEditor.cellCanSpanDown(col, row)) {
-                                       $container.append('<a class="t3js-grideditor-link-expand-down link link_expand_down" href="#" title="' + TYPO3.lang['mergeCell'] + '" ' + dataString + '><!-- --></a>');
+                                       $container.append('<a class="t3js-grideditor-link-expand-down link link_expand_down" href="#" title="' + TYPO3.lang['grid_mergeCell'] + '" ' + dataString + '><!-- --></a>');
                                }
                                if (GridEditor.cellCanShrinkUp(col, row)) {
-                                       $container.append('<a class="t3js-grideditor-link-shrink-up link link_shrink_up" href="#" title="' + TYPO3.lang['splitCell'] + '" ' + dataString + '><!-- --></a>');
+                                       $container.append('<a class="t3js-grideditor-link-shrink-up link link_shrink_up" href="#" title="' + TYPO3.lang['grid_splitCell'] + '" ' + dataString + '><!-- --></a>');
                                }
-                               $cell.append('<div class="cell_data">' + TYPO3.lang['name'] + ': ' + (cell.name ? GridEditor.stripMarkup(cell.name) : TYPO3.lang['notSet'])
-                                       + '<br />' + TYPO3.lang['column'] + ': '
-                                       + (cell.column === undefined ? TYPO3.lang['notSet'] : parseInt(cell.column, 10)) + '</div>');
+                               $cell.append('<div class="cell_data">' + TYPO3.lang['grid_name'] + ': ' + (cell.name ? GridEditor.stripMarkup(cell.name) : TYPO3.lang['grid_notSet'])
+                                       + '<br />' + TYPO3.lang['grid_column'] + ': '
+                                       + (cell.column === undefined ? TYPO3.lang['grid_notSet'] : parseInt(cell.column, 10)) + '</div>');
 
                                if (cell.colspan > 1) {
                                        $cell.attr('colspan', cell.colspan);
@@ -367,20 +414,29 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                        return false;
                }
 
+               var colPos;
+               if (cell.column === 0) {
+                       colPos = 0;
+               } else if(parseInt(cell.column, 10)) {
+                       colPos = parseInt(cell.column, 10);
+               } else {
+                       colPos = '';
+               }
+
                var $markup = $('<div>');
                $markup.append(
                        '<div>' +
                                '<div class="form-group">' +
-                                       '<label>' + TYPO3.lang['nameHelp'] + '</label>' +
+                                       '<label>' + TYPO3.lang['grid_nameHelp'] + '</label>' +
                                        '<input type="text" class="t3js-grideditor-field-name form-control" name="name" value="' + (GridEditor.stripMarkup(cell.name) || '') + '">' +
                                '</div>' +
                                '<div class="form-group">' +
-                                       '<label>' + TYPO3.lang['columnHelp'] + '</label>' +
-                                       '<input type="text" class="t3js-grideditor-field-colpos form-control" name="name" value="' + (parseInt(cell.column, 10) || '') + '">' +
+                                       '<label>' + TYPO3.lang['grid_columnHelp'] + '</label>' +
+                                       '<input type="text" class="t3js-grideditor-field-colpos form-control" name="name" value="' + colPos + '">' +
                                '</div>' +
                        '</div>'
                );
-               var $modal = Modal.show(TYPO3.lang['title'], $markup, Severity.notice, [
+               var $modal = Modal.show(TYPO3.lang['grid_windowTitle'], $markup, Severity.notice, [
                        {
                                text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
                                active: true,
@@ -397,12 +453,13 @@ define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity', 'boot
                $modal.data('row', row);
                $modal.on('button.clicked', function(e) {
                        if (e.target.name === 'cancel') {
-                               $(this).trigger('modal-dismiss');
+                               Modal.currentModal.trigger('modal-dismiss');
                        } else if (e.target.name === 'ok') {
                                GridEditor.setName($modal.find('.t3js-grideditor-field-name').val(), $modal.data('col'), $modal.data('row'));
                                GridEditor.setColumn($modal.find('.t3js-grideditor-field-colpos').val(), $modal.data('col'), $modal.data('row'));
                                GridEditor.drawTable();
-                               $(this).trigger('modal-dismiss');
+                               GridEditor.writeConfig(GridEditor.export2LayoutRecord());
+                               Modal.currentModal.trigger('modal-dismiss');
                        }
                });
        };
index 9535b56..3a85e44 100644 (file)
@@ -26,6 +26,12 @@ if (TYPO3_MODE === 'BE') {
     $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['avatarProviders']['defaultAvatarProvider'] = array(
         'provider' => \TYPO3\CMS\Backend\Backend\Avatar\DefaultAvatarProvider::class
     );
+
+    $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1460321142] = array(
+        'nodeName' => 'belayoutwizard',
+        'priority' => 40,
+        'class' => \TYPO3\CMS\Backend\View\Wizard\Element\BackendLayoutWizardElement::class,
+    );
 }
 
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default'] = \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController::class;
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-75497-InlineBackendLayoutWizard.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-75497-InlineBackendLayoutWizard.rst
new file mode 100644 (file)
index 0000000..ab562ec
--- /dev/null
@@ -0,0 +1,28 @@
+===============================================
+Breaking: #75497 - inline backend layout wizard
+===============================================
+
+Description
+===========
+
+The ``BackendLayoutWizardController`` has been removed and a new renderType has been added to render the backend layout wizard inline in FormEngine.
+
+Also the backend route ``wizard_backend_layout`` has been removed.
+
+
+Impact
+======
+
+Extending or using the ``BackendLayoutWizardController`` will break your installation.
+
+
+Affected Installations
+======================
+
+An installation which uses an extension which make use of ``BackendLayoutWizardController``
+
+
+Migration
+=========
+
+Use the renderType "belayoutwizard", which renders the backend layout wizard inline in FormEngine.
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-75497-InlineBackendLayoutWizard.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-75497-InlineBackendLayoutWizard.rst
new file mode 100644 (file)
index 0000000..a89a255
--- /dev/null
@@ -0,0 +1,28 @@
+==============================================
+Feature: #75497 - inline backend layout wizard
+==============================================
+
+Description
+===========
+
+A new renderType was added to render the backend layout wizard inline in FormEngine.
+
+
+Impact
+======
+
+The old ``BackendLayoutWizardController`` which has rendered the backend layout wizard in a popup has been removed.
+
+Use the new renderType ``belayoutwizard`` to render the backend layout wizard inline in FormEngine.
+
+example TCA configuration:
+
+.. code-block:: php
+
+   'config' => array(
+      'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:backend_layout.config',
+      'config' => array(
+         'type' => 'text',
+         'renderType' => 'belayoutwizard',
+      )
+   )
index 20bffbb..67d4374 100644 (file)
@@ -46,22 +46,8 @@ return array(
             'label' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:backend_layout.config',
             'config' => array(
                 'type' => 'text',
-                'rows' => '10',
-                'cols' => '48',
-                'wrap' => 'OFF',
-                'wizards' => array(
-                    0 => array(
-                        'title' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:backend_layout.wizard',
-                        'type' => 'popup',
-                        'icon' => 'wizard-backendlayout',
-                        'module' => array(
-                            'name' => 'wizard_backend_layout'
-                        ),
-                        'JSopenParams' => 'height=800,width=800,status=0,menubar=0,scrollbars=0'
-                    )
-                )
-            ),
-            'defaultExtras' => 'fixed-font : enable-tab',
+                'renderType' => 'belayoutwizard',
+            )
         ),
         'hidden' => array(
             'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.disable',
@@ -87,7 +73,9 @@ return array(
     ),
     'types' => array(
         '1' => array(
-            'showitem' => 'hidden, title, icon, description, config',
+            'showitem' => 'title,icon,config,
+            --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:backend_layout.tabs.access, hidden,
+            --div--;LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:backend_layout.tabs.extended, description',
         ),
     )
 );
index 8da535d..ede7c95 100644 (file)
                        <trans-unit id="backend_layout.icon">
                                <source>Icon</source>
                        </trans-unit>
+                       <trans-unit id="backend_layout.tabs.access">
+                               <source>Access</source>
+                       </trans-unit>
+                       <trans-unit id="backend_layout.tabs.extended">
+                               <source>Extended</source>
+                       </trans-unit>
                </body>
        </file>
 </xliff>
index 4656599..ba4800e 100644 (file)
@@ -11347,6 +11347,9 @@ span.warningboxheader {
 .grideditor div.cell_container:hover {
   opacity: 0.5;
 }
+.grideditor .grideditor-preview {
+  margin-top: 5px;
+}
 .grideditor .link {
   display: block;
   position: absolute;