TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
|
||||
namespace TYPO3\CMS\Backend\View\Drawing;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\ContentFetcher;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\Grid;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumn;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridRow;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\LanguageColumn;
|
||||
use TYPO3\CMS\Backend\View\BackendViewFactory;
|
||||
use TYPO3\CMS\Backend\View\PageLayoutContext;
|
||||
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
|
||||
use TYPO3\CMS\Core\Domain\RecordFactory;
|
||||
use TYPO3\CMS\Core\Localization\LanguageService;
|
||||
use TYPO3\CMS\Core\Messaging\FlashMessage;
|
||||
use TYPO3\CMS\Core\Messaging\FlashMessageService;
|
||||
use TYPO3\CMS\Core\Schema\Exception\UndefinedSchemaException;
|
||||
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\View\ViewInterface;
|
||||
|
||||
/**
|
||||
* Backend Layout Renderer
|
||||
*
|
||||
* Draws a page layout - essentially, behaves as a wrapper for a view
|
||||
* which renders the Resources/Private/PageLayout/PageLayout template
|
||||
* with necessary assigned template variables.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
readonly class BackendLayoutRenderer
|
||||
{
|
||||
public function __construct(
|
||||
protected BackendViewFactory $backendViewFactory,
|
||||
protected RecordFactory $recordFactory,
|
||||
protected FlashMessageService $flashMessageService,
|
||||
) {}
|
||||
|
||||
public function getGridForPageLayoutContext(PageLayoutContext $context): Grid
|
||||
{
|
||||
$recordIdentityMap = $context->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'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user