Completed
Push — master ( 48e6ef...c5bbe8 )
by Giacomo "Mr. Wolf"
08:19 queued 06:33
created

SegmentManager::getItemsDataProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 13
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php declare(strict_types=1);
2
3
namespace Audiens\AdForm\Manager;
4
5
use Audiens\AdForm\Cache\CacheInterface;
6
use Audiens\AdForm\Entity\Segment;
7
use Audiens\AdForm\Entity\SegmentHydrator;
8
use Audiens\AdForm\Exception\ApiException;
9
use Audiens\AdForm\Exception\EntityInvalidException;
10
use Audiens\AdForm\Exception\EntityNotFoundException;
11
use Audiens\AdForm\HttpClient;
12
use GuzzleHttp\Exception\ClientException;
13
14
class SegmentManager
15
{
16
    /** @var HttpClient */
17
    protected $httpClient;
18
19
    /** @var CacheInterface */
20
    protected $cache;
21
22
    /** @var string */
23
    protected $cachePrefix = 'segment';
24
25
    public function __construct(HttpClient $httpClient, ?CacheInterface $cache = null)
26
    {
27
        $this->httpClient = $httpClient;
28
        $this->cache = $cache;
29
    }
30
31
    /**
32
     * Return a category based on ID
33
     *
34
     * @param int $segmentId ID of the category
35
     *
36
     * @throws EntityNotFoundException if the API call fails
37
     *
38
     * @return Segment
39
     */
40
    public function getItem($segmentId): Segment
41
    {
42
        // Endpoint URI
43
        $uri = sprintf('v1/segments/%d', $segmentId);
44
45
        try {
46
            $data = null;
47
48
            // try to get from cache
49
            if ($this->cache) {
50
                $data = $this->cache->get($this->cachePrefix, $uri, []);
51
            }
52
53
            // load from API
54
            if (!$data) {
55
                $data = $this->httpClient->get($uri)->getBody()->getContents();
56
57
                if ($this->cache && $data) {
58
                    $this->cache->put($this->cachePrefix, $uri, [], $data);
59
                }
60
            }
61
62
            return SegmentHydrator::fromStdClass(json_decode($data));
63
        } catch (ClientException $e) {
64
            $response = $e->getResponse();
65
            if ($response === null) {
66
                throw $e;
67
            }
68
            $responseBody = $response->getBody()->getContents();
69
            $responseCode = $response->getStatusCode();
70
71
            throw EntityNotFoundException::translate($segmentId, $responseBody, $responseCode);
72
        }
73
    }
74
75
    /**
76
     * Returns an array of segments
77
     *
78
     * @param int $limit
79
     * @param int $offset
80
     *
81
     * @throws ApiException if the API call fails
82
     *
83
     * @return Segment[]
84
     */
85
    public function getItems(int $limit = 1000, int $offset = 0): array
86
    {
87
        // Endpoint URI
88
        $uri = 'v1/segments';
89
90
        $options = [
91
            'query' => [
92
                'limit' => $limit,
93
                'offset' => $offset,
94
            ],
95
        ];
96
97
        return $this->getSegmentsFromListEndpoint($uri, $options);
98
    }
99
100
    /**
101
     * Returns an array of segments for a Data Provider
102
     *
103
     * @param int $dataProviderId
104
     * @param int $limit
105
     * @param int $offset
106
107
     * @throws ApiException if the API call fails
108
     *
109
     * @return Segment[]
110
     */
111
    public function getItemsDataProvider(int $dataProviderId, int $limit = 1000, int $offset = 0): array
112
    {
113
        // Endpoint URI
114
        $uri = sprintf('v1/dataproviders/%d/segments', $dataProviderId);
115
116
        $options = [
117
            'query' => [
118
                'limit' => $limit,
119
                'offset' => $offset,
120
            ],
121
        ];
122
123
        return $this->getSegmentsFromListEndpoint($uri, $options);
124
    }
125
126
    /**
127
     * Returns an array of segments for a Category
128
     *
129
     * @param int $categoryId
130
     * @param int $limit
131
     * @param int $offset
132
     *
133
     * @throws ApiException if the API call fails
134
     *
135
     * @return Segment[]
136
     */
137
    public function getItemsCategory(int $categoryId, int $limit = 1000, int $offset = 0): array
138
    {
139
        // Endpoint URI
140
        $uri = sprintf('v1/categories/%d/segments', $categoryId);
141
142
        $options = [
143
            'query' => [
144
                'limit' => $limit,
145
                'offset' => $offset,
146
            ],
147
        ];
148
149
        return $this->getSegmentsFromListEndpoint($uri, $options);
150
    }
151
152
    /**
153
     * Returns an array of segments for a Data Consumer
154
     *
155
     * @param int $dataConsumerId
156
     * @param int $limit
157
     * @param int $offset
158
     *
159
     * @throws ApiException if the API call fails
160
     *
161
     * @return Segment[]
162
     */
163
    public function getItemsDataConsumer(int $dataConsumerId, int $limit = 1000, int $offset = 0): array
164
    {
165
        // Endpoint URI
166
        $uri = sprintf('v1/dataconsumers/%d/segments', $dataConsumerId);
167
168
        $options = [
169
            'query' => [
170
                'limit' => $limit,
171
                'offset' => $offset,
172
            ],
173
        ];
174
175
        return $this->getSegmentsFromListEndpoint($uri, $options);
176
    }
177
178
    /**
179
     * @param string $uri
180
     * @param array  $options
181
     *
182
     * @return array
183
     * @throws ApiException
184
     */
185
    private function getSegmentsFromListEndpoint(string $uri, array $options)
186
    {
187
        $segments = [];
188
189
        try {
190
            $data = null;
191
192
            // try to get from cache
193
            if ($this->cache) {
194
                $data = $this->cache->get($this->cachePrefix, $uri, $options);
195
            }
196
197
            // load from API
198
            if (!$data) {
199
                $data = $this->httpClient->get($uri, $options)->getBody()->getContents();
200
201
                if ($this->cache && $data) {
202
                    $this->cache->put($this->cachePrefix, $uri, $options, $data);
203
                }
204
            }
205
206
            $classArray = \json_decode($data);
207
208
            foreach ($classArray as $class) {
209
                $segments[] = SegmentHydrator::fromStdClass($class);
210
            }
211
        } catch (ClientException $e) {
212
            $response = $e->getResponse();
213
            if ($response === null) {
214
                throw $e;
215
            }
216
            $responseBody = $response->getBody()->getContents();
217
            $responseCode = $response->getStatusCode();
218
219
            throw ApiException::translate($responseBody, $responseCode);
220
        }
221
222
        return $segments;
223
    }
224
225
    /**
226
     * Create a category
227
     *
228
     * @param Segment $segment
229
     *
230
     * @throws EntityInvalidException if the API returns a validation error
231
     * @throws ApiException if the API call fails
232
     *
233
     * @return Segment
234
     */
235
    public function create(Segment $segment): Segment
236
    {
237
        // Endpoint URI
238
        $uri = 'v1/segments';
239
240
        $options = [
241
            'json' => $segment,
242
        ];
243
244
        try {
245
            $data = $this->httpClient->post($uri, $options)->getBody()->getContents();
246
247
            $segment = SegmentHydrator::fromStdClass(json_decode($data));
248
249
            if ($this->cache && $data) {
250
                $this->cache->invalidate($this->cachePrefix);
251
                $this->cache->put($this->cachePrefix, $uri.'/'.$segment->getId(), [], $data);
252
            }
253
        } catch (ClientException $e) {
254
            $this->manageClientException($e);
255
        }
256
257
        return $segment;
258
    }
259
260
    /**
261
     * Update a category
262
     *
263
     * @param Segment $segment
264
     *
265
     * @throws EntityInvalidException if the API returns a validation error
266
     * @throws ApiException if the API call fails
267
     *
268
     * @return Segment
269
     */
270
    public function update(Segment $segment): Segment
271
    {
272
        // Endpoint URI
273
        $uri = sprintf('v1/segments/%d', $segment->getId());
274
275
        $options = [
276
            'json' => $segment,
277
        ];
278
279
        try {
280
            $data = $this->httpClient->put($uri, $options)->getBody()->getContents();
281
282
            $segment = SegmentHydrator::fromStdClass(json_decode($data));
283
284
            if ($this->cache && $data) {
285
                $this->cache->invalidate($this->cachePrefix);
286
                $this->cache->put($this->cachePrefix, $uri.'/'.$segment->getId(), [], $data);
287
            }
288
        } catch (ClientException $e) {
289
            $this->manageClientException($e);
290
        }
291
292
        return $segment;
293
    }
294
295
    /**
296
     * Delete a category
297
     *
298
     * @param Segment $segment
299
     *
300
     * @throws ApiException if the API call fails
301
     *
302
     * @return bool
303
     */
304
    public function delete(Segment $segment): bool
305
    {
306
        // Endpoint URI
307
        $uri = sprintf('v1/segments/%d', $segment->getId());
308
309
        try {
310
311
            $this->httpClient->delete($uri);
312
313
            if ($this->cache) {
314
                $this->cache->invalidate($this->cachePrefix);
315
            }
316
        } catch (ClientException $e) {
317
            $response = $e->getResponse();
318
            if ($response === null) {
319
                throw $e;
320
            }
321
            $responseBody = $response->getBody()->getContents();
322
            $responseCode = $response->getStatusCode();
323
324
            throw ApiException::translate($responseBody, $responseCode);
325
        }
326
327
        return true;
328
    }
329
330
    /**
331
     * @param ClientException $exception
332
     *
333
     * @throws EntityInvalidException
334
     * @throws ApiException
335
     */
336
    protected function manageClientException(ClientException $exception): void
337
    {
338
        $response = $exception->getResponse();
339
340
        if ($response === null) {
341
            throw $exception;
342
        }
343
344
        $responseBody = $response->getBody()->getContents();
345
        $responseCode = $response->getStatusCode();
346
347
        $error = \json_decode($responseBody);
348
349
        // Validation
350
        if (isset($error->modelState)) {
351
            throw EntityInvalidException::invalid($responseBody, $responseCode, $error->modelState);
352
        }
353
354
        if (isset($error->reason, $error->params) && $error->reason === 'validationFailed') {
355
            $errorMessages = [];
356
            foreach ($error->params as $paramName => $paramArr) {
357
                if (!\is_array($paramArr)) {
358
                    $errorMessages[] = $paramName;
359
360
                    continue;
361
                }
362
363
                foreach ($paramArr as $paramObj) {
364
                    $errorMessages[] = $paramObj->message ?? $paramName;
365
                }
366
            }
367
368
            throw EntityInvalidException::invalid(
369
                $responseBody,
370
                $responseCode,
371
                $errorMessages
372
            );
373
        }
374
375
        // Generic exception
376
        throw ApiException::translate($responseBody, $responseCode);
377
    }
378
}
379