Test Failed
Push — develop ( d71559...359c84 )
by Brent
06:20 queued 17s
created

Server::run()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Stitcher\Application;
4
5
use GuzzleHttp\Psr7\Request;
6
use GuzzleHttp\Psr7\Response;
7
use GuzzleHttp\Psr7\ServerRequest;
8
use Parsedown;
9
use Stitcher\Exception\Http;
10
use Stitcher\Exception\StitcherException;
11
12
abstract class Server
13
{
14
    /** @var Router */
15
    protected $router;
16
17
    /** @var Request */
18
    protected $request;
19
20
    /** @var Parsedown */
21
    protected $markdownParser;
22
23 3
    public function setRouter(Router $router): Server
24
    {
25 3
        $this->router = $router;
26
27 3
        return $this;
28
    }
29
30 3
    public function setMarkdownParser(Parsedown $markdownParser): Server
31
    {
32 3
        $this->markdownParser = $markdownParser;
33
34 3
        return $this;
35
    }
36
37 4
    public function run(): string
38
    {
39 4
        $response = $this->createResponse();
40
41 4
        return $this->handleResponse($response);
42
    }
43
44 2
    protected function getRequest(): Request
45
    {
46 2
        if (! $this->request) {
47 2
            $this->request = ServerRequest::fromGlobals();
0 ignored issues
show
Documentation Bug introduced by
It seems like \GuzzleHttp\Psr7\ServerRequest::fromGlobals() of type object<Psr\Http\Message\ServerRequestInterface> is incompatible with the declared type object<GuzzleHttp\Psr7\Request> of property $request.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
48
        }
49
50 2
        return $this->request;
51
    }
52
53 2
    protected function getCurrentPath(): string
54
    {
55 2
        $path = $this->getRequest()->getUri()->getPath();
56
57 2
        return $path === '' ? '/' : $path;
58
    }
59
60
    abstract protected function handleStaticRoute(): ?Response;
61
62
    protected function handleDynamicRoute(): ?Response
63
    {
64
        if (! $this->router) {
65
            return null;
66
        }
67
68
        return $this->router->dispatch($this->getRequest());
69
    }
70
71 4
    protected function createResponse(): Response
72
    {
73
        if (
74 4
            $this->router
75
            && $redirectTo = $this->router->getRedirectForUrl($this->getCurrentPath())
76 4
        ) {
77 4
            return $this->redirectResponse($redirectTo);
78
        }
79
80
        try {
81
            $response = $this->handleStaticRoute();
82
83 4
            if (! $response) {
84
                $response = $this->handleDynamicRoute();
85 4
            }
86
        } catch (StitcherException $e) {
87
            $response = $this->responseFromException($e);
88
        }
89
90
        return $response ?? $this->responseFromException(
91
                Http::notFound(
92
                    $this->getCurrentPath()
93
                )
94
            );
95
    }
96
97
    protected function redirectResponse(string $targetUrl): Response
98
    {
99
        return new Response(301, ["Location: {$targetUrl}"]);
100
    }
101
102
    protected function responseFromException(StitcherException $e): Response
103
    {
104
        $statusCode = $e instanceof Http ? $e->statusCode() : 500;
105
106
        $responseBody = file_get_contents(__DIR__ . '/../../static/exception.html');
107
108
        $responseBody = str_replace(
109
            '{{ title }}',
110
            $this->markdownParser->parse($e->title()),
111 4
            $responseBody
112
        );
113 4
114
        $responseBody = str_replace(
115 4
            '{{ body }}',
116
            $this->markdownParser->parse($e->body()),
117
            $responseBody
118
        );
119
120
        return new Response($statusCode, [], $responseBody);
121
    }
122
123
    protected function handleResponse(Response $response): string
124
    {
125
        foreach ($response->getHeaders() as $headers) {
126
            header(implode(', ', $headers));
127
        }
128
129
        http_response_code($response->getStatusCode());
130
131
        return $response->getBody()->getContents();
132
    }
133
}
134