first commit
This commit is contained in:
commit
1218dd1517
12716 files changed
+989233
No files matched your search
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to represent a backend layout.
|
||||
*/
|
||||
class BackendLayout
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $iconPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $configuration;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @param string $title
|
||||
* @param string $configuration
|
||||
* @return BackendLayout
|
||||
*/
|
||||
public static function create($identifier, $title, $configuration)
|
||||
{
|
||||
return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
self::class,
|
||||
$identifier,
|
||||
$title,
|
||||
$configuration
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @param string $title
|
||||
* @param string $configuration
|
||||
*/
|
||||
public function __construct($identifier, $title, $configuration)
|
||||
{
|
||||
$this->setIdentifier($identifier);
|
||||
$this->setTitle($title);
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function setIdentifier($identifier)
|
||||
{
|
||||
if (strpos($identifier, '__') !== false) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Identifier "' . $identifier . '" must not contain "__"',
|
||||
1381597630
|
||||
);
|
||||
}
|
||||
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $description
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIconPath()
|
||||
{
|
||||
return $this->iconPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $iconPath
|
||||
*/
|
||||
public function setIconPath($iconPath)
|
||||
{
|
||||
$this->iconPath = $iconPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getConfiguration()
|
||||
{
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $configuration
|
||||
*/
|
||||
public function setConfiguration($configuration)
|
||||
{
|
||||
$this->configuration = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collection of backend layouts.
|
||||
*/
|
||||
class BackendLayoutCollection
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $identifier;
|
||||
|
||||
/**
|
||||
* @var array|BackendLayout[]
|
||||
*/
|
||||
protected $backendLayouts = [];
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
*/
|
||||
public function __construct($identifier)
|
||||
{
|
||||
$this->setIdentifier($identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentifier()
|
||||
{
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $identifier
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
public function setIdentifier($identifier)
|
||||
{
|
||||
if (strpos($identifier, '__') !== false) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Identifier "' . $identifier . '" must not contain "__"',
|
||||
1381597631
|
||||
);
|
||||
}
|
||||
|
||||
$this->identifier = $identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a backend layout to this collection.
|
||||
*
|
||||
* @param BackendLayout $backendLayout
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function add(BackendLayout $backendLayout)
|
||||
{
|
||||
$identifier = $backendLayout->getIdentifier();
|
||||
|
||||
if (strpos($identifier, '__') !== false) {
|
||||
throw new \UnexpectedValueException(
|
||||
'BackendLayout Identifier "' . $identifier . '" must not contain "__"',
|
||||
1381597628
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($this->backendLayouts[$identifier])) {
|
||||
throw new \LogicException(
|
||||
'Backend Layout ' . $identifier . ' is already defined',
|
||||
1381559376
|
||||
);
|
||||
}
|
||||
|
||||
$this->backendLayouts[$identifier] = $backendLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a backend layout by (regular) identifier.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @return BackendLayout|null
|
||||
*/
|
||||
public function get($identifier)
|
||||
{
|
||||
$backendLayout = null;
|
||||
|
||||
if (isset($this->backendLayouts[$identifier])) {
|
||||
$backendLayout = $this->backendLayouts[$identifier];
|
||||
}
|
||||
|
||||
return $backendLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all backend layouts in this collection.
|
||||
*
|
||||
* @return array|BackendLayout[]
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
return $this->backendLayouts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collection of backend layout data providers.
|
||||
*/
|
||||
class DataProviderCollection implements \TYPO3\CMS\Core\SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var array|DataProviderInterface[]
|
||||
*/
|
||||
protected $dataProviders = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $results = [];
|
||||
|
||||
/**
|
||||
* Adds a data provider to this collection.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param string|object $classNameOrObject
|
||||
* @throws \UnexpectedValueException
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function add($identifier, $classNameOrObject)
|
||||
{
|
||||
if (strpos($identifier, '__') !== false) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Identifier "' . $identifier . '" must not contain "__"',
|
||||
1381597629
|
||||
);
|
||||
}
|
||||
|
||||
if (is_object($classNameOrObject)) {
|
||||
$className = get_class($classNameOrObject);
|
||||
$dataProvider = $classNameOrObject;
|
||||
} else {
|
||||
$className = $classNameOrObject;
|
||||
$dataProvider = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($classNameOrObject);
|
||||
}
|
||||
|
||||
if (!$dataProvider instanceof DataProviderInterface) {
|
||||
throw new \LogicException(
|
||||
$className . ' must implement interface ' . \TYPO3\CMS\Backend\View\BackendLayout\DataProviderInterface::class,
|
||||
1381269811
|
||||
);
|
||||
}
|
||||
|
||||
$this->dataProviders[$identifier] = $dataProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all backend layout collections and thus, all
|
||||
* backend layouts. Each data provider returns its own
|
||||
* backend layout collection.
|
||||
*
|
||||
* @param DataProviderContext $dataProviderContext
|
||||
* @return array|BackendLayoutCollection[]
|
||||
*/
|
||||
public function getBackendLayoutCollections(DataProviderContext $dataProviderContext)
|
||||
{
|
||||
$result = [];
|
||||
|
||||
foreach ($this->dataProviders as $identifier => $dataProvider) {
|
||||
$backendLayoutCollection = $this->createBackendLayoutCollection($identifier);
|
||||
$dataProvider->addBackendLayouts($dataProviderContext, $backendLayoutCollection);
|
||||
$result[$identifier] = $backendLayoutCollection;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a backend layout by a combined identifier, which is
|
||||
* e.g. "myextension_regular" and "myextension" is the identifier
|
||||
* of the accordant data provider and "regular" the identifier of
|
||||
* the accordant backend layout.
|
||||
*
|
||||
* @param string $combinedIdentifier
|
||||
* @param int $pageId
|
||||
* @return BackendLayout|null
|
||||
*/
|
||||
public function getBackendLayout($combinedIdentifier, $pageId)
|
||||
{
|
||||
$backendLayout = null;
|
||||
|
||||
if (strpos($combinedIdentifier, '__') === false) {
|
||||
$dataProviderIdentifier = 'default';
|
||||
$backendLayoutIdentifier = $combinedIdentifier;
|
||||
} else {
|
||||
list($dataProviderIdentifier, $backendLayoutIdentifier) = explode('__', $combinedIdentifier, 2);
|
||||
}
|
||||
|
||||
if (isset($this->dataProviders[$dataProviderIdentifier])) {
|
||||
$backendLayout = $this->dataProviders[$dataProviderIdentifier]->getBackendLayout($backendLayoutIdentifier, $pageId);
|
||||
}
|
||||
|
||||
return $backendLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new backend layout collection.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @return BackendLayoutCollection
|
||||
*/
|
||||
protected function createBackendLayoutCollection($identifier)
|
||||
{
|
||||
return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
|
||||
BackendLayoutCollection::class,
|
||||
$identifier
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Context that is forwarded to backend layout data providers.
|
||||
*/
|
||||
class DataProviderContext implements \TYPO3\CMS\Core\SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $pageId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tableName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $fieldName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $pageTsConfig;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPageId()
|
||||
{
|
||||
return $this->pageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pageId
|
||||
* @return DataProviderContext
|
||||
*/
|
||||
public function setPageId($pageId)
|
||||
{
|
||||
$this->pageId = $pageId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTableName()
|
||||
{
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tableName
|
||||
* @return DataProviderContext
|
||||
*/
|
||||
public function setTableName($tableName)
|
||||
{
|
||||
$this->tableName = $tableName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldName()
|
||||
{
|
||||
return $this->fieldName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fieldName
|
||||
* @return DataProviderContext
|
||||
*/
|
||||
public function setFieldName($fieldName)
|
||||
{
|
||||
$this->fieldName = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return DataProviderContext
|
||||
*/
|
||||
public function setData(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getPageTsConfig()
|
||||
{
|
||||
return $this->pageTsConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $pageTsConfig
|
||||
* @return DataProviderContext
|
||||
*/
|
||||
public function setPageTsConfig(array $pageTsConfig)
|
||||
{
|
||||
$this->pageTsConfig = $pageTsConfig;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into BackendLayoutDataProvider
|
||||
* to provide additional backend layouts from various sources.
|
||||
*/
|
||||
interface DataProviderInterface
|
||||
{
|
||||
/**
|
||||
* Adds backend layouts to the given backend layout collection.
|
||||
*
|
||||
* @param DataProviderContext $dataProviderContext
|
||||
* @param BackendLayoutCollection $backendLayoutCollection
|
||||
*/
|
||||
public function addBackendLayouts(DataProviderContext $dataProviderContext, BackendLayoutCollection $backendLayoutCollection);
|
||||
|
||||
/**
|
||||
* Gets a backend layout by (regular) identifier.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param int $pageId
|
||||
* @return BackendLayout|null
|
||||
*/
|
||||
public function getBackendLayout($identifier, $pageId);
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View\BackendLayout;
|
||||
|
||||
/*
|
||||
* 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\Core\Context\Context;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
|
||||
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
|
||||
use TYPO3\CMS\Core\Resource\FileRepository;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Backend layout data provider class
|
||||
*/
|
||||
class DefaultDataProvider implements DataProviderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* Table name for backend_layouts
|
||||
*/
|
||||
protected $tableName = 'backend_layout';
|
||||
|
||||
/**
|
||||
* Adds backend layouts to the given backend layout collection.
|
||||
* The default backend layout ('default_default') is not added
|
||||
* since it's the default fallback if nothing is specified.
|
||||
*
|
||||
* @param DataProviderContext $dataProviderContext
|
||||
* @param BackendLayoutCollection $backendLayoutCollection
|
||||
*/
|
||||
public function addBackendLayouts(
|
||||
DataProviderContext $dataProviderContext,
|
||||
BackendLayoutCollection $backendLayoutCollection
|
||||
) {
|
||||
$layoutData = $this->getLayoutData(
|
||||
$dataProviderContext->getFieldName(),
|
||||
$dataProviderContext->getPageTsConfig(),
|
||||
$dataProviderContext->getPageId()
|
||||
);
|
||||
|
||||
foreach ($layoutData as $data) {
|
||||
$backendLayout = $this->createBackendLayout($data);
|
||||
$backendLayoutCollection->add($backendLayout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a backend layout by (regular) identifier.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param int $pageId
|
||||
* @return BackendLayout|null
|
||||
*/
|
||||
public function getBackendLayout($identifier, $pageId)
|
||||
{
|
||||
$backendLayout = null;
|
||||
|
||||
if ((string)$identifier === 'default') {
|
||||
return $this->createDefaultBackendLayout();
|
||||
}
|
||||
|
||||
$data = BackendUtility::getRecordWSOL($this->tableName, $identifier);
|
||||
|
||||
if (is_array($data)) {
|
||||
$backendLayout = $this->createBackendLayout($data);
|
||||
}
|
||||
|
||||
return $backendLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a backend layout with the default configuration.
|
||||
*
|
||||
* @return BackendLayout
|
||||
*/
|
||||
protected function createDefaultBackendLayout()
|
||||
{
|
||||
return BackendLayout::create(
|
||||
'default',
|
||||
'LLL:EXT:frontend/Resources/Private/Language/locallang_tca.xlf:pages.backend_layout.default',
|
||||
\TYPO3\CMS\Backend\View\BackendLayoutView::getDefaultColumnLayout()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
$backendLayout->setData($data);
|
||||
return $backendLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the icon from the database record
|
||||
*
|
||||
* @param array $icon
|
||||
* @return string
|
||||
*/
|
||||
protected function getIconPath(array $icon)
|
||||
{
|
||||
$fileRepository = GeneralUtility::makeInstance(FileRepository::class);
|
||||
$references = $fileRepository->findByRelation($this->tableName, 'icon', $icon['uid']);
|
||||
if (!empty($references)) {
|
||||
$icon = reset($references);
|
||||
return $icon->getPublicUrl();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all layouts from the core's default data provider.
|
||||
*
|
||||
* @param string $fieldName the name of the field the layouts are provided for (either backend_layout or backend_layout_next_level)
|
||||
* @param array $pageTsConfig PageTSconfig of the given page
|
||||
* @param int $pageUid the ID of the page wea re getting the layouts for
|
||||
* @return array $layouts A collection of layout data of the registered provider
|
||||
*/
|
||||
protected function getLayoutData($fieldName, array $pageTsConfig, $pageUid)
|
||||
{
|
||||
$storagePid = $this->getStoragePid($pageTsConfig);
|
||||
$pageTsConfigId = $this->getPageTSconfigIds($pageTsConfig);
|
||||
|
||||
// Add layout records
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable($this->tableName);
|
||||
$queryBuilder->getRestrictions()
|
||||
->add(
|
||||
GeneralUtility::makeInstance(
|
||||
WorkspaceRestriction::class,
|
||||
GeneralUtility::makeInstance(Context::class)->getPropertyFromAspect('workspace', 'id')
|
||||
)
|
||||
);
|
||||
$queryBuilder
|
||||
->select('*')
|
||||
->from($this->tableName)
|
||||
->where(
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->andX(
|
||||
$queryBuilder->expr()->comparison(
|
||||
$queryBuilder->createNamedParameter($pageTsConfigId[$fieldName], \PDO::PARAM_INT),
|
||||
ExpressionBuilder::EQ,
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->comparison(
|
||||
$queryBuilder->createNamedParameter($storagePid, \PDO::PARAM_INT),
|
||||
ExpressionBuilder::EQ,
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
)
|
||||
),
|
||||
$queryBuilder->expr()->orX(
|
||||
$queryBuilder->expr()->eq(
|
||||
'backend_layout.pid',
|
||||
$queryBuilder->createNamedParameter($pageTsConfigId[$fieldName], \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'backend_layout.pid',
|
||||
$queryBuilder->createNamedParameter($storagePid, \PDO::PARAM_INT)
|
||||
)
|
||||
),
|
||||
$queryBuilder->expr()->andX(
|
||||
$queryBuilder->expr()->comparison(
|
||||
$queryBuilder->createNamedParameter($pageTsConfigId[$fieldName], \PDO::PARAM_INT),
|
||||
ExpressionBuilder::EQ,
|
||||
$queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->eq(
|
||||
'backend_layout.pid',
|
||||
$queryBuilder->createNamedParameter($pageUid, \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (!empty($GLOBALS['TCA'][$this->tableName]['ctrl']['sortby'])) {
|
||||
$queryBuilder->orderBy($GLOBALS['TCA'][$this->tableName]['ctrl']['sortby']);
|
||||
}
|
||||
|
||||
$statement = $queryBuilder->execute();
|
||||
|
||||
$results = [];
|
||||
while ($record = $statement->fetch()) {
|
||||
BackendUtility::workspaceOL($this->tableName, $record);
|
||||
if (is_array($record)) {
|
||||
$results[$record['t3ver_oid'] ?: $record['uid']] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the storage PID from TCEFORM.
|
||||
*
|
||||
* @param array $pageTsConfig
|
||||
* @return int
|
||||
*/
|
||||
protected function getStoragePid(array $pageTsConfig)
|
||||
{
|
||||
$storagePid = 0;
|
||||
|
||||
if (!empty($pageTsConfig['TCEFORM.']['pages.']['_STORAGE_PID'])) {
|
||||
$storagePid = (int)$pageTsConfig['TCEFORM.']['pages.']['_STORAGE_PID'];
|
||||
}
|
||||
|
||||
return $storagePid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the page TSconfig from TCEFORM.
|
||||
*
|
||||
* @param array $pageTsConfig
|
||||
* @return array
|
||||
*/
|
||||
protected function getPageTSconfigIds(array $pageTsConfig)
|
||||
{
|
||||
$pageTsConfigIds = [
|
||||
'backend_layout' => 0,
|
||||
'backend_layout_next_level' => 0,
|
||||
];
|
||||
|
||||
if (!empty($pageTsConfig['TCEFORM.']['pages.']['backend_layout.']['PAGE_TSCONFIG_ID'])) {
|
||||
$pageTsConfigIds['backend_layout'] = (int)$pageTsConfig['TCEFORM.']['pages.']['backend_layout.']['PAGE_TSCONFIG_ID'];
|
||||
}
|
||||
|
||||
if (!empty($pageTsConfig['TCEFORM.']['pages.']['backend_layout_next_level.']['PAGE_TSCONFIG_ID'])) {
|
||||
$pageTsConfigIds['backend_layout_next_level'] = (int)$pageTsConfig['TCEFORM.']['pages.']['backend_layout_next_level.']['PAGE_TSCONFIG_ID'];
|
||||
}
|
||||
|
||||
return $pageTsConfigIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,491 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View;
|
||||
|
||||
/*
|
||||
* 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\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\TypoScript\Parser\TypoScriptParser;
|
||||
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Backend layout for CMS
|
||||
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
|
||||
*/
|
||||
class BackendLayoutView implements \TYPO3\CMS\Core\SingletonInterface
|
||||
{
|
||||
/**
|
||||
* @var BackendLayout\DataProviderCollection
|
||||
*/
|
||||
protected $dataProviderCollection;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $selectedCombinedIdentifier = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $selectedBackendLayout = [];
|
||||
|
||||
/**
|
||||
* Creates this object and initializes data providers.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->initializeDataProviderCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes data providers
|
||||
*/
|
||||
protected function initializeDataProviderCollection()
|
||||
{
|
||||
/** @var BackendLayout\DataProviderCollection $dataProviderCollection */
|
||||
$dataProviderCollection = GeneralUtility::makeInstance(
|
||||
BackendLayout\DataProviderCollection::class
|
||||
);
|
||||
|
||||
$dataProviderCollection->add(
|
||||
'default',
|
||||
\TYPO3\CMS\Backend\View\BackendLayout\DefaultDataProvider::class
|
||||
);
|
||||
|
||||
if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider'])) {
|
||||
$dataProviders = (array)$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['BackendLayoutDataProvider'];
|
||||
foreach ($dataProviders as $identifier => $className) {
|
||||
$dataProviderCollection->add($identifier, $className);
|
||||
}
|
||||
}
|
||||
|
||||
$this->setDataProviderCollection($dataProviderCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BackendLayout\DataProviderCollection $dataProviderCollection
|
||||
*/
|
||||
public function setDataProviderCollection(BackendLayout\DataProviderCollection $dataProviderCollection)
|
||||
{
|
||||
$this->dataProviderCollection = $dataProviderCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BackendLayout\DataProviderCollection
|
||||
*/
|
||||
public function getDataProviderCollection()
|
||||
{
|
||||
return $this->dataProviderCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets backend layout items to be shown in the forms engine.
|
||||
* This method is called as "itemsProcFunc" with the accordant context
|
||||
* for pages.backend_layout and pages.backend_layout_next_level.
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function addBackendLayoutItems(array $parameters)
|
||||
{
|
||||
$pageId = $this->determinePageId($parameters['table'], $parameters['row']);
|
||||
$pageTsConfig = (array)BackendUtility::getPagesTSconfig($pageId);
|
||||
$identifiersToBeExcluded = $this->getIdentifiersToBeExcluded($pageTsConfig);
|
||||
|
||||
$dataProviderContext = $this->createDataProviderContext()
|
||||
->setPageId($pageId)
|
||||
->setData($parameters['row'])
|
||||
->setTableName($parameters['table'])
|
||||
->setFieldName($parameters['field'])
|
||||
->setPageTsConfig($pageTsConfig);
|
||||
|
||||
$backendLayoutCollections = $this->getDataProviderCollection()->getBackendLayoutCollections($dataProviderContext);
|
||||
foreach ($backendLayoutCollections as $backendLayoutCollection) {
|
||||
$combinedIdentifierPrefix = '';
|
||||
if ($backendLayoutCollection->getIdentifier() !== 'default') {
|
||||
$combinedIdentifierPrefix = $backendLayoutCollection->getIdentifier() . '__';
|
||||
}
|
||||
|
||||
foreach ($backendLayoutCollection->getAll() as $backendLayout) {
|
||||
$combinedIdentifier = $combinedIdentifierPrefix . $backendLayout->getIdentifier();
|
||||
|
||||
if (in_array($combinedIdentifier, $identifiersToBeExcluded, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameters['items'][] = [
|
||||
$this->getLanguageService()->sL($backendLayout->getTitle()),
|
||||
$combinedIdentifier,
|
||||
$backendLayout->getIconPath(),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the page id for a given record of a database table.
|
||||
*
|
||||
* @param string $tableName
|
||||
* @param array $data
|
||||
* @return int|bool Returns page id or false on error
|
||||
*/
|
||||
protected function determinePageId($tableName, array $data)
|
||||
{
|
||||
if (strpos($data['uid'], 'NEW') === 0) {
|
||||
// negative uid_pid values of content elements indicate that the element
|
||||
// has been inserted after an existing element so there is no pid to get
|
||||
// the backendLayout for and we have to get that first
|
||||
if ($data['pid'] < 0) {
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable($tableName);
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeAll();
|
||||
$pageId = $queryBuilder
|
||||
->select('pid')
|
||||
->from($tableName)
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'uid',
|
||||
$queryBuilder->createNamedParameter(abs($data['pid']), \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->execute()
|
||||
->fetchColumn();
|
||||
} else {
|
||||
$pageId = $data['pid'];
|
||||
}
|
||||
} elseif ($tableName === 'pages') {
|
||||
$pageId = $data['uid'];
|
||||
} else {
|
||||
$pageId = $data['pid'];
|
||||
}
|
||||
|
||||
return $pageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the backend layout which should be used for this page.
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return bool|string Identifier of the backend layout to be used, or FALSE if none
|
||||
*/
|
||||
public function getSelectedCombinedIdentifier($pageId)
|
||||
{
|
||||
if (!isset($this->selectedCombinedIdentifier[$pageId])) {
|
||||
$page = $this->getPage($pageId);
|
||||
$this->selectedCombinedIdentifier[$pageId] = (string)$page['backend_layout'];
|
||||
|
||||
if ($this->selectedCombinedIdentifier[$pageId] === '-1') {
|
||||
// If it is set to "none" - don't use any
|
||||
$this->selectedCombinedIdentifier[$pageId] = false;
|
||||
} elseif ($this->selectedCombinedIdentifier[$pageId] === '' || $this->selectedCombinedIdentifier[$pageId] === '0') {
|
||||
// If it not set check the root-line for a layout on next level and use this
|
||||
// (root-line starts with current page and has page "0" at the end)
|
||||
$rootLine = $this->getRootLine($pageId);
|
||||
// Remove first and last element (current and root page)
|
||||
array_shift($rootLine);
|
||||
array_pop($rootLine);
|
||||
foreach ($rootLine as $rootLinePage) {
|
||||
$this->selectedCombinedIdentifier[$pageId] = (string)$rootLinePage['backend_layout_next_level'];
|
||||
if ($this->selectedCombinedIdentifier[$pageId] === '-1') {
|
||||
// If layout for "next level" is set to "none" - don't use any and stop searching
|
||||
$this->selectedCombinedIdentifier[$pageId] = false;
|
||||
break;
|
||||
}
|
||||
if ($this->selectedCombinedIdentifier[$pageId] !== '' && $this->selectedCombinedIdentifier[$pageId] !== '0') {
|
||||
// Stop searching if a layout for "next level" is set
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it is set to a positive value use this
|
||||
return $this->selectedCombinedIdentifier[$pageId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets backend layout identifiers to be excluded
|
||||
*
|
||||
* @param array $pageTSconfig
|
||||
* @return array
|
||||
*/
|
||||
protected function getIdentifiersToBeExcluded(array $pageTSconfig)
|
||||
{
|
||||
$identifiersToBeExcluded = [];
|
||||
|
||||
if (ArrayUtility::isValidPath($pageTSconfig, 'options./backendLayout./exclude')) {
|
||||
$identifiersToBeExcluded = GeneralUtility::trimExplode(
|
||||
',',
|
||||
ArrayUtility::getValueByPath($pageTSconfig, 'options./backendLayout./exclude'),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
return $identifiersToBeExcluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets colPos items to be shown in the forms engine.
|
||||
* This method is called as "itemsProcFunc" with the accordant context
|
||||
* for tt_content.colPos.
|
||||
*
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function colPosListItemProcFunc(array $parameters)
|
||||
{
|
||||
$pageId = $this->determinePageId($parameters['table'], $parameters['row']);
|
||||
|
||||
if ($pageId !== false) {
|
||||
$parameters['items'] = $this->addColPosListLayoutItems($pageId, $parameters['items']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds items to a colpos list
|
||||
*
|
||||
* @param int $pageId
|
||||
* @param array $items
|
||||
* @return array
|
||||
*/
|
||||
protected function addColPosListLayoutItems($pageId, $items)
|
||||
{
|
||||
$layout = $this->getSelectedBackendLayout($pageId);
|
||||
if ($layout && $layout['__items']) {
|
||||
$items = $layout['__items'];
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of available columns for a given page id
|
||||
*
|
||||
* @param int $id
|
||||
* @return array $tcaItems
|
||||
*/
|
||||
public function getColPosListItemsParsed($id)
|
||||
{
|
||||
$tsConfig = BackendUtility::getPagesTSconfig($id)['TCEFORM.']['tt_content.']['colPos.'] ?? [];
|
||||
$tcaConfig = $GLOBALS['TCA']['tt_content']['columns']['colPos']['config'];
|
||||
$tcaItems = $tcaConfig['items'];
|
||||
$tcaItems = $this->addItems($tcaItems, $tsConfig['addItems.']);
|
||||
if (isset($tcaConfig['itemsProcFunc']) && $tcaConfig['itemsProcFunc']) {
|
||||
$tcaItems = $this->addColPosListLayoutItems($id, $tcaItems);
|
||||
}
|
||||
if (!empty($tsConfig['removeItems'])) {
|
||||
foreach (GeneralUtility::trimExplode(',', $tsConfig['removeItems'], true) as $removeId) {
|
||||
foreach ($tcaItems as $key => $item) {
|
||||
if ($item[1] == $removeId) {
|
||||
unset($tcaItems[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $tcaItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges items into an item-array, optionally with an icon
|
||||
* example:
|
||||
* TCEFORM.pages.doktype.addItems.13 = My Label
|
||||
* TCEFORM.pages.doktype.addItems.13.icon = EXT:t3skin/icons/gfx/i/pages.gif
|
||||
*
|
||||
* @param array $items The existing item array
|
||||
* @param array $iArray An array of items to add. NOTICE: The keys are mapped to values, and the values and mapped to be labels. No possibility of adding an icon.
|
||||
* @return array The updated $item array
|
||||
* @internal
|
||||
*/
|
||||
protected function addItems($items, $iArray)
|
||||
{
|
||||
$languageService = static::getLanguageService();
|
||||
if (is_array($iArray)) {
|
||||
foreach ($iArray as $value => $label) {
|
||||
// if the label is an array (that means it is a subelement
|
||||
// like "34.icon = mylabel.png", skip it (see its usage below)
|
||||
if (is_array($label)) {
|
||||
continue;
|
||||
}
|
||||
// check if the value "34 = mylabel" also has a "34.icon = myimage.png"
|
||||
if (isset($iArray[$value . '.']) && $iArray[$value . '.']['icon']) {
|
||||
$icon = $iArray[$value . '.']['icon'];
|
||||
} else {
|
||||
$icon = '';
|
||||
}
|
||||
$items[] = [$languageService->sL($label), $value, $icon];
|
||||
}
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected backend layout
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return array|null $backendLayout
|
||||
*/
|
||||
public function getSelectedBackendLayout($pageId)
|
||||
{
|
||||
if (isset($this->selectedBackendLayout[$pageId])) {
|
||||
return $this->selectedBackendLayout[$pageId];
|
||||
}
|
||||
$backendLayoutData = null;
|
||||
|
||||
$selectedCombinedIdentifier = $this->getSelectedCombinedIdentifier($pageId);
|
||||
// If no backend layout is selected, use default
|
||||
if (empty($selectedCombinedIdentifier)) {
|
||||
$selectedCombinedIdentifier = 'default';
|
||||
}
|
||||
|
||||
$backendLayout = $this->getDataProviderCollection()->getBackendLayout($selectedCombinedIdentifier, $pageId);
|
||||
// If backend layout is not found available anymore, use default
|
||||
if ($backendLayout === null) {
|
||||
$selectedCombinedIdentifier = 'default';
|
||||
$backendLayout = $this->getDataProviderCollection()->getBackendLayout($selectedCombinedIdentifier, $pageId);
|
||||
}
|
||||
|
||||
if (!empty($backendLayout)) {
|
||||
/** @var TypoScriptParser $parser */
|
||||
$parser = GeneralUtility::makeInstance(TypoScriptParser::class);
|
||||
/** @var \TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher $conditionMatcher */
|
||||
$conditionMatcher = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Configuration\TypoScript\ConditionMatching\ConditionMatcher::class);
|
||||
$parser->parse(TypoScriptParser::checkIncludeLines($backendLayout->getConfiguration()), $conditionMatcher);
|
||||
|
||||
$backendLayoutData = [];
|
||||
$backendLayoutData['config'] = $backendLayout->getConfiguration();
|
||||
$backendLayoutData['__config'] = $parser->setup;
|
||||
$backendLayoutData['__items'] = [];
|
||||
$backendLayoutData['__colPosList'] = [];
|
||||
|
||||
// create items and colPosList
|
||||
if (!empty($backendLayoutData['__config']['backend_layout.']['rows.'])) {
|
||||
foreach ($backendLayoutData['__config']['backend_layout.']['rows.'] as $row) {
|
||||
if (!empty($row['columns.'])) {
|
||||
foreach ($row['columns.'] as $column) {
|
||||
if (!isset($column['colPos'])) {
|
||||
continue;
|
||||
}
|
||||
$backendLayoutData['__items'][] = [
|
||||
$this->getColumnName($column),
|
||||
$column['colPos'],
|
||||
null
|
||||
];
|
||||
$backendLayoutData['__colPosList'][] = $column['colPos'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->selectedBackendLayout[$pageId] = $backendLayoutData;
|
||||
}
|
||||
|
||||
return $backendLayoutData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default columns layout
|
||||
*
|
||||
* @return string Default four column layout
|
||||
* @static
|
||||
*/
|
||||
public static function getDefaultColumnLayout()
|
||||
{
|
||||
return '
|
||||
backend_layout {
|
||||
colCount = 1
|
||||
rowCount = 1
|
||||
rows {
|
||||
1 {
|
||||
columns {
|
||||
1 {
|
||||
name = LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf:colPos.I.1
|
||||
colPos = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a page record.
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getPage($pageId)
|
||||
{
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
||||
->getQueryBuilderForTable('pages');
|
||||
$queryBuilder->getRestrictions()
|
||||
->removeAll();
|
||||
$page = $queryBuilder
|
||||
->select('uid', 'pid', 'backend_layout')
|
||||
->from('pages')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'uid',
|
||||
$queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->execute()
|
||||
->fetch();
|
||||
BackendUtility::workspaceOL('pages', $page);
|
||||
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page root-line.
|
||||
*
|
||||
* @param int $pageId
|
||||
* @return array
|
||||
*/
|
||||
protected function getRootLine($pageId)
|
||||
{
|
||||
return BackendUtility::BEgetRootLine($pageId, '', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BackendLayout\DataProviderContext
|
||||
*/
|
||||
protected function createDataProviderContext()
|
||||
{
|
||||
return GeneralUtility::makeInstance(BackendLayout\DataProviderContext::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \TYPO3\CMS\Core\Localization\LanguageService
|
||||
*/
|
||||
protected function getLanguageService()
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get column name from colPos item structure
|
||||
*
|
||||
* @param array $column
|
||||
* @return string
|
||||
*/
|
||||
protected function getColumnName($column)
|
||||
{
|
||||
$columnName = $column['name'];
|
||||
|
||||
if (GeneralUtility::isFirstPartOfStr($columnName, 'LLL:')) {
|
||||
$columnName = $this->getLanguageService()->sL($columnName);
|
||||
}
|
||||
|
||||
return $columnName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View;
|
||||
|
||||
/*
|
||||
* 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\Template\ModuleTemplate;
|
||||
use TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext;
|
||||
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
|
||||
use TYPO3\CMS\Fluid\View\TemplateView;
|
||||
|
||||
/**
|
||||
* Decorates the main template view. Should be used as view if you want to use
|
||||
* Fluid templates in a backend module in order to have a consistent backend.
|
||||
*/
|
||||
class BackendTemplateView implements ViewInterface
|
||||
{
|
||||
/**
|
||||
* @var ModuleTemplate
|
||||
*/
|
||||
protected $moduleTemplate;
|
||||
|
||||
/**
|
||||
* @var TemplateView
|
||||
*/
|
||||
protected $templateView;
|
||||
|
||||
/**
|
||||
* @param ModuleTemplate $moduleTemplate
|
||||
*/
|
||||
public function injectModuleTemplate(ModuleTemplate $moduleTemplate)
|
||||
{
|
||||
$this->moduleTemplate = $moduleTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TemplateView $templateView
|
||||
*/
|
||||
public function injectTemplateView(TemplateView $templateView)
|
||||
{
|
||||
$this->templateView = $templateView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ModuleTemplate
|
||||
*/
|
||||
public function getModuleTemplate()
|
||||
{
|
||||
return $this->moduleTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the template source and render the template.
|
||||
* If "layoutName" is set in a PostParseFacet callback, it will render the file with the given layout.
|
||||
*
|
||||
* Additionally amends the rendered template with a module template "frame"
|
||||
*
|
||||
* @param string $actionName If set, the view of the specified action will be rendered instead. Default is the action specified in the Request object
|
||||
* @return string Rendered Template
|
||||
*/
|
||||
public function render($actionName = null)
|
||||
{
|
||||
$actionViewContent = $this->templateView->render($actionName);
|
||||
$this->moduleTemplate->setContent($actionViewContent);
|
||||
return $this->moduleTemplate->renderContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current controller context
|
||||
*
|
||||
* @param \TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext Controller context which is available inside the view
|
||||
*/
|
||||
public function setControllerContext(\TYPO3\CMS\Extbase\Mvc\Controller\ControllerContext $controllerContext)
|
||||
{
|
||||
$this->templateView->setControllerContext($controllerContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign a value to the variable container.
|
||||
*
|
||||
* @param string $key The key of a view variable to set
|
||||
* @param mixed $value The value of the view variable
|
||||
* @return \TYPO3\CMS\Fluid\View\AbstractTemplateView the instance of this view to allow chaining
|
||||
*/
|
||||
public function assign($key, $value)
|
||||
{
|
||||
$this->templateView->assign($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns multiple values to the JSON output.
|
||||
* However, only the key "value" is accepted.
|
||||
*
|
||||
* @param array $values Keys and values - only a value with key "value" is considered
|
||||
* @return \TYPO3\CMS\Fluid\View\AbstractTemplateView the instance of this view to allow chaining
|
||||
*/
|
||||
public function assignMultiple(array $values)
|
||||
{
|
||||
$this->templateView->assignMultiple($values);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a template can be resolved for the current request context.
|
||||
*
|
||||
* @param ControllerContext $controllerContext Controller context which is available inside the view
|
||||
* @return bool
|
||||
*/
|
||||
public function canRender(ControllerContext $controllerContext)
|
||||
{
|
||||
return $this->templateView->canRender($controllerContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init view
|
||||
*/
|
||||
public function initializeView()
|
||||
{
|
||||
$this->templateView->initializeView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root path(s) to the templates.
|
||||
*
|
||||
* @param array $templateRootPaths Root path(s) to the templates.
|
||||
*/
|
||||
public function setTemplateRootPaths(array $templateRootPaths)
|
||||
{
|
||||
$this->templateView->setTemplateRootPaths($templateRootPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root path(s) to the partials.
|
||||
*
|
||||
* @param array $partialRootPaths Root paths to the partials.
|
||||
*/
|
||||
public function setPartialRootPaths(array $partialRootPaths)
|
||||
{
|
||||
$this->templateView->setPartialRootPaths($partialRootPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root path(s) to the layouts.
|
||||
*
|
||||
* @param array $layoutRootPaths Root path to the layouts.
|
||||
*/
|
||||
public function setLayoutRootPaths(array $layoutRootPaths)
|
||||
{
|
||||
$this->templateView->setLayoutRootPaths($layoutRootPaths);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into PageLayoutView and do additional
|
||||
* tt_content_drawFooter processing.
|
||||
*/
|
||||
interface PageLayoutViewDrawFooterHookInterface
|
||||
{
|
||||
/**
|
||||
* Preprocesses the preview footer rendering of a content element.
|
||||
*
|
||||
* @param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object
|
||||
* @param array $info Processed values
|
||||
* @param array $row Record row of tt_content
|
||||
*/
|
||||
public function preProcess(\TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$info, array &$row);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View;
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for classes which hook into PageLayoutView and do additional
|
||||
* tt_content_drawItem processing.
|
||||
*/
|
||||
interface PageLayoutViewDrawItemHookInterface
|
||||
{
|
||||
/**
|
||||
* Preprocesses the preview rendering of a content element.
|
||||
*
|
||||
* @param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object
|
||||
* @param bool $drawItem Whether to draw the item using the default functionalities
|
||||
* @param string $headerContent Header content
|
||||
* @param string $itemContent Item content
|
||||
* @param array $row Record row of tt_content
|
||||
*/
|
||||
public function preProcess(\TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row);
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
namespace TYPO3\CMS\Backend\View;
|
||||
|
||||
/*
|
||||
* 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\Tree\View\BrowseTreeView;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Core\Imaging\Icon;
|
||||
use TYPO3\CMS\Core\Imaging\IconFactory;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Browse pages in Web module
|
||||
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
|
||||
*/
|
||||
class PageTreeView extends BrowseTreeView
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $ext_showPageId = false;
|
||||
|
||||
/**
|
||||
* Indicates, whether the ajax call was successful, i.e. the requested page has been found
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $ajaxStatus = false;
|
||||
|
||||
/**
|
||||
* Calls init functions
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapping icon in browse tree
|
||||
*
|
||||
* @param string $thePageIcon Icon IMG code
|
||||
* @param array $row Data row for element.
|
||||
* @return string Page icon
|
||||
*/
|
||||
public function wrapIcon($thePageIcon, $row)
|
||||
{
|
||||
/** @var IconFactory $iconFactory */
|
||||
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
|
||||
// If the record is locked, present a warning sign.
|
||||
if ($lockInfo = BackendUtility::isRecordLocked('pages', $row['uid'])) {
|
||||
$aOnClick = 'alert(' . GeneralUtility::quoteJSvalue($lockInfo['msg']) . ');return false;';
|
||||
$lockIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">'
|
||||
. '<span title="' . htmlspecialchars($lockInfo['msg']) . '">' . $iconFactory->getIcon('warning-in-use', Icon::SIZE_SMALL)->render() . '</span></a>';
|
||||
} else {
|
||||
$lockIcon = '';
|
||||
}
|
||||
// Wrap icon in click-menu link.
|
||||
if (!$this->ext_IconMode) {
|
||||
$thePageIcon = BackendUtility::wrapClickMenuOnIcon($thePageIcon, 'pages', $row['uid'], 'tree');
|
||||
} elseif ($this->ext_IconMode === 'titlelink') {
|
||||
$aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->getJumpToParam($row)) . ',this,' . GeneralUtility::quoteJSvalue($this->treeName) . ');';
|
||||
$thePageIcon = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $thePageIcon . '</a>';
|
||||
}
|
||||
// Wrap icon in a drag/drop span.
|
||||
$dragDropIcon = '<span class="list-tree-icon dragIcon" id="dragIconID_' . $row['uid'] . '">' . $thePageIcon . '</span> ';
|
||||
// Add Page ID:
|
||||
$pageIdStr = '';
|
||||
if ($this->ext_showPageId) {
|
||||
$pageIdStr = '<span class="dragId">[' . $row['uid'] . ']</span> ';
|
||||
}
|
||||
// Call stats information hook
|
||||
$stat = '';
|
||||
$_params = ['pages', $row['uid']];
|
||||
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['GLOBAL']['recStatInfoHooks'] ?? [] as $_funcRef) {
|
||||
$stat .= GeneralUtility::callUserFunction($_funcRef, $_params, $this);
|
||||
}
|
||||
return $dragDropIcon . $lockIcon . $pageIdStr . $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapping $title in a-tags.
|
||||
*
|
||||
* @param string $title Title string
|
||||
* @param string $row Item record
|
||||
* @param int $bank Bank pointer (which mount point number)
|
||||
* @return string
|
||||
* @internal
|
||||
*/
|
||||
public function wrapTitle($title, $row, $bank = 0)
|
||||
{
|
||||
// Hook for overriding the page title
|
||||
|
||||
$_params = ['title' => &$title, 'row' => &$row];
|
||||
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.webpagetree.php']['pageTitleOverlay'] ?? [] as $_funcRef) {
|
||||
GeneralUtility::callUserFunction($_funcRef, $_params, $this);
|
||||
}
|
||||
|
||||
$aOnClick = 'return jumpTo(' . GeneralUtility::quoteJSvalue($this->getJumpToParam($row)) . ',this,' . GeneralUtility::quoteJSvalue($this->domIdPrefix . $this->getId($row)) . ',' . $bank . ');';
|
||||
$clickMenuParts = BackendUtility::wrapClickMenuOnIcon('', 'pages', $row['uid'], 'tree', '', '', true);
|
||||
|
||||
$thePageTitle = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '" ' . GeneralUtility::implodeAttributes($clickMenuParts) . '>' . $title . '</a>';
|
||||
// Wrap title in a drag/drop span.
|
||||
return '<span class="list-tree-title dragTitle" id="dragTitleID_' . $row['uid'] . '">' . $thePageTitle . '</span>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the HTML code for displaying the structure found inside the ->tree array
|
||||
*
|
||||
* @param array|string $treeArr "tree-array" - if blank string, the internal ->tree array is used.
|
||||
* @return string The HTML code for the tree
|
||||
*/
|
||||
public function printTree($treeArr = '')
|
||||
{
|
||||
$titleLen = (int)$this->BE_USER->uc['titleLen'];
|
||||
if (!is_array($treeArr)) {
|
||||
$treeArr = $this->tree;
|
||||
}
|
||||
$out = '<ul class="list-tree list-tree-root">';
|
||||
// -- evaluate AJAX request
|
||||
// IE takes anchor as parameter
|
||||
$PM = GeneralUtility::_GP('PM');
|
||||
if (($PMpos = strpos($PM, '#')) !== false) {
|
||||
$PM = substr($PM, 0, $PMpos);
|
||||
}
|
||||
$PM = explode('_', $PM);
|
||||
|
||||
$doCollapse = false;
|
||||
$doExpand = false;
|
||||
$expandedPageUid = null;
|
||||
$collapsedPageUid = null;
|
||||
if (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_AJAX && is_array($PM) && count($PM) === 4 && $PM[2] != 0) {
|
||||
if ($PM[1]) {
|
||||
$expandedPageUid = $PM[2];
|
||||
$doExpand = true;
|
||||
} else {
|
||||
$collapsedPageUid = $PM[2];
|
||||
$doCollapse = true;
|
||||
}
|
||||
}
|
||||
// We need to count the opened <ul>'s every time we dig into another level,
|
||||
// so we know how many we have to close when all children are done rendering
|
||||
$closeDepth = [];
|
||||
$ajaxOutput = '';
|
||||
$invertedDepthOfAjaxRequestedItem = 0;
|
||||
foreach ($treeArr as $k => $treeItem) {
|
||||
$classAttr = $treeItem['row']['_CSSCLASS'];
|
||||
$uid = $treeItem['row']['uid'];
|
||||
$idAttr = htmlspecialchars($this->domIdPrefix . $this->getId($treeItem['row']) . '_' . $treeItem['bank']);
|
||||
$itemHTML = '';
|
||||
// If this item is the start of a new level,
|
||||
// then a new level <ul> is needed, but not in ajax mode
|
||||
if ($treeItem['isFirst'] && !$doCollapse && (!$doExpand || (int)$expandedPageUid !== (int)$uid)) {
|
||||
$itemHTML = '<ul class="list-tree">';
|
||||
}
|
||||
|
||||
// Add CSS classes to the list item
|
||||
if ($treeItem['hasSub']) {
|
||||
$classAttr .= ' list-tree-control-open';
|
||||
}
|
||||
$itemHTML .= '<li id="' . $idAttr . '" ' . ($classAttr ? ' class="' . trim($classAttr) . '"' : '')
|
||||
. '><span class="list-tree-group">' . $treeItem['HTML']
|
||||
. $this->wrapTitle($this->getTitleStr($treeItem['row'], $titleLen), $treeItem['row'], $treeItem['bank']) . '</span>';
|
||||
if (!$treeItem['hasSub']) {
|
||||
$itemHTML .= '</li>';
|
||||
}
|
||||
|
||||
// We have to remember if this is the last one
|
||||
// on level X so the last child on level X+1 closes the <ul>-tag
|
||||
if ($treeItem['isLast'] && !($doExpand && $expandedPageUid == $uid)) {
|
||||
$closeDepth[$treeItem['invertedDepth']] = 1;
|
||||
}
|
||||
// If this is the last one and does not have subitems, we need to close
|
||||
// the tree as long as the upper levels have last items too
|
||||
if ($treeItem['isLast'] && !$treeItem['hasSub'] && !$doCollapse && !($doExpand && $expandedPageUid == $uid)) {
|
||||
for ($i = $treeItem['invertedDepth']; $closeDepth[$i] == 1; $i++) {
|
||||
$closeDepth[$i] = 0;
|
||||
$itemHTML .= '</ul></li>';
|
||||
}
|
||||
}
|
||||
// Ajax request: collapse
|
||||
if ($doCollapse && (int)$collapsedPageUid === (int)$uid) {
|
||||
$this->ajaxStatus = true;
|
||||
return $itemHTML;
|
||||
}
|
||||
// ajax request: expand
|
||||
if ($doExpand && (int)$expandedPageUid === (int)$uid) {
|
||||
$ajaxOutput .= $itemHTML;
|
||||
$invertedDepthOfAjaxRequestedItem = $treeItem['invertedDepth'];
|
||||
} elseif ($invertedDepthOfAjaxRequestedItem) {
|
||||
if ($treeItem['invertedDepth'] < $invertedDepthOfAjaxRequestedItem) {
|
||||
$ajaxOutput .= $itemHTML;
|
||||
} else {
|
||||
$this->ajaxStatus = true;
|
||||
return $ajaxOutput;
|
||||
}
|
||||
}
|
||||
$out .= $itemHTML;
|
||||
}
|
||||
if ($ajaxOutput) {
|
||||
$this->ajaxStatus = true;
|
||||
return $ajaxOutput;
|
||||
}
|
||||
// Finally close the first ul
|
||||
$out .= '</ul>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the plus/minus icon for the browsable tree.
|
||||
*
|
||||
* @param array $row Record for the entry
|
||||
* @param int $a The current entry number
|
||||
* @param int $c The total number of entries. If equal to $a, a "bottom" element is returned.
|
||||
* @param int $nextCount The number of sub-elements to the current element.
|
||||
* @param bool $exp The element was expanded to render subelements if this flag is set.
|
||||
* @return string Image tag with the plus/minus icon.
|
||||
* @internal
|
||||
* @see \TYPO3\CMS\Backend\Tree\View\PageTreeView::PMicon()
|
||||
*/
|
||||
public function PMicon($row, $a, $c, $nextCount, $exp)
|
||||
{
|
||||
$icon = '';
|
||||
if ($nextCount) {
|
||||
$cmd = $this->bank . '_' . ($exp ? '0_' : '1_') . $row['uid'] . '_' . $this->treeName;
|
||||
$icon = $this->PMiconATagWrap($icon, $cmd, !$exp);
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the plus/minus icon in a link
|
||||
*
|
||||
* @param string $icon HTML string to wrap, probably an image tag.
|
||||
* @param string $cmd Command for 'PM' get var
|
||||
* @param bool $isExpand Link-wrapped input string
|
||||
* @return string
|
||||
* @internal
|
||||
*/
|
||||
public function PMiconATagWrap($icon, $cmd, $isExpand = true)
|
||||
{
|
||||
if ($this->thisScript) {
|
||||
// Activate dynamic ajax-based tree
|
||||
$js = htmlspecialchars('Tree.load(' . GeneralUtility::quoteJSvalue($cmd) . ', ' . (int)$isExpand . ', this);');
|
||||
return '<a class="list-tree-control' . (!$isExpand ? ' list-tree-control-open' : ' list-tree-control-closed') . '" onclick="' . $js . '"><i class="fa"></i></a>';
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will create and return the HTML code for a browsable tree
|
||||
* Is based on the mounts found in the internal array ->MOUNTS (set in the constructor)
|
||||
*
|
||||
* @return string HTML code for the browsable tree
|
||||
*/
|
||||
public function getBrowsableTree()
|
||||
{
|
||||
// Get stored tree structure AND updating it if needed according to incoming PM GET var.
|
||||
$this->initializePositionSaving();
|
||||
// Init done:
|
||||
$treeArr = [];
|
||||
// Traverse mounts:
|
||||
$firstHtml = '';
|
||||
foreach ($this->MOUNTS as $idx => $uid) {
|
||||
// Set first:
|
||||
$this->bank = $idx;
|
||||
$isOpen = $this->stored[$idx][$uid] || $this->expandFirst || $uid === '0';
|
||||
// Save ids while resetting everything else.
|
||||
$curIds = $this->ids;
|
||||
$this->reset();
|
||||
$this->ids = $curIds;
|
||||
// Only, if not for uid 0
|
||||
if ($uid) {
|
||||
// Set PM icon for root of mount:
|
||||
$cmd = $this->bank . '_' . ($isOpen ? '0_' : '1_') . $uid . '_' . $this->treeName;
|
||||
$firstHtml = '<a class="list-tree-control list-tree-control-' . ($isOpen ? 'open' : 'closed')
|
||||
. '" href="' . htmlspecialchars($this->getThisScript() . 'PM=' . $cmd) . '"><i class="fa"></i></a>';
|
||||
}
|
||||
// Preparing rootRec for the mount
|
||||
if ($uid) {
|
||||
$rootRec = $this->getRecord($uid);
|
||||
$firstHtml .= $this->getIcon($rootRec);
|
||||
} else {
|
||||
// Artificial record for the tree root, id=0
|
||||
$rootRec = $this->getRootRecord();
|
||||
$firstHtml .= $this->getRootIcon($rootRec);
|
||||
}
|
||||
if (is_array($rootRec)) {
|
||||
// In case it was swapped inside getRecord due to workspaces.
|
||||
$uid = $rootRec['uid'];
|
||||
// Add the root of the mount to ->tree
|
||||
$this->tree[] = ['HTML' => $firstHtml, 'row' => $rootRec, 'bank' => $this->bank, 'hasSub' => true, 'invertedDepth' => 1000];
|
||||
// If the mount is expanded, go down:
|
||||
if ($isOpen) {
|
||||
// Set depth:
|
||||
if ($this->addSelfId) {
|
||||
$this->ids[] = $uid;
|
||||
}
|
||||
$this->getTree($uid);
|
||||
}
|
||||
// Add tree:
|
||||
$treeArr = array_merge($treeArr, $this->tree);
|
||||
}
|
||||
}
|
||||
return $this->printTree($treeArr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Backend layout element
|
||||
* @internal This class is a TYPO3 Backend implementation and is not considered part of the Public TYPO3 API.
|
||||
*/
|
||||
class BackendLayoutWizardElement extends AbstractFormElement
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $rows = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $colCount = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $rowCount = 0;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$lang = $this->getLanguageService();
|
||||
$resultArray = $this->initializeResultArray();
|
||||
$this->init();
|
||||
|
||||
$fieldInformationResult = $this->renderFieldInformation();
|
||||
$fieldInformationHtml = $fieldInformationResult['html'];
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
|
||||
|
||||
$fieldWizardResult = $this->renderFieldWizard();
|
||||
$fieldWizardHtml = $fieldWizardResult['html'];
|
||||
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
|
||||
|
||||
$json = json_encode($this->rows, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS);
|
||||
$html = [];
|
||||
$html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
|
||||
$html[] = $fieldInformationHtml;
|
||||
$html[] = '<div class="form-control-wrap">';
|
||||
$html[] = '<div class="form-wizards-wrap">';
|
||||
$html[] = '<div class="form-wizards-element">';
|
||||
$html[] = '<input';
|
||||
$html[] = ' type="hidden"';
|
||||
$html[] = ' name="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
|
||||
$html[] = ' value="' . htmlspecialchars($this->data['parameterArray']['itemFormElValue']) . '"';
|
||||
$html[] = '/>';
|
||||
$html[] = '<table class="grideditor table table-bordered">';
|
||||
$html[] = '<tr>';
|
||||
$html[] = '<td colspan="2" align="center">';
|
||||
$html[] = '<div class="btn-group">';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removerow-top" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-minus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addrow-top" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-plus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</td>';
|
||||
$html[] = '</tr>';
|
||||
$html[] = '<tr>';
|
||||
$html[] = '<td class="editor_cell">';
|
||||
$html[] = '<div';
|
||||
$html[] = ' id="editor"';
|
||||
$html[] = ' class="t3js-grideditor"';
|
||||
$html[] = ' data-data="' . htmlspecialchars($json) . '"';
|
||||
$html[] = ' data-rowcount="' . (int)$this->rowCount . '"';
|
||||
$html[] = ' data-colcount="' . (int)$this->colCount . '"';
|
||||
$html[] = ' data-field="' . htmlspecialchars($this->data['parameterArray']['itemFormElName']) . '"';
|
||||
$html[] = '>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</td>';
|
||||
$html[] = '<td>';
|
||||
$html[] = '<div class="btn-group-vertical">';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addcolumn" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addColumn')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-plus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removecolumn" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeColumn')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-minus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</td>';
|
||||
$html[] = '</tr>';
|
||||
$html[] = '<tr>';
|
||||
$html[] = '<td colspan="2" align="center">';
|
||||
$html[] = '<div class="btn-group">';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-addrow-bottom" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_addRow')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-plus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '<a class="btn btn-default btn-sm t3js-grideditor-removerow-bottom" href="#"';
|
||||
$html[] = ' title="' . htmlspecialchars($lang->getLL('grid_removeRow')) . '">';
|
||||
$html[] = '<i class="fa fa-fw fa-minus"></i>';
|
||||
$html[] = '</a>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</td>';
|
||||
$html[] = '</tr>';
|
||||
$html[] = '<tr>';
|
||||
$html[] = '<td colspan="2">';
|
||||
$html[] = '<a href="#" class="btn btn-default btn-sm t3js-grideditor-preview-button"></a>';
|
||||
$html[] = '<pre class="t3js-grideditor-preview-config grideditor-preview"><code></code></pre>';
|
||||
$html[] = '</td>';
|
||||
$html[] = '</tr>';
|
||||
$html[] = '</table>';
|
||||
$html[] = '</div>';
|
||||
if (!empty($fieldWizardHtml)) {
|
||||
$html[] = '<div class="form-wizards-items-bottom">';
|
||||
$html[] = $fieldWizardHtml;
|
||||
$html[] = '</div>';
|
||||
}
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
$html[] = '</div>';
|
||||
|
||||
$html = implode(LF, $html);
|
||||
$resultArray['html'] = $html;
|
||||
$resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/GridEditor' => 'function(GridEditor) { new GridEditor.GridEditor(); }'];
|
||||
$resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_wizards.xlf';
|
||||
$resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:backend/Resources/Private/Language/locallang.xlf';
|
||||
|
||||
return $resultArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize wizard
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
if (empty($this->data['databaseRow']['config'])) {
|
||||
$rows = [[['colspan' => 1, 'rowspan' => 1, 'spanned' => 0, 'name' => '0x0']]];
|
||||
$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;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user