Completed
Pull Request — master (#9)
by Hugo
01:44
created

GraphQLClient::doGraphQLRequest()   B

Complexity

Conditions 3
Paths 7

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 24
rs 8.9713
cc 3
eloc 16
nc 7
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yproximite\Api\Client;
6
7
use GuzzleHttp\Psr7\MultipartStream;
8
use Http\Client\HttpClient;
9
use Http\Message\MessageFactory;
10
use Psr\Http\Message\StreamInterface;
11
use Yproximite\Api\Exception\AuthenticationException;
12
use Yproximite\Api\Exception\UploadEmptyFilesException;
13
use Yproximite\Api\Response;
14
use Yproximite\Api\Util\UploadFile;
15
16
class GraphQLClient extends AbstractClient
17
{
18
    private $graphqlEndpoint;
19
    private $authClient;
20
21
    public function __construct(AuthClient $authClient, string $graphqlEndpoint = null, HttpClient $httpClient = null, MessageFactory $messageFactory = null)
22
    {
23
        parent::__construct($httpClient, $messageFactory);
24
25
        $this->authClient      = $authClient;
26
        $this->graphqlEndpoint = $graphqlEndpoint;
27
    }
28
29
    /**
30
     * @throws \Http\Client\Exception
31
     */
32
    public function query(string $query, array $variables = []): Response
33
    {
34
        return $this->doGraphQLRequest($query, $variables);
35
    }
36
37
    /**
38
     * @throws \Http\Client\Exception
39
     */
40
    public function mutation(string $query, array $variables = []): Response
41
    {
42
        return $this->doGraphQLRequest($query, $variables);
43
    }
44
45
    /**
46
     * @throws UploadEmptyFilesException
47
     */
48
    public function upload(int $siteId, array $files = []): Response
49
    {
50
        $normalizedFiles = [];
51
52
        if (0 === \count($files)) {
53
            throw new UploadEmptyFilesException();
54
        }
55
56
        foreach ($files as $k => $file) {
57
            $normalizedFiles[] = new UploadFile($file);
58
        }
59
60
        // @TODO: Implement upload mutation
61
        return $this->doGraphQLRequest('upload ...', ['siteId' => $siteId], $normalizedFiles);
62
    }
63
64
    /**
65
     * @param $files UploadFile[]
66
     *
67
     * @throws \Http\Client\Exception
68
     */
69
    private function doGraphQLRequest(string $query, array $variables = [], array $files = [], string $filesParameterName = 'medias[]'): Response
70
    {
71
        $this->authClient->auth();
72
73
        $headers = $this->computeRequestHeaders();
74
        $body    = $this->computeRequestBody($query, $variables, $files, $filesParameterName);
75
76
        $request = $this->createRequest('POST', $this->graphqlEndpoint, $headers, $body);
77
78
        try {
79
            $response = $this->sendRequest($request);
80
            $contents = $this->extractJson($request, $response);
81
        } catch (AuthenticationException $e) {
82
            $this->authClient->auth(true);
83
            try {
84
                $response = $this->sendRequest($request);
85
                $contents = $this->extractJson($request, $response);
86
            } catch (AuthenticationException $e) {
87
                throw $e;
88
            }
89
        }
90
91
        return new Response($contents);
92
    }
93
94
    private function computeRequestHeaders(): array
95
    {
96
        $headers = ['Accept' => '*/*'];
97
98
        if ($this->authClient->isAuthenticated()) {
99
            $headers['Authorization'] = sprintf('Bearer %s', $this->authClient->getApiToken());
100
        }
101
102
        return $headers;
103
    }
104
105
    private function computeRequestBody(string $query, array $variables = [], array $files = [], string $filesParameterName = 'medias[]'): StreamInterface
106
    {
107
        $data = [
108
            ['name' => 'query', 'contents' => $query],
109
            ['name' => 'variables', 'contents' => json_encode($variables)],
110
        ];
111
112
        foreach ($files as $file) {
113
            $data[] = [
114
                'name'     => $filesParameterName,
115
                'contents' => $file->getContent(),
116
                'filename' => $file->getName(),
117
            ];
118
        }
119
120
        return new MultipartStream($data);
121
    }
122
}
123