Test Failed
Push — master ( 07773a...ee3332 )
by Vítězslav
04:50
created

FlexiBeeRO::uncode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * FlexiPeeHP - Read Only Access to FlexiBee class.
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 čtení z FlexiBee
13
 *
14
 * @url https://demo.flexibee.eu/devdoc/
15
 */
16
class FlexiBeeRO extends \Ease\Brick
17
{
18
    /**
19
     * Version of FlexiPeeHP library
20
     *
21
     * @var string
22
     */
23
    public static $libVersion = '1.6.4.2';
24
25
    /**
26
     * Základní namespace pro komunikaci s FlexiBee.
27
     * Basic namespace for communication with FlexiBee
28
     *
29
     * @var string Jmený prostor datového bloku odpovědi
30
     */
31
    public $nameSpace = 'winstrom';
32
33
    /**
34
     * URL of object data in FlexiBee
35
     * @var string url
36
     */
37
    public $apiURL = null;
38
39
    /**
40
     * Datový blok v poli odpovědi.
41
     * Data block in response field.
42
     *
43
     * @var string
44
     */
45
    public $resultField = 'results';
46
47
    /**
48
     * Verze protokolu použitého pro komunikaci.
49
     * Communication protocol version used.
50
     *
51
     * @var string Verze použitého API
52
     */
53
    public $protoVersion = '1.0';
54
55
    /**
56
     * Evidence užitá objektem.
57
     * Evidence used by object
58
     *
59
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
60
     * @var string
61
     */
62
    public $evidence = null;
63
64
    /**
65
     * Výchozí formát pro komunikaci.
66
     * Default communication format.
67
     *
68
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
69
     *
70
     * @var string json|xml|...
71
     */
72
    public $format = 'json';
73
74
    /**
75
     * formát příchozí odpovědi
76
     * response format
77
     *
78
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
79
     *
80
     * @var string json|xml|...
81
     */
82
    public $responseFormat = 'json';
83
84
    /**
85
     * Curl Handle.
86
     *
87
     * @var resource
88
     */
89
    public $curl = null;
90
91
    /**
92
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
93
     * @var string
94
     */
95
    public $company = null;
96
97
    /**
98
     * Server[:port]
99
     * @var string
100
     */
101
    public $url = null;
102
103
    /**
104
     * REST API Username
105
     * @var string
106
     */
107
    public $user = null;
108
109
    /**
110
     * REST API Password
111
     * @var string
112
     */
113
    public $password = null;
114
115
    /**
116
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
117
     */
118
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
119
120
    /**
121
     * Default additional request url parameters after question mark
122
     *
123
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
124
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
125
     * @var array
126
     */
127
    public $defaultUrlParams = ['limit' => 0];
128
129
    /**
130
     * Identifikační řetězec.
131
     *
132
     * @var string
133
     */
134
    public $init = null;
135
136
    /**
137
     * Sloupeček s názvem.
138
     *
139
     * @var string
140
     */
141
    public $nameColumn = 'nazev';
142
143
    /**
144
     * Sloupeček obsahující datum vložení záznamu do shopu.
145
     *
146
     * @var string
147
     */
148
    public $myCreateColumn = 'false';
149
150
    /**
151
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
152
     *
153
     * @var string
154
     */
155
    public $myLastModifiedColumn = 'lastUpdate';
156
157
    /**
158
     * Klíčový idendifikátor záznamu.
159
     *
160
     * @var string
161
     */
162
    public $fbKeyColumn = 'id';
163
164
    /**
165
     * Informace o posledním HTTP requestu.
166
     *
167
     * @var *
168
     */
169
    public $curlInfo;
170
171
    /**
172
     * Informace o poslední HTTP chybě.
173
     *
174
     * @var string
175
     */
176
    public $lastCurlError = null;
177
178
    /**
179
     * Used codes storage.
180
     *
181
     * @var array
182
     */
183
    public $codes = null;
184
185
    /**
186
     * Last Inserted ID.
187
     *
188
     * @var int
189
     */
190
    public $lastInsertedID = null;
191
192
    /**
193
     * Default Line Prefix.
194
     *
195
     * @var string
196
     */
197
    public $prefix = '/c/';
198
199
    /**
200
     * Raw Content of last curl response
201
     *
202
     * @var string
203
     */
204
    public $lastCurlResponse;
205
206
    /**
207
     * HTTP Response code of last request
208
     *
209
     * @var int
210
     */
211
    public $lastResponseCode = null;
212
213
    /**
214
     * Body data  for next curl POST operation
215
     *
216
     * @var string
217
     */
218
    protected $postFields = null;
219
220
    /**
221
     * Last operation result data or message(s)
222
     *
223
     * @var array
224
     */
225
    public $lastResult = null;
226
227
    /**
228
     * Nuber from  @rowCount
229
     * @var int
230
     */
231
    public $rowCount = null;
232
233
    /**
234
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
235
     * @var string filter query
236
     */
237
    public $filter;
238
239
    /**
240
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
241
     * @var string
242
     */
243
    protected $action;
244
245
    /**
246
     * Pole akcí které podporuje ta která evidence
247
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
248
     * @var array
249
     */
250
    public $actionsAvailable = null;
251
252
    /**
253
     * Parmetry pro URL
254
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
255
     * @var array
256
     */
257
    public $urlParams = [
258
        'idUcetniObdobi',
259
        'dry-run',
260
        'fail-on-warning',
261
        'report-name',
262
        'report-lang',
263
        'report-sign',
264
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
265
        'mode',
266
        'limit',
267
        'start',
268
        'order',
269
        'sort',
270
        'add-row-count',
271
        'relations',
272
        'includes',
273
        'use-ext-id',
274
        'use-internal-id',
275
        'stitky-as-ids',
276
        'only-ext-ids',
277
        'no-ext-ids',
278
        'no-ids',
279
        'code-as-id',
280
        'no-http-errors',
281
        'export-settings',
282
        'as-gui',
283
        'code-in-response',
284
        'add-global-version',
285
        'encoding',
286
        'delimeter',
287
        'format',
288
        'auth',
289
        'skupina-stitku',
290
        'dir',
291
        'relations',
292
        'relations',
293
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
294
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
295
        'inDesktopApp' // Note: Undocumented function (html only)
296
    ];
297
298
    /**
299
     * Save 404 results to log ?
300
     * @var boolean
301
     */
302
    protected $ignoreNotFound = false;
303
304
    /**
305
     * Array of errors caused by last request
306
     * @var array
307
     */
308
    private $errors = [];
309
310
    /**
311
     * List of Error500 reports sent
312
     * @var array
313
     */
314
    private $reports = [];
315
316
    /**
317
     * Send Error500 Report to
318
     * @var string email address
319
     */
320
    public $reportRecipient = '[email protected]';
321
322
    /**
323
     * Class for read only interaction with FlexiBee.
324
     *
325
     * @param mixed $init default record id or initial data
326
     * @param array $options Connection settings override
327
     */
328 26
    public function __construct($init = null, $options = [])
329
    {
330 26
        $this->init = $init;
331
332 26
        parent::__construct();
333 26
        $this->setUp($options);
334 26
        $this->curlInit();
335 26
        if (!empty($init)) {
336 22
            $this->processInit($init);
337 22
        }
338 26
    }
339
340
    /**
341
     * SetUp Object to be ready for connect
342
     *
343
     * @param array $options Object Options (company,url,user,password,evidence,
344
     *                                       prefix,defaultUrlParams,debug)
345
     */
346 49
    public function setUp($options = [])
347
    {
348 49
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
349 49
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
350 49
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
351 49
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
352 49
        if (isset($options['evidence'])) {
353 44
            $this->setEvidence($options['evidence']);
354 44
        }
355 49
        $this->setupProperty($options, 'defaultUrlParams');
356 49
        if (isset($options['prefix'])) {
357 44
            $this->setPrefix($options['prefix']);
358 44
        }
359 49
        $this->setupProperty($options, 'debug');
360 49
        $this->updateApiURL();
361 49
    }
362
363
    /**
364
     * Set up one of properties
365
     *
366
     * @param array  $options  array of given properties
367
     * @param string $name     name of property to process
368
     * @param string $constant load default property value from constant
369
     */
370 26
    public function setupProperty($options, $name, $constant = null)
371
    {
372 26
        if (isset($options[$name])) {
373 22
            $this->$name = $options[$name];
374 22
        } else {
375 26
            if (is_null($this->$name) && !empty($constant) && defined($constant)) {
376 26
                $this->$name = constant($constant);
377 26
            }
378
        }
379 26
    }
380
381
    /**
382
     * Inicializace CURL
383
     */
384 72
    public function curlInit()
385
    {
386 72
        $this->curl = \curl_init(); // create curl resource
387 72
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
388 72
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
389 72
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
390 72
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
391 72
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
392 72
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
393 72
        curl_setopt($this->curl, CURLOPT_USERPWD,
394 72
            $this->user.':'.$this->password); // set username and password
395 72
    }
396
397
    /**
398
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
399
     *
400
     *  * 234                              - interní číslo záznamu k načtení
401
     *  * code:LOPATA                      - kód záznamu
402
     *  * BAGR                             - kód záznamu ka načtení
403
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
404
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
405
     *
406
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
407
     */
408 44
    public function processInit($init)
409
    {
410 44
        if (is_integer($init)) {
411 22
            $this->loadFromFlexiBee($init);
412 44
        } elseif (is_array($init)) {
413 22
            $this->takeData($init);
414 22
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
415
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->getEvidenceURL($init)
0 ignored issues
show
Unused Code introduced by
The call to FlexiBeeRO::getEvidenceURL() has too many arguments starting with $init.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
416
                            : $init)));
417
        } else {
418
            $this->loadFromFlexiBee('code:'.str_replace('code:', '', $init));
419
        }
420 44
    }
421
422
    /**
423
     * Set URL prefix
424
     *
425
     * @param string $prefix
426
     */
427 44
    public function setPrefix($prefix)
428
    {
429
        switch ($prefix) {
430 44
            case 'a': //Access
431 44
            case 'c': //Company
432 44
            case 'u': //User
433 44
            case 'g': //License Groups
434 44
            case 'admin':
435 44
            case 'status':
436 44
            case 'login-logout':
437 44
                $this->prefix = '/'.$prefix.'/';
438 44
                break;
439 22
            case null:
440 22
            case '':
441 22
            case '/':
442 22
                $this->prefix = '';
443 22
                break;
444 22
            default:
445 22
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
446 22
        }
447 44
    }
448
449
    /**
450
     * Set communication format.
451
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
452
     *
453
     * @param string $format
454
     * @return boolen format is availble
455
     */
456 22
    public function setFormat($format)
457
    {
458 22
        $result = true;
459 22
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
460
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
461
                === false) {
462
                $result = false;
463
            }
464
        }
465 22
        if ($result === true) {
466 22
            $this->format = $format;
467 22
            $this->updateApiURL();
468 22
        }
469 22
        return $result;
470
    }
471
472
    /**
473
     * Nastaví Evidenci pro Komunikaci.
474
     * Set evidence for communication
475
     *
476
     * @param string $evidence evidence pathName to use
477
     * @return boolean evidence switching status
478
     */
479 44
    public function setEvidence($evidence)
480
    {
481 44
        switch ($this->prefix) {
482 44
            case '/c/':
483 43
                if (array_key_exists($evidence, EvidenceList::$name)) {
484 41
                    $this->evidence = $evidence;
485 41
                    $result         = true;
486 41
                } else {
487 22
                    throw new \Exception(sprintf('Try to set unsupported evidence %s',
488 22
                        $evidence));
489
                }
490 41
                break;
491 3
            default:
492 3
                $this->evidence = $evidence;
493 3
                $result         = true;
494 3
                break;
495 44
        }
496 44
        $this->updateApiURL();
497 44
        return $result;
498
    }
499
500
    /**
501
     * Vrací právě používanou evidenci pro komunikaci
502
     * Obtain current used evidence
503
     *
504
     * @return string
505
     */
506 49
    public function getEvidence()
507
    {
508 49
        return $this->evidence;
509
    }
510
511
    /**
512
     * Set used company.
513
     * Nastaví Firmu.
514
     *
515
     * @param string $company
516
     */
517 22
    public function setCompany($company)
518
    {
519 22
        $this->company = $company;
520 22
    }
521
522
    /**
523
     * Obtain company now used
524
     * Vrací právě používanou firmu
525
     *
526
     * @return string
527
     */
528 22
    public function getCompany()
529
    {
530 22
        return $this->company;
531
    }
532
533
    /**
534
     * Vrací název evidence použité v odpovědích z FlexiBee
535
     *
536
     * @return string
537
     */
538 42
    public function getResponseEvidence()
539
    {
540 42
        switch ($this->evidence) {
541 42
            case 'c':
542
                $evidence = 'company';
543
                break;
544 42
            case 'evidence-list':
545 2
                $evidence = 'evidence';
546 2
                break;
547 40
            default:
548 40
                $evidence = $this->getEvidence();
549 40
                break;
550 42
        }
551 42
        return $evidence;
552
    }
553
554
    /**
555
     * Převede rekurzivně Objekt na pole.
556
     *
557
     * @param object|array $object
558
     *
559
     * @return array
560
     */
561 22
    public static function object2array($object)
562
    {
563 22
        $result = null;
564 22
        if (is_object($object)) {
565 22
            $objectData = get_object_vars($object);
566 22
            if (is_array($objectData) && count($objectData)) {
567 22
                $result = array_map('self::object2array', $objectData);
568 22
            }
569 22
        } else {
570 22
            if (is_array($object)) {
571 22
                foreach ($object as $item => $value) {
572 22
                    $result[$item] = self::object2array($value);
573 22
                }
574 22
            } else {
575 22
                $result = $object;
576
            }
577
        }
578
579 22
        return $result;
580
    }
581
582
    /**
583
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
584
     *
585
     * @param object|array $object
586
     *
587
     * @return array
588
     */
589 22
    public static function objectToID($object)
590
    {
591 22
        $resultID = null;
592 22
        if (is_object($object)) {
593 22
            $resultID = $object->__toString();
594 22
        } else {
595 22
            if (is_array($object)) {
596 22
                foreach ($object as $item => $value) {
597 22
                    $resultID[$item] = self::objectToID($value);
598 22
                }
599 22
            } else { //String
600 22
                $resultID = $object;
601
            }
602
        }
603
604 22
        return $resultID;
605
    }
606
607
    /**
608
     * Return basic URL for used Evidence
609
     *
610
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
611
     *
612
     * @return string Evidence URL
613
     */
614 47
    public function getEvidenceURL()
615
    {
616 47
        $evidenceUrl = $this->url.$this->prefix.$this->company;
617 47
        $evidence    = $this->getEvidence();
618 47
        if (!empty($evidence)) {
619 45
            $evidenceUrl .= '/'.$evidence;
620 45
        }
621 47
        return $evidenceUrl;
622
    }
623
624
    /**
625
     * Add suffix to Evidence URL
626
     *
627
     * @param string $urlSuffix
628
     *
629
     * @return string
630
     */
631
    public function evidenceUrlWithSuffix($urlSuffix)
632
    {
633
        $evidenceUrl = $this->getEvidenceUrl();
634
        if (!empty($urlSuffix)) {
635
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
636
                != '?')) {
637
                $evidenceUrl .= '/';
638
            }
639
            $evidenceUrl .= $urlSuffix;
640
        }
641
        return $evidenceUrl;
642
    }
643
644
    /**
645
     * Update $this->apiURL
646
     */
647 26
    public function updateApiURL()
648
    {
649 26
        $this->apiURL = $this->getEvidenceURL();
650 26
        $id           = $this->__toString();
651 26
        if (!empty($id)) {
652 13
            $this->apiURL .= '/'.urlencode($id);
653 13
        }
654 26
        $this->apiURL .= '.'.$this->format;
655 26
    }
656
657
    /**
658
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
659
     *
660
     * @param string $urlSuffix část URL za identifikátorem firmy.
661
     * @param string $method    HTTP/REST metoda
662
     * @param string $format    Requested format
663
     * @return array|boolean Výsledek operace
664
     */
665 42
    public function performRequest($urlSuffix = null, $method = 'GET',
666
                                   $format = null)
667
    {
668 42
        $this->rowCount = null;
669
670 42
        if (preg_match('/^http/', $urlSuffix)) {
671 22
            $url = $urlSuffix;
672 42
        } elseif ($urlSuffix[0] == '/') {
673
            $url = $this->url.$urlSuffix;
674
        } else {
675 20
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
676
        }
677
678 42
        $responseCode = $this->doCurlRequest($url, $method, $format);
679
680 42
        return strlen($this->lastCurlResponse) ? $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
681 42
                    $this->responseFormat), $responseCode) : null;
682
    }
683
684
    /**
685
     * Parse Raw FlexiBee response in several formats
686
     *
687
     * @param string $responseRaw raw response body
688
     * @param string $format      Raw Response format json|xml|etc
689
     *
690
     * @return array
691
     */
692 22
    public function rawResponseToArray($responseRaw, $format)
693
    {
694
        switch ($format) {
695 22
            case 'json':
696 22
                $responseDecoded = json_decode($responseRaw, true, 10);
697 22
                $decodeError     = json_last_error_msg();
698 22
                if ($decodeError == 'No error') {
699 22
                    if (array_key_exists($this->nameSpace, $responseDecoded)) {
700 21
                        $responseDecoded = $responseDecoded[$this->nameSpace];
701 21
                    }
702 22
                } else {
703
                    $this->addStatusMessage('JSON Decoder: '.$decodeError,
704
                        'error');
705
                    $this->addStatusMessage($responseRaw, 'debug');
706
                }
707 22
                break;
708
            case 'xml':
709
                $responseDecoded = self::xml2array($this->lastCurlResponse);
710
                break;
711
            case 'txt':
712
            default:
713
                $responseDecoded = $this->lastCurlResponse;
714
                break;
715
        }
716 22
        return $responseDecoded;
717
    }
718
719
    /**
720
     * Parse Response array
721
     *
722
     * @param array $responseDecoded
723
     * @param int $responseCode Request Response Code
724
     *
725
     * @return array main data part of response
726
     */
727 22
    public function parseResponse($responseDecoded, $responseCode)
728
    {
729 22
        $response = null;
730
        switch ($responseCode) {
731 22
            case 201: //Success Write
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
732
                if (isset($responseDecoded[$this->resultField][0]['id'])) {
733
                    $this->lastInsertedID = $responseDecoded[$this->resultField][0]['id'];
734
                    $this->setMyKey($this->lastInsertedID);
735
                    $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
736
                } else {
737
                    $this->lastInsertedID = null;
738
                }
739 22
            case 200: //Success Read
740 13
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
741 13
                if (isset($responseDecoded['@rowCount'])) {
742
                    $this->rowCount = (int) $responseDecoded['@rowCount'];
743
                }
744 13
                break;
745
746 9
            case 500: // Internal Server Error
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
747
                if ($this->debug === true) {
748
                    $this->error500Reporter($responseDecoded);
749
                }
750 9
            case 404: // Page not found
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
751 8
                if ($this->ignoreNotFound === true) {
752
                    break;
753
                }
754 9
            case 400: //Bad Request parameters
755 9
            default: //Something goes wrong
756 9
                $this->addStatusMessage($this->curlInfo['url'], 'warning');
757 9
                if (is_array($responseDecoded)) {
758 9
                    $this->parseError($responseDecoded);
759 9
                }
760 9
                $this->logResult($responseDecoded, $this->curlInfo['url']);
761 9
                break;
762
        }
763 22
        return $response;
764
    }
765
766
    /**
767
     * Parse error message response
768
     *
769
     * @param array $responseDecoded
770
     * @return int number of errors processed
771
     */
772 9
    public function parseError(array $responseDecoded)
773
    {
774 9
        if (array_key_exists('results', $responseDecoded)) {
775
            $this->errors = $responseDecoded['results'][0]['errors'];
776
        } else {
777 9
            if (array_key_exists('message', $responseDecoded)) {
778 8
                $this->errors = [['message' => $responseDecoded['message']]];
779 8
            }
780
        }
781 9
        return count($this->errors);
782
    }
783
784
    /**
785
     * Vykonej HTTP požadavek
786
     *
787
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
788
     * @param string $url    URL požadavku
789
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
790
     * @param string $format požadovaný formát komunikace
791
     * @return int HTTP Response CODE
792
     */
793 22
    public function doCurlRequest($url, $method, $format = null)
794
    {
795 22
        if (is_null($format)) {
796 22
            $format = $this->format;
797 22
        }
798 22
        curl_setopt($this->curl, CURLOPT_URL, $url);
799
// Nastavení samotné operace
800 22
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
801
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
802 22
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
803
804 22
        $httpHeaders = $this->defaultHttpHeaders;
805
806 22
        $formats = Formats::bySuffix();
807
808 22
        if (!isset($httpHeaders['Accept'])) {
809 22
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
810 22
        }
811 22
        if (!isset($httpHeaders['Content-Type'])) {
812 22
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
813 22
        }
814 22
        $httpHeadersFinal = [];
815 22
        foreach ($httpHeaders as $key => $value) {
816 22
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
817 22
                $value .= ' v'.self::$libVersion;
818 22
            }
819 22
            $httpHeadersFinal[] = $key.': '.$value;
820 22
        }
821
822 22
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
823
824
// Proveď samotnou operaci
825 22
        $this->lastCurlResponse            = curl_exec($this->curl);
826 22
        $this->curlInfo                    = curl_getinfo($this->curl);
827 22
        $this->curlInfo['when']            = microtime();
828 22
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
829 22
        $this->responseFormat              = Formats::contentTypeToSuffix($this->curlInfo['content_type']);
830 22
        $this->lastResponseCode            = $this->curlInfo['http_code'];
831 22
        $this->lastCurlError               = curl_error($this->curl);
832 22
        if (strlen($this->lastCurlError)) {
833
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
834
                    $this->lastResponseCode, $this->lastCurlError), 'error');
835
        }
836
837 22
        if ($this->debug === true) {
838
            $this->saveDebugFiles();
839
        }
840
841 22
        return $this->lastResponseCode;
842
    }
843
844
    /**
845
     * Nastaví druh prováděné akce.
846
     *
847
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
848
     * @param string $action
849
     * @return boolean
850
     */
851 19
    public function setAction($action)
852
    {
853 19
        $result           = false;
854 19
        $actionsAvailable = $this->getActionsInfo();
855 19
        if (is_array($actionsAvailable) && array_key_exists($action,
856 19
                $actionsAvailable)) {
857 15
            $this->action = $action;
858 15
            $result       = true;
859 15
        }
860 19
        return $result;
861
    }
862
863
    /**
864
     * Convert XML to array.
865
     *
866
     * @param string $xml
867
     *
868
     * @return array
869
     */
870 22
    public static function xml2array($xml)
871
    {
872 22
        $arr = [];
873
874 22
        if (is_string($xml)) {
875 22
            $xml = simplexml_load_string($xml);
876 22
        }
877
878 22
        foreach ($xml->children() as $r) {
879 22
            if (count($r->children()) == 0) {
880 22
                $arr[$r->getName()] = strval($r);
881 22
            } else {
882 22
                $arr[$r->getName()][] = self::xml2array($r);
883
            }
884 22
        }
885
886 22
        return $arr;
887
    }
888
889
    /**
890
     * Odpojení od FlexiBee.
891
     */
892 22
    public function disconnect()
893
    {
894 22
        if (is_resource($this->curl)) {
895 22
            curl_close($this->curl);
896 22
        }
897 22
        $this->curl = null;
898 22
    }
899
900
    /**
901
     * Disconnect CURL befere pass away
902
     */
903 22
    public function __destruct()
904
    {
905 22
        $this->disconnect();
906 22
    }
907
908
    /**
909
     * Načte řádek dat z FlexiBee.
910
     *
911
     * @param int $recordID id požadovaného záznamu
912
     *
913
     * @return array
914
     */
915 22
    public function getFlexiRow($recordID)
916
    {
917 22
        $record   = null;
918 22
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
919 22
        if (isset($response[$this->evidence])) {
920
            $record = $response[$this->evidence][0];
921
        }
922
923 22
        return $record;
924
    }
925
926
    /**
927
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
928
     *
929
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
930
     * @param array $conditions pole podmínek   - rendrují se do ()
931
     * @param array $urlParams  pole parametrů  - rendrují za ?
932
     */
933
    public function extractUrlParams(&$conditions, &$urlParams)
934
    {
935
        foreach ($this->urlParams as $urlParam) {
936
            if (isset($conditions[$urlParam])) {
937
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
938
            }
939
        }
940
    }
941
942
    /**
943
     * Načte data z FlexiBee.
944
     *
945
     * @param string $suffix     dotaz
946
     * @param string|array $conditions Volitelný filtrovací výraz
947
     *
948 44
     * @return array Data obtained
949
     */
950 44
    public function getFlexiData($suffix = null, $conditions = null)
951
    {
952 44
        $finalUrl  = '';
953 4
        $urlParams = $this->defaultUrlParams;
954
955
        if (!is_null($conditions)) {
956
            if (is_array($conditions)) {
957
                $this->extractUrlParams($conditions, $urlParams);
958 4
                $conditions = $this->flexiUrl($conditions);
959
            }
960
961 4
            if (strlen($conditions) && ($conditions[0] != '/')) {
962
                $conditions = rawurlencode('('.($conditions).')');
963 44
            }
964 22
        }
965 22
966 22
        if (strlen($suffix)) {
967 22
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
968
                $finalUrl = $suffix;
969 44
            }
970
        }
971 22
972 22
        $finalUrl .= $conditions;
973
974
        if (count($urlParams)) {
975 22
            if (strstr($finalUrl, '?')) {
976
                $finalUrl .= '&';
977 22
            } else {
978 22
                $finalUrl .= '?';
979
            }
980 22
            $finalUrl .= http_build_query($urlParams);
981
        }
982 22
983 22
        $transactions = $this->performRequest($finalUrl, 'GET');
984 22
985 13
        $responseEvidence = $this->getResponseEvidence();
986 13
        if (is_array($transactions) && array_key_exists($responseEvidence,
987
                $transactions)) {
988
            $result = $transactions[$responseEvidence];
989 13
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
990 9
                $result = null; // Response is empty Array
991
            }
992
        } else {
993 22
            $result = $transactions;
994
        }
995
996
        return $result;
997
    }
998
999
    /**
1000
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1001
     * Read FlexiBee record and store it inside od object
1002
     *
1003
     * @param int $id ID or conditions
1004 44
     *
1005
     * @return int počet načtených položek
1006 44
     */
1007 44
    public function loadFromFlexiBee($id = null)
1008 22
    {
1009 22
        $data = [];
1010 44
        if (is_null($id)) {
1011
            $id = $this->getMyKey();
1012
        }
1013 44
        if (is_array($id)) {
1014 44
            $id = '('.self::flexiUrl($id).')';
1015 44
        }
1016 22
        $flexidata    = $this->getFlexiData($this->getEvidenceUrl().'/'.$id);
1017 22
        $this->apiURL = $this->curlInfo['url'];
1018 44
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1019
            $data = current($flexidata);
1020
        }
1021
        return $this->takeData($data);
1022
    }
1023
1024
    /**
1025
     * Převede data do Json formátu pro FlexiBee.
1026
     * Convert data to FlexiBee like Json format
1027
     *
1028
     * @param array $data
1029 22
     *
1030
     * @return string
1031
     */
1032 22
    public function jsonizeData($data)
1033 22
    {
1034 22
        $dataToJsonize = [
1035 22
            $this->nameSpace => [
1036 22
                '@version' => $this->protoVersion,
1037
                $this->evidence => $this->objectToID($data),
1038 22
            ],
1039 15
        ];
1040 15
1041 15 View Code Duplication
        if (!is_null($this->action)) {
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...
1042
            $dataToJsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1043 22
            $this->action                                               = null;
1044
        }
1045
1046 View Code Duplication
        if (!is_null($this->filter)) {
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...
1047 22
            $dataToJsonize[$this->nameSpace][$this->evidence.'@filter'] = $this->filter;
1048
        }
1049
1050
        return json_encode($dataToJsonize);
1051
    }
1052
1053
    /**
1054
     * Test if given record ID exists in FlexiBee.
1055 22
     *
1056
     * @param string|int $identifer
1057 22
     */
1058
    public function idExists($identifer = null)
1059
    {
1060 22
        if (is_null($identifer)) {
1061 22
            $identifer = $this->getMyKey();
1062 22
        }
1063
        $flexiData = $this->getFlexiData(
1064
            'detail=custom:'.$this->getmyKeyColumn(),
1065
            [$this->getmyKeyColumn() => $identifer]);
1066
1067
        return $flexiData;
1068
    }
1069
1070
    /**
1071
     * Test if given record exists in FlexiBee.
1072
     *
1073
     * @param array $data
1074
     * @return boolean Record presence status
1075
     */
1076
    public function recordExists($data = [])
1077
    {
1078
1079
        if (empty($data)) {
1080
            $data = $this->getData();
1081
        }
1082
1083
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1084
            self::flexiUrl($data));
0 ignored issues
show
Documentation introduced by
self::flexiUrl($data) is of type string, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1085
1086
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1087
            || !count($res[0])) {
1088
            $found = false;
1089
        } else {
1090
            $found = true;
1091
        }
1092
        return $found;
1093
    }
1094
1095
    /**
1096
     * Vrací z FlexiBee sloupečky podle podmínek.
1097
     *
1098
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1099
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1100
     *                                     sloupečku
1101
     * @return array
1102
     */
1103
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1104
    {
1105
        if (is_int($conditions)) {
1106
            $conditions = [$this->getmyKeyColumn() => $conditions];
1107
        }
1108
1109
        $flexiData = $this->getFlexiData('', $conditions);
1110
1111
        if (!is_null($indexBy)) {
1112
            $flexiData = $this->reindexArrayBy($flexiData);
1113
        }
1114
1115
        return $flexiData;
1116
    }
1117
1118
    /**
1119
     * Vrací z FlexiBee sloupečky podle podmínek.
1120
     *
1121
     * @param string[] $columnsList seznam položek
1122
     * @param array    $conditions  pole podmínek nebo ID záznamu
1123
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1124 22
     *
1125
     * @return array
1126
     */
1127 22
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1128 22
                                           $indexBy = null)
1129 22
    {
1130
        $detail = 'full';
1131 22
        switch (gettype($columnsList)) {
1132 22
            case 'integer': //Record ID
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1133 22
                $conditions = [$this->getmyKeyColumn() => $conditions];
1134 22
            case 'array': //Few Conditions
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1135 22
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1136 22
                        $columnsList)) {
1137 22
                    $columnsList[] = $indexBy;
1138 22
                }
1139
                $columns = implode(',', array_unique($columnsList));
1140 22
                $detail  = 'custom:'.$columns;
1141
            default:
1142
                switch ($columnsList) {
1143 22
                    case 'id':
1144
                        $detail = 'id';
1145
                        break;
1146 22
                    case 'summary':
1147 22
                        $detail = 'summary';
1148 22
                        break;
1149 22
                    default:
1150 22
                        break;
1151
                }
1152 22
                break;
1153
        }
1154
1155
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1156
1157
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1158
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1159
        }
1160
1161
        return $flexiData;
1162
    }
1163
1164
    /**
1165
     * Vrací kód záznamu.
1166
     * Obtain record CODE
1167
     *
1168
     * @param mixed $data
1169 22
     *
1170
     * @return string
1171 22
     */
1172
    public function getKod($data = null, $unique = true)
1173 22
    {
1174 22
        $kod = null;
1175 22
1176
        if (is_null($data)) {
1177 22
            $data = $this->getData();
1178 22
        }
1179 22
1180
        if (is_string($data)) {
1181 22
            $data = [$this->nameColumn => $data];
1182 22
        }
1183 22
1184 22
        if (isset($data['kod'])) {
1185 22
            $kod = $data['kod'];
1186 22
        } else {
1187 22
            if (isset($data[$this->nameColumn])) {
1188 22
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1189 22
                    \Ease\Sand::rip($data[$this->nameColumn]));
1190 22
            } else {
1191
                if (isset($data[$this->myKeyColumn])) {
1192
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1193
                }
1194 22
            }
1195 22
        }
1196 22
1197
        if (!strlen($kod)) {
1198 22
            $kod = 'NOTSET';
1199 22
        }
1200 22
1201 22
        if (strlen($kod) > 18) {
1202
            $kodfinal = strtoupper(substr($kod, 0, 18));
1203
        } else {
1204 22
            $kodfinal = strtoupper($kod);
1205 22
        }
1206 22
1207 22
        if ($unique) {
1208 22
            $counter = 0;
1209 22
            if (count($this->codes)) {
1210 22
                foreach ($this->codes as $codesearch => $keystring) {
1211 22
                    if (strstr($codesearch, $kodfinal)) {
1212 22
                        ++$counter;
1213 22
                    }
1214 22
                }
1215 22
            }
1216
            if ($counter) {
1217 22
                $kodfinal = $kodfinal.$counter;
1218 22
            }
1219
1220 22
            $this->codes[$kodfinal] = $kod;
1221
        }
1222
1223
        return $kodfinal;
1224
    }
1225
1226
    /**
1227
     * Write Operation Result.
1228
     *
1229
     * @param array  $resultData
1230 31
     * @param string $url        URL
1231
     * @return boolean Log save success
1232 31
     */
1233 31
    public function logResult($resultData = null, $url = null)
1234 30
    {
1235 8
        $logResult = false;
1236 8
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1237 30
            if (isset($resultData['message'])) {
1238 30
                $this->addStatusMessage($resultData['message'], 'warning');
1239 30
            }
1240 30
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1241 31
                'warning');
1242
            unset($url);
1243
        }
1244 31
        if (is_null($resultData)) {
1245 23
            $resultData = $this->lastResult;
1246 23
        }
1247
        if (isset($url)) {
1248 31
            $this->logger->addStatusMessage(urldecode($url));
1249 22
        }
1250 22
1251 22
        if (isset($resultData['results'])) {
1252 22
            if ($resultData['success'] == 'false') {
1253
                $status = 'error';
1254 22
            } else {
1255 22
                $status = 'success';
1256 22
            }
1257 22
            foreach ($resultData['results'] as $result) {
1258 22
                if (isset($result['request-id'])) {
1259
                    $rid = $result['request-id'];
1260 22
                } else {
1261 22
                    $rid = '';
1262 22
                }
1263 22
                if (isset($result['errors'])) {
1264
                    foreach ($result['errors'] as $error) {
1265
                        $message = $error['message'];
1266 22
                        if (isset($error['for'])) {
1267
                            $message .= ' for: '.$error['for'];
1268
                        }
1269 22
                        if (isset($error['value'])) {
1270
                            $message .= ' value:'.$error['value'];
1271
                        }
1272 22
                        if (isset($error['code'])) {
1273 22
                            $message .= ' code:'.$error['code'];
1274 22
                        }
1275 22
                        $this->addStatusMessage($rid.': '.$message, $status);
1276 22
                    }
1277 31
                }
1278
            }
1279
        }
1280
        return $logResult;
1281
    }
1282
1283
    /**
1284
     * Save RAW Curl Request & Response to files in Temp directory
1285
     */
1286
    public function saveDebugFiles()
1287
    {
1288
        $tmpdir   = sys_get_temp_dir();
1289
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1290
        $reqname  = $tmpdir.'/request-'.$fname;
1291
        $respname = $tmpdir.'/response-'.$fname;
1292
        file_put_contents($reqname, $this->postFields);
1293
        file_put_contents($respname, $this->lastCurlResponse);
1294
    }
1295
1296
    /**
1297
     * Připraví data pro odeslání do FlexiBee
1298
     *
1299
     * @param string $data
1300
     */
1301
    public function setPostFields($data)
1302
    {
1303
        $this->postFields = $data;
1304
    }
1305
1306
    /**
1307
     * Generuje fragment url pro filtrování.
1308
     *
1309
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1310
     *
1311
     * @param array  $data
1312
     * @param string $joiner default and/or
1313
     * @param string $defop  default operator
1314 22
     *
1315
     * @return string
1316 22
     */
1317
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1318 22
    {
1319 22
        $parts = [];
1320 22
1321 22
        foreach ($data as $column => $value) {
1322 22
            if (is_integer($data[$column]) || is_float($data[$column])) {
1323 22
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1324 22
            } elseif (is_bool($data[$column])) {
1325 22
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1326
            } elseif (is_null($data[$column])) {
1327 22
                $parts[$column] = $column." is null";
1328 22
            } else {
1329 22
                switch ($value) {
1330 22
                    case '!null':
1331 22
                        $parts[$column] = $column." is not null";
1332
                        break;
1333
                    case 'is empty':
1334 22
                    case 'is not empty':
1335 22
                        $parts[$column] = $column.' '.$value;
1336
                        break;
1337
                    default:
1338 22
                        if ($column == 'stitky') {
1339
                            $parts[$column] = $column."='".self::code($data[$column])."'";
1340 22
                        } else {
1341 22
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1342
                        }
1343 22
                        break;
1344 22
                }
1345
            }
1346
        }
1347
        return implode(' '.$joiner.' ', $parts);
1348
    }
1349
1350
    /**
1351
     * Obtain record/object identificator code: or id:
1352
     * Vrací identifikátor objektu code: nebo id:
1353
     *
1354 49
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1355
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1356 49
     */
1357 49
    public function getRecordID()
1358 32
    {
1359 32
        $myCode = $this->getDataValue('kod');
1360 49
        if ($myCode) {
1361 49
            $id = 'code:'.$myCode;
1362 9
        } else {
1363 9
            $id = $this->getDataValue('id');
1364 9
            if (($this->debug === true) && is_null($id)) {
1365
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1366 49
                    'warning');
1367
            }
1368
        }
1369
        return is_numeric($id) ? intval($id) : strval($id);
1370
    }
1371
1372
    /**
1373
     * Obtain record/object identificator code: or id:
1374
     * Vrací identifikátor objektu code: nebo id:
1375
     *
1376 49
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1377
     * @return string indentifikátor záznamu reprezentovaného objektem
1378 49
     */
1379
    public function __toString()
1380
    {
1381
        return strval($this->getRecordID());
1382
    }
1383
1384
    /**
1385
     * Gives you FlexiPeeHP class name for Given Evidence
1386
     *
1387 22
     * @param string $evidence
1388
     * @return string Class name
1389 22
     */
1390
    public static function evidenceToClassName($evidence)
1391
    {
1392
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1393
    }
1394
1395
    /**
1396
     * Obtain ID of first record in evidence
1397 22
     *
1398
     * @return string|null id or null if no records
1399 22
     */
1400 22
    public function getFirstRecordID()
1401 22
    {
1402
        $firstID    = null;
1403
        $firstIdRaw = $this->getColumnsFromFlexibee(['id'],
1404
            ['limit' => 1, 'order' => 'id'], 'id');
1405
        if (count($firstIdRaw)) {
1406
            $firstID = (int) current($firstIdRaw)['id'];
1407
        }
1408
        return $firstID;
1409
    }
1410
1411
    /**
1412
     * Vrací hodnotu daného externího ID
1413
     *
1414 22
     * @param string $want Which ? If empty,you obtain the first one.
1415
     * @return string
1416 22
     */
1417 22
    public function getExternalID($want = null)
1418 22
    {
1419
        $extid = null;
1420
        $ids   = $this->getDataValue('external-ids');
1421
        if (is_null($want)) {
1422
            if (count($ids)) {
1423 22
                $extid = current($ids);
1424
            }
1425
        } else {
1426
            if (!is_null($ids) && is_array($ids)) {
1427
                foreach ($ids as $id) {
1428
                    if (strstr($id, 'ext:'.$want)) {
1429
                        $extid = str_replace('ext:'.$want.':', '', $id);
1430
                    }
1431 22
                }
1432
            }
1433
        }
1434
        return $extid;
1435
    }
1436
1437
    /**
1438
     * Obtain actual GlobalVersion
1439
     * Vrací aktuální globální verzi změn
1440
     *
1441 21
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1442
     * @return type
1443 21
     */
1444 21
    public function getGlobalVersion()
1445 21
    {
1446 21
        $globalVersion = null;
1447
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1448
            $this->getFlexiData(null,
1449
                ['add-global-version' => 'true', 'limit' => 1]);
1450
        }
1451
1452
        if (isset($this->lastResult['@globalVersion'])) {
1453
            $globalVersion = intval($this->lastResult['@globalVersion']);
1454
        }
1455
1456
        return $globalVersion;
1457
    }
1458
1459
    /**
1460
     * Obtain content type of last response
1461 22
     *
1462
     * @return string
1463 22
     */
1464 22
    public function getResponseFormat()
1465 22
    {
1466
        if (isset($this->curlInfo['content_type'])) {
1467
            $responseFormat = $this->curlInfo['content_type'];
1468 22
        } else {
1469
            $responseFormat = null;
1470
        }
1471
        return $responseFormat;
1472
    }
1473
1474
    /**
1475
     * Return the same response format for one and multiplete results
1476
     *
1477 35
     * @param array $responseBody
1478
     * @return array
1479 35
     */
1480 35
    public function unifyResponseFormat($responseBody)
1481 22
    {
1482 22
        if (!is_array($responseBody) || array_key_exists('message',
1483 35
                $responseBody)) { //Unifi response format
1484 35
            $response = $responseBody;
1485 35
        } else {
1486 35
            $evidence = $this->getResponseEvidence();
1487 35
            if (array_key_exists($evidence, $responseBody)) {
1488 35
                $response        = [];
1489 35
                $evidenceContent = $responseBody[$evidence];
1490 22
                if (array_key_exists(0, $evidenceContent)) {
1491
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1492 35
                } else {
1493
                    $response[$evidence][0] = $evidenceContent; //One result
1494
                }
1495
            } else {
1496
                if (isset($responseBody['priloha'])) {
1497
                    $response = $responseBody['priloha'];
1498
                } else {
1499
                    $response = $responseBody;
1500 35
                }
1501
            }
1502
        }
1503
        return $response;
1504
    }
1505
1506
    /**
1507
     * Obtain structure for current (or given) evidence
1508
     *
1509 22
     * @param string $evidence
1510
     * @return array Evidence structure
1511 22
     */
1512 22 View Code Duplication
    public function getColumnsInfo($evidence = null)
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...
1513 22
    {
1514 22
        $columnsInfo = null;
1515 22
        if (is_null($evidence)) {
1516 22
            $evidence = $this->getEvidence();
1517 21
        }
1518 21
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1519 22
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1520
            $columnsInfo = Properties::$$propsName;
1521
        }
1522
        return $columnsInfo;
1523
    }
1524
1525
    /**
1526
     * Obtain actions for current (or given) evidence
1527
     *
1528 22
     * @param string $evidence
1529
     * @return array Evidence structure
1530 22
     */
1531 22 View Code Duplication
    public function getActionsInfo($evidence = null)
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...
1532 22
    {
1533 22
        $actionsInfo = null;
1534 22
        if (is_null($evidence)) {
1535 22
            $evidence = $this->getEvidence();
1536 21
        }
1537 21
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1538 22
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1539
            $actionsInfo = Actions::$$propsName;
1540
        }
1541
        return $actionsInfo;
1542
    }
1543
1544
    /**
1545
     * Obtain relations for current (or given) evidence
1546
     *
1547 22
     * @param string $evidence
1548
     * @return array Evidence structure
1549 22
     */
1550 22
    public function getRelationsInfo($evidence = null)
1551 22
    {
1552 22
        $relationsInfo = null;
1553 22
        if (is_null($evidence)) {
1554 22
            $evidence = $this->getEvidence();
1555 19
        }
1556 19
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1557 22
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1558
            $relationsInfo = Relations::$$propsName;
1559
        }
1560
        return $relationsInfo;
1561
    }
1562
1563
    /**
1564
     * Obtain info for current (or given) evidence
1565
     *
1566 22
     * @param string $evidence
1567
     * @return array Evidence info
1568 22
     */
1569 22 View Code Duplication
    public function getEvidenceInfo($evidence = null)
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...
1570 22
    {
1571 22
        $evidencesInfo = null;
1572 22
        if (is_null($evidence)) {
1573 16
            $evidence = $this->getEvidence();
1574 16
        }
1575 22
        if (isset(EvidenceList::$evidences[$evidence])) {
1576
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1577
        }
1578
        return $evidencesInfo;
1579
    }
1580
1581
    /**
1582
     * Obtain name for current (or given) evidence path
1583
     *
1584 22
     * @param string $evidence Evidence Path
1585
     * @return array Evidence info
1586 22
     */
1587 22 View Code Duplication
    public function getEvidenceName($evidence = null)
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...
1588 22
    {
1589 22
        $evidenceName = null;
1590 22
        if (is_null($evidence)) {
1591 16
            $evidence = $this->getEvidence();
1592 16
        }
1593 22
        if (isset(EvidenceList::$name[$evidence])) {
1594
            $evidenceName = EvidenceList::$name[$evidence];
1595
        }
1596
        return $evidenceName;
1597
    }
1598
1599
    /**
1600
     * Perform given action (if availble) on current evidence/record
1601
     * @url https://demo.flexibee.eu/devdoc/actions
1602
     *
1603
     * @param string $action one of evidence actions
1604 15
     * @param string $method ext|int External method call operation in URL.
1605
     *                               Internal add the @action element to request body
1606 15
     */
1607
    public function performAction($action, $method = 'ext')
1608 15
    {
1609 15
        $actionsAvailble = $this->getActionsInfo();
1610 15
1611 15
        if (is_array($actionsAvailble) && array_key_exists($action,
1612 15
                $actionsAvailble)) {
1613
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1614
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1615
                case 'ONLY_WITH_INSTANCE': //Add instance
1616 15
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1617 15
                    break;
1618 15
1619 15
                default:
1620
                    $urlSuffix = '/'.$action;
1621
                    break;
1622 15
            }
1623
1624
            switch ($method) {
1625
                case 'int':
1626
                    $this->setAction($action);
1627
                    $this->setPostFields($this->jsonizeData($this->getData()));
1628 15
                    $result = $this->performRequest(null, 'POST');
1629 15
                    break;
1630 15
1631 15
                default:
1632 15
                    $result = $this->performRequest($urlSuffix, 'GET');
1633
                    break;
1634
            }
1635
        } else {
1636
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1637 15
                $action, $this->getEvidence()));
1638
        }
1639
1640
        return $result;
1641
    }
1642
1643
    /**
1644
     * Save current object to file
1645 22
     *
1646
     * @param string $destfile path to file
1647 22
     */
1648
    public function saveResponseToFile($destfile)
1649
    {
1650 22
        if (strlen($this->lastCurlResponse)) {
1651 22
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1652
        }
1653
        file_put_contents($destfile, $this->lastCurlResponse);
1654
    }
1655
1656
    /**
1657
     * Obtain established relations listing
1658
     *
1659
     * @return array Null or Relations
1660
     */
1661
    public function getVazby($id = null)
1662
    {
1663
        if (is_null($id)) {
1664
            $id = $this->getRecordID();
1665
        }
1666
        if (!empty($id)) {
1667
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
1668
                ['relations' => 'vazby', 'id' => $id]);
1669
            $vazby    = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby']
1670
                    : null;
1671
        } else {
1672
            throw new \Exception(_('ID requied to get record relations '));
1673
        }
1674
        return $vazby;
1675
    }
1676
1677
    /**
1678
     * Gives You URL for Current Record in FlexiBee web interface
1679
     *
1680
     * @return string url
1681
     */
1682
    public function getFlexiBeeURL()
1683
    {
1684
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1685
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1686
                : '';
1687
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1688
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1689
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1690
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1691
        $pass       = ($user || $pass) ? "$pass@" : '';
1692
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1693
        return $scheme.$user.$pass.$host.$port.$path;
1694
    }
1695
1696
    /**
1697
     * Set Record Key
1698
     *
1699
     * @param int|string $myKeyValue
1700
     * @return boolean
1701
     */
1702
    public function setMyKey($myKeyValue)
1703
    {
1704
        $res = parent::setMyKey($myKeyValue);
1705
        $this->updateApiURL();
1706
        return $res;
1707
    }
1708
1709
    /**
1710
     * Set or get ignore not found pages flag
1711
     *
1712
     * @param boolean $ignore set flag to
1713
     *
1714
     * @return boolean get flag state
1715
     */
1716
    public function ignore404($ignore = null)
1717
    {
1718
        if (!is_null($ignore)) {
1719
            $this->ignoreNotFound = $ignore;
1720
        }
1721
        return $this->ignoreNotFound;
1722
    }
1723
1724
    /**
1725
     * Send Document by mail
1726
     *
1727
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1728
     *
1729
     * @param string $to
1730
     * @param string $subject
1731
     * @param string $body Email Text
1732
     *
1733
     * @return int http response code
1734
     */
1735
    public function sendByMail($to, $subject, $body, $cc = null)
1736
    {
1737
        $this->setPostFields($body);
1738
        $result = $this->doCurlRequest(urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1739
            , 'PUT', 'xml');
1740
        return $result == 200;
1741
    }
1742
1743
    /**
1744
     * Send all unsent Invoices by mail
1745
     *
1746
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1747
     * @return int http response code
1748
     */
1749
    public function sendUnsent()
1750
    {
1751
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT', 'xml');
1752
    }
1753
1754
    /**
1755
     * FlexiBee date to PHP DateTime
1756
     *
1757
     * @param string $flexidate
1758
     *
1759
     * @return \DateTime | false
1760
     */
1761
    public static function flexiDateToDateTime($flexidate)
1762
    {
1763
        return \DateTime::createFromFormat('Y-m-jO', $flexidate);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression \DateTime::createFromFor...('Y-m-jO', $flexidate); of type DateTime|false adds false to the return on line 1763 which is incompatible with the return type documented by FlexiPeeHP\FlexiBeeRO::flexiDateToDateTime of type DateTime. It seems like you forgot to handle an error condition.
Loading history...
1764
    }
1765
1766
    /**
1767
     * Získá dokument v daném formátu
1768
     * Obtain document in given format
1769
     *
1770
     * @param string $format  pdf/csv/xml/json/ ...
1771
     *
1772
     * @return string|null filename downloaded or none
1773
     */
1774
    public function getInFormat($format)
1775
    {
1776
        $response = null;
1777
        if ($this->setFormat($format)) {
1778
            if (($this->doCurlRequest(($format == 'html') ? $this->apiURL.'?inDesktopApp=true'
1779
                            : $this->apiURL, 'GET') == 200)) {
1780
                $response = $this->lastCurlResponse;
1781
            }
1782
        }
1783
        return $response;
1784
    }
1785
1786
    /**
1787
     * Uloží dokument v daném formátu do složky v systému souborů
1788
     * Save document in given format to directory in filesystem
1789
     *
1790
     * @param string $format  pdf/csv/xml/json/ ...
1791
     * @param string $destDir where to put file (prefix)
1792
     *
1793
     * @return string|null filename downloaded or none
1794
     */
1795
    public function downloadInFormat($format, $destDir = './')
1796
    {
1797
        $fileOnDisk = null;
1798
        if ($this->setFormat($format)) {
1799
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1800
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1801
                    $this->lastCurlResponse) !== false)) {
1802
                $fileOnDisk = $downloadTo;
1803
            }
1804
        }
1805
        return $fileOnDisk;
1806
    }
1807
1808
    /**
1809
     * Compile and send Report about Error500 to FlexiBee developers
1810
     * If FlexiBee is running on localost try also include java backtrace
1811
     *
1812
     * @param array $errorResponse result of parseError();
1813
     */
1814
    public function error500Reporter($errorResponse)
1815
    {
1816
        $ur = str_replace('/c/'.$this->company, '',
1817
            str_replace($this->url, '', $this->curlInfo['url']));
1818
        if (!array_key_exists($ur, $this->reports)) {
1819
            $tmpdir   = sys_get_temp_dir();
1820
            $myTime   = $this->curlInfo['when'];
1821
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
1822
            file_put_contents($curlname,
1823
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
1824
1825
            $report = new \Ease\Mailer($this->reportRecipient,
1826
                'Error report 500 - '.$ur);
1827
1828
            $d     = dir($tmpdir);
1829
            while (false !== ($entry = $d->read())) {
1830
                if (strstr($entry, $myTime)) {
1831
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
1832
                    $mime = Formats::suffixToContentType($ext);
1833
                    $report->addFile($tmpdir.'/'.$entry,
1834
                        empty($mime) ? 'text/plain' : $mime);
1835
                }
1836
            }
1837
            $d->close();
1838
1839
            if ((strstr($this->url, '://localhost') || strstr($this->url,
1840
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
1841
1842
                $fl = fopen("/var/log/flexibee.log", "r");
1843
                if ($fl) {
1844
                    $tracelog = [];
1845
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
1846
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
1847
                        $char = fgetc($fl);
1848
                        if ($char === "\n") {
1849
                            $tracelog[] = $output[$ln];
1850
                            if (strstr($output[$ln], $errorResponse['message'])) {
1851
                                break;
1852
                            }
1853
                            $ln++;
1854
                            continue;
1855
                        }
1856
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
1857
                                : '');
1858
                    }
1859
1860
                    $trace     = implode("\n", array_reverse($tracelog));
1861
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
1862
                    file_put_contents($tracefile, $trace);
1863
                    $report->addItem("\n\n".$trace);
1864
                    fclose($fl);
1865
                }
1866
            } else {
1867
                $report->addItem($errorResponse['message']);
1868
            }
1869
1870
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
1871
1872
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
1873
                    JSON_PRETTY_PRINT));
1874
1875
            if ($report->send()) {
1876
                $this->reports[$ur] = $myTime;
1877
            }
1878
        }
1879
    }
1880
1881
    /**
1882
     * Returns code:CODE
1883
     *
1884
     * @param string $code
1885
     *
1886
     * @return string
1887
     */
1888
    public static function code($code)
1889
    {
1890
        return 'code:'.self::uncode($code);
1891
    }
1892
1893
    /**
1894
     * Returns CODE without code: prefix
1895
     *
1896
     * @param string $code
1897
     *
1898
     * @return string
1899
     */
1900
    public static function uncode($code)
1901
    {
1902
        return str_replace('code:', '', $code);
1903
    }
1904
}
1905