‪TYPO3CMS  9.5
Site.php
Go to the documentation of this file.
1 <?php
2 declare(strict_types = 1);
3 
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\UriInterface;
20 use Symfony\Component\ExpressionLanguage\SyntaxError;
34 
38 class ‪Site implements ‪SiteInterface
39 {
40  protected const ‪ERRORHANDLER_TYPE_PAGE = 'Page';
41  protected const ‪ERRORHANDLER_TYPE_FLUID = 'Fluid';
42  protected const ‪ERRORHANDLER_TYPE_PHP = 'PHP';
43 
47  protected ‪$identifier;
48 
52  protected ‪$base;
53 
57  protected ‪$rootPageId;
58 
63  protected ‪$configuration;
64 
68  protected ‪$languages;
69 
73  protected ‪$errorHandlers;
74 
82  public function ‪__construct(string ‪$identifier, int ‪$rootPageId, array ‪$configuration)
83  {
84  $this->identifier = ‪$identifier;
85  $this->rootPageId = ‪$rootPageId;
86  $this->configuration = ‪$configuration;
87  ‪$configuration['languages'] = !empty(‪$configuration['languages']) ? ‪$configuration['languages'] : [
88  0 => [
89  'languageId' => 0,
90  'title' => 'Default',
91  'navigationTitle' => '',
92  'typo3Language' => 'default',
93  'flag' => 'us',
94  'locale' => 'en_US.UTF-8',
95  'iso-639-1' => 'en',
96  'hreflang' => 'en-US',
97  'direction' => '',
98  ]
99  ];
100  $baseUrl = $this->‪resolveBaseWithVariants(
101  $configuration['base'] ?? '',
102  ‪$configuration['baseVariants'] ?? null
103  );
104  $this->base = new ‪Uri($this->‪sanitizeBaseUrl($baseUrl));
105 
106  foreach (‪$configuration['languages'] as $languageConfiguration) {
107  $languageUid = (int)$languageConfiguration['languageId'];
108  // site language has defined its own base, this is the case most of the time.
109  if (!empty($languageConfiguration['base'])) {
111  $languageConfiguration['base'],
112  $languageConfiguration['baseVariants'] ?? null
113  );
115  // no host given by the language-specific base, so lets prefix the main site base
116  if (‪$base->getScheme() === null && ‪$base->getHost() === '') {
117  ‪$base = rtrim((string)$this->base, '/') . '/' . ltrim((string)‪$base, '/');
118  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl($base));
119  }
120  } else {
121  // Language configuration does not have a base defined
122  // So the main site base is used (usually done for default languages)
123  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl(rtrim((string)$this->base, '/') . '/'));
124  }
125  if (!empty($languageConfiguration['flag'])) {
126  if ($languageConfiguration['flag'] === 'global') {
127  $languageConfiguration['flag'] = 'flags-multiple';
128  } elseif ($languageConfiguration['flag'] !== 'empty-empty') {
129  $languageConfiguration['flag'] = 'flags-' . $languageConfiguration['flag'];
130  }
131  }
132  $this->languages[$languageUid] = new ‪SiteLanguage(
133  $languageUid,
134  $languageConfiguration['locale'],
135  ‪$base,
136  $languageConfiguration
137  );
138  }
139  foreach (‪$configuration['errorHandling'] ?? [] as $errorHandlingConfiguration) {
140  $code = $errorHandlingConfiguration['errorCode'];
141  unset($errorHandlingConfiguration['errorCode']);
142  $this->errorHandlers[(int)$code] = $errorHandlingConfiguration;
143  }
144  }
145 
153  protected function ‪resolveBaseWithVariants(string $baseUrl, ?array $baseVariants): string
154  {
155  if (!empty($baseVariants)) {
156  $expressionLanguageResolver = GeneralUtility::makeInstance(
157  Resolver::class,
158  'site',
159  []
160  );
161  foreach ($baseVariants as $baseVariant) {
162  try {
163  if ($expressionLanguageResolver->evaluate($baseVariant['condition'])) {
164  $baseUrl = $baseVariant['base'];
165  break;
166  }
167  } catch (SyntaxError $e) {
168  // silently fail and do not evaluate
169  // no logger here, as Site is currently cached and serialized
170  }
171  }
172  }
173  return $baseUrl;
174  }
175 
182  public function ‪getIdentifier(): string
183  {
184  return ‪$this->identifier;
185  }
186 
192  public function ‪getBase(): UriInterface
193  {
194  return ‪$this->base;
195  }
196 
202  public function ‪getRootPageId(): int
203  {
204  return ‪$this->rootPageId;
205  }
206 
212  public function ‪getLanguages(): array
213  {
214  ‪$languages = [];
215  foreach ($this->languages as $languageId => $language) {
216  if ($language->enabled()) {
217  ‪$languages[$languageId] = $language;
218  }
219  }
220  return ‪$languages;
221  }
222 
228  public function ‪getAllLanguages(): array
229  {
230  return ‪$this->languages;
231  }
232 
240  public function ‪getLanguageById(int $languageId): ‪SiteLanguage
241  {
242  if (isset($this->languages[$languageId])) {
243  return $this->languages[$languageId];
244  }
245  throw new \InvalidArgumentException(
246  'Language ' . $languageId . ' does not exist on site ' . $this->identifier . '.',
247  1522960188
248  );
249  }
250 
254  public function ‪getDefaultLanguage(): ‪SiteLanguage
255  {
256  return reset($this->languages);
257  }
258 
262  public function ‪getAvailableLanguages(‪BackendUserAuthentication $user, bool $includeAllLanguagesFlag = false, int $pageId = null): array
263  {
264  $availableLanguages = [];
265 
266  // Check if we need to add language "-1"
267  if ($includeAllLanguagesFlag && $user->‪checkLanguageAccess(-1)) {
268  $availableLanguages[-1] = new ‪SiteLanguage(-1, '', $this->‪getBase(), [
269  'title' => $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages'),
270  'flag' => 'flags-multiple'
271  ]);
272  }
273 
274  // Do not add the ones that are not allowed by the user
275  foreach ($this->languages as $language) {
276  if ($user->‪checkLanguageAccess($language->getLanguageId())) {
277  $availableLanguages[$language->getLanguageId()] = $language;
278  }
279  }
280 
281  return $availableLanguages;
282  }
283 
292  public function ‪getErrorHandler(int $statusCode): PageErrorHandlerInterface
293  {
294  $errorHandlerConfiguration = $this->errorHandlers[$statusCode] ?? null;
295  switch ($errorHandlerConfiguration['errorHandler'] ?? null) {
297  return GeneralUtility::makeInstance(FluidPageErrorHandler::class, $statusCode, $errorHandlerConfiguration);
299  return GeneralUtility::makeInstance(PageContentErrorHandler::class, $statusCode, $errorHandlerConfiguration);
301  $handler = GeneralUtility::makeInstance($errorHandlerConfiguration['errorPhpClassFQCN'], $statusCode, $errorHandlerConfiguration);
302  // Check if the interface is implemented
303  if (!($handler instanceof PageErrorHandlerInterface)) {
304  throw new InvalidPageErrorHandlerException('The configured error handler "' . (string)$errorHandlerConfiguration['errorPhpClassFQCN'] . '" for status code ' . $statusCode . ' must implement the PageErrorHandlerInterface.', 1527432330);
305  }
306  return $handler;
307  }
308  throw new PageErrorHandlerNotConfiguredException('No error handler given for the status code "' . $statusCode . '".', 1522495914);
309  }
310 
316  public function ‪getConfiguration(): array
317  {
319  }
320 
328  public function ‪getAttribute(string $attributeName)
329  {
330  if (isset($this->configuration[$attributeName])) {
331  return $this->configuration[$attributeName];
332  }
333  throw new \InvalidArgumentException(
334  'Attribute ' . $attributeName . ' does not exist on site ' . $this->identifier . '.',
335  1522495954
336  );
337  }
338 
346  protected function ‪sanitizeBaseUrl(string ‪$base): string
347  {
348  // no protocol ("//") and the first part is no "/" (path), means that this is a domain like
349  // "www.domain.com/subpage", and we want to ensure that this one then gets a "no-scheme agnostic" part
350  if (!empty(‪$base) && strpos(‪$base, '//') === false && ‪$base[0] !== '/') {
351  // either a scheme is added, or no scheme but with domain, or a path which is not absolute
352  // make the base prefixed with a slash, so it is recognized as path, not as domain
353  // treat as path
354  if (strpos(‪$base, '.') === false) {
355  ‪$base = '/' . ‪$base;
356  } else {
357  // treat as domain name
358  ‪$base = '//' . ‪$base;
359  }
360  }
361  return ‪$base;
362  }
363 
370  public function ‪getRouter(Context $context = null): RouterInterface
371  {
372  return GeneralUtility::makeInstance(PageRouter::class, $this, $context);
373  }
374 
379  protected function ‪getLanguageService(): ‪LanguageService
380  {
381  return ‪$GLOBALS['LANG'];
382  }
383 }
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:25
‪TYPO3\CMS\Core\Routing\RouterInterface
Definition: RouterInterface.php:27
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageById
‪SiteLanguage getLanguageById(int $languageId)
Definition: Site.php:234
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageService
‪LanguageService getLanguageService()
Definition: Site.php:373
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguages
‪SiteLanguage[] getLanguages()
Definition: Site.php:206
‪TYPO3\CMS\Core\Site\Entity\Site\getRouter
‪RouterInterface getRouter(Context $context=null)
Definition: Site.php:364
‪TYPO3\CMS\Core\Site\Entity\Site\getAttribute
‪mixed getAttribute(string $attributeName)
Definition: Site.php:322
‪TYPO3\CMS\Core\Site\Entity\Site\getErrorHandler
‪PageErrorHandlerInterface getErrorHandler(int $statusCode)
Definition: Site.php:286
‪TYPO3\CMS\Core\Error\PageErrorHandler\FluidPageErrorHandler
Definition: FluidPageErrorHandler.php:31
‪TYPO3\CMS\Core\Routing\PageRouter
Definition: PageRouter.php:75
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_PAGE
‪const ERRORHANDLER_TYPE_PAGE
Definition: Site.php:40
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException
Definition: PageErrorHandlerNotConfiguredException.php:26
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:49
‪TYPO3\CMS\Core\Site\Entity\Site\getConfiguration
‪array getConfiguration()
Definition: Site.php:310
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:27
‪TYPO3\CMS\Core\Error\PageErrorHandler\InvalidPageErrorHandlerException
Definition: InvalidPageErrorHandlerException.php:26
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Core\Site\Entity\Site\getAvailableLanguages
‪getAvailableLanguages(BackendUserAuthentication $user, bool $includeAllLanguagesFlag=false, int $pageId=null)
Definition: Site.php:256
‪TYPO3\CMS\Core\Site\Entity\Site\getIdentifier
‪string getIdentifier()
Definition: Site.php:176
‪TYPO3\CMS\Core\Site\Entity\Site\$identifier
‪string $identifier
Definition: Site.php:46
‪TYPO3\CMS\Core\Site\Entity\Site\$rootPageId
‪int $rootPageId
Definition: Site.php:54
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_FLUID
‪const ERRORHANDLER_TYPE_FLUID
Definition: Site.php:41
‪TYPO3\CMS\Core\Site\Entity\Site\ERRORHANDLER_TYPE_PHP
‪const ERRORHANDLER_TYPE_PHP
Definition: Site.php:42
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler
Definition: PageContentErrorHandler.php:38
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:733
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:45
‪TYPO3\CMS\Core\Site\Entity\Site\$languages
‪SiteLanguage[] $languages
Definition: Site.php:63
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface
Definition: PageErrorHandlerInterface.php:28
‪TYPO3\CMS\Core\Site\Entity\Site\getBase
‪UriInterface getBase()
Definition: Site.php:186
‪TYPO3\CMS\Core\Site\Entity\Site\getAllLanguages
‪SiteLanguage[] getAllLanguages()
Definition: Site.php:222
‪TYPO3\CMS\Core\Site\Entity\Site\sanitizeBaseUrl
‪string sanitizeBaseUrl(string $base)
Definition: Site.php:340
‪TYPO3\CMS\Core\Site\Entity
Definition: NullSite.php:4
‪TYPO3\CMS\Core\Site\Entity\Site\$configuration
‪array $configuration
Definition: Site.php:59
‪TYPO3\CMS\Core\ExpressionLanguage\Resolver
Definition: Resolver.php:25
‪TYPO3\CMS\Core\Site\Entity\Site\getRootPageId
‪int getRootPageId()
Definition: Site.php:196
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Site\Entity\Site\getDefaultLanguage
‪getDefaultLanguage()
Definition: Site.php:248
‪TYPO3\CMS\Core\Site\Entity\Site\resolveBaseWithVariants
‪string resolveBaseWithVariants(string $baseUrl, ?array $baseVariants)
Definition: Site.php:147
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:29
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Site\Entity\Site\$base
‪UriInterface $base
Definition: Site.php:50
‪TYPO3\CMS\Core\Site\Entity\Site\$errorHandlers
‪array $errorHandlers
Definition: Site.php:67
‪TYPO3\CMS\Core\Site\Entity\Site\__construct
‪__construct(string $identifier, int $rootPageId, array $configuration)
Definition: Site.php:76