Completed
Push — api ( cecea0...116a36 )
by Kamil
29:57 queued 30s
created

ApiPlatformClient::buildCreateRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Sylius\Behat\Client;
15
16
use Sylius\Behat\Service\SharedStorageInterface;
17
use Symfony\Component\BrowserKit\AbstractBrowser;
18
use Symfony\Component\HttpFoundation\Response;
19
use Webmozart\Assert\Assert;
20
21
final class ApiPlatformClient implements ApiClientInterface
22
{
23
    /** @var AbstractBrowser */
24
    private $client;
25
26
    /** @var SharedStorageInterface */
27
    private $sharedStorage;
28
29
    /** @var array */
30
    private $request = ['url' => null, 'body' => []];
31
32
    /** @var array */
33
    private $filters;
34
35
    public function __construct(AbstractBrowser $client, SharedStorageInterface $sharedStorage)
36
    {
37
        $this->client = $client;
38
        $this->sharedStorage = $sharedStorage;
39
    }
40
41
    public function index(string $resource): void
42
    {
43
        $this->request('GET', '/new-api/'.$resource, ['HTTP_ACCEPT' => 'application/ld+json']);
44
    }
45
46
    public function show(string $resource, string $id): void
47
    {
48
        $this->request('GET', sprintf('/new-api/%s/%s', $resource, $id), ['HTTP_ACCEPT' => 'application/ld+json']);
49
    }
50
51
    public function showRelated(string $resource): void
52
    {
53
        $this->request('GET', $this->getResponseContentValue($resource), ['HTTP_ACCEPT' => 'application/ld+json']);
54
    }
55
56
    public function showByIri(string $iri): void
57
    {
58
        $this->request('GET', $iri, ['HTTP_ACCEPT' => 'application/ld+json']);
59
    }
60
61
    public function subResourceIndex(string $resource, string $subResource, string $id): void
62
    {
63
        $this->request('GET', sprintf('/new-api/%s/%s/%s', $resource, $id, $subResource), ['HTTP_ACCEPT' => 'application/ld+json']);
64
    }
65
66
    public function buildCreateRequest(string $resource): void
67
    {
68
        $this->request['url'] = '/new-api/' . $resource;
69
    }
70
71
    public function buildUpdateRequest(string $resource, string $id): void
72
    {
73
        $this->show($resource, $id);
74
75
        $this->request['url'] = sprintf('/new-api/%s/%s', $resource, $id);
76
        $this->request['body'] = json_decode($this->client->getResponse()->getContent(), true);
77
    }
78
79
    public function buildFilter(array $filters): void
80
    {
81
        $this->filters = $filters;
82
    }
83
84
    /** @param string|int $value */
85
    public function addRequestData(string $key, $value): void
86
    {
87
        $this->request['body'][$key] = $value;
88
    }
89
90
    public function addCompoundRequestData(array $data): void
91
    {
92
        $this->request['body'] = array_merge_recursive($this->request['body'], $data);
93
    }
94
95
    public function updateRequestData(array $data): void
96
    {
97
        $this->request['body'] = $this->mergeArraysUniquely($this->request['body'], $data);
98
    }
99
100
    public function create(): void
101
    {
102
        $content = json_encode($this->request['body']);
103
104
        $this->request('POST', $this->request['url'], ['CONTENT_TYPE' => 'application/json'], $content);
105
    }
106
107
    public function update(): void
108
    {
109
        $content = json_encode($this->request['body']);
110
111
        $this->request('PUT', $this->request['url'], ['CONTENT_TYPE' => 'application/ld+json'], $content);
112
    }
113
114
    public function delete(string $resource, string $id): void
115
    {
116
        $this->request('DELETE', sprintf('/new-api/%s/%s', $resource, $id), []);
117
    }
118
119
    public function filter(string $resource): void
120
    {
121
        $query = http_build_query($this->filters, '', '&', PHP_QUERY_RFC3986);
122
        $path = sprintf('/new-api/%s?%s', $resource, $query);
123
124
        $this->request('GET', $path, ['HTTP_ACCEPT' => 'application/ld+json']);
125
    }
126
127
    public function applyTransition(string $resource, string $id, string $transition): void
128
    {
129
        $this->request(
130
            'PATCH',
131
            sprintf('/new-api/%s/%s/%s', $resource, $id, $transition),
132
            ['CONTENT_TYPE' => 'application/merge-patch+json'],
133
            '{}'
134
        );
135
    }
136
137
    public function countCollectionItems(): int
138
    {
139
        return (int) $this->getResponseContentValue('hydra:totalItems');
140
    }
141
142
    public function getCollectionItems(): array
143
    {
144
        return $this->getResponseContentValue('hydra:member');
145
    }
146
147
    public function getCollectionItemsWithValue(string $key, string $value): array
148
    {
149
        $items = array_filter($this->getCollectionItems(), function (array $item) use ($key, $value): bool {
150
            return $item[$key] === $value;
151
        });
152
153
        return $items;
154
    }
155
156
    public function getError(): string
157
    {
158
        return $this->getResponseContentValue('hydra:description');
159
    }
160
161
    public function isCreationSuccessful(): bool
162
    {
163
        return $this->client->getResponse()->getStatusCode() === Response::HTTP_CREATED;
164
    }
165
166
    public function isUpdateSuccessful(): bool
167
    {
168
        return $this->client->getResponse()->getStatusCode() === Response::HTTP_OK;
169
    }
170
171
    public function isDeletionSuccessful(): bool
172
    {
173
        return $this->client->getResponse()->getStatusCode() === Response::HTTP_NO_CONTENT;
174
    }
175
176
    /** @param string|int $value */
177
    public function responseHasValue(string $key, $value): bool
178
    {
179
        return $this->getResponseContentValue($key) === $value;
180
    }
181
182
    /** @param string|int $value */
183
    public function relatedResourceHasValue(string $resource, string $key, $value): bool
184
    {
185
        $this->showRelated($resource);
186
187
        return $this->getResponseContentValue($key) === $value;
188
    }
189
190
    /** @param string|float $value */
191
    public function hasItemWithValue(string $key, $value): bool
192
    {
193
        foreach ($this->getCollectionItems() as $resource) {
194
            if ($resource[$key] === $value) {
195
                return true;
196
            }
197
        }
198
199
        return false;
200
    }
201
202
    public function hasItemOnPositionWithValue(int $position, string $key, string $value): bool
203
    {
204
        return $this->getCollectionItems()[$position][$key] === $value;
205
    }
206
207
    public function hasItemWithTranslation(string $locale, string $key, string $translation): bool
208
    {
209
        foreach ($this->getCollectionItems() as $resource) {
210
            if (
211
                isset($resource['translations']) &&
212
                isset($resource['translations'][$locale]) &&
213
                $resource['translations'][$locale][$key] === $translation
214
            ) {
215
                return true;
216
            }
217
        }
218
219
        return false;
220
    }
221
222
    private function request(string $method, string $url, array $headers, string $content = null): void
223
    {
224
        $defaultHeaders = ['HTTP_ACCEPT' => 'application/ld+json'];
225
        if ($this->sharedStorage->has('token')) {
226
            $defaultHeaders['HTTP_Authorization'] = 'Bearer ' . $this->sharedStorage->get('token');
227
        }
228
229
        $this->client->request($method, $url, [], [], array_merge($defaultHeaders, $headers), $content);
230
    }
231
232
    private function getResponseContentValue(string $key)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
233
    {
234
        $content = json_decode($this->client->getResponse()->getContent(), true);
235
236
        Assert::keyExists($content, $key);
237
238
        return $content[$key];
239
    }
240
241
    private function mergeArraysUniquely(array $firstArray, array $secondArray): array
242
    {
243
        foreach ($secondArray as $key => $value) {
244
            if (is_array($value) && is_array(@$firstArray[$key])) {
245
                $value = $this->mergeArraysUniquely($firstArray[$key], $value);
246
            }
247
            $firstArray[$key] = $value;
248
        }
249
        return $firstArray;
250
    }
251
}
252