From 5dcecfc393b02232123461fb0ede7a93fa1a3165 Mon Sep 17 00:00:00 2001 From: "Carsten Biebricher (orangefluid)" Date: Mon, 31 Aug 2026 14:35:03 +0200 Subject: [PATCH] fix(cache): detect not-cached elements via PageParts on TYPO3 v14 TYPO3 v14 removed INTincScript from FrontendTypoScript::getConfigArray() as part of the TypoScriptFrontendController dissolution (#107831/#107578), so this listener silently stopped adding cache rule explanations and pages with USER_INT/COA_INT or uncached extbase plugins were statically cached. Read the not-cached content element registry from the "frontend.page.parts" request attribute (PageParts) instead. The nonce-substitution skip is kept and now evaluates the cspGenerationOverride setting once per call. getInformation() is strictly typed and reports the new "substKey" key. PageParts is marked "@internal Experimental, will change" by the core and may change during v14/v15 development; a @todo documents this. Refs: https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.0/Breaking-107831-RemovedTypoScriptFrontendController.html --- .../Cache/Listener/NoIntScriptsListener.php | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/Classes/Cache/Listener/NoIntScriptsListener.php b/Classes/Cache/Listener/NoIntScriptsListener.php index becabd8c8b9..aa90e06190a 100644 --- a/Classes/Cache/Listener/NoIntScriptsListener.php +++ b/Classes/Cache/Listener/NoIntScriptsListener.php @@ -6,9 +6,8 @@ use SFC\Staticfilecache\Event\CacheRuleEvent; use SFC\Staticfilecache\Service\ConfigurationService; -use TYPO3\CMS\Core\TypoScript\FrontendTypoScript; use TYPO3\CMS\Frontend\Cache\NonceValueSubstitution; -use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; +use TYPO3\CMS\Frontend\Page\PageParts; class NoIntScriptsListener { @@ -16,34 +15,43 @@ public function __construct(protected readonly ConfigurationService $configurati public function __invoke(CacheRuleEvent $event): void { - $frontendTypoScript = $event->getRequest()->getAttribute('frontend.typoscript'); - if ($frontendTypoScript instanceof FrontendTypoScript) { - $configArray = $frontendTypoScript->getConfigArray(); - if (isset($configArray['INTincScript']) && is_array($configArray['INTincScript'])) { - foreach ($configArray['INTincScript'] as $key => $configuration) { - - $cspGenerationOverride = (bool) $this->configurationService->get('cspGenerationOverride'); - if ($cspGenerationOverride && isset($configuration['target']) && $configuration['target'] === NonceValueSubstitution::class . '->substituteNonce') { - continue; - } - - $event->addExplanation(__CLASS__ . ':' . $key, 'The page has a INTincScript: ' . implode(', ', $this->getInformation($configuration))); - } + // @todo PageParts is marked "@internal Experimental, will change" by the TYPO3 core + // and may change during v14/v15 development. Re-check this listener with + // every major TYPO3 update, see Breaking-107831/107578 (TSFE removal series). + $pageParts = $event->getRequest()->getAttribute('frontend.page.parts'); + if (!$pageParts instanceof PageParts) { + return; + } + $cspGenerationOverride = (bool) $this->configurationService->get('cspGenerationOverride'); + foreach ($pageParts->getNotCachedContentElementRegistry() as $key => $configuration) { + if ($cspGenerationOverride + && isset($configuration['target']) + && $configuration['target'] === NonceValueSubstitution::class . '->substituteNonce' + ) { + continue; } + + $event->addExplanation( + __CLASS__ . ':' . $key, + 'The page has a not-cached content element: ' . implode(', ', $this->getInformation($configuration)) + ); } } /** * Get the debug information. * - * @param array $configuration + * @param array $configuration + * + * @return array */ - protected function getInformation($configuration): array + protected function getInformation(array $configuration): array { $info = []; // Root properties foreach ([ + 'substKey', 'target', 'type', ] as $value) {