Skip to content

Instantly share code, notes, and snippets.

@josefglatz
Forked from bmack/LocalPageErrorHandler.php
Last active December 28, 2020 23:28
Show Gist options
  • Save josefglatz/67681aee236a090fd0f82edeee41a32e to your computer and use it in GitHub Desktop.
Save josefglatz/67681aee236a090fd0f82edeee41a32e to your computer and use it in GitHub Desktop.
Local Error Handler for TYPO3 (works also if your TYPO3 website is behind a basic auth)
errorHandling:
-
errorCode: '404'
errorContentSource: 't3://page?uid=316'
errorHandler: PHP
errorPhpClassFQCN: B13\AnyProject\PageErrorHandler\LocalPageErrorHandler
<?php
namespace B13\AnyProject\PageErrorHandler;
/*
* This file is part of a b13 extension.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*/
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\DependencyInjection\Container;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Error\PageErrorHandler\PageContentErrorHandler;
use TYPO3\CMS\Core\Exception\SiteNotFoundException;
use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Http\MiddlewareDispatcher;
use TYPO3\CMS\Core\Http\MiddlewareStackResolver;
use TYPO3\CMS\Core\LinkHandling\LinkService;
use TYPO3\CMS\Core\Routing\InvalidRouteArgumentsException;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\Http\RequestHandler;
/**
* Does not execute a CURL request for internal pages. Just set it up in an extension
* and refer to it in your Site Configuration (PHP Error Handler)
*/
class LocalPageErrorHandler extends PageContentErrorHandler
{
/**
* @param ServerRequestInterface $request
* @param string $message
* @param array $reasons
* @return ResponseInterface
* @throws \RuntimeException
*/
public function handlePageError(ServerRequestInterface $request, string $message, array $reasons = []): ResponseInterface
{
$targetDetails = $this->resolveDetails($this->errorHandlerConfiguration['errorContentSource']);
if ($targetDetails['type'] !== 'page' && $targetDetails['type'] !== 'url') {
throw new \InvalidArgumentException('PageContentErrorHandler can only handle TYPO3 urls of types "page" or "url"', 1522826609);
}
if ($targetDetails['type'] === 'page') {
$response = $this->buildSubRequest($request, (int)$targetDetails['pageuid']);
return $response->withStatus($this->statusCode);
}
if ($targetDetails['type'] !== 'url') {
return new HtmlResponse('Big fail', $this->statusCode);
}
$resolvedUrl = $targetDetails['url'];
try {
$content = null;
$report = [];
if ($resolvedUrl !== (string)$request->getUri()) {
$content = GeneralUtility::getUrl($resolvedUrl, 0, null, $report);
if ($content === false && ((int)$report['error'] === -1 || (int)$report['error'] > 200)) {
throw new \RuntimeException('Error handler could not fetch error page "' . $resolvedUrl . '", reason: ' . $report['message'], 1544172838);
}
}
} catch (InvalidRouteArgumentsException | SiteNotFoundException $e) {
$content = 'Invalid error handler configuration: ' . $this->errorHandlerConfiguration['errorContentSource'];
}
return new HtmlResponse($content, $this->statusCode);
}
/**
* @param ServerRequestInterface $request
* @param int $pageId
* @return ResponseInterface
* @throws SiteNotFoundException
* @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \TYPO3\CMS\Core\Exception
*/
protected function buildSubRequest(ServerRequestInterface $request, int $pageId): ResponseInterface
{
$site = $request->getAttribute('site', null);
if (!$site instanceof Site) {
$site = GeneralUtility::makeInstance(SiteFinder::class)->getSiteByPageId($pageId);
$request = $request->withAttribute('site', $site);
}
$request = $request->withQueryParams(['id' => $pageId]);
$dispatcher = $this->buildDispatcher();
return $dispatcher->handle($request);
}
/**
* @param string $typoLinkUrl
* @return array
*/
protected function resolveDetails(string $typoLinkUrl): array
{
$linkService = GeneralUtility::makeInstance(LinkService::class);
return $linkService->resolve($typoLinkUrl);
}
/**
* @return MiddlewareDispatcher
* @throws \TYPO3\CMS\Core\Cache\Exception\InvalidDataException
* @throws \TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException
* @throws \TYPO3\CMS\Core\Exception
*/
protected function buildDispatcher()
{
$requestHandler = GeneralUtility::makeInstance(RequestHandler::class);
$resolver = new MiddlewareStackResolver(
GeneralUtility::makeInstance(Container::class),
GeneralUtility::makeInstance(DependencyOrderingService::class),
GeneralUtility::makeInstance(CacheManager::class)->getCache('core')
);
$middlewares = $resolver->resolve('frontend');
return new MiddlewareDispatcher($requestHandler, $middlewares);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment