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

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 14
cts 14
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 45
    public function __construct(protected ResponseFactoryInterface $responseFactory, protected int $jsonFlags = 0)
21
    {
22 45
        $this->addResponseDecorator(static function (ResponseInterface $response): ResponseInterface {
23 15
            if (false === $response->hasHeader('content-type')) {
24 15
                $response = $response->withHeader('content-type', 'application/json');
25
            }
26
27 15
            return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response could return the type Psr\Http\Message\MessageInterface which includes types incompatible with the type-hinted return Psr\Http\Message\ResponseInterface. Consider adding an additional type-check to rule them out.
Loading history...
28 45
        });
29
    }
30
31 6
    public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception): MiddlewareInterface
32
    {
33 6
        return $this->buildJsonResponseMiddleware($exception);
34
    }
35
36 6
    public function getNotFoundDecorator(NotFoundException $exception): MiddlewareInterface
37
    {
38 6
        return $this->buildJsonResponseMiddleware($exception);
39
    }
40
41 12
    public function getOptionsCallable(array $methods): callable
42
    {
43 12
        return function () use ($methods): ResponseInterface {
44 3
            $options  = implode(', ', $methods);
45 3
            $response = $this->responseFactory->createResponse();
46 3
            $response = $response->withHeader('allow', $options);
47 3
            return $response->withHeader('access-control-allow-methods', $options);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response->withHe...low-methods', $options) returns the type Psr\Http\Message\MessageInterface which includes types incompatible with the type-hinted return Psr\Http\Message\ResponseInterface.
Loading history...
48 12
        };
49
    }
50
51 18
    public function getThrowableHandler(): MiddlewareInterface
52
    {
53 18
        return new class ($this->responseFactory->createResponse()) implements MiddlewareInterface
54 18
        {
55
            protected $response;
56
57
            public function __construct(ResponseInterface $response)
58
            {
59 18
                $this->response = $response;
60
            }
61
62
            public function process(
63
                ServerRequestInterface $request,
64
                RequestHandlerInterface $handler
65
            ): ResponseInterface {
66
                try {
67 18
                    return $handler->handle($request);
68 12
                } catch (Throwable $exception) {
69 12
                    $response = $this->response;
70
71 12
                    if ($exception instanceof Http\Exception) {
72 6
                        return $exception->buildJsonResponse($response);
73
                    }
74
75 6
                    $response->getBody()->write(json_encode([
76 6
                        'status_code'   => 500,
77 6
                        'reason_phrase' => $exception->getMessage()
78 6
                    ]));
79
80 6
                    $response = $response->withAddedHeader('content-type', 'application/json');
81 6
                    return $response->withStatus(500, strtok($exception->getMessage(), "\n"));
0 ignored issues
show
Bug introduced by
The method withStatus() does not exist on Psr\Http\Message\MessageInterface. It seems like you code against a sub-type of Psr\Http\Message\MessageInterface such as Psr\Http\Message\ResponseInterface. ( Ignorable by Annotation )

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

81
                    return $response->/** @scrutinizer ignore-call */ withStatus(500, strtok($exception->getMessage(), "\n"));
Loading history...
82
                }
83
            }
84 18
        };
85
    }
86
87 21
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request): ResponseInterface
88
    {
89 21
        $controller = $route->getCallable($this->getContainer());
90 21
        $response = $controller($request, $route->getVars());
91
92 15
        if ($this->isJsonSerializable($response)) {
93 12
            $body = json_encode($response, $this->jsonFlags);
94 12
            $response = $this->responseFactory->createResponse();
95 12
            $response->getBody()->write($body);
96
        }
97
98 15
        return $this->decorateResponse($response);
99
    }
100
101 12
    protected function buildJsonResponseMiddleware(Http\Exception $exception): MiddlewareInterface
102
    {
103 12
        return new class ($this->responseFactory->createResponse(), $exception) implements MiddlewareInterface
104 12
        {
105
            protected $response;
106
            protected $exception;
107
108
            public function __construct(ResponseInterface $response, Http\Exception $exception)
109
            {
110 12
                $this->response  = $response;
111 12
                $this->exception = $exception;
112
            }
113
114
            public function process(
115
                ServerRequestInterface $request,
116
                RequestHandlerInterface $handler
117
            ): ResponseInterface {
118 12
                return $this->exception->buildJsonResponse($this->response);
119
            }
120 12
        };
121
    }
122
123 15
    protected function isJsonSerializable($response): bool
124
    {
125 15
        if ($response instanceof ResponseInterface) {
126 3
            return false;
127
        }
128
129 12
        return (is_array($response) || is_object($response) || $response instanceof JsonSerializable);
130
    }
131
}
132