diff --git a/app/src/Bootstrap/AppManager.php b/app/src/Bootstrap/AppManager.php index feca7e9..b3440f0 100644 --- a/app/src/Bootstrap/AppManager.php +++ b/app/src/Bootstrap/AppManager.php @@ -51,6 +51,9 @@ class AppManager 'text/json' => '+1 hour', ])); + $errorMiddleware = $app->addErrorMiddleware(true, true, true); + $errorMiddleware->setDefaultErrorHandler(ErrorHandler::class); + return $app; } diff --git a/app/src/Bootstrap/ErrorHandler.php b/app/src/Bootstrap/ErrorHandler.php new file mode 100644 index 0000000..04d377e --- /dev/null +++ b/app/src/Bootstrap/ErrorHandler.php @@ -0,0 +1,63 @@ +view = $view; + } + + /** + * Invoke the ErrorHandler class. + * + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Throwable $exception + * @param bool $displayErrorDetails + * @param bool $logErrors + * @param bool $logErrorDetails + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function __invoke( + ServerRequestInterface $request, + Throwable $exception, + bool $displayErrorDetails, + bool $logErrors, + bool $logErrorDetails + ): ResponseInterface { + $response = (new Response)->withStatus(500); + + if (in_array('application/json', explode(',', $request->getHeaderLine('Accept')))) { + $response->getBody()->write(json_encode([ + 'error' => ['message' => self::DEFAULT_ERROR_MESSAGE] + ])); + + return $response->withHeader('Content-Type', 'application/json'); + } + + return $this->view->render($response, 'error.twig', [ + 'message' => self::DEFAULT_ERROR_MESSAGE, + 'subtext' => 'Enable debugging for additional information', + ]); + } +} diff --git a/app/views/error.twig b/app/views/error.twig index e17b61c..96051b3 100644 --- a/app/views/error.twig +++ b/app/views/error.twig @@ -4,10 +4,14 @@ {% block content %} {% include 'components/header.twig' %} -
+

{{ message | default('An unexpected error occured') }}

+ +

+ {{ subtext }} +

{% include 'components/footer.twig' %} diff --git a/tests/Bootstrap/ErrorHandlerTest.php b/tests/Bootstrap/ErrorHandlerTest.php new file mode 100644 index 0000000..73361c2 --- /dev/null +++ b/tests/Bootstrap/ErrorHandlerTest.php @@ -0,0 +1,57 @@ +container->call(TwigProvider::class); + $errorHandler = new ErrorHandler($this->container->get(Twig::class)); + + $response = $errorHandler( + $this->createMock(Request::class), + new Exception('Test exception; please ignore'), + true, + true, + true + ); + + $this->assertEquals(500, $response->getStatusCode()); + $this->assertEquals('text/html', finfo_buffer( + finfo_open(), (string) $response->getBody(), FILEINFO_MIME_TYPE + )); + } + + public function test_it_returns_an_error_for_a_json_request(): void + { + $this->container->call(TwigProvider::class); + $errorHandler = new ErrorHandler($this->container->get(Twig::class)); + + $request = $this->createMock(Request::class); + $request->expects($this->once())->method('getHeaderLine')->willReturn( + 'application/json' + ); + + $response = $errorHandler( + $request, + new Exception('Test exception; please ignore'), + true, + true, + true + ); + + $this->assertEquals(500, $response->getStatusCode()); + $this->assertEquals('application/json', $response->getHeaderLine('Content-Type')); + $this->assertEquals('An unexpected error occured', json_decode( + (string) $response->getBody() + )->error->message); + } +}