[BUGFIX] Ensure most site related exceptions are handled
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Site / SiteFinder.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\Site;
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\Configuration\SiteConfiguration;
20 use TYPO3\CMS\Core\Core\Environment;
21 use TYPO3\CMS\Core\Exception\Page\PageNotFoundException;
22 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
23 use TYPO3\CMS\Core\Site\Entity\Site;
24 use TYPO3\CMS\Core\Utility\GeneralUtility;
25 use TYPO3\CMS\Core\Utility\RootlineUtility;
26
27 /**
28 * Is used in backend and frontend for all places where to read / identify sites and site languages.
29 */
30 class SiteFinder
31 {
32 /**
33 * @var Site[]
34 */
35 protected $sites = [];
36
37 /**
38 * Short-hand to quickly fetch a site based on a rootPageId
39 *
40 * @var array
41 */
42 protected $mappingRootPageIdToIdentifier = [];
43
44 /**
45 * Fetches all existing configurations as Site objects
46 */
47 public function __construct()
48 {
49 $reader = GeneralUtility::makeInstance(SiteConfiguration::class, Environment::getConfigPath() . '/sites');
50 $sites = $reader->resolveAllExistingSites();
51 foreach ($sites as $identifier => $site) {
52 $this->sites[$identifier] = $site;
53 $this->mappingRootPageIdToIdentifier[$site->getRootPageId()] = $identifier;
54 }
55 }
56
57 /**
58 * Return a list of all configured sites
59 *
60 * @return Site[]
61 */
62 public function getAllSites(): array
63 {
64 return $this->sites;
65 }
66
67 /**
68 * Find a site by given root page id
69 *
70 * @param int $rootPageId the page ID (default language)
71 * @return Site
72 * @throws SiteNotFoundException
73 * @internal only for usage in some places for managing Site Configuration, might be removed without further notice
74 */
75 public function getSiteByRootPageId(int $rootPageId): Site
76 {
77 if (isset($this->mappingRootPageIdToIdentifier[$rootPageId])) {
78 return $this->sites[$this->mappingRootPageIdToIdentifier[$rootPageId]];
79 }
80 throw new SiteNotFoundException('No site found for root page id ' . $rootPageId, 1521668882);
81 }
82
83 /**
84 * Find a site by given identifier
85 *
86 * @param string $identifier
87 * @return Site
88 * @throws SiteNotFoundException
89 */
90 public function getSiteByIdentifier(string $identifier): Site
91 {
92 if (isset($this->sites[$identifier])) {
93 return $this->sites[$identifier];
94 }
95 throw new SiteNotFoundException('No site found for identifier ' . $identifier, 1521716628);
96 }
97
98 /**
99 * Traverses the rootline of a page up until a Site was found.
100 *
101 * @param int $pageId
102 * @param array $rootLine
103 * @return Site
104 * @throws SiteNotFoundException
105 */
106 public function getSiteByPageId(int $pageId, array $rootLine = null): Site
107 {
108 if ($pageId === 0) {
109 // page uid 0 has no root line. We don't need to ask the root line resolver to know that.
110 $rootLine = [];
111 }
112 if (!is_array($rootLine)) {
113 try {
114 $rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId)->get();
115 } catch (PageNotFoundException $e) {
116 // Usually when a page was hidden or disconnected
117 // This could be improved by handing in a Context object and decide whether hidden pages
118 // Should be linkeable too
119 $rootLine = [];
120 }
121 }
122 foreach ($rootLine as $pageInRootLine) {
123 if (isset($this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']])) {
124 return $this->sites[$this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']]];
125 }
126 }
127 throw new SiteNotFoundException('No site found in root line of page ' . $pageId, 1521716622);
128 }
129 }