diff --git a/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php b/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php new file mode 100644 index 00000000..ec4aefd3 --- /dev/null +++ b/Classes/Event/Listener/AfterCacheableContentIsGeneratedListener.php @@ -0,0 +1,43 @@ +getController()->content, true, 512, JSON_THROW_ON_ERROR); + + if (($content['meta']['title'] ?? null) === null) { + return; + } + + $content['meta']['title'] = $event->getController()->generatePageTitle(); + + $event->getController()->content = $this->encoder->encode($content); + } catch (\Throwable) { + return; + } + } +} diff --git a/Configuration/Services.php b/Configuration/Services.php index b3f3ce34..a438b4ba 100644 --- a/Configuration/Services.php +++ b/Configuration/Services.php @@ -20,6 +20,7 @@ use FriendsOfTYPO3\Headless\DataProcessing\GalleryProcessor; use FriendsOfTYPO3\Headless\DataProcessing\MenuProcessor; use FriendsOfTYPO3\Headless\DataProcessing\RootSitesProcessor; +use FriendsOfTYPO3\Headless\Event\Listener\AfterCacheableContentIsGeneratedListener; use FriendsOfTYPO3\Headless\Event\Listener\AfterLinkIsGeneratedListener; use FriendsOfTYPO3\Headless\Event\Listener\AfterPagePreviewUriGeneratedListener; use FriendsOfTYPO3\Headless\Event\Listener\LoginConfirmedEventListener; @@ -77,6 +78,12 @@ 'event.listener', ['identifier' => 'headless/AfterLinkIsGenerated'] ); + $services->set(AfterCacheableContentIsGeneratedListener::class)->tag( + 'event.listener', + ['identifier' => 'headless/AfterCacheableContentIsGenerated'] + ); + + $features = GeneralUtility::makeInstance(Features::class); if ($feloginInstalled) { $services->set(LoginConfirmedEventListener::class)->tag( @@ -94,8 +101,6 @@ $services->set(FormTranslationService::class)->arg('$runtimeCache', service('cache.runtime'))->public(); } - $features = GeneralUtility::makeInstance(Features::class); - if ($features->isFeatureEnabled('headless.overrideFluidTemplates')) { $templateService = $services->alias( \TYPO3\CMS\Fluid\View\TemplateView::class, diff --git a/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php b/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php new file mode 100644 index 00000000..cd189b0a --- /dev/null +++ b/Tests/Unit/Event/Listener/AfterCacheableContentIsGeneratedListenerTest.php @@ -0,0 +1,76 @@ +prophesize(ServerRequestInterface::class); + $controller = $this->prophesize(TypoScriptFrontendController::class); + $controller->content = ''; + + $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); + + $listener($event); + + self::assertSame('', $event->getController()->content); + } + + public function testNotModifiedWhileValidJson(): void + { + $listener = new AfterCacheableContentIsGeneratedListener(new JsonEncoder()); + + $content = json_encode(['someCustomPageWithoutMeta' => ['title' => 'test before event']]); + + $request = $this->prophesize(ServerRequestInterface::class); + $controller = $this->prophesize(TypoScriptFrontendController::class); + $controller->content = $content; + $controller->generatePageTitle()->willReturn('Modified title via PageTitleManager'); + + $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); + + $listener($event); + + self::assertSame($content, $event->getController()->content); + } + + public function testModifiedPageTitle(): void + { + $listener = new AfterCacheableContentIsGeneratedListener(new JsonEncoder()); + + $request = $this->prophesize(ServerRequestInterface::class); + $controller = $this->prophesize(TypoScriptFrontendController::class); + $controller->content = json_encode(['meta' => ['title' => 'test before event']]); + $controller->generatePageTitle()->willReturn('Modified title via PageTitleProviderManager'); + + $event = new AfterCacheableContentIsGeneratedEvent($request->reveal(), $controller->reveal(), 'abc', false); + + $listener($event); + + self::assertSame(json_encode(['meta' => ['title' => 'Modified title via PageTitleProviderManager']]), $event->getController()->content); + } +}