Completed
Pull Request — master (#178)
by Phil
01:48
created

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

Complexity

Total Complexity 2

Size/Duplication

Total Lines 18
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 100%

Importance

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