Completed
Push — master ( cdb331...f48116 )
by Vítězslav
23:45
created

FlexiBeeRW::sendUnsent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * FlexiPeeHP - Třída pro zápis do FlexiBee.
4
 *
5
 * @author     Vítězslav Dvořák <[email protected]>
6
 * @copyright  (C) 2015-2017 Spoje.Net
7
 */
8
9
namespace FlexiPeeHP;
10
11
/**
12
 * Základní třída pro zápis do FlexiBee
13
 *
14
 * @url https://demo.flexibee.eu/devdoc/http-operations
15
 */
16
class FlexiBeeRW extends FlexiBeeRO
17
{
18
    /**
19
     * Sloupeček obsahující datum vložení záznamu do shopu.
20
     *
21
     * @var string
22
     */
23
    public $myCreateColumn = 'false';
24
25
    /**
26
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
27
     *
28
     * @var string
29
     */
30
    public $myLastModifiedColumn = 'lastUpdate';
31
32
    /**
33
     * Last Inserted ID.
34
     *
35
     * @var int
36
     */
37
    public $lastInsertedID = null;
38
39
    /**
40
     * Array of fields for next curl POST operation
41
     * 
42
     * @var string
43
     */
44
    public $postFields = null;
45
46
    /**
47
     * Transaction processing mode
48
     * 
49
     * @link https://www.flexibee.eu/api/dokumentace/ref/tx/ Transakční zpracování
50
     * @var boolean
51
     */
52
    public $atomic = null;
53
54
    /**
55
     * Record Copy helper
56
     * 
57
     * @var int 
58
     */
59
    private $sourceId = null;
60
61
62
    /**
63
     * SetUp Object to be ready for work
64
     *
65
     * @param array $options Object Options (authSessionId,user,password,
66
     *                                       url,company,evidence,companyUrl
67
     *                                       prefix,defaultUrlParams,debug,ver
68
     *                                       detail,offline,atomic,filter,ignore404
69
     */
70
    public function setUp($options = array())
71
    {
72
        if (array_key_exists('atomic', $options)) {
73
            $this->atomic = (boolean) $options['atomic'];
74
        }
75
        return parent::setUp($options);
76
    }
77
78
    /**
79
     * Save record (if evidence allow to).
80
     * Uloží záznam (pokud to evidence dovoluje)
81
     *
82
     * @param array $data Data to save
83
     * @throws Exception Evidence does not support Import
84
     *
85
     * @return array odpověď
86
     */
87
    public function insertToFlexiBee($data = null)
88
    {
89
        if (is_null($data)) {
90
            $data = $this->getData();
91
        }
92
        $this->postFields = $this->getJsonizedData($data,
93
            $this->debug ? JSON_PRETTY_PRINT : 0);
94
        return $this->performRequest(null, 'PUT');
95
    }
96
97
    /**
98
     * Parse Response array
99
     *
100
     * @param array $responseDecoded
101
     * @param int $responseCode Request Response Code
102
     *
103
     * @return array main data part of response
104
     */
105
    public function parseResponse($responseDecoded, $responseCode)
106
    {
107
        $parsedData = parent::parseResponse($responseDecoded, $responseCode);
108
        switch ($responseCode) {
109
            case 201: //Success Write
110
                if (is_array($responseDecoded)) {
111
                    $this->responseStats = array_key_exists('stats',
0 ignored issues
show
Documentation Bug introduced by
It seems like array_key_exists('stats'...ecoded['stats']) : null can be null. However, the property $responseStats is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
112
                            $responseDecoded) ? (isset($responseDecoded['stats'][0])
113
                            ? array_map('intval', $responseDecoded['stats'][0]) : array_map('intval',  $responseDecoded['stats']))
114
                            : null;
115
                if (isset($responseDecoded[$this->resultField][0]['id'])) {
116
                    $this->lastInsertedID = $responseDecoded[$this->resultField][0]['id'];
117
                    $this->setMyKey($this->lastInsertedID);
118
                } else {
119
                    $this->lastInsertedID = null;
120
                }
121
                if (count($this->chained)) {
122
                    $this->assignResultIDs($this->extractResultIDs($responseDecoded[$this->resultField]));
123
                }
124
        }
125
                $parsedData = $responseDecoded['results'];
126
        }
127
        return $parsedData;
128
    }
129
130
    /**
131
     * Assign result IDs to its source objects
132
     * 
133
     * @param array $candidates FlexiBee insert IDs  prepared by extractResultIDs()
134
     */
135
    public function assignResultIDs($candidates)
136
    {
137
        foreach ($this->chained as $chid => $chained) {
138
            $chainedEvidence = $chained->getEvidence();
139
            $chainedExtid    = $chained->getRecordID();
140
            if (is_array($chainedExtid)) { //if there are more IDs
141
                foreach ($chainedExtid as $extId) { //find external ID in format ext:.....
142
                    if (stripos($extId, 'ext:') === 0) {
143
                        $chainedExtid = $extId;
144
                        break;
145
                    }
146
                }
147
            }
148
            $chained->getData();
149
            if (isset($candidates[$chainedEvidence][$chainedExtid])) {
150
                $chained->setMyKey($candidates[$chainedEvidence][$chainedExtid]);
151
                $chained->setDataValue('external-ids', [$chainedExtid]);
152
            }
153
            if (count($this->chained[$chid]->chained)) {
154
                $this->chained[$chid]->assignResultIDs($candidates);
155
            }
156
        }
157
    }
158
159
    /**
160
     * Extract IDs from FlexiBee response Array
161
     * 
162
     * @param array $resultInfo FlexiBee response
163
     * 
164
     * @return array List of [ 'evidence1'=>[ 'original-id'=>numericID,'original-id2'=>numericID2 ], 'evidence2'=> ... ]
165
     */
166
    public function extractResultIDs($resultInfo)
167
    {
168
        $candidates = [];
169
        foreach ($resultInfo as $insertResult) {
170
            $newID = $insertResult['id'];
171
            if (array_key_exists('request-id', $insertResult)) {
172
                $extid = $insertResult['request-id'];
173
            } else {
174
                $extid = null;
175
            }
176
            $evidence                      = explode('/', $insertResult['ref'])[3];
177
            $candidates[$evidence][$extid] = $newID;
178
        }
179
        return $candidates;
180
    }
181
182
    /**
183
     * Give you last inserted record ID.
184
     * 
185
     * @return int
186
     */
187
    public function getLastInsertedId()
188
    {
189
        return $this->lastInsertedID;
190
    }
191
192
    /**
193
     * Smaže záznam
194
     * Delete record in FlexiBee
195
     *
196
     * @param int|string $id identifikátor záznamu
197
     * 
198
     * @return boolean Response code is 200 ?
199
     */
200
    public function deleteFromFlexiBee($id = null)
201
    {
202
        if (is_null($id)) {
203
            $id = $this->getMyKey();
204
        }
205
206
        $this->performRequest($this->getEvidenceUrl().'/'.self::urlizeId($id),
207
            'DELETE');
208
        return $this->lastResponseCode == 200;
209
    }
210
211
    /**
212
     * Control for existing column names in evidence and take data
213
     *
214
     * @param array $data Data to keep
215
     * 
216
     * @return int number of records taken
217
     */
218
    public function takeData($data)
219
    {
220
        if ($this->debug === true) {
221
            $fbRelations = [];
222
            $fbColumns   = $this->getColumnsInfo();
223
            foreach ($this->getRelationsInfo() as $relation) {
224
                if (is_array($relation) && isset($relation['url'])) {
225
                    $fbRelations[$relation['url']] = $relation['url'];
226
                }
227
            }
228
            if (count($fbColumns)) {
229
                foreach ($data as $key => $value) {
230
                    if (!array_key_exists($key, $fbColumns)) {
231
232
                        if (!array_key_exists($key, $fbRelations)) {
233
                            $this->addStatusMessage(sprintf('unknown column %s for evidence %s',
234
                                    $key, $this->getEvidence()), 'warning');
235
                        } else {
236
                            if (!is_array($value)) {
237
                                $this->addStatusMessage(sprintf('subevidence %s in evidence %s must bee an array',
238
                                        $key, $this->getEvidence()), 'warning');
239
                            }
240
                        }
241
                    }
242
                }
243
            }
244
        }
245
        return parent::takeData($data);
246
    }
247
248
    /**
249
     * Control data for mandatory columns presence.
250
     *
251
     * @deprecated since version 1.8.7
252
     * 
253
     * @param array $data
254
     * 
255
     * @return array List of missing columns. Empty if all is ok
256
     */
257
    public function controlMandatoryColumns($data = null)
258
    {
259
        if (is_null($data)) {
260
            $data = $this->getData();
261
        }
262
        $missingMandatoryColumns = [];
263
        if (!empty($data) && count($data)) {
264
            $fbColumns = $this->getColumnsInfo();
265
            if (count($fbColumns)) {
266
                foreach ($fbColumns as $columnName => $columnInfo) {
267
                    $mandatory = ($columnInfo['mandatory'] == 'true');
268
                    if ($mandatory && !array_key_exists($columnName, $data)) {
269
                        $missingMandatoryColumns[$columnName] = $columnInfo['name'];
270
                    }
271
                }
272
            }
273
        }
274
        return $missingMandatoryColumns;
275
    }
276
277
    /**
278
     * Control data for readonly columns presence.
279
     *
280
     * @param array $data
281
     * 
282
     * @return array List of ReadOnly columns. Empty if all is ok
283
     */
284
    public function controlReadOnlyColumns($data = null)
285
    {
286
        if (is_null($data)) {
287
            $data = $this->getData();
288
        }
289
290
        $readonlyColumns = [];
291
292
        $fbColumns = $this->getColumnsInfo();
293
        if (!empty($fbColumns) && count($fbColumns)) {
294
            foreach ($fbColumns as $columnName => $columnInfo) {
295
                $writable = ($columnInfo['isWritable'] == 'true');
296
                if (!$writable && !array_key_exists($columnName, $data)) {
297
                    $readonlyColumns[$columnName] = $columnInfo['name'];
298
                }
299
            }
300
        }
301
        return $readonlyColumns;
302
    }
303
304
    /**
305
     * Convert Timestamp to FlexiBee Date format.
306
     *
307
     * @param int $timpestamp
308
     *
309
     * @return string FlexiBee Date or NULL
310
     */
311
    public static function timestampToFlexiDate($timpestamp = null)
312
    {
313
        $flexiDate = null;
314
        if (!is_null($timpestamp)) {
315
            $date      = new \DateTime();
316
            $date->setTimestamp($timpestamp);
317
            $flexiDate = $date->format('Y-m-d');
318
        }
319
        return $flexiDate;
320
    }
321
322
    /**
323
     * Convert Timestamp to Flexi DateTime format.
324
     *
325
     * @param int $timpestamp
326
     *
327
     * @return string FlexiBee DateTime or NULL
328
     */
329
    public static function timestampToFlexiDateTime($timpestamp = null)
330
    {
331
        $flexiDateTime = null;
332
        if (!is_null($timpestamp)) {
333
            $date          = new \DateTime();
334
            $date->setTimestamp($timpestamp);
335
            $flexiDateTime = $date->format('Y-m-dTH:i:s');
336
        }
337
        return $flexiDateTime;
338
    }
339
340
    /**
341
     * Add Data to evidence Branch
342
     * Přidá data do větve
343
     *
344
     * @thanksto Karel Běl
345
     *
346
     * @see Relations
347
     *
348
     * @param array   $data pole dat
349
     * @param string  $relationPath path evidence (relation) pro vkládaná data
350
     * @param boolean $removeAll
351
     *
352
     * @return boolean Operation success
353
     */
354
    public function addArrayToBranch($data, $relationPath = 'polozkyDokladu',
355
                                     $removeAll = false)
356
    {
357
        $currentBranchData = $this->getDataValue($relationPath);
358
        $branchData        = $currentBranchData;
359
        $branchData[]      = $data;
360
        if (is_array($this->getEvidence()) && array_key_exists('bezPolozek',
361
                $this->getColumnsInfo())) {
362
            $this->setDataValue('bezPolozek', false);
363
        }
364
        if ($removeAll === true) {
365
            $this->setDataValue($relationPath.'@removeAll', true);
366
        }
367
        return $this->setDataValue($relationPath, $branchData);
368
    }
369
370
    /**
371
     * Vloží do větve data z objektu
372
     *
373
     * @param FlexiBeeRO $object    objekt evidence
374
     * @param boolean    $removeAll flush older items 
375
     */
376
    public function addObjectToBranch($object, $removeAll = false)
377
    {
378
        $this->addArrayToBranch([$object->getEvidence() => $object->getData()],
379
            'polozkyDokladu', $removeAll);
380
    }
381
382
    /**
383
     * Přidá uživatelskou vazbu
384
     *
385
     * @see https://www.flexibee.eu/api/dokumentace/ref/uzivatelske-vazby/
386
     * @param string $vazba
387
     */
388
    public function vazbaAdd($vazba)
389
    {
390
        $this->addArrayToBranch(['uzivatelska-vazba' => $vazba],
391
            'uzivatelske-vazby');
392
    }
393
394
    /**
395
     * Smaže uživatelskou vazbu
396
     *
397
     * @see https://www.flexibee.eu/api/dokumentace/ref/uzivatelske-vazby/
398
     * @param string $vazba
399
     */
400
    public function vazbaDel($vazba)
401
    {
402
        $this->setDataValue('uzivatelska-vazba@action', 'delete');
403
        $this->addArrayToBranch(['uzivatelska-vazba' => $vazba],
404
            'uzivatelske-vazby');
405
    }
406
407
    /**
408
     * Převede data do Json formátu pro FlexiBee.
409
     * Pokud jsou štítky pole, jsou převedeny na seznam oddělený čárkou.
410
     * Convert data to FlexiBee like Json format.
411
     * Array of Labels is converted to coma separated list
412
     *
413
     * @param array $data
414
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc 
415
     *
416
     * @return string
417
     */
418
    public function getJsonizedData($data = null, $options = 0)
419
    {
420
        if (is_null($data)) {
421
            $data = $this->getData();
422
        }
423
424
        if (array_key_exists('stitky', $data)) {
425
            if (is_array($data['stitky'])) {
426
                $data['stitky'] = implode(',', $data['stitky']);
427
            }
428
        }
429
        $dataToJsonize = parent::getJsonizedData($data, $options);
430
        return $dataToJsonize;
431
    }
432
433
    /**
434
     * Get Data Fragment specific for current object
435
     * 
436
     * @param array $data
437
     * 
438
     * @return array
439
     */
440
    public function getDataForJSON($data = null)
441
    {
442
        if (is_null($data)) {
443
            $data = $this->getData();
444
        }
445
        $dataForJSON = parent::getDataForJSON($data);
446
        if (!is_null($this->atomic)) {
447
            $dataForJSON['@atomic'] = $this->atomic;
448
        }
449
        if (isset($this->sourceId)) {
450
            $dataForJSON['@sourceId'] = $this->sourceId;
451
            $this->sourceId = null;
452
        }
453
        return $dataForJSON;
454
    }
455
456
    /**
457
     * Insert current data into FlexiBee and load actual record data back
458
     *
459
     * @param array $data Initial data to save
460
     * 
461
     * @return boolean Operation success
462
     */
463
    public function sync($data = null)
464
    {
465
        $this->insertToFlexiBee($data);
466
        $insertResult = $this->lastResponseCode;
467
        if ($insertResult == 201) {
468
            $this->reload();
469
        }
470
        $loadResult = $this->lastResponseCode;
471
        return ($insertResult + $loadResult) == 401;
472
    }
473
474
    /**
475
     * Make Copy of given record with optional modifiactions
476
     * 
477
     * !!!Experimental Feature!!!
478
     * 
479
     * @param int  $source
480
     * @param array $overrides
481
     * 
482
     * @return FlexiBeeRW|null copied record object or null in case of failure
483
     */
484
    public function copy($source, $overrides = [])
485
    {
486
        $this->sourceId = $source;
487
        return $this->sync($overrides) ? $this : null;
488
    }
489
490
    /**
491
     * Perform given action (if availble) on current evidence/record
492
     * @url https://demo.flexibee.eu/devdoc/actions
493
     *
494
     * @param string $action one of evidence actions
495
     * @param string $method ext|int External method call operation in URL.
496
     *                               Internal add the @action element to request body
497
     *
498
     * @return boolean operation success
499
     */
500
    public function performAction($action, $method = 'int')
501
    {
502
        $actionsAvailble = $this->getActionsInfo();
503
504
        if (is_array($actionsAvailble) && array_key_exists($action,
505
                $actionsAvailble)) {
506
            switch ($actionsAvailble[$action]['actionMakesSense']) {
507
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
508
                case 'ONLY_WITH_INSTANCE': //Add instance
509
                    $urlSuffix = '/'.$this->__toString().'/'.$action;
510
                    break;
511
512
                default:
513
                    $urlSuffix = '/'.$action;
514
                    break;
515
            }
516
517
            switch ($method) {
518
                case 'int':
519
                    $this->setAction($action);
520
                    $this->setPostFields($this->getJsonizedData(['id' => $this]));
521
                    $this->performRequest(null, 'POST');
522
                    $result = $this->lastResponseCode == 201;
523
                    break;
524
525
                default:
526
                    $result = $this->performRequest($this->evidenceUrlWithSuffix($urlSuffix),
527
                        'GET');
528
                    break;
529
            }
530
        } else {
531
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
532
                    $action, $this->getEvidence()));
533
        }
534
535
        return $result;
536
    }
537
538
    /**
539
     * Add External ID to Current Record
540
     * 
541
     * @param string $extId ext:whatever:123 or simplay whatever:123
542
     * 
543
     * @return array Insert result
544
     */
545
    public function addExternalID($extId)
546
    {
547
        return $this->insertToFlexiBee(['id' => [$this->getRecordID(), 'ext:'.preg_replace('/^ext:/',
548
                        '', $extId)]]);
549
    }
550
551
    /**
552
     * Change Value of external id identified by selector. Add new if not exists
553
     * 
554
     * @param string     $selector ext:$selector:$newValue
555
     * @param string|int $newValue string or number
556
     * @param string|int $forID    Other than current record id
557
     * 
558
     * @return array operation result
559
     */
560
    public function changeExternalID($selector, $newValue, $forID = null)
561
    {
562
        $change['@removeExternalIds'] = 'ext:'.$selector.':';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$change was never initialized. Although not strictly required by PHP, it is generally a good practice to add $change = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
563
        $change['id']                 = [is_null($forID) ? $this->getRecordID() : $forID,
564
            'ext:'.$selector.':'.$newValue];
565
        return $this->insertToFlexiBee($change);
566
    }
567
    
568
    /**
569
     * Send all unsent Documents by eMail
570
     *
571
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
572
     * 
573
     * @return int http response code
574
     */
575
    public function sendUnsent() {
576
        $this->performRequest('automaticky-odeslat-neodeslane', 'PUT', 'xml');
577
        return $this->lastResponseCode  == 202;
578
    }
579
    
580
}
581