‪TYPO3CMS  9.5
PageContentErrorHandler.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\ResponseInterface;
20 use Psr\Http\Message\ServerRequestInterface;
32 
38 {
39 
43  protected ‪$statusCode;
44 
49 
53  protected ‪$pageUid = 0;
54 
61  public function ‪__construct(int ‪$statusCode, array $configuration)
62  {
63  $this->statusCode = ‪$statusCode;
64  if (empty($configuration['errorContentSource'])) {
65  throw new \InvalidArgumentException('PageContentErrorHandler needs to have a proper link set.', 1522826413);
66  }
67  $this->errorHandlerConfiguration = $configuration;
68  }
69 
78  public function ‪handlePageError(ServerRequestInterface $request, string $message, array $reasons = []): ResponseInterface
79  {
80  try {
81  $resolvedUrl = $this->‪resolveUrl($request, $this->errorHandlerConfiguration['errorContentSource']);
82 
83  $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('cache_pages');
84  $cacheIdentifier = 'errorPage_' . md5($resolvedUrl);
85  $cacheContent = $cache->get($cacheIdentifier);
86 
87  if (!$cacheContent && $resolvedUrl !== (string)$request->getUri()) {
88  try {
89  $subResponse = GeneralUtility::makeInstance(RequestFactory::class)
90  ->request($resolvedUrl, 'GET', $this->‪getSubRequestOptions());
91  } catch (\‪Exception $e) {
92  throw new \RuntimeException('Error handler could not fetch error page "' . $resolvedUrl . '", reason: ' . $e->getMessage(), 1544172838);
93  }
94  if ($subResponse->getStatusCode() >= 300) {
95  throw new \RuntimeException('Error handler could not fetch error page "' . $resolvedUrl . '", status code: ' . $subResponse->getStatusCode(), 1544172839);
96  }
97 
98  $body = $subResponse->getBody()->getContents();
99  $contentType = $subResponse->getHeader('Content-Type');
100 
101  // Cache body and content-type if sub-response returned a HTTP status 200
102  if ($subResponse->getStatusCode() === 200) {
103  $cacheTags = ['errorPage'];
104  if ($this->pageUid > 0) {
105  // Cache Tag "pageId_" ensures, cache is purged when content of 404 page changes
106  $cacheTags[] = 'pageId_' . ‪$this->pageUid;
107  }
108  $cacheContent = [
109  'body' => $body,
110  'headers' => ['Content-Type' => $contentType],
111  ];
112  $cache->set($cacheIdentifier, $cacheContent, $cacheTags);
113  }
114  }
115  if ($cacheContent && $cacheContent['body'] && $cacheContent['headers']) {
116  // We use a HtmlResponse here, since no Stream is available for cached response content
117  return new ‪HtmlResponse($cacheContent['body'], $this->statusCode, $cacheContent['headers']);
118  }
120  $content = 'Invalid error handler configuration: ' . $this->errorHandlerConfiguration['errorContentSource'];
121  }
122  return new ‪HtmlResponse($content, $this->statusCode);
123  }
124 
130  protected function ‪getSubRequestOptions(): array
131  {
132  $options = [];
133  if ((int)‪$GLOBALS['TYPO3_CONF_VARS']['HTTP']['timeout'] === 0) {
134  $options = [
135  'timeout' => 30
136  ];
137  }
138  return $options;
139  }
140 
150  protected function ‪resolveUrl(ServerRequestInterface $request, string $typoLinkUrl): string
151  {
152  $linkService = GeneralUtility::makeInstance(LinkService::class);
153  $urlParams = $linkService->resolve($typoLinkUrl);
154  if ($urlParams['type'] !== 'page' && $urlParams['type'] !== 'url') {
155  throw new \InvalidArgumentException('PageContentErrorHandler can only handle TYPO3 urls of types "page" or "url"', 1522826609);
156  }
157  if ($urlParams['type'] === 'url') {
158  return $urlParams['url'];
159  }
160 
161  $this->pageUid = (int)$urlParams['pageuid'];
162 
163  // Get the site related to the configured error page
164  $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($this->pageUid);
165  // Fall back to current request for the site
166  if (!$site instanceof ‪Site) {
167  $site = $request->getAttribute('site', null);
168  }
170  $requestLanguage = $request->getAttribute('language', null);
171  // Try to get the current request language from the site that was found above
172  if ($requestLanguage instanceof ‪SiteLanguage && $requestLanguage->‪isEnabled()) {
173  try {
174  $language = $site->getLanguageById($requestLanguage->getLanguageId());
175  } catch (\InvalidArgumentException $e) {
176  $language = $site->getDefaultLanguage();
177  }
178  } else {
179  $language = $site->getDefaultLanguage();
180  }
181 
182  // Build Url
183  $uri = $site->getRouter()->generateUri(
184  (int)$urlParams['pageuid'],
185  ['_language' => $language]
186  );
187 
188  // Fallback to the current URL if the site is not having a proper scheme and host
189  $currentUri = $request->getUri();
190  if (empty($uri->getScheme())) {
191  $uri = $uri->withScheme($currentUri->getScheme());
192  }
193  if (empty($uri->getUserInfo())) {
194  $uri = $uri->withUserInfo($currentUri->getUserInfo());
195  }
196  if (empty($uri->getHost())) {
197  $uri = $uri->withHost($currentUri->getHost());
198  }
199  if ($uri->getPort() === null) {
200  $uri = $uri->withPort($currentUri->getPort());
201  }
202 
203  return (string)$uri;
204  }
205 }
‪TYPO3\CMS\Core\Exception\SiteNotFoundException
Definition: SiteNotFoundException.php:25
‪TYPO3\CMS\Core\Site\SiteFinder
Definition: SiteFinder.php:31
‪TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
Definition: NoSuchCacheException.php:21
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\$pageUid
‪int $pageUid
Definition: PageContentErrorHandler.php:50
‪TYPO3\CMS\Core\Site\Entity\Site
Definition: Site.php:39
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage
Definition: SiteLanguage.php:25
‪TYPO3\CMS\Core\Cache\CacheManager
Definition: CacheManager.php:34
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\getSubRequestOptions
‪array int[] getSubRequestOptions()
Definition: PageContentErrorHandler.php:127
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler
Definition: PageContentErrorHandler.php:38
‪TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException
Definition: InvalidRouteArgumentsException.php:23
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\$errorHandlerConfiguration
‪array $errorHandlerConfiguration
Definition: PageContentErrorHandler.php:46
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\__construct
‪__construct(int $statusCode, array $configuration)
Definition: PageContentErrorHandler.php:58
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:21
‪TYPO3\CMS\Core\Http\RequestFactory
Definition: RequestFactory.php:27
‪TYPO3\CMS\Core\Site\Entity\SiteLanguage\isEnabled
‪bool isEnabled()
Definition: SiteLanguage.php:286
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageErrorHandlerInterface
Definition: PageErrorHandlerInterface.php:28
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\$statusCode
‪int $statusCode
Definition: PageContentErrorHandler.php:42
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\handlePageError
‪ResponseInterface handlePageError(ServerRequestInterface $request, string $message, array $reasons=[])
Definition: PageContentErrorHandler.php:75
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Error\PageErrorHandler
Definition: FluidPageErrorHandler.php:4
‪TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler\resolveUrl
‪string resolveUrl(ServerRequestInterface $request, string $typoLinkUrl)
Definition: PageContentErrorHandler.php:147
‪TYPO3\CMS\Core\Http\HtmlResponse
Definition: HtmlResponse.php:25