diff --git a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php index 1cd2c49f9488..be3f4f48df0d 100644 --- a/typo3/sysext/backend/Classes/Controller/PageLayoutController.php +++ b/typo3/sysext/backend/Classes/Controller/PageLayoutController.php @@ -25,6 +25,7 @@ use TYPO3\CMS\Backend\Template\ModuleTemplate; use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Backend\View\BackendLayoutView; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Backend\View\PageLayoutView; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Configuration\Features; @@ -160,9 +161,9 @@ class PageLayoutController protected $uriBuilder; /** - * @var BackendLayoutView + * @var PageLayoutContext */ - protected $backendLayouts; + protected $context; /** * Injects the request object for the current request or subrequest @@ -179,13 +180,18 @@ public function mainAction(ServerRequestInterface $request): ResponseInterface $this->iconFactory = $this->moduleTemplate->getIconFactory(); $this->uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); $this->buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar(); - $this->backendLayouts = GeneralUtility::makeInstance(BackendLayoutView::class); $this->getLanguageService()->includeLLFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf'); // Setting module configuration / page select clause $this->id = (int)($request->getParsedBody()['id'] ?? $request->getQueryParams()['id'] ?? 0); // Load page info array $this->pageinfo = BackendUtility::readPageAccess($this->id, $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)); + $this->context = GeneralUtility::makeInstance( + PageLayoutContext::class, + $this->pageinfo, + GeneralUtility::makeInstance(BackendLayoutView::class)->getBackendLayoutForPage($this->id) + ); + /** @var SiteInterface $currentSite */ $currentSite = $request->getAttribute('site'); $this->availableLanguages = $currentSite->getAvailableLanguages($this->getBackendUser(), false, $this->id); @@ -547,8 +553,9 @@ function deleteRecord(table,id,url) { // } '); + $backendLayout = $this->context->getBackendLayout(); + // Find backend layout / columns - $backendLayout = $this->backendLayouts->getBackendLayoutForPage($this->id); if (!empty($backendLayout->getColumnPositionNumbers())) { $this->colPosList = implode(',', $backendLayout->getColumnPositionNumbers()); } @@ -619,26 +626,26 @@ protected function renderContent(): string $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/LayoutModule/Paste'); $this->pageRenderer->addInlineLanguageLabelFile('EXT:backend/Resources/Private/Language/locallang_layout.xlf'); - $backendLayout = $this->backendLayouts->getBackendLayoutForPage((int)$this->id); + $backendLayout = $this->context->getBackendLayout(); - $configuration = $backendLayout->getDrawingConfiguration(); - $configuration->setPageId($this->id); + $configuration = $this->context->getDrawingConfiguration(); $configuration->setDefaultLanguageBinding(!empty($this->modTSconfig['properties']['defLangBinding'])); $configuration->setActiveColumns(GeneralUtility::trimExplode(',', $this->activeColPosList)); $configuration->setShowHidden((bool)$this->MOD_SETTINGS['tt_content_showHidden']); $configuration->setLanguageColumns($this->MOD_MENU['language']); - $configuration->setLanguageColumnsPointer((int)$this->current_sys_language); + $configuration->setShowNewContentWizard(empty($this->modTSconfig['properties']['disableNewContentElementWizard'])); + $configuration->setSelectedLanguageId((int)$this->MOD_SETTINGS['language']); if ($this->MOD_SETTINGS['function'] == 2) { $configuration->setLanguageMode(true); } - $configuration->setShowNewContentWizard(empty($this->modTSconfig['properties']['disableNewContentElementWizard'])); + $numberOfHiddenElements = $this->getNumberOfHiddenElements($configuration->getLanguageColumns()); if (GeneralUtility::makeInstance(Features::class)->isFeatureEnabled('fluidBasedPageModule')) { - $pageLayoutDrawer = $backendLayout->getBackendLayoutRenderer(); + $pageLayoutDrawer = $this->context->getBackendLayoutRenderer(); $pageActionsCallback = null; - if ($configuration->isPageEditable()) { + if ($this->context->isPageEditable()) { $languageOverlayId = 0; $pageLocalizationRecord = BackendUtility::getRecordLocalization('pages', $this->id, (int)$this->current_sys_language); if (is_array($pageLocalizationRecord)) { @@ -655,7 +662,7 @@ protected function renderContent(): string $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/PageActions', $pageActionsCallback); $tableOutput = $pageLayoutDrawer->drawContent(); } else { - $dbList = PageLayoutView::createFromDrawingConfiguration($configuration); + $dbList = PageLayoutView::createFromPageLayoutContext($this->context); // Setting up the tt_content columns to show $colList = array_keys($backendLayout->getUsedColumns()); if ($this->colPosList !== '') { diff --git a/typo3/sysext/backend/Classes/Preview/StandardContentPreviewRenderer.php b/typo3/sysext/backend/Classes/Preview/StandardContentPreviewRenderer.php index e08a4503cc81..059f7063b53b 100644 --- a/typo3/sysext/backend/Classes/Preview/StandardContentPreviewRenderer.php +++ b/typo3/sysext/backend/Classes/Preview/StandardContentPreviewRenderer.php @@ -54,7 +54,7 @@ class StandardContentPreviewRenderer implements PreviewRendererInterface, Logger public function renderPageModulePreviewHeader(GridColumnItem $item): string { $record = $item->getRecord(); - $itemLabels = $item->getBackendLayout()->getDrawingConfiguration()->getItemLabels(); + $itemLabels = $item->getContext()->getItemLabels(); $outHeader = ''; @@ -81,14 +81,14 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string $out = ''; $record = $item->getRecord(); - $contentTypeLabels = $item->getBackendLayout()->getDrawingConfiguration()->getContentTypeLabels(); + $contentTypeLabels = $item->getContext()->getContentTypeLabels(); $languageService = $this->getLanguageService(); $drawItem = true; $hookPreviewContent = ''; // Hook: Render an own preview of a record if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'])) { - $pageLayoutView = PageLayoutView::createFromDrawingConfiguration($item->getBackendLayout()->getDrawingConfiguration()); + $pageLayoutView = PageLayoutView::createFromPageLayoutContext($item->getContext()); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'] ?? [] as $className) { $hookObject = GeneralUtility::makeInstance($className); if (!$hookObject instanceof PageLayoutViewDrawItemHookInterface) { @@ -169,7 +169,7 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string case 'list': $hookOut = ''; if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'])) { - $pageLayoutView = PageLayoutView::createFromDrawingConfiguration($item->getBackendLayout()->getDrawingConfiguration()); + $pageLayoutView = PageLayoutView::createFromPageLayoutContext($item->getBackendLayout()); $_params = ['pObj' => &$pageLayoutView, 'row' => $record]; foreach ( $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['list_type_Info'][$record['list_type']] ?? @@ -240,7 +240,7 @@ public function renderPageModulePreviewFooter(GridColumnItem $item): string // Call drawFooter hooks if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawFooter'])) { - $pageLayoutView = PageLayoutView::createFromDrawingConfiguration($item->getBackendLayout()->getDrawingConfiguration()); + $pageLayoutView = PageLayoutView::createFromPageLayoutContext($item->getBackendLayout()); foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawFooter'] ?? [] as $className) { $hookObject = GeneralUtility::makeInstance($className); if (!$hookObject instanceof PageLayoutViewDrawFooterHookInterface) { @@ -273,7 +273,7 @@ public function wrapPageModulePreview(string $previewHeader, string $previewCont protected function getProcessedValue(GridColumnItem $item, string $fieldList, array &$info): void { - $itemLabels = $item->getBackendLayout()->getDrawingConfiguration()->getItemLabels(); + $itemLabels = $item->getContext()->getItemLabels(); $record = $item->getRecord(); $fieldArr = explode(',', $fieldList); foreach ($fieldArr as $field) { diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/BackendLayout.php b/typo3/sysext/backend/Classes/View/BackendLayout/BackendLayout.php index 7a838be53a8a..cd15ee4d4980 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/BackendLayout.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/BackendLayout.php @@ -15,14 +15,7 @@ namespace TYPO3\CMS\Backend\View\BackendLayout; -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\Grid; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumn; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridRow; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\LanguageColumn; use TYPO3\CMS\Backend\View\BackendLayoutView; -use TYPO3\CMS\Backend\View\Drawing\BackendLayoutRenderer; -use TYPO3\CMS\Backend\View\Drawing\DrawingConfiguration; use TYPO3\CMS\Core\Utility\GeneralUtility; /** @@ -67,26 +60,6 @@ class BackendLayout */ protected $data; - /** - * @var DrawingConfiguration - */ - protected $drawingConfiguration; - - /** - * @var ContentFetcher - */ - protected $contentFetcher; - - /** - * @var LanguageColumn[] - */ - protected $languageColumns = []; - - /** - * @var RecordRememberer - */ - protected $recordRememberer; - /** * @param string $identifier * @param string $title @@ -110,9 +83,6 @@ public static function create($identifier, $title, $configuration) */ public function __construct($identifier, $title, $configuration) { - $this->drawingConfiguration = GeneralUtility::makeInstance(DrawingConfiguration::class); - $this->contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class, $this); - $this->recordRememberer = GeneralUtility::makeInstance(RecordRememberer::class); $this->setIdentifier($identifier); $this->setTitle($title); if (is_array($configuration)) { @@ -250,90 +220,8 @@ public function getStructure(): array return $this->structure; } - /** - * @return LanguageColumn[] - */ - public function getLanguageColumns(): iterable - { - if (empty($this->languageColumns)) { - $availableLanguageColumns = $this->getDrawingConfiguration()->getLanguageColumns(); - foreach ($this->getDrawingConfiguration()->getSiteLanguages() as $siteLanguage) { - if (!isset($availableLanguageColumns[$siteLanguage->getLanguageId()])) { - continue; - } - $backendLayout = clone $this; - $backendLayout->getDrawingConfiguration()->setLanguageColumnsPointer($siteLanguage->getLanguageId()); - $this->languageColumns[] = GeneralUtility::makeInstance(LanguageColumn::class, $backendLayout, $siteLanguage); - } - } - return $this->languageColumns; - } - - public function getGrid(): Grid - { - $grid = GeneralUtility::makeInstance(Grid::class, $this); - foreach ($this->structure['__config']['backend_layout.']['rows.'] ?? [] as $row) { - $rowObject = GeneralUtility::makeInstance(GridRow::class, $this); - foreach ($row['columns.'] as $column) { - $columnObject = GeneralUtility::makeInstance(GridColumn::class, $this, $column); - $rowObject->addColumn($columnObject); - } - $grid->addRow($rowObject); - } - $pageId = $this->drawingConfiguration->getPageId(); - $allowInconsistentLanguageHandling = (bool)(BackendUtility::getPagesTSconfig($pageId)['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false); - if (!$allowInconsistentLanguageHandling && $this->getLanguageModeIdentifier() === 'connected') { - $grid->setAllowNewContent(false); - } - return $grid; - } - public function getColumnPositionNumbers(): array { return $this->structure['__colPosList']; } - - public function getContentFetcher(): ContentFetcher - { - return $this->contentFetcher; - } - - public function setContentFetcher(ContentFetcher $contentFetcher): void - { - $this->contentFetcher = $contentFetcher; - } - - public function getDrawingConfiguration(): DrawingConfiguration - { - return $this->drawingConfiguration; - } - - public function setDrawingConfiguration(DrawingConfiguration $drawingConfiguration): void - { - $this->drawingConfiguration = $drawingConfiguration; - } - - public function getBackendLayoutRenderer(): BackendLayoutRenderer - { - return GeneralUtility::makeInstance(BackendLayoutRenderer::class, $this); - } - - public function getRecordRememberer(): RecordRememberer - { - return $this->recordRememberer; - } - - public function getLanguageModeIdentifier(): string - { - $contentRecordsPerColumn = $this->contentFetcher->getContentRecordsPerColumn(null, $this->drawingConfiguration->getLanguageColumnsPointer()); - $contentRecords = empty($contentRecordsPerColumn) ? [] : array_merge(...$contentRecordsPerColumn); - $translationData = $this->contentFetcher->getTranslationData($contentRecords, $this->drawingConfiguration->getLanguageColumnsPointer()); - return $translationData['mode'] ?? ''; - } - - public function __clone() - { - $this->drawingConfiguration = clone $this->drawingConfiguration; - $this->contentFetcher->setBackendLayout($this); - } } diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/ContentFetcher.php b/typo3/sysext/backend/Classes/View/BackendLayout/ContentFetcher.php index 64add58c75a4..4a5785f4f0c9 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/ContentFetcher.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/ContentFetcher.php @@ -19,7 +19,10 @@ use Doctrine\DBAL\Driver\Statement; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Backend\View\PageLayoutView; +use TYPO3\CMS\Core\Cache\CacheManager; +use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; @@ -41,30 +44,19 @@ class ContentFetcher { /** - * @var BackendLayout + * @var PageLayoutContext */ - protected $backendLayout; + protected $context; /** * @var array */ protected $fetchedContentRecords = []; - /** - * Stores whether a certain language has translations in it - * - * @var array - */ - protected $languageHasTranslationsCache = []; - - public function __construct(BackendLayout $backendLayout) + public function __construct(PageLayoutContext $pageLayoutContext) { - $this->backendLayout = $backendLayout; - } - - public function setBackendLayout(BackendLayout $backendLayout): void - { - $this->backendLayout = $backendLayout; + $this->context = $pageLayoutContext; + $this->fetchedContentRecords = $this->getRuntimeCache()->get('ContentFetcher_fetchedContentRecords') ?: []; } /** @@ -77,18 +69,30 @@ public function setBackendLayout(BackendLayout $backendLayout): void */ public function getContentRecordsPerColumn(?int $columnNumber = null, ?int $languageId = null): iterable { + $languageId = $languageId ?? $this->context->getSiteLanguage()->getLanguageId(); + if (empty($this->fetchedContentRecords)) { + $isLanguageMode = $this->context->getDrawingConfiguration()->getLanguageMode(); $queryBuilder = $this->getQueryBuilder(); $records = $this->getResult($queryBuilder->execute()); foreach ($records as $record) { $recordLanguage = (int)$record['sys_language_uid']; $recordColumnNumber = (int)$record['colPos']; + if ($recordLanguage === -1) { + // Record is set to "all languages", place it according to view mode. + if ($isLanguageMode) { + // Force the record to only be shown in default language in "Languages" view mode. + $recordLanguage = 0; + } else { + // Force the record to be shown in the currently active language in "Columns" view mode. + $recordLanguage = $languageId; + } + } $this->fetchedContentRecords[$recordLanguage][$recordColumnNumber][] = $record; } + $this->getRuntimeCache()->set('ContentFetcher_fetchedContentRecords', $this->fetchedContentRecords); } - $languageId = $languageId ?? $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(); - $contentByLanguage = &$this->fetchedContentRecords[$languageId]; if ($columnNumber === null) { @@ -98,9 +102,8 @@ public function getContentRecordsPerColumn(?int $columnNumber = null, ?int $lang return $contentByLanguage[$columnNumber] ?? []; } - public function getFlatContentRecords(): iterable + public function getFlatContentRecords(int $languageId): iterable { - $languageId = $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(); $contentRecords = $this->getContentRecordsPerColumn(null, $languageId); return empty($contentRecords) ? [] : array_merge(...$contentRecords); } @@ -114,11 +117,11 @@ public function getUnusedRecords(): iterable { $unrendered = []; $hookArray = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['record_is_used'] ?? []; - $pageLayoutView = PageLayoutView::createFromDrawingConfiguration($this->backendLayout->getDrawingConfiguration()); + $pageLayoutView = PageLayoutView::createFromPageLayoutContext($this->context); - $knownColumnPositionNumbers = $this->backendLayout->getColumnPositionNumbers(); - $rememberer = $this->backendLayout->getRecordRememberer(); - foreach ($this->fetchedContentRecords[$this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer()] ?? [] as $contentRecordsInColumn) { + $knownColumnPositionNumbers = $this->context->getBackendLayout()->getColumnPositionNumbers(); + $rememberer = GeneralUtility::makeInstance(RecordRememberer::class); + foreach ($this->getContentRecordsPerColumn(null, 0) as $contentRecordsInColumn) { foreach ($contentRecordsInColumn as $contentRecord) { $used = $rememberer->isRemembered((int)$contentRecord['uid']); // A hook mentioned that this record is used somewhere, so this is in fact "rendered" already @@ -136,47 +139,45 @@ public function getUnusedRecords(): iterable public function getTranslationData(iterable $contentElements, int $language): array { - $configuration = $this->backendLayout->getDrawingConfiguration(); - if ($language === 0) { return []; } - if (!isset($this->languageHasTranslationsCache[$language])) { - if ($language) { - $contentRecordsInDefaultLanguage = $this->getContentRecordsPerColumn(null, 0); - if (!empty($contentRecordsInDefaultLanguage)) { - $contentRecordsInDefaultLanguage = array_merge(...$contentRecordsInDefaultLanguage); - } - } else { - $contentRecordsInDefaultLanguage = $contentElements; + $languageTranslationInfo = $this->getRuntimeCache()->get('ContentFetcher_TranslationInfo_' . $language) ?: []; + if (empty($languageTranslationInfo)) { + $contentRecordsInDefaultLanguage = $this->getContentRecordsPerColumn(null, 0); + if (!empty($contentRecordsInDefaultLanguage)) { + $contentRecordsInDefaultLanguage = array_merge(...$contentRecordsInDefaultLanguage); } $untranslatedRecordUids = array_flip(array_column($contentRecordsInDefaultLanguage, 'uid')); foreach ($contentElements as $contentElement) { + if ((int)$contentElement['sys_language_uid'] === -1) { + continue; + } if ((int)$contentElement['l18n_parent'] === 0) { - $this->languageHasTranslationsCache[$language]['hasStandAloneContent'] = true; - $this->languageHasTranslationsCache[$language]['mode'] = 'free'; + $languageTranslationInfo['hasStandAloneContent'] = true; + $languageTranslationInfo['mode'] = 'free'; } if ((int)$contentElement['l18n_parent'] > 0) { - $this->languageHasTranslationsCache[$language]['hasTranslations'] = true; - $this->languageHasTranslationsCache[$language]['mode'] = 'connected'; + $languageTranslationInfo['hasTranslations'] = true; + $languageTranslationInfo['mode'] = 'connected'; } if ((int)$contentElement['l10n_source'] > 0) { unset($untranslatedRecordUids[(int)$contentElement['l10n_source']]); } } - if (!isset($this->languageHasTranslationsCache[$language])) { - $this->languageHasTranslationsCache[$language]['hasTranslations'] = false; + if (!isset($languageTranslationInfo['hasTranslations'])) { + $languageTranslationInfo['hasTranslations'] = false; } - $this->languageHasTranslationsCache[$language]['untranslatedRecordUids'] = array_keys($untranslatedRecordUids); + $languageTranslationInfo['untranslatedRecordUids'] = array_keys($untranslatedRecordUids); // Check for inconsistent translations, force "mixed" mode and dispatch a FlashMessage to user if such a case is encountered. - if (isset($this->languageHasTranslationsCache[$language]['hasStandAloneContent']) - && $this->languageHasTranslationsCache[$language]['hasTranslations'] + if (isset($languageTranslationInfo['hasStandAloneContent']) + && $languageTranslationInfo['hasTranslations'] ) { - $this->languageHasTranslationsCache[$language]['mode'] = 'mixed'; - $siteLanguage = $configuration->getSiteLanguage($language); + $languageTranslationInfo['mode'] = 'mixed'; + $siteLanguage = $this->context->getSiteLanguage(); $message = GeneralUtility::makeInstance( FlashMessage::class, sprintf($this->getLanguageService()->getLL('staleTranslationWarning'), $siteLanguage->getTitle()), @@ -187,8 +188,10 @@ public function getTranslationData(iterable $contentElements, int $language): ar $queue = $service->getMessageQueueByIdentifier(); $queue->addMessage($message); } + + $this->getRuntimeCache()->set('ContentFetcher_TranslationInfo_' . $language, $languageTranslationInfo); } - return $this->languageHasTranslationsCache[$language]; + return $languageTranslationInfo; } protected function getQueryBuilder(): QueryBuilder @@ -207,7 +210,7 @@ protected function getQueryBuilder(): QueryBuilder $queryBuilder->andWhere( $queryBuilder->expr()->eq( 'tt_content.pid', - $queryBuilder->createNamedParameter($this->backendLayout->getDrawingConfiguration()->getPageId(), \PDO::PARAM_INT) + $queryBuilder->createNamedParameter($this->context->getPageId(), \PDO::PARAM_INT) ) ); @@ -224,7 +227,7 @@ protected function getQueryBuilder(): QueryBuilder $hookObject->modifyQuery( $parameters, 'tt_content', - $this->backendLayout->getDrawingConfiguration()->getPageId(), + $this->context->getPageId(), $additionalConstraints, $fields, $queryBuilder @@ -251,4 +254,9 @@ protected function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } + + protected function getRuntimeCache(): VariableFrontend + { + return GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_runtime'); + } } diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/AbstractGridObject.php b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/AbstractGridObject.php index 2635bf2331ec..6c9e8a377fbd 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/AbstractGridObject.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/AbstractGridObject.php @@ -17,7 +17,7 @@ namespace TYPO3\CMS\Backend\View\BackendLayout\Grid; -use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Imaging\IconFactory; use TYPO3\CMS\Core\Localization\LanguageService; @@ -38,9 +38,9 @@ abstract class AbstractGridObject { /** - * @var BackendLayout + * @var PageLayoutContext */ - protected $backendLayout; + protected $context; /** * @var IconFactory @@ -52,9 +52,9 @@ abstract class AbstractGridObject */ protected $uniqueId; - public function __construct(BackendLayout $backendLayout) + public function __construct(PageLayoutContext $context) { - $this->backendLayout = $backendLayout; + $this->context = $context; $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); } @@ -63,9 +63,9 @@ public function getUniqueId(): string return $this->uniqueId ?? $this->uniqueId = StringUtility::getUniqueId(); } - public function getBackendLayout(): BackendLayout + public function getContext(): PageLayoutContext { - return $this->backendLayout; + return $this->context; } protected function getLanguageService(): LanguageService diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/Grid.php b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/Grid.php index 9e8330254052..38be6610672f 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/Grid.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/Grid.php @@ -67,19 +67,9 @@ public function getColumns(): iterable return $columns; } - public function isAllowNewContent(): bool - { - return $this->allowNewContent; - } - - public function setAllowNewContent(bool $allowNewContent): void - { - $this->allowNewContent = $allowNewContent; - } - public function getSpan(): int { - if (!isset($this->rows[0]) || $this->backendLayout->getDrawingConfiguration()->getLanguageMode()) { + if (!isset($this->rows[0]) || $this->context->getDrawingConfiguration()->getLanguageMode()) { return 1; } $span = 0; diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumn.php b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumn.php index 73ee24b53ab1..fadfd6465c2d 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumn.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumn.php @@ -19,7 +19,7 @@ use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; @@ -67,31 +67,19 @@ class GridColumn extends AbstractGridObject */ protected $rowSpan = 1; - /** - * @var array - */ - protected $records; - - public function __construct(BackendLayout $backendLayout, array $columnDefinition, ?array $records = null) + public function __construct(PageLayoutContext $context, array $columnDefinition) { - parent::__construct($backendLayout); + parent::__construct($context); $this->columnNumber = isset($columnDefinition['colPos']) ? (int)$columnDefinition['colPos'] : $this->columnNumber; $this->columnName = $columnDefinition['name'] ?? $this->columnName; $this->icon = $columnDefinition['icon'] ?? $this->icon; $this->colSpan = (int)($columnDefinition['colspan'] ?? $this->colSpan); $this->rowSpan = (int)($columnDefinition['rowspan'] ?? $this->rowSpan); - if ($this->columnNumber !== null) { - $this->records = $records ?? $backendLayout->getContentFetcher()->getContentRecordsPerColumn($this->columnNumber, $backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer()); - foreach ($this->records as $contentRecord) { - $columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $backendLayout, $this, $contentRecord); - $this->addItem($columnItem); - } - } } public function isActive(): bool { - return $this->columnNumber !== null && in_array($this->columnNumber, $this->backendLayout->getDrawingConfiguration()->getActiveColumns()); + return $this->columnNumber !== null && in_array($this->columnNumber, $this->context->getDrawingConfiguration()->getActiveColumns()); } public function addItem(GridColumnItem $item): void @@ -99,11 +87,6 @@ public function addItem(GridColumnItem $item): void $this->items[] = $item; } - public function getRecords(): iterable - { - return $this->records; - } - /** * @return GridColumnItem[] */ @@ -129,7 +112,7 @@ public function getIcon(): ?string public function getColSpan(): int { - if ($this->backendLayout->getDrawingConfiguration()->getLanguageMode()) { + if ($this->context->getDrawingConfiguration()->getLanguageMode()) { return 1; } return $this->colSpan; @@ -137,7 +120,7 @@ public function getColSpan(): int public function getRowSpan(): int { - if ($this->backendLayout->getDrawingConfiguration()->getLanguageMode()) { + if ($this->context->getDrawingConfiguration()->getLanguageMode()) { return 1; } return $this->rowSpan; @@ -157,9 +140,9 @@ public function getEditUrl(): ?string if (empty($this->items)) { return null; } - $pageRecord = $this->backendLayout->getDrawingConfiguration()->getPageRecord(); + $pageRecord = $this->context->getPageRecord(); if (!$this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT) - || !$this->getBackendUser()->checkLanguageAccess($this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer())) { + || !$this->getBackendUser()->checkLanguageAccess($this->context->getSiteLanguage()->getLanguageId())) { return null; } $pageTitleParamForAltDoc = '&recTitle=' . rawurlencode( @@ -172,10 +155,10 @@ public function getEditUrl(): ?string public function getNewContentUrl(): string { - $pageId = $this->backendLayout->getDrawingConfiguration()->getPageId(); + $pageId = $this->context->getPageId(); $urlParameters = [ 'id' => $pageId, - 'sys_language_uid' => $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(), + 'sys_language_uid' => $this->context->getSiteLanguage()->getLanguageId(), 'colPos' => $this->getColumnNumber(), 'uid_pid' => $pageId, 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') @@ -190,7 +173,7 @@ public function getTitle(): string { $columnNumber = $this->getColumnNumber(); $colTitle = (string)BackendUtility::getProcessedValue('tt_content', 'colPos', $columnNumber); - foreach ($this->backendLayout->getUsedColumns() as $colPos => $title) { + foreach ($this->context->getBackendLayout()->getUsedColumns() as $colPos => $title) { if ($colPos === $columnNumber) { $colTitle = (string)$this->getLanguageService()->sL($title); } @@ -221,9 +204,9 @@ public function isContentEditable(): bool if ($this->getBackendUser()->isAdmin()) { return true; } - $pageRecord = $this->backendLayout->getDrawingConfiguration()->getPageRecord(); + $pageRecord = $this->context->getPageRecord(); return !$pageRecord['editlock'] && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT) - && $this->getBackendUser()->checkLanguageAccess($this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer()); + && $this->getBackendUser()->checkLanguageAccess($this->context->getSiteLanguage()->getLanguageId()); } } diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumnItem.php b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumnItem.php index cf996b5e8fdc..e636f357b0ec 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumnItem.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/GridColumnItem.php @@ -20,7 +20,7 @@ use TYPO3\CMS\Backend\Preview\StandardPreviewRendererResolver; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Type\Bitmask\Permission; @@ -49,13 +49,11 @@ class GridColumnItem extends AbstractGridObject */ protected $column; - public function __construct(BackendLayout $backendLayout, GridColumn $column, array $record) + public function __construct(PageLayoutContext $context, GridColumn $column, array $record) { - parent::__construct($backendLayout); + parent::__construct($context); $this->column = $column; $this->record = $record; - $backendLayout->getRecordRememberer()->rememberRecordUid((int)$record['uid']); - $backendLayout->getRecordRememberer()->rememberRecordUid((int)$record['l18n_parent']); } public function isVersioned(): bool @@ -70,7 +68,7 @@ public function getPreview(): string ->resolveRendererFor( 'tt_content', $record, - $this->backendLayout->getDrawingConfiguration()->getPageId() + $this->context->getPageId() ); $previewHeader = $previewRenderer->renderPageModulePreviewHeader($this); $previewContent = $previewRenderer->renderPageModulePreviewContent($this); @@ -82,7 +80,7 @@ public function getWrapperClassName(): string $wrapperClassNames = []; if ($this->isDisabled()) { $wrapperClassNames[] = 't3-page-ce-hidden t3js-hidden-record'; - } elseif (!in_array($this->record['colPos'], $this->backendLayout->getColumnPositionNumbers())) { + } elseif (!in_array($this->record['colPos'], $this->context->getBackendLayout()->getColumnPositionNumbers())) { $wrapperClassNames[] = 't3-page-ce-warning'; } @@ -92,7 +90,7 @@ public function getWrapperClassName(): string public function isDelible(): bool { $backendUser = $this->getBackendUser(); - if (!$backendUser->doesUserHaveAccess($this->backendLayout->getDrawingConfiguration()->getPageRecord(), Permission::CONTENT_EDIT)) { + if (!$backendUser->doesUserHaveAccess($this->context->getPageRecord(), Permission::CONTENT_EDIT)) { return false; } return !(bool)($backendUser->getTSConfig()['options.']['disableDelete.']['tt_content'] ?? $backendUser->getTSConfig()['options.']['disableDelete'] ?? false); @@ -126,7 +124,7 @@ public function getFooterInfo(): string ->resolveRendererFor( 'tt_content', $record, - $this->backendLayout->getDrawingConfiguration()->getPageId() + $this->context->getPageId() ); return $previewRenderer->renderPageModulePreviewFooter($this); } @@ -162,9 +160,11 @@ public function getIcons(): string $icon = BackendUtility::wrapClickMenuOnIcon($icon, $table, $row['uid']); } $icons[] = $icon; - $siteLanguage = $this->backendLayout->getDrawingConfiguration()->getSiteLanguage((int)$row['sys_language_uid']); - if ($siteLanguage instanceof SiteLanguage) { - $icons[] = $this->renderLanguageFlag($siteLanguage); + if ($row['sys_language_uid'] >= 0) { + $siteLanguage = $this->context->getSiteLanguage(); + if ($siteLanguage instanceof SiteLanguage) { + $icons[] = $this->renderLanguageFlag($siteLanguage); + } } if ($lockInfo = BackendUtility::isRecordLocked('tt_content', $row['uid'])) { @@ -204,22 +204,6 @@ public function isDisabled(): bool || $enableCols['endtime'] && $row[$enableCols['endtime']] && $row[$enableCols['endtime']] < $GLOBALS['EXEC_TIME']; } - public function hasTranslation(): bool - { - $contentElements = $this->column->getRecords(); - $id = $this->backendLayout->getDrawingConfiguration()->getPageId(); - $language = $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(); - // If in default language, you may always create new entries - // Also, you may override this strict behavior via user TS Config - // If you do so, you're on your own and cannot rely on any support by the TYPO3 core. - $allowInconsistentLanguageHandling = (bool)(BackendUtility::getPagesTSconfig($id)['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false); - if ($language === 0 || $allowInconsistentLanguageHandling) { - return false; - } - - return $this->backendLayout->getContentFetcher()->getTranslationData($contentElements, $language)['hasTranslations'] ?? false; - } - public function isDeletePlaceholder(): bool { return VersionState::cast($this->record['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER); @@ -227,11 +211,11 @@ public function isDeletePlaceholder(): bool public function isEditable(): bool { - $languageId = $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(); + $languageId = $this->context->getSiteLanguage()->getLanguageId(); if ($this->getBackendUser()->isAdmin()) { return true; } - $pageRecord = $this->backendLayout->getDrawingConfiguration()->getPageRecord(); + $pageRecord = $this->context->getPageRecord(); return !$pageRecord['editlock'] && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::CONTENT_EDIT) && ($languageId === null || $this->getBackendUser()->checkLanguageAccess($languageId)); @@ -239,7 +223,7 @@ public function isEditable(): bool public function isDragAndDropAllowed(): bool { - $pageRecord = $this->backendLayout->getDrawingConfiguration()->getPageRecord(); + $pageRecord = $this->context->getPageRecord(); return (int)$this->record['l18n_parent'] === 0 && ( $this->getBackendUser()->isAdmin() @@ -262,10 +246,10 @@ public function getNewContentAfterTitle(): string public function getNewContentAfterUrl(): string { - $pageId = $this->backendLayout->getDrawingConfiguration()->getPageId(); + $pageId = $this->context->getPageId(); $urlParameters = [ 'id' => $pageId, - 'sys_language_uid' => $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer(), + 'sys_language_uid' => $this->context->getSiteLanguage()->getLanguageId(), 'colPos' => $this->column->getColumnNumber(), 'uid_pid' => -$this->record['uid'], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/LanguageColumn.php b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/LanguageColumn.php index a2dbb8b635e7..c28dc07064c3 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/Grid/LanguageColumn.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/Grid/LanguageColumn.php @@ -19,9 +19,8 @@ use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Core\Imaging\Icon; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Versioning\VersionState; @@ -42,96 +41,45 @@ */ class LanguageColumn extends AbstractGridObject { - /** - * @var SiteLanguage - */ - protected $siteLanguage; - - /** - * @var array - */ - protected $localizedPageRecord = []; - /** * @var array */ protected $localizationConfiguration = []; /** - * @var GridColumn|null + * @var Grid|null */ protected $grid; - public function __construct(BackendLayout $backendLayout, SiteLanguage $language) - { - parent::__construct($backendLayout); - $this->siteLanguage = $language; - $this->localizationConfiguration = BackendUtility::getPagesTSconfig($backendLayout->getDrawingConfiguration()->getPageId())['mod.']['web_layout.']['localization.'] ?? []; - if ($this->siteLanguage->getLanguageId() > 0) { - $pageLocalizationRecord = BackendUtility::getRecordLocalization( - 'pages', - $backendLayout->getDrawingConfiguration()->getPageId(), - $language->getLanguageId() - ); - if (is_array($pageLocalizationRecord)) { - $pageLocalizationRecord = reset($pageLocalizationRecord); - } - BackendUtility::workspaceOL('pages', $pageLocalizationRecord); - $this->localizedPageRecord = $pageLocalizationRecord; - } else { - $this->localizedPageRecord = $backendLayout->getDrawingConfiguration()->getPageRecord(); - } - } - - public function getLocalizedPageRecord(): ?array - { - return $this->localizedPageRecord ?: null; - } + /** + * @var array + */ + protected $translationInfo = [ + 'hasStandaloneContent' => false, + 'hasTranslations' => false, + 'untranslatedRecordUids' => [], + ]; - public function getSiteLanguage(): SiteLanguage + public function __construct(PageLayoutContext $context, Grid $grid, array $translationInfo) { - return $this->siteLanguage; + parent::__construct($context); + $this->localizationConfiguration = BackendUtility::getPagesTSconfig($context->getPageId())['mod.']['web_layout.']['localization.'] ?? []; + $this->grid = $grid; + $this->translationInfo = $translationInfo; } - public function getGrid(): Grid + public function getGrid(): ?Grid { - if (empty($this->grid)) { - $this->grid = $this->backendLayout->getGrid(); - } return $this->grid; } - public function getLanguageModeLabelClass(): string - { - $contentRecordsPerColumn = $this->backendLayout->getContentFetcher()->getFlatContentRecords(); - $translationData = $this->backendLayout->getContentFetcher()->getTranslationData($contentRecordsPerColumn, $this->siteLanguage->getLanguageId()); - return $translationData['mode'] === 'mixed' ? 'danger' : 'info'; - } - - public function getLanguageMode(): string - { - switch ($this->backendLayout->getLanguageModeIdentifier()) { - case 'mixed': - $languageMode = $this->getLanguageService()->getLL('languageModeMixed'); - break; - case 'connected': - $languageMode = $this->getLanguageService()->getLL('languageModeConnected'); - break; - case 'free': - $languageMode = $this->getLanguageService()->getLL('languageModeFree'); - break; - default: - $languageMode = ''; - } - return $languageMode; - } - public function getPageIcon(): string { + $localizedPageRecord = $this->context->getLocalizedPageRecord() ?? $this->context->getPageRecord(); return BackendUtility::wrapClickMenuOnIcon( - $this->iconFactory->getIconForRecord('pages', $this->localizedPageRecord, Icon::SIZE_SMALL)->render(), + $this->iconFactory->getIconForRecord('pages', $localizedPageRecord, Icon::SIZE_SMALL)->render(), 'pages', - $this->localizedPageRecord['uid'] + $localizedPageRecord['uid'] ); } @@ -142,8 +90,7 @@ public function getAllowTranslate(): bool public function getTranslationData(): array { - $contentFetcher = $this->backendLayout->getContentFetcher(); - return $contentFetcher->getTranslationData($contentFetcher->getFlatContentRecords(), $this->siteLanguage->getLanguageId()); + return $this->translationInfo; } public function getAllowTranslateCopy(): bool @@ -171,13 +118,13 @@ public function getPageEditUrl(): string $urlParameters = [ 'edit' => [ 'pages' => [ - $this->localizedPageRecord['uid'] => 'edit' + $this->context->getLocalizedPageRecord()['uid'] => 'edit' ] ], // Disallow manual adjustment of the language field for pages 'overrideVals' => [ 'pages' => [ - 'sys_language_uid' => $this->siteLanguage->getLanguageId() + 'sys_language_uid' => $this->context->getSiteLanguage()->getLanguageId() ] ], 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') @@ -188,7 +135,7 @@ public function getPageEditUrl(): string public function getAllowViewPage(): bool { - return !VersionState::cast($this->backendLayout->getDrawingConfiguration()->getPageRecord()['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER); + return !VersionState::cast($this->context->getPageRecord()['t3ver_state'])->equals(VersionState::DELETE_PLACEHOLDER); } public function getViewPageLinkTitle(): string @@ -198,14 +145,14 @@ public function getViewPageLinkTitle(): string public function getViewPageOnClick(): string { - $pageId = $this->backendLayout->getDrawingConfiguration()->getPageId(); + $pageId = $this->context->getPageId(); return BackendUtility::viewOnClick( $pageId, '', BackendUtility::BEgetRootLine($pageId), '', '', - '&L=' . $this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer() + '&L=' . $this->context->getSiteLanguage()->getLanguageId() ); } } diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/RecordRememberer.php b/typo3/sysext/backend/Classes/View/BackendLayout/RecordRememberer.php index 40f47db281a8..e9e9d11a1e03 100644 --- a/typo3/sysext/backend/Classes/View/BackendLayout/RecordRememberer.php +++ b/typo3/sysext/backend/Classes/View/BackendLayout/RecordRememberer.php @@ -26,6 +26,14 @@ class RecordRememberer implements SingletonInterface */ protected $rememberedUids = []; + public function rememberRecords(iterable $records): void + { + foreach ($records as $record) { + $this->rememberRecordUid($record['uid'] ?? 0); + $this->rememberRecordUid($record['l18n_parent'] ?? 0); + } + } + public function rememberRecordUid(int $uid): void { $this->rememberedUids[$uid] = $uid; diff --git a/typo3/sysext/backend/Classes/View/Drawing/BackendLayoutRenderer.php b/typo3/sysext/backend/Classes/View/Drawing/BackendLayoutRenderer.php index 77ba30f9a454..e2b6b9aaa2c1 100644 --- a/typo3/sysext/backend/Classes/View/Drawing/BackendLayoutRenderer.php +++ b/typo3/sysext/backend/Classes/View/Drawing/BackendLayoutRenderer.php @@ -20,10 +20,14 @@ use Psr\Log\LoggerAwareTrait; use TYPO3\CMS\Backend\Clipboard\Clipboard; use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\BackendLayout; +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\BackendLayout\RecordRememberer; +use TYPO3\CMS\Backend\View\PageLayoutContext; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; @@ -57,9 +61,14 @@ class BackendLayoutRenderer protected $iconFactory; /** - * @var BackendLayout + * @var PageLayoutContext */ - protected $backendLayout; + protected $context; + + /** + * @var ContentFetcher + */ + protected $contentFetcher; /** * @var Clipboard @@ -71,9 +80,10 @@ class BackendLayoutRenderer */ protected $view; - public function __construct(BackendLayout $backendLayout) + public function __construct(PageLayoutContext $context) { - $this->backendLayout = $backendLayout; + $this->context = $context; + $this->contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class, $context); $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); $this->initializeClipboard(); $objectManager = GeneralUtility::makeInstance(ObjectManager::class); @@ -84,7 +94,64 @@ public function __construct(BackendLayout $backendLayout) $this->view->getRenderingContext()->setControllerContext($controllerContext); $this->view->getRenderingContext()->getTemplatePaths()->fillDefaultsByPackageName('backend'); $this->view->getRenderingContext()->setControllerName('PageLayout'); - $this->view->assign('backendLayout', $backendLayout); + $this->view->assign('context', $context); + } + + public function getGridForPageLayoutContext(PageLayoutContext $context): Grid + { + $grid = GeneralUtility::makeInstance(Grid::class, $context); + $recordRememberer = GeneralUtility::makeInstance(RecordRememberer::class); + if ($context->getDrawingConfiguration()->getLanguageMode()) { + $languageId = $context->getSiteLanguage()->getLanguageId(); + } else { + $languageId = $context->getDrawingConfiguration()->getSelectedLanguageId(); + } + foreach ($context->getBackendLayout()->getStructure()['__config']['backend_layout.']['rows.'] ?? [] as $row) { + $rowObject = GeneralUtility::makeInstance(GridRow::class, $context); + foreach ($row['columns.'] as $column) { + $columnObject = GeneralUtility::makeInstance(GridColumn::class, $context, $column); + $rowObject->addColumn($columnObject); + $records = $this->contentFetcher->getContentRecordsPerColumn((int)$column['colPos'], $languageId); + $recordRememberer->rememberRecords($records); + foreach ($records as $contentRecord) { + $columnItem = GeneralUtility::makeInstance(GridColumnItem::class, $context, $columnObject, $contentRecord); + $columnObject->addItem($columnItem); + } + } + $grid->addRow($rowObject); + } + return $grid; + } + + /** + * @return LanguageColumn[] + */ + public function getLanguageColumnsForPageLayoutContext(PageLayoutContext $context): iterable + { + $languageColumns = []; + foreach ($context->getLanguagesToShow() as $siteLanguage) { + $localizedLanguageId = $siteLanguage->getLanguageId(); + if ($localizedLanguageId > 0) { + $localizedContext = $context->cloneForLanguage($siteLanguage); + if (!$localizedContext->getLocalizedPageRecord()) { + continue; + } + } else { + $localizedContext = $context; + } + $translationInfo = $this->contentFetcher->getTranslationData( + $this->contentFetcher->getFlatContentRecords($localizedLanguageId), + $localizedContext->getSiteLanguage()->getLanguageId() + ); + $languageColumnObject = GeneralUtility::makeInstance( + LanguageColumn::class, + $localizedContext, + $this->getGridForPageLayoutContext($localizedContext), + $translationInfo + ); + $languageColumns[] = $languageColumnObject; + } + return $languageColumns; } /** @@ -93,20 +160,20 @@ public function __construct(BackendLayout $backendLayout) */ public function drawContent(bool $renderUnused = true): string { - $this->view->assign('pageLayoutConfiguration', $this->backendLayout->getDrawingConfiguration()); - $this->view->assign('hideRestrictedColumns', (bool)(BackendUtility::getPagesTSconfig($this->backendLayout->getDrawingConfiguration()->getPageId())['mod.']['web_layout.']['hideRestrictedCols'] ?? false)); - if (!$this->backendLayout->getDrawingConfiguration()->getLanguageMode()) { - $this->view->assign('grid', $this->backendLayout->getGrid()); - } + $this->view->assign('hideRestrictedColumns', (bool)(BackendUtility::getPagesTSconfig($this->context->getPageId())['mod.']['web_layout.']['hideRestrictedCols'] ?? false)); $this->view->assign('newContentTitle', $this->getLanguageService()->getLL('newContentElement')); $this->view->assign('newContentTitleShort', $this->getLanguageService()->getLL('content')); $this->view->assign('allowEditContent', $this->getBackendUser()->check('tables_modify', 'tt_content')); + if ($this->context->getDrawingConfiguration()->getLanguageMode()) { + $this->view->assign('languageColumns', $this->getLanguageColumnsForPageLayoutContext($this->context)); + } else { + $this->view->assign('grid', $this->getGridForPageLayoutContext($this->context)); + } + $rendered = $this->view->render('PageLayout'); if ($renderUnused) { - $unusedBackendLayout = clone $this->backendLayout; - $unusedBackendLayout->getDrawingConfiguration()->setLanguageColumnsPointer($this->backendLayout->getDrawingConfiguration()->getLanguageColumnsPointer()); - $unusedRecords = $this->backendLayout->getContentFetcher()->getUnusedRecords(); + $unusedRecords = $this->contentFetcher->getUnusedRecords(); if (!empty($unusedRecords)) { $unusedElementsMessage = GeneralUtility::makeInstance( @@ -119,14 +186,19 @@ public function drawContent(bool $renderUnused = true): string $queue = $service->getMessageQueueByIdentifier(); $queue->addMessage($unusedElementsMessage); - $unusedGrid = GeneralUtility::makeInstance(Grid::class, $unusedBackendLayout); - $unusedRow = GeneralUtility::makeInstance(GridRow::class, $unusedBackendLayout); - $unusedColumn = GeneralUtility::makeInstance(GridColumn::class, $unusedBackendLayout, ['colPos' => 99, 'name' => 'unused'], $unusedRecords); + $unusedGrid = GeneralUtility::makeInstance(Grid::class, $this->context); + $unusedRow = GeneralUtility::makeInstance(GridRow::class, $this->context); + $unusedColumn = GeneralUtility::makeInstance(GridColumn::class, $this->context, ['colPos' => false, 'name' => 'unused']); $unusedGrid->addRow($unusedRow); $unusedRow->addColumn($unusedColumn); - $this->view->assign('unusedGrid', $unusedGrid); + foreach ($unusedRecords as $unusedRecord) { + $item = GeneralUtility::makeInstance(GridColumnItem::class, $this->context, $unusedColumn, $unusedRecord); + $unusedColumn->addItem($item); + } + + $this->view->assign('grid', $unusedGrid); $rendered .= $this->view->render('UnusedRecords'); } } @@ -148,7 +220,7 @@ protected function initializeClipboard(): void $this->clipboard->endClipboard(); $elFromTable = $this->clipboard->elFromTable('tt_content'); - if (!empty($elFromTable) && $this->backendLayout->getDrawingConfiguration()->isPageEditable()) { + if (!empty($elFromTable) && $this->context->isPageEditable()) { $pasteItem = (int)substr(key($elFromTable), 11); $pasteRecord = BackendUtility::getRecord('tt_content', (int)$pasteItem); $pasteTitle = (string)($pasteRecord['header'] ?: $pasteItem); diff --git a/typo3/sysext/backend/Classes/View/Drawing/DrawingConfiguration.php b/typo3/sysext/backend/Classes/View/Drawing/DrawingConfiguration.php index 46acee084707..6cdcc814c750 100644 --- a/typo3/sysext/backend/Classes/View/Drawing/DrawingConfiguration.php +++ b/typo3/sysext/backend/Classes/View/Drawing/DrawingConfiguration.php @@ -17,19 +17,8 @@ namespace TYPO3\CMS\Backend\View\Drawing; -use TYPO3\CMS\Backend\Routing\UriBuilder; -use TYPO3\CMS\Backend\Utility\BackendUtility; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction; -use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction; -use TYPO3\CMS\Core\Exception\SiteNotFoundException; use TYPO3\CMS\Core\Localization\LanguageService; -use TYPO3\CMS\Core\Site\Entity\NullSite; -use TYPO3\CMS\Core\Site\Entity\SiteLanguage; -use TYPO3\CMS\Core\Site\SiteFinder; -use TYPO3\CMS\Core\Type\Bitmask\Permission; -use TYPO3\CMS\Core\Utility\GeneralUtility; /** * Drawing Configuration @@ -44,66 +33,70 @@ class DrawingConfiguration { /** + * @var int + */ + protected $selectedLanguageId = 0; + + /** + * Determines whether rendering should happen with a visually aligned + * connection between default language and translation. When rendered + * with this flag enabled, any translated versions are vertically + * aligned so they are rendered in the same visual row as the original. + * * @var bool */ protected $defaultLanguageBinding = true; /** + * If TRUE, indicates that the current rendering method shows multiple + * languages (e.g. the "page" module is set in "Languages" mode. + * * @var bool */ protected $languageMode = false; /** * Key => "Language ID", Value "Label of language" + * * @var array */ protected $languageColumns = []; /** - * @var int - */ - protected $languageColumnsPointer = 0; - - /** + * Whether or not to show hidden records when rendering column contents. + * * @var bool */ protected $showHidden = true; /** + * An array list of currently active columns. Only column identifiers + * (colPos value) which are contained in this array will be rendered in + * the page module. + * * @var array */ protected $activeColumns = [1, 0, 2, 3]; /** - * @var array - */ - protected $contentTypeLabels = []; - - /** - * @var array - */ - protected $itemLabels = []; - - /** - * @var int - */ - protected $pageId = 0; - - /** - * @var array - */ - protected $pageRecord = []; - - /** - * @var SiteLanguage[] - */ - protected $siteLanguages = []; - - /** + * Whether or not to show the "new content" buttons that open the new content + * wizard, when rendering columns. Disabling this will disable the rendering + * of new content buttons both in column top and after each content element. + * * @var bool */ protected $showNewContentWizard = true; + public function getSelectedLanguageId(): int + { + return $this->selectedLanguageId; + } + + public function setSelectedLanguageId(int $selectedLanguageId): void + { + $this->selectedLanguageId = $selectedLanguageId; + } + public function getDefaultLanguageBinding(): bool { return $this->defaultLanguageBinding; @@ -137,16 +130,6 @@ public function setLanguageColumns(array $languageColumns): void $this->languageColumns = $languageColumns; } - public function getLanguageColumnsPointer(): int - { - return $this->languageColumnsPointer; - } - - public function setLanguageColumnsPointer(int $languageColumnsPointer): void - { - $this->languageColumnsPointer = $languageColumnsPointer; - } - public function getShowHidden(): bool { return $this->showHidden; @@ -167,63 +150,6 @@ public function setActiveColumns(array $activeColumns): void $this->activeColumns = $activeColumns; } - public function getContentTypeLabels(): array - { - if (empty($this->contentTypeLabels)) { - foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { - $this->contentTypeLabels[$val[1]] = $this->getLanguageService()->sL($val[0]); - } - } - return $this->contentTypeLabels; - } - - public function getItemLabels(): array - { - if (empty($this->itemLabels)) { - foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { - $this->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); - } - } - return $this->itemLabels; - } - - public function getPageId(): int - { - return $this->pageId; - } - - public function setPageId(int $pageId): void - { - $this->pageId = $pageId; - $this->pageRecord = BackendUtility::getRecordWSOL('pages', $pageId); - } - - public function getPageRecord(): array - { - return $this->pageRecord; - } - - /** - * @return SiteLanguage[] - */ - public function getSiteLanguages(): array - { - if (empty($this->setSiteLanguages)) { - try { - $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->pageId); - } catch (SiteNotFoundException $e) { - $site = new NullSite(); - } - $this->siteLanguages = $site->getAvailableLanguages($this->getBackendUser(), false, $this->pageId); - } - return $this->siteLanguages; - } - - public function getSiteLanguage(int $languageUid): ?SiteLanguage - { - return $this->getSiteLanguages()[$languageUid] ?? null; - } - public function getShowNewContentWizard(): bool { return $this->showNewContentWizard; @@ -234,104 +160,6 @@ public function setShowNewContentWizard(bool $showNewContentWizard): void $this->showNewContentWizard = $showNewContentWizard; } - public function getLocalizedPageTitle(): string - { - if ($this->getLanguageColumnsPointer()) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages'); - $queryBuilder->getRestrictions() - ->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace)); - $localizedPage = $queryBuilder - ->select('*') - ->from('pages') - ->where( - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'], - $queryBuilder->createNamedParameter($this->getPageId(), \PDO::PARAM_INT) - ), - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages']['ctrl']['languageField'], - $queryBuilder->createNamedParameter($this->getLanguageColumnsPointer(), \PDO::PARAM_INT) - ) - ) - ->setMaxResults(1) - ->execute() - ->fetch(); - BackendUtility::workspaceOL('pages', $localizedPage); - return $localizedPage['title']; - } - return $this->getPageRecord()['title']; - } - - public function isPageEditable(): bool - { - if ($this->getBackendUser()->isAdmin()) { - return true; - } - $pageRecord = $this->getPageRecord(); - return !$pageRecord['editlock'] && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::PAGE_EDIT); - } - - public function getNewLanguageOptions(): array - { - if (!$this->getBackendUser()->check('tables_modify', 'pages')) { - return ''; - } - $id = $this->getPageId(); - - // First, select all languages that are available for the current user - $availableTranslations = []; - foreach ($this->getSiteLanguages() as $language) { - if ($language->getLanguageId() === 0) { - continue; - } - $availableTranslations[$language->getLanguageId()] = $language->getTitle(); - } - - // Then, subtract the languages which are already on the page: - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); - $queryBuilder->getRestrictions()->removeAll() - ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) - ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace)); - $queryBuilder->select('uid', $GLOBALS['TCA']['pages']['ctrl']['languageField']) - ->from('pages') - ->where( - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'], - $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) - ) - ); - $statement = $queryBuilder->execute(); - while ($row = $statement->fetch()) { - unset($availableTranslations[(int)$row[$GLOBALS['TCA']['pages']['ctrl']['languageField']]]); - } - // If any languages are left, make selector: - $options = []; - if (!empty($availableTranslations)) { - $options[] = $this->getLanguageService()->getLL('new_language'); - foreach ($availableTranslations as $languageUid => $languageTitle) { - // Build localize command URL to DataHandler (tce_db) - // which redirects to FormEngine (record_edit) - // which, when finished editing should return back to the current page (returnUrl) - $parameters = [ - 'justLocalized' => 'pages:' . $id . ':' . $languageUid, - 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') - ]; - $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); - $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', $parameters); - $targetUrl = BackendUtility::getLinkToDataHandlerAction( - '&cmd[pages][' . $id . '][localize]=' . $languageUid, - $redirectUrl - ); - - $options[$targetUrl] = $languageTitle; - } - } - return $options; - } - protected function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; diff --git a/typo3/sysext/backend/Classes/View/PageLayoutContext.php b/typo3/sysext/backend/Classes/View/PageLayoutContext.php new file mode 100644 index 000000000000..7df86cca5894 --- /dev/null +++ b/typo3/sysext/backend/Classes/View/PageLayoutContext.php @@ -0,0 +1,366 @@ +pageId = (int)$pageRecord['uid']; + try { + $this->site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->pageId); + } catch (SiteNotFoundException $e) { + $this->site = new NullSite(); + } + // TODO: retrieve implementation class names from Site? + $this->pageRecord = $pageRecord; + $this->backendLayout = $backendLayout; + $this->drawingConfiguration = GeneralUtility::makeInstance(DrawingConfiguration::class); + $this->contentFetcher = GeneralUtility::makeInstance(ContentFetcher::class, $this); + $this->backendLayoutRenderer = GeneralUtility::makeInstance(BackendLayoutRenderer::class, $this); + $this->siteLanguages = $this->site->getAvailableLanguages($this->getBackendUser(), false, $this->pageId); + $this->siteLanguage = $this->site->getDefaultLanguage(); + } + + public function cloneForLanguage(SiteLanguage $language): self + { + $copy = clone $this; + $copy->setSiteLanguage($language); + return $copy; + } + + /** + * @param SiteLanguage $siteLanguage + */ + public function setSiteLanguage(SiteLanguage $siteLanguage): void + { + $this->siteLanguage = $siteLanguage; + $languageId = $siteLanguage->getLanguageId(); + if ($languageId > 0) { + $pageLocalizationRecord = BackendUtility::getRecordLocalization( + 'pages', + $this->getPageId(), + $languageId + ); + $pageLocalizationRecord = reset($pageLocalizationRecord); + if (!empty($pageLocalizationRecord)) { + BackendUtility::workspaceOL('pages', $pageLocalizationRecord); + $this->localizedPageRecord = $pageLocalizationRecord ?: null; + } + } + } + + public function getBackendLayout(): BackendLayout + { + return $this->backendLayout; + } + + public function getDrawingConfiguration(): DrawingConfiguration + { + return $this->drawingConfiguration; + } + + public function getBackendLayoutRenderer(): BackendLayoutRenderer + { + return $this->backendLayoutRenderer; + } + + public function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + public function getPageRecord(): array + { + return $this->pageRecord; + } + + public function getPageId(): int + { + return $this->pageId; + } + + /** + * @return SiteLanguage[] + */ + public function getSiteLanguages(): iterable + { + return $this->siteLanguages; + } + + /** + * @return SiteLanguage[] + */ + public function getLanguagesToShow(): iterable + { + $selectedLanguageId = $this->drawingConfiguration->getSelectedLanguageId(); + if ($selectedLanguageId > 0) { + // A specific language is selected; compose a list of default language plus selected language + return [ + $this->site->getDefaultLanguage(), + $this->site->getLanguageById($selectedLanguageId) + ]; + } + return $this->getSiteLanguages(); + } + + public function getSiteLanguage(?int $languageId = null): SiteLanguage + { + if ($languageId === null) { + return $this->siteLanguage; + } + return $this->site->getLanguageById($languageId); + } + + public function isPageEditable(): bool + { + // TODO: refactor to page permissions container + if ($this->getBackendUser()->isAdmin()) { + return true; + } + $pageRecord = $this->getPageRecord(); + return !$pageRecord['editlock'] && $this->getBackendUser()->doesUserHaveAccess($pageRecord, Permission::PAGE_EDIT); + } + + public function getAllowNewContent(): bool + { + $pageId = $this->getPageId(); + $allowInconsistentLanguageHandling = (bool)(BackendUtility::getPagesTSconfig($pageId)['mod.']['web_layout.']['allowInconsistentLanguageHandling'] ?? false); + if (!$allowInconsistentLanguageHandling && $this->getLanguageModeIdentifier() === 'connected') { + return false; + } + return true; + } + + public function getContentTypeLabels(): array + { + if (empty($this->contentTypeLabels)) { + foreach ($GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'] as $val) { + $this->contentTypeLabels[$val[1]] = $this->getLanguageService()->sL($val[0]); + } + } + return $this->contentTypeLabels; + } + + public function getItemLabels(): array + { + if (empty($this->itemLabels)) { + foreach ($GLOBALS['TCA']['tt_content']['columns'] as $name => $val) { + $this->itemLabels[$name] = $this->getLanguageService()->sL($val['label']); + } + } + return $this->itemLabels; + } + + public function getLanguageModeLabelClass(): string + { + $languageId = $this->siteLanguage->getLanguageId(); + $contentRecordsPerColumn = $this->contentFetcher->getFlatContentRecords($languageId); + $translationData = $this->contentFetcher->getTranslationData($contentRecordsPerColumn, $languageId); + return $translationData['mode'] === 'mixed' ? 'danger' : 'info'; + } + + public function getLanguageMode(): string + { + switch ($this->getLanguageModeIdentifier()) { + case 'mixed': + $languageMode = $this->getLanguageService()->getLL('languageModeMixed'); + break; + case 'connected': + $languageMode = $this->getLanguageService()->getLL('languageModeConnected'); + break; + case 'free': + $languageMode = $this->getLanguageService()->getLL('languageModeFree'); + break; + default: + $languageMode = ''; + } + return $languageMode; + } + + public function getLanguageModeIdentifier(): string + { + $contentRecordsPerColumn = $this->contentFetcher->getContentRecordsPerColumn(null, $this->siteLanguage->getLanguageId()); + $contentRecords = empty($contentRecordsPerColumn) ? [] : array_merge(...$contentRecordsPerColumn); + $translationData = $this->contentFetcher->getTranslationData($contentRecords, $this->siteLanguage->getLanguageId()); + return $translationData['mode'] ?? ''; + } + + public function getNewLanguageOptions(): array + { + if (!$this->getBackendUser()->check('tables_modify', 'pages')) { + return []; + } + $id = $this->getPageId(); + + // First, select all languages that are available for the current user + $availableTranslations = []; + foreach ($this->getSiteLanguages() as $language) { + if ($language->getLanguageId() === 0) { + continue; + } + $availableTranslations[$language->getLanguageId()] = $language->getTitle(); + } + + // Then, subtract the languages which are already on the page: + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages'); + $queryBuilder->getRestrictions()->removeAll() + ->add(GeneralUtility::makeInstance(DeletedRestriction::class)) + ->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, (int)$this->getBackendUser()->workspace)); + $queryBuilder->select('uid', $GLOBALS['TCA']['pages']['ctrl']['languageField']) + ->from('pages') + ->where( + $queryBuilder->expr()->eq( + $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'], + $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) + ) + ); + $statement = $queryBuilder->execute(); + while ($row = $statement->fetch()) { + unset($availableTranslations[(int)$row[$GLOBALS['TCA']['pages']['ctrl']['languageField']]]); + } + // If any languages are left, make selector: + $options = []; + if (!empty($availableTranslations)) { + $options[] = $this->getLanguageService()->getLL('new_language'); + foreach ($availableTranslations as $languageUid => $languageTitle) { + // Build localize command URL to DataHandler (tce_db) + // which redirects to FormEngine (record_edit) + // which, when finished editing should return back to the current page (returnUrl) + $parameters = [ + 'justLocalized' => 'pages:' . $id . ':' . $languageUid, + 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') + ]; + $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); + $redirectUrl = (string)$uriBuilder->buildUriFromRoute('record_edit', $parameters); + $targetUrl = BackendUtility::getLinkToDataHandlerAction( + '&cmd[pages][' . $id . '][localize]=' . $languageUid, + $redirectUrl + ); + + $options[$targetUrl] = $languageTitle; + } + } + return $options; + } + + public function getLocalizedPageTitle(): string + { + return $this->getLocalizedPageRecord()['title'] ?? $this->getPageRecord()['title']; + } + + public function getLocalizedPageRecord(): ?array + { + return $this->localizedPageRecord; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/typo3/sysext/backend/Classes/View/PageLayoutView.php b/typo3/sysext/backend/Classes/View/PageLayoutView.php index 2a55b74894c6..55609547a7cc 100644 --- a/typo3/sysext/backend/Classes/View/PageLayoutView.php +++ b/typo3/sysext/backend/Classes/View/PageLayoutView.php @@ -23,7 +23,6 @@ use TYPO3\CMS\Backend\Controller\Page\LocalizationController; use TYPO3\CMS\Backend\Routing\UriBuilder; use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\Drawing\DrawingConfiguration; use TYPO3\CMS\Backend\View\Event\AfterSectionMarkupGeneratedEvent; use TYPO3\CMS\Backend\View\Event\BeforeSectionMarkupGeneratedEvent; use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; @@ -207,31 +206,33 @@ public function __construct(EventDispatcherInterface $eventDispatcher) } /** - * @param DrawingConfiguration $drawingConfiguration + * @param PageLayoutContext $context * @return PageLayoutView * @internal */ - public static function createFromDrawingConfiguration(DrawingConfiguration $drawingConfiguration): PageLayoutView + public static function createFromPageLayoutContext(PageLayoutContext $context): PageLayoutView { + $drawingConfiguration = $context->getDrawingConfiguration(); + $languageId = $drawingConfiguration->getSelectedLanguageId(); /** @var PageLayoutView $pageLayoutView */ $pageLayoutView = GeneralUtility::makeInstance(self::class); - $pageLayoutView->id = $drawingConfiguration->getPageId(); + $pageLayoutView->id = $context->getPageId(); $pageLayoutView->pageinfo = BackendUtility::readPageAccess($pageLayoutView->id, ''); - $pageLayoutView->pageRecord = $drawingConfiguration->getPageRecord(); + $pageLayoutView->pageRecord = $context->getPageRecord(); $pageLayoutView->option_newWizard = $drawingConfiguration->getShowNewContentWizard(); $pageLayoutView->defLangBinding = $drawingConfiguration->getDefaultLanguageBinding(); $pageLayoutView->tt_contentConfig['cols'] = implode(',', $drawingConfiguration->getActiveColumns()); $pageLayoutView->tt_contentConfig['activeCols'] = implode(',', $drawingConfiguration->getActiveColumns()); $pageLayoutView->tt_contentConfig['showHidden'] = $drawingConfiguration->getShowHidden(); - $pageLayoutView->tt_contentConfig['sys_language_uid'] = $drawingConfiguration->getLanguageColumnsPointer(); + $pageLayoutView->tt_contentConfig['sys_language_uid'] = $languageId; if ($drawingConfiguration->getLanguageMode()) { $pageLayoutView->tt_contentConfig['languageMode'] = 1; $pageLayoutView->tt_contentConfig['languageCols'] = $drawingConfiguration->getLanguageColumns(); - $pageLayoutView->tt_contentConfig['languageColsPointer'] = $drawingConfiguration->getLanguageColumnsPointer(); + $pageLayoutView->tt_contentConfig['languageColsPointer'] = $languageId; } - $pageLayoutView->doEdit = $pageLayoutView->isContentEditable($drawingConfiguration->getLanguageColumnsPointer()); - $pageLayoutView->CType_labels = $drawingConfiguration->getContentTypeLabels(); - $pageLayoutView->itemLabels = $drawingConfiguration->getItemLabels(); + $pageLayoutView->doEdit = $pageLayoutView->isContentEditable($languageId); + $pageLayoutView->CType_labels = $context->getContentTypeLabels(); + $pageLayoutView->itemLabels = $context->getItemLabels(); return $pageLayoutView; } diff --git a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Grid/Column.html b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Grid/Column.html index eaf0d5e6010e..dff2b5426562 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Grid/Column.html +++ b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Grid/Column.html @@ -25,9 +25,9 @@ - -
-
+ +
+
diff --git a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html index e3cf8f2ba8b8..172d073b07bb 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html +++ b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/LanguageColumns.html @@ -1,8 +1,8 @@ - +
@@ -12,22 +12,22 @@
- + - + - + - + diff --git a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Record.html b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Record.html index 2b1351039838..e4d25412d48b 100644 --- a/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Record.html +++ b/typo3/sysext/backend/Resources/Private/Partials/PageLayout/Record.html @@ -1,4 +1,4 @@ -{f:if(condition: '{item.disabled} && {item.backendLayout.drawingConfiguration.showHidden} == 0', then: 'display: none;') -> f:variable(name: 'style')} +{f:if(condition: '{item.disabled} && {item.context.drawingConfiguration.showHidden} == 0', then: 'display: none;') -> f:variable(name: 'style')}
@@ -15,8 +15,8 @@
- -
-

{languageColumn.siteLanguage.title}

- - {languageColumn.languageMode} +

{languageColumn.context.siteLanguage.title}

+ + {languageColumn.context.languageMode}
{languageColumn.pageIcon -> f:format.raw()} - {languageColumn.localizedPageRecord.title} + {languageColumn.context.localizedPageTitle}