Page TSconfig Configuration * * @internal This class is a specific Backend controller implementation and is not part of the TYPO3's Core API. */ #[AsController] final readonly class PageTsConfigRecordsOverviewController { public function __construct( private IconFactory $iconFactory, private UriBuilder $uriBuilder, private ModuleTemplateFactory $moduleTemplateFactory, ) {} public function handleRequest(ServerRequestInterface $request): ResponseInterface { $backendUser = $this->getBackendUser(); $currentModule = $request->getAttribute('module'); $currentModuleIdentifier = $currentModule->getIdentifier(); $pageId = (int)($request->getQueryParams()['id'] ?? 0); $pageRecord = BackendUtility::readPageAccess($pageId, $backendUser->getPagePermsClause(Permission::PAGE_SHOW)) ?: []; $moduleData = $request->getAttribute('moduleData'); if ($moduleData->cleanUp([])) { $backendUser->pushModuleData($currentModuleIdentifier, $moduleData->toArray()); } $view = $this->moduleTemplateFactory->create($request); $view->setTitle( $this->getLanguageService()->sL($currentModule->getTitle()), $pageId !== 0 && isset($pageRecord['title']) ? $pageRecord['title'] : '' ); // The page will show only if there is a valid page and if this page may be viewed by the user. if ($pageRecord !== []) { $view->getDocHeaderComponent()->setPageBreadcrumb($pageRecord); } $accessContent = false; if (($pageId && $pageRecord !== []) || ($backendUser->isAdmin() && !$pageId)) { $accessContent = true; if (!$pageId && $backendUser->isAdmin()) { $pageRecord = ['title' => '[root-level]', 'uid' => 0, 'pid' => 0]; } $view->assign('id', $pageId); // Setting up the buttons and the module menu for the doc header $view->getDocHeaderComponent()->setShortcutContext( $currentModule->getIdentifier(), $this->getLanguageService()->sL($currentModule->getTitle()), ['id' => $pageId] ); } $view->assign('accessContent', $accessContent); $pagesUsingTSConfig = $this->getOverviewOfPagesUsingTSConfig($currentModule); if (count($pagesUsingTSConfig) > 0) { $view->assign('overviewOfPagesUsingTSConfig', $pagesUsingTSConfig); } $view->makeDocHeaderModuleMenu(['id' => $pageId]); return $view->renderResponse('PageTsConfig/RecordsOverview'); } /** * Renders table rows of all pages containing TSConfig together with its rootline */ private function getOverviewOfPagesUsingTSConfig(ModuleInterface $currentModule): array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); $queryBuilder->getRestrictions() ->removeAll() ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, 0)); $res = $queryBuilder ->select('uid', 'TSconfig') ->from('pages') ->where( $queryBuilder->expr()->neq( 'TSconfig', $queryBuilder->createNamedParameter('') ), $queryBuilder->expr()->eq( 'sys_language_uid', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT) ) ) ->executeQuery(); $pageArray = []; while ($row = $res->fetchAssociative()) { $this->setInPageArray($pageArray, BackendUtility::BEgetRootLine($row['uid'], 'AND 1=1'), $row); } return $this->getList($currentModule, $pageArray); } /** * Builds a multidimensional array that reflects the page hierarchy. */ private function setInPageArray(array &$hierarchicArray, array $rootlineArray, array $row): void { ksort($rootlineArray); if (!($rootlineArray[0]['uid'] ?? false)) { array_shift($rootlineArray); } $currentElement = current($rootlineArray); $hierarchicArray[$currentElement['uid']] = htmlspecialchars($currentElement['title']); array_shift($rootlineArray); if (!empty($rootlineArray)) { if (!is_array($hierarchicArray[$currentElement['uid'] . '.'] ?? null)) { $hierarchicArray[$currentElement['uid'] . '.'] = []; } $this->setInPageArray($hierarchicArray[$currentElement['uid'] . '.'], $rootlineArray, $row); } else { $hierarchicArray[$currentElement['uid'] . '_'] = $this->extractLinesFromTSConfig($row); } } /** * Extract the lines of TSConfig from a given pages row. */ private function extractLinesFromTSConfig(array $row): array { $out = []; $out['uid'] = $row['uid']; $lines = GeneralUtility::trimExplode("\r\n", $row['TSconfig']); $out['writtenLines'] = count($lines); return $out; } /** * Recursive method to get the list of pages to show. */ private function getList(ModuleInterface $currentModule, array $pageArray, array $lines = [], int $pageDepth = 0): array { if ($pageArray === []) { return $lines; } foreach ($pageArray as $identifier => $title) { if (!MathUtility::canBeInterpretedAsInteger($identifier)) { continue; } $line = []; $line['padding'] = ($pageDepth * 20); $line['title'] = $identifier; if (isset($pageArray[$identifier . '_'])) { $line['link'] = $this->uriBuilder->buildUriFromRoute($currentModule->getIdentifier(), ['id' => $identifier]); $line['icon'] = $this->iconFactory->getIconForRecord('pages', BackendUtility::getRecordWSOL('pages', $identifier), IconSize::SMALL)->render(); $line['pageTitle'] = GeneralUtility::fixed_lgd_cs($title, 30); $line['lines'] = ($pageArray[$identifier . '_']['writtenLines'] === 0 ? '' : $pageArray[$identifier . '_']['writtenLines']); } else { $line['link'] = ''; $line['icon'] = $this->iconFactory->getIconForRecord('pages', BackendUtility::getRecordWSOL('pages', $identifier), IconSize::SMALL)->render(); $line['pageTitle'] = GeneralUtility::fixed_lgd_cs($title, 30); $line['lines'] = ''; } $lines[] = $line; $lines = $this->getList($currentModule, $pageArray[$identifier . '.'] ?? [], $lines, $pageDepth + 1); } return $lines; } private function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } private function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } }