Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
85 / 85
96.49% covered (success)
96.49%
55 / 57
36.49% covered (danger)
36.49%
27 / 74
85.71% covered (warning)
85.71%
12 / 14
CRAP
0.00% covered (danger)
0.00%
0 / 1
Handler
100.00% covered (success)
100.00%
85 / 85
96.49% covered (success)
96.49%
55 / 57
36.49% covered (danger)
36.49%
27 / 74
100.00% covered (success)
100.00%
14 / 14
294.36
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 debugHandler
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 logger
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 process
100.00% covered (success)
100.00%
5 / 5
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 4
100.00% covered (success)
100.00%
1 / 1
2
 renderer
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 handleError
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 response
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
19 / 19
16.67% covered (danger)
16.67%
8 / 48
100.00% covered (success)
100.00%
1 / 1
55.88
 normalize
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 fallback
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 status
100.00% covered (success)
100.00%
4 / 4
87.50% covered (warning)
87.50%
7 / 8
40.00% covered (danger)
40.00%
2 / 5
100.00% covered (success)
100.00%
1 / 1
7.46
 log
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 recordServerException
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 logUnmatched
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 escape
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Celemas\Core\Error;
6
7use Celemas\Core\Exception\HttpError;
8use Celemas\Core\Exception\HttpMethodNotAllowed;
9use Celemas\Core\Exception\HttpNotFound;
10use Celemas\Core\Server\Console as ServerConsole;
11use Celemas\Router\Exception\MethodNotAllowedException;
12use Celemas\Router\Exception\NotFoundException;
13use ErrorException;
14use Override;
15use Psr\Http\Message\ResponseFactoryInterface as ResponseFactory;
16use Psr\Http\Message\ResponseInterface as Response;
17use Psr\Http\Message\ServerRequestInterface as Request;
18use Psr\Http\Server\MiddlewareInterface as Middleware;
19use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
20use Psr\Log\LoggerInterface as Logger;
21use Throwable;
22
23/** @api */
24class Handler implements Middleware
25{
26    protected ?Logger $logger = null;
27    protected ?DebugHandler $debugHandler = null;
28
29    /** @var list<RendererEntry> */
30    protected array $renderers = [];
31
32    protected ?RendererEntry $defaultRenderer = null;
33
34    public function __construct(
35        protected readonly ResponseFactory $responseFactory,
36        protected readonly bool $debug = false,
37    ) {}
38
39    public function debugHandler(DebugHandler $debugHandler): void
40    {
41        $this->debugHandler = $debugHandler;
42    }
43
44    public function logger(?Logger $logger = null): void
45    {
46        $this->logger = $logger;
47    }
48
49    #[Override]
50    public function process(Request $request, RequestHandler $handler): Response
51    {
52        set_error_handler([$this, 'handleError'], E_ALL);
53
54        try {
55            return $handler->handle($request);
56        } catch (Throwable $e) {
57            return $this->response($e, $request);
58        } finally {
59            restore_error_handler();
60        }
61    }
62
63    /**
64     * @param class-string<Throwable>|list<class-string<Throwable>>|null $exceptions
65     */
66    public function renderer(Renderer $renderer, string|array|null $exceptions = null): RendererEntry
67    {
68        if ($exceptions === null) {
69            $entry = new RendererEntry([], $renderer);
70            $this->defaultRenderer = $entry;
71
72            return $entry;
73        }
74
75        $classes = (array) $exceptions;
76        $entry = new RendererEntry($classes, $renderer);
77        $this->renderers[] = $entry;
78
79        return $entry;
80    }
81
82    public function handleError(
83        int $level,
84        string $message,
85        string $file = '',
86        int $line = 0,
87    ): bool {
88        if (($level & error_reporting()) !== 0) {
89            throw new ErrorException($message, 0, $level, $file, $line);
90        }
91
92        return false;
93    }
94
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
123            );
124        }
125
126        if ($this->debug) {
127            if ($this->debugHandler) {
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
131            }
132
133            throw $exception;
134        }
135
136        if ($this->defaultRenderer) {
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
141            } else {
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
152            );
153        }
154
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
160
161    protected function normalize(Throwable $exception, Request $request): Throwable
162    {
163        if ($exception instanceof NotFoundException) {
164            return new HttpNotFound($request, previous: $exception);
165        }
166
167        if ($exception instanceof MethodNotAllowedException) {
168            return new HttpMethodNotAllowed(
169                $request,
170                ['allowed' => $exception->allowedMethods()],
171                previous: $exception,
172            );
173        }
174
175        return $exception;
176    }
177
178    protected function fallback(Throwable $exception): Response
179    {
180        $status = $this->status($exception);
181        $title = $exception instanceof HttpError
182            ? $exception->title()
183            : '500 Internal Server Error';
184        $response = $this->responseFactory
185            ->createResponse($status)
186            ->withHeader('Content-Type', 'text/html; charset=utf-8');
187        $response->getBody()->write('<h1>' . $this->escape($title) . '</h1>');
188
189        return $response;
190    }
191
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
195            return 500;
196        }
197
198        $status = $exception->statusCode();
199
200        return $status >= 400 && $status <= 599 ? $status : 500;
201    }
202
203    protected function log(string|int $logLevel, Throwable $exception): void
204    {
205        $this->logger?->log($logLevel, 'Matched exception', ['exception' => $exception]);
206    }
207
208    protected function recordServerException(Throwable $exception): void
209    {
210        if ($this->status($exception) >= 500) {
211            ServerConsole::recordException($exception, trace: $this->debug);
212        }
213    }
214
215    protected function logUnmatched(Throwable $exception): void
216    {
217        $this->logger?->alert('Unmatched exception', ['exception' => $exception]);
218    }
219
220    private function escape(string $value): string
221    {
222        return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
223    }
224}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

Handler->__construct
35        protected readonly ResponseFactory $responseFactory,
36        protected readonly bool $debug = false,
37    ) {}
Handler->debugHandler
39    public function debugHandler(DebugHandler $debugHandler): void
40    {
41        $this->debugHandler = $debugHandler;
42    }
Handler->escape
220    private function escape(string $value): string
221    {
222        return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
223    }
Handler->fallback
178    protected function fallback(Throwable $exception): Response
179    {
180        $status = $this->status($exception);
181        $title = $exception instanceof HttpError
 
182            ? $exception->title()
 
181        $title = $exception instanceof HttpError
182            ? $exception->title()
183            : '500 Internal Server Error';
184        $response = $this->responseFactory
185            ->createResponse($status)
186            ->withHeader('Content-Type', 'text/html; charset=utf-8');
187        $response->getBody()->write('<h1>' . $this->escape($title) . '</h1>');
188
189        return $response;
190    }
178    protected function fallback(Throwable $exception): Response
179    {
180        $status = $this->status($exception);
181        $title = $exception instanceof HttpError
 
181        $title = $exception instanceof HttpError
182            ? $exception->title()
183            : '500 Internal Server Error';
 
181        $title = $exception instanceof HttpError
182            ? $exception->title()
183            : '500 Internal Server Error';
184        $response = $this->responseFactory
185            ->createResponse($status)
186            ->withHeader('Content-Type', 'text/html; charset=utf-8');
187        $response->getBody()->write('<h1>' . $this->escape($title) . '</h1>');
188
189        return $response;
190    }
Handler->handleError
83        int $level,
84        string $message,
85        string $file = '',
86        int $line = 0,
87    ): bool {
88        if (($level & error_reporting()) !== 0) {
 
89            throw new ErrorException($message, 0, $level, $file, $line);
83        int $level,
84        string $message,
85        string $file = '',
86        int $line = 0,
87    ): bool {
88        if (($level & error_reporting()) !== 0) {
 
92        return false;
93    }
Handler->log
203    protected function log(string|int $logLevel, Throwable $exception): void
204    {
205        $this->logger?->log($logLevel, 'Matched exception', ['exception' => $exception]);
206    }
Handler->logUnmatched
215    protected function logUnmatched(Throwable $exception): void
216    {
217        $this->logger?->alert('Unmatched exception', ['exception' => $exception]);
218    }
Handler->logger
44    public function logger(?Logger $logger = null): void
45    {
46        $this->logger = $logger;
47    }
Handler->normalize
161    protected function normalize(Throwable $exception, Request $request): Throwable
162    {
163        if ($exception instanceof NotFoundException) {
 
164            return new HttpNotFound($request, previous: $exception);
161    protected function normalize(Throwable $exception, Request $request): Throwable
162    {
163        if ($exception instanceof NotFoundException) {
 
167        if ($exception instanceof MethodNotAllowedException) {
 
168            return new HttpMethodNotAllowed(
169                $request,
161    protected function normalize(Throwable $exception, Request $request): Throwable
162    {
163        if ($exception instanceof NotFoundException) {
 
167        if ($exception instanceof MethodNotAllowedException) {
 
175        return $exception;
176    }
Handler->process
50    public function process(Request $request, RequestHandler $handler): Response
51    {
52        set_error_handler([$this, 'handleError'], E_ALL);
53
54        try {
55            return $handler->handle($request);
 
59            restore_error_handler();
60        }
61    }
50    public function process(Request $request, RequestHandler $handler): Response
51    {
52        set_error_handler([$this, 'handleError'], E_ALL);
53
54        try {
55            return $handler->handle($request);
 
55            return $handler->handle($request);
56        } catch (Throwable $e) {
 
57            return $this->response($e, $request);
 
59            restore_error_handler();
60        }
61    }
56        } catch (Throwable $e) {
 
57            return $this->response($e, $request);
 
57            return $this->response($e, $request);
Handler->recordServerException
208    protected function recordServerException(Throwable $exception): void
209    {
210        if ($this->status($exception) >= 500) {
 
211            ServerConsole::recordException($exception, trace: $this->debug);
212        }
213    }
 
213    }
208    protected function recordServerException(Throwable $exception): void
209    {
210        if ($this->status($exception) >= 500) {
 
213    }
Handler->renderer
66    public function renderer(Renderer $renderer, string|array|null $exceptions = null): RendererEntry
67    {
68        if ($exceptions === null) {
 
69            $entry = new RendererEntry([], $renderer);
70            $this->defaultRenderer = $entry;
71
72            return $entry;
66    public function renderer(Renderer $renderer, string|array|null $exceptions = null): RendererEntry
67    {
68        if ($exceptions === null) {
 
75        $classes = (array) $exceptions;
76        $entry = new RendererEntry($classes, $renderer);
77        $this->renderers[] = $entry;
78
79        return $entry;
80    }
Handler->response
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
103                continue;
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
102            if (!$entry->matches($exception)) {
 
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
112            $this->log($logLevel, $exception);
113        }
114
115        if ($renderer) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
116            $this->recordServerException($exception);
117
118            return $renderer->render(
119                $exception,
120                $this->responseFactory,
121                $request,
122                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
128                $this->recordServerException($exception);
129
130                return $this->debugHandler->handle($exception, $this->responseFactory);
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
127            if ($this->debugHandler) {
 
133            throw $exception;
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
139            if ($logLevel !== null) {
140                $this->log($logLevel, $exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
137            $logLevel = $this->defaultRenderer->logLevel();
138
139            if ($logLevel !== null) {
 
142                $this->logUnmatched($exception);
143            }
144
145            $this->recordServerException($exception);
 
145            $this->recordServerException($exception);
146
147            return $this->defaultRenderer->renderer->render(
148                $exception,
149                $this->responseFactory,
150                $request,
151                $this->debug,
95    public function response(Throwable $exception, Request $request): Response
96    {
97        $exception = $this->normalize($exception, $request);
98        $renderer = null;
99        $logLevel = null;
100
101        foreach ($this->renderers as $entry) {
 
101        foreach ($this->renderers as $entry) {
102            if (!$entry->matches($exception)) {
103                continue;
104            }
105
106            $renderer = $entry->renderer;
107            $logLevel = $entry->logLevel();
108            break;
109        }
110
111        if ($logLevel !== null) {
 
115        if ($renderer) {
 
126        if ($this->debug) {
 
136        if ($this->defaultRenderer) {
 
155        $this->logUnmatched($exception);
156        $this->recordServerException($exception);
157
158        return $this->fallback($exception);
159    }
Handler->status
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
 
195            return 500;
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
 
198        $status = $exception->statusCode();
199
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
201    }
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
 
198        $status = $exception->statusCode();
199
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
201    }
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
 
198        $status = $exception->statusCode();
199
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
201    }
192    protected function status(Throwable $exception): int
193    {
194        if (!$exception instanceof HttpError) {
 
198        $status = $exception->statusCode();
199
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
 
200        return $status >= 400 && $status <= 599 ? $status : 500;
201    }