diff --git a/Build/phpstan11-7.4.neon b/Build/phpstan11-7.4.neon index 75fd97dc..be7d44f8 100644 --- a/Build/phpstan11-7.4.neon +++ b/Build/phpstan11-7.4.neon @@ -15,4 +15,5 @@ parameters: - %currentWorkingDirectory%/Tests/Functional/Listener/ContentUsedOnPageTest.php - %currentWorkingDirectory%/Classes/Listener/RecordSummaryForLocalization.php - %currentWorkingDirectory%/Classes/Listener/PageTsConfig.php + - %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php diff --git a/Build/phpstan11.neon b/Build/phpstan11.neon index b3e9c6fc..443a2014 100644 --- a/Build/phpstan11.neon +++ b/Build/phpstan11.neon @@ -15,4 +15,5 @@ parameters: - %currentWorkingDirectory%/Tests/Functional/Listener/ContentUsedOnPageTest.php - %currentWorkingDirectory%/Classes/Listener/RecordSummaryForLocalization.php - %currentWorkingDirectory%/Classes/Listener/PageTsConfig.php + - %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php diff --git a/Classes/Backend/Preview/ContainerPreviewRenderer.php b/Classes/Backend/Preview/ContainerPreviewRenderer.php index 73e98640..54774a65 100644 --- a/Classes/Backend/Preview/ContainerPreviewRenderer.php +++ b/Classes/Backend/Preview/ContainerPreviewRenderer.php @@ -12,122 +12,23 @@ * of the License, or any later version. */ -use B13\Container\Backend\Grid\ContainerGridColumn; -use B13\Container\Backend\Grid\ContainerGridColumnItem; -use B13\Container\Backend\Service\NewContentUrlBuilder; -use B13\Container\Domain\Factory\Exception; -use B13\Container\Domain\Factory\PageView\Backend\ContainerFactory; -use B13\Container\Events\BeforeContainerPreviewIsRenderedEvent; -use B13\Container\Tca\Registry; -use Psr\EventDispatcher\EventDispatcherInterface; + use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer; -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\Grid; use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem; -use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridRow; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Fluid\View\StandaloneView; class ContainerPreviewRenderer extends StandardContentPreviewRenderer { - /** - * @var Registry - */ - protected $tcaRegistry; - - /** - * @var ContainerFactory - */ - protected $containerFactory; - - protected NewContentUrlBuilder $newContentUrlBuilder; + protected GridRenderer $gridRenderer; - /** - * @var EventDispatcherInterface - */ - protected $eventDispatcher; - - public function __construct( - Registry $tcaRegistry, - ContainerFactory $containerFactory, - NewContentUrlBuilder $newContentUrlBuilder, - EventDispatcherInterface $eventDispatcher - ) { - $this->eventDispatcher = $eventDispatcher; - $this->tcaRegistry = $tcaRegistry; - $this->containerFactory = $containerFactory; - $this->newContentUrlBuilder = $newContentUrlBuilder; + public function __construct(GridRenderer $gridRenderer) { + $this->gridRenderer = $gridRenderer; } public function renderPageModulePreviewContent(GridColumnItem $item): string { - $content = parent::renderPageModulePreviewContent($item); - $context = $item->getContext(); $record = $item->getRecord(); - $grid = GeneralUtility::makeInstance(Grid::class, $context); - try { - $container = $this->containerFactory->buildContainer((int)$record['uid']); - } catch (Exception $e) { - // not a container - return $content; - } - $containerGrid = $this->tcaRegistry->getGrid($record['CType']); - foreach ($containerGrid as $cols) { - $rowObject = GeneralUtility::makeInstance(GridRow::class, $context); - foreach ($cols as $col) { - $defVals = $this->getDefValsForContentDefenderAllowsOnlyOneSpecificContentType($record['CType'], (int)$col['colPos']); - $url = $this->newContentUrlBuilder->getNewContentUrlAtTopOfColumn($context, $container, (int)$col['colPos'], $defVals); - $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $url, $defVals !== null); - $rowObject->addColumn($columnObject); - if (isset($col['colPos'])) { - $records = $container->getChildrenByColPos($col['colPos']); - foreach ($records as $contentRecord) { - $url = $this->newContentUrlBuilder->getNewContentUrlAfterChild($context, $container, (int)$col['colPos'], (int)$contentRecord['uid'], $defVals); - $columnItem = GeneralUtility::makeInstance(ContainerGridColumnItem::class, $context, $columnObject, $contentRecord, $container, $url); - $columnObject->addItem($columnItem); - } - } - } - $grid->addRow($rowObject); - } - - $gridTemplate = $this->tcaRegistry->getGridTemplate($record['CType']); - $partialRootPaths = $this->tcaRegistry->getGridPartialPaths($record['CType']); - $layoutRootPaths = $this->tcaRegistry->getGridLayoutPaths($record['CType']); - $view = GeneralUtility::makeInstance(StandaloneView::class); - $view->setPartialRootPaths($partialRootPaths); - $view->setLayoutRootPaths($layoutRootPaths); - $view->setTemplatePathAndFilename($gridTemplate); - - $view->assign('hideRestrictedColumns', (bool)(BackendUtility::getPagesTSconfig($context->getPageId())['mod.']['web_layout.']['hideRestrictedCols'] ?? false)); - $view->assign('newContentTitle', $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:newContentElement')); - $view->assign('newContentTitleShort', $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:content')); - $view->assign('allowEditContent', $this->getBackendUser()->check('tables_modify', 'tt_content')); - // keep compatibility - $view->assign('containerGrid', $grid); - $view->assign('grid', $grid); - $view->assign('containerRecord', $record); - $view->assign('context', $context); - $beforeContainerPreviewIsRendered = new BeforeContainerPreviewIsRenderedEvent($container, $view, $grid, $item); - $this->eventDispatcher->dispatch($beforeContainerPreviewIsRendered); - $rendered = $view->render(); - - return $content . $rendered; - } - - protected function getDefValsForContentDefenderAllowsOnlyOneSpecificContentType(string $cType, int $colPos): ?array - { - $contentDefefenderConfiguration = $this->tcaRegistry->getContentDefenderConfiguration($cType, $colPos); - $allowedCTypes = GeneralUtility::trimExplode(',', $contentDefefenderConfiguration['allowed.']['CType'] ?? '', true); - $allowedListTypes = GeneralUtility::trimExplode(',', $contentDefefenderConfiguration['allowed.']['list_type'] ?? '', true); - if (count($allowedCTypes) === 1) { - if ($allowedCTypes[0] !== 'list') { - return ['CType' => $allowedCTypes[0]]; - } - if (count($allowedListTypes) === 1) { - return ['CType' => 'list', 'list_type' => $allowedListTypes[0]]; - } - } - return null; + $record['tx_container_grid'] = $this->gridRenderer->renderGrid($record, $item->getContext(), $item); + $item->setRecord($record); + return parent::renderPageModulePreviewContent($item); } } diff --git a/Classes/Backend/Preview/GridRenderer.php b/Classes/Backend/Preview/GridRenderer.php new file mode 100644 index 00000000..3bcd113b --- /dev/null +++ b/Classes/Backend/Preview/GridRenderer.php @@ -0,0 +1,130 @@ +eventDispatcher = $eventDispatcher; + $this->tcaRegistry = $tcaRegistry; + $this->containerFactory = $containerFactory; + $this->newContentUrlBuilder = $newContentUrlBuilder; + } + + public function renderGrid(array $record, PageLayoutContext $context, ?GridColumnItem $parentGridColumnItem = null): string + { + $grid = GeneralUtility::makeInstance(Grid::class, $context); + try { + $container = $this->containerFactory->buildContainer((int)$record['uid']); + } catch (Exception $e) { + // not a container + return ''; + } + $containerGrid = $this->tcaRegistry->getGrid($record['CType']); + foreach ($containerGrid as $cols) { + $rowObject = GeneralUtility::makeInstance(GridRow::class, $context); + foreach ($cols as $col) { + $defVals = $this->getDefValsForContentDefenderAllowsOnlyOneSpecificContentType($record['CType'], (int)$col['colPos']); + $url = $this->newContentUrlBuilder->getNewContentUrlAtTopOfColumn($context, $container, (int)$col['colPos'], $defVals); + $columnObject = GeneralUtility::makeInstance(ContainerGridColumn::class, $context, $col, $container, $url, $defVals !== null); + $rowObject->addColumn($columnObject); + if (isset($col['colPos'])) { + $records = $container->getChildrenByColPos($col['colPos']); + foreach ($records as $contentRecord) { + $url = $this->newContentUrlBuilder->getNewContentUrlAfterChild($context, $container, (int)$col['colPos'], (int)$contentRecord['uid'], $defVals); + $columnItem = GeneralUtility::makeInstance(ContainerGridColumnItem::class, $context, $columnObject, $contentRecord, $container, $url); + $columnObject->addItem($columnItem); + } + } + } + $grid->addRow($rowObject); + } + + $gridTemplate = $this->tcaRegistry->getGridTemplate($record['CType']); + $partialRootPaths = $this->tcaRegistry->getGridPartialPaths($record['CType']); + $layoutRootPaths = $this->tcaRegistry->getGridLayoutPaths($record['CType']); + $view = GeneralUtility::makeInstance(StandaloneView::class); + $view->setPartialRootPaths($partialRootPaths); + $view->setLayoutRootPaths($layoutRootPaths); + $view->setTemplatePathAndFilename($gridTemplate); + + $view->assign('hideRestrictedColumns', (bool)(BackendUtility::getPagesTSconfig($context->getPageId())['mod.']['web_layout.']['hideRestrictedCols'] ?? false)); + $view->assign('newContentTitle', $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:newContentElement')); + $view->assign('newContentTitleShort', $this->getLanguageService()->sL('LLL:EXT:backend/Resources/Private/Language/locallang_layout.xlf:content')); + $view->assign('allowEditContent', $this->getBackendUser()->check('tables_modify', 'tt_content')); + // keep compatibility + $view->assign('containerGrid', $grid); + $view->assign('grid', $grid); + $view->assign('containerRecord', $record); + $view->assign('context', $context); + $beforeContainerPreviewIsRendered = new BeforeContainerPreviewIsRenderedEvent($container, $view, $grid, $parentGridColumnItem); + $this->eventDispatcher->dispatch($beforeContainerPreviewIsRendered); + $rendered = $view->render(); + return $rendered; + } + + protected function getDefValsForContentDefenderAllowsOnlyOneSpecificContentType(string $cType, int $colPos): ?array + { + $contentDefefenderConfiguration = $this->tcaRegistry->getContentDefenderConfiguration($cType, $colPos); + $allowedCTypes = GeneralUtility::trimExplode(',', $contentDefefenderConfiguration['allowed.']['CType'] ?? '', true); + $allowedListTypes = GeneralUtility::trimExplode(',', $contentDefefenderConfiguration['allowed.']['list_type'] ?? '', true); + if (count($allowedCTypes) === 1) { + if ($allowedCTypes[0] !== 'list') { + return ['CType' => $allowedCTypes[0]]; + } + if (count($allowedListTypes) === 1) { + return ['CType' => 'list', 'list_type' => $allowedListTypes[0]]; + } + } + return null; + } + + protected function getBackendUser(): BackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } +} diff --git a/Classes/Events/BeforeContainerPreviewIsRenderedEvent.php b/Classes/Events/BeforeContainerPreviewIsRenderedEvent.php index 15e4fb01..7e883737 100644 --- a/Classes/Events/BeforeContainerPreviewIsRenderedEvent.php +++ b/Classes/Events/BeforeContainerPreviewIsRenderedEvent.php @@ -25,9 +25,9 @@ final class BeforeContainerPreviewIsRenderedEvent protected Grid $grid; - protected GridColumnItem $item; + protected ?GridColumnItem $item; - public function __construct(Container $container, StandaloneView $view, Grid $grid, GridColumnItem $item) + public function __construct(Container $container, StandaloneView $view, Grid $grid, ?GridColumnItem $item) { $this->container = $container; $this->view = $view; @@ -50,7 +50,7 @@ public function getGrid(): Grid return $this->grid; } - public function getItem(): GridColumnItem + public function getItem(): ?GridColumnItem { return $this->item; } diff --git a/Classes/Listener/PageContentPreviewRendering.php b/Classes/Listener/PageContentPreviewRendering.php new file mode 100644 index 00000000..e986e24a --- /dev/null +++ b/Classes/Listener/PageContentPreviewRendering.php @@ -0,0 +1,39 @@ +gridRenderer = $gridRenderer; + $this->tcaRegistry = $tcaRegistry; + } + + public function __invoke(PageContentPreviewRenderingEvent $event): void + { + $record = $event->getRecord(); + if (!$this->tcaRegistry->isContainerElement($record['CType'])) { + return; + } + $record['tx_container_grid'] = $this->gridRenderer->renderGrid($record, $event->getPageLayoutContext()); + $event->setRecord($record); + } +} diff --git a/Classes/Tca/ContainerConfiguration.php b/Classes/Tca/ContainerConfiguration.php index a0a52709..0c9a1c42 100644 --- a/Classes/Tca/ContainerConfiguration.php +++ b/Classes/Tca/ContainerConfiguration.php @@ -42,7 +42,7 @@ class ContainerConfiguration */ protected $icon = 'EXT:container/Resources/Public/Icons/Extension.svg'; - protected ?string $backendTemplate = null; + protected string $backendTemplate = 'EXT:container/Resources/Private/Templates/Container.html'; /** * @var string @@ -228,7 +228,7 @@ public function getIcon(): string return $this->icon; } - public function getBackendTemplate(): ?string + public function getBackendTemplate(): string { return $this->backendTemplate; } diff --git a/Classes/Tca/Registry.php b/Classes/Tca/Registry.php index 1f41df6e..b379fc7f 100644 --- a/Classes/Tca/Registry.php +++ b/Classes/Tca/Registry.php @@ -64,10 +64,9 @@ public function configureContainer(ContainerConfiguration $containerConfiguratio $containerConfiguration->getGroup(), ] ); + $GLOBALS['TCA']['tt_content']['types'][$containerConfiguration->getCType()]['previewRenderer'] = \B13\Container\Backend\Preview\ContainerPreviewRenderer::class; } - $GLOBALS['TCA']['tt_content']['types'][$containerConfiguration->getCType()]['previewRenderer'] = \B13\Container\Backend\Preview\ContainerPreviewRenderer::class; - if ((GeneralUtility::makeInstance(Typo3Version::class))->getMajorVersion() >= 13) { if (!isset($GLOBALS['TCA']['tt_content']['types'][$containerConfiguration->getCType()]['creationOptions'])) { $GLOBALS['TCA']['tt_content']['types'][$containerConfiguration->getCType()]['creationOptions'] = []; @@ -266,12 +265,10 @@ public function getPageTsString(): string } $groupedByGroup[$group][$cType] = $containerConfiguration; } - if ($containerConfiguration['backendTemplate'] !== null) { - $pageTs .= LF . 'mod.web_layout.tt_content.preview { + $pageTs .= LF . 'mod.web_layout.tt_content.preview { ' . $cType . ' = ' . $containerConfiguration['backendTemplate'] . ' } '; - } } $typo3Version = GeneralUtility::makeInstance(Typo3Version::class); if ($typo3Version->getMajorVersion() > 12) { diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index ee4ba369..ee77691d 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -68,6 +68,11 @@ services: tags: - name: event.listener identifier: 'tx-container-boot-completed' + B13\Container\Listener\PageContentPreviewRendering: + tags: + - name: event.listener + identifier: 'tx-container-page-content-preview-rendering' + before: 'typo3-backend/fluid-preview/content' B13\Container\Command\FixLanguageModeCommand: tags: - name: 'console.command' diff --git a/README.md b/README.md index 59bc09c8..8b298e7e 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ This is an example to create a 2 column container. The code snippet goes into a | Method name | Description | Parameters | Default | | ----------- | ----------- | ---------- | ---------- | | `setIcon` | icon file, or existing icon identifier | `string $icon` | `'EXT:container/Resources/Public/Icons/Extension.svg'` | -| `setBackendTemplate` | Template for backend view| `string $backendTemplate` | `null'` | +| `setBackendTemplate` | Template for backend view| `string $backendTemplate` | `EXT:container/Resources/Private/Templates/Container.html'` | | `setGridTemplate` | Template for grid | `string $gridTemplate` | `'EXT:container/Resources/Private/Templates/Container.html'` | | `setGridPartialPaths` / `addGridPartialPath` | Partial root paths for grid | `array $gridPartialPaths` / `string $gridPartialPath` | `['EXT:backend/Resources/Private/Partials/', 'EXT:container/Resources/Private/Partials/']` | | `setGridLayoutPaths` | Layout root paths for grid | `array $gridLayoutPaths` | `[]` | diff --git a/Resources/Private/Templates/Container.html b/Resources/Private/Templates/Container.html new file mode 100644 index 00000000..a91e8da2 --- /dev/null +++ b/Resources/Private/Templates/Container.html @@ -0,0 +1,6 @@ + +{tx_container_grid} + \ No newline at end of file