‪TYPO3CMS  ‪main
Site.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\Http\Message\UriInterface;
21 use Symfony\Component\ExpressionLanguage\SyntaxError;
35 
41 class ‪Site implements ‪SiteInterface
42 {
43  protected const ‪ERRORHANDLER_TYPE_PAGE = 'Page';
44  protected const ‪ERRORHANDLER_TYPE_FLUID = 'Fluid';
45  protected const ‪ERRORHANDLER_TYPE_PHP = 'PHP';
46 
50  protected ‪$identifier;
51 
55  protected ‪$base;
56 
60  protected ‪$rootPageId;
61 
66  protected ‪$configuration;
67 
71  protected ‪$languages;
72 
76  protected array $sets;
77 
81  protected $errorHandlers;
82 
83  protected ‪SiteSettings $settings;
84 
85  protected ?‪SiteTypoScript $typoscript;
86 
87  protected ?‪SiteTSconfig $tsConfig;
88 
92  public function __construct(string ‪$identifier, int ‪$rootPageId, array ‪$configuration, ‪SiteSettings $settings = null, ?‪SiteTypoScript $typoscript = null, ?‪SiteTSconfig $tsConfig = null)
93  {
96  if ($settings === null) {
97  $settings = new ‪SiteSettings(‪$configuration['settings'] ?? []);
98  }
99  $this->‪settings = $settings;
100  $this->‪typoscript = $typoscript;
101  $this->‪tsConfig = $tsConfig;
102  // Merge settings back in configuration for backwards-compatibility
103  ‪$configuration['settings'] = $this->‪settings->getAll();
105  $configuration['languages'] = !empty(‪$configuration['languages']) ? ‪$configuration['languages'] : [
106  0 => [
107  'languageId' => 0,
108  'title' => 'Default',
109  'navigationTitle' => '',
110  'flag' => 'us',
111  'locale' => 'en_US.UTF-8',
112  ],
113  ];
115  $configuration['base'] ?? '',
116  ‪$configuration['baseVariants'] ?? null
117  );
118  $this->‪base = new ‪Uri($this->‪sanitizeBaseUrl(‪$baseUrl));
119 
120  $this->‪sets = $configuration['dependencies'] ?? [];
121  foreach (‪$configuration['languages'] as $languageConfiguration) {
122  $languageUid = (int)$languageConfiguration['languageId'];
123  // site language has defined its own base, this is the case most of the time.
124  if (!empty($languageConfiguration['base'])) {
126  $languageConfiguration['base'],
127  $languageConfiguration['baseVariants'] ?? null
128  );
129  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl($base));
130  // no host given by the language-specific base, so lets prefix the main site base
131  if (‪$base->getScheme() === '' && ‪$base->getHost() === '') {
132  ‪$base = rtrim((string)$this->‪base, '/') . '/' . ltrim((string)‪$base, '/');
133  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl($base));
134  }
135  } else {
136  // Language configuration does not have a base defined
137  // So the main site base is used (usually done for default languages)
138  ‪$base = new Uri($this->‪sanitizeBaseUrl(rtrim((string)$this->‪base, '/') . '/'));
139  }
140  if (!empty($languageConfiguration['flag'])) {
141  if ($languageConfiguration['flag'] === 'global') {
142  $languageConfiguration['flag'] = 'flags-multiple';
143  } elseif ($languageConfiguration['flag'] !== 'empty-empty') {
144  $languageConfiguration['flag'] = 'flags-' . $languageConfiguration['flag'];
145  }
146  }
147  $this->‪languages[$languageUid] = new SiteLanguage(
148  $languageUid,
149  $languageConfiguration['locale'],
150  ‪$base,
151  $languageConfiguration
152  );
153  }
154  foreach (‪$configuration['errorHandling'] ?? [] as $errorHandlingConfiguration) {
155  $code = $errorHandlingConfiguration['errorCode'];
156  unset($errorHandlingConfiguration['errorCode']);
157  $this->errorHandlers[(int)$code] = $errorHandlingConfiguration;
158  }
159  }
160 
164  protected function ‪resolveBaseWithVariants(string ‪$baseUrl, ?array $baseVariants): string
165  {
166  if (!empty($baseVariants)) {
167  $expressionLanguageResolver = GeneralUtility::makeInstance(
168  Resolver::class,
169  'site',
170  []
171  );
172  foreach ($baseVariants as $baseVariant) {
173  try {
174  if ((bool)$expressionLanguageResolver->evaluate($baseVariant['condition'])) {
175  ‪$baseUrl = $baseVariant['base'];
176  break;
177  }
178  } catch (SyntaxError $e) {
179  // silently fail and do not evaluate
180  // no logger here, as Site is currently cached and serialized
181  }
182  }
183  }
184  return ‪$baseUrl;
185  }
186 
191  public function ‪getIdentifier(): string
192  {
194  }
195 
199  public function ‪getBase(): UriInterface
200  {
202  }
203 
207  public function ‪getRootPageId(): int
208  {
209  return ‪$this->rootPageId;
210  }
211 
217  public function ‪getLanguages(): array
218  {
219  ‪$languages = [];
220  foreach ($this->‪languages as $languageId => $language) {
221  if ($language->enabled()) {
222  ‪$languages[$languageId] = $language;
223  }
224  }
225  return ‪$languages;
226  }
227 
233  public function getSets(): array
234  {
235  return $this->sets;
236  }
237 
243  public function getAllLanguages(): array
244  {
245  return ‪$this->languages;
246  }
247 
253  public function ‪getLanguageById(int $languageId): ‪SiteLanguage
254  {
255  if (isset($this->‪languages[$languageId])) {
256  return $this->‪languages[$languageId];
257  }
258  throw new \InvalidArgumentException(
259  'Language ' . $languageId . ' does not exist on site ' . $this->‪identifier . '.',
260  1522960188
261  );
262  }
263 
264  public function ‪getDefaultLanguage(): ‪SiteLanguage
265  {
266  return reset($this->‪languages);
267  }
268 
272  public function ‪getAvailableLanguages(BackendUserAuthentication $user, bool $includeAllLanguagesFlag = false, int $pageId = null): array
273  {
275 
276  // Check if we need to add language "-1"
277  if ($includeAllLanguagesFlag && $user->checkLanguageAccess(-1)) {
278  ‪$availableLanguages[-1] = new ‪SiteLanguage(-1, '', $this->‪getBase(), [
279  'title' => $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages'),
280  'flag' => 'flags-multiple',
281  ]);
282  }
283 
284  // Do not add the ones that are not allowed by the user
285  foreach ($this->‪languages as $language) {
286  if ($user->checkLanguageAccess($language)) {
287  ‪$availableLanguages[$language->getLanguageId()] = $language;
288  }
289  }
290 
291  return ‪$availableLanguages;
292  }
293 
300  public function ‪getErrorHandler(int ‪$statusCode): PageErrorHandlerInterface
301  {
302  $errorHandlerConfiguration = $this->errorHandlers[‪$statusCode] ?? $this->errorHandlers[0] ?? null;
303  switch ($errorHandlerConfiguration['errorHandler'] ?? null) {
305  return GeneralUtility::makeInstance(FluidPageErrorHandler::class, ‪$statusCode, $errorHandlerConfiguration);
307  return GeneralUtility::makeInstance(PageContentErrorHandler::class, ‪$statusCode, $errorHandlerConfiguration);
309  $handler = GeneralUtility::makeInstance($errorHandlerConfiguration['errorPhpClassFQCN'], ‪$statusCode, $errorHandlerConfiguration);
310  // Check if the interface is implemented
311  if (!($handler instanceof PageErrorHandlerInterface)) {
312  throw new InvalidPageErrorHandlerException('The configured error handler "' . (string)$errorHandlerConfiguration['errorPhpClassFQCN'] . '" for status code ' . ‪$statusCode . ' must implement the PageErrorHandlerInterface.', 1527432330);
313  }
314  return $handler;
315  }
316  throw new ‪PageErrorHandlerNotConfiguredException('No error handler given for the status code "' . ‪$statusCode . '".', 1522495914);
317  }
318 
322  public function ‪getConfiguration(): array
323  {
325  }
326 
327  public function ‪getSettings(): ‪SiteSettings
328  {
329  return $this->settings;
330  }
331 
335  public function ‪isTypoScriptRoot(): bool
336  {
337  return $this->‪sets !== [] || $this->‪typoscript !== null || $this->‪tsConfig !== null;
338  }
339 
340  public function ‪getTypoScript(): ?SiteTypoScript
341  {
342  return $this->typoscript;
343  }
344 
348  public function ‪getTSconfig(): ?‪SiteTSconfig
349  {
350  return $this->tsConfig;
351  }
352 
359  public function ‪getAttribute(string $attributeName)
360  {
361  if (isset($this->‪configuration[$attributeName])) {
362  return $this->‪configuration[$attributeName];
363  }
364  throw new \InvalidArgumentException(
365  'Attribute ' . $attributeName . ' does not exist on site ' . $this->‪identifier . '.',
366  1522495954
367  );
368  }
369 
374  protected function ‪sanitizeBaseUrl(string $base): string
375  {
376  // no protocol ("//") and the first part is no "/" (path), means that this is a domain like
377  // "www.domain.com/subpage", and we want to ensure that this one then gets a "no-scheme agnostic" part
378  if (!empty(‪$base) && !str_contains(‪$base, '//') && ‪$base[0] !== '/') {
379  // either a scheme is added, or no scheme but with domain, or a path which is not absolute
380  // make the base prefixed with a slash, so it is recognized as path, not as domain
381  // treat as path
382  if (!str_contains(‪$base, '.')) {
383  ‪$base = '/' . ‪$base;
384  } else {
385  // treat as domain name
386  ‪$base = '//' . ‪$base;
387  }
388  }
389  return ‪$base;
390  }
391 
395  public function ‪getRouter(‪Context $context = null): ‪RouterInterface
396  {
397  return GeneralUtility::makeInstance(PageRouter::class, $this, $context);
398  }
399 
400  protected function ‪getLanguageService(): LanguageService
401  {
402  return ‪$GLOBALS['LANG'];
403  }
404 }
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageService
‪getLanguageService()
Definition: Site.php:394
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Core\Site\Entity\Site\getTSconfig
‪getTSconfig()
Definition: Site.php:342
‪TYPO3\CMS\Core\Routing\RouterInterface
Definition: RouterInterface.php:28
‪TYPO3\CMS\Core\Site\Entity\Site\base
‪$this base
Definition: Site.php:112
‪TYPO3\CMS\Core\Site\Entity\SiteTSconfig
Definition: SiteTSconfig.php:24
‪TYPO3\CMS\Core\Site\Entity\Site\identifier
‪array< LanguageRef, $languages;protected array $sets;protected array $errorHandlers;protected SiteSettings $settings;protected ?SiteTypoScript $typoscript;protected ?SiteTSconfig $tsConfig;public function __construct(string $identifier, int $rootPageId, array $configuration, SiteSettings $settings=null, ?SiteTypoScript $typoscript=null, ?SiteTSconfig $tsConfig=null) { $this-> identifier
Definition: Site.php:88
‪$languages
‪$languages
Definition: updateIsoDatabase.php:104
‪TYPO3\CMS\Core\Site\Entity\Site\getAttribute
‪mixed getAttribute(string $attributeName)
Definition: Site.php:353
‪TYPO3\CMS\Core\Error\PageErrorHandler\FluidPageErrorHandler
Definition: FluidPageErrorHandler.php:32
‪TYPO3\CMS\Core\Routing\PageRouter
Definition: PageRouter.php:71
‪TYPO3\CMS\Core\Site\Entity\Site\typoscript
‪$this typoscript
Definition: Site.php:94
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_PAGE
‪const ERRORHANDLER_TYPE_PAGE
Definition: Site.php:43
‪TYPO3\CMS\Core\Site\Entity\Site\sets
‪$this sets
Definition: Site.php:114
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException
Definition: PageErrorHandlerNotConfiguredException.php:26
‪TYPO3\CMS\Core\Site\Entity\Site\resolveBaseWithVariants
‪foreach($configuration['languages'] as $languageConfiguration) foreach($configuration['errorHandling'] ??[] as $errorHandlingConfiguration) resolveBaseWithVariants(string $baseUrl, ?array $baseVariants)
Definition: Site.php:158
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:54
‪TYPO3\CMS\Core\Site\Entity\Site\configuration
‪$this configuration
Definition: Site.php:98
‪TYPO3\CMS\Core\Site\Entity\Site\settings
‪if($settings===null) $this settings
Definition: Site.php:93
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:30
‪TYPO3\CMS\Core\Error\PageErrorHandler\InvalidPageErrorHandlerException
Definition: InvalidPageErrorHandlerException.php:26
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:42
‪TYPO3\CMS\Core\Site\Entity\Site\getErrorHandler
‪getErrorHandler(int $statusCode)
Definition: Site.php:294
‪TYPO3\CMS\Core\Site\Entity\Site\tsConfig
‪$this tsConfig
Definition: Site.php:95
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:27
‪TYPO3\CMS\Core\Site\Entity\Site\getRootPageId
‪getRootPageId()
Definition: Site.php:201
‪TYPO3\CMS\Core\Site\Entity\Site\$identifier
‪string $identifier
Definition: Site.php:49
‪TYPO3\CMS\Redirects\Message\$statusCode
‪identifier readonly UriInterface readonly int $statusCode
Definition: RedirectWasHitMessage.php:34
‪TYPO3\CMS\Core\Site\Entity\Site\$rootPageId
‪int $rootPageId
Definition: Site.php:57
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_FLUID
‪const ERRORHANDLER_TYPE_FLUID
Definition: Site.php:44
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_PHP
‪const ERRORHANDLER_TYPE_PHP
Definition: Site.php:45
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler
Definition: PageContentErrorHandler.php:39
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:561
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Site\Entity\Site\getTypoScript
‪getTypoScript()
Definition: Site.php:334
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface
Definition: PageErrorHandlerInterface.php:29
‪TYPO3\CMS\Core\Site\Entity\Site\languages
‪array< LanguageRef, function getAllLanguages():array { return $this-> languages
Definition: Site.php:239
‪TYPO3\CMS\Core\Site\Entity\Site\isTypoScriptRoot
‪isTypoScriptRoot()
Definition: Site.php:329
‪TYPO3\CMS\Core\Site\Entity\SiteTypoScript
Definition: SiteTypoScript.php:21
‪TYPO3\CMS\Core\Site\Entity
Definition: NullSite.php:18
‪TYPO3\CMS\Core\Site\Entity\Site\$configuration
‪array $configuration
Definition: Site.php:62
‪TYPO3\CMS\Core\Site\Entity\Site\getConfiguration
‪getConfiguration()
Definition: Site.php:316
‪TYPO3\CMS\Core\ExpressionLanguage\Resolver
Definition: Resolver.php:32
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageById
‪getLanguageById(int $languageId)
Definition: Site.php:247
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\Site\Entity\SiteInterface\getLanguages
‪SiteLanguage[] getLanguages()
‪TYPO3\CMS\Core\Site\Entity\Site\getDefaultLanguage
‪getDefaultLanguage()
Definition: Site.php:258
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Site\Entity\Site\$availableLanguages
‪return $availableLanguages
Definition: Site.php:285
‪TYPO3\CMS\Core\Site\Entity\Site\$baseUrl
‪$baseUrl
Definition: Site.php:108
‪TYPO3\CMS\Core\Site\Entity\SiteInterface\getAvailableLanguages
‪SiteLanguage[] getAvailableLanguages(BackendUserAuthentication $user, bool $includeAllLanguagesFlag=false, int $pageId=null)
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Core\Site\Entity\Site\rootPageId
‪$this rootPageId
Definition: Site.php:89
‪TYPO3\CMS\Core\Site\Entity\SiteSettings
Definition: SiteSettings.php:29
‪TYPO3\CMS\Core\Site\Entity\Site\getSettings
‪getSettings()
Definition: Site.php:321
‪TYPO3\CMS\Core\Site\Entity\Site\$base
‪UriInterface $base
Definition: Site.php:53
‪TYPO3\CMS\Core\Site\Entity\Site\getIdentifier
‪getIdentifier()
Definition: Site.php:185
‪TYPO3\CMS\Core\Site\Entity\Site\getRouter
‪getRouter(Context $context=null)
Definition: Site.php:389
‪TYPO3\CMS\Core\Site\Entity\Site\getBase
‪getBase()
Definition: Site.php:193
‪TYPO3\CMS\Core\Site\Entity\Site\sanitizeBaseUrl
‪sanitizeBaseUrl(string $base)
Definition: Site.php:368