Passed
Push — master ( 1434a5...a5b1a9 )
by Jonathan
09:22
created

ReportingCloud::mergeDocument()   C

Complexity

Conditions 11
Paths 192

Size

Total Lines 67
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 11

Importance

Changes 7
Bugs 0 Features 0
Metric Value
c 7
b 0
f 0
dl 0
loc 67
ccs 43
cts 43
cp 1
rs 5.4917
cc 11
eloc 34
nc 192
nop 6
crap 11

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\AccountSettings as AccountSettingsPropertyMap;
24
use TxTextControl\ReportingCloud\PropertyMap\ApiKey as ApiKeyPropertyMap;
25
use TxTextControl\ReportingCloud\PropertyMap\IncorrectWord as IncorrectWordMap;
26
use TxTextControl\ReportingCloud\PropertyMap\MergeSettings as MergeSettingsPropertyMap;
27
use TxTextControl\ReportingCloud\PropertyMap\TemplateInfo as TemplateInfoPropertyMap;
28
use TxTextControl\ReportingCloud\PropertyMap\TemplateList as TemplateListPropertyMap;
29
use TxTextControl\ReportingCloud\Validator\StaticValidator;
30
31
/**
32
 * ReportingCloud
33
 *
34
 * @package TxTextControl\ReportingCloud
35
 * @author  Jonathan Maron (@JonathanMaron)
36
 */
37
class ReportingCloud
38
{
39
    /**
40
     * Constants
41
     * -----------------------------------------------------------------------------------------------------------------
42
     */
43
44
    /**
45
     * Default date/time format of backend is 'ISO 8601'
46
     *
47
     * Note, last letter is 'P' and not 'O':
48
     *
49
     * O - Difference to Greenwich time (GMT) in hours (e.g. +0200)
50
     * P - Difference to Greenwich time (GMT) with colon between hours and minutes (e.g. +02:00)
51
     *
52
     * Backend uses the 'P' variant
53
     *
54
     * @const DEFAULT_DATE_FORMAT
55
     */
56
    const DEFAULT_DATE_FORMAT = 'Y-m-d\TH:i:sP';
57
58
    /**
59
     * Default time zone of backend
60
     *
61
     * @const DEFAULT_TIME_ZONE
62
     */
63
    const DEFAULT_TIME_ZONE = 'UTC';
64
65
    /**
66
     * Default base URI of backend
67
     *
68
     * @const DEFAULT_BASE_URI
69
     */
70
    const DEFAULT_BASE_URI = 'https://api.reporting.cloud';
71
72
    /**
73
     * Default version string of backend
74
     *
75
     * @const DEFAULT_VERSION
76
     */
77
    const DEFAULT_VERSION = 'v1';
78
79
    /**
80
     * Default timeout of backend in seconds
81
     *
82
     * @const DEFAULT_TIMEOUT
83
     */
84
    const DEFAULT_TIMEOUT = 120;
85
86
    /**
87
     * Default test flag of backend
88
     *
89
     * @const DEFAULT_TEST
90
     */
91
    const DEFAULT_TEST = false;
92
93
    /**
94
     * Default debug flag of REST client
95
     *
96
     * @const DEFAULT_DEBUG
97
     */
98
    const DEFAULT_DEBUG = false;
99
100
    /**
101
     * Properties
102
     * -----------------------------------------------------------------------------------------------------------------
103
     */
104
105
    /**
106
     * Backend API key
107
     *
108
     * @var string|null
109
     */
110
    protected $apiKey;
111
112
    /**
113
     * Backend username
114
     *
115
     * @var string|null
116
     */
117
    protected $username;
118
119
    /**
120
     * Backend password
121
     *
122
     * @var string|null
123
     */
124
    protected $password;
125
126
    /**
127
     * When true, API call does not count against quota
128
     * "TEST MODE" watermark is added to document
129
     *
130
     * @var bool|null
131
     */
132
    protected $test;
133
134
    /**
135
     * Backend base URI
136
     *
137
     * @var string|null
138
     */
139
    protected $baseUri;
140
141
    /**
142
     * Backend version string
143
     *
144
     * @var string|null
145
     */
146
    protected $version;
147
148
    /**
149
     * Backend timeout in seconds
150
     *
151
     * @var int|null
152
     */
153
    protected $timeout;
154
155
    /**
156
     * REST client to backend
157
     *
158
     * @var Client|null
159
     */
160
    protected $client;
161
162
    /**
163
     * Debug flag of REST client
164
     *
165
     * @var bool|null
166
     */
167
    protected $debug;
168
169
    /**
170
     * Constructor Method
171
     * -----------------------------------------------------------------------------------------------------------------
172
     */
173
174
    /**
175
     * ReportingCloud constructor
176
     *
177
     * @param array $options
178
     */
179 132
    public function __construct(array $options = [])
180
    {
181
        $methods = [
182 132
            'api_key'  => 'setApiKey',
183 66
            'base_uri' => 'setBaseUri',
184 66
            'debug'    => 'setDebug',
185 66
            'password' => 'setPassword',
186 66
            'test'     => 'setTest',
187 66
            'timeout'  => 'setTimeout',
188 66
            'username' => 'setUsername',
189 66
            'version'  => 'setVersion',
190 66
        ];
191
192 132
        foreach ($methods as $key => $method) {
193 132
            if (array_key_exists($key, $options)) {
194 67
                $this->$method($options[$key]);
195 1
            }
196 66
        }
197 132
    }
198
199
    /**
200
     * Set and Get Methods
201
     * -----------------------------------------------------------------------------------------------------------------
202
     */
203
204
    /**
205
     * Return the API key
206
     *
207
     * @return string
208
     */
209 48
    public function getApiKey()
210
    {
211 48
        return $this->apiKey;
212
    }
213
214
    /**
215
     * Set the API key
216
     *
217
     * @param string $apiKey API key
218
     *
219
     * @return ReportingCloud
220
     */
221 4
    public function setApiKey($apiKey)
222
    {
223 4
        $this->apiKey = $apiKey;
224
225 4
        return $this;
226
    }
227
228
    /**
229
     * Return the username
230
     *
231
     * @return string
232
     */
233 54
    public function getUsername()
234
    {
235 54
        return $this->username;
236
    }
237
238
    /**
239
     * Set the username
240
     *
241
     * @param string $username Username
242
     *
243
     * @return ReportingCloud
244
     */
245 132
    public function setUsername($username)
246
    {
247 132
        $this->username = $username;
248
249 132
        return $this;
250
    }
251
252
    /**
253
     * Return the password
254
     *
255
     * @return string
256
     */
257 52
    public function getPassword()
258
    {
259 52
        return $this->password;
260
    }
261
262
    /**
263
     * Set the password
264
     *
265
     * @param string $password Password
266
     *
267
     * @return ReportingCloud
268
     */
269 132
    public function setPassword($password)
270
    {
271 132
        $this->password = $password;
272
273 132
        return $this;
274
    }
275
276
    /**
277
     * Return the base URI of the backend web service
278
     *
279
     * @return string
280
     */
281 56
    public function getBaseUri()
282
    {
283 56
        if (null === $this->baseUri) {
284 52
            $this->setBaseUri(self::DEFAULT_BASE_URI);
285 26
        }
286
287 56
        return $this->baseUri;
288
    }
289
290
    /**
291
     * Set the base URI of the backend web service
292
     *
293
     * @param string $baseUri Base URI
294
     *
295
     * @return ReportingCloud
296
     */
297 56
    public function setBaseUri($baseUri)
298
    {
299 56
        $this->baseUri = $baseUri;
300
301 56
        return $this;
302
    }
303
304
    /**
305
     * Get the timeout (in seconds) of the backend web service
306
     *
307
     * @return int
308
     */
309 54
    public function getTimeout()
310
    {
311 54
        if (null === $this->timeout) {
312 50
            $this->setTimeout(self::DEFAULT_TIMEOUT);
313 25
        }
314
315 54
        return $this->timeout;
316
    }
317
318
    /**
319
     * Set the timeout (in seconds) of the backend web service
320
     *
321
     * @param int $timeout Timeout
322
     *
323
     * @return ReportingCloud
324
     */
325 54
    public function setTimeout($timeout)
326
    {
327 54
        $this->timeout = (int) $timeout;
328
329 54
        return $this;
330
    }
331
332
    /**
333
     * Return the debug flag
334
     *
335
     * @return mixed
336
     */
337 54
    public function getDebug()
338
    {
339 54
        if (null === $this->debug) {
340 50
            $this->setDebug(self::DEFAULT_DEBUG);
341 25
        }
342
343 54
        return $this->debug;
344
    }
345
346
    /**
347
     * Set the debug flag
348
     *
349
     * @param bool $debug Debug flag
350
     *
351
     * @return ReportingCloud
352
     */
353 54
    public function setDebug($debug)
354
    {
355 54
        $this->debug = (bool) $debug;
356
357 54
        return $this;
358
    }
359
360
    /**
361
     * Return the test flag
362
     *
363
     * @return mixed
364
     */
365 48
    public function getTest()
366
    {
367 48
        if (null === $this->test) {
368 44
            $this->setTest(self::DEFAULT_TEST);
369 22
        }
370
371 48
        return $this->test;
372
    }
373
374
    /**
375
     * Set the test flag
376
     *
377
     * @param bool $test Test flag
378
     *
379
     * @return ReportingCloud
380
     */
381 48
    public function setTest($test)
382
    {
383 48
        $this->test = (bool) $test;
384
385 48
        return $this;
386
    }
387
388
    /**
389
     * Get the version string of the backend web service
390
     *
391
     * @return string
392
     */
393 52
    public function getVersion()
394
    {
395 52
        if (null === $this->version) {
396 48
            $this->version = self::DEFAULT_VERSION;
397 24
        }
398
399 52
        return $this->version;
400
    }
401
402
    /**
403
     * Set the version string of the backend web service
404
     *
405
     * @param string $version Version string
406
     *
407
     * @return ReportingCloud
408
     */
409 4
    public function setVersion($version)
410
    {
411 4
        $this->version = $version;
412
413 4
        return $this;
414
    }
415
416
     /**
417
     * Return the REST client of the backend web service
418
     *
419
     * @return \GuzzleHttp\Client
420
     */
421 48
    public function getClient()
422
    {
423 48
        if (null === $this->client) {
424
425 24
            $authorization = function () {
426
427 48
                if (!empty($this->getApiKey())) {
428 2
                    return sprintf('ReportingCloud-APIKey %s', $this->getApiKey());
429
                }
430
431 48
                if (!empty($this->getUsername()) && !empty($this->getPassword())) {
432 46
                    $value = sprintf('%s:%s', $this->getUsername(), $this->getPassword());
433 46
                    return sprintf('Basic %s', base64_encode($value));
434
                }
435
436 2
                $message = 'Either the API key, or username and password must be set for authorization';
437 2
                throw new InvalidArgumentException($message);
438 48
            };
439
440
            $options = [
441 48
                'base_uri'              => $this->getBaseUri(),
442 48
                RequestOptions::TIMEOUT => $this->getTimeout(),
443 48
                RequestOptions::DEBUG   => $this->getDebug(),
444 48
                RequestOptions::HEADERS => [
445 48
                    'Authorization' => $authorization(),
446 23
                ],
447 23
            ];
448
449 46
            $client = new Client($options);
450
451 46
            $this->setClient($client);
452 23
        }
453
454 46
        return $this->client;
455
    }
456
457
    /**
458
     * Set the REST client of the backend web service
459
     *
460
     * @param Client $client REST client
461
     *
462
     * @return ReportingCloud
463
     */
464 46
    public function setClient(Client $client)
465
    {
466 46
        $this->client = $client;
467
468 46
        return $this;
469
    }
470
471
    /**
472
     * Utility Methods
473
     * -----------------------------------------------------------------------------------------------------------------
474
     */
475
476
    /**
477
     * Request the URI with options
478
     *
479
     * @param string $method  HTTP method
480
     * @param string $uri     URI
481
     * @param array  $options Options
482
     *
483
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
484
     *
485
     * @throws RuntimeException
486
     */
487 46
    protected function request($method, $uri, $options)
488
    {
489 46
        $client = $this->getClient();
490
491
        try {
492 44
            if ($this->getTest()) {
493 2
                $options[RequestOptions::QUERY]['test'] = StaticFilter::execute($this->getTest(), 'BooleanToString');
494 1
            }
495 44
            $ret = $client->request($method, $uri, $options);
496 24
        } catch (\Exception $exception) {
497
            // \GuzzleHttp\Exception\ClientException
498
            // \GuzzleHttp\Exception\ServerException
499 4
            $message = (string) $exception->getMessage();
500 4
            $code    = (int) $exception->getCode();
501 4
            throw new RuntimeException($message, $code);
502
        }
503
504 42
        return $ret;
505
    }
506
507
    /**
508
     * Construct URI with version number
509
     *
510
     * @param string $uri URI
511
     *
512
     * @return string
513
     */
514 46
    protected function uri($uri)
515
    {
516 46
        return sprintf('/%s%s', $this->getVersion(), $uri);
517
    }
518
519
    /**
520
     * Using the passed propertyMap, recursively build array
521
     *
522
     * @param array       $array       Array
523
     * @param PropertyMap $propertyMap PropertyMap
524
     *
525
     * @return array
526
     */
527 14
    protected function buildPropertyMapArray(array $array, PropertyMap $propertyMap)
528
    {
529 14
        $ret = [];
530
531 14
        foreach ($array as $key => $value) {
532 14
            $map = $propertyMap->getMap();
533 14
            if (isset($map[$key])) {
534 14
                $key = $map[$key];
535 7
            }
536 14
            if (is_array($value)) {
537 6
                $value = $this->buildPropertyMapArray($value, $propertyMap);
538 3
            }
539 14
            $ret[$key] = $value;
540 7
        }
541
542 14
        return $ret;
543
    }
544
545
    /**
546
     * Using passed mergeSettings array, build array for backend
547
     *
548
     * @param array $array MergeSettings array
549
     *
550
     * @return array
551
     */
552 18
    protected function buildMergeSettingsArray(array $array)
553
    {
554 18
        $ret = [];
555
556 18
        $propertyMap = new MergeSettingsPropertyMap();
557
558 18
        foreach ($propertyMap->getMap() as $property => $key) {
559 18
            if (isset($array[$key])) {
560 18
                $value = $array[$key];
561 18
                if ('culture' == $key) {
562 2
                    StaticValidator::execute($value, 'Culture');
563
                }
564 18
                if ('remove_' == substr($key, 0, 7)) {
565 12
                    StaticValidator::execute($value, 'TypeBoolean');
566 4
                }
567 18
                if ('_date' == substr($key, -5)) {
568 18
                    StaticValidator::execute($value, 'Timestamp');
569 14
                    $value = StaticFilter::execute($value, 'TimestampToDateTime');
570 7
                }
571 18
                $ret[$property] = $value;
572 9
            }
573 9
        }
574
575 8
        return $ret;
576
    }
577
578
    /**
579
     * Using passed findAndReplaceData associative array (key-value), build array for backend (list of string arrays)
580
     *
581
     * @param array $array FindAndReplaceData array
582
     *
583
     * @return array
584
     */
585 8
    protected function buildFindAndReplaceDataArray(array $array)
586
    {
587 8
        $ret = [];
588
589 8
        foreach ($array as $key => $value) {
590 8
            array_push($ret, [
591 8
                $key,
592 8
                $value,
593 4
            ]);
594 4
        }
595
596 8
        return $ret;
597
    }
598
599
    /**
600
     * DELETE Methods
601
     * -----------------------------------------------------------------------------------------------------------------
602
     */
603
604
    /**
605
     * Delete an API key
606
     *
607
     * @param string $key API key
608
     *
609
     * @return bool
610
     */
611 4
    public function deleteApiKey($key)
612
    {
613 4
        $ret = false;
614
615 4
        StaticValidator::execute($key, 'ApiKey');
616
617
        $options = [
618 4
            RequestOptions::QUERY => [
619 4
                'key' => $key,
620 2
            ],
621 2
        ];
622
623 4
        $response = $this->request('DELETE', $this->uri('/account/apikey'), $options);
624
625 4
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
626 4
            $ret = true;
627 2
        }
628
629 4
        return $ret;
630
    }
631
632
    /**
633
     * Delete a template in template storage
634
     *
635
     * @param string $templateName Template name
636
     *
637
     * @throws InvalidArgumentException
638
     *
639
     * @return bool
640
     */
641 22
    public function deleteTemplate($templateName)
642
    {
643 22
        $ret = false;
644
645 22
        StaticValidator::execute($templateName, 'TemplateName');
646
647
        $options = [
648 20
            RequestOptions::QUERY => [
649 20
                'templateName' => $templateName,
650 10
            ],
651 10
        ];
652
653 20
        $response = $this->request('DELETE', $this->uri('/templates/delete'), $options);
654
655 18
        if ($response instanceof Response && 204 === $response->getStatusCode()) {
656 18
            $ret = true;
657 9
        }
658
659 18
        return $ret;
660
    }
661
662
    /**
663
     * GET Methods
664
     * -----------------------------------------------------------------------------------------------------------------
665
     */
666
667
    /**
668
     * Return an associative array of API keys associated with the Reporting Cloud account
669
     *
670
     * @return array|null
671
     */
672 6
    public function getApiKeys()
673
    {
674 6
        $ret = null;
675
676 6
        $propertyMap = new ApiKeyPropertyMap();
677
678 6
        $records = $this->get('/account/apikeys');
679
680 6
        if (is_array($records) && count($records) > 0) {
681 6
            $ret = [];
682 6
            foreach ($records as $record) {
683 6
                $ret[] = $this->buildPropertyMapArray($record, $propertyMap);
684 3
            }
685 3
        }
686
687 6
        return $ret;
688
    }
689
690
    /**
691
     * Check a corpus of text for spelling errors.
692
     *
693
     * Return an array of misspelled words, if spelling errors are found in the corpus of text.
694
     *
695
     * Return null, if no misspelled words are found in the corpus of text.
696
     *
697
     * @param string $text     Corpus of text that should be spell checked
698
     * @param string $language Language of specified text
699
     *
700
     * @return array|null
701
     */
702 2
    public function proofingCheck($text, $language)
703
    {
704 2
        $ret = null;
705
706 2
        StaticValidator::execute($text, 'TypeString');
707 2
        StaticValidator::execute($language, 'Language');
708
709 2
        $propertyMap = new IncorrectWordMap();
710
711
        $query = [
712 2
            'text'     => $text,
713 2
            'language' => $language,
714 1
        ];
715
716 2
        $records = $this->get('/proofing/check', $query);
717
718 2
        if (is_array($records) && count($records) > 0) {
719 2
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
720 1
        }
721
722 2
        return $ret;
723
    }
724
725
    /**
726
     * Return an array of available dictionaries on the Reporting Cloud service
727
     *
728
     * @return array|null
729
     */
730 2
    public function getAvailableDictionaries()
731
    {
732 2
        $ret = null;
733
734 2
        $dictionaries = $this->get('/proofing/availabledictionaries');
735
736 2
        if (is_array($dictionaries) && count($dictionaries) > 0) {
737 2
            $ret = array_map('trim', $dictionaries);
738 1
        }
739
740 2
        return $ret;
741
    }
742
743
    /**
744
     * Return an array of suggestions for a misspelled word.
745
     *
746
     * @param string $word     Word that should be spell checked
747
     * @param string $language Language of specified text
748
     * @param int    $max      Maximum number of suggestions to return
749
     *
750
     * @return array|null
751
     */
752 2
    public function getProofingSuggestions($word, $language, $max = 10)
753
    {
754 2
        $ret = null;
755
756 2
        StaticValidator::execute($word, 'TypeString');
757 2
        StaticValidator::execute($language, 'Language');
758 2
        StaticValidator::execute($max, 'TypeInteger');
759
760
        $query = [
761 2
            'word'     => $word,
762 2
            'language' => $language,
763 2
            'max'      => $max,
764 1
        ];
765
766 2
        $records = $this->get('/proofing/suggestions', $query);
767
768 2
        if (is_array($records) && count($records) > 0) {
769 2
            $ret = array_map('trim', $records);
770 1
        }
771
772 2
        return $ret;
773
    }
774
775
    /**
776
     * Return an array of merge blocks and merge fields in a template file in template storage.
777
     *
778
     * @param string $templateName Template name
779
     *
780
     * @throws InvalidArgumentException
781
     *
782
     * @return array|null
783
     */
784 2
    public function getTemplateInfo($templateName)
785
    {
786 2
        $ret = null;
787
788 2
        $propertyMap = new TemplateInfoPropertyMap();
789
790 2
        StaticValidator::execute($templateName, 'TemplateName');
791
792
        $query = [
793 2
            'templateName' => $templateName,
794 1
        ];
795
796 2
        $records = $this->get('/templates/info', $query);
797
798 2
        if (is_array($records) && count($records) > 0) {
799 2
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
800 1
        }
801
802 2
        return $ret;
803
    }
804
805
    /**
806
     * Return an array of binary data.
807
     * Each record in the array is the binary data of a thumbnail image
808
     *
809
     * @param string $templateName Template name
810
     * @param int    $zoomFactor   Zoom factor
811
     * @param int    $fromPage     From page
812
     * @param int    $toPage       To page
813
     * @param string $imageFormat  Image format
814
     *
815
     * @throws InvalidArgumentException
816
     *
817
     * @return array|null
818
     */
819 12
    public function getTemplateThumbnails($templateName, $zoomFactor, $fromPage, $toPage, $imageFormat)
820
    {
821 12
        $ret = null;
822
823 12
        StaticValidator::execute($templateName, 'TemplateName');
824 10
        StaticValidator::execute($zoomFactor, 'ZoomFactor');
825 8
        StaticValidator::execute($fromPage, 'Page');
826 6
        StaticValidator::execute($toPage, 'Page');
827 4
        StaticValidator::execute($imageFormat, 'ImageFormat');
828
829
        $query = [
830 2
            'templateName' => $templateName,
831 2
            'zoomFactor'   => $zoomFactor,
832 2
            'fromPage'     => $fromPage,
833 2
            'toPage'       => $toPage,
834 2
            'imageFormat'  => $imageFormat,
835 1
        ];
836
837 2
        $records = $this->get('/templates/thumbnails', $query);
838
839 2
        if (is_array($records) && count($records) > 0) {
840 2
            $ret = array_map('base64_decode', $records);
841 1
        }
842
843 2
        return $ret;
844
    }
845
846
    /**
847
     * Return the number of templates in template storage
848
     *
849
     * @return int
850
     */
851 2
    public function getTemplateCount()
852
    {
853 2
        return (int) $this->get('/templates/count');
854
    }
855
856
    /**
857
     * Return an array properties for the templates in template storage
858
     *
859
     * @return array|null
860
     */
861 2
    public function getTemplateList()
862
    {
863 2
        $ret = null;
864
865 2
        $propertyMap = new TemplateListPropertyMap();
866
867 2
        $records = $this->get('/templates/list');
868
869 2
        if (is_array($records) && count($records) > 0) {
870 2
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
871 2
            array_walk($ret, function (&$record) {
872 2
                $key = 'modified';
873 2
                if (isset($record[$key])) {
874 2
                    $record[$key] = StaticFilter::execute($record[$key], 'DateTimeToTimestamp');
875 1
                }
876 2
            });
877 1
        }
878
879 2
        return $ret;
880
    }
881
882
    /**
883
     * Return the number of pages in a template in template storage
884
     *
885
     * @param string $templateName Template name
886
     *
887
     * @throws InvalidArgumentException
888
     *
889
     * @return int
890
     */
891 4
    public function getTemplatePageCount($templateName)
892
    {
893 4
        StaticValidator::execute($templateName, 'TemplateName');
894
895
        $query = [
896 2
            'templateName' => $templateName,
897 1
        ];
898
899 2
        return (int) $this->get('/templates/pagecount', $query);
900
    }
901
902
    /**
903
     * Return true, if the template exists in template storage
904
     *
905
     * @param string $templateName Template name
906
     *
907
     * @throws InvalidArgumentException
908
     *
909
     * @return bool
910
     */
911 4
    public function templateExists($templateName)
912
    {
913 4
        StaticValidator::execute($templateName, 'TemplateName');
914
915
        $query = [
916 2
            'templateName' => $templateName,
917 1
        ];
918
919 2
        return (bool) $this->get('/templates/exists', $query);
920
    }
921
922
    /**
923
     * Return an array of available fonts on the Reporting Cloud service
924
     *
925
     * @return array|null
926
     */
927 6
    public function getFontList()
928
    {
929 6
        $ret = null;
930
931 6
        $fonts = $this->get('/fonts/list');
932
933 4
        if (is_array($fonts) && count($fonts) > 0) {
934 4
            $ret = array_map('trim', $fonts);
935 2
        }
936
937 4
        return $ret;
938
    }
939
940
    /**
941
     * Return an array properties for the ReportingCloud account
942
     *
943
     * @throws \Zend\Filter\Exception\ExceptionInterface
944
     *
945
     * @return array|null
946
     */
947 2
    public function getAccountSettings()
948
    {
949 2
        $ret = null;
950
951 2
        $propertyMap = new AccountSettingsPropertyMap();
952
953 2
        $records = $this->get('/account/settings');
954
955 2
        if (is_array($records) && count($records) > 0) {
956 2
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
957 2
            $key = 'valid_until';
958 2
            if ($ret[$key]) {
959 2
                $ret[$key] = StaticFilter::execute($ret[$key], 'DateTimeToTimestamp');
960 1
            }
961 1
        }
962
963 2
        return $ret;
964
    }
965
966
    /**
967
     * Download the binary data of a template from template storage
968
     *
969
     * @param string $templateName Template name
970
     *
971
     * @throws InvalidArgumentException
972
     *
973
     * @return string|null
974
     */
975 4
    public function downloadTemplate($templateName)
976
    {
977 4
        $ret = null;
978
979 4
        StaticValidator::execute($templateName, 'TemplateName');
980
981
        $query = [
982 2
            'templateName' => $templateName,
983 1
        ];
984
985 2
        $data = $this->get('/templates/download', $query);
986
987 2
        if (null !== $data) {
988 2
            $ret = base64_decode($data);
989 1
        }
990
991 2
        return $ret;
992
    }
993
994
    /**
995
     * Execute a GET request via REST client
996
     *
997
     * @param string $uri   URI
998
     * @param array  $query Query
999
     *
1000
     * @return mixed|null
1001
     */
1002 32
    protected function get($uri, $query = [])
1003
    {
1004 32
        $ret = null;
1005
1006
        $options = [
1007 32
            RequestOptions::QUERY => $query,
1008 16
        ];
1009
1010 32
        $response = $this->request('GET', $this->uri($uri), $options);
1011
1012 30
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
1013 30
            $ret = json_decode($response->getBody(), true);
1014 15
        }
1015
1016 30
        return $ret;
1017
    }
1018
1019
    /**
1020
     * POST Methods
1021
     * -----------------------------------------------------------------------------------------------------------------
1022
     */
1023
1024
    /**
1025
     * Upload a template to template storage
1026
     *
1027
     * @param string $templateFilename Template name
1028
     *
1029
     * @throws InvalidArgumentException
1030
     *
1031
     * @return bool
1032
     */
1033 26
    public function uploadTemplate($templateFilename)
1034
    {
1035 26
        $ret = false;
1036
1037 26
        StaticValidator::execute($templateFilename, 'TemplateExtension');
1038 20
        StaticValidator::execute($templateFilename, 'FileExists');
1039
1040 18
        $templateFilename = realpath($templateFilename);
1041 18
        $templateName     = basename($templateFilename);
1042
1043
        $query = [
1044 18
            'templateName' => $templateName,
1045 9
        ];
1046
1047 18
        $json = file_get_contents($templateFilename);
1048 18
        $json = base64_encode($json);
1049
1050
        $options = [
1051 18
            RequestOptions::QUERY => $query,
1052 18
            RequestOptions::JSON  => $json,
1053 9
        ];
1054
1055 18
        $response = $this->request('POST', $this->uri('/templates/upload'), $options);
1056
1057 18
        if ($response instanceof Response && 201 === $response->getStatusCode()) {
1058 18
            $ret = true;
1059 9
        }
1060
1061 18
        return $ret;
1062
    }
1063
1064
    /**
1065
     * Convert a document on the local file system to a different format
1066
     *
1067
     * @param string $documentFilename Document filename
1068
     * @param string $returnFormat     Return format
1069
     *
1070
     * @throws InvalidArgumentException
1071
     *
1072
     * @return string|null
1073
     */
1074 12
    public function convertDocument($documentFilename, $returnFormat)
1075
    {
1076 12
        $ret = null;
1077
1078 12
        StaticValidator::execute($documentFilename, 'DocumentExtension');
1079 6
        StaticValidator::execute($documentFilename, 'FileExists');
1080 4
        StaticValidator::execute($returnFormat, 'ReturnFormat');
1081
1082
        $query = [
1083 2
            'returnFormat' => $returnFormat,
1084 1
        ];
1085
1086 2
        $documentFilename = realpath($documentFilename);
1087
1088 2
        $json = file_get_contents($documentFilename);
1089 2
        $json = base64_encode($json);
1090
1091
        $options = [
1092 2
            RequestOptions::QUERY => $query,
1093 2
            RequestOptions::JSON  => $json,
1094 1
        ];
1095
1096 2
        $response = $this->request('POST', $this->uri('/document/convert'), $options);
1097
1098 2
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
1099 2
            $ret = base64_decode($response->getBody());
1100 1
        }
1101
1102 2
        return $ret;
1103
    }
1104
1105
    /**
1106
     * Merge data into a template and return an array of binary data.
1107
     * Each record in the array is the binary data of one document
1108
     *
1109
     * @param array  $mergeData        Array of merge data
1110
     * @param string $returnFormat     Return format
1111
     * @param string $templateName     Template name
1112
     * @param string $templateFilename Template filename on local file system
1113
     * @param bool   $append           Append flag
1114
     * @param array  $mergeSettings    Array of merge settings
1115
     *
1116
     * @throws InvalidArgumentException
1117
     *
1118
     * @return array|null
1119
     */
1120 28
    public function mergeDocument(
1121
        $mergeData,
1122
        $returnFormat,
1123
        $templateName = null,
1124
        $templateFilename = null,
1125
        $append = null,
1126
        $mergeSettings = []
1127
    ) {
1128 28
        $ret = null;
1129
1130 28
        StaticValidator::execute($mergeData, 'TypeArray');
1131 28
        StaticValidator::execute($returnFormat, 'ReturnFormat');
1132
1133 26
        if (null !== $templateName) {
1134 4
            StaticValidator::execute($templateName, 'TemplateName');
1135 1
        }
1136
1137 24
        if (null !== $templateFilename) {
1138 22
            StaticValidator::execute($templateFilename, 'TemplateExtension');
1139 16
            StaticValidator::execute($templateFilename, 'FileExists');
1140 14
            $templateFilename = realpath($templateFilename);
1141 7
        }
1142
1143 16
        if (null !== $append) {
1144 14
            $append = StaticFilter::execute($append, 'BooleanToString');
1145 6
        }
1146
1147 14
        StaticValidator::execute($mergeSettings, 'TypeArray');
1148
1149
        $query = [
1150 12
            'returnFormat' => $returnFormat,
1151 12
            'append'       => $append,
1152 6
        ];
1153
1154 12
        if (null !== $templateName) {
1155 2
            $query['templateName'] = $templateName;
1156 1
        }
1157
1158
        $json = [
1159 12
            'mergeData' => $mergeData,
1160 6
        ];
1161
1162 12
        if (null !== $templateFilename) {
1163 10
            $template         = file_get_contents($templateFilename);
1164 10
            $template         = base64_encode($template);
1165 10
            $json['template'] = $template;
1166 5
        }
1167
1168 12
        if (count($mergeSettings) > 0) {
1169 10
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
1170 2
        }
1171
1172
        $options = [
1173 6
            RequestOptions::QUERY => $query,
1174 6
            RequestOptions::JSON  => $json,
1175 3
        ];
1176
1177 6
        $response = $this->request('POST', $this->uri('/document/merge'), $options);
1178
1179 6
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
1180 6
            $body = json_decode($response->getBody(), true);
1181 6
            if (is_array($body) && count($body) > 0) {
1182 6
                $ret = array_map('base64_decode', $body);
1183 3
            }
1184 3
        }
1185
1186 6
        return $ret;
1187
    }
1188
1189
    /**
1190
     * Perform find and replace in document and return binary data.
1191
     *
1192
     * @param array  $findAndReplaceData Array of find and replace data
1193
     * @param string $returnFormat       Return format
1194
     * @param string $templateName       Template name
1195
     * @param string $templateFilename   Template filename on local file system
1196
     * @param array  $mergeSettings      Array of merge settings
1197
     *
1198
     * @throws InvalidArgumentException
1199
     *
1200
     * @return string|null
1201
     */
1202 22
    public function findAndReplaceDocument(
1203
        $findAndReplaceData,
1204
        $returnFormat,
1205
        $templateName = null,
1206
        $templateFilename = null,
1207
        $mergeSettings = []
1208
    ) {
1209 22
        $ret = null;
1210
1211 22
        StaticValidator::execute($findAndReplaceData, 'TypeArray');
1212 22
        StaticValidator::execute($returnFormat, 'ReturnFormat');
1213
1214 20
        if (null !== $templateName) {
1215 4
            StaticValidator::execute($templateName, 'TemplateName');
1216 1
        }
1217
1218 18
        if (null !== $templateFilename) {
1219 16
            StaticValidator::execute($templateFilename, 'TemplateExtension');
1220 10
            StaticValidator::execute($templateFilename, 'FileExists');
1221 8
            $templateFilename = realpath($templateFilename);
1222 4
        }
1223
1224 10
        StaticValidator::execute($mergeSettings, 'TypeArray');
1225
1226
        $query = [
1227 8
            'returnFormat' => $returnFormat,
1228 4
        ];
1229
1230 8
        if (null !== $templateName) {
1231 2
            $query['templateName'] = $templateName;
1232 1
        }
1233
1234
        $json = [
1235 8
            'findAndReplaceData' => $this->buildFindAndReplaceDataArray($findAndReplaceData),
1236 4
        ];
1237
1238 8
        if (null !== $templateFilename) {
1239 6
            $template         = file_get_contents($templateFilename);
1240 6
            $template         = base64_encode($template);
1241 6
            $json['template'] = $template;
1242 3
        }
1243
1244 8
        if (count($mergeSettings) > 0) {
1245 8
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
1246 2
        }
1247
1248
        $options = [
1249 4
            RequestOptions::QUERY => $query,
1250 4
            RequestOptions::JSON  => $json,
1251 2
        ];
1252
1253 4
        $response = $this->request('POST', $this->uri('/document/findandreplace'), $options);
1254
1255 4
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
1256 4
            $ret = base64_decode($response->getBody());
1257 2
        }
1258
1259 4
        return $ret;
1260
    }
1261
1262
    /**
1263
     * PUT Methods
1264
     * -----------------------------------------------------------------------------------------------------------------
1265
     */
1266
1267
    /**
1268
     * Create an API key
1269
     *
1270
     * @return string|null
1271
     */
1272 6
    public function createApiKey()
1273
    {
1274 6
        $ret = null;
1275
1276 6
        $response = $this->request('PUT', $this->uri('/account/apikey'), []);
1277
1278 6
        if ($response instanceof Response && 201 === $response->getStatusCode()) {
1279 6
            $ret = (string) json_decode($response->getBody(), true);
1280 6
            StaticValidator::execute($ret, 'ApiKey');
1281 3
        }
1282
1283 6
        return $ret;
1284
    }
1285
}
1286