Test Failed
Push — master ( 1ea845...275c2e )
by Vítězslav
03:06
created

FlexiBeeRW::addObjectToBranch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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