Completed
Push — master ( 85642f...03f790 )
by Jonathan
03:58
created

ReportingCloud   B

Complexity

Total Complexity 50

Size/Duplication

Total Lines 507
Duplicated Lines 16.96 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 99.07%

Importance

Changes 14
Bugs 0 Features 0
Metric Value
wmc 50
c 14
b 0
f 0
lcom 1
cbo 7
dl 86
loc 507
ccs 212
cts 214
cp 0.9907
rs 8.6206

14 Methods

Rating   Name   Duplication   Size   Complexity  
A getTemplateInfo() 0 20 3
B getTemplateThumbnails() 3 26 3
A getTemplateCount() 0 4 1
A getTemplateList() 20 20 4
A getTemplatePageCount() 10 10 1
A templateExists() 10 10 1
A getAccountSettings() 20 20 4
A downloadTemplate() 0 18 2
A get() 0 16 3
B uploadTemplate() 0 30 3
B convertDocument() 0 30 3
C mergeDocument() 13 63 11
A deleteTemplate() 0 22 3
B findAndReplaceDocument() 10 55 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\PropertyMap\AccountSettings as AccountSettingsPropertyMap;
19
use TxTextControl\ReportingCloud\PropertyMap\TemplateInfo as TemplateInfoPropertyMap;
20
use TxTextControl\ReportingCloud\PropertyMap\TemplateList as TemplateListPropertyMap;
21
use TxTextControl\ReportingCloud\Validator\StaticValidator;
22
use TxTextControl\ReportingCloud\Filter\StaticFilter;
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->buildPropertyMapArray($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 View Code Duplication
        if (is_array($records) && count($records) > 0) {
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...
103 1
            $ret = array_map('base64_decode', $records);
104 1
        }
105
106 1
        return $ret;
107
    }
108
109
    /**
110
     * Return the number of templates in template storage
111
     *
112
     * @return integer
113
     */
114 1
    public function getTemplateCount()
115
    {
116 1
        return (integer) $this->get('/templates/count');
117
    }
118
119
    /**
120
     * Return an array properties for the templates in template storage
121
     *
122
     * @return array|null
123
     */
124 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...
125
    {
126 1
        $ret = null;
127
128 1
        $propertyMap = new TemplateListPropertyMap();
129
130 1
        $records = $this->get('/templates/list');
131
132 1
        if (is_array($records) && count($records) > 0) {
133 1
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
134
            array_walk($ret, function (&$record) {
135 1
                $key = 'modified';
136 1
                if (isset($record[$key])) {
137 1
                    StaticFilter::execute($record[$key], 'DateTimeToTimestamp');
138 1
                }
139 1
            });
140 1
        }
141
142 1
        return $ret;
143
    }
144
145
    /**
146
     * Return the number of pages in a template in template storage
147
     *
148
     * @param string $templateName Template name
149
     *
150
     * @throws InvalidArgumentException
151
     *
152
     * @return integer
153
     */
154 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...
155
    {
156 2
        StaticValidator::execute($templateName, 'TemplateName');
157
158
        $query = [
159 1
            'templateName' => $templateName,
160 1
        ];
161
162 1
        return (integer) $this->get('/templates/pagecount', $query);
163
    }
164
165
    /**
166
     * Return true, if the template exists in template storage
167
     *
168
     * @param string $templateName Template name
169
     *
170
     * @throws InvalidArgumentException
171
     *
172
     * @return bool
173
     */
174 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...
175
    {
176 2
        StaticValidator::execute($templateName, 'TemplateName');
177
178
        $query = [
179 1
            'templateName' => $templateName,
180 1
        ];
181
182 1
        return (boolean) $this->get('/templates/exists', $query);
183
    }
184
185
    /**
186
     * Return an array properties for the ReportingCloud account
187
     *
188
     * @return array|null
189
     */
190 3 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...
191
    {
192 3
        $ret = null;
193
194 3
        $propertyMap = new AccountSettingsPropertyMap();
195
196 3
        $records = $this->get('/account/settings');
197
198 3
        if (is_array($records) && count($records) > 0) {
199 3
            $ret = $this->buildPropertyMapArray($records, $propertyMap);
200 3
            array_walk($ret, function (&$record) {
201 3
                $key = 'valid_until';
202 3
                if (isset($record[$key])) {
203
                    StaticFilter::execute($record[$key], 'DateTimeToTimestamp');
204
                }
205 3
            });
206 3
        }
207
208 3
        return $ret;
209
    }
210
211
    /**
212
     * Download the binary data of a template from template storage
213
     *
214
     * @param string $templateName Template name
215
     *
216
     * @throws InvalidArgumentException
217
     *
218
     * @return null|resource
219
     */
220 2
    public function downloadTemplate($templateName)
221
    {
222 2
        $ret = null;
223
224 2
        StaticValidator::execute($templateName, 'TemplateName');
225
226
        $query = [
227 1
            'templateName' => $templateName,
228 1
        ];
229
230 1
        $data = $this->get('/templates/download', $query);
231
232 1
        if (null !== $data) {
233 1
            $ret = base64_decode($data);
234 1
        }
235
236 1
        return $ret;
237
    }
238
239
    /**
240
     * Execute a GET request via REST client
241
     *
242
     * @param string $uri   URI
243
     * @param array  $query Query
244
     *
245
     * @return mixed|null
246
     */
247 10
    protected function get($uri, $query = [])
248
    {
249 10
        $ret = null;
250
251
        $options = [
252 10
            RequestOptions::QUERY => $query,
253 10
        ];
254
255 10
        $response = $this->request('GET', $this->uri($uri), $options);
256
257 10
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
258 10
            $ret  = json_decode($response->getBody(), true);
259 10
        }
260
261 10
        return $ret;
262
    }
263
264
265
    /**
266
     * POST methods
267
     * =================================================================================================================
268
     */
269
270
    /**
271
     * Upload a template to template storage
272
     *
273
     * @param string $templateFilename Template name
274
     *
275
     * @throws InvalidArgumentException
276
     *
277
     * @return bool
278
     */
279 13
    public function uploadTemplate($templateFilename)
280
    {
281 13
        $ret = false;
282
283 13
        StaticValidator::execute($templateFilename, 'TemplateExtension');
284 10
        StaticValidator::execute($templateFilename, 'FileExists');
285
286 9
        $templateFilename = realpath($templateFilename);
287 9
        $templateName     = basename($templateFilename);
288
289
        $query = [
290 9
            'templateName' => $templateName,
291 9
        ];
292
293 9
        $json = file_get_contents($templateFilename);
294 9
        $json = base64_encode($json);
295
296
        $options = [
297 9
            RequestOptions::QUERY => $query,
298 9
            RequestOptions::JSON  => $json,
299 9
        ];
300
301 9
        $response = $this->request('POST', $this->uri('/templates/upload'), $options);
302
303 9
        if ($response instanceof Response && 201 === $response->getStatusCode()) {
304 9
            $ret = true;
305 9
        }
306
307 9
        return $ret;
308
    }
309
310
    /**
311
     * Convert a document on the local file system to a different format
312
     *
313
     * @param string $documentFilename Document filename
314
     * @param string $returnFormat     Return format
315
     *
316
     * @throws InvalidArgumentException
317
     *
318
     * @return null|resource
319
     */
320 6
    public function convertDocument($documentFilename, $returnFormat)
321
    {
322 6
        $ret = null;
323
324 6
        StaticValidator::execute($documentFilename, 'DocumentExtension');
325 3
        StaticValidator::execute($documentFilename, 'FileExists');
326 2
        StaticValidator::execute($returnFormat    , 'ReturnFormat');
327
328
        $query = [
329 1
            'returnFormat' => $returnFormat,
330 1
        ];
331
332 1
        $documentFilename = realpath($documentFilename);
333
334 1
        $json = file_get_contents($documentFilename);
335 1
        $json = base64_encode($json);
336
337
        $options = [
338 1
            RequestOptions::QUERY => $query,
339 1
            RequestOptions::JSON  => $json,
340 1
        ];
341
342 1
        $response = $this->request('POST', $this->uri('/document/convert'), $options);
343
344 1
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
345 1
            $ret  = base64_decode($response->getBody());
346 1
        }
347
348 1
        return $ret;
349
    }
350
351
    /**
352
     * Merge data into a template and return an array of binary data.
353
     * Each record in the array is the binary data of one document
354
     *
355
     * @param array   $mergeData        Array of merge data
356
     * @param string  $returnFormat     Return format
357
     * @param string  $templateName     Template name
358
     * @param string  $templateFilename Template filename on local file system
359
     * @param boolean $append           Append flag
360
     * @param array   $mergeSettings    Array of merge settings
361
     *
362
     * @throws InvalidArgumentException
363
     *
364
     * @return null|string
365
     */
366 15
    public function mergeDocument($mergeData, $returnFormat, $templateName = null, $templateFilename = null,
367
                                    $append = null, $mergeSettings = [])
368
    {
369 15
        $ret = null;
370
371 15
        StaticValidator::execute($mergeData   , 'TypeArray');
372 15
        StaticValidator::execute($returnFormat, 'ReturnFormat');
373
374 14
        if (null !== $templateName) {
375 2
            StaticValidator::execute($templateName, 'TemplateName');
376 1
        }
377
378 13 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...
379 12
            StaticValidator::execute($templateFilename, 'TemplateExtension');
380 9
            StaticValidator::execute($templateFilename, 'FileExists');
381 8
            $templateFilename = realpath($templateFilename);
382 8
        }
383
384 9
        if (null !== $append) {
385 6
            $append = StaticFilter::execute($append, 'BooleanToString');
386 5
        }
387
388 8
        StaticValidator::execute($mergeSettings, 'TypeArray');
389
390
        $query = [
391 7
            'returnFormat' => $returnFormat,
392 7
            'append'       => $append,
393 7
        ];
394
395 7
        if (null !== $templateName) {
396 1
            $query['templateName'] = $templateName;
397 1
        }
398
399
        $json = [
400 7
            'mergeData' => $mergeData,
401 7
        ];
402
403 7 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...
404 6
            $template = file_get_contents($templateFilename);
405 6
            $template = base64_encode($template);
406 6
            $json['template'] = $template;
407 6
        }
408
409 7
        if (count($mergeSettings) > 0) {
410 4
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
411 2
        }
412
413
        $options = [
414 5
            RequestOptions::QUERY => $query,
415 5
            RequestOptions::JSON  => $json,
416 5
        ];
417
418 5
        $response = $this->request('POST', $this->uri('/document/merge'), $options);
419
420 5
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
421 5
            $body = json_decode($response->getBody(), true);
422 5 View Code Duplication
            if (is_array($body) && count($body) > 0) {
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...
423 5
                $ret = array_map('base64_decode', $body);
424 5
            }
425 5
        }
426
427 5
        return $ret;
428
    }
429
430
    /**
431
     * Perform find and replace in document and return binary data.
432
     *
433
     * @param array  $findAndReplaceData Array of find and replace data
434
     * @param string $returnFormat       Return format
435
     * @param string $templateName       Template name
436
     * @param string $templateFilename   Template filename on local file system
437
     * @param array  $mergeSettings      Array of merge settings
438
     *
439
     * @throws InvalidArgumentException
440
     *
441
     * @return null|string
442
     */
443 11
    public function findAndReplaceDocument($findAndReplaceData, $returnFormat, $templateName = null,
444
                                           $templateFilename = null, $mergeSettings = [])
445
    {
446 11
        $ret = null;
447
448 11
        StaticValidator::execute($findAndReplaceData, 'TypeArray');
449 11
        StaticValidator::execute($returnFormat      , 'ReturnFormat');
450
451 10
        if (null !== $templateName) {
452 2
            StaticValidator::execute($templateName, 'TemplateName');
453 1
        }
454
455 9 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...
456 9
            StaticValidator::execute($templateFilename, 'TemplateExtension');
457 5
            StaticValidator::execute($templateFilename, 'FileExists');
458 4
            $templateFilename = realpath($templateFilename);
459 4
        }
460
461 5
        StaticValidator::execute($mergeSettings, 'TypeArray');
462
463
        $query = [
464 4
            'returnFormat' => $returnFormat,
465 4
        ];
466
467 4
        if (null !== $templateName) {
468 1
            $query['templateName'] = $templateName;
469 1
        }
470
471
        $json = [
472 4
            'findAndReplaceData' => $this->buildFindAndReplaceDataArray($findAndReplaceData),
473 4
        ];
474
475 4 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...
476 3
            $template = file_get_contents($templateFilename);
477 3
            $template = base64_encode($template);
478 3
            $json['template'] = $template;
479 3
        }
480
481 4
        if (count($mergeSettings) > 0) {
482 4
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
483 2
        }
484
485
        $options = [
486 2
            RequestOptions::QUERY => $query,
487 2
            RequestOptions::JSON  => $json,
488 2
        ];
489
490 2
        $response = $this->request('POST', $this->uri('/document/findandreplace'), $options);
491
492 2
        if ($response instanceof Response && 200 === $response->getStatusCode()) {
493 2
            $ret  = base64_decode($response->getBody());
494 2
        }
495
496 2
        return $ret;
497
    }
498
499
500
    /**
501
     * DELETE methods
502
     * =================================================================================================================
503
     */
504
505
    /**
506
     * Delete a template in template storage
507
     *
508
     * @param string $templateName Template name
509
     *
510
     * @throws InvalidArgumentException
511
     *
512
     * @return bool
513
     */
514 11
    public function deleteTemplate($templateName)
515
    {
516 11
        $ret = false;
517
518 11
        StaticValidator::execute($templateName, 'TemplateName');
519
520
        $query = [
521 10
            'templateName' => $templateName,
522 10
        ];
523
524
        $options = [
525 10
            RequestOptions::QUERY => $query,
526 10
        ];
527
528 10
        $response = $this->request('DELETE', $this->uri('/templates/delete'), $options);
529
530 9
        if ($response instanceof Response && 204 === $response->getStatusCode()) {
531 9
            $ret = true;
532 9
        }
533
534 9
        return $ret;
535
    }
536
}