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

GraphQLClient::query()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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