Passed
Push — master ( a15edb...2827e6 )
by Jonathan
03:41
created

AbstractReportingCloud   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 489
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 6

Test Coverage

Coverage 98.54%

Importance

Changes 0
Metric Value
wmc 43
lcom 3
cbo 6
dl 0
loc 489
ccs 135
cts 137
cp 0.9854
rs 8.3157
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
D __construct() 0 30 8
A getClient() 0 22 2
A setClient() 0 6 1
A getBaseUri() 0 8 2
A setBaseUri() 0 6 1
A getTimeout() 0 8 2
A setTimeout() 0 6 1
A getUsername() 0 4 1
A setUsername() 0 6 1
A getPassword() 0 4 1
A setPassword() 0 6 1
A getTest() 0 8 2
A setTest() 0 6 1
A getDebug() 0 8 2
A setDebug() 0 6 1
A uri() 0 4 1
A getVersion() 0 8 2
A setVersion() 0 6 1
B request() 0 27 3
A normalizeArrayKeys() 0 17 4
B assembleMergeSettings() 0 23 5

How to fix   Complexity   

Complex Class

Complex classes like AbstractReportingCloud 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 AbstractReportingCloud, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * ReportingCloud PHP Wrapper
5
 *
6
 * Official wrapper (authored by Text Control GmbH, publisher of ReportingCloud) to access ReportingCloud in PHP.
7
 *
8
 * @link      http://www.reporting.cloud to learn more about ReportingCloud
9
 * @link      https://github.com/TextControl/txtextcontrol-reportingcloud-php for the canonical source repository
10
 * @license   https://raw.githubusercontent.com/TextControl/txtextcontrol-reportingcloud-php/master/LICENSE.md
11
 * @copyright © 2016 Text Control GmbH
12
 */
13
namespace TxTextControl\ReportingCloud;
14
15
use GuzzleHttp\Client;
16
use GuzzleHttp\RequestOptions;
17
use TxTextControl\ReportingCloud\Exception\RuntimeException;
18
use TxTextControl\ReportingCloud\PropertyMap\AbstractPropertyMap as PropertyMap;
19
use TxTextControl\ReportingCloud\Filter\TimestampToDateTime as TimestampToDateTimeFilter;
20
use TxTextControl\ReportingCloud\PropertyMap\MergeSettings as MergeSettingsPropertyMap;
21
use TxTextControl\ReportingCloud\Validator\StaticValidator;
22
23
/**
24
 * Abstract ReportingCloud
25
 *
26
 * @package TxTextControl\ReportingCloud
27
 * @author  Jonathan Maron (@JonathanMaron)
28
 */
29
abstract class AbstractReportingCloud
30
{
31
    /**
32
     * Default date/time format of backend is 'ISO 8601'
33
     *
34
     * Note, last letter is 'P' and not 'O':
35
     *
36
     * O - Difference to Greenwich time (GMT) in hours (e.g. +0200)
37
     * P - Difference to Greenwich time (GMT) with colon between hours and minutes (e.g. +02:00)
38
     *
39
     * Backend uses the 'P' variant
40
     *
41
     * @const DEFAULT_DATE_FORMAT
42
     */
43
    const DEFAULT_DATE_FORMAT = 'Y-m-d\TH:i:sP';
44
45
    /**
46
     * Default time zone of backend
47
     *
48
     * @const DEFAULT_TIME_ZONE
49
     */
50
    const DEFAULT_TIME_ZONE = 'UTC';
51
52
    /**
53
     * Default base URI of backend
54
     *
55
     * @const DEFAULT_BASE_URI
56
     */
57
    const DEFAULT_BASE_URI = 'https://api.reporting.cloud';
58
59
    /**
60
     * Default version string of backend
61
     *
62
     * @const DEFAULT_VERSION
63
     */
64
    const DEFAULT_VERSION = 'v1';
65
66
    /**
67
     * Default timeout of backend in seconds
68
     *
69
     * @const DEFAULT_TIMEOUT
70
     */
71
    const DEFAULT_TIMEOUT = 120; // seconds
72
73
    /**
74
     * Default test flag of backend
75
     *
76
     * @const DEFAULT_TEST
77
     */
78
    const DEFAULT_TEST = false;
79
80
    /**
81
     * Default debug flag of REST client
82
     *
83
     * @const DEFAULT_DEBUG
84
     */
85
    const DEFAULT_DEBUG = false;
86
87
    /**
88
     * Backend username
89
     *
90
     * @var string
91
     */
92
    protected $username;
93
94
    /**
95
     * Backend password
96
     *
97
     * @var string
98
     */
99
    protected $password;
100
101
    /**
102
     * When true, backend prints "TEST MODE" water mark into output document, but API call does not count against quota
103
     *
104
     * @var boolean
105
     */
106
    protected $test;
107
108
    /**
109
     * Backend base URI
110
     *
111
     * @var string
112
     */
113
    protected $baseUri;
114
115
    /**
116
     * Backend version string
117
     *
118
     * @var string
119
     */
120
    protected $version;
121
122
    /**
123
     * Backend timeout in seconds
124
     *
125
     * @var integer
126
     */
127
    protected $timeout;
128
129
    /**
130
     * REST client to backend
131
     *
132
     * @var Client
133
     */
134
    protected $client;
135
136
    /**
137
     * Debug flag of REST client
138
     *
139
     * @var boolean
140
     */
141
    protected $debug;
142
143
    /**
144
     * AbstractReportingCloud constructor
145
     *
146
     * @param array $options
147
     */
148 59
    public function __construct($options = [])
149
    {
150 59
        if (array_key_exists('username', $options)) {
151 1
            $this->setUsername($options['username']);
152 1
        }
153
154 59
        if (array_key_exists('password', $options)) {
155 1
            $this->setPassword($options['password']);
156 1
        }
157
158 59
        if (array_key_exists('test', $options)) {
159 1
            $this->setTest($options['test']);
160 1
        }
161
162 59
        if (array_key_exists('base_uri', $options)) {
163 1
            $this->setBaseUri($options['base_uri']);
164 1
        }
165
166 59
        if (array_key_exists('version', $options)) {
167 1
            $this->setVersion($options['version']);
168 1
        }
169
170 59
        if (array_key_exists('timeout', $options)) {
171 1
            $this->setTimeout($options['timeout']);
172 1
        }
173
174 59
        if (array_key_exists('debug', $options)) {
175 1
            $this->setDebug($options['debug']);
176 1
        }
177 59
    }
178
179
    /**
180
     * Return the REST client of the backend web service
181
     *
182
     * @return \GuzzleHttp\Client
183
     */
184 18
    public function getClient()
185
    {
186 18
        if (null === $this->client) {
187
188 18
            $usernamePassword = sprintf('%s:%s', $this->getUsername(), $this->getPassword());
189 18
            $authorization    = sprintf('Basic %s', base64_encode($usernamePassword));
190
191 18
            $client = new Client([
192 18
                'base_uri'              => $this->getBaseUri(),
193 18
                RequestOptions::TIMEOUT => $this->getTimeout(),
194 18
                RequestOptions::DEBUG   => $this->getDebug(),
195 18
                RequestOptions::HEADERS => [
196 18
                    'Authorization' => $authorization,
197 18
                    'Content-Type' => 'application/json',
198 18
                ],
199 18
            ]);
200
201 18
            $this->setClient($client);
202 18
        }
203
204 18
        return $this->client;
205
    }
206
207
    /**
208
     * Set the REST client of the backend web service
209
     *
210
     * @param Client $client REST client
211
     *
212
     * @return ReportingCloud
213
     */
214 18
    public function setClient(Client $client)
215
    {
216 18
        $this->client = $client;
217
218 18
        return $this;
219
    }
220
221
    /**
222
     * Return the base URI of the backend web service
223
     *
224
     * @return string
225
     */
226 22
    public function getBaseUri()
227
    {
228 22
        if (null === $this->baseUri) {
229 20
            $this->setBaseUri(self::DEFAULT_BASE_URI);
230 20
        }
231
232 22
        return $this->baseUri;
233
    }
234
235
    /**
236
     * Set the base URI of the backend web service
237
     *
238
     * @param string $baseUri Base URI
239
     *
240
     * @return ReportingCloud
241
     */
242 22
    public function setBaseUri($baseUri)
243
    {
244 22
        $this->baseUri = $baseUri;
245
246 22
        return $this;
247
    }
248
249
    /**
250
     * Get the timeout (in seconds) of the backend web service
251
     *
252
     * @return integer
253
     */
254 21
    public function getTimeout()
255
    {
256 21
        if (null === $this->timeout) {
257 19
            $this->setTimeout(self::DEFAULT_TIMEOUT);
258 19
        }
259
260 21
        return $this->timeout;
261
    }
262
263
    /**
264
     * Set the timeout (in seconds) of the backend web service
265
     *
266
     * @param integer $timeout Timeout
267
     *
268
     * @return ReportingCloud
269
     */
270 21
    public function setTimeout($timeout)
271
    {
272 21
        $this->timeout = (integer) $timeout;
273
274 21
        return $this;
275
    }
276
277
    /**
278
     * Return the username
279
     *
280
     * @return string
281
     */
282 21
    public function getUsername()
283
    {
284 21
        return $this->username;
285
    }
286
287
    /**
288
     * Set the username
289
     *
290
     * @param string $username Username
291
     *
292
     * @return ReportingCloud
293
     */
294 56
    public function setUsername($username)
295
    {
296 56
        $this->username = $username;
297
298 56
        return $this;
299
    }
300
301
    /**
302
     * Return the password
303
     *
304
     * @return string
305
     */
306 21
    public function getPassword()
307
    {
308 21
        return $this->password;
309
    }
310
311
    /**
312
     * Set the password
313
     *
314
     * @param string $password Password
315
     *
316
     * @return ReportingCloud
317
     */
318 56
    public function setPassword($password)
319
    {
320 56
        $this->password = $password;
321
322 56
        return $this;
323
    }
324
325
    /**
326
     * Return the test flag
327
     *
328
     * @return mixed
329
     */
330 14
    public function getTest()
331
    {
332 14
        if (null === $this->test) {
333 11
            $this->setTest(self::DEFAULT_TEST);
334 11
        }
335
336 14
        return $this->test;
337
    }
338
339
    /**
340
     * Set the test flag
341
     *
342
     * @param boolean $test Test flag
343
     *
344
     * @return ReportingCloud
345
     */
346 14
    public function setTest($test)
347
    {
348 14
        $this->test = (boolean) $test;
349
350 14
        return $this;
351
    }
352
353
    /**
354
     * Return the debug flag
355
     *
356
     * @return mixed
357
     */
358 21
    public function getDebug()
359
    {
360 21
        if (null === $this->debug) {
361 19
            $this->setDebug(self::DEFAULT_DEBUG);
362 19
        }
363
364 21
        return $this->debug;
365
    }
366
367
    /**
368
     * Set the debug flag
369
     *
370
     * @param boolean $debug Debug flag
371
     *
372
     * @return ReportingCloud
373
     */
374 21
    public function setDebug($debug)
375
    {
376 21
        $this->debug = (boolean) $debug;
377
378 21
        return $this;
379
    }
380
381
    /**
382
     * Construct URI with version number
383
     *
384
     * @param string $uri URI
385
     *
386
     * @return string
387
     */
388 17
    protected function uri($uri)
389
    {
390 17
        return sprintf('/%s%s', $this->getVersion(), $uri);
391
    }
392
393
    /**
394
     * Get the version string of the backend web service
395
     *
396
     * @return string
397
     */
398 20
    public function getVersion()
399
    {
400 20
        if (null === $this->version) {
401 18
            $this->version = self::DEFAULT_VERSION;
402 18
        }
403
404 20
        return $this->version;
405
    }
406
407
    /**
408
     * Set the version string of the backend web service
409
     *
410
     * @param string $version Version string
411
     *
412
     * @return ReportingCloud
413
     */
414 2
    public function setVersion($version)
415
    {
416 2
        $this->version = $version;
417
418 2
        return $this;
419
    }
420
421
    /**
422
     * Request the URI with options
423
     *
424
     * @param string $method  HTTP method
425
     * @param string $uri     URI
426
     * @param array  $options Options
427
     *
428
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
429
     *
430
     * @throws RuntimeException
431
     */
432 17
    protected function request($method, $uri, $options)
433
    {
434 17
        $ret = null;
435
436 17
        $client = $this->getClient();
437
438
        try {
439
440 17
            if (getenv('TRAVIS')) {
441
                $options['curl'][CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_1;
442
            }
443
444 17
            $ret = $client->request($method, $uri, $options);
445
446 17
        } catch (\Exception $exception) {
447
448
            // \GuzzleHttp\Exception\ClientException
449
            // \GuzzleHttp\Exception\ServerException
450
451 1
            $message = (string)  $exception->getMessage();
452 1
            $code    = (integer) $exception->getCode();
453
454 1
            throw new RuntimeException($message, $code);
455
        }
456
457 16
        return $ret;
458
    }
459
460
    /**
461
     * Using the passed propertyMap, recursively normalizes the keys of the passed array
462
     *
463
     * @param array       $array       Array
464
     * @param PropertyMap $propertyMap PropertyMap
465
     *
466
     * @return array
467
     */
468 5
    protected function normalizeArrayKeys($array, PropertyMap $propertyMap)
469
    {
470 5
        $ret = [];
471
472 5
        foreach ($array as $key => $value) {
473 5
            $map = $propertyMap->getMap();
474 5
            if (isset($map[$key])) {
475 5
                $key = $map[$key];
476 5
            }
477 5
            if (is_array($value)) {
478 2
                $value = $this->normalizeArrayKeys($value, $propertyMap);
479 2
            }
480 5
            $ret[$key] = $value;
481 5
        }
482
483 5
        return $ret;
484
    }
485
486
    /**
487
     * Assemble MergeSettings array to pass to ReportingCloud
488
     *
489
     * @param array $mergeSettings MergeSettings array
490
     *
491
     * @return array
492
     */
493 8
    protected function assembleMergeSettings($mergeSettings)
494
    {
495 8
        $ret = [];
496
497 8
        $filter      = new TimestampToDateTimeFilter();
498 8
        $propertyMap = new MergeSettingsPropertyMap();
499
500 8
        foreach ($propertyMap->getMap() as $property => $key) {
501 8
            if (isset($mergeSettings[$key])) {
502 8
                $value = $mergeSettings[$key];
503 8
                if ('remove_' == substr($key, 0, 7)) {
504 6
                    StaticValidator::execute($value, 'TypeBoolean');
505 4
                }
506 8
                if ('_date' == substr($key, -5)) {
507 8
                    StaticValidator::execute($value, 'Timestamp');
508 6
                    $value = $filter->filter($value);
509 6
                }
510 8
                $ret[$property] = $value;
511 8
            }
512 8
        }
513
514 4
        return $ret;
515
    }
516
517
}