Passed
Branch tracked-changes-1.0 (52237f)
by Jonathan
18:39
created

PostTrait::removeTrackedChange()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 30
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 15
c 0
b 0
f 0
dl 0
loc 30
ccs 15
cts 15
cp 1
rs 9.7666
cc 3
nc 3
nop 3
crap 3
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * ReportingCloud PHP SDK
6
 *
7
 * PHP SDK for ReportingCloud Web API. Authored and supported by Text Control GmbH.
8
 *
9
 * @link      https://www.reporting.cloud to learn more about ReportingCloud
10
 * @link      https://github.com/TextControl/txtextcontrol-reportingcloud-php for the canonical source repository
11
 * @license   https://raw.githubusercontent.com/TextControl/txtextcontrol-reportingcloud-php/master/LICENSE.md
12
 * @copyright © 2019 Text Control GmbH
13
 */
14
15
namespace TxTextControl\ReportingCloud;
16
17
use GuzzleHttp\RequestOptions;
18
use Psr\Http\Message\ResponseInterface;
19
use TxTextControl\ReportingCloud\Assert\Assert;
20
use TxTextControl\ReportingCloud\Exception\InvalidArgumentException;
21
use TxTextControl\ReportingCloud\Exception\RuntimeException;
22
use TxTextControl\ReportingCloud\Filter\Filter;
23
use TxTextControl\ReportingCloud\PropertyMap\AbstractPropertyMap as PropertyMap;
24
use TxTextControl\ReportingCloud\PropertyMap\ModifiedDocument as ModifiedDocumentPropertyMap;
25
use TxTextControl\ReportingCloud\PropertyMap\TrackedChanges as TrackedChangesPropertyMap;
26
use TxTextControl\ReportingCloud\StatusCode\StatusCode;
27
use TxTextControl\ReportingCloud\Stdlib\FileUtils;
28
29
/**
30
 * Trait PostTrait
31
 *
32
 * @package TxTextControl\ReportingCloud
33
 * @author  Jonathan Maron (@JonathanMaron)
34
 */
35
trait PostTrait
36
{
37
    // <editor-fold desc="Abstract methods">
38
39
    /**
40
     * Construct URI with version number
41
     *
42
     * @param string $uri URI
43
     *
44
     * @return string
45
     */
46
    abstract protected function uri(string $uri): string;
47
48
    /**
49
     * Request the URI with options
50
     *
51
     * @param string $method  HTTP method
52
     * @param string $uri     URI
53
     * @param array  $options Options
54
     *
55
     * @return ResponseInterface
56
     * @throws RuntimeException
57
     */
58
    abstract protected function request(string $method, string $uri, array $options): ResponseInterface;
59
60
    /**
61
     * Using passed findAndReplaceData associative array (key-value), build array for backend (list of string arrays)
62
     *
63
     * @param array $array FindAndReplaceData array
64
     *
65
     * @return array
66
     */
67
    abstract protected function buildFindAndReplaceDataArray(array $array): array;
68
69
    /**
70
     * Using passed mergeSettings array, build array for backend
71
     *
72
     * @param array $array MergeSettings array
73
     *
74
     * @return array
75
     */
76
    abstract protected function buildMergeSettingsArray(array $array): array;
77
78
    /**
79
     * Using passed documentsData array, build array for backend
80
     *
81
     * @param array $array AppendDocument array
82
     *
83
     * @return array
84
     */
85
    abstract protected function buildDocumentsArray(array $array): array;
86
87
    /**
88
     * Using passed documentsSettings array, build array for backend
89
     *
90
     * @param array $array
91
     *
92
     * @return array
93
     */
94
    abstract protected function buildDocumentSettingsArray(array $array): array;
95
96
    /**
97
     * Using the passed propertyMap, recursively build array
98
     *
99
     * @param array       $array       Array
100
     * @param PropertyMap $propertyMap PropertyMap
101
     *
102
     * @return array
103
     */
104
    abstract protected function buildPropertyMapArray(array $array, PropertyMap $propertyMap): array;
105
106
    // </editor-fold>
107
108
    // <editor-fold desc="Methods">
109
110
    /**
111
     * Upload a base64 encoded template to template storage
112
     *
113
     * @param string $data         Template encoded as base64
114
     * @param string $templateName Template name
115
     *
116
     * @return bool
117
     * @throws InvalidArgumentException
118
     */
119 36
    public function uploadTemplateFromBase64(string $data, string $templateName): bool
120
    {
121 36
        Assert::assertBase64Data($data);
122 36
        Assert::assertTemplateName($templateName);
123
124
        $query = [
125 36
            'templateName' => $templateName,
126
        ];
127
128 36
        $result = $this->post('/templates/upload', $query, $data, StatusCode::CREATED);
129
130 36
        return (null === $result) ? true : false;
131
    }
132
133
    /**
134
     * Upload a template to template storage
135
     *
136
     * @param string $templateFilename Template name
137
     *
138
     * @return bool
139
     * @throws InvalidArgumentException
140
     */
141 45
    public function uploadTemplate(string $templateFilename): bool
142
    {
143 45
        Assert::assertTemplateExtension($templateFilename);
144 36
        Assert::assertFilenameExists($templateFilename);
145
146 33
        $templateName = basename($templateFilename);
147
148 33
        $data = FileUtils::read($templateFilename, true);
149
150 33
        return $this->uploadTemplateFromBase64($data, $templateName);
151
    }
152
153
    /**
154
     * Convert a document on the local file system to a different format
155
     *
156
     * @param string $documentFilename Document filename
157
     * @param string $returnFormat     Return format
158
     *
159
     * @return string
160
     * @throws InvalidArgumentException
161
     */
162 21
    public function convertDocument(string $documentFilename, string $returnFormat): string
163
    {
164 21
        Assert::assertDocumentExtension($documentFilename);
165 12
        Assert::assertFilenameExists($documentFilename);
166 9
        Assert::assertReturnFormat($returnFormat);
167
168
        $query  = [
169 6
            'returnFormat' => $returnFormat,
170
        ];
171
172 6
        $data   = FileUtils::read($documentFilename, true);
173
174 6
        $result = (string) $this->post('/document/convert', $query, $data, StatusCode::OK);
175
176 6
        $ret    = (string) base64_decode($result);
177
178 6
        return $ret;
179
    }
180
181
    /**
182
     * Merge data into a template and return an array of binary data.
183
     * Each record in the array is the binary data of one document
184
     *
185
     * @param array       $mergeData        Array of merge data
186
     * @param string      $returnFormat     Return format
187
     * @param string|null $templateName     Template name
188
     * @param string|null $templateFilename Template filename on local file system
189
     * @param bool|null   $append           Append flag
190
     * @param array|null  $mergeSettings    Array of merge settings
191
     *
192
     * @return array
193
     * @throws InvalidArgumentException
194
     */
195 34
    public function mergeDocument(
196
        array $mergeData,
197
        string $returnFormat,
198
        ?string $templateName = null,
199
        ?string $templateFilename = null,
200
        ?bool $append = null,
201
        ?array $mergeSettings = null
202
    ): array {
203 34
        $ret = [];
204
205 34
        $query = [];
206 34
        $json  = [];
207
208
        //Assert::assertArray($mergeData);
209 34
        $json['mergeData'] = $mergeData;
210
211 34
        Assert::assertReturnFormat($returnFormat);
212 31
        $query['returnFormat'] = $returnFormat;
213
214 31
        if (null !== $templateName) {
215 6
            Assert::assertTemplateName($templateName);
216 3
            $query['templateName'] = $templateName;
217
        }
218
219 28
        if (null !== $templateFilename) {
220 25
            Assert::assertTemplateExtension($templateFilename);
221 16
            Assert::assertFilenameExists($templateFilename);
222 13
            $json['template'] = FileUtils::read($templateFilename, true);
223
        }
224
225 16
        if (null !== $append) {
226
            //Assert::assertBoolean($append);
227 15
            $query['append'] = Filter::filterBooleanToString($append);
228
        }
229
230 16
        if (is_array($mergeSettings)) {
231 15
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
232
        }
233
234 7
        $result = $this->post('/document/merge', $query, $json, StatusCode::OK);
235
236 7
        if (is_array($result)) {
237 7
            $ret = array_map('base64_decode', $result);
238
        }
239
240 7
        return $ret;
241
    }
242
243
    /**
244
     * Combine documents to appending them, divided by a new section, paragraph or nothing
245
     *
246
     * @param array      $documentsData
247
     * @param string     $returnFormat
248
     * @param array|null $documentSettings
249
     *
250
     * @return string
251
     * @throws InvalidArgumentException
252
     */
253 3
    public function appendDocument(
254
        array $documentsData,
255
        string $returnFormat,
256
        ?array $documentSettings = null
257
    ): string {
258 3
        $query = [];
259 3
        $json  = [];
260
261
        //Assert::assertArray($documentsData);
262 3
        $json['documents'] = $this->buildDocumentsArray($documentsData);
263
264 3
        Assert::assertReturnFormat($returnFormat);
265 3
        $query['returnFormat'] = $returnFormat;
266
267 3
        if (is_array($documentSettings)) {
268 3
            $json['documentSettings'] = $this->buildDocumentSettingsArray($documentSettings);
269
        }
270
271 3
        $result = (string) $this->post('/document/append', $query, $json, StatusCode::OK);
272
273 3
        $ret    = (string) base64_decode($result);
274
275 3
        return $ret;
276
    }
277
278
    /**
279
     * Perform find and replace in document and return binary data.
280
     *
281
     * @param array       $findAndReplaceData Array of find and replace data
282
     * @param string      $returnFormat       Return format
283
     * @param string|null $templateName       Template name
284
     * @param string|null $templateFilename   Template filename on local file system
285
     * @param array|null  $mergeSettings      Array of merge settings
286
     *
287
     * @return string
288
     * @throws InvalidArgumentException
289
     */
290 30
    public function findAndReplaceDocument(
291
        array $findAndReplaceData,
292
        string $returnFormat,
293
        ?string $templateName = null,
294
        ?string $templateFilename = null,
295
        ?array $mergeSettings = null
296
    ): string {
297 30
        $query = [];
298 30
        $json  = [];
299
300
        //Assert::assertArray($findAndReplaceData);
301 30
        $json['findAndReplaceData'] = $this->buildFindAndReplaceDataArray($findAndReplaceData);
302
303 30
        Assert::assertReturnFormat($returnFormat);
304 27
        $query['returnFormat'] = $returnFormat;
305
306 27
        if (null !== $templateName) {
307 6
            Assert::assertTemplateName($templateName);
308 3
            $query['templateName'] = $templateName;
309
        }
310
311 24
        if (null !== $templateFilename) {
312 21
            Assert::assertTemplateExtension($templateFilename);
313 12
            Assert::assertFilenameExists($templateFilename);
314 9
            $json['template'] = FileUtils::read($templateFilename, true);
315
        }
316
317 12
        if (is_array($mergeSettings)) {
318 12
            $json['mergeSettings'] = $this->buildMergeSettingsArray($mergeSettings);
319
        }
320
321 6
        $result = (string) $this->post('/document/findandreplace', $query, $json, StatusCode::OK);
322
323 6
        $ret    = (string) base64_decode($result);
324
325 6
        return $ret;
326
    }
327
328
    /**
329
     * Generate a thumbnail image per page of specified document filename.
330
     * Return an array of binary data with each record containing one thumbnail.
331
     *
332
     * @param string $documentFilename Document filename
333
     * @param int    $zoomFactor       Zoom factor
334
     * @param int    $fromPage         From page
335
     * @param int    $toPage           To page
336
     * @param string $imageFormat      Image format
337
     *
338
     * @throws InvalidArgumentException
339
     * @return array
340
     */
341 3
    public function getDocumentThumbnails(
342
        string $documentFilename,
343
        int $zoomFactor,
344
        int $fromPage,
345
        int $toPage,
346
        string $imageFormat
347
    ): array {
348 3
        $ret = [];
349
350 3
        Assert::assertDocumentThumbnailExtension($documentFilename);
351 3
        Assert::assertFilenameExists($documentFilename);
352 3
        Assert::assertZoomFactor($zoomFactor);
353 3
        Assert::assertPage($fromPage);
354 3
        Assert::assertPage($toPage);
355 3
        Assert::assertImageFormat($imageFormat);
356
357
        $query = [
358 3
            'zoomFactor'   => $zoomFactor,
359 3
            'fromPage'     => $fromPage,
360 3
            'toPage'       => $toPage,
361 3
            'imageFormat'  => $imageFormat,
362
        ];
363
364 3
        $data   = FileUtils::read($documentFilename, true);
365
366 3
        $result = $this->post('/document/thumbnails', $query, $data, StatusCode::OK);
367
368 3
        if (is_array($result)) {
369 3
            $ret = array_map('base64_decode', $result);
370
        }
371
372 3
        return $ret;
373
    }
374
375
    /**
376
     * Return the tracked changes in a document.
377
     *
378
     * @param string $documentFilename Document filename
379
     *
380
     * @throws InvalidArgumentException
381
     * @return array
382
     */
383 3
    public function getTrackedChanges(
384
        string $documentFilename
385
    ): array {
386 3
        $ret = [];
387
388 3
        $propertyMap = new TrackedChangesPropertyMap();
389
390 3
        Assert::assertDocumentExtension($documentFilename);
391 3
        Assert::assertFilenameExists($documentFilename);
392
393 3
        $data   = FileUtils::read($documentFilename, true);
394
395 3
        $result = $this->post('/processing/review/trackedchanges', null, $data, StatusCode::OK);
396
397 3
        if (is_array($result)) {
398 3
            $ret = $this->buildPropertyMapArray($result, $propertyMap);
399
            array_walk($ret, function (array &$record): void {
400 3
                $key = 'change_time';
401 3
                if (isset($record[$key])) {
402
                    //@todo [20190902] return value of backend DateTime in Zulu timezone
403
                    //Assert::assertDateTime($record[$key]);
404 3
                    $record[$key] = Filter::filterDateTimeToTimestamp($record[$key]);
405
                }
406 3
            });
407
        }
408
409 3
        return $ret;
410
    }
411
412
    /**
413
     * Removes a specific tracked change and returns the resulting document.
414
     *
415
     * @param string $documentFilename Document filename
416
     * @param int $id                  The ID of the tracked change that needs to be removed
417
     * @param bool $accept             Specifies whether the tracked change should be accepted or not (reject)
418
     *
419
     * @throws InvalidArgumentException
420
     * @return array
421
     *
422
     */
423 3
    public function removeTrackedChange(
424
        string $documentFilename,
425
        int $id,
426
        bool $accept
427
    ): array {
428 3
        $ret = [];
429
430 3
        $propertyMap = new ModifiedDocumentPropertyMap();
431
432 3
        Assert::assertDocumentExtension($documentFilename);
433 3
        Assert::assertFilenameExists($documentFilename);
434
435
        $query  = [
436 3
            'id'     => $id,
437 3
            'accept' => Filter::filterBooleanToString($accept),
438
        ];
439
440 3
        $data   = FileUtils::read($documentFilename, true);
441
442 3
        $result = $this->post('/processing/review/removetrackedchange', $query, $data, StatusCode::OK);
443
444 3
        if (is_array($result)) {
445 3
            $ret = $this->buildPropertyMapArray($result, $propertyMap);
446 3
            $key = 'document';
447 3
            if (isset($ret[$key])) {
448 3
                $ret[$key] = (string) base64_decode($ret[$key]);
449
            }
450
        }
451
452 3
        return $ret;
453
    }
454
455
    /**
456
     * Execute a POST request via REST client
457
     *
458
     * @param string     $uri        URI
459
     * @param array|null $query      Query
460
     * @param mixed|null $json       JSON
461
     * @param int|null   $statusCode Required HTTP status code for response
462
     *
463
     * @return mixed|null
464
     */
465 61
    private function post(
466
        string $uri,
467
        ?array $query = null,
468
        $json = null,
469
        ?int $statusCode = null
470
    ) {
471 61
        $ret = '';
472
473
        $options = [
474 61
            RequestOptions::QUERY => $query,
475 61
            RequestOptions::JSON  => $json,
476
        ];
477
478 61
        $response = $this->request('POST', $this->uri($uri), $options);
479
480 61
        if ($statusCode === $response->getStatusCode()) {
481 61
            $ret = json_decode($response->getBody()->getContents(), true);
482
        }
483
484 61
        return $ret;
485
    }
486
487
    // </editor-fold>
488
}
489