302925a19f45fb803cca093db93f4ea5b232b135
[Packages/TYPO3.CMS.git] / typo3 / sysext / seo / Classes / XmlSitemap / XmlSitemapRenderer.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Seo\XmlSitemap;
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 Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Core\Utility\PathUtility;
23 use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
24 use TYPO3\CMS\Extbase\Object\ObjectManager;
25 use TYPO3\CMS\Fluid\View\StandaloneView;
26 use TYPO3\CMS\Seo\XmlSitemap\Exception\InvalidConfigurationException;
27
28 /**
29 * Class to render the XML Sitemap to be used as a UserFunction
30 * @internal this class is not part of TYPO3's Core API.
31 */
32 class XmlSitemapRenderer
33 {
34 /**
35 * @var array
36 */
37 protected $configuration;
38
39 /**
40 * @var \TYPO3\CMS\Fluid\View\StandaloneView
41 */
42 protected $view;
43
44 public function __construct()
45 {
46 $this->configuration = $this->getConfiguration();
47 $this->view = $this->getStandaloneView();
48 $this->view->assign(
49 'xslFile',
50 PathUtility::stripPathSitePrefix(
51 ExtensionManagementUtility::extPath('seo', 'Resources/Public/CSS/Sitemap.xsl')
52 )
53 );
54 }
55
56 /**
57 * @return string
58 * @throws InvalidConfigurationException
59 */
60 public function render(): string
61 {
62 // Inject request from globals until request will be available to cObj
63 $request = $GLOBALS['TYPO3_REQUEST'];
64 $this->view->assign('type', $request->getQueryParams()['type']);
65 if (!empty($sitemap = $request->getQueryParams()['sitemap'])) {
66 return $this->renderSitemap($request, $sitemap);
67 }
68
69 return $this->renderIndex($request);
70 }
71
72 /**
73 * @param \Psr\Http\Message\ServerRequestInterface $request
74 * @return string
75 */
76 protected function renderIndex(ServerRequestInterface $request): string
77 {
78 $sitemaps = [];
79 foreach ($this->configuration['config']['xmlSitemap']['sitemaps'] ?? [] as $sitemap => $config) {
80 if (class_exists($config['provider']) &&
81 is_subclass_of($config['provider'], XmlSitemapDataProviderInterface::class)) {
82 /** @var XmlSitemapDataProviderInterface $provider */
83 $provider = GeneralUtility::makeInstance(
84 $config['provider'],
85 $request,
86 $sitemap,
87 (array)$config['config']
88 );
89
90 $pages = $provider->getNumberOfPages();
91
92 for ($page = 0; $page < $pages; $page++) {
93 $sitemaps[] = [
94 'key' => $sitemap,
95 'page' => $page,
96 'lastMod' => $provider->getLastModified()
97 ];
98 }
99 }
100 }
101
102 $this->view->assign('sitemaps', $sitemaps);
103 $this->view->setTemplate('Index');
104
105 return $this->view->render();
106 }
107
108 /**
109 * @param \Psr\Http\Message\ServerRequestInterface $request
110 * @param string $sitemap
111 * @return string
112 * @throws \TYPO3\CMS\Seo\XmlSitemap\Exception\InvalidConfigurationException
113 */
114 protected function renderSitemap(ServerRequestInterface $request, string $sitemap): string
115 {
116 if (!empty($sitemapConfig = $this->configuration['config']['xmlSitemap']['sitemaps'][$sitemap])) {
117 if (class_exists($sitemapConfig['provider']) &&
118 is_subclass_of($sitemapConfig['provider'], XmlSitemapDataProviderInterface::class)) {
119 /** @var XmlSitemapDataProviderInterface $provider */
120 $provider = GeneralUtility::makeInstance(
121 $sitemapConfig['provider'],
122 $request,
123 $sitemap,
124 (array)$sitemapConfig['config']
125 );
126
127 $items = $provider->getItems();
128
129 $template = $sitemapConfig['config']['template'] ?: 'Sitemap';
130 $this->view->setTemplate($template);
131 $this->view->assign('items', $items);
132
133 return $this->view->render();
134 }
135 throw new InvalidConfigurationException('No valid provider set for ' . $sitemap, 1535578522);
136 }
137
138 throw new InvalidConfigurationException('No valid configuration found for sitemap ' . $sitemap, 1535578569);
139 }
140
141 /**
142 * @return \TYPO3\CMS\Fluid\View\StandaloneView
143 */
144 protected function getStandaloneView(): StandaloneView
145 {
146 $view = GeneralUtility::makeInstance(StandaloneView::class);
147 $view->setTemplateRootPaths($this->configuration['view']['templateRootPaths']);
148 $view->setLayoutRootPaths($this->configuration['view']['layoutRootPaths']);
149 $view->setPartialRootPaths($this->configuration['view']['partialRootPaths']);
150 $view->setFormat('xml');
151
152 return $view;
153 }
154
155 /**
156 * Get the whole typoscript array
157 * @return array
158 */
159 private function getConfiguration(): array
160 {
161 $configurationManager = GeneralUtility::makeInstance(ObjectManager::class)
162 ->get(ConfigurationManagerInterface::class);
163
164 return $configurationManager->getConfiguration(
165 ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK,
166 'seo'
167 );
168 }
169 }