[FEATURE] Add PageTitle API
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / PageTitle / PageTitleProviderManager.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\PageTitle;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use TYPO3\CMS\Core\Cache\Backend\AbstractBackend;
20 use TYPO3\CMS\Core\Cache\CacheManager;
21 use TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException;
22 use TYPO3\CMS\Core\Service\DependencyOrderingService;
23 use TYPO3\CMS\Core\SingletonInterface;
24 use TYPO3\CMS\Core\TypoScript\TypoScriptService;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
27
28 /**
29 * This class will take care of the different providers and returns the title with the highest priority
30 */
31 class PageTitleProviderManager implements SingletonInterface
32 {
33 /**
34 * @var \TYPO3\CMS\Core\Cache\Backend\AbstractBackend
35 */
36 protected $pageCache;
37
38 public function __construct()
39 {
40 $this->initCaches();
41 }
42
43 /**
44 * @return string
45 * @throws \TYPO3\CMS\Core\Cache\Exception
46 * @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
47 */
48 public function getTitle(): string
49 {
50 $pageTitle = '';
51
52 $titleProviders = $this->getPageTitleProviderConfiguration();
53 $titleProviders = $this->setProviderOrder($titleProviders);
54
55 $orderedTitleProviders = GeneralUtility::makeInstance(DependencyOrderingService::class)
56 ->orderByDependencies($titleProviders);
57
58 foreach ($orderedTitleProviders as $provider => $configuration) {
59 $cacheIdentifier = $this->getTypoScriptFrontendController()->newHash . '-titleTag-' . $provider;
60 if ($this->pageCache instanceof AbstractBackend &&
61 $pageTitle = $this->pageCache->get($cacheIdentifier)
62 ) {
63 break;
64 }
65 if (class_exists($configuration['provider']) && is_subclass_of($configuration['provider'], PageTitleProviderInterface::class)) {
66 /** @var PageTitleProviderInterface $titleProviderObject */
67 $titleProviderObject = GeneralUtility::makeInstance($configuration['provider']);
68 if ($pageTitle = $titleProviderObject->getTitle()) {
69 $this->pageCache->set(
70 $cacheIdentifier,
71 $pageTitle,
72 ['pageTitle_' . $this->getTypoScriptFrontendController()->page['uid']]
73 );
74 break;
75 }
76 }
77 }
78
79 return $pageTitle;
80 }
81
82 /**
83 * @return \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController
84 */
85 private function getTypoScriptFrontendController(): TypoScriptFrontendController
86 {
87 return $GLOBALS['TSFE'];
88 }
89
90 /**
91 * Get the TypoScript configuration for pageTitleProviders
92 * @return array
93 */
94 private function getPageTitleProviderConfiguration(): array
95 {
96 $typoscriptService = GeneralUtility::makeInstance(TypoScriptService::class);
97 $config = $typoscriptService->convertTypoScriptArrayToPlainArray(
98 $this->getTypoScriptFrontendController()->config['config'] ?? []
99 );
100
101 return $config['pageTitleProviders'] ?? [];
102 }
103
104 /**
105 * Initializes the caching system.
106 */
107 protected function initCaches(): void
108 {
109 try {
110 $this->pageCache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_pages');
111 } catch (NoSuchCacheException $e) {
112 // Intended fall-through
113 }
114 }
115
116 /**
117 * @param array $orderInformation
118 * @return string[]
119 * @throws \UnexpectedValueException
120 */
121 protected function setProviderOrder(array $orderInformation): array
122 {
123 foreach ($orderInformation as $provider => &$configuration) {
124 if (isset($configuration['before'])) {
125 if (is_string($configuration['before'])) {
126 $configuration['before'] = GeneralUtility::trimExplode(',', $configuration['before'], true);
127 } elseif (!is_array($configuration['before'])) {
128 throw new \UnexpectedValueException(
129 'The specified "before" order configuration for provider "' . $provider . '" is invalid.',
130 1535803185
131 );
132 }
133 }
134 if (isset($configuration['after'])) {
135 if (is_string($configuration['after'])) {
136 $configuration['after'] = GeneralUtility::trimExplode(',', $configuration['after'], true);
137 } elseif (!is_array($configuration['after'])) {
138 throw new \UnexpectedValueException(
139 'The specified "after" order configuration for provider "' . $provider . '" is invalid.',
140 1535803186
141 );
142 }
143 }
144 }
145 return $orderInformation;
146 }
147 }