Passed
Push — master ( 04408a...af617e )
by Daniel
01:47
created

DefaultErrorHandler   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Test Coverage

Coverage 89.19%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 10
eloc 35
c 1
b 0
f 0
dl 0
loc 107
ccs 33
cts 37
cp 0.8919
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __invoke() 0 24 2
A getErrorDetails() 0 15 2
A __construct() 0 8 1
A getHttpStatusCode() 0 20 5
1
<?php
2
3
namespace App\Handler;
4
5
use App\Renderer\JsonRenderer;
6
use DomainException;
7
use Fig\Http\Message\StatusCodeInterface;
8
use InvalidArgumentException;
9
use Psr\Http\Message\ResponseFactoryInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Log\LoggerInterface;
13
use Slim\Exception\HttpException;
14
use Slim\Interfaces\ErrorHandlerInterface;
15
use Throwable;
16
17
/**
18
 * Default Error Renderer.
19
 */
20
final class DefaultErrorHandler implements ErrorHandlerInterface
21
{
22
    private JsonRenderer $jsonRenderer;
23
24
    private ResponseFactoryInterface $responseFactory;
25
26
    private LoggerInterface $logger;
27
28 2
    public function __construct(
29
        JsonRenderer $jsonRenderer,
30
        ResponseFactoryInterface $responseFactory,
31
        LoggerInterface $logger,
32
    ) {
33 2
        $this->jsonRenderer = $jsonRenderer;
34 2
        $this->responseFactory = $responseFactory;
35 2
        $this->logger = $logger;
36
    }
37
38
    /**
39
     * Invoke.
40
     *
41
     * @param ServerRequestInterface $request The request
42
     * @param Throwable $exception The exception
43
     * @param bool $displayErrorDetails Show error details
44
     * @param bool $logErrors Log errors
45
     * @param bool $logErrorDetails Log error details
46
     *
47
     * @return ResponseInterface The response
48
     */
49 1
    public function __invoke(
50
        ServerRequestInterface $request,
51
        Throwable $exception,
52
        bool $displayErrorDetails,
53
        bool $logErrors,
54
        bool $logErrorDetails
55
    ): ResponseInterface {
56
        // Log error
57 1
        if ($logErrors) {
58 1
            $error = $this->getErrorDetails($exception, $logErrorDetails);
59 1
            $error['method'] = $request->getMethod();
60 1
            $error['url'] = (string)$request->getUri();
61
62 1
            $this->logger->error($exception->getMessage(), $error);
63
        }
64
65 1
        $response = $this->responseFactory->createResponse();
66
67
        // Render response
68 1
        $response = $this->jsonRenderer->json($response, [
69 1
            'error' => $this->getErrorDetails($exception, $displayErrorDetails),
70 1
        ]);
71
72 1
        return $response->withStatus($this->getHttpStatusCode($exception));
73
    }
74
75
    /**
76
     * Get http status code.
77
     *
78
     * @param Throwable $exception The exception
79
     *
80
     * @return int The http code
81
     */
82 1
    private function getHttpStatusCode(Throwable $exception): int
83
    {
84
        // Detect status code
85 1
        $statusCode = StatusCodeInterface::STATUS_INTERNAL_SERVER_ERROR;
86
87 1
        if ($exception instanceof HttpException) {
88 1
            $statusCode = $exception->getCode();
89
        }
90
91 1
        if ($exception instanceof DomainException || $exception instanceof InvalidArgumentException) {
92
            // Bad request
93
            $statusCode = StatusCodeInterface::STATUS_BAD_REQUEST;
94
        }
95
96 1
        $file = basename($exception->getFile());
97 1
        if ($file === 'CallableResolver.php') {
98
            $statusCode = StatusCodeInterface::STATUS_NOT_FOUND;
99
        }
100
101 1
        return $statusCode;
102
    }
103
104
    /**
105
     * Get error message.
106
     *
107
     * @param Throwable $exception The error
108
     * @param bool $displayErrorDetails Display details
109
     *
110
     * @return array The error details
111
     */
112 1
    private function getErrorDetails(Throwable $exception, bool $displayErrorDetails): array
113
    {
114 1
        if ($displayErrorDetails === true) {
115 1
            return [
116 1
                'message' => $exception->getMessage(),
117 1
                'code' => $exception->getCode(),
118 1
                'file' => $exception->getFile(),
119 1
                'line' => $exception->getLine(),
120 1
                'previous' => $exception->getPrevious(),
121 1
                'trace' => $exception->getTrace(),
122 1
            ];
123
        }
124
125
        return [
126
            'message' => $exception->getMessage(),
127
        ];
128
    }
129
}
130