[ 'CType' => 'container-downloads' ], ]; */ class ParentChildToContainerService { private const TABLE_NAME = 'tt_content'; 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->colPosOffset = $config['childParentColPosOffset'] ?? 0; $this->configuration = $config['childParentMigrationMapping'] ?? []; } public function migrate(): void { $this->initializeDataHandler(); $this->migrateConfiguredContainer(); } protected function initializeDataHandler(): void { $backendUser = GeneralUtility::makeInstance(BackendUserAuthentication::class); $backendUser->user = [ 'uid' => 0, 'admin' => 1, ]; $this->dataHandler->start([], [], $backendUser); } protected function migrateConfiguredContainer(): void { array_walk($this->configuration, function($config, $key) { $parents = $this->getParentsByCType((string)$key); foreach ($parents as $parent) { $this->processParentMigration($parent, $config); } }); } protected function processParentMigration(array $parent, array $config): void { $children = $this->getChildren($parent['uid']); foreach ($children as $child) { $this->processChildMigration($child, $parent); } $this->updateElement( $parent['uid'], [ 'CType' => $this->getCType($parent, $config), 'children' => 0, ] ); } protected function processChildMigration(array $child, array $parent): void { $this->updateElement( $child['uid'], [ 'tx_container_parent' => $parent['uid'], 'colPos' => $child['colPos'] + $this->colPosOffset, 'parent' => 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 updateElement(int $uid, array $changes): void { $this->connectionPool ->getConnectionForTable(self::TABLE_NAME) ->update(self::TABLE_NAME, $changes, ['uid' => $uid]); } protected function getChildren(int $parentUid): array { $queryBuilder = $this->getQueryBuilderForTable(); return $queryBuilder ->select('*') ->where( $queryBuilder->expr()->eq( 'parent', $queryBuilder->createNamedParameter($parentUid, \PDO::PARAM_INT) ) ) ->orderBy('sorting') ->executeQuery() ->fetchAllAssociative(); } protected function getParentsByCType(string $cType): array { $queryBuilder = $this->getQueryBuilderForTable(); $expr = $queryBuilder->expr(); return $queryBuilder ->select('*') ->where( $expr->eq('CType', $queryBuilder->createNamedParameter($cType)) ) ->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; } }