Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.27% covered (warning)
87.27%
48 / 55
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
GraphqlWithFileUpload
87.27% covered (warning)
87.27%
48 / 55
0.00% covered (danger)
0.00%
0 / 2
4.03
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getRequest
97.96% covered (success)
97.96%
48 / 49
0.00% covered (danger)
0.00%
0 / 1
3
1<?php
2namespace Apie\IntegrationTests\Graphql;
3
4use Apie\Core\BoundedContext\BoundedContextId;
5use Apie\Core\Entities\EntityInterface;
6use Apie\Core\FileStorage\StoredFile;
7use GuzzleHttp\Psr7\MultipartStream;
8use Nyholm\Psr7\ServerRequest;
9use Psr\Http\Message\ServerRequestInterface;
10use Psr\Http\Message\UploadedFileInterface;
11
12/**
13 * @see https://github.com/jaydenseric/graphql-multipart-request-spec
14 */
15class GraphqlWithFileUpload extends GraphqlProvider
16{
17    /**
18     * @param array<string, mixed> $graphQlQuery
19     * @param array<string, mixed> $expectedResponse
20     * @param array<int, EntityInterface> $entities
21     * @param array<string|int, UploadedFileInterface> $uploadedFiles
22     */
23    public function __construct(
24        BoundedContextId $boundedContextId,
25        array $graphQlQuery,
26        array $expectedResponse,
27        array $entities = [],
28        protected array $uploadedFiles = []
29    ) {
30        parent::__construct(
31            $boundedContextId,
32            $graphQlQuery,
33            $expectedResponse,
34            $entities
35        );
36    }
37
38    public function getRequest(): ServerRequestInterface
39    {
40        $map = [];
41        $files = [];
42        $uploadedFiles = [];
43        foreach ($this->uploadedFiles as $index => $file) {
44            $fileIndex = count($files);
45            $map[$fileIndex] = [$index];
46            $files[] = $file;
47        }
48        $multipart = new MultipartStream([
49            [
50                'name'     => 'operations',
51                'contents' => json_encode($this->graphQlQuery),
52            ],
53            [
54                'name'     => 'map',
55                'contents' => json_encode($map),
56            ],
57            ...array_map(
58                function (UploadedFileInterface $file, int|string $index) {
59                    if (!$file instanceof StoredFile) {
60                        $file = StoredFile::createFromUploadedFile($file);
61                    }
62                    return [
63                        'name' => (string) $index,
64                        'filename' => $file->getClientFilename(),
65                        'headers' => [
66                            'Content-Type' => $file->getClientMediaType(),
67                        ],
68                        'contents' => $file->getContent(),
69                    ];
70                },
71                $this->uploadedFiles,
72                array_keys($this->uploadedFiles)
73            )
74        ]);
75        $request = new ServerRequest(
76            'POST',
77            'http://localhost/' . $this->boundedContextId . '/graphql',
78            [
79                'Content-Type'   => 'multipart/form-data; boundary=' . $multipart->getBoundary(),
80                'Content-Length' => $multipart->getSize(),
81            ],
82            $multipart
83        );
84        $parsedBody = [
85            'operations' => json_encode($this->graphQlQuery),
86            'map' => json_encode($map),
87        ];
88        $request = $request->withParsedBody($parsedBody)
89                         ->withUploadedFiles($files);
90        return $request;
91    }
92}