getRecordIdentityMap(); $contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class); $grid = GeneralUtility::makeInstance(Grid::class, $context); if ($context->getDrawingConfiguration()->isLanguageComparisonMode()) { $languageId = $context->getSiteLanguage()->getLanguageId(); } else { $languageId = $context->getDrawingConfiguration()->getPrimaryLanguageId(); } $rows = $context->getBackendLayout()->getStructure()['__config']['backend_layout.']['rows.'] ?? []; ksort($rows); foreach ($rows as $row) { $rowObject = GeneralUtility::makeInstance(GridRow::class, $context); foreach ($row['columns.'] ?? [] as $column) { $columnObject = GeneralUtility::makeInstance(GridColumn::class, $context, $column); $rowObject->addColumn($columnObject); if (isset($column['colPos'])) { $records = $contentFetcher->getContentRecordsPerColumn($context, (int)$column['colPos'], $languageId); foreach ($records as $contentRecord) { try { // By calling record factory to create the record, it is also stored in the identity map. $contentRecord = $this->recordFactory->createResolvedRecordFromDatabaseRow('tt_content', $contentRecord, null, $recordIdentityMap); $columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $context, $columnObject, $contentRecord); $columnObject->addItem($columnItem); } catch (UndefinedSchemaException) { } } } } $grid->addRow($rowObject); } return $grid; } protected function createView(ServerRequestInterface $request, PageLayoutContext $pageLayoutContext): ViewInterface { $backendUser = $this->getBackendUser(); $view = $this->backendViewFactory->create($request); $view->assignMultiple([ 'context' => $pageLayoutContext, 'hideRestrictedColumns' => $pageLayoutContext->getDrawingConfiguration()->shouldHideRestrictedColumns(), 'allowEditContent' => $backendUser->check('tables_modify', 'tt_content'), 'maxTitleLength' => $backendUser->uc['titleLen'] ?? 20, ]); return $view; } /** * @param bool $renderUnused If true, renders the bottom column with unused records */ public function drawContent(ServerRequestInterface $request, PageLayoutContext $pageLayoutContext, bool $renderUnused = true): string { $view = $this->createView($request, $pageLayoutContext); if ($pageLayoutContext->getDrawingConfiguration()->isLanguageComparisonMode()) { $view->assign('languageColumns', $this->getLanguageColumnsForPageLayoutContext($pageLayoutContext)); } else { $context = $pageLayoutContext; // Check if we have to use a localized context for grid creation $primaryLanguageId = $pageLayoutContext->getDrawingConfiguration()->getPrimaryLanguageId(); if ($primaryLanguageId > 0) { // In case a localization is selected, clone the context with this language $localizedContext = $pageLayoutContext->cloneForLanguage( $pageLayoutContext->getSiteLanguage($primaryLanguageId) ); if ($localizedContext->getLocalizedPageRecord()) { // In case the localized context contains the corresponding // localized page record use this context for grid creation. $context = $localizedContext; } } $grid = $this->getGridForPageLayoutContext($context); $view->assign('grid', $grid); $view->assign('gridColumns', array_fill(1, $grid->getContext()->getBackendLayout()->getColCount(), null)); } $rendered = $view->render('PageLayout/PageLayout'); if ($renderUnused) { $rendered .= $this->renderUnused($request, $pageLayoutContext); } return $rendered; } protected function renderUnused(ServerRequestInterface $request, PageLayoutContext $pageLayoutContext): string { $contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class); $view = $this->createView($request, $pageLayoutContext); $unusedRecords = $contentFetcher->getUnusedRecords($pageLayoutContext); if (empty($unusedRecords)) { return ''; } $unusedElementsMessage = new FlashMessage( $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:staleUnusedElementsWarning'), $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:staleUnusedElementsWarningTitle'), ContextualFeedbackSeverity::WARNING ); $queue = $this->flashMessageService->getMessageQueueByIdentifier(); $queue->addMessage($unusedElementsMessage); $unusedGrid = GeneralUtility::makeInstance(Grid::class, $pageLayoutContext); $unusedRow = GeneralUtility::makeInstance(GridRow::class, $pageLayoutContext); $unusedColumn = GeneralUtility::makeInstance(GridColumn::class, $pageLayoutContext, ['name' => 'unused']); $unusedGrid->addRow($unusedRow); $unusedRow->addColumn($unusedColumn); foreach ($unusedRecords as $unusedRecord) { $unusedRecord = $this->recordFactory->createResolvedRecordFromDatabaseRow('tt_content', $unusedRecord, null, $pageLayoutContext->getRecordIdentityMap()); $item = GeneralUtility::makeInstance(GridColumnItem::class, $pageLayoutContext, $unusedColumn, $unusedRecord); $unusedColumn->addItem($item); } $view->assign('grid', $unusedGrid); $view->assign('gridColumns', null); return $view->render('PageLayout/UnusedRecords'); } protected function getLanguageColumnsForPageLayoutContext(PageLayoutContext $context): iterable { $contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class); $languageColumns = []; // default language $translationInfo = $contentFetcher->getTranslationData( $context, $contentFetcher->getFlatContentRecords($context, 0), 0 ); $defaultLanguageColumnObject = GeneralUtility::makeInstance( LanguageColumn::class, $context, $this->getGridForPageLayoutContext($context), $translationInfo ); foreach ($context->getLanguagesToShow() as $siteLanguage) { $localizedLanguageId = $siteLanguage->getLanguageId(); if ($localizedLanguageId <= 0) { continue; } $localizedContext = $context->cloneForLanguage($siteLanguage); if (!$localizedContext->getLocalizedPageRecord()) { continue; } $translationInfo = $contentFetcher->getTranslationData( $context, $contentFetcher->getFlatContentRecords($context, $localizedLanguageId), $localizedContext->getSiteLanguage()->getLanguageId() ); $translatedRows = $contentFetcher->getFlatContentRecords($context, $localizedLanguageId); foreach ($defaultLanguageColumnObject->getGrid()->getRows() as $rows) { foreach ($rows->getColumns() as $column) { if (($translationInfo['mode'] ?? '') === 'connected') { foreach ($column->getItems() as $item) { // check if translation exists foreach ($translatedRows as $translation) { if ($translation['l18n_parent'] === $item->getRecord()->getUid()) { $translation = $this->recordFactory->createResolvedRecordFromDatabaseRow('tt_content', $translation, null, $context->getRecordIdentityMap()); $translatedItem = GeneralUtility::makeInstance(GridColumnItem::class, $localizedContext, $column, $translation); $item->addTranslation($localizedLanguageId, $translatedItem); } } } } } } $languageColumnObject = GeneralUtility::makeInstance( LanguageColumn::class, $localizedContext, $this->getGridForPageLayoutContext($localizedContext), $translationInfo ); $languageColumns[$localizedLanguageId] = $languageColumnObject; } return [$defaultLanguageColumnObject] + $languageColumns; } protected function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } protected function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } }