[BUGFIX] Check if language is accessible before uri generation
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Error / PageErrorHandler / PageContentErrorHandler.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Core\Error\PageErrorHandler;
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;
21 use TYPO3\CMS\Core\Exception\SiteNotFoundException;
22 use TYPO3\CMS\Core\Http\HtmlResponse;
23 use TYPO3\CMS\Core\LinkHandling\LinkService;
24 use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
25 use TYPO3\CMS\Core\Site\Entity\Site;
26 use TYPO3\CMS\Core\Site\Entity\SiteLanguage;
27 use TYPO3\CMS\Core\Site\SiteFinder;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30 /**
31 * Renders the content of a page to be displayed (also in relation to language etc)
32 * This is typically configured via the "Sites configuration" module in the backend.
33 */
34 class PageContentErrorHandler implements PageErrorHandlerInterface
35 {
36
37 /**
38 * @var int
39 */
40 protected $statusCode;
41
42 /**
43 * @var array
44 */
45 protected $errorHandlerConfiguration;
46
47 /**
48 * PageContentErrorHandler constructor.
49 * @param int $statusCode
50 * @param array $configuration
51 * @throws \InvalidArgumentException
52 */
53 public function __construct(int $statusCode, array $configuration)
54 {
55 $this->statusCode = $statusCode;
56 if (empty($configuration['errorContentSource'])) {
57 throw new \InvalidArgumentException('PageContentErrorHandler needs to have a proper link set.', 1522826413);
58 }
59 $this->errorHandlerConfiguration = $configuration;
60 }
61
62 /**
63 * @param ServerRequestInterface $request
64 * @param string $message
65 * @param array $reasons
66 * @return ResponseInterface
67 * @throws \RuntimeException
68 */
69 public function handlePageError(ServerRequestInterface $request, string $message, array $reasons = []): ResponseInterface
70 {
71 try {
72 $resolvedUrl = $this->resolveUrl($request, $this->errorHandlerConfiguration['errorContentSource']);
73 $content = null;
74 $report = [];
75 if ($resolvedUrl !== (string)$request->getUri()) {
76 $content = GeneralUtility::getUrl($resolvedUrl, 0, null, $report);
77 if ($content === false && ((int)$report['error'] === -1 || (int)$report['error'] > 200)) {
78 throw new \RuntimeException('Error handler could not fetch error page "' . $resolvedUrl . '", reason: ' . $report['message'], 1544172838);
79 }
80 }
81 } catch (InvalidRouteArgumentsException | SiteNotFoundException $e) {
82 $content = 'Invalid error handler configuration: ' . $this->errorHandlerConfiguration['errorContentSource'];
83 }
84 return new HtmlResponse($content, $this->statusCode);
85 }
86
87 /**
88 * Resolve the URL (currently only page and external URL are supported)
89 *
90 * @param ServerRequestInterface $request
91 * @param string $typoLinkUrl
92 * @return string
93 * @throws SiteNotFoundException
94 * @throws InvalidRouteArgumentsException
95 */
96 protected function resolveUrl(ServerRequestInterface $request, string $typoLinkUrl): string
97 {
98 $linkService = GeneralUtility::makeInstance(LinkService::class);
99 $urlParams = $linkService->resolve($typoLinkUrl);
100 if ($urlParams['type'] !== 'page' && $urlParams['type'] !== 'url') {
101 throw new \InvalidArgumentException('PageContentErrorHandler can only handle TYPO3 urls of types "page" or "url"', 1522826609);
102 }
103 if ($urlParams['type'] === 'url') {
104 return $urlParams['url'];
105 }
106
107 $site = $request->getAttribute('site', null);
108 if (!$site instanceof Site) {
109 $site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId((int)$urlParams['pageuid']);
110 }
111 $language = $request->getAttribute('language', null);
112 if (!$language instanceof SiteLanguage || !$language->isEnabled()) {
113 $language = $site->getDefaultLanguage();
114 }
115 // Build Url
116 return (string)$site->getRouter()->generateUri(
117 (int)$urlParams['pageuid'],
118 ['_language' => $language]
119 );
120 }
121 }