Completed
Push — master ( 0e82da...cafa4f )
by Giacomo "Mr. Wolf"
02:53 queued 43s
created

SegmentProvider   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 451
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 55
eloc 169
dl 0
loc 451
rs 6
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
B getItemsDataConsumer() 0 45 7
A getItem() 0 29 6
B getItemsDataProvider() 0 45 7
A create() 0 22 4
B manageClientException() 0 41 9
A delete() 0 20 3
A update() 0 22 4
A __construct() 0 5 1
B getItems() 0 45 7
B getItemsCategory() 0 45 7

How to fix   Complexity   

Complex Class

Complex classes like SegmentProvider often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SegmentProvider, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Audiens\AdForm\Provider;
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
/**
15
 * Class Adform
16
 *
17
 * @package Adform
18
 */
19
class SegmentProvider
20
{
21
    /**
22
     * @var HttpClient
23
     */
24
    protected $httpClient;
25
26
    /**
27
     * @var CacheInterface
28
     */
29
    protected $cache;
30
31
    /**
32
     * @var string
33
     */
34
    protected $cachePrefix = 'segment';
35
36
    /**
37
     * @param HttpClient          $httpClient
38
     * @param CacheInterface|null $cache
39
     */
40
    public function __construct(HttpClient $httpClient, CacheInterface $cache = null)
41
    {
42
        $this->httpClient = $httpClient;
43
44
        $this->cache = $cache;
45
    }
46
47
    /**
48
     * Return a category based on ID
49
     *
50
     * @param int $segmentId ID of the category
51
     *
52
     * @throws EntityNotFoundException if the API call fails
53
     *
54
     * @return Segment
55
     */
56
    public function getItem($segmentId)
57
    {
58
        // Endpoint URI
59
        $uri = sprintf('v1/segments/%d', $segmentId);
60
61
        try {
62
            $data = null;
63
64
            // try to get from cache
65
            if ($this->cache) {
66
                $data = $this->cache->get($this->cachePrefix, $uri, []);
67
            }
68
69
            // load from API
70
            if (!$data) {
71
                $data = $this->httpClient->get($uri)->getBody()->getContents();
72
73
                if ($this->cache and $data) {
74
                    $this->cache->put($this->cachePrefix, $uri, [], $data);
75
                }
76
            }
77
78
            return SegmentHydrator::fromStdClass(json_decode($data));
79
        } catch (ClientException $e) {
80
            $response = $e->getResponse();
81
            $responseBody = $response->getBody()->getContents();
82
            $responseCode = $response->getStatusCode();
83
84
            throw EntityNotFoundException::translate($segmentId, $responseBody, $responseCode);
85
        }
86
    }
87
88
    /**
89
     * Returns an array of segments
90
     *
91
     * @param int $limit
92
     * @param int $offset
93
     *
94
     * @throws ApiException if the API call fails
95
     *
96
     * @return array
97
     */
98
    public function getItems($limit = 1000, $offset = 0)
99
    {
100
        // Endpoint URI
101
        $uri = 'v1/segments';
102
103
        $options = [
104
            'query' => [
105
                'limit' => $limit,
106
                'offset' => $offset,
107
            ],
108
        ];
109
110
        $segments = [];
111
112
        try {
113
            $data = null;
114
115
            // try to get from cache
116
            if ($this->cache) {
117
                $data = $this->cache->get($this->cachePrefix, $uri, $options);
118
            }
119
120
            // load from API
121
            if (!$data) {
122
                $data = $this->httpClient->get($uri, $options)->getBody()->getContents();
123
124
                if ($this->cache and $data) {
125
                    $this->cache->put($this->cachePrefix, $uri, $options, $data);
126
                }
127
            }
128
129
            $classArray = json_decode($data);
130
131
            foreach ($classArray as $class) {
132
                $segments[] = SegmentHydrator::fromStdClass($class);
133
            }
134
        } catch (ClientException $e) {
135
            $response = $e->getResponse();
136
            $responseBody = $response->getBody()->getContents();
137
            $responseCode = $response->getStatusCode();
138
139
            throw ApiException::translate($responseBody, $responseCode);
140
        }
141
142
        return $segments;
143
    }
144
145
    /**
146
     * Returns an array of segments for a Data Provider
147
     *
148
     * @param int $dataProviderId
149
     * @param int $limit
150
     * @param int $offset
151
152
     * @throws ApiException if the API call fails
153
     *
154
     * @return array
155
     */
156
    public function getItemsDataProvider($dataProviderId, $limit = 1000, $offset = 0)
157
    {
158
        // Endpoint URI
159
        $uri = sprintf('v1/dataproviders/%d/segments', $dataProviderId);
160
161
        $options = [
162
            'query' => [
163
                'limit' => $limit,
164
                'offset' => $offset,
165
            ],
166
        ];
167
168
        $segments = [];
169
170
        try {
171
            $data = null;
172
173
            // try to get from cache
174
            if ($this->cache) {
175
                $data = $this->cache->get($this->cachePrefix, $uri, $options);
176
            }
177
178
            // load from API
179
            if (!$data) {
180
                $data = $this->httpClient->get($uri, $options)->getBody()->getContents();
181
182
                if ($this->cache and $data) {
183
                    $this->cache->put($this->cachePrefix, $uri, $options, $data);
184
                }
185
            }
186
187
            $classArray = json_decode($data);
188
189
            foreach ($classArray as $class) {
190
                $segments[] = SegmentHydrator::fromStdClass($class);
191
            }
192
        } catch (ClientException $e) {
193
            $response = $e->getResponse();
194
            $responseBody = $response->getBody()->getContents();
195
            $responseCode = $response->getStatusCode();
196
197
            throw ApiException::translate($responseBody, $responseCode);
198
        }
199
200
        return $segments;
201
    }
202
203
    /**
204
     * Returns an array of segments for a Category
205
     *
206
     * @param int $categoryId
207
     * @param int $limit
208
     * @param int $offset
209
     *
210
     * @throws ApiException if the API call fails
211
     *
212
     * @return array
213
     */
214
    public function getItemsCategory($categoryId, $limit = 1000, $offset = 0)
215
    {
216
        // Endpoint URI
217
        $uri = sprintf('v1/categories/%d/segments', $categoryId);
218
219
        $options = [
220
            'query' => [
221
                'limit' => $limit,
222
                'offset' => $offset,
223
            ],
224
        ];
225
226
        $segments = [];
227
228
        try {
229
            $data = null;
230
231
            // try to get from cache
232
            if ($this->cache) {
233
                $data = $this->cache->get($this->cachePrefix, $uri, $options);
234
            }
235
236
            // load from API
237
            if (!$data) {
238
                $data = $this->httpClient->get($uri, $options)->getBody()->getContents();
239
240
                if ($this->cache and $data) {
241
                    $this->cache->put($this->cachePrefix, $uri, $options, $data);
242
                }
243
            }
244
245
            $classArray = json_decode($data);
246
247
            foreach ($classArray as $class) {
248
                $segments[] = SegmentHydrator::fromStdClass($class);
249
            }
250
        } catch (ClientException $e) {
251
            $response = $e->getResponse();
252
            $responseBody = $response->getBody()->getContents();
253
            $responseCode = $response->getStatusCode();
254
255
            throw ApiException::translate($responseBody, $responseCode);
256
        }
257
258
        return $segments;
259
    }
260
261
    /**
262
     * Returns an array of segments for a Data Consumer
263
     *
264
     * @param int $dataConsumerId
265
     * @param int $limit
266
     * @param int $offset
267
     *
268
     * @throws ApiException if the API call fails
269
     *
270
     * @return array
271
     */
272
    public function getItemsDataConsumer($dataConsumerId, $limit = 1000, $offset = 0)
273
    {
274
        // Endpoint URI
275
        $uri = sprintf('v1/dataconsumers/%d/segments', $dataConsumerId);
276
277
        $options = [
278
            'query' => [
279
                'limit' => $limit,
280
                'offset' => $offset,
281
            ],
282
        ];
283
284
        $segments = [];
285
286
        try {
287
            $data = null;
288
289
            // try to get from cache
290
            if ($this->cache) {
291
                $data = $this->cache->get($this->cachePrefix, $uri, $options);
292
            }
293
294
            // load from API
295
            if (!$data) {
296
                $data = $this->httpClient->get($uri, $options)->getBody()->getContents();
297
298
                if ($this->cache and $data) {
299
                    $this->cache->put($this->cachePrefix, $uri, $options, $data);
300
                }
301
            }
302
303
            $classArray = json_decode($data);
304
305
            foreach ($classArray as $class) {
306
                $segments[] = SegmentHydrator::fromStdClass($class);
307
            }
308
        } catch (ClientException $e) {
309
            $response = $e->getResponse();
310
            $responseBody = $response->getBody()->getContents();
311
            $responseCode = $response->getStatusCode();
312
313
            throw ApiException::translate($responseBody, $responseCode);
314
        }
315
316
        return $segments;
317
    }
318
319
    /**
320
     * Create a category
321
     *
322
     * @param Segment $segment
323
     *
324
     * @throws EntityInvalidException if the API returns a validation error
325
     * @throws ApiException if the API call fails
326
     *
327
     * @return Segment
328
     */
329
    public function create(Segment $segment)
330
    {
331
        // Endpoint URI
332
        $uri = 'v1/segments';
333
334
        $options = [
335
            'json' => $segment,
336
        ];
337
338
        try {
339
            $data = $this->httpClient->post($uri, $options)->getBody()->getContents();
340
341
            $segment = SegmentHydrator::fromStdClass(json_decode($data));
342
343
            if ($this->cache and $data) {
344
                $this->cache->invalidate($this->cachePrefix);
345
                $this->cache->put($this->cachePrefix, $uri.'/'.$segment->getId(), [], $data);
346
            }
347
348
            return $segment;
349
        } catch (ClientException $e) {
350
            $this->manageClientException($e);
351
        }
352
353
    }
354
355
    /**
356
     * Update a category
357
     *
358
     * @param Segment $segment
359
     *
360
     * @throws EntityInvalidException if the API returns a validation error
361
     * @throws ApiException if the API call fails
362
     *
363
     * @return Segment
364
     */
365
    public function update(Segment $segment)
366
    {
367
        // Endpoint URI
368
        $uri = sprintf('v1/segments/%d', $segment->getId());
369
370
        $options = [
371
            'json' => $segment,
372
        ];
373
374
        try {
375
            $data = $this->httpClient->put($uri, $options)->getBody()->getContents();
376
377
            $segment = SegmentHydrator::fromStdClass(json_decode($data));
378
379
            if ($this->cache and $data) {
380
                $this->cache->invalidate($this->cachePrefix);
381
                $this->cache->put($this->cachePrefix, $uri.'/'.$segment->getId(), [], $data);
382
            }
383
384
            return $segment;
385
        } catch (ClientException $e) {
386
            $this->manageClientException($e);
387
        }
388
    }
389
390
    /**
391
     * Delete a category
392
     *
393
     * @param Segment $segment
394
     *
395
     * @throws ApiException if the API call fails
396
     *
397
     * @return Segment
398
     */
399
    public function delete(Segment $segment)
400
    {
401
        // Endpoint URI
402
        $uri = sprintf('v1/segments/%d', $segment->getId());
403
404
        try {
405
406
            $this->httpClient->delete($uri);
407
408
            if ($this->cache) {
409
                $this->cache->invalidate($this->cachePrefix);
410
            }
411
412
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the documented return type Audiens\AdForm\Entity\Segment.
Loading history...
413
        } catch (ClientException $e) {
414
            $response = $e->getResponse();
415
            $responseBody = $response->getBody()->getContents();
416
            $responseCode = $response->getStatusCode();
417
418
            throw ApiException::translate($responseBody, $responseCode);
419
        }
420
421
    }
422
423
    /**
424
     * @param ClientException $exception
425
     *
426
     * @throws EntityInvalidException
427
     * @throws ApiException
428
     */
429
    protected function manageClientException(ClientException $exception)
430
    {
431
        $response = $exception->getResponse();
432
433
        if ($response === null) {
434
            throw $exception;
435
        }
436
437
        $responseBody = $response->getBody()->getContents();
438
        $responseCode = $response->getStatusCode();
439
440
        $error = json_decode($responseBody);
441
442
        // Validation
443
        if (isset($error->modelState)) {
444
            throw EntityInvalidException::invalid($responseBody, $responseCode, $error->modelState);
445
        }
446
447
        if (isset($error->reason, $error->params) && $error->reason === 'validationFailed') {
448
            $errorMessages = [];
449
            foreach ($error->params as $paramName => $paramArr) {
450
                if (!\is_array($paramArr)) {
451
                    $errorMessages[] = $paramName;
452
453
                    continue;
454
                }
455
456
                foreach ($paramArr as $paramObj) {
457
                    $errorMessages[] = isset($paramObj->message) ? $paramObj->message : $paramName;
458
                }
459
            }
460
461
            throw EntityInvalidException::invalid(
462
                $responseBody,
463
                $responseCode,
464
                \implode("\n", $errorMessages)
0 ignored issues
show
Bug introduced by
implode(' ', $errorMessages) of type string is incompatible with the type array expected by parameter $errors of Audiens\AdForm\Exception...lidException::invalid(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

464
                /** @scrutinizer ignore-type */ \implode("\n", $errorMessages)
Loading history...
465
            );
466
        }
467
468
        // Generic exception
469
        throw ApiException::translate($responseBody, $responseCode);
470
    }
471
}
472