269 lines
8.7 KiB
PHP
Executable File
269 lines
8.7 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Evoweb\EwBase\Updates;
|
|
|
|
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
|
use TYPO3\CMS\Core\Database\ConnectionPool;
|
|
use TYPO3\CMS\Core\Database\Query\QueryBuilder;
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\EndTimeRestriction;
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
|
|
use TYPO3\CMS\Core\Database\Query\Restriction\StartTimeRestriction;
|
|
use TYPO3\CMS\Core\DataHandling\DataHandler;
|
|
use TYPO3\CMS\Core\Service\FlexFormService;
|
|
use TYPO3\CMS\Core\Utility\ArrayUtility;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
|
|
/**
|
|
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationResolveContainer'] = [];
|
|
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationColPosOffset'] = 0;
|
|
$GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base']['migrationMapping'] = [
|
|
'130' => [
|
|
'CType' => 'three-col-columns',
|
|
],
|
|
'140' => [
|
|
'CType' => [
|
|
'search' => 'pi_flexform/type',
|
|
'matches' => [
|
|
0 => 'two-col-columns-11',
|
|
1 => 'two-col-columns-12',
|
|
2 => 'two-col-columns-21',
|
|
],
|
|
],
|
|
'map' => [
|
|
'pi_flexform/row_class' => 'frame_class',
|
|
]
|
|
],
|
|
];
|
|
*/
|
|
|
|
class GridelementsToContainerService
|
|
{
|
|
private const TABLE_NAME = 'tt_content';
|
|
|
|
protected array $resolveContainer = [];
|
|
|
|
protected int $colPosOffset = 0;
|
|
|
|
protected array $configuration = [];
|
|
|
|
public function __construct(
|
|
protected ConnectionPool $connectionPool,
|
|
protected DataHandler $dataHandler,
|
|
protected FlexFormService $flexFormService,
|
|
) {
|
|
$config =& $GLOBALS['TYPO3_CONF_VARS']['EXTENSIONS']['ew_base'];
|
|
$this->resolveContainer = $config['migrationResolveContainer'] ?? [];
|
|
$this->colPosOffset = $config['migrationColPosOffset'] ?? 0;
|
|
$this->configuration = $config['migrationMapping'] ?? [];
|
|
}
|
|
|
|
public function migrate(): void
|
|
{
|
|
$this->initializeDataHandler();
|
|
|
|
// Move children out of container and remove container
|
|
foreach ($this->resolveContainer as $containerId) {
|
|
$this->resolveContainers((string)$containerId);
|
|
}
|
|
|
|
$this->migrateConfiguredContainer();
|
|
}
|
|
|
|
protected function initializeDataHandler(): void
|
|
{
|
|
$backendUser = GeneralUtility::makeInstance(BackendUserAuthentication::class);
|
|
$backendUser->user = [
|
|
'uid' => 0,
|
|
'admin' => 1,
|
|
];
|
|
$this->dataHandler->start([], [], $backendUser);
|
|
}
|
|
|
|
|
|
protected function resolveContainers(string $layout): void
|
|
{
|
|
$containers = $this->getGridElementsByLayout($layout);
|
|
foreach ($containers as $container) {
|
|
$this->processContainerResolve($container);
|
|
}
|
|
}
|
|
|
|
protected function processContainerResolve(array $container): void
|
|
{
|
|
$children = $this->getGridContainerChildren($container['uid']);
|
|
// move first child after container
|
|
$moveAfterThis = $container;
|
|
foreach ($children as $child) {
|
|
[$moveAfterThis, $container] = $this->processContainerResolveChild($child, $moveAfterThis, $container);
|
|
}
|
|
|
|
$this->deleteElement($container['uid']);
|
|
}
|
|
|
|
protected function processContainerResolveChild(array $child, array $moveAfterThis, array $container): array
|
|
{
|
|
$this->updateElement(
|
|
$child['uid'],
|
|
[
|
|
'tx_gridelements_container' => 0,
|
|
'colPos' => $container['colPos'],
|
|
'header' => $child['header'] ?: $container['header']
|
|
]
|
|
);
|
|
$this->moveElementAfterElement($child['uid'], $moveAfterThis['uid']);
|
|
// use this child to move the next child after
|
|
$moveAfterThis = $child;
|
|
// empty container header so only the first child gets the header
|
|
$container['header'] = '';
|
|
|
|
return [$moveAfterThis, $container];
|
|
}
|
|
|
|
protected function deleteElement(int $uid): void
|
|
{
|
|
$this->connectionPool
|
|
->getConnectionForTable(self::TABLE_NAME)
|
|
->update(self::TABLE_NAME, ['delete' => 1], ['uid' => $uid]);
|
|
}
|
|
|
|
protected function moveElementAfterElement(int $elementToMove, int $elementToMoveAfter): void
|
|
{
|
|
$this->dataHandler->moveRecord(self::TABLE_NAME, $elementToMove, $elementToMoveAfter * -1);
|
|
}
|
|
|
|
|
|
protected function migrateConfiguredContainer(): void
|
|
{
|
|
array_walk($this->configuration, function($config, $key) {
|
|
$containers = $this->getGridElementsByLayout((string)$key);
|
|
foreach ($containers as $container) {
|
|
$container['pi_flexform'] = $this->flexFormService->convertFlexFormContentToArray(
|
|
$container['pi_flexform']
|
|
);
|
|
$this->processContainerMigration($container, $config);
|
|
}
|
|
});
|
|
}
|
|
|
|
protected function processContainerMigration(array $container, array $config): void
|
|
{
|
|
$children = $this->getGridContainerChildren($container['uid']);
|
|
foreach ($children as $child) {
|
|
$this->processContainerMigrationChild($child, $container);
|
|
}
|
|
|
|
$data = [
|
|
'CType' => $this->getCType($container, $config),
|
|
'tx_gridelements_backend_layout' => ''
|
|
];
|
|
|
|
if (isset($config['map']) && is_array($config['map']) && !empty($container['pi_flexform'])) {
|
|
$data = $this->addMappedValues($data, $container, $config['map']);
|
|
}
|
|
|
|
$this->updateElement($container['uid'], $data);
|
|
}
|
|
|
|
protected function processContainerMigrationChild(array $child, array $container): void
|
|
{
|
|
$this->updateElement(
|
|
$child['uid'],
|
|
[
|
|
'hidden' => $child['hidden'] ?: $container['hidden'],
|
|
'colPos' => $child['tx_gridelements_columns'] + $this->colPosOffset,
|
|
'tx_container_parent' => $child['tx_gridelements_container'],
|
|
'tx_gridelements_columns' => 0,
|
|
'tx_gridelements_container' => 0,
|
|
]
|
|
);
|
|
}
|
|
|
|
protected function getCType(array $container, array $config): string
|
|
{
|
|
if (is_array($config['CType'])) {
|
|
$value = ArrayUtility::getValueByPath($container, $config['CType']['search']);
|
|
$result = $config['CType']['matches'][$value] ?? null;
|
|
} else {
|
|
$result = $config['CType'] ?? null;
|
|
}
|
|
|
|
if (empty($result)) {
|
|
throw new \Exception('CType must always be set');
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
protected function addMappedValues(array $data, array $container, array $config): array
|
|
{
|
|
foreach ($config as $from => $to) {
|
|
try {
|
|
$value = ArrayUtility::getValueByPath($container, $from);
|
|
if (empty($container[$to]) && !empty($value)) {
|
|
$data[$to] = $value;
|
|
}
|
|
} catch (\throwable) {}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
|
|
protected function updateElement(int $uid, array $changes): void
|
|
{
|
|
$this->connectionPool
|
|
->getConnectionForTable(self::TABLE_NAME)
|
|
->update(self::TABLE_NAME, $changes, ['uid' => $uid]);
|
|
}
|
|
|
|
protected function getGridContainerChildren(int $containerUid): array
|
|
{
|
|
$queryBuilder = $this->getQueryBuilderForTable();
|
|
|
|
return $queryBuilder
|
|
->select('*')
|
|
->where(
|
|
$queryBuilder->expr()->eq(
|
|
'tx_gridelements_container',
|
|
$queryBuilder->createNamedParameter($containerUid, \PDO::PARAM_INT)
|
|
)
|
|
)
|
|
->orderBy('sorting')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
}
|
|
|
|
protected function getGridElementsByLayout(string $layout): array
|
|
{
|
|
$queryBuilder = $this->getQueryBuilderForTable();
|
|
$expr = $queryBuilder->expr();
|
|
|
|
return $queryBuilder
|
|
->select('*')
|
|
->where(
|
|
$expr->eq('CType', $queryBuilder->createNamedParameter('gridelements_pi1')),
|
|
$expr->eq('tx_gridelements_backend_layout', $queryBuilder->createNamedParameter($layout))
|
|
)
|
|
->orderBy('sorting')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
}
|
|
|
|
protected function getQueryBuilderForTable(string $table = 'tt_content'): QueryBuilder
|
|
{
|
|
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
|
|
->getQueryBuilderForTable($table);
|
|
|
|
$queryBuilder->getRestrictions()
|
|
->removeByType(HiddenRestriction::class)
|
|
->removeByType(StartTimeRestriction::class)
|
|
->removeByType(EndTimeRestriction::class);
|
|
|
|
$queryBuilder->from($table);
|
|
|
|
return $queryBuilder;
|
|
}
|
|
}
|