displayErrorDetails = (bool)$displayErrorDetails; } /** * Invoke error handler * * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object * @param Exception $exception The caught Exception object * * @return ResponseInterface */ public function __invoke(ServerRequestInterface $request, ResponseInterface $response, Exception $exception) { $contentType = $this->determineContentType($request); switch ($contentType) { case 'application/json': $output = $this->renderJsonErrorMessage($exception); break; case 'text/xml': case 'application/xml': $output = $this->renderXmlErrorMessage($exception); break; case 'text/html': $output = $this->renderHtmlErrorMessage($exception); break; } $body = new Body(fopen('php://temp', 'r+')); $body->write($output); return $response ->withStatus(500) ->withHeader('Content-type', $contentType) ->withBody($body); } /** * Render HTML error page * * @param Exception $exception * @return string */ protected function renderHtmlErrorMessage(Exception $exception) { $title = 'Slim Application Error'; if ($this->displayErrorDetails) { $html = '

The application could not run because of the following error:

'; $html .= '

Details

'; $html .= $this->renderHtmlException($exception); while ($exception = $exception->getPrevious()) { $html .= '

Previous exception

'; $html .= $this->renderHtmlException($exception); } } else { $html = '

A website error has occurred. Sorry for the temporary inconvenience.

'; } $output = sprintf( "" . "%s

%s

%s", $title, $title, $html ); return $output; } /** * Render exception as HTML. * * @param Exception $exception * * @return string */ protected function renderHtmlException(Exception $exception) { $html = sprintf('
Type: %s
', get_class($exception)); if (($code = $exception->getCode())) { $html .= sprintf('
Code: %s
', $code); } if (($message = $exception->getMessage())) { $html .= sprintf('
Message: %s
', htmlentities($message)); } if (($file = $exception->getFile())) { $html .= sprintf('
File: %s
', $file); } if (($line = $exception->getLine())) { $html .= sprintf('
Line: %s
', $line); } if (($trace = $exception->getTraceAsString())) { $html .= '

Trace

'; $html .= sprintf('
%s
', htmlentities($trace)); } return $html; } /** * Render JSON error * * @param Exception $exception * @return string */ protected function renderJsonErrorMessage(Exception $exception) { $error = [ 'message' => 'Slim Application Error', ]; if ($this->displayErrorDetails) { $error['exception'] = []; do { $error['exception'][] = [ 'type' => get_class($exception), 'code' => $exception->getCode(), 'message' => $exception->getMessage(), 'file' => $exception->getFile(), 'line' => $exception->getLine(), 'trace' => explode("\n", $exception->getTraceAsString()), ]; } while ($exception = $exception->getPrevious()); } return json_encode($error, JSON_PRETTY_PRINT); } /** * Render XML error * * @param Exception $exception * @return string */ protected function renderXmlErrorMessage(Exception $exception) { $xml = "\n Slim Application Error\n"; if ($this->displayErrorDetails) { do { $xml .= " \n"; $xml .= " " . get_class($exception) . "\n"; $xml .= " " . $exception->getCode() . "\n"; $xml .= " " . $this->createCdataSection($exception->getMessage()) . "\n"; $xml .= " " . $exception->getFile() . "\n"; $xml .= " " . $exception->getLine() . "\n"; $xml .= " " . $this->createCdataSection($exception->getTraceAsString()) . "\n"; $xml .= " \n"; } while ($exception = $exception->getPrevious()); } $xml .= ""; return $xml; } /** * Returns a CDATA section with the given content. * * @param string $content * @return string */ private function createCdataSection($content) { return sprintf('', str_replace(']]>', ']]]]>', $content)); } /** * Determine which content type we know about is wanted using Accept header * * @param ServerRequestInterface $request * @return string */ private function determineContentType(ServerRequestInterface $request) { $acceptHeader = $request->getHeaderLine('Accept'); $selectedContentTypes = array_intersect(explode(',', $acceptHeader), $this->knownContentTypes); if (count($selectedContentTypes)) { return $selectedContentTypes[0]; } return 'text/html'; } }