Completed
Pull Request — master (#283)
by Phil
04:05 queued 40s
created

anonymous//src/Strategy/JsonStrategy.php$0   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 29
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 4
c 0
b 0
f 0
dl 0
loc 29
ccs 12
cts 12
cp 1
rs 10
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 15
    public function __construct(ResponseFactoryInterface $responseFactory, int $jsonFlags = 0)
31
    {
32 15
        $this->responseFactory = $responseFactory;
33 15
        $this->jsonFlags = $jsonFlags;
34
35
        $this->addResponseDecorator(static function (ResponseInterface $response): ResponseInterface {
36 5
            if (false === $response->hasHeader('content-type')) {
37 3
                $response = $response->withHeader('content-type', 'application/json');
38
            }
39
40 5
            return $response;
41 15
        });
42 15
    }
43
44 2
    public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception): MiddlewareInterface
45
    {
46 2
        return $this->buildJsonResponseMiddleware($exception);
47
    }
48
49 2
    public function getNotFoundDecorator(NotFoundException $exception): MiddlewareInterface
50
    {
51 2
        return $this->buildJsonResponseMiddleware($exception);
52
    }
53
54 4
    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. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

56
        return function (/** @scrutinizer ignore-unused */ ServerRequestInterface $request) use ($methods): ResponseInterface {

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

Loading history...
57 1
            $methods  = implode(', ', $methods);
58 1
            $response = $this->responseFactory->createResponse();
59 1
            $response = $response->withHeader('allow', $methods);
60 1
            return $response->withHeader('access-control-allow-methods', $methods);
61 4
        };
62
    }
63
64 6
    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 6
                $this->response = $response;
73 6
            }
74
75
            public function process(
76
                ServerRequestInterface $request,
77
                RequestHandlerInterface $requestHandler
78
            ): ResponseInterface {
79
                try {
80 6
                    return $requestHandler->handle($request);
81 4
                } catch (Throwable $exception) {
82 4
                    $response = $this->response;
83
84 4
                    if ($exception instanceof Http\Exception) {
85 2
                        return $exception->buildJsonResponse($response);
86
                    }
87
88 2
                    $response->getBody()->write(json_encode([
89 2
                        'status_code'   => 500,
90 2
                        'reason_phrase' => $exception->getMessage()
91
                    ]));
92
93 2
                    $response = $response->withAddedHeader('content-type', 'application/json');
94 2
                    return $response->withStatus(500, strtok($exception->getMessage(), "\n"));
95
                }
96
            }
97
        };
98
    }
99
100 7
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request): ResponseInterface
101
    {
102 7
        $controller = $route->getCallable($this->getContainer());
103 7
        $response = $controller($request, $route->getVars());
104
105 5
        if ($this->isJsonSerializable($response)) {
106 4
            $body = json_encode($response, $this->jsonFlags);
107 4
            $response = $this->responseFactory->createResponse();
108 4
            $response->getBody()->write($body);
109
        }
110
111 5
        return $this->decorateResponse($response);
112
    }
113
114 8
    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 4
            public function __construct(ResponseInterface $response, Http\Exception $exception)
122
            {
123 12
                $this->response  = $response;
124 12
                $this->exception = $exception;
125 12
            }
126
127 4
            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);
143
    }
144
}
145