renderer = $renderer; } /** * Returns an array of events this subscriber will listen to. * * @return array */ public static function getSubscribedEvents(): array { return [ ApplicationEvents::ERROR => 'handleWebError', ConsoleEvents::APPLICATION_ERROR => 'handleConsoleError', ]; } /** * Handle console application errors. * * @param ConsoleApplicationErrorEvent $event Event object * * @return void */ public function handleConsoleError(ConsoleApplicationErrorEvent $event): void { $this->logError($event->getError()); } /** * Handle web application errors. * * @param ApplicationErrorEvent $event Event object * * @return void */ public function handleWebError(ApplicationErrorEvent $event): void { /** @var SiteApplication $app */ $app = $event->getApplication(); switch (true) { case $event->getError() instanceof MethodNotAllowedException : // Log the error for reference $this->logger->error( sprintf('Route `%s` not supported by method `%s`', $app->get('uri.route'), $app->input->getMethod()), ['exception' => $event->getError()] ); $this->prepareResponse($event); $app->setHeader('Allow', implode(', ', $event->getError()->getAllowedMethods())); break; case $event->getError() instanceof RouteNotFoundException : // Log the error for reference $this->logger->error( sprintf('Route `%s` not found', $app->get('uri.route')), ['exception' => $event->getError()] ); $this->prepareResponse($event); break; default: $this->logError($event->getError()); $this->prepareResponse($event); break; } } /** * Log the error. * * @param \Throwable $throwable The error being processed * * @return void */ private function logError(\Throwable $throwable): void { $this->logger->error( sprintf('Uncaught Throwable of type %s caught.', \get_class($throwable)), ['exception' => $throwable] ); } /** * Prepare the response for the event * * @param ApplicationErrorEvent $event Event object * * @return void */ private function prepareResponse(ApplicationErrorEvent $event): void { /** @var SiteApplication $app */ $app = $event->getApplication(); $app->allowCache(false); switch (true) { case $app->input->getString('_format', 'html') === 'json' : case $app->mimeType === 'application/json' : case $app->getResponse() instanceof JsonResponse : $data = [ 'code' => $event->getError()->getCode(), 'message' => $event->getError()->getMessage(), 'error' => true, ]; $response = new JsonResponse($data); break; default : $response = new HtmlResponse( $this->renderer->render('exception.twig', ['exception' => $event->getError()]) ); break; } switch ($event->getError()->getCode()) { case 404 : $response = $response->withStatus(404); break; case 405 : $response = $response->withStatus(405); break; case 500 : default : $response = $response->withStatus(500); break; } $app->setResponse($response); } }