JsonStrategy.php$1 ➔ buildJsonResponseMiddleware()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
ccs 5
cts 5
cp 1
rs 9.6666
cc 1
crap 1

2 Methods

Rating   Name   Duplication   Size   Complexity  
A JsonStrategy.php$1 ➔ __construct() 0 4 1
A JsonStrategy.php$1 ➔ process() 0 5 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 34
    public function __construct(ResponseFactoryInterface $responseFactory, int $jsonFlags = 0)
31
    {
32 34
        $this->responseFactory = $responseFactory;
33 34
        $this->jsonFlags = $jsonFlags;
34
35
        $this->addResponseDecorator(static function (ResponseInterface $response): ResponseInterface {
36 14
            if (false === $response->hasHeader('content-type')) {
37 6
                $response = $response->withHeader('content-type', 'application/json');
38
            }
39
40 14
            return $response;
41 34
        });
42 34
    }
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 10
    public function getOptionsCallable(array $methods): callable
55
    {
56
        return function () use ($methods): ResponseInterface {
57 4
            $options  = implode(', ', $methods);
58 4
            $response = $this->responseFactory->createResponse();
59 4
            $response = $response->withHeader('allow', $options);
60 4
            return $response->withHeader('access-control-allow-methods', $options);
61 10
        };
62
    }
63
64 16
    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 16
                $this->response = $response;
73 16
            }
74
75
            public function process(
76
                ServerRequestInterface $request,
77
                RequestHandlerInterface $handler
78
            ): ResponseInterface {
79
                try {
80 16
                    return $handler->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 18
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request): ResponseInterface
101
    {
102 18
        $controller = $route->getCallable($this->getContainer());
103 18
        $response = $controller($request, $route->getVars());
104
105 14
        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 14
        return $this->decorateResponse($response);
112
    }
113
114 12
    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
            public function __construct(ResponseInterface $response, Http\Exception $exception)
122
            {
123 12
                $this->response  = $response;
124 12
                $this->exception = $exception;
125 12
            }
126
127
            public function process(
128
                ServerRequestInterface $request,
129
                RequestHandlerInterface $handler
130
            ): ResponseInterface {
131 12
                return $this->exception->buildJsonResponse($this->response);
132
            }
133
        };
134
    }
135
136 21
    protected function isJsonSerializable($response): bool
137
    {
138 21
        if ($response instanceof ResponseInterface) {
139 9
            return false;
140
        }
141
142 12
        return (is_array($response) || is_object($response) || $response instanceof JsonSerializable);
143
    }
144
}
145