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

CategoryProvider   B

Complexity

Total Complexity 48

Size/Duplication

Total Lines 394
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 48
eloc 146
dl 0
loc 394
rs 8.5599
c 0
b 0
f 0

9 Methods

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

How to fix   Complexity   

Complex Class

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

407
                /** @scrutinizer ignore-type */ \implode("\n", $errorMessages)
Loading history...
408
            );
409
        }
410
411
        // Generic exception
412
        throw ApiException::translate($responseBody, $responseCode);
413
    }
414
}
415