‪TYPO3CMS  11.5
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 $errorHandlers;
77 
85  public function __construct(string ‪$identifier, int ‪$rootPageId, array ‪$configuration)
86  {
90  $configuration['languages'] = !empty(‪$configuration['languages']) ? ‪$configuration['languages'] : [
91  0 => [
92  'languageId' => 0,
93  'title' => 'Default',
94  'navigationTitle' => '',
95  'typo3Language' => 'default',
96  'flag' => 'us',
97  'locale' => 'en_US.UTF-8',
98  'iso-639-1' => 'en',
99  'hreflang' => 'en-US',
100  'direction' => '',
101  ],
102  ];
104  $configuration['base'] ?? '',
105  ‪$configuration['baseVariants'] ?? null
106  );
107  $this->‪base = new ‪Uri($this->‪sanitizeBaseUrl(‪$baseUrl));
108 
109  foreach ($configuration['languages'] as $languageConfiguration) {
110  $languageUid = (int)$languageConfiguration['languageId'];
111  // site language has defined its own base, this is the case most of the time.
112  if (!empty($languageConfiguration['base'])) {
114  $languageConfiguration['base'],
115  $languageConfiguration['baseVariants'] ?? null
116  );
117  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl($base));
118  // no host given by the language-specific base, so lets prefix the main site base
119  if (‪$base->getScheme() === '' && ‪$base->getHost() === '') {
120  ‪$base = rtrim((string)$this->‪base, '/') . '/' . ltrim((string)‪$base, '/');
121  ‪$base = new ‪Uri($this->‪sanitizeBaseUrl($base));
122  }
123  } else {
124  // Language configuration does not have a base defined
125  // So the main site base is used (usually done for default languages)
126  ‪$base = new Uri($this->‪sanitizeBaseUrl(rtrim((string)$this->‪base, '/') . '/'));
127  }
128  if (!empty($languageConfiguration['flag'])) {
129  if ($languageConfiguration['flag'] === 'global') {
130  $languageConfiguration['flag'] = 'flags-multiple';
131  } elseif ($languageConfiguration['flag'] !== 'empty-empty') {
132  $languageConfiguration['flag'] = 'flags-' . $languageConfiguration['flag'];
133  }
134  }
135  $this->‪languages[$languageUid] = new SiteLanguage(
136  $languageUid,
137  $languageConfiguration['locale'],
138  ‪$base,
139  $languageConfiguration
140  );
141  }
142  foreach (‪$configuration['errorHandling'] ?? [] as $errorHandlingConfiguration) {
143  $code = $errorHandlingConfiguration['errorCode'];
144  unset($errorHandlingConfiguration['errorCode']);
145  $this->errorHandlers[(int)$code] = $errorHandlingConfiguration;
146  }
147  }
148 
156  protected function ‪resolveBaseWithVariants(string ‪$baseUrl, ?array $baseVariants): string
157  {
158  if (!empty($baseVariants)) {
159  $expressionLanguageResolver = GeneralUtility::makeInstance(
160  Resolver::class,
161  'site',
162  []
163  );
164  foreach ($baseVariants as $baseVariant) {
165  try {
166  if ($expressionLanguageResolver->evaluate($baseVariant['condition'])) {
167  ‪$baseUrl = $baseVariant['base'];
168  break;
169  }
170  } catch (SyntaxError $e) {
171  // silently fail and do not evaluate
172  // no logger here, as Site is currently cached and serialized
173  }
174  }
175  }
176  return ‪$baseUrl;
177  }
178 
185  public function ‪getIdentifier(): string
186  {
187  return ‪$this->identifier;
188  }
189 
195  public function ‪getBase(): UriInterface
196  {
197  return ‪$this->base;
198  }
199 
205  public function ‪getRootPageId(): int
206  {
207  return ‪$this->rootPageId;
208  }
209 
215  public function ‪getLanguages(): array
216  {
217  $languages = [];
218  foreach ($this->‪languages as $languageId => $language) {
219  if ($language->enabled()) {
220  $languages[$languageId] = $language;
221  }
222  }
223  return $languages;
224  }
225 
231  public function getAllLanguages(): array
232  {
233  return $this->languages;
234  }
235 
243  public function ‪getLanguageById(int $languageId): SiteLanguage
244  {
245  if (isset($this->‪languages[$languageId])) {
246  return $this->‪languages[$languageId];
247  }
248  throw new \InvalidArgumentException(
249  'Language ' . $languageId . ' does not exist on site ' . $this->‪identifier . '.',
250  1522960188
251  );
252  }
253 
257  public function ‪getDefaultLanguage(): ‪SiteLanguage
258  {
259  return reset($this->‪languages);
260  }
261 
266  public function ‪getAvailableLanguages(BackendUserAuthentication $user, bool $includeAllLanguagesFlag = false, int $pageId = null): array
267  {
269 
270  // Check if we need to add language "-1"
271  if ($includeAllLanguagesFlag && $user->checkLanguageAccess(-1)) {
272  ‪$availableLanguages[-1] = new ‪SiteLanguage(-1, '', $this->‪getBase(), [
273  'title' => $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_mod_web_list.xlf:multipleLanguages'),
274  'flag' => 'flags-multiple',
275  ]);
276  }
277 
278  // Do not add the ones that are not allowed by the user
279  foreach ($this->‪languages as $language) {
280  if ($user->checkLanguageAccess($language->getLanguageId())) {
281  ‪$availableLanguages[$language->getLanguageId()] = $language;
282  }
283  }
284 
285  return ‪$availableLanguages;
286  }
287 
296  public function ‪getErrorHandler(int $statusCode): PageErrorHandlerInterface
297  {
298  $errorHandlerConfiguration = $this->errorHandlers[$statusCode] ?? null;
299  switch ($errorHandlerConfiguration['errorHandler'] ?? null) {
301  return GeneralUtility::makeInstance(FluidPageErrorHandler::class, $statusCode, $errorHandlerConfiguration);
303  return GeneralUtility::makeInstance(PageContentErrorHandler::class, $statusCode, $errorHandlerConfiguration);
305  $handler = GeneralUtility::makeInstance($errorHandlerConfiguration['errorPhpClassFQCN'], $statusCode, $errorHandlerConfiguration);
306  // Check if the interface is implemented
307  if (!($handler instanceof PageErrorHandlerInterface)) {
308  throw new InvalidPageErrorHandlerException('The configured error handler "' . (string)$errorHandlerConfiguration['errorPhpClassFQCN'] . '" for status code ' . $statusCode . ' must implement the PageErrorHandlerInterface.', 1527432330);
309  }
310  return $handler;
311  }
312  throw new PageErrorHandlerNotConfiguredException('No error handler given for the status code "' . $statusCode . '".', 1522495914);
313  }
314 
320  public function ‪getConfiguration(): array
321  {
323  }
324 
332  public function ‪getAttribute(string $attributeName)
333  {
334  if (isset($this->‪configuration[$attributeName])) {
335  return $this->‪configuration[$attributeName];
336  }
337  throw new \InvalidArgumentException(
338  'Attribute ' . $attributeName . ' does not exist on site ' . $this->‪identifier . '.',
339  1522495954
340  );
341  }
342 
350  protected function ‪sanitizeBaseUrl(string $base): string
351  {
352  // no protocol ("//") and the first part is no "/" (path), means that this is a domain like
353  // "www.domain.com/subpage", and we want to ensure that this one then gets a "no-scheme agnostic" part
354  if (!empty(‪$base) && !str_contains(‪$base, '//') && ‪$base[0] !== '/') {
355  // either a scheme is added, or no scheme but with domain, or a path which is not absolute
356  // make the base prefixed with a slash, so it is recognized as path, not as domain
357  // treat as path
358  if (!str_contains(‪$base, '.')) {
359  ‪$base = '/' . ‪$base;
360  } else {
361  // treat as domain name
362  ‪$base = '//' . ‪$base;
363  }
364  }
365  return ‪$base;
366  }
367 
374  public function ‪getRouter(Context $context = null): RouterInterface
375  {
376  return GeneralUtility::makeInstance(PageRouter::class, $this, $context);
377  }
378 
383  protected function ‪getLanguageService(): ‪LanguageService
384  {
385  return ‪$GLOBALS['LANG'];
386  }
387 }
‪TYPO3\CMS\Core\Site\Entity\SiteInterface
Definition: SiteInterface.php:26
‪TYPO3\CMS\Core\Routing\RouterInterface
Definition: RouterInterface.php:28
‪TYPO3\CMS\Core\Site\Entity\Site\base
‪$this base
Definition: Site.php:101
‪TYPO3\CMS\Core\Site\Entity\Site\getLanguageService
‪LanguageService getLanguageService()
Definition: Site.php:377
‪TYPO3\CMS\Core\Site\Entity\Site\resolveBaseWithVariants
‪foreach($configuration['languages'] as $languageConfiguration) foreach($configuration['errorHandling'] ??[] as $errorHandlingConfiguration) string resolveBaseWithVariants(string $baseUrl, ?array $baseVariants)
Definition: Site.php:150
‪TYPO3\CMS\Core\Site\Entity\Site\getRouter
‪RouterInterface getRouter(Context $context=null)
Definition: Site.php:368
‪TYPO3\CMS\Core\Site\Entity\Site\getAttribute
‪mixed getAttribute(string $attributeName)
Definition: Site.php:326
‪TYPO3\CMS\Core\Site\Entity\Site\getErrorHandler
‪PageErrorHandlerInterface getErrorHandler(int $statusCode)
Definition: Site.php:290
‪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\ERRORHANDLER_TYPE_PAGE
‪const ERRORHANDLER_TYPE_PAGE
Definition: Site.php:43
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerNotConfiguredException
Definition: PageErrorHandlerNotConfiguredException.php:26
‪TYPO3\CMS\Core\Context\Context
Definition: Context.php:53
‪TYPO3\CMS\Core\Site\Entity\Site\configuration
‪$this configuration
Definition: Site.php:83
‪TYPO3\CMS\Core\Site\Entity\Site\getConfiguration
‪array getConfiguration()
Definition: Site.php:314
‪TYPO3\CMS\Core\Http\Uri
Definition: Uri.php:29
‪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\SiteLanguage
Definition: SiteLanguage.php:26
‪TYPO3\CMS\Core\Site\Entity\Site\getIdentifier
‪string getIdentifier()
Definition: Site.php:179
‪TYPO3\CMS\Core\Site\Entity\Site\$identifier
‪string $identifier
Definition: Site.php:49
‪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\Site\Entity\SiteInterface\getLanguageById
‪SiteLanguage getLanguageById(int $languageId)
‪TYPO3\CMS\Core\Site\Entity\Site\languages
‪array< LanguageRef, function getLanguages():array { $languages=[];foreach( $this->languages as $languageId=> $language) { if( $language->enabled()) { $languages[ $languageId]=$language;} } return $languages;} public array< LanguageRef, function getAllLanguages():array { return $this->languages;} public SiteLanguage function getLanguageById(int $languageId):SiteLanguage { if(isset( $this->languages[ $languageId])) { return $this-> languages[$languageId]
Definition: Site.php:240
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler
Definition: PageContentErrorHandler.php:51
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication\checkLanguageAccess
‪bool checkLanguageAccess($langValue)
Definition: BackendUserAuthentication.php:670
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface
Definition: PageErrorHandlerInterface.php:29
‪TYPO3\CMS\Core\Site\Entity\Site\getBase
‪UriInterface getBase()
Definition: Site.php:189
‪TYPO3\CMS\Core\Site\Entity\Site\sanitizeBaseUrl
‪string sanitizeBaseUrl(string $base)
Definition: Site.php:344
‪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\ExpressionLanguage\Resolver
Definition: Resolver.php:28
‪TYPO3\CMS\Core\Site\Entity\Site\getRootPageId
‪int getRootPageId()
Definition: Site.php:199
‪$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:251
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:42
‪TYPO3\CMS\Core\Site\Entity\Site\$availableLanguages
‪return $availableLanguages
Definition: Site.php:279
‪TYPO3\CMS\Core\Site\Entity\Site\$baseUrl
‪$baseUrl
Definition: Site.php:97
‪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:50
‪TYPO3\CMS\Core\Site\Entity\Site\rootPageId
‪$this rootPageId
Definition: Site.php:82
‪TYPO3\CMS\Core\Site\Entity\Site\$base
‪UriInterface $base
Definition: Site.php:53
‪TYPO3\CMS\Core\Site\Entity\Site\identifier
‪array< LanguageRef, $languages;protected array $errorHandlers;public function __construct(string $identifier, int $rootPageId, array $configuration) { $this-> identifier
Definition: Site.php:81