Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ErrorHandler
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 5
110
0.00% covered (danger)
0.00%
0 / 1
 __invoke
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
6
 getStatusCode
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 formatErrorPayload
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 getErrorMessage
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 logError
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace BO\Zmscitizenapi\Helper;
6
7use BO\Zmscitizenapi\Helper\ClientIpHelper;
8use BO\Zmscitizenapi\Services\Core\LoggerService;
9use Psr\Http\Message\ResponseInterface;
10use Psr\Http\Message\ServerRequestInterface;
11use Slim\Exception\HttpException;
12use Slim\Interfaces\ErrorHandlerInterface;
13
14class ErrorHandler implements ErrorHandlerInterface
15{
16    public function __invoke(
17        ServerRequestInterface $request,
18        \Throwable $exception,
19        bool $displayErrorDetails,
20        bool $logErrors,
21        bool $logErrorDetails
22    ): ResponseInterface {
23        $statusCode = $this->getStatusCode($exception);
24
25        if ($logErrors) {
26            $this->logError($exception, $request, $displayErrorDetails, $logErrorDetails);
27        }
28
29        $response = new \Slim\Psr7\Response();
30        $payload = $this->formatErrorPayload($exception, $displayErrorDetails);
31
32        $response->getBody()->write(json_encode($payload));
33
34        return $response
35            ->withHeader('Content-Type', 'application/json')
36            ->withStatus($statusCode);
37    }
38
39    private function getStatusCode(\Throwable $exception): int
40    {
41        if ($exception instanceof HttpException) {
42            return $exception->getCode();
43        }
44
45        return 500;
46    }
47
48    private function formatErrorPayload(\Throwable $exception, bool $displayErrorDetails): array
49    {
50        $error = [
51            'message' => $this->getErrorMessage($exception, $displayErrorDetails),
52            'code' => $exception->getCode()
53        ];
54
55        if ($displayErrorDetails) {
56            $error['type'] = get_class($exception);
57            $error['file'] = $exception->getFile();
58            $error['line'] = $exception->getLine();
59            $error['trace'] = $exception->getTrace();
60        }
61
62        return ['error' => $error];
63    }
64
65    private function getErrorMessage(\Throwable $exception, bool $displayErrorDetails): string
66    {
67        if ($displayErrorDetails) {
68            return $exception->getMessage();
69        }
70
71        if ($exception instanceof HttpException) {
72            return $exception->getMessage();
73        }
74
75        return 'An internal error has occurred.';
76    }
77
78    private function logError(
79        \Throwable $exception,
80        ServerRequestInterface $request,
81        bool $displayErrorDetails,
82        bool $logErrorDetails
83    ): void {
84        LoggerService::logError($exception, $request, null, [
85            'displayErrorDetails' => $displayErrorDetails,
86            'logErrorDetails' => $logErrorDetails,
87            'uri' => (string)$request->getUri(),
88            'method' => $request->getMethod(),
89            'ip' => ClientIpHelper::getClientIp()
90        ]);
91    }
92}