ErrorHandler   A
last analyzed

Complexity

Total Complexity 11

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 11
lcom 0
cbo 6
dl 0
loc 94
ccs 0
cts 39
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B __invoke() 0 37 6
A response() 0 6 1
A getErrorArray() 0 14 2
A getErrorCode() 0 4 1
1
<?php
2
namespace Staticus\Middlewares;
3
4
use Psr\Http\Message\ServerRequestInterface as Request;
5
use Psr\Http\Message\ResponseInterface as Response;
6
use Staticus\Config\ConfigInterface;
7
use Staticus\Config\Config;
8
use Staticus\Diactoros\Response\NotFoundResponse;
9
use Staticus\Exceptions\ExceptionCodes;
10
use Staticus\Exceptions\ResourceNotFoundException;
11
use Staticus\Exceptions\WrongRequestException;
12
use Staticus\Resources\ResourceDOInterface;
13
use Zend\Diactoros\Response\JsonResponse;
14
15
class ErrorHandler
16
{
17
    /**
18
     * @var ConfigInterface|Config
19
     */
20
    private $config;
21
22
    public function __construct(ConfigInterface $config)
23
    {
24
        $this->config = $config;
25
    }
26
27
    public function __invoke($error, Request $request, Response $response, callable $next)
28
    {
29
        /*
30
         If $error is not an exception, it will use the response status if it already indicates an error
31
         (ie., >= 400 status), or will use a 500 status, and return the response directly with the reason phrase.
32
         */
33
        if ($error instanceof \Exception) {
34
            $className = $error->getTrace();
35
            if (isset($className[0]['class'])) {
36
                $className = $className[0]['class'];
37
            }
38
            if ($error instanceof ResourceNotFoundException) {
39
                $error = $this->getErrorArray(
40
                    $error->getMessage()
41
                    , $this->getErrorCode($error, $className)
42
                    , $error->getResourceDO()
43
                );
44
45
                return new NotFoundResponse($error);
46
            } else if ($error instanceof WrongRequestException) {
47
48
                /** @see \Zend\Diactoros\Response::$phrases */
49
                return $this->response(400, $error->getMessage(),
50
                    ExceptionCodes::code($className) . '.' . $error->getCode());
51
            } else {
52
53
                $message = $this->config->get('error_handler', false)
54
                    ? $error->getMessage()
55
                    : 'Internal error';
56
57
                /** @see \Zend\Diactoros\Response::$phrases */
58
                return $this->response(503, $message, $this->getErrorCode($error, $className));
59
            }
60
        } else {
61
            $next($request, $response, $next);
62
        }
63
    }
64
65
    /**
66
     * @param integer $status
67
     * @param string $message
68
     * @param integer $code
69
     * @return JsonResponse
70
     */
71
    protected function response($status, $message, $code)
72
    {
73
        $error = $this->getErrorArray($message, $code);
74
75
        return new JsonResponse($error, $status);
76
    }
77
78
    /**
79
     * @param string $message
80
     * @param integer $code
81
     * @param null|ResourceDOInterface $resourceDO
82
     * @return array
83
     */
84
    protected function getErrorArray($message, $code, ResourceDOInterface $resourceDO = null)
85
    {
86
        $error = [
87
            'error' => [
88
                'title' => $message,
89
                'code' => $code,
90
            ],
91
        ];
92
        if ($resourceDO) {
93
            $error['error']['detail']['resource'] = $resourceDO->toArray();
94
        }
95
96
        return $error;
97
    }
98
99
    /**
100
     * @param \Exception $error
101
     * @param string $className
102
     * @return string
103
     */
104
    protected function getErrorCode(\Exception $error, $className)
105
    {
106
        return $error->getCode() . '.' . ExceptionCodes::code($className) . '.' . $error->getLine();
107
    }
108
}