Completed
Pull Request — master (#22)
by Adam
02:38
created

ExceptionHandler::handler()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace Equip\Handler;
4
5
use Equip\Exception\HttpException;
6
use Exception;
7
use InvalidArgumentException;
8
use Negotiation\Negotiator;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Relay\ResolverInterface;
12
use Whoops\Run as Whoops;
13
14
class ExceptionHandler
15
{
16
    /**
17
     * @var Negotiator
18
     */
19
    private $negotiator;
20
21
    /**
22
     * @var ExceptionHandlerPreferences
23
     */
24
    private $preferences;
25
26
    /**
27
     * @var ResolverInterface
28
     */
29
    private $resolver;
30
31
    /**
32
     * @var Whoops
33
     */
34
    private $whoops;
35
36
    /**
37
     * @param ExceptionHandlerPreferences $preferences
38
     * @param Negotiator $negotiator
39
     * @param ResolverInterface $resolver
40
     * @param Whoops $whoops
41
     */
42 12
    public function __construct(
43
        ExceptionHandlerPreferences $preferences,
44
        Negotiator $negotiator,
45
        ResolverInterface $resolver,
46
        Whoops $whoops
47
    ) {
48 12
        $this->preferences = $preferences;
49 12
        $this->negotiator = $negotiator;
50 12
        $this->resolver = $resolver;
51 12
        $this->whoops = $whoops;
52 12
    }
53
54
    /**
55
     * @param ServerRequestInterface $request
56
     * @param ResponseInterface $response
57
     * @param callable $next
58
     *
59
     * @return ResponseInterface
60
     */
61 12
    public function __invoke(
62
        ServerRequestInterface $request,
63
        ResponseInterface $response,
64
        callable $next
65
    ) {
66
        try {
67 12
            return $next($request, $response);
68 12
        } catch (Exception $e) {
69 12
            $type = $this->type($request);
70
71 12
            $response = $response->withHeader('Content-Type', $type);
72
73
            try {
74 12
                if (method_exists($e, 'getHttpStatus')) {
75 12
                    $code = $e->getHttpStatus();
76
                } else {
77 10
                    $code = $e->getCode();
78
                }
79
                $response = $response->withStatus($code);
80 12
            } catch (InvalidArgumentException $_) {
81 2
                // Exception did not contain a valid code
82 2
                $response = $response->withStatus(500);
83
            }
84 12
85 12
            if ($e instanceof HttpException) {
86
                $response = $e->withResponse($response);
87 12
            }
88 12
89
            $handler = $this->handler($type);
90 12
            $this->whoops->pushHandler($handler);
0 ignored issues
show
Documentation introduced by
$handler is of type object<Whoops\Handler\HandlerInterface>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
91
92 12
            $body = $this->whoops->handleException($e);
0 ignored issues
show
Documentation introduced by
$e is of type object<Exception>, but the function expects a object<Throwable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
93
            $response->getBody()->write($body);
94
95
            $this->whoops->popHandler();
96
97
            return $response;
98
        }
99
    }
100
101
    /**
102
     * Determine the preferred content type for the current request
103 12
     *
104
     * @param ServerRequestInterface $request
105 12
     *
106 12
     * @return string
107
     */
108 12
    private function type(ServerRequestInterface $request)
109 10
    {
110 10
        $accept = $request->getHeaderLine('Accept');
111
        $priorities = $this->preferences->toArray();
112 12
113 10
        if (!empty($accept)) {
114
            $preferred = $this->negotiator->getBest($accept, array_keys($priorities));
115
        }
116 2
117
        if (!empty($preferred)) {
118
            return $preferred->getValue();
119
        }
120
121
        return key($priorities);
122
    }
123
124
    /**
125
     * Retrieve the handler to use for the given type
126 12
     *
127
     * @param string $type
128 12
     *
129
     * @return \Whoops\Handler\HandlerInterface
130
     */
131
    private function handler($type)
132
    {
133
        return call_user_func($this->resolver, $this->preferences[$type]);
134
    }
135
}
136