[BUGFIX] Respect GET parameters when generating canonicalized URLs
[Packages/TYPO3.CMS.git] / typo3 / sysext / seo / Classes / HrefLang / HrefLangGenerator.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Seo\HrefLang;
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\Http\Uri;
20 use TYPO3\CMS\Core\Site\Entity\Site;
21 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
22 use TYPO3\CMS\Core\Utility\GeneralUtility;
23 use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
24 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
25 use TYPO3\CMS\Frontend\DataProcessing\LanguageMenuProcessor;
26
27 /**
28 * Class to add the hreflang tags to the page
29 *
30 * @internal
31 */
32 class HrefLangGenerator
33 {
34 /**
35 * The content object renderer
36 *
37 * @var ContentObjectRenderer
38 */
39 public $cObj;
40
41 /**
42 * @var TypoScriptFrontendController
43 */
44 protected $typoScriptFrontendController;
45
46 /**
47 * HreflangGenerator constructor
48 *
49 * @param ContentObjectRenderer|null $cObj
50 * @param TypoScriptFrontendController|null $typoScriptFrontendController
51 */
52 public function __construct(ContentObjectRenderer $cObj = null, TypoScriptFrontendController $typoScriptFrontendController = null)
53 {
54 if ($cObj === null) {
55 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
56 }
57 if ($typoScriptFrontendController === null) {
58 $typoScriptFrontendController = $this->getTypoScriptFrontendController();
59 }
60
61 $this->cObj = $cObj;
62 $this->typoScriptFrontendController = $typoScriptFrontendController;
63 }
64
65 public function generate(): string
66 {
67 $hreflangs = [];
68 if ((int)$this->typoScriptFrontendController->page['no_index'] === 1) {
69 return '';
70 }
71
72 if ($GLOBALS['TYPO3_REQUEST']->getAttribute('site') instanceof Site) {
73 $languageMenu = GeneralUtility::makeInstance(LanguageMenuProcessor::class);
74 $languages = $languageMenu->process($this->cObj, [], [], []);
75 foreach ($languages['languagemenu'] as $language) {
76 if ($language['available'] === 1) {
77 $href = $this->getAbsoluteUrl($language['link']);
78 $hreflangs[] =
79 '<link rel="alternate" hreflang="' . htmlspecialchars($language['hreflang']) . '" href="' . htmlspecialchars($href) . '"/>';
80 }
81 }
82
83 if (count($hreflangs) > 1) {
84 $href = $this->getAbsoluteUrl($languages['languagemenu'][0]['link']);
85 $hreflangs[] =
86 '<link rel="alternate" hreflang="x-default" href="' . htmlspecialchars($href) . '"/>' . LF;
87
88 $GLOBALS['TSFE']->additionalHeaderData[] = implode(LF, $hreflangs);
89 }
90 }
91
92 return implode(LF, $hreflangs);
93 }
94
95 /**
96 * @param string $url
97 * @return string
98 */
99 protected function getAbsoluteUrl(string $url): string
100 {
101 $uri = new Uri($url);
102 if (empty($uri->getHost())) {
103 $url = $this->getSiteLanguage()->getBase()->withPath($uri->getPath());
104
105 if ($uri->getQuery()) {
106 $url = $url->withQuery($uri->getQuery());
107 }
108 }
109
110 return (string)$url;
111 }
112
113 /**
114 * @return SiteLanguage
115 */
116 protected function getSiteLanguage(): SiteLanguage
117 {
118 return $GLOBALS['TYPO3_REQUEST']->getAttribute('language');
119 }
120
121 /**
122 * @return TypoScriptFrontendController
123 */
124 protected function getTypoScriptFrontendController(): TypoScriptFrontendController
125 {
126 return $GLOBALS['TSFE'];
127 }
128 }