Completed
Push — master ( 1f6fb4...84726b )
by Adrien
11:01
created

UploadMiddleware::validateParsedBody()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 12
cts 12
cp 1
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 11
nc 4
nop 1
crap 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQL\Upload;
6
7
use GraphQL\Error\InvariantViolation;
8
use GraphQL\Server\RequestError;
9
use GraphQL\Utils\Utils;
10
use Interop\Http\Server\MiddlewareInterface;
11
use Interop\Http\Server\RequestHandlerInterface;
12
use Psr\Http\Message\ResponseInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
15
class UploadMiddleware implements MiddlewareInterface
16
{
17 8
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
18
    {
19 8
        $contentType = $request->getHeader('content-type')[0] ?? '';
20
21 8
        if (mb_stripos($contentType, 'multipart/form-data') !== false) {
22 7
            $this->validateParsedBody($request);
23 4
            $request = $this->parseUploadedFiles($request);
24
        }
25
26 4
        return $handler->handle($request);
27
    }
28
29
    /**
30
     * Inject uploaded files defined in the 'map' key into the 'variables' key
31
     *
32
     * @param ServerRequestInterface $request
33
     *
34
     * @return ServerRequestInterface
35
     */
36 4
    private function parseUploadedFiles(ServerRequestInterface $request): ServerRequestInterface
37
    {
38 4
        $bodyParams = $request->getParsedBody();
39 4
        if (!isset($bodyParams['map'])) {
40 1
            throw new RequestError('The request must define a `map`');
41
        }
42
43 3
        $map = json_decode($bodyParams['map'], true);
44 3
        $result = json_decode($bodyParams['operations'], true);
45 3
        $result['operation'] = $result['operationName'];
46 3
        unset($result['operationName']);
47
48 3
        foreach ($map as $fileKey => $locations) {
49 2
            foreach ($locations as $location) {
50 2
                $items = &$result;
51 2
                foreach (explode('.', $location) as $key) {
52 2
                    if (!isset($items[$key]) || !is_array($items[$key])) {
53 2
                        $items[$key] = [];
54
                    }
55 2
                    $items = &$items[$key];
56
                }
57
58 2
                $items = $request->getUploadedFiles()[$fileKey];
59
            }
60
        }
61
62
        return $request
63 3
            ->withHeader('content-type', 'application/json')
64 3
            ->withParsedBody($result);
65
    }
66
67 7
    private function validateParsedBody(ServerRequestInterface $request): void
68
    {
69 7
        $bodyParams = $request->getParsedBody();
70
71 7
        if (null === $bodyParams) {
72 1
            throw new InvariantViolation(
73 1
                'PSR-7 request is expected to provide parsed body for "multipart/form-data" requests but got null'
74
            );
75
        }
76
77 6
        if (!is_array($bodyParams)) {
78 1
            throw new RequestError(
79 1
                'GraphQL Server expects JSON object or array, but got ' . Utils::printSafeJson($bodyParams)
80
            );
81
        }
82
83 5
        if (empty($bodyParams)) {
84 1
            throw new InvariantViolation(
85 1
                'PSR-7 request is expected to provide parsed body for "multipart/form-data" requests but got empty array'
86
            );
87
        }
88 4
    }
89
}
90