[FEATURE] Add backend layout PageTs provider 32/41632/4
authorBenjamin Kott <benjamin.kott@wfp2.com>
Fri, 17 Jul 2015 22:01:33 +0000 (00:01 +0200)
committerBenjamin Kott <info@bk2k.info>
Sat, 18 Jul 2015 17:31:33 +0000 (19:31 +0200)
It is now possible to define backend layouts via PageTSConfig on every page.

Resolves: #61903
Releases: master
Change-Id: I121e6ac36eb961f1e1fb260034b89b44596fa00d
Reviewed-on: http://review.typo3.org/41632
Reviewed-by: Frank Nägler <frank.naegler@typo3.org>
Tested-by: Frank Nägler <frank.naegler@typo3.org>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
Reviewed-by: Benjamin Kott <info@bk2k.info>
Tested-by: Benjamin Kott <info@bk2k.info>
typo3/sysext/backend/Classes/Provider/PageTsBackendLayoutDataProvider.php [new file with mode: 0644]
typo3/sysext/backend/ext_tables.php
typo3/sysext/core/Documentation/Changelog/master/Feature-61903-PageTSDataproviderForBackendLayouts.rst [new file with mode: 0644]

diff --git a/typo3/sysext/backend/Classes/Provider/PageTsBackendLayoutDataProvider.php b/typo3/sysext/backend/Classes/Provider/PageTsBackendLayoutDataProvider.php
new file mode 100644 (file)
index 0000000..852dddc
--- /dev/null
@@ -0,0 +1,252 @@
+<?php
+namespace TYPO3\CMS\Backend\Provider;
+
+/*
+ * 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\Utility\BackendUtility;
+use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout;
+use TYPO3\CMS\Backend\View\BackendLayout\BackendLayoutCollection;
+use TYPO3\CMS\Backend\View\BackendLayout\DataProviderContext;
+use TYPO3\CMS\Backend\View\BackendLayout\DataProviderInterface;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * This Provider adds Backend Layouts based on PageTsConfig
+ *
+ * = Example =
+ * mod {
+ *     web_layout {
+ *             BackendLayouts {
+ *                     example {
+ *                             title = Example
+ *                             config {
+ *                                     backend_layout {
+ *                                             colCount = 1
+ *                                             rowCount = 2
+ *                                             rows {
+ *                                                     1 {
+ *                                                             columns {
+ *                                                                     1 {
+ *                                                                             name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.3
+ *                                                                             colPos = 3
+ *                                                                             colspan = 1
+ *                                                                     }
+ *                                                             }
+ *                                                     }
+ *                                                     2 {
+ *                                                             columns {
+ *                                                                     1 {
+ *                                                                             name = Main
+ *                                                                             colPos = 0
+ *                                                                             colspan = 1
+ *                                                                     }
+ *                                                             }
+ *                                                     }
+ *                                             }
+ *                                     }
+ *                             }
+ *                             icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
+ *                     }
+ *             }
+ *     }
+ * }
+ *
+ */
+class PageTsBackendLayoutDataProvider implements DataProviderInterface {
+
+       /**
+        * Internal Backend Layout stack
+        *
+        * @var array
+        */
+       protected $backendLayouts = array();
+
+       /**
+        * PageTs Config
+        *
+        * @var array
+        */
+       protected $pageTsConfig = array();
+
+       /**
+        * PageId
+        *
+        * @var int
+        */
+       protected $pageId = 0;
+
+       /**
+        * Set PageTsConfig
+        *
+        * @param array $pageTsConfig
+        * @return void
+        */
+       protected function setPageTsConfig(array $pageTsConfig) {
+               $this->pageTsConfig = $pageTsConfig;
+       }
+
+       /**
+        * Get PageTsConfig
+        *
+        * @return array
+        */
+       protected function getPageTsConfig() {
+               return $this->pageTsConfig;
+       }
+
+       /**
+        * Set PageId
+        *
+        * @param int $pageId
+        * @return void
+        */
+       protected function setPageId($pageId) {
+               $this->pageId = (int)$pageId;
+       }
+
+       /**
+        * Get PageId
+        *
+        * @return int
+        */
+       protected function getPageId() {
+               return (int)$this->pageId;
+       }
+
+       /**
+        * Gets PageTsConfig from DataProviderContext if available,
+        * if not it will be generated for the current Page.
+        *
+        * @param DataProviderContext $dataProviderContext
+        * @return void
+        */
+       protected function generatePageTsConfig($dataProviderContext = NULL) {
+               if ($dataProviderContext === NULL) {
+                       $pageId = $this->getPageId();
+                       $pageId = $pageId > 0 ? $pageId : (int)GeneralUtility::_GP('id');
+                       $pageTsConfig = BackendUtility::getPagesTSconfig($pageId);
+               } else {
+                       $pageTsConfig = $dataProviderContext->getPageTsConfig();
+               }
+               $this->setPageTsConfig($pageTsConfig);
+       }
+
+       /**
+        * Generate the Backend Layout configs
+        *
+        * @param DataProviderContext $dataProviderContext
+        * @return void
+        */
+       protected function generateBackendLayouts($dataProviderContext = NULL) {
+               $this->generatePageTsConfig($dataProviderContext);
+               $pageTsConfig = $this->getPageTsConfig();
+               if (!empty($pageTsConfig['mod.']['web_layout.']['BackendLayouts.'])) {
+                       $backendLayouts = (array)$pageTsConfig['mod.']['web_layout.']['BackendLayouts.'];
+                       foreach ($backendLayouts as $identifier => $data) {
+                               $backendLayout = $this->generateBackendLayoutFromTsConfig($identifier, $data);
+                               $this->attachBackendLayout($backendLayout);
+                       }
+               }
+       }
+
+       /**
+        * Generates a Backend Layout from PageTsConfig array
+        *
+        * @return mixed
+        */
+       protected function generateBackendLayoutFromTsConfig($identifier, $data) {
+               if (!empty($data['config.']['backend_layout.']) && is_array($data['config.']['backend_layout.'])) {
+                       $backendLayout['uid'] = substr($identifier, 0, -1);
+                       $backendLayout['title'] = ($data['title']) ? $data['title'] : $backendLayout['uid'];
+                       $backendLayout['icon'] = ($data['icon']) ? $data['icon'] : '';
+                       // Convert PHP array back to plain TypoScript so it can be procecced
+                       $config = \TYPO3\CMS\Core\Utility\ArrayUtility::flatten($data['config.']);
+                       $backendLayout['config'] = '';
+                       foreach ($config as $row => $value) {
+                               $backendLayout['config'] .= $row . " = " . $value . "\r\n";
+                       }
+                       return $backendLayout;
+               }
+               return NULL;
+       }
+
+       /**
+        * Attach Backend Layout to internal Stack
+        *
+        * @param mixed $backendLayout
+        */
+       protected function attachBackendLayout($backendLayout = NULL) {
+               if ($backendLayout) {
+                       $this->backendLayouts[$backendLayout['uid']] = $backendLayout;
+               }
+       }
+
+       /**
+        * @param DataProviderContext $dataProviderContext
+        * @param BackendLayoutCollection $backendLayoutCollection
+        * @return void
+        */
+       public function addBackendLayouts(DataProviderContext $dataProviderContext, BackendLayoutCollection $backendLayoutCollection) {
+               $this->generateBackendLayouts($dataProviderContext);
+               foreach ($this->backendLayouts as $backendLayoutConfig) {
+                       $backendLayout = $this->createBackendLayout($backendLayoutConfig);
+                       $backendLayoutCollection->add($backendLayout);
+               }
+       }
+
+       /**
+        * Gets a backend layout by (regular) identifier.
+        *
+        * @param string $identifier
+        * @param int $pageId
+        * @return NULL|BackendLayout
+        */
+       public function getBackendLayout($identifier, $pageId) {
+               $this->setPageId($pageId);
+               $this->generateBackendLayouts();
+               $backendLayout = NULL;
+               if (array_key_exists($identifier, $this->backendLayouts)) {
+                       return $this->createBackendLayout($this->backendLayouts[$identifier]);
+               }
+               return $backendLayout;
+       }
+
+       /**
+        * Creates a new backend layout using the given record data.
+        *
+        * @param array $data
+        * @return BackendLayout
+        */
+       protected function createBackendLayout(array $data) {
+               $backendLayout = BackendLayout::create($data['uid'], $data['title'], $data['config']);
+               $backendLayout->setIconPath($this->getIconPath($data['icon']));
+               $backendLayout->setData($data);
+               return $backendLayout;
+       }
+
+       /**
+        * Gets and sanitizes the icon path.
+        *
+        * @param string $icon Name of the icon file
+        * @return string
+        */
+       protected function getIconPath($icon) {
+               $iconPath = '';
+               if (!empty($icon)) {
+                       $iconPath = $icon;
+               }
+               return $iconPath;
+       }
+
+}
index 77209d2..bf8feab 100644 (file)
@@ -175,4 +175,7 @@ if (TYPO3_MODE === 'BE') {
                'dummy',
                \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath($_EXTKEY) . 'Modules/Dummy/'
        );
+
+       // Register BackendLayoutDataProvider for PageTs
+       $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider']['pagets'] = \TYPO3\CMS\Backend\Provider\PageTsBackendLayoutDataProvider::class;
 }
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-61903-PageTSDataproviderForBackendLayouts.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-61903-PageTSDataproviderForBackendLayouts.rst
new file mode 100644 (file)
index 0000000..60fdb8a
--- /dev/null
@@ -0,0 +1,61 @@
+=========================================================
+Feature: #61903 - PageTS dataprovider for backend layouts
+=========================================================
+
+Description
+===========
+
+Over the last year, several extensions appeared on TER that implemented the very same basic feature:
+Deploying backend layouts without database records by providing them via PageTS.
+
+Implement a generic PageTS provider for backend layouts to unify those approaches and to make backend layouts reusable
+across installations.
+
+
+Impact
+======
+
+It is now possible to define backend layouts via PageTSConfig on every page.
+
+
+Example
+-------
+
+.. code-block:: typoscript
+
+mod {
+       web_layout {
+               BackendLayouts {
+                       exampleKey {
+                               title = Example
+                               config {
+                                       backend_layout {
+                                               colCount = 1
+                                               rowCount = 2
+                                               rows {
+                                                       1 {
+                                                               columns {
+                                                                       1 {
+                                                                               name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.3
+                                                                               colPos = 3
+                                                                               colspan = 1
+                                                                       }
+                                                               }
+                                                       }
+                                                       2 {
+                                                               columns {
+                                                                       1 {
+                                                                               name = Main
+                                                                               colPos = 0
+                                                                               colspan = 1
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
+                       }
+               }
+       }
+}