Completed
Pull Request — master (#202)
by Woody
02:13
created

JsonStrategy::getContentType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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