Completed
Push — master ( b2aef0...c91c69 )
by Jonathan
04:05
created

ReportingCloud   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 545
Duplicated Lines 27.34 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 83%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 55
lcom 1
cbo 7
dl 149
loc 545
ccs 205
cts 247
cp 0.83
rs 6.8
c 6
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getTemplateInfo() 0 20 3
B getTemplateThumbnails() 0 29 4
A getTemplateCount() 0 4 1
B getTemplateList() 21 21 5
A getTemplatePageCount() 10 10 1
A templateExists() 10 10 1
B getAccountSettings() 21 21 5
A downloadTemplate() 0 18 2
A get() 0 19 3
B deleteTemplate() 0 24 3
B uploadTemplate() 33 33 3
B convertDocument() 34 34 3
F mergeDocument() 10 79 13
B findAndReplace() 10 60 8

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like ReportingCloud 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 ReportingCloud, 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\Psr7\Response;
16
use GuzzleHttp\RequestOptions;
17
use TxTextControl\ReportingCloud\Exception\InvalidArgumentException;
18
use TxTextControl\ReportingCloud\Filter\DateTimeToTimestamp as DateTimeToTimestampFilter;
19
use TxTextControl\ReportingCloud\PropertyMap\AccountSettings as AccountSettingsPropertyMap;
20
use TxTextControl\ReportingCloud\PropertyMap\TemplateInfo as TemplateInfoPropertyMap;
21
use TxTextControl\ReportingCloud\PropertyMap\TemplateList as TemplateListPropertyMap;
22
use TxTextControl\ReportingCloud\Validator\StaticValidator;
23
24
/**
25
 * ReportingCloud
26
 *
27
 * @package TxTextControl\ReportingCloud
28
 * @author  Jonathan Maron (@JonathanMaron)
29
 */
30
class ReportingCloud extends AbstractReportingCloud
31
{
32
33
    /**
34
     * GET methods
35
     * =================================================================================================================
36
     */
37
38
    /**
39
     * Return an array of merge blocks and merge fields in a template file in template storage.
40
     *
41
     * @param string  $templateName Template name
42
     *
43
     * @throws InvalidArgumentException
44
     *
45
     * @return array|null
46
     */
47 1
    public function getTemplateInfo($templateName)
48
    {
49 1
        $ret = null;
50
51 1
        $propertyMap = new TemplateInfoPropertyMap();
52
53 1
        StaticValidator::execute($templateName, 'TemplateName');
54
55
        $query = [
56 1
            'templateName' => $templateName,
57 1
        ];
58
59 1
        $records = $this->get('/templates/info', $query);
60
61 1
        if (is_array($records) && count($records) > 0) {
62 1
            $ret = $this->normalizeArrayKeys($records, $propertyMap);
63 1
        }
64
65 1
        return $ret;
66
    }
67
68
    /**
69
     * Return an array of binary data.
70
     * Each record in the array is the binary data of a thumbnail image
71
     *
72
     * @param string  $templateName Template name
73
     * @param integer $zoomFactor   Zoom factor
74
     * @param integer $fromPage     From page
75
     * @param integer $toPage       To page
76
     * @param string  $imageFormat  Image format
77
     *
78
     * @throws InvalidArgumentException
79
     *
80
     * @return array|null
81
     */
82 6
    public function getTemplateThumbnails($templateName, $zoomFactor, $fromPage, $toPage, $imageFormat)
83
    {
84 6
        $ret = null;
85
86 6
        StaticValidator::execute($templateName, 'TemplateName');
87 5
        StaticValidator::execute($zoomFactor  , 'ZoomFactor');
88 4
        StaticValidator::execute($fromPage    , 'Page');
89 3
        StaticValidator::execute($toPage      , 'Page');
90 2
        StaticValidator::execute($imageFormat , 'ImageFormat');
91
92
        $query = [
93 1
            'templateName' => $templateName,
94 1
            'zoomFactor'   => $zoomFactor,
95 1
            'fromPage'     => $fromPage,
96 1
            'toPage'       => $toPage,
97 1
            'imageFormat'  => $imageFormat,
98 1
        ];
99
100 1
        $records = $this->get('/templates/thumbnails', $query);
101
102 1
        if (is_array($records) && count($records) > 0) {
103 1
            $ret = [];
104 1
            foreach ($records as $index => $data) {
105 1
                $ret[$index] = base64_decode($data);
106 1
            }
107 1
        }
108
109 1
        return $ret;
110
    }
111
112
    /**
113
     * Return the number of templates in template storage
114
     *
115
     * @return integer|null
116
     */
117 1
    public function getTemplateCount()
118
    {
119 1
        return $this->get('/templates/count');
120
    }
121
122
    /**
123
     * Return an array properties for the templates in template storage
124
     *
125
     * @return array|null
126
     */
127 1 View Code Duplication
    public function getTemplateList()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
128
    {
129 1
        $ret = null;
130
131 1
        $propertyMap = new TemplateListPropertyMap();
132 1
        $filter      = new DateTimeToTimestampFilter();
133
134 1
        $records = $this->get('/templates/list');
135
136 1
        if (is_array($records) && count($records) > 0) {
137 1
            $ret = $this->normalizeArrayKeys($records, $propertyMap);
138 1
            foreach ($ret as $index => $record) {
139 1
                $key = 'modified';
140 1
                if (isset($record[$key])) {
141 1
                    $ret[$index][$key] = $filter->filter($record[$key]);
142 1
                }
143 1
            }
144 1
        }
145
146 1
        return $ret;
147
    }
148
149
    /**
150
     * Return the number of pages in a template in template storage
151
     *
152
     * @param string $templateName Template name
153
     *
154
     * @throws InvalidArgumentException
155
     *
156
     * @return bool
157
     */
158 2 View Code Duplication
    public function getTemplatePageCount($templateName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
159
    {
160 2
        StaticValidator::execute($templateName, 'TemplateName');
161
162
        $query = [
163 1
            'templateName' => $templateName,
164 1
        ];
165
166 1
        return (integer) $this->get('/templates/pagecount', $query);
167
    }
168
169
    /**
170
     * Return true, if the template exists in template storage
171
     *
172
     * @param string $templateName Template name
173
     *
174
     * @throws InvalidArgumentException
175
     *
176
     * @return bool
177
     */
178 2 View Code Duplication
    public function templateExists($templateName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
    {
180 2
        StaticValidator::execute($templateName, 'TemplateName');
181
182
        $query = [
183 1
            'templateName' => $templateName,
184 1
        ];
185
186 1
        return (boolean) $this->get('/templates/exists', $query);
187
    }
188
189
    /**
190
     * Return an array properties for the ReportingCloud account
191
     *
192
     * @return array|null
193
     */
194 1 View Code Duplication
    public function getAccountSettings()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
    {
196 1
        $ret = null;
197
198 1
        $propertyMap = new AccountSettingsPropertyMap();
199 1
        $filter      = new DateTimeToTimestampFilter();
200
201 1
        $records = $this->get('/account/settings');
202
203 1
        if (is_array($records) && count($records) > 0) {
204 1
            $ret = $this->normalizeArrayKeys($records, $propertyMap);
205 1
            foreach ($ret as $index => $record) {
206 1
                $key = 'valid_until';
207 1
                if (isset($record[$key])) {
208
                    $ret[$index][$key] = $filter->filter($record[$key]);
209
                }
210 1
            }
211 1
        }
212
213 1
        return $ret;
214
    }
215
216
    /**
217
     * Download the binary data of a template from template storage
218
     *
219
     * @param string $templateName Template name
220
     *
221
     * @throws InvalidArgumentException
222
     *
223
     * @return null|resource
224
     */
225 2
    public function downloadTemplate($templateName)
226
    {
227 2
        $ret = null;
228
229 2
        StaticValidator::execute($templateName, 'TemplateName');
230
231
        $query = [
232 1
            'templateName' => $templateName,
233 1
        ];
234
235 1
        $data = $this->get('/templates/download', $query);
236
237 1
        if (null !== $data) {
238 1
            $ret = base64_decode($data);
239 1
        }
240
241 1
        return $ret;
242
    }
243
244
    /**
245
     * Execute a GET request via REST client
246
     *
247
     * @param string $uri   URI
248
     * @param array  $query Query
249
     *
250
     * @return mixed|null
251
     */
252 8
    protected function get($uri, $query = [])
253
    {
254 8
        $ret = null;
255
256
        $options = [
257 8
            RequestOptions::QUERY => $query,
258 8
        ];
259
260 8
        $response = $this->request('GET', $this->uri($uri), $options);
261
262 8
        if ($response instanceof Response) {
263 8
            if (200 === $response->getStatusCode()) {
264 8
                $body = (string) $response->getBody();
265 8
                $ret  = json_decode($body, true);
266 8
            }
267 8
        }
268
269 8
        return $ret;
270
    }
271
272
273
    /**
274
     * POST methods
275
     * =================================================================================================================
276
     */
277
278
    /**
279
     * Upload a template to template storage
280
     *
281
     * @param string $templateFilename Template name
282
     *
283
     * @throws InvalidArgumentException
284
     *
285
     * @return bool
286
     */
287 12 View Code Duplication
    public function uploadTemplate($templateFilename)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
288
    {
289 12
        $ret = false;
290
291 12
        StaticValidator::execute($templateFilename, 'TemplateExtension');
292 9
        StaticValidator::execute($templateFilename, 'FileExists');
293
294 8
        $templateFilename = realpath($templateFilename);
295 8
        $templateName     = basename($templateFilename);
296
297
        $query = [
298 8
            'templateName' => $templateName,
299 8
        ];
300
301 8
        $body = file_get_contents($templateFilename);
302 8
        $body = base64_encode($body);
303 8
        $body = json_encode($body);
304
305
        $options = [
306 8
            RequestOptions::QUERY => $query,
307 8
            RequestOptions::BODY  => $body,
308 8
        ];
309
310 8
        $response = $this->request('POST', $this->uri('/templates/upload'), $options);
311
312 8
        if ($response instanceof Response) {
313 8
            if (201 === $response->getStatusCode()) {
314 8
                $ret = true;
315 8
            }
316 8
        }
317
318 8
        return $ret;
319
    }
320
321
    /**
322
     * Convert a document on the local file system to a different format
323
     *
324
     * @param string $documentFilename Document filename
325
     * @param string $returnFormat     Return format
326
     *
327
     * @throws InvalidArgumentException
328
     *
329
     * @return null|resource
330
     */
331 6 View Code Duplication
    public function convertDocument($documentFilename, $returnFormat)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
332
    {
333 6
        $ret = null;
334
335 6
        StaticValidator::execute($documentFilename, 'DocumentExtension');
336 3
        StaticValidator::execute($documentFilename, 'FileExists');
337 2
        StaticValidator::execute($returnFormat    , 'ReturnFormat');
338
339
        $query = [
340 1
            'returnFormat' => $returnFormat,
341 1
        ];
342
343 1
        $documentFilename = realpath($documentFilename);
344
345 1
        $body = file_get_contents($documentFilename);
346 1
        $body = base64_encode($body);
347 1
        $body = json_encode($body);
348
349
        $options = [
350 1
            RequestOptions::QUERY => $query,
351 1
            RequestOptions::BODY  => $body,
352 1
        ];
353
354 1
        $response = $this->request('POST', $this->uri('/document/convert'), $options);
355
356 1
        if ($response instanceof Response) {
357 1
            if (200 === $response->getStatusCode()) {
358 1
                $body = (string) $response->getBody();
359 1
                $ret  = base64_decode($body);
360 1
            }
361 1
        }
362
363 1
        return $ret;
364
    }
365
366
    /**
367
     * Merge data into a template and return an array of binary data.
368
     * Each record in the array is the binary data of one document
369
     *
370
     * @param array   $mergeData         Array of merge data
371
     * @param string  $returnFormat      Return format
372
     * @param string  $templateName      Template name
373
     * @param string  $templateFilename  Template filename on local file system
374
     * @param boolean $append            Append flag
375
     * @param array   $mergeSettings     Array of merge settings
376
     *
377
     * @throws InvalidArgumentException
378
     *
379
     * @return null|string
380
     */
381 13
    public function mergeDocument($mergeData, $returnFormat, $templateName = null, $templateFilename = null,
382
                                    $append = null, $mergeSettings = [])
383
    {
384 13
        $ret = null;
385
386 13
        StaticValidator::execute($mergeData   , 'TypeArray');
387 13
        StaticValidator::execute($returnFormat, 'ReturnFormat');
388
389 12
        if (null !== $templateName) {
390 2
            StaticValidator::execute($templateName, 'TemplateName');
391 1
        }
392
393 11 View Code Duplication
        if (null !== $templateFilename) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
394 10
            StaticValidator::execute($templateFilename, 'TemplateExtension');
395 7
            StaticValidator::execute($templateFilename, 'FileExists');
396 6
            $templateFilename = realpath($templateFilename);
397 6
        }
398
399
        // This boolean value MUST be passed as a string to prevent Guzzle converting the
400
        // query parameter to ?append=0 or ?append=1, which the backend does not recognize.
401
        // The backend only recognizes query parameter ?append=true and ?append=false.
402 7
        if (null !== $append) {
403 6
            StaticValidator::execute($append, 'TypeBoolean');
404 5
            if (true === $append) {
405 1
                $append = 'true';
406 1
            } else {
407 4
                $append = 'false';
408
            }
409 6
        }
410
411 6
        StaticValidator::execute($mergeSettings, 'TypeArray');
412
413
        $query = [
414 5
            'returnFormat' => $returnFormat,
415 5
            'append'       => $append,
416 5
        ];
417
418 5
        if (null !== $templateName) {
419 1
            $query['templateName'] = $templateName;
420 1
        }
421
422
        $mergeBody = [
423 5
            'mergeData' => $mergeData,
424 5
        ];
425
426 5 View Code Duplication
        if (null !== $templateFilename) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
427 4
            $template = file_get_contents($templateFilename);
428 4
            $template = base64_encode($template);
429 4
            $mergeBody['template'] = $template;
430 4
        }
431
432 5
        if (count($mergeSettings) > 0) {
433 4
            $mergeBody['mergeSettings'] = $this->assembleMergeSettings($mergeSettings);
434 2
        }
435
436 3
        $body = json_encode($mergeBody);
437
438
        $options = [
439 3
            RequestOptions::QUERY => $query,
440 3
            RequestOptions::BODY  => $body,
441 3
        ];
442
443 3
        $response = $this->request('POST', $this->uri('/document/merge'), $options);
444
445 3
        if ($response instanceof Response) {
446 3
            if (200 === $response->getStatusCode()) {
447 3
                $body = (string) $response->getBody();
448 3
                $body = json_decode($body);
449 3
                if (is_array($body) && count($body) > 0) {
450 3
                    $ret = [];
451 3
                    foreach ($body as $record) {
452 3
                        array_push($ret, base64_decode($record));
453 3
                    }
454 3
                }
455 3
            }
456 3
        }
457
458 3
        return $ret;
459
    }
460
461
    /**
462
     * Perform find and replace in template and return binary data.
463
     *
464
     * @param array   $findAndReplaceData  Array of find and replace data
465
     * @param string  $returnFormat        Return format
466
     * @param string  $templateName        Template name
467
     * @param string  $templateFilename    Template filename on local file system
468
     * @param array   $mergeSettings       Array of merge settings
469
     *
470
     * @throws InvalidArgumentException
471
     *
472
     * @return null|string
473
     */
474
    public function findAndReplace($findAndReplaceData, $returnFormat, $templateName = null, $templateFilename = null,
475
                                   $mergeSettings = [])
476
    {
477
        $ret = null;
478
479
        StaticValidator::execute($findAndReplaceData, 'TypeArray');
480
        StaticValidator::execute($returnFormat      , 'ReturnFormat');
481
482
        if (null !== $templateName) {
483
            StaticValidator::execute($templateName, 'TemplateName');
484
        }
485
486 View Code Duplication
        if (null !== $templateFilename) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
487
            StaticValidator::execute($templateFilename, 'TemplateExtension');
488
            StaticValidator::execute($templateFilename, 'FileExists');
489
            $templateFilename = realpath($templateFilename);
490
        }
491
492
        StaticValidator::execute($mergeSettings, 'TypeArray');
493
494
        $query = [
495
            'returnFormat' => $returnFormat,
496
        ];
497
498
        if (null !== $templateName) {
499
            $query['templateName'] = $templateName;
500
        }
501
502
        $findAndReplaceBody = [
503
            'findAndReplaceData' => $findAndReplaceData,
504
        ];
505
506 View Code Duplication
        if (null !== $templateFilename) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
507
            $template = file_get_contents($templateFilename);
508
            $template = base64_encode($template);
509
            $findAndReplaceBody['template'] = $template;
510
        }
511
512
        if (count($mergeSettings) > 0) {
513
            $findAndReplaceBody['mergeSettings'] = $this->assembleMergeSettings($mergeSettings);
514
        }
515
516
        $body = json_encode($findAndReplaceBody);
517
518
        $options = [
519
            RequestOptions::QUERY => $query,
520
            RequestOptions::BODY  => $body,
521
        ];
522
523
        $response = $this->request('POST', $this->uri('/document/findandreplace'), $options);
524
525
        if ($response instanceof Response) {
526
            if (200 === $response->getStatusCode()) {
527
                $body = (string) $response->getBody();
528
                $ret = base64_decode($body);
529
            }
530
        }
531
532
        return $ret;
533
    }
534
535
536
    /**
537
     * DELETE methods
538
     * =================================================================================================================
539
     */
540
541
    /**
542
     * Delete a template in template storage
543
     *
544
     * @param string $templateName Template name
545
     *
546
     * @throws InvalidArgumentException
547
     *
548
     * @return bool
549
     */
550 10
    public function deleteTemplate($templateName)
551
    {
552 10
        $ret = false;
553
554 10
        StaticValidator::execute($templateName, 'TemplateName');
555
556
        $query = [
557 9
            'templateName' => $templateName,
558 9
        ];
559
560
        $options = [
561 9
            RequestOptions::QUERY => $query,
562 9
        ];
563
564 9
        $response = $this->request('DELETE', $this->uri('/templates/delete'), $options);
565
566 8
        if ($response instanceof Response) {
567 8
            if (204 === $response->getStatusCode()) {
568 8
                $ret = true;
569 8
            }
570 8
        }
571
572 8
        return $ret;
573
    }
574
}