Completed
Pull Request — master (#184)
by
unknown
24:22
created

JsonStrategy::getMethodNotAllowedDecorator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
crap 2
nc 1
nop 1
1
<?php declare(strict_types=1);
2
3
namespace League\Route\Strategy;
4
5
use Exception;
6
use League\Route\{ContainerAwareInterface, ContainerAwareTrait};
7
use League\Route\Http\Exception as HttpException;
8
use League\Route\Http\Exception\{MethodNotAllowedException, NotFoundException};
9
use League\Route\Route;
10
use Psr\Http\Message\{ResponseFactoryInterface, ResponseInterface, ServerRequestInterface};
11
use Psr\Http\Server\{MiddlewareInterface, RequestHandlerInterface};
12
13
class JsonStrategy implements ContainerAwareInterface, StrategyInterface
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 22
    public function __construct(ResponseFactoryInterface $responseFactory)
28
    {
29 22
        $this->responseFactory = $responseFactory;
30 22
    }
31
32
    /**
33
     * {@inheritdoc}
34
     */
35 8
    public function invokeRouteCallable(Route $route, ServerRequestInterface $request) : ResponseInterface
36
    {
37 8
        $response = call_user_func_array($route->getCallable($this->getContainer()), [$request, $route->getVars()]);
38
39 4
        if ($this->isJsonEncodable($response)) {
40 2
            $body     = json_encode($response);
41 2
            $response = $this->responseFactory->createResponse();
42 2
            $response = $response->withStatus(200);
43 2
            $response->getBody()->write($body);
44
        }
45
46 4
        if ($response instanceof ResponseInterface && ! $response->hasHeader('content-type')) {
47 4
            $response = $response->withAddedHeader('content-type', 'application/json');
48
        }
49
50 4
        return $response;
51
    }
52
53
    /**
54
     * Check if the response can be converted to json
55
     * Arrays can always be converted, objects can be converted if they're not a response already
56 4
     *
57
     * @param $response
58 4
     *
59
     * @return bool
60
     */
61
    private function isJsonEncodable($response):bool{
62
        if (! (is_array($response) || is_object($response))){
63
            return false;
64 4
        }
65
        return ! ($response instanceof ResponseInterface);
66 4
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getNotFoundDecorator(NotFoundException $exception) : MiddlewareInterface
72
    {
73
        return $this->buildJsonResponseMiddleware($exception);
74
    }
75
76 8
    /**
77
     * {@inheritdoc}
78
     */
79
    public function getMethodNotAllowedDecorator(MethodNotAllowedException $exception) : MiddlewareInterface
80
    {
81
        return $this->buildJsonResponseMiddleware($exception);
82
    }
83
84
    /**
85 8
     * Return a middleware that simply throws and exception.
86 8
     *
87 8
     * @param \Exception $exception
88
     *
89
     * @return \Psr\Http\Server\MiddlewareInterface
90
     */
91
    protected function buildJsonResponseMiddleware(HttpException $exception) : MiddlewareInterface
92
    {
93 8
        return new class($this->responseFactory->createResponse(), $exception) implements MiddlewareInterface
94
        {
95
            protected $response;
96
            protected $exception;
97
98
            public function __construct(ResponseInterface $response, HttpException $exception)
99
            {
100
                $this->response  = $response;
101
                $this->exception = $exception;
102
            }
103
104
            public function process(
105
                ServerRequestInterface $request,
106
                RequestHandlerInterface $requestHandler
107 8
            ) : ResponseInterface {
108
                return $this->exception->buildJsonResponse($this->response);
109 8
            }
110 8
        };
111
    }
112 8
113
    /**
114
     * {@inheritdoc}
115
     */
116
    public function getExceptionHandler() : MiddlewareInterface
117 8
    {
118 8
        return new class($this->responseFactory->createResponse()) implements MiddlewareInterface
119 8
        {
120
            protected $response;
121 8
122 4
            public function __construct(ResponseInterface $response)
123
            {
124
                $this->response = $response;
125 4
            }
126 4
127 4
            public function process(
128
                ServerRequestInterface $request,
129
                RequestHandlerInterface $requestHandler
130 4
            ) : ResponseInterface {
131 4
                try {
132
                    return $requestHandler->handle($request);
133
                } catch (Exception $exception) {
134
                    $response = $this->response;
135
136
                    if ($exception instanceof HttpException) {
137
                        return $exception->buildJsonResponse($response);
138
                    }
139
140
                    $response->getBody()->write(json_encode([
141
                        'status_code'   => 500,
142
                        'reason_phrase' => $exception->getMessage()
143
                    ]));
144
145
                    $response = $response->withAddedHeader('content-type', 'application/json');
146
                    return $response->withStatus(500, strtok($exception->getMessage(), "\n"));
147
                }
148
            }
149
        };
150
    }
151
}
152