Skip to content

Commit cc52a10

Browse files
committed
[FEATURE] core content-defender
1 parent 9fe832a commit cc52a10

File tree

9 files changed

+130
-26
lines changed

9 files changed

+130
-26
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -t ${{ matrix.TYPO3 }} -s acceptance -- --fail-fast
5959
if: matrix.TYPO3 != '14'
6060
- name: Acceptance Tests 14
61-
run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -t ${{ matrix.TYPO3 }} -s acceptance -- --fail-fast --skip-group=content_defender
61+
run: Build/Scripts/runTests.sh -p ${{ matrix.php }} -t ${{ matrix.TYPO3 }} -s acceptance -- --fail-fast
6262
if: matrix.TYPO3 == '14'
6363
- name: Archive acceptance tests results
6464
uses: actions/upload-artifact@v4

Build/phpstan11-7.4.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ parameters:
1717
- %currentWorkingDirectory%/Classes/Listener/PageTsConfig.php
1818
- %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php
1919
- %currentWorkingDirectory%/Classes/Domain/Core/RecordWithRenderedGrid.php
20+
- %currentWorkingDirectory%/Classes/Listener/ManipulateBackendLayoutColPosConfigurationForPage.php
2021

Build/phpstan11.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ parameters:
1717
- %currentWorkingDirectory%/Classes/Listener/PageTsConfig.php
1818
- %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php
1919
- %currentWorkingDirectory%/Classes/Domain/Core/RecordWithRenderedGrid.php
20+
- %currentWorkingDirectory%/Classes/Listener/ManipulateBackendLayoutColPosConfigurationForPage.php
2021

Build/phpstan12.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ parameters:
1414
- %currentWorkingDirectory%/Tests/Unit/Hooks/UsedRecordsTest.php
1515
- %currentWorkingDirectory%/Classes/Domain/Core/RecordWithRenderedGrid.php
1616
- %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php
17+
- %currentWorkingDirectory%/Classes/Listener/ManipulateBackendLayoutColPosConfigurationForPage.php
1718

1819

Build/phpstan13.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ parameters:
1515
- %currentWorkingDirectory%/Classes/Hooks/WizardItems.php
1616
- %currentWorkingDirectory%/Classes/Listener/LegacyPageTsConfig.php
1717
- %currentWorkingDirectory%/Classes/Listener/PageContentPreviewRendering.php
18+
- %currentWorkingDirectory%/Classes/Listener/ManipulateBackendLayoutColPosConfigurationForPage.php
1819

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace B13\Container\Listener;
6+
7+
/*
8+
* This file is part of TYPO3 CMS-based extension "container" by b13.
9+
*
10+
* It is free software; you can redistribute it and/or modify it under
11+
* the terms of the GNU General Public License, either version 2
12+
* of the License, or any later version.
13+
*/
14+
15+
use B13\Container\Domain\Factory\ContainerFactory;
16+
use B13\Container\Domain\Factory\Exception;
17+
use B13\Container\Tca\Registry;
18+
use Psr\Http\Message\ServerRequestInterface;
19+
use TYPO3\CMS\Backend\Utility\BackendUtility;
20+
use TYPO3\CMS\Backend\View\Event\ManipulateBackendLayoutColPosConfigurationForPageEvent;
21+
22+
class ManipulateBackendLayoutColPosConfigurationForPage
23+
{
24+
/**
25+
* @var Registry
26+
*/
27+
protected $tcaRegistry;
28+
29+
/**
30+
* @var ContainerFactory
31+
*/
32+
protected $containerFactory;
33+
34+
public function __construct(ContainerFactory $containerFactory, Registry $tcaRegistry)
35+
{
36+
$this->containerFactory = $containerFactory;
37+
$this->tcaRegistry = $tcaRegistry;
38+
}
39+
40+
public function __invoke(ManipulateBackendLayoutColPosConfigurationForPageEvent $e)
41+
{
42+
$parent = $this->getParentUid($e->request);
43+
if ($parent === null) {
44+
return;
45+
}
46+
47+
try {
48+
$container = $this->containerFactory->buildContainer($parent);
49+
} catch (Exception $e) {
50+
// not a container
51+
return;
52+
}
53+
$cType = $container->getCType();
54+
$configuration = $this->tcaRegistry->getContentDefenderConfiguration($cType, $e->colPos);
55+
$e->configuration = [
56+
'allowedContentTypes' => $configuration['allowedContentTypes'],
57+
'disallowedContentTypes' => $configuration['disallowedContentTypes'],
58+
];
59+
}
60+
61+
private function getParentUid(?ServerRequestInterface $request): ?int
62+
{
63+
if ($request === null) {
64+
return null;
65+
}
66+
$queryParams = $request->getQueryParams();
67+
if (isset($queryParams['tx_container_parent']) && $queryParams['tx_container_parent'] > 0) {
68+
// new content elemment wizard
69+
return (int)$queryParams['tx_container_parent'];
70+
}
71+
if (
72+
isset($queryParams['defVals']['tt_content']['tx_container_parent']) &&
73+
$queryParams['defVals']['tt_content']['tx_container_parent'] > 0
74+
) {
75+
// TcaCTypeItems: new record
76+
return (int)$queryParams['defVals']['tt_content']['tx_container_parent'];
77+
}
78+
if (isset($queryParams['edit']['tt_content'])) {
79+
$recordUid = array_keys($queryParams['edit']['tt_content'])[0];
80+
$recordUid = (int)abs($recordUid);
81+
// TcaCTypeItems: edit record
82+
$record = BackendUtility::getRecord('tt_content', $recordUid, 'tx_container_parent');
83+
if (isset($record['tx_container_parent'])) {
84+
return (int)$record['tx_container_parent'];
85+
}
86+
}
87+
// todo tests ?
88+
// negative id occures in edit element -> create new
89+
// https://core14.ddev.site/typo3/record/edit?edit%5Btt_content%5D%5B11%5D=edit
90+
// https://core14.ddev.site/typo3/record/edit?edit%5Btt_content%5D%5B-11%5D=new&
91+
return null;
92+
}
93+
}

Classes/Tca/Registry.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,17 @@ public function getContentDefenderConfiguration(string $cType, int $colPos): arr
124124
foreach ($rows as $columns) {
125125
foreach ($columns as $column) {
126126
if ((int)$column['colPos'] === $colPos) {
127+
$contentDefenderConfiguration['allowedContentTypes'] = $column['allowedContentTypes'] ?? [];
128+
$contentDefenderConfiguration['disallowedContentTypes'] = $column['disallowedContentTypes'] ?? [];
127129
$contentDefenderConfiguration['allowed.'] = $column['allowed'] ?? [];
128130
$contentDefenderConfiguration['disallowed.'] = $column['disallowed'] ?? [];
129131
$contentDefenderConfiguration['maxitems'] = $column['maxitems'] ?? 0;
132+
if ($contentDefenderConfiguration['allowedContentTypes'] === [] && $contentDefenderConfiguration['allowed.'] !== []) {
133+
$contentDefenderConfiguration['allowedContentTypes'] = $contentDefenderConfiguration['allowed.']['CType'] ?? '';
134+
}
135+
if ($contentDefenderConfiguration['disallowedContentTypes'] === [] && $contentDefenderConfiguration['disallowed.'] !== []) {
136+
$contentDefenderConfiguration['disallowedContentTypes'] = $contentDefenderConfiguration['disallowed.']['CType'] ?? '';
137+
}
130138
return $contentDefenderConfiguration;
131139
}
132140
}

Configuration/Services.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ services:
5757
tags:
5858
- name: event.listener
5959
identifier: 'tx-container-content-used-on-page'
60+
B13\Container\Listener\ManipulateBackendLayoutColPosConfigurationForPage:
61+
tags:
62+
- name: event.listener
63+
identifier: 'tx-container-ManipulateBackendLayoutColPosConfigurationForPage'
6064
B13\Container\Listener\ModifyNewContentElementWizardItems:
6165
tags:
6266
- name: event.listener

Tests/Acceptance/Backend/ContentDefenderCest.php

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
use B13\Container\Tests\Acceptance\Support\BackendTester;
1616
use B13\Container\Tests\Acceptance\Support\PageTree;
1717
use B13\Container\Tests\Acceptance\Support\PageTreeV13;
18-
use TYPO3\CMS\Core\Information\Typo3Version;
19-
use TYPO3\CMS\Core\Utility\GeneralUtility;
2018

2119
class ContentDefenderCest
2220
{
@@ -34,7 +32,7 @@ public function _before(BackendTester $I)
3432
public function canCreateChildIn2ColsContainerWithNoContentDefenderRestrictionsDefined(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13): void
3533
{
3634
$I->clickLayoutModuleButton();
37-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
35+
if ($I->getTypo3MajorVersion() < 13) {
3836
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
3937
$pageTree->openPath(['home', 'pageWithDifferentContainers']);
4038
} else {
@@ -47,7 +45,7 @@ public function canCreateChildIn2ColsContainerWithNoContentDefenderRestrictionsD
4745
$I->clickNewContentElement($colPosSelector);
4846
$I->switchToIFrame();
4947
$I->waitForModal();
50-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() > 12) {
48+
if ($I->getTypo3MajorVersion() > 12) {
5149
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default\"]').click()");
5250
}
5351
$I->waitForText('Header Only');
@@ -61,7 +59,7 @@ public function canCreateChildIn2ColsContainerWithNoContentDefenderRestrictionsD
6159
public function doNotSeeNotAllowedContentElementsInNewContentElementWizard(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13): void
6260
{
6361
$I->clickLayoutModuleButton();
64-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
62+
if ($I->getTypo3MajorVersion() < 13) {
6563
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
6664
$pageTree->openPath(['home', 'pageWithContainer-3']);
6765
} else {
@@ -74,7 +72,7 @@ public function doNotSeeNotAllowedContentElementsInNewContentElementWizard(Backe
7472
$I->clickNewContentElement($colPosSelector);
7573
$I->switchToIFrame();
7674
$I->waitForModal();
77-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() > 12) {
75+
if ($I->getTypo3MajorVersion() > 12) {
7876
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default\"]').click()");
7977
}
8078
$I->waitForText('Header Only');
@@ -87,23 +85,22 @@ public function doNotSeeNotAllowedContentElementsInNewContentElementWizard(Backe
8785
public function doNotSeeNotAllowedContentElementsInNewContentElementWizardTriggeredByContextMenu(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13): void
8886
{
8987
$I->clickLayoutModuleButton();
90-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
88+
if ($I->getTypo3MajorVersion() < 13) {
9189
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
9290
$pageTree->openPath(['home', 'pageWithContainer-3']);
9391
} else {
9492
$pageTreeV13->openPath(['home', 'pageWithContainer-3']);
9593
}
9694
$I->wait(0.5);
9795
$I->switchToContentFrame();
98-
$typo3Version = GeneralUtility::makeInstance(Typo3Version::class);
99-
if ($typo3Version->getMajorVersion() < 12) {
96+
if ($I->getTypo3MajorVersion() < 12) {
10097
$I->waitForElement('#element-tt_content-810 a.t3js-contextmenutrigger');
10198
$I->click('#element-tt_content-810 a.t3js-contextmenutrigger');
10299
} else {
103100
$I->waitForElement('#element-tt_content-800 [data-contextmenu-uid="810"]');
104101
$I->click('#element-tt_content-800 [data-contextmenu-uid="810"]');
105102
}
106-
switch ($typo3Version->getMajorVersion()) {
103+
switch ($I->getTypo3MajorVersion()) {
107104
case 11:
108105
$I->waitForText('More options...');
109106
$I->click('.list-group-item-submenu');
@@ -128,7 +125,7 @@ public function doNotSeeNotAllowedContentElementsInNewContentElementWizardTrigge
128125

129126
$I->switchToIFrame();
130127
$I->waitForModal();
131-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() > 12) {
128+
if ($I->getTypo3MajorVersion() > 12) {
132129
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default\"]').click()");
133130
}
134131
$I->waitForText('Header Only');
@@ -141,7 +138,7 @@ public function doNotSeeNotAllowedContentElementsInNewContentElementWizardTrigge
141138
public function doNotSeeNotAllowedContentElementsInCTypeSelectBoxWhenCreateNewElement(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
142139
{
143140
$I->clickLayoutModuleButton();
144-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
141+
if ($I->getTypo3MajorVersion() < 13) {
145142
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
146143
$pageTree->openPath(['home', 'pageWithContainer-4']);
147144
} else {
@@ -154,15 +151,14 @@ public function doNotSeeNotAllowedContentElementsInCTypeSelectBoxWhenCreateNewEl
154151
$I->clickNewContentElement($colPosSelector);
155152
$I->switchToIFrame();
156153
$I->waitForModal();
157-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() > 12) {
154+
if ($I->getTypo3MajorVersion() > 12) {
158155
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default\"]').click()");
159156
}
160157
$I->waitForText('Header Only');
161-
$typo3Version = GeneralUtility::makeInstance(Typo3Version::class);
162-
if ($typo3Version->getMajorVersion() < 12) {
158+
if ($I->getTypo3MajorVersion() < 12) {
163159
$I->click('Header Only');
164160
} else {
165-
if ($typo3Version->getMajorVersion() < 13) {
161+
if ($I->getTypo3MajorVersion() < 13) {
166162
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"common_header\"]').click()");
167163
} else {
168164
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default_header\"]').click()");
@@ -180,7 +176,7 @@ public function doNotSeeNotAllowedContentElementsInCTypeSelectBoxWhenCreateNewEl
180176
public function doNotSeeNotAllowedContentElementsInCTypeSelectBoxWhenEditAnElement(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
181177
{
182178
$I->clickLayoutModuleButton();
183-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
179+
if ($I->getTypo3MajorVersion() < 13) {
184180
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
185181
$pageTree->openPath(['home', 'contentTCASelectCtype']);
186182
} else {
@@ -201,7 +197,7 @@ public function doNotSeeNotAllowedContentElementsInCTypeSelectBoxWhenEditAnEleme
201197
public function canSeeNewContentButtonIfMaxitemsIsNotReached(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
202198
{
203199
$I->clickLayoutModuleButton();
204-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
200+
if ($I->getTypo3MajorVersion() < 13) {
205201
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
206202
$pageTree->openPath(['home', 'contentDefenderMaxitems']);
207203
} else {
@@ -220,7 +216,7 @@ public function canSeeNewContentButtonIfMaxitemsIsNotReached(BackendTester $I, P
220216
public function canNotSeeNewContentButtonIfMaxitemsIsReached(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
221217
{
222218
$I->clickLayoutModuleButton();
223-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
219+
if ($I->getTypo3MajorVersion() < 13) {
224220
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
225221
$pageTree->openPath(['home', 'contentDefenderMaxitems']);
226222
} else {
@@ -240,7 +236,7 @@ public function canNotSeeNewContentButtonIfMaxitemsIsReached(BackendTester $I, P
240236
public function canCreateNewChildInContainerIfMaxitemsIsReachedInOtherContainer(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
241237
{
242238
$I->clickLayoutModuleButton();
243-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
239+
if ($I->getTypo3MajorVersion() < 13) {
244240
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
245241
$pageTree->openPath(['home', 'contentDefenderMaxitems']);
246242
} else {
@@ -253,15 +249,14 @@ public function canCreateNewChildInContainerIfMaxitemsIsReachedInOtherContainer(
253249
$I->clickNewContentElement($colPosSelector);
254250
$I->switchToIFrame();
255251
$I->waitForModal();
256-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() > 12) {
252+
if ($I->getTypo3MajorVersion() > 12) {
257253
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default\"]').click()");
258254
}
259255
$I->waitForText('Header Only');
260-
$typo3Version = GeneralUtility::makeInstance(Typo3Version::class);
261-
if ($typo3Version->getMajorVersion() < 12) {
256+
if ($I->getTypo3MajorVersion() < 12) {
262257
$I->click('Header Only');
263258
} else {
264-
if ($typo3Version->getMajorVersion() < 13) {
259+
if ($I->getTypo3MajorVersion() < 13) {
265260
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"common_header\"]').click()");
266261
} else {
267262
$I->executeJS("document.querySelector('" . $I->getNewRecordWizardSelector() . "').shadowRoot.querySelector('button[data-identifier=\"default_header\"]').click()");
@@ -278,7 +273,7 @@ public function canCreateNewChildInContainerIfMaxitemsIsReachedInOtherContainer(
278273
public function seeEditDocumentWhenAddingChildrenToColposWhereOnlyHeaderIsAllowed(BackendTester $I, PageTree $pageTree, PageTreeV13 $pageTreeV13)
279274
{
280275
$I->clickLayoutModuleButton();
281-
if (GeneralUtility::makeInstance(Typo3Version::class)->getMajorVersion() < 13) {
276+
if ($I->getTypo3MajorVersion() < 13) {
282277
$I->waitForElement('#typo3-pagetree-tree .nodes .node');
283278
$pageTree->openPath(['home', 'pageWithDifferentContainers']);
284279
} else {

0 commit comments

Comments
 (0)