Passed
Push — master ( 85a67e...fabbda )
by Jonathan
17:41
created

AbstractReportingCloud::getVersion()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
cc 2
eloc 3
nc 2
nop 0
crap 2
1
<?php
2
3
/**
4
 * ReportingCloud PHP Wrapper
5
 *
6
 * PHP wrapper for ReportingCloud Web API. Authored and supported by Text Control GmbH.
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 © 2018 Text Control GmbH
12
 */
13
14
namespace TxTextControl\ReportingCloud;
15
16
use GuzzleHttp\Client;
17
use GuzzleHttp\Psr7\Response;
18
use GuzzleHttp\RequestOptions;
19
use TxTextControl\ReportingCloud\Exception\InvalidArgumentException;
20
use TxTextControl\ReportingCloud\Exception\RuntimeException;
21
use TxTextControl\ReportingCloud\Filter\StaticFilter;
22
use TxTextControl\ReportingCloud\PropertyMap\AbstractPropertyMap as PropertyMap;
23
use TxTextControl\ReportingCloud\PropertyMap\MergeSettings as MergeSettingsPropertyMap;
24
use TxTextControl\ReportingCloud\Validator\StaticValidator;
25
26
/**
27
 * Abstract ReportingCloud
28
 *
29
 * @package TxTextControl\ReportingCloud
30
 * @author  Jonathan Maron (@JonathanMaron)
31
 */
32
abstract class AbstractReportingCloud
33
{
34
    /**
35
     * Constants
36
     * -----------------------------------------------------------------------------------------------------------------
37
     */
38
39
    /**
40
     * Default date/time format of backend is 'ISO 8601'
41
     *
42
     * Note, last letter is 'P' and not 'O':
43
     *
44
     * O - Difference to Greenwich time (GMT) in hours (e.g. +0200)
45
     * P - Difference to Greenwich time (GMT) with colon between hours and minutes (e.g. +02:00)
46
     *
47
     * Backend uses the 'P' variant
48
     *
49
     * @const DEFAULT_DATE_FORMAT
50
     */
51
    const DEFAULT_DATE_FORMAT = 'Y-m-d\TH:i:sP';
52
53
    /**
54
     * Default time zone of backend
55
     *
56
     * @const DEFAULT_TIME_ZONE
57
     */
58
    const DEFAULT_TIME_ZONE = 'UTC';
59
60
    /**
61
     * Default base URI of backend
62
     *
63
     * @const DEFAULT_BASE_URI
64
     */
65
    const DEFAULT_BASE_URI = 'https://api.reporting.cloud';
66
67
    /**
68
     * Default version string of backend
69
     *
70
     * @const DEFAULT_VERSION
71
     */
72
    const DEFAULT_VERSION = 'v1';
73
74
    /**
75
     * Default timeout of backend in seconds
76
     *
77
     * @const DEFAULT_TIMEOUT
78
     */
79
    const DEFAULT_TIMEOUT = 120;
80
81
    /**
82
     * Default test flag of backend
83
     *
84
     * @const DEFAULT_TEST
85
     */
86
    const DEFAULT_TEST = false;
87
88
    /**
89
     * Default debug flag of REST client
90
     *
91
     * @const DEFAULT_DEBUG
92
     */
93
    const DEFAULT_DEBUG = false;
94
95
    /**
96
     * Properties
97
     * -----------------------------------------------------------------------------------------------------------------
98
     */
99
100
    /**
101
     * Backend API key
102
     *
103
     * @var string|null
104
     */
105
    protected $apiKey;
106
107
    /**
108
     * Backend username
109
     *
110
     * @var string|null
111
     */
112
    protected $username;
113
114
    /**
115
     * Backend password
116
     *
117
     * @var string|null
118
     */
119
    protected $password;
120
121
    /**
122
     * When true, API call does not count against quota
123
     * "TEST MODE" watermark is added to document
124
     *
125
     * @var bool|null
126
     */
127
    protected $test;
128
129
    /**
130
     * Backend base URI
131
     *
132
     * @var string|null
133
     */
134
    protected $baseUri;
135
136
    /**
137
     * Backend version string
138
     *
139
     * @var string|null
140
     */
141
    protected $version;
142
143
    /**
144
     * Backend timeout in seconds
145
     *
146
     * @var int|null
147
     */
148
    protected $timeout;
149
150
    /**
151
     * REST client to backend
152
     *
153
     * @var Client|null
154
     */
155
    protected $client;
156
157
    /**
158
     * Debug flag of REST client
159
     *
160
     * @var bool|null
161
     */
162
    protected $debug;
163
164
    /**
165
     * Constructor Method
166
     * -----------------------------------------------------------------------------------------------------------------
167
     */
168
169
    /**
170
     * ReportingCloud constructor
171
     *
172
     * @param array $options
173
     */
174 132
    public function __construct(array $options = [])
175
    {
176
        $methods = [
177 132
            'api_key'  => 'setApiKey',
178 66
            'base_uri' => 'setBaseUri',
179 66
            'debug'    => 'setDebug',
180 66
            'password' => 'setPassword',
181 66
            'test'     => 'setTest',
182 66
            'timeout'  => 'setTimeout',
183 66
            'username' => 'setUsername',
184 66
            'version'  => 'setVersion',
185 66
        ];
186
187 132
        foreach ($methods as $key => $method) {
188 132
            if (array_key_exists($key, $options)) {
189 67
                $this->$method($options[$key]);
190 1
            }
191 66
        }
192 132
    }
193
194
    /**
195
     * Set and Get Methods
196
     * -----------------------------------------------------------------------------------------------------------------
197
     */
198
199
    /**
200
     * Return the API key
201
     *
202
     * @return string
203
     */
204 48
    public function getApiKey()
205
    {
206 48
        return $this->apiKey;
207
    }
208
209
    /**
210
     * Set the API key
211
     *
212
     * @param string $apiKey API key
213
     *
214
     * @return ReportingCloud
215
     */
216 4
    public function setApiKey($apiKey)
217
    {
218 4
        $this->apiKey = $apiKey;
219
220 4
        return $this;
221
    }
222
223
    /**
224
     * Return the username
225
     *
226
     * @return string
227
     */
228 54
    public function getUsername()
229
    {
230 54
        return $this->username;
231
    }
232
233
    /**
234
     * Set the username
235
     *
236
     * @param string $username Username
237
     *
238
     * @return ReportingCloud
239
     */
240 132
    public function setUsername($username)
241
    {
242 132
        $this->username = $username;
243
244 132
        return $this;
245
    }
246
247
    /**
248
     * Return the password
249
     *
250
     * @return string
251
     */
252 52
    public function getPassword()
253
    {
254 52
        return $this->password;
255
    }
256
257
    /**
258
     * Set the password
259
     *
260
     * @param string $password Password
261
     *
262
     * @return ReportingCloud
263
     */
264 132
    public function setPassword($password)
265
    {
266 132
        $this->password = $password;
267
268 132
        return $this;
269
    }
270
271
    /**
272
     * Return the base URI of the backend web service
273
     *
274
     * @return string
275
     */
276 56
    public function getBaseUri()
277
    {
278 56
        if (null === $this->baseUri) {
279 52
            $this->setBaseUri(self::DEFAULT_BASE_URI);
280 26
        }
281
282 56
        return $this->baseUri;
283
    }
284
285
    /**
286
     * Set the base URI of the backend web service
287
     *
288
     * @param string $baseUri Base URI
289
     *
290
     * @return ReportingCloud
291
     */
292 56
    public function setBaseUri($baseUri)
293
    {
294 56
        $this->baseUri = $baseUri;
295
296 56
        return $this;
297
    }
298
299
    /**
300
     * Get the timeout (in seconds) of the backend web service
301
     *
302
     * @return int
303
     */
304 54
    public function getTimeout()
305
    {
306 54
        if (null === $this->timeout) {
307 50
            $this->setTimeout(self::DEFAULT_TIMEOUT);
308 25
        }
309
310 54
        return $this->timeout;
311
    }
312
313
    /**
314
     * Set the timeout (in seconds) of the backend web service
315
     *
316
     * @param int $timeout Timeout
317
     *
318
     * @return ReportingCloud
319
     */
320 54
    public function setTimeout($timeout)
321
    {
322 54
        $this->timeout = (int) $timeout;
323
324 54
        return $this;
325
    }
326
327
    /**
328
     * Return the debug flag
329
     *
330
     * @return mixed
331
     */
332 54
    public function getDebug()
333
    {
334 54
        if (null === $this->debug) {
335 50
            $this->setDebug(self::DEFAULT_DEBUG);
336 25
        }
337
338 54
        return $this->debug;
339
    }
340
341
    /**
342
     * Set the debug flag
343
     *
344
     * @param bool $debug Debug flag
345
     *
346
     * @return ReportingCloud
347
     */
348 54
    public function setDebug($debug)
349
    {
350 54
        $this->debug = (bool) $debug;
351
352 54
        return $this;
353
    }
354
355
    /**
356
     * Return the test flag
357
     *
358
     * @return mixed
359
     */
360 48
    public function getTest()
361
    {
362 48
        if (null === $this->test) {
363 44
            $this->setTest(self::DEFAULT_TEST);
364 22
        }
365
366 48
        return $this->test;
367
    }
368
369
    /**
370
     * Set the test flag
371
     *
372
     * @param bool $test Test flag
373
     *
374
     * @return ReportingCloud
375
     */
376 48
    public function setTest($test)
377
    {
378 48
        $this->test = (bool) $test;
379
380 48
        return $this;
381
    }
382
383
    /**
384
     * Get the version string of the backend web service
385
     *
386
     * @return string
387
     */
388 52
    public function getVersion()
389
    {
390 52
        if (null === $this->version) {
391 48
            $this->version = self::DEFAULT_VERSION;
392 24
        }
393
394 52
        return $this->version;
395
    }
396
397
    /**
398
     * Set the version string of the backend web service
399
     *
400
     * @param string $version Version string
401
     *
402
     * @return ReportingCloud
403
     */
404 4
    public function setVersion($version)
405
    {
406 4
        $this->version = $version;
407
408 4
        return $this;
409
    }
410
411
     /**
412
     * Return the REST client of the backend web service
413
     *
414
     * @return \GuzzleHttp\Client
415
     */
416 48
    public function getClient()
417
    {
418 48
        if (null === $this->client) {
419
420 48
            $authorization = function () {
421
422 48
                if (!empty($this->getApiKey())) {
423 2
                    return sprintf('ReportingCloud-APIKey %s', $this->getApiKey());
424
                }
425
426 48
                if (!empty($this->getUsername()) && !empty($this->getPassword())) {
427 46
                    $value = sprintf('%s:%s', $this->getUsername(), $this->getPassword());
428 46
                    return sprintf('Basic %s', base64_encode($value));
429
                }
430
431 2
                $message = 'Either the API key, or username and password must be set for authorization';
432 2
                throw new InvalidArgumentException($message);
433 48
            };
434
435
            $options = [
436 48
                'base_uri'              => $this->getBaseUri(),
437 48
                RequestOptions::TIMEOUT => $this->getTimeout(),
438 48
                RequestOptions::DEBUG   => $this->getDebug(),
439 48
                RequestOptions::HEADERS => [
440 48
                    'Authorization' => $authorization(),
441 23
                ],
442 23
            ];
443
444 46
            $client = new Client($options);
445
446 46
            $this->setClient($client);
447 23
        }
448
449 46
        return $this->client;
450
    }
451
452
    /**
453
     * Set the REST client of the backend web service
454
     *
455
     * @param Client $client REST client
456
     *
457
     * @return ReportingCloud
458
     */
459 46
    public function setClient(Client $client)
460
    {
461 46
        $this->client = $client;
462
463 46
        return $this;
464
    }
465
466
    /**
467
     * Utility Methods
468
     * -----------------------------------------------------------------------------------------------------------------
469
     */
470
471
    /**
472
     * Request the URI with options
473
     *
474
     * @param string $method  HTTP method
475
     * @param string $uri     URI
476
     * @param array  $options Options
477
     *
478
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
479
     *
480
     * @throws RuntimeException
481
     */
482 46
    protected function request($method, $uri, $options)
483
    {
484 46
        $client = $this->getClient();
485
486
        try {
487 44
            if ($this->getTest()) {
488 2
                $options[RequestOptions::QUERY]['test'] = StaticFilter::execute($this->getTest(), 'BooleanToString');
489 1
            }
490 44
            $ret = $client->request($method, $uri, $options);
491 24
        } catch (\Exception $exception) {
492
            // \GuzzleHttp\Exception\ClientException
493
            // \GuzzleHttp\Exception\ServerException
494 4
            $message = (string) $exception->getMessage();
495 4
            $code    = (int) $exception->getCode();
496 4
            throw new RuntimeException($message, $code);
497
        }
498
499 42
        return $ret;
500
    }
501
502
    /**
503
     * Construct URI with version number
504
     *
505
     * @param string $uri URI
506
     *
507
     * @return string
508
     */
509 46
    protected function uri($uri)
510
    {
511 46
        return sprintf('/%s%s', $this->getVersion(), $uri);
512
    }
513
514
    /**
515
     * Using the passed propertyMap, recursively build array
516
     *
517
     * @param array       $array       Array
518
     * @param PropertyMap $propertyMap PropertyMap
519
     *
520
     * @return array
521
     */
522 14
    protected function buildPropertyMapArray(array $array, PropertyMap $propertyMap)
523
    {
524 14
        $ret = [];
525
526 14
        foreach ($array as $key => $value) {
527 14
            $map = $propertyMap->getMap();
528 14
            if (isset($map[$key])) {
529 14
                $key = $map[$key];
530 7
            }
531 14
            if (is_array($value)) {
532 6
                $value = $this->buildPropertyMapArray($value, $propertyMap);
533 3
            }
534 14
            $ret[$key] = $value;
535 7
        }
536
537 14
        return $ret;
538
    }
539
540
    /**
541
     * Using passed mergeSettings array, build array for backend
542
     *
543
     * @param array $array MergeSettings array
544
     *
545
     * @return array
546
     */
547 18
    protected function buildMergeSettingsArray(array $array)
548
    {
549 18
        $ret = [];
550
551 18
        $propertyMap = new MergeSettingsPropertyMap();
552
553 18
        foreach ($propertyMap->getMap() as $property => $key) {
554 18
            if (isset($array[$key])) {
555 18
                $value = $array[$key];
556 18
                if ('culture' == $key) {
557 2
                    StaticValidator::execute($value, 'Culture');
558
                }
559 18
                if ('remove_' == substr($key, 0, 7)) {
560 12
                    StaticValidator::execute($value, 'TypeBoolean');
561 4
                }
562 18
                if ('_date' == substr($key, -5)) {
563 18
                    StaticValidator::execute($value, 'Timestamp');
564 14
                    $value = StaticFilter::execute($value, 'TimestampToDateTime');
565 7
                }
566 18
                $ret[$property] = $value;
567 9
            }
568 9
        }
569
570 8
        return $ret;
571
    }
572
573
    /**
574
     * Using passed findAndReplaceData associative array (key-value), build array for backend (list of string arrays)
575
     *
576
     * @param array $array FindAndReplaceData array
577
     *
578
     * @return array
579
     */
580 8
    protected function buildFindAndReplaceDataArray(array $array)
581
    {
582 8
        $ret = [];
583
584 8
        foreach ($array as $key => $value) {
585 8
            array_push($ret, [
586 8
                $key,
587 8
                $value,
588 4
            ]);
589 4
        }
590
591 8
        return $ret;
592
    }
593
594
    /**
595
     * Execute a GET request via REST client
596
     *
597
     * @param string $uri   URI
598
     * @param array  $query Query
599
     *
600
     * @return mixed|null
601
     */
602 32
    protected function get($uri, $query = [])
603
    {
604 32
        $ret = null;
605
606
        $options = [
607 32
            RequestOptions::QUERY => $query,
608 16
        ];
609
610 32
        $response = $this->request('GET', $this->uri($uri), $options);
611
612 30
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
613 30
            $ret = json_decode($response->getBody(), true);
614 15
        }
615
616 30
        return $ret;
617
    }
618
}
619