From 6a2c200f0ea3bb948595b465163dedd1f23d83bb Mon Sep 17 00:00:00 2001 From: David Mellen Date: Wed, 7 Aug 2024 08:22:39 +0200 Subject: [PATCH] feat: add breadcrumbTitleProvider --- .../AbstractBreadcrumbTitleProvider.php | 17 +++ .../BreadcrumbTitleProviderInterface.php | 10 ++ .../BreadcrumbTitleProviderManager.php | 100 ++++++++++++++++++ ...cheableContentIsGeneratedEventListener.php | 36 +++++++ Configuration/Services.yaml | 4 + ext_localconf.php | 6 +- 6 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 Classes/BreadcrumbTitle/AbstractBreadcrumbTitleProvider.php create mode 100644 Classes/BreadcrumbTitle/BreadcrumbTitleProviderInterface.php create mode 100644 Classes/BreadcrumbTitle/BreadcrumbTitleProviderManager.php create mode 100644 Classes/Event/Listener/AfterCacheableContentIsGeneratedEventListener.php diff --git a/Classes/BreadcrumbTitle/AbstractBreadcrumbTitleProvider.php b/Classes/BreadcrumbTitle/AbstractBreadcrumbTitleProvider.php new file mode 100644 index 0000000..d20ee70 --- /dev/null +++ b/Classes/BreadcrumbTitle/AbstractBreadcrumbTitleProvider.php @@ -0,0 +1,17 @@ +title; + } +} diff --git a/Classes/BreadcrumbTitle/BreadcrumbTitleProviderInterface.php b/Classes/BreadcrumbTitle/BreadcrumbTitleProviderInterface.php new file mode 100644 index 0000000..546fe7e --- /dev/null +++ b/Classes/BreadcrumbTitle/BreadcrumbTitleProviderInterface.php @@ -0,0 +1,10 @@ +getBreadcrumbTitleProviderConfiguration(); + $titleProviders = $this->setProviderOrder($titleProviders); + + $orderedTitleProviders = GeneralUtility::makeInstance(DependencyOrderingService::class) + ->orderByDependencies($titleProviders); + + $this->logger->debug('Breadcrumb title providers ordered', [ + 'orderedTitleProviders' => $orderedTitleProviders, + ]); + + foreach ($orderedTitleProviders as $provider => $configuration) { + if ( + class_exists($configuration['provider']) && + is_subclass_of($configuration['provider'], BreadcrumbTitleProviderInterface::class) + ) { + /** @var BreadcrumbTitleProviderInterface $titleProviderObject */ + $titleProviderObject = GeneralUtility::makeInstance($configuration['provider']); + if ( + ($breadcrumbTitle = $titleProviderObject->getTitle()) + || ($breadcrumbTitle = $this->breadcrumbTitleCache[$configuration['provider']] ?? '') !== '' + ) { + $this->logger->debug('Breadcrumb title provider {provider} used on page {title}', [ + 'title' => $breadcrumbTitle, + 'provider' => $configuration['provider'], + ]); + $this->breadcrumbTitleCache[$configuration['provider']] = $breadcrumbTitle; + break; + } + $this->logger->debug('Breadcrumb title provider {provider} skipped on page {title}', [ + 'title' => $breadcrumbTitle, + 'provider' => $configuration['provider'], + 'providerUsed' => $configuration['provider'], + ]); + } + } + + return $breadcrumbTitle; + } + + protected function setProviderOrder(array $orderInformation): array + { + foreach ($orderInformation as $provider => &$configuration) { + if (isset($configuration['before'])) { + if (is_string($configuration['before'])) { + $configuration['before'] = GeneralUtility::trimExplode(',', $configuration['before'], true); + } elseif (!is_array($configuration['before'])) { + throw new UnexpectedValueException( + 'The specified "before" order configuration for provider "' . $provider . '" is invalid.', + 1535803185 + ); + } + } + if (isset($configuration['after'])) { + if (is_string($configuration['after'])) { + $configuration['after'] = GeneralUtility::trimExplode(',', $configuration['after'], true); + } elseif (!is_array($configuration['after'])) { + throw new UnexpectedValueException( + 'The specified "after" order configuration for provider "' . $provider . '" is invalid.', + 1535803186 + ); + } + } + } + return $orderInformation; + } + + private function getBreadcrumbTitleProviderConfiguration(): array + { + $typoscriptService = GeneralUtility::makeInstance(TypoScriptService::class); + $config = $typoscriptService->convertTypoScriptArrayToPlainArray( + $GLOBALS['TSFE']->config['config'] ?? [] + ); + + return $config['breadcrumbTitleProviders'] ?? []; + } +} diff --git a/Classes/Event/Listener/AfterCacheableContentIsGeneratedEventListener.php b/Classes/Event/Listener/AfterCacheableContentIsGeneratedEventListener.php new file mode 100644 index 0000000..eda3e66 --- /dev/null +++ b/Classes/Event/Listener/AfterCacheableContentIsGeneratedEventListener.php @@ -0,0 +1,36 @@ +getController()->content, true, 512, JSON_THROW_ON_ERROR); + + $breadcrumbTitle = $this->breadcrumbTitleProviderManager->getTitle(); + + if ($breadcrumbTitle) { + $content['breadcrumbs'][array_key_last($content['breadcrumbs'])]['title'] = $breadcrumbTitle; + } + + $event->getController()->content = $this->encoder->encode($content); + } catch (Throwable) { + return; + } + } +} diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml index 8bea0d7..40ad936 100644 --- a/Configuration/Services.yaml +++ b/Configuration/Services.yaml @@ -15,3 +15,7 @@ services: tags: - name: event.listener + Remind\Headless\Event\Listener\AfterCacheableContentIsGeneratedEventListener: + tags: + - + name: event.listener diff --git a/ext_localconf.php b/ext_localconf.php index eeebb36..5152133 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -20,12 +20,14 @@ $GLOBALS ['TYPO3_CONF_VARS'] - ['SYS']['features'] + ['SYS'] + ['features'] ['headless.elementBodyResponse'] = true; $GLOBALS ['TYPO3_CONF_VARS'] - ['SYS']['features'] + ['SYS'] + ['features'] ['headless.frontendUrls'] = true; $GLOBALS