Completed
Push — master ( a73fad...f8ec74 )
by Baptiste
02:31
created

RequestTranslator::doTranslation()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 17
cts 17
cp 1
rs 8.9713
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Rest\ServerBundle\Translator;
5
6
use Innmind\Http\{
7
    Message\ServerRequestInterface,
8
    Message\ServerRequest,
9
    Message\Method,
10
    Message\Environment,
11
    Message\EnvironmentInterface,
12
    Message\Cookies,
13
    Message\CookiesInterface,
14
    Message\Query,
15
    Message\QueryInterface,
16
    Message\Query\ParameterInterface as QueryParameterInterface,
17
    Message\Query\Parameter as QueryParameter,
18
    Message\Form,
19
    Message\FormInterface,
20
    Message\Form\ParameterInterface as FormParameterInterface,
21
    Message\Form\Parameter as FormParameter,
22
    Message\Files,
23
    Message\FilesInterface,
24
    File\File,
25
    File\FileInterface,
26
    File\StatusInterface,
27
    File\OkStatus,
28
    File\ExceedsFormMaxFileSizeStatus,
29
    File\ExceedsIniMaxFileSizeStatus,
30
    File\NoTemporaryDirectoryStatus,
31
    File\NotUploadedStatus,
32
    File\PartiallyUploadedStatus,
33
    File\StoppedByExtensionStatus,
34
    File\WriteFailedStatus,
35
    ProtocolVersion,
36
    Headers,
37
    HeadersInterface,
38
    Header\HeaderInterface,
39
    Factory\Header\DefaultFactory
40
};
41
use Innmind\Filesystem\{
42
    Stream\Stream,
43
    MediaType\MediaType
44
};
45
use Innmind\Url\Url;
46
use Innmind\Immutable\{
47
    Map,
48
    StringPrimitive as Str
49
};
50
use Symfony\Component\HttpFoundation\{
51
    Request,
52
    HeaderBag,
53
    ParameterBag,
54
    FileBag,
55
    ServerBag
56
};
57
58
final class RequestTranslator
59
{
60
    private $transformed;
61
    private $headerFactory;
62
63 3
    public function __construct(DefaultFactory $headerFactory)
64
    {
65 3
        $this->transformed = new Map(
66 3
            Request::class,
67 3
            ServerRequestInterface::class
68
        );
69 3
        $this->headerFactory = $headerFactory;
70 3
    }
71
72 2
    public function translate(Request $request): ServerRequestInterface
73
    {
74 2
        if ($this->transformed->contains($request)) {
75
            return $this->transformed->get($request);
76
        }
77
78 2
        $serverRequest = $this->doTranslation($request);
79 2
        $this->transformed = $this->transformed->put(
80
            $request,
81
            $serverRequest
82
        );
83
84 2
        return $serverRequest;
85
    }
86
87 2
    private function doTranslation(Request $request): ServerRequestInterface
88
    {
89 2
        $protocol = (new Str($request->server->get('SERVER_PROTOCOL')))->getMatches(
90 2
            '~HTTP/(?<major>\d)\.(?<minor>\d)~'
91
        );
92
93 2
        return new ServerRequest(
94 2
            Url::fromString(
95 2
                $request->getSchemeAndHttpHost().'/'.ltrim($request->getPathInfo(), '/')
96
            ),
97 2
            new Method($request->getMethod()),
98 2
            new ProtocolVersion(
99 2
                (int) (string) $protocol['major'],
100 2
                (int) (string) $protocol['minor']
101
            ),
102 2
            $this->translateHeaders($request->headers),
103 2
            new Stream($request->getContent(true)),
104 2
            $this->translateEnvironment($request->server),
105 2
            $this->translateCookies($request->cookies),
106 2
            $this->translateQuery($request->query),
107 2
            $this->translateForm($request->request),
108 2
            $this->translateFiles($request->files)
109
        );
110
    }
111
112 2
    private function translateHeaders(HeaderBag $headerBag): HeadersInterface
113
    {
114 2
        $map = new Map('string', HeaderInterface::class);
115
116 2
        foreach ($headerBag as $name => $value) {
117 1
            $map = $map->put(
118
                $name,
119 1
                $this->headerFactory->make(
120 1
                    new Str($name),
121 1
                    new Str(implode(', ', $value))
122
                )
123
            );
124
        }
125
126 2
        return new Headers($map);
127
    }
128
129 2
    private function translateEnvironment(ServerBag $server): EnvironmentInterface
130
    {
131 2
        $map = new Map('string', 'scalar');
132
133 2
        foreach ($server as $key => $value) {
134 2
            if (!is_scalar($value)) {
135
                continue;
136
            }
137
138 2
            $map = $map->put($key, $value);
139
        }
140
141 2
        return new Environment($map);
142
    }
143
144 2
    private function translateCookies(ParameterBag $cookies): CookiesInterface
145
    {
146 2
        $map = new Map('string', 'scalar');
147
148 2
        foreach ($cookies as $key => $value) {
149 1
            $map = $map->put($key, $value);
150
        }
151
152 2
        return new Cookies($map);
153
    }
154
155 2
    private function translateQuery(ParameterBag $query): QueryInterface
156
    {
157 2
        $map = new Map('string', QueryParameterInterface::class);
158
159 2
        foreach ($query as $key => $value) {
160 1
            $map = $map->put(
161
                $key,
162 1
                new QueryParameter($key, $value)
163
            );
164
        }
165
166 2
        return new Query($map);
167
    }
168
169 2
    private function translateForm(ParameterBag $form): FormInterface
170
    {
171 2
        $map = new Map('scalar', FormParameterInterface::class);
172
173 2
        foreach ($form as $key => $value) {
174 1
            $map = $map->put(
175
                $key,
176 1
                $this->buildFormParameter($key, $value)
177
            );
178
        }
179
180 2
        return new Form($map);
181
    }
182
183 1
    private function buildFormParameter($name, $value): FormParameterInterface
184
    {
185 1
        if (!is_array($value)) {
186 1
            return new FormParameter((string) $name, $value);
187
        }
188
189
        $map = new Map('scalar', FormParameterInterface::class);
190
191
        foreach ($value as $key => $sub) {
192
            $map = $map->put(
193
                $key,
194
                $this->buildFormParameter($key, $sub)
195
            );
196
        }
197
198
        return new FormParameter((string) $name, $map);
199
    }
200
201 2
    private function translateFiles(FileBag $files): FilesInterface
202
    {
203 2
        $map = new Map('string', FileInterface::class);
204
205 2
        foreach ($files as $name => $file) {
206 1
            $map = $map->put(
207
                $name,
208 1
                new File(
209 1
                    $file->getClientOriginalName(),
210 1
                    new Stream(
211 1
                        fopen($file->getPathname(), 'r')
212
                    ),
213 1
                    $this->buildFileStatus($file->getError()),
214 1
                    MediaType::fromString((string) $file->getClientMimeType())
215
                )
216
            );
217
        }
218
219 2
        return new Files($map);
220
    }
221
222 1
    private function buildFileStatus(int $status): StatusInterface
223
    {
224
        switch ($status) {
225 1
            case UPLOAD_ERR_FORM_SIZE:
226
                return new ExceedsFormMaxFileSizeStatus;
227 1
            case UPLOAD_ERR_INI_SIZE:
228
                return new ExceedsIniMaxFileSizeStatus;
229 1
            case UPLOAD_ERR_NO_TMP_DIR:
230
                return new NoTemporaryDirectoryStatus;
231 1
            case UPLOAD_ERR_NO_FILE:
232
                return new NotUploadedStatus;
233 1
            case UPLOAD_ERR_OK:
234 1
                return new OkStatus;
235
            case UPLOAD_ERR_PARTIAL:
236
                return new PartiallyUploadedStatus;
237
            case UPLOAD_ERR_EXTENSION:
238
                return new StoppedByExtensionStatus;
239
            case UPLOAD_ERR_CANT_WRITE:
240
                return new WriteFailedStatus;
241
        }
242
    }
243
}
244