Completed
Push — master ( e81b92...349f3b )
by Phil
58:34 queued 08:42
created

JsonStrategy   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 7
dl 0
loc 150
ccs 42
cts 42
cp 1
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$0 ➔ process() 0 6 1
A isJsonEncodable() 0 8 3
A getNotFoundDecorator() 0 4 1
A getMethodNotAllowedDecorator() 0 4 1
A buildJsonResponseMiddleware() 0 21 1
A hp$0 ➔ __construct() 0 5 1
A hp$1 ➔ __construct() 0 4 1
A hp$1 ➔ process() 0 22 3
A __construct() 0 6 1
A invokeRouteCallable() 0 15 2
A getExceptionHandler() 0 4 1
A getThrowableHandler() 0 35 3
1
<?php declare(strict_types=1);
2
3
namespace League\Route\Strategy;
4
5
use League\Route\{ContainerAwareInterface, ContainerAwareTrait};
6
use League\Route\Http\Exception as HttpException;
7
use League\Route\Http\Exception\{MethodNotAllowedException, NotFoundException};
8
use League\Route\Route;
9
use Psr\Http\Message\{ResponseFactoryInterface, ResponseInterface, ServerRequestInterface};
10
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
11
use Throwable;
12
13
class JsonStrategy extends AbstractStrategy implements ContainerAwareInterface
14
{
15
    use ContainerAwareTrait;
16
17
    /**
18
     * @var \Psr\Http\Message\ResponseFactoryInterface
19
     */
20
    protected $responseFactory;
21
22
    /**
23
     * Construct.
24
     *
25
     * @param \Psr\Http\Message\ResponseFactoryInterface $responseFactory
26
     */
27 32
    public function __construct(ResponseFactoryInterface $responseFactory)
28
    {
29 32
        $this->responseFactory = $responseFactory;
30
31 32
        $this->addDefaultResponseHeader('content-type', 'application/json');
32 32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37 14
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request) : ResponseInterface
38
    {
39 14
        $controller = $route->getCallable($this->getContainer());
40 14
        $response = $controller($request, $route->getVars());
41
42 10
        if ($this->isJsonEncodable($response)) {
43 8
            $body     = json_encode($response);
44 8
            $response = $this->responseFactory->createResponse(200);
45 8
            $response->getBody()->write($body);
46
        }
47
48 10
        $response = $this->applyDefaultResponseHeaders($response);
49
50 10
        return $response;
51
    }
52
53
    /**
54
     * Check if the response can be converted to JSON
55
     *
56
     * Arrays can always be converted, objects can be converted if they're not a response already
57
     *
58
     * @param mixed $response
59
     *
60
     * @return bool
61
     */
62 10
    protected function isJsonEncodable($response) : bool
63
    {
64 10
        if ($response instanceof ResponseInterface) {
1 ignored issue
show
Bug introduced by
The class Psr\Http\Message\ResponseInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
65 2
            return false;
66
        }
67
68 8
        return (is_array($response) || is_object($response));
69
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 4
    public function getNotFoundDecorator(NotFoundException $exception) : MiddlewareInterface
75
    {
76 4
        return $this->buildJsonResponseMiddleware($exception);
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82 4
    public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception) : MiddlewareInterface
83
    {
84 4
        return $this->buildJsonResponseMiddleware($exception);
85
    }
86
87
    /**
88
     * Return a middleware the creates a JSON response from an HTTP exception
89
     *
90
     * @param \League\Route\Http\Exception $exception
91
     *
92
     * @return \Psr\Http\Server\MiddlewareInterface
93
     */
94 8
    protected function buildJsonResponseMiddleware(HttpException $exception) : MiddlewareInterface
95
    {
96
        return new class($this->responseFactory->createResponse(), $exception) implements MiddlewareInterface
97
        {
98
            protected $response;
99
            protected $exception;
100
101
            public function __construct(ResponseInterface $response, HttpException $exception)
102
            {
103 8
                $this->response  = $response;
104 8
                $this->exception = $exception;
105 8
            }
106
107
            public function process(
108
                ServerRequestInterface $request,
109
                RequestHandlerInterface $requestHandler
110
            ) : ResponseInterface {
111 8
                return $this->exception->buildJsonResponse($this->response);
112
            }
113
        };
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119 12
    public function getExceptionHandler() : MiddlewareInterface
120
    {
121 12
        return $this->getThrowableHandler();
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127
    public function getThrowableHandler() : MiddlewareInterface
128
    {
129
        return new class($this->responseFactory->createResponse()) implements MiddlewareInterface
130
        {
131
            protected $response;
132
133 12
            public function __construct(ResponseInterface $response)
134
            {
135 12
                $this->response = $response;
136 12
            }
137
138 12
            public function process(
139
                ServerRequestInterface $request,
140
                RequestHandlerInterface $requestHandler
141
            ) : ResponseInterface {
142
                try {
143 12
                    return $requestHandler->handle($request);
144 8
                } catch (Throwable $exception) {
145 8
                    $response = $this->response;
146
147 8
                    if ($exception instanceof HttpException) {
148 4
                        return $exception->buildJsonResponse($response);
149
                    }
150
151 4
                    $response->getBody()->write(json_encode([
152 4
                        'status_code'   => 500,
153 4
                        'reason_phrase' => $exception->getMessage()
154
                    ]));
155
156 4
                    $response = $response->withAddedHeader('content-type', 'application/json');
157 4
                    return $response->withStatus(500, strtok($exception->getMessage(), "\n"));
158
                }
159
            }
160
        };
161
    }
162
}
163