Skip to content

Commit

Permalink
[TASK] provide some events
Browse files Browse the repository at this point in the history
Introduce 2 new PSR-14 Events

BeforeContainerConfigurationIsAppliedEvent

* change container configuration for 3rd party extensions container you have installed
* apply same configuration to all or a set of containers (e.g. gridTemplate)
* Note: CType and Grid Structure cannot be changed (but Column Properties of the Grid)

BeforeContainerPreviewIsRendered

change view object, e.g. add variables to view or change paths
  • Loading branch information
achimfritz committed Aug 7, 2024
1 parent ef6cc8d commit 43c6fba
Show file tree
Hide file tree
Showing 16 changed files with 212 additions and 27 deletions.
17 changes: 15 additions & 2 deletions Classes/Backend/Preview/ContainerPreviewRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
use B13\Container\Domain\Factory\Exception;
use B13\Container\Domain\Factory\PageView\Backend\ContainerFactory;
use B13\Container\Domain\Service\ContainerService;
use B13\Container\Events\BeforeContainerPreviewIsRenderedEvent;
use B13\Container\Tca\Registry;
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\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;

Expand All @@ -49,16 +51,23 @@ class ContainerPreviewRenderer extends StandardContentPreviewRenderer
*/
protected $containerService;

/**
* @var EventDispatcher
*/
protected $eventDispatcher;

public function __construct(
Registry $tcaRegistry,
ContainerFactory $containerFactory,
ContainerColumnConfigurationService $containerColumnConfigurationService,
ContainerService $containerService
ContainerService $containerService,
EventDispatcher $eventDispatcher
) {
$this->tcaRegistry = $tcaRegistry;
$this->containerFactory = $containerFactory;
$this->containerColumnConfigurationService = $containerColumnConfigurationService;
$this->containerService = $containerService;
$this->eventDispatcher = $eventDispatcher;
}

public function renderPageModulePreviewContent(GridColumnItem $item): string
Expand All @@ -74,7 +83,7 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string
return $content;
}
$containerGrid = $this->tcaRegistry->getGrid($record['CType']);
foreach ($containerGrid as $row => $cols) {
foreach ($containerGrid as $cols) {
$rowObject = GeneralUtility::makeInstance(GridRow::class, $context);
foreach ($cols as $col) {
$newContentElementAtTopTarget = $this->containerService->getNewContentElementAtTopTargetInColumn($container, $col['colPos']);
Expand Down Expand Up @@ -107,8 +116,12 @@ public function renderPageModulePreviewContent(GridColumnItem $item): string
$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);
$beforeContainerPreviewIsRendered = new BeforeContainerPreviewIsRenderedEvent($container, $view);
$this->eventDispatcher->dispatch($beforeContainerPreviewIsRendered);
$rendered = $view->render();

return $content . $rendered;
Expand Down
41 changes: 41 additions & 0 deletions Classes/Events/BeforeContainerConfigurationIsAppliedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace B13\Container\Events;

/*
* This file is part of TYPO3 CMS-based extension "container" by b13.
*
* 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.
*/

use B13\Container\Tca\ContainerConfiguration;

final class BeforeContainerConfigurationIsAppliedEvent
{
protected ContainerConfiguration $containerConfiguration;
protected bool $skip = false;

public function __construct(ContainerConfiguration $containerConfiguration)
{
$this->containerConfiguration = $containerConfiguration;
}

public function skip(): void
{
$this->skip = true;
}

public function shouldBeSkipped(): bool
{
return $this->skip;
}

public function getContainerConfiguration(): ContainerConfiguration
{
return $this->containerConfiguration;
}
}
39 changes: 39 additions & 0 deletions Classes/Events/BeforeContainerPreviewIsRenderedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace B13\Container\Events;

/*
* This file is part of TYPO3 CMS-based extension "container" by b13.
*
* 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.
*/

use B13\Container\Domain\Model\Container;
use TYPO3\CMS\Fluid\View\StandaloneView;

final class BeforeContainerPreviewIsRenderedEvent
{
protected Container $container;

protected StandaloneView $view;

public function __construct(Container $container, StandaloneView $view)
{
$this->container = $container;
$this->view = $view;
}

public function getContainer(): Container
{
return $this->container;
}

public function getView(): StandaloneView
{
return $this->view;
}
}
62 changes: 62 additions & 0 deletions Classes/Tca/ContainerConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,31 @@ public function getGrid(): array
return $this->grid;
}

public function getDescription(): string
{
return $this->description;
}

public function getIcon(): string
{
return $this->icon;
}

public function getBackendTemplate(): ?string
{
return $this->backendTemplate;
}

public function isRegisterInNewContentElementWizard(): bool
{
return $this->registerInNewContentElementWizard;
}

public function getDefaultValues(): array
{
return $this->defaultValues;
}

/**
* @return string[]
*/
Expand Down Expand Up @@ -249,6 +274,43 @@ public function setDefaultValues(array $defaultValues): ContainerConfiguration
return $this;
}

protected function setLabel(string $label): ContainerConfiguration
{
$this->label = $label;
return $this;
}

public function setDescription(string $description): ContainerConfiguration
{
$this->description = $description;
return $this;
}

public function getGridTemplate(): string
{
return $this->gridTemplate;
}

public function changeGridColumnConfiguration(int $colPos, array $override): void
{
$rows = $this->getGrid();
$modRows = [];
$columnConfigurationFields = ['name', 'allowed', 'disallowed', 'maxitems', 'colspan'];
foreach ($rows as &$columns) {
foreach ($columns as &$column) {
if ((int)$column['colPos'] === $colPos) {
foreach ($columnConfigurationFields as $field) {
if (isset($override[$field])) {
$column[$field] = $override[$field];
}
}
}
}
$modRows[] = $columns;
}
$this->grid = $modRows;
}

/**
* @return mixed[]
*/
Expand Down
20 changes: 16 additions & 4 deletions Classes/Tca/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* of the License, or any later version.
*/

use B13\Container\Events\BeforeContainerConfigurationIsAppliedEvent;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Imaging\IconProvider\BitmapIconProvider;
use TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider;
use TYPO3\CMS\Core\Imaging\IconRegistry;
Expand All @@ -22,11 +24,23 @@

class Registry implements SingletonInterface
{
protected EventDispatcher $eventDispatcher;

public function __construct(EventDispatcher $eventDispatcher)
{
$this->eventDispatcher = $eventDispatcher;
}

/**
* @param ContainerConfiguration $containerConfiguration
*/
public function configureContainer(ContainerConfiguration $containerConfiguration): void
{
$beforeContainerConfigurationIsAppliedEvent = new BeforeContainerConfigurationIsAppliedEvent($containerConfiguration);
$this->eventDispatcher->dispatch($beforeContainerConfigurationIsAppliedEvent);
if ($beforeContainerConfigurationIsAppliedEvent->shouldBeSkipped()) {
return;
}
if ((GeneralUtility::makeInstance(Typo3Version::class))->getMajorVersion() >= 12) {
ExtensionManagementUtility::addTcaSelectItem(
'tt_content',
Expand Down Expand Up @@ -109,6 +123,7 @@ public function getContentDefenderConfiguration(string $cType, int $colPos): arr
$contentDefenderConfiguration['allowed.'] = $column['allowed'] ?? [];
$contentDefenderConfiguration['disallowed.'] = $column['disallowed'] ?? [];
$contentDefenderConfiguration['maxitems'] = $column['maxitems'] ?? 0;
return $contentDefenderConfiguration;
}
}
}
Expand Down Expand Up @@ -167,10 +182,7 @@ public function getRegisteredCTypes(): array

public function getGrid(string $cType): array
{
if (empty($GLOBALS['TCA']['tt_content']['containerConfiguration'][$cType]['grid'])) {
return [];
}
return $GLOBALS['TCA']['tt_content']['containerConfiguration'][$cType]['grid'];
return $GLOBALS['TCA']['tt_content']['containerConfiguration'][$cType]['grid'] ?? [];
}

public function getGridTemplate(string $cType): ?string
Expand Down
2 changes: 2 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ services:
- '../Classes/Tca/ContainerConfiguration.php'
- '../Classes/**/Exception.php'

B13\Container\Tca\Registry:
public: true
B13\Container\Backend\Preview\ContainerPreviewRenderer:
public: true
B13\Container\Hooks\UsedRecords:
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ The html template file goes in the folder that you have defined in your TypoScri

With explicit colPos defined use `{children_200|201}` as set in the example above

## PSR-14 Events

### BeforeContainerConfigurationIsAppliedEvent

* change container configuration for 3rd party extensions container you have installed
* apply same configuration to all or a set of containers (e.g. ``gridTemplate``)
* **Note** CType and Grid Structure cannot be changed (but Column Properties of the Grid)

### BeforeContainerPreviewIsRendered

change view object, e.g. add variables to view or change paths

## Concepts
- Complete registration is done with one PHP call to TCA Registry
- A container in the TYPO3 backend Page module is rendered like a page itself (see View/ContainerLayoutView)
Expand Down
4 changes: 2 additions & 2 deletions Resources/Private/Templates/Grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
data-namespace-typo3-fluid="true"
>

<f:if condition="{containerGrid}">
<f:render partial="PageLayout/Grid" arguments="{grid: containerGrid, hideRestrictedColumns: hideRestrictedColumns, newContentTitle: newContentTitle, newContentTitleShort: newContentTitleShort, allowEditContent: allowEditContent}" />
<f:if condition="{grid}">
<f:render partial="PageLayout/Grid" arguments="{_all}" />
</f:if>

</html>
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function containerByUidReturnsNullIfNoRecordInDatabaseIsFound(): void
->onlyMethods(['fetchOneRecord'])
->getMock();
$database->expects(self::once())->method('fetchOneRecord')->with(1)->willReturn(null);
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$context = $this->getMockBuilder(Context::class)->getMock();
$containerFactory = $this->getMockBuilder($this->buildAccessibleProxy(ContainerFactory::class))
->setConstructorArgs(['database' => $database, 'tcaRegistry' => $tcaRegistry, 'context' => $context])
Expand Down
2 changes: 1 addition & 1 deletion Tests/Unit/Domain/Service/ContainerServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function setupDataProvider()
*/
public function getFirstNewContentElementTargetInColumnTest(array $containerRecord, array $childRecords, int $targetColPos, int $expectedTarget): void
{
$tcaRegistry = $this->getMockBuilder(Registry::class)->onlyMethods(['getAllAvailableColumnsColPos'])->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->onlyMethods(['getAllAvailableColumnsColPos'])->getMock();
$tcaRegistry->expects(self::any())->method('getAllAvailableColumnsColPos')->willReturn($this->allContainerColumns);
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$container = new Container($containerRecord, $childRecords, 0);
Expand Down
12 changes: 6 additions & 6 deletions Tests/Unit/Hooks/Datahandler/CommandMapBeforeStartHookTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function rewriteCommandMapTargetForTopAtContainerTest(): void
->getMock();
$containerService->expects(self::once())->method('getNewContentElementAtTopTargetInColumn')->with($container, 2)->willReturn(-4);
$database = $this->getMockBuilder(Database::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
->setConstructorArgs(['containerFactory' => $containerFactory, 'tcaRegistry' => $tcaRegistry, 'database' => $database, 'containerService' => $containerService])
->onlyMethods([])
Expand Down Expand Up @@ -94,7 +94,7 @@ public function rewriteSimpleCommandMapTestForIntoContainer(): void
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$database = $this->getMockBuilder(Database::class)->onlyMethods(['fetchOneRecord'])->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$database->expects(self::once())->method('fetchOneRecord')->with(1)->willReturn($copyAfterRecord);
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
->setConstructorArgs(['containerFactory' => $containerFactory, 'tcaRegistry' => $tcaRegistry, 'database' => $database, 'containerService' => $containerService])
Expand Down Expand Up @@ -143,7 +143,7 @@ public function rewriteSimpleCommandMapTestForAfterContainer(): void
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$database = $this->getMockBuilder(Database::class)->onlyMethods(['fetchOneRecord'])->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->onlyMethods(['isContainerElement'])->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->onlyMethods(['isContainerElement'])->getMock();
$database->expects(self::once())->method('fetchOneRecord')->with(1)->willReturn($copyAfterRecord);
$tcaRegistry->expects(self::once())->method('isContainerElement')->with('container-ctype')->willReturn(true);
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
Expand Down Expand Up @@ -184,7 +184,7 @@ public function extractContainerIdFromColPosInDatamapSetsContainerIdToSplittedCo
{
$database = $this->getMockBuilder(Database::class)->getMock();
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
->setConstructorArgs(['containerFactory' => $containerFactory, 'tcaRegistry' => $tcaRegistry, 'database' => $database, 'containerService' => $containerService])
Expand Down Expand Up @@ -227,7 +227,7 @@ public function extractContainerIdFromColPosInDatamapSetsContainerIdToSplittedCo
{
$database = $this->getMockBuilder(Database::class)->getMock();
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
->setConstructorArgs(['containerFactory' => $containerFactory, 'tcaRegistry' => $tcaRegistry, 'database' => $database, 'containerService' => $containerService])
Expand Down Expand Up @@ -257,7 +257,7 @@ public function extractContainerIdFromColPosInDatamapSetsContainerIdToZeroValue(
{
$database = $this->getMockBuilder(Database::class)->getMock();
$containerFactory = $this->getMockBuilder(ContainerFactory::class)->disableOriginalConstructor()->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->getMock();
$tcaRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(CommandMapBeforeStartHook::class))
->setConstructorArgs(['containerFactory' => $containerFactory, 'tcaRegistry' => $tcaRegistry, 'database' => $database, 'containerService' => $containerService])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function datamapForLocalizationsExtendsDatamapWithLocalizations(): void
->getMock();
$database->expects(self::once())->method('fetchOverlayRecords')->with($defaultRecord)->willReturn([['uid' => 3]]);
$database->expects(self::once())->method('fetchOneRecord')->with(2)->willReturn($defaultRecord);
$containerRegistry = $this->getMockBuilder(Registry::class)->getMock();
$containerRegistry = $this->getMockBuilder(Registry::class)->disableOriginalConstructor()->getMock();
$containerService = $this->getMockBuilder(ContainerService::class)->disableOriginalConstructor()->getMock();
$dataHandlerHook = $this->getMockBuilder($this->buildAccessibleProxy(DatamapBeforeStartHook::class))
->setConstructorArgs([
Expand Down
Loading

0 comments on commit 43c6fba

Please sign in to comment.