Completed
Pull Request — master (#283)
by Phil
02:20
created

JsonStrategy::getOptionsCallable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 6
cts 6
cp 1
rs 9.9666
c 0
b 0
f 0
cc 1
crap 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace League\Route\Strategy;
6
7
use JsonSerializable;
8
use League\Route\Http;
9
use League\Route\Http\Exception\{MethodNotAllowedException, NotFoundException};
10
use League\Route\Route;
11
use League\Route\{ContainerAwareInterface, ContainerAwareTrait};
12
use Psr\Http\Message\{ResponseFactoryInterface, ResponseInterface, ServerRequestInterface};
13
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
14
use Throwable;
15
16
class JsonStrategy extends AbstractStrategy implements ContainerAwareInterface, OptionsHandlerInterface
17
{
18
    use ContainerAwareTrait;
19
20
    /**
21
     * @var ResponseFactoryInterface
22
     */
23
    protected $responseFactory;
24
25
    /**
26
     * @var int
27
     */
28
    protected $jsonFlags;
29
30 30
    public function __construct(ResponseFactoryInterface $responseFactory, int $jsonFlags = 0)
31
    {
32 30
        $this->responseFactory = $responseFactory;
33 30
        $this->jsonFlags = $jsonFlags;
34
35
        $this->addResponseDecorator(static function (ResponseInterface $response): ResponseInterface {
36 10
            if (false === $response->hasHeader('content-type')) {
37 6
                $response = $response->withHeader('content-type', 'application/json');
38
            }
39
40 10
            return $response;
41 30
        });
42 30
    }
43
44 4
    public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception): MiddlewareInterface
45
    {
46 4
        return $this->buildJsonResponseMiddleware($exception);
47
    }
48
49 4
    public function getNotFoundDecorator(NotFoundException $exception): MiddlewareInterface
50
    {
51 4
        return $this->buildJsonResponseMiddleware($exception);
52
    }
53
54 8
    public function getOptionsCallable(array $methods): callable
55
    {
56
        return function (ServerRequestInterface $request) use ($methods): ResponseInterface {
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
57 2
            $methods  = implode(', ', $methods);
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $methods, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
58 2
            $response = $this->responseFactory->createResponse();
59 2
            $response = $response->withHeader('allow', $methods);
60 2
            return $response->withHeader('access-control-allow-methods', $methods);
61 8
        };
62
    }
63
64 12
    public function getThrowableHandler(): MiddlewareInterface
65
    {
66
        return new class ($this->responseFactory->createResponse()) implements MiddlewareInterface
67
        {
68
            protected $response;
69
70
            public function __construct(ResponseInterface $response)
71
            {
72 12
                $this->response = $response;
73 12
            }
74
75
            public function process(
76
                ServerRequestInterface $request,
77
                RequestHandlerInterface $requestHandler
78
            ): ResponseInterface {
79
                try {
80 12
                    return $requestHandler->handle($request);
81 8
                } catch (Throwable $exception) {
82 8
                    $response = $this->response;
83
84 8
                    if ($exception instanceof Http\Exception) {
85 4
                        return $exception->buildJsonResponse($response);
86
                    }
87
88 4
                    $response->getBody()->write(json_encode([
89 4
                        'status_code'   => 500,
90 4
                        'reason_phrase' => $exception->getMessage()
91
                    ]));
92
93 4
                    $response = $response->withAddedHeader('content-type', 'application/json');
94 4
                    return $response->withStatus(500, strtok($exception->getMessage(), "\n"));
95
                }
96
            }
97
        };
98
    }
99
100 14
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request): ResponseInterface
101
    {
102 14
        $controller = $route->getCallable($this->getContainer());
103 14
        $response = $controller($request, $route->getVars());
104
105 10
        if ($this->isJsonSerializable($response)) {
106 8
            $body = json_encode($response, $this->jsonFlags);
107 8
            $response = $this->responseFactory->createResponse();
108 8
            $response->getBody()->write($body);
109
        }
110
111 10
        return $this->decorateResponse($response);
112
    }
113
114 4
    protected function buildJsonResponseMiddleware(Http\Exception $exception): MiddlewareInterface
115
    {
116
        return new class ($this->responseFactory->createResponse(), $exception) implements MiddlewareInterface
117
        {
118
            protected $response;
119
            protected $exception;
120
121 8
            public function __construct(ResponseInterface $response, Http\Exception $exception)
122
            {
123 12
                $this->response  = $response;
124 12
                $this->exception = $exception;
125 12
            }
126
127 8
            public function process(
128
                ServerRequestInterface $request,
129
                RequestHandlerInterface $requestHandler
130
            ): ResponseInterface {
131 12
                return $this->exception->buildJsonResponse($this->response);
132
            }
133
        };
134
    }
135
136 15
    protected function isJsonSerializable($response): bool
137
    {
138 15
        if ($response instanceof ResponseInterface) {
139 3
            return false;
140
        }
141
142 12
        return (is_array($response) || is_object($response) || $response instanceof JsonSerializable);
0 ignored issues
show
Bug introduced by
The class JsonSerializable does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
143
    }
144
}
145