Test Failed
Push — master ( bfc976...d9bc34 )
by Vítězslav
04:39
created

FlexiBeeRO::getEvidenceURL()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 10
nc 6
nop 1
dl 0
loc 15
rs 8.8571
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
    public function __construct($init = null, $options = [])
329
    {
330
        $this->init = $init;
331
332
        parent::__construct();
333
        $this->setUp($options);
334
        $this->curlInit();
335
        if (!empty($init)) {
336
            $this->processInit($init);
337
        }
338
    }
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
    public function setUp($options = [])
347
    {
348
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
349
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
350
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
351
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
352
        if (isset($options['evidence'])) {
353
            $this->setEvidence($options['evidence']);
354
        }
355
        $this->setupProperty($options, 'defaultUrlParams');
356
        if (isset($options['prefix'])) {
357
            $this->setPrefix($options['prefix']);
358
        }
359
        $this->setupProperty($options, 'debug');
360
        $this->updateApiURL();
361
    }
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
    public function setupProperty($options, $name, $constant = null)
371
    {
372
        if (isset($options[$name])) {
373
            $this->$name = $options[$name];
374
        } else {
375
            if (is_null($this->$name) && !empty($constant) && defined($constant)) {
376
                $this->$name = constant($constant);
377
            }
378
        }
379
    }
380
381
    /**
382
     * Inicializace CURL
383
     */
384
    public function curlInit()
385
    {
386
        $this->curl = \curl_init(); // create curl resource
387
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
388
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
389
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
390
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
391
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
392
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
393
        curl_setopt($this->curl, CURLOPT_USERPWD,
394
            $this->user.':'.$this->password); // set username and password
395
    }
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
    public function processInit($init)
409
    {
410
        if (is_integer($init)) {
411
            $this->loadFromFlexiBee($init);
412
        } elseif (is_array($init)) {
413
            $this->takeData($init);
414
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
415
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->getEvidenceURL($init)
416
                            : $init)));
417
        } else {
418
            $this->loadFromFlexiBee('code:'.str_replace('code:', '', $init));
419
        }
420
    }
421
422
    /**
423
     * Set URL prefix
424
     *
425
     * @param string $prefix
426
     */
427
    public function setPrefix($prefix)
428
    {
429
        switch ($prefix) {
430
            case 'a': //Access
431
            case 'c': //Company
432
            case 'u': //User
433
            case 'g': //License Groups
434
            case 'admin':
435
            case 'status':
436
            case 'login-logout':
437
                $this->prefix = '/'.$prefix.'/';
438
                break;
439
            case null:
440
            case '':
441
            case '/':
442
                $this->prefix = '';
443
                break;
444
            default:
445
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
446
        }
447
    }
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
    public function setFormat($format)
457
    {
458
        $result = true;
459
        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
        if ($result === true) {
466
            $this->format = $format;
467
            $this->updateApiURL();
468
        }
469
        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
    public function setEvidence($evidence)
480
    {
481
        switch ($this->prefix) {
482
            case '/c/':
483
                if (array_key_exists($evidence, EvidenceList::$name)) {
484
                    $this->evidence = $evidence;
485
                    $result         = true;
486
                } else {
487
                    throw new \Exception(sprintf('Try to set unsupported evidence %s',
488
                        $evidence));
489
                }
490
                break;
491
            default:
492
                $this->evidence = $evidence;
493
                $result         = true;
494
                break;
495
        }
496
        $this->updateApiURL();
497
        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
    public function getEvidence()
507
    {
508
        return $this->evidence;
509
    }
510
511
    /**
512
     * Set used company.
513
     * Nastaví Firmu.
514
     *
515
     * @param string $company
516
     */
517
    public function setCompany($company)
518
    {
519
        $this->company = $company;
520
    }
521
522
    /**
523
     * Obtain company now used
524
     * Vrací právě používanou firmu
525
     *
526
     * @return string
527
     */
528
    public function getCompany()
529
    {
530
        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
    public function getResponseEvidence()
539
    {
540
        switch ($this->evidence) {
541
            case 'c':
542
                $evidence = 'company';
543
                break;
544
            case 'evidence-list':
545
                $evidence = 'evidence';
546
                break;
547
            default:
548
                $evidence = $this->getEvidence();
549
                break;
550
        }
551
        return $evidence;
552
    }
553
554
    /**
555
     * Převede rekurzivně Objekt na pole.
556
     *
557
     * @param object|array $object
558
     *
559
     * @return array
560
     */
561
    public static function object2array($object)
562
    {
563
        $result = null;
564
        if (is_object($object)) {
565
            $objectData = get_object_vars($object);
566
            if (is_array($objectData) && count($objectData)) {
567
                $result = array_map('self::object2array', $objectData);
568
            }
569
        } else {
570
            if (is_array($object)) {
571
                foreach ($object as $item => $value) {
572
                    $result[$item] = self::object2array($value);
573
                }
574
            } else {
575
                $result = $object;
576
            }
577
        }
578
579
        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
    public static function objectToID($object)
590
    {
591
        $resultID = null;
592
        if (is_object($object)) {
593
            $resultID = $object->__toString();
594
        } else {
595
            if (is_array($object)) {
596
                foreach ($object as $item => $value) {
597
                    $resultID[$item] = self::objectToID($value);
598
                }
599
            } else { //String
600
                $resultID = $object;
601
            }
602
        }
603
604
        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
     * @param string $urlSuffix additional url Suffix
612
     */
613
    public function getEvidenceURL($urlSuffix = null)
614
    {
615
        $evidenceUrl = $this->url.$this->prefix.$this->company;
616
        $evidence    = $this->getEvidence();
617
        if (!empty($evidence)) {
618
            $evidenceUrl .= '/'.$evidence;
619
        }
620
        if (!empty($urlSuffix)) {
621
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';')) {
622
                $evidenceUrl .= '/';
623
            }
624
            $evidenceUrl .= $urlSuffix;
625
        }
626
        return $evidenceUrl;
627
    }
628
629
    /**
630
     * Update $this->apiURL
631
     */
632
    public function updateApiURL()
633
    {
634
        $this->apiURL = $this->getEvidenceURL();
635
        $id           = $this->__toString();
636
        if (!empty($id)) {
637
            $this->apiURL .= '/'.urlencode($id);
638
        }
639
        $this->apiURL .= '.'.$this->format;
640
    }
641
642
    /**
643
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
644
     *
645
     * @param string $urlSuffix část URL za identifikátorem firmy.
646
     * @param string $method    HTTP/REST metoda
647
     * @param string $format    Requested format
648
     * @return array|boolean Výsledek operace
649
     */
650
    public function performRequest($urlSuffix = null, $method = 'GET',
651
                                   $format = null)
652
    {
653
        $this->rowCount = null;
654
655
        if (preg_match('/^http/', $urlSuffix)) {
656
            $url = $urlSuffix;
657
        } elseif ($urlSuffix[0] == '/') {
658
            $url = $this->url.$urlSuffix;
659
        } else {
660
            $url = $this->getEvidenceURL($urlSuffix);
661
        }
662
663
        $responseCode = $this->doCurlRequest($url, $method, $format);
664
665
        return strlen($this->lastCurlResponse) ? $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
666
                    $this->responseFormat), $responseCode) : null;
667
    }
668
669
    /**
670
     * Parse Raw FlexiBee response in several formats
671
     *
672
     * @param string $responseRaw raw response body
673
     * @param string $format      Raw Response format json|xml|etc
674
     *
675
     * @return array
676
     */
677
    public function rawResponseToArray($responseRaw, $format)
678
    {
679
        switch ($format) {
680
            case 'json':
681
                $responseDecoded = json_decode($responseRaw, true, 10);
682
                $decodeError     = json_last_error_msg();
683
                if ($decodeError == 'No error') {
684
                    if (array_key_exists($this->nameSpace, $responseDecoded)) {
685
                        $responseDecoded = $responseDecoded[$this->nameSpace];
686
                    }
687
                } else {
688
                    $this->addStatusMessage('JSON Decoder: '.$decodeError,
689
                        'error');
690
                    $this->addStatusMessage($responseRaw, 'debug');
691
                }
692
                break;
693
            case 'xml':
694
                $responseDecoded = self::xml2array($this->lastCurlResponse);
695
                break;
696
            case 'txt':
697
            default:
698
                $responseDecoded = $this->lastCurlResponse;
699
                break;
700
        }
701
        return $responseDecoded;
702
    }
703
704
    /**
705
     * Parse Response array
706
     *
707
     * @param array $responseDecoded
708
     * @param int $responseCode Request Response Code
709
     *
710
     * @return array main data part of response
711
     */
712
    public function parseResponse($responseDecoded, $responseCode)
713
    {
714
        $response = null;
715
        switch ($responseCode) {
716
            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...
717
                if (isset($responseDecoded[$this->resultField][0]['id'])) {
718
                    $this->lastInsertedID = $responseDecoded[$this->resultField][0]['id'];
719
                    $this->setMyKey($this->lastInsertedID);
720
                    $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
721
                } else {
722
                    $this->lastInsertedID = null;
723
                }
724
            case 200: //Success Read
725
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
726
                if (isset($responseDecoded['@rowCount'])) {
727
                    $this->rowCount = (int) $responseDecoded['@rowCount'];
728
                }
729
                break;
730
731
            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...
732
                if ($this->debug === true) {
733
                    $this->error500Reporter($responseDecoded);
734
                }
735
            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...
736
                if ($this->ignoreNotFound === true) {
737
                    break;
738
                }
739
            case 400: //Bad Request parameters
740
            default: //Something goes wrong
741
                $this->addStatusMessage($this->curlInfo['url'], 'warning');
742
                if (is_array($responseDecoded)) {
743
                    $this->parseError($responseDecoded);
744
                }
745
                $this->logResult($responseDecoded, $this->curlInfo['url']);
746
                break;
747
        }
748
        return $response;
749
    }
750
751
    /**
752
     * Parse error message response
753
     *
754
     * @param array $responseDecoded
755
     * @return int number of errors processed
756
     */
757
    public function parseError(array $responseDecoded)
758
    {
759
        if (array_key_exists('results', $responseDecoded)) {
760
            $this->errors = $responseDecoded['results'][0]['errors'];
761
        } else {
762
            $this->errors = [['message' => $responseDecoded['message']]];
763
        }
764
        return count($this->errors);
765
    }
766
767
    /**
768
     * Vykonej HTTP požadavek
769
     *
770
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
771
     * @param string $url    URL požadavku
772
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
773
     * @param string $format požadovaný formát komunikace
774
     * @return int HTTP Response CODE
775
     */
776
    public function doCurlRequest($url, $method, $format = null)
777
    {
778
        if (is_null($format)) {
779
            $format = $this->format;
780
        }
781
        curl_setopt($this->curl, CURLOPT_URL, $url);
782
// Nastavení samotné operace
783
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
784
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
785
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
786
787
        $httpHeaders = $this->defaultHttpHeaders;
788
789
        $formats = Formats::bySuffix();
790
791
        if (!isset($httpHeaders['Accept'])) {
792
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
793
        }
794
        if (!isset($httpHeaders['Content-Type'])) {
795
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
796
        }
797
        $httpHeadersFinal = [];
798
        foreach ($httpHeaders as $key => $value) {
799
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
800
                $value .= ' v'.self::$libVersion;
801
            }
802
            $httpHeadersFinal[] = $key.': '.$value;
803
        }
804
805
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
806
807
// Proveď samotnou operaci
808
        $this->lastCurlResponse            = curl_exec($this->curl);
809
        $this->curlInfo                    = curl_getinfo($this->curl);
810
        $this->curlInfo['when']            = microtime();
811
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
812
        $this->responseFormat              = Formats::contentTypeToSuffix($this->curlInfo['content_type']);
813
        $this->lastResponseCode            = $this->curlInfo['http_code'];
814
        $this->lastCurlError               = curl_error($this->curl);
815
        if (strlen($this->lastCurlError)) {
816
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
817
                    $this->lastResponseCode, $this->lastCurlError), 'error');
818
        }
819
820
        if ($this->debug === true) {
821
            $this->saveDebugFiles();
822
        }
823
824
        return $this->lastResponseCode;
825
    }
826
827
    /**
828
     * Nastaví druh prováděné akce.
829
     *
830
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
831
     * @param string $action
832
     * @return boolean
833
     */
834
    public function setAction($action)
835
    {
836
        $result           = false;
837
        $actionsAvailable = $this->getActionsInfo();
838
        if (array_key_exists($action, $actionsAvailable)) {
839
            $this->action = $action;
840
            $result       = true;
841
        }
842
        return $result;
843
    }
844
845
    /**
846
     * Convert XML to array.
847
     *
848
     * @param string $xml
849
     *
850
     * @return array
851
     */
852
    public static function xml2array($xml)
853
    {
854
        $arr = [];
855
856
        if (is_string($xml)) {
857
            $xml = simplexml_load_string($xml);
858
        }
859
860
        foreach ($xml->children() as $r) {
861
            if (count($r->children()) == 0) {
862
                $arr[$r->getName()] = strval($r);
863
            } else {
864
                $arr[$r->getName()][] = self::xml2array($r);
865
            }
866
        }
867
868
        return $arr;
869
    }
870
871
    /**
872
     * Odpojení od FlexiBee.
873
     */
874
    public function disconnect()
875
    {
876
        if (is_resource($this->curl)) {
877
            curl_close($this->curl);
878
        }
879
        $this->curl = null;
880
    }
881
882
    /**
883
     * Disconnect CURL befere pass away
884
     */
885
    public function __destruct()
886
    {
887
        $this->disconnect();
888
    }
889
890
    /**
891
     * Načte řádek dat z FlexiBee.
892
     *
893
     * @param int $recordID id požadovaného záznamu
894
     *
895
     * @return array
896
     */
897
    public function getFlexiRow($recordID)
898
    {
899
        $record   = null;
900
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
901
        if (isset($response[$this->evidence])) {
902
            $record = $response[$this->evidence][0];
903
        }
904
905
        return $record;
906
    }
907
908
    /**
909
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
910
     *
911
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
912
     * @param array $conditions pole podmínek   - rendrují se do ()
913
     * @param array $urlParams  pole parametrů  - rendrují za ?
914
     */
915
    public function extractUrlParams(&$conditions, &$urlParams)
916
    {
917
        foreach ($this->urlParams as $urlParam) {
918
            if (isset($conditions[$urlParam])) {
919
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
920
            }
921
        }
922
    }
923
924
    /**
925
     * Načte data z FlexiBee.
926
     *
927
     * @param string $suffix     dotaz
928
     * @param string|array $conditions Volitelný filtrovací výraz
929
     */
930
    public function getFlexiData($suffix = null, $conditions = null)
931
    {
932
        $urlParams = $this->defaultUrlParams;
933
        if (!is_null($conditions)) {
934
            if (is_array($conditions)) {
935
                $this->extractUrlParams($conditions, $urlParams);
936
                $conditions = $this->flexiUrl($conditions);
937
            }
938
939
            if (strlen($conditions) && ($conditions[0] != '/')) {
940
                $conditions = '/'.rawurlencode('('.($conditions).')');
941
            }
942
        } else {
943
            $conditions = '';
944
        }
945
946
        if (preg_match('/^http/', $suffix) || ($suffix[0] == '/')) {
947
            $transactions = $this->performRequest($suffix, 'GET');
948
        } else {
949
            if (strlen($suffix)) {
950
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
951
                    'GET');
952
            } else {
953
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
954
                    'GET');
955
            }
956
        }
957
        $responseEvidence = $this->getResponseEvidence();
958
        if (is_array($transactions) && array_key_exists($responseEvidence,
959
                $transactions)) {
960
            $result = $transactions[$responseEvidence];
961
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
962
                $result = null; // Response is empty Array
963
            }
964
        } else {
965
            $result = $transactions;
966
        }
967
968
        return $result;
969
    }
970
971
    /**
972
     * Načte záznam z FlexiBee a uloží v sobě jeho data
973
     * Read FlexiBee record and store it inside od object
974
     *
975
     * @param int|array $id ID or conditions
976
     *
977
     * @return int počet načtených položek
978
     */
979
    public function loadFromFlexiBee($id = null)
980
    {
981
        $data = [];
982
        if (is_null($id)) {
983
            $id = $this->getMyKey();
984
        }
985
986
        $flexidata = $this->getFlexiData(null, is_array($id) ? $id : '/'.$id);
987
988
        $this->apiURL = $this->curlInfo['url'];
989
        if (is_array($flexidata) && (count($flexidata) == 1)) {
990
            $data = current($flexidata);
991
        }
992
        return $this->takeData($data);
993
    }
994
995
    /**
996
     * Převede data do Json formátu pro FlexiBee.
997
     * Convert data to FlexiBee like Json format
998
     *
999
     * @param array $data
1000
     *
1001
     * @return string
1002
     */
1003
    public function jsonizeData($data)
1004
    {
1005
        $dataToJsonize = [
1006
            $this->nameSpace => [
1007
                '@version' => $this->protoVersion,
1008
                $this->evidence => $this->objectToID($data),
1009
            ],
1010
        ];
1011
1012 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...
1013
            $dataToJsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1014
            $this->action                                               = null;
1015
        }
1016
1017 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...
1018
            $dataToJsonize[$this->nameSpace][$this->evidence.'@filter'] = $this->filter;
1019
        }
1020
1021
        return json_encode($dataToJsonize);
1022
    }
1023
1024
    /**
1025
     * Test if given record ID exists in FlexiBee.
1026
     *
1027
     * @param string|int $identifer
1028
     */
1029
    public function idExists($identifer = null)
1030
    {
1031
        if (is_null($identifer)) {
1032
            $identifer = $this->getMyKey();
1033
        }
1034
        $flexiData = $this->getFlexiData(
1035
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
1036
1037
        return $flexiData;
1038
    }
1039
1040
    /**
1041
     * Test if given record exists in FlexiBee.
1042
     *
1043
     * @param array $data
1044
     * @return boolean Record presence status
1045
     */
1046
    public function recordExists($data = [])
1047
    {
1048
1049
        if (empty($data)) {
1050
            $data = $this->getData();
1051
        }
1052
1053
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1054
            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...
1055
1056
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1057
            || !count($res[0])) {
1058
            $found = false;
1059
        } else {
1060
            $found = true;
1061
        }
1062
        return $found;
1063
    }
1064
1065
    /**
1066
     * Vrací z FlexiBee sloupečky podle podmínek.
1067
     *
1068
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1069
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1070
     *                                     sloupečku
1071
     * @return array
1072
     */
1073
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1074
    {
1075
        if (is_int($conditions)) {
1076
            $conditions = [$this->getmyKeyColumn() => $conditions];
1077
        }
1078
1079
        $flexiData = $this->getFlexiData('', $conditions);
1080
1081
        if (!is_null($indexBy)) {
1082
            $flexiData = $this->reindexArrayBy($flexiData);
1083
        }
1084
1085
        return $flexiData;
1086
    }
1087
1088
    /**
1089
     * Vrací z FlexiBee sloupečky podle podmínek.
1090
     *
1091
     * @param string[] $columnsList seznam položek
1092
     * @param array    $conditions  pole podmínek nebo ID záznamu
1093
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1094
     *
1095
     * @return array
1096
     */
1097
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1098
                                           $indexBy = null)
1099
    {
1100
        $detail = 'full';
1101
        switch (gettype($columnsList)) {
1102
            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...
1103
                $conditions = [$this->getmyKeyColumn() => $conditions];
1104
            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...
1105
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1106
                        $columnsList)) {
1107
                    $columnsList[] = $indexBy;
1108
                }
1109
                $columns = implode(',', array_unique($columnsList));
1110
                $detail  = 'custom:'.$columns;
1111
            default:
1112
                switch ($columnsList) {
1113
                    case 'id':
1114
                        $detail = 'id';
1115
                        break;
1116
                    case 'summary':
1117
                        $detail = 'summary';
1118
                        break;
1119
                    default:
1120
                        break;
1121
                }
1122
                break;
1123
        }
1124
1125
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1126
1127
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1128
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1129
        }
1130
1131
        return $flexiData;
1132
    }
1133
1134
    /**
1135
     * Vrací kód záznamu.
1136
     * Obtain record CODE
1137
     *
1138
     * @param mixed $data
1139
     *
1140
     * @return string
1141
     */
1142
    public function getKod($data = null, $unique = true)
1143
    {
1144
        $kod = null;
1145
1146
        if (is_null($data)) {
1147
            $data = $this->getData();
1148
        }
1149
1150
        if (is_string($data)) {
1151
            $data = [$this->nameColumn => $data];
1152
        }
1153
1154
        if (isset($data['kod'])) {
1155
            $kod = $data['kod'];
1156
        } else {
1157
            if (isset($data[$this->nameColumn])) {
1158
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1159
                    \Ease\Sand::rip($data[$this->nameColumn]));
1160
            } else {
1161
                if (isset($data[$this->myKeyColumn])) {
1162
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1163
                }
1164
            }
1165
        }
1166
1167
        if (!strlen($kod)) {
1168
            $kod = 'NOTSET';
1169
        }
1170
1171
        if (strlen($kod) > 18) {
1172
            $kodfinal = strtoupper(substr($kod, 0, 18));
1173
        } else {
1174
            $kodfinal = strtoupper($kod);
1175
        }
1176
1177
        if ($unique) {
1178
            $counter = 0;
1179
            if (count($this->codes)) {
1180
                foreach ($this->codes as $codesearch => $keystring) {
1181
                    if (strstr($codesearch, $kodfinal)) {
1182
                        ++$counter;
1183
                    }
1184
                }
1185
            }
1186
            if ($counter) {
1187
                $kodfinal = $kodfinal.$counter;
1188
            }
1189
1190
            $this->codes[$kodfinal] = $kod;
1191
        }
1192
1193
        return $kodfinal;
1194
    }
1195
1196
    /**
1197
     * Write Operation Result.
1198
     *
1199
     * @param array  $resultData
1200
     * @param string $url        URL
1201
     * @return boolean Log save success
1202
     */
1203
    public function logResult($resultData = null, $url = null)
1204
    {
1205
        $logResult = false;
1206
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1207
            if (isset($resultData['message'])) {
1208
                $this->addStatusMessage($resultData['message'], 'warning');
1209
            }
1210
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1211
                'warning');
1212
            unset($url);
1213
        }
1214
        if (is_null($resultData)) {
1215
            $resultData = $this->lastResult;
1216
        }
1217
        if (isset($url)) {
1218
            $this->logger->addStatusMessage(urldecode($url));
1219
        }
1220
1221
        if (isset($resultData['results'])) {
1222
            if ($resultData['success'] == 'false') {
1223
                $status = 'error';
1224
            } else {
1225
                $status = 'success';
1226
            }
1227
            foreach ($resultData['results'] as $result) {
1228
                if (isset($result['request-id'])) {
1229
                    $rid = $result['request-id'];
1230
                } else {
1231
                    $rid = '';
1232
                }
1233
                if (isset($result['errors'])) {
1234
                    foreach ($result['errors'] as $error) {
1235
                        $message = $error['message'];
1236
                        if (isset($error['for'])) {
1237
                            $message .= ' for: '.$error['for'];
1238
                        }
1239
                        if (isset($error['value'])) {
1240
                            $message .= ' value:'.$error['value'];
1241
                        }
1242
                        if (isset($error['code'])) {
1243
                            $message .= ' code:'.$error['code'];
1244
                        }
1245
                        $this->addStatusMessage($rid.': '.$message, $status);
1246
                    }
1247
                }
1248
            }
1249
        }
1250
        return $logResult;
1251
    }
1252
1253
    /**
1254
     * Save RAW Curl Request & Response to files in Temp directory
1255
     */
1256
    public function saveDebugFiles()
1257
    {
1258
        $tmpdir   = sys_get_temp_dir();
1259
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1260
        $reqname  = $tmpdir.'/request-'.$fname;
1261
        $respname = $tmpdir.'/response-'.$fname;
1262
        file_put_contents($reqname, $this->postFields);
1263
        file_put_contents($respname, $this->lastCurlResponse);
1264
    }
1265
1266
    /**
1267
     * Připraví data pro odeslání do FlexiBee
1268
     *
1269
     * @param string $data
1270
     */
1271
    public function setPostFields($data)
1272
    {
1273
        $this->postFields = $data;
1274
    }
1275
1276
    /**
1277
     * Generuje fragment url pro filtrování.
1278
     *
1279
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1280
     *
1281
     * @param array  $data
1282
     * @param string $joiner default and/or
1283
     * @param string $defop  default operator
1284
     *
1285
     * @return string
1286
     */
1287
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1288
    {
1289
        $parts = [];
1290
1291
        foreach ($data as $column => $value) {
1292
            if (is_integer($data[$column]) || is_float($data[$column])) {
1293
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1294
            } elseif (is_bool($data[$column])) {
1295
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1296
            } elseif (is_null($data[$column])) {
1297
                $parts[$column] = $column." is null";
1298
            } else {
1299
                switch ($value) {
1300
                    case '!null':
1301
                        $parts[$column] = $column." is not null";
1302
                        break;
1303
                    case 'is empty':
1304
                    case 'is not empty':
1305
                        $parts[$column] = $column.' '.$value;
1306
                        break;
1307
                    default:
1308
                        if ($column == 'stitky') {
1309
                            $parts[$column] = $column."='code:".$data[$column]."'";
1310
                        } else {
1311
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1312
                        }
1313
                        break;
1314
                }
1315
            }
1316
        }
1317
        return implode(' '.$joiner.' ', $parts);
1318
    }
1319
1320
    /**
1321
     * Obtain record/object identificator code: or id:
1322
     * Vrací identifikátor objektu code: nebo id:
1323
     *
1324
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1325
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1326
     */
1327
    public function getRecordID()
1328
    {
1329
        $myCode = $this->getDataValue('kod');
1330
        if ($myCode) {
1331
            $id = 'code:'.$myCode;
1332
        } else {
1333
            $id = $this->getDataValue('id');
1334
            if (($this->debug === true) && is_null($id)) {
1335
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1336
                    'warning');
1337
            }
1338
        }
1339
        return is_numeric($id) ? intval($id) : strval($id);
1340
    }
1341
1342
    /**
1343
     * Obtain record/object identificator code: or id:
1344
     * Vrací identifikátor objektu code: nebo id:
1345
     *
1346
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1347
     * @return string indentifikátor záznamu reprezentovaného objektem
1348
     */
1349
    public function __toString()
1350
    {
1351
        return strval($this->getRecordID());
1352
    }
1353
1354
    /**
1355
     * Gives you FlexiPeeHP class name for Given Evidence
1356
     *
1357
     * @param string $evidence
1358
     * @return string Class name
1359
     */
1360
    public static function evidenceToClassName($evidence)
1361
    {
1362
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1363
    }
1364
1365
    /**
1366
     * Vrací hodnotu daného externího ID
1367
     *
1368
     * @param string $want Which ? If empty,you obtain the first one.
1369
     * @return string
1370
     */
1371
    public function getExternalID($want = null)
1372
    {
1373
        $extid = null;
1374
        $ids   = $this->getDataValue('external-ids');
1375
        if (is_null($want)) {
1376
            if (count($ids)) {
1377
                $extid = current($ids);
1378
            }
1379
        } else {
1380
            if (!is_null($ids) && is_array($ids)) {
1381
                foreach ($ids as $id) {
1382
                    if (strstr($id, 'ext:'.$want)) {
1383
                        $extid = str_replace('ext:'.$want.':', '', $id);
1384
                    }
1385
                }
1386
            }
1387
        }
1388
        return $extid;
1389
    }
1390
1391
    /**
1392
     * Obtain actual GlobalVersion
1393
     * Vrací aktuální globální verzi změn
1394
     *
1395
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1396
     * @return type
1397
     */
1398
    public function getGlobalVersion()
1399
    {
1400
        $globalVersion = null;
1401
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1402
            $this->getFlexiData(null,
1403
                ['add-global-version' => 'true', 'limit' => 1]);
1404
        }
1405
1406
        if (isset($this->lastResult['@globalVersion'])) {
1407
            $globalVersion = intval($this->lastResult['@globalVersion']);
1408
        }
1409
1410
        return $globalVersion;
1411
    }
1412
1413
    /**
1414
     * Obtain content type of last response
1415
     *
1416
     * @return string
1417
     */
1418
    public function getResponseFormat()
1419
    {
1420
        if (isset($this->curlInfo['content_type'])) {
1421
            $responseFormat = $this->curlInfo['content_type'];
1422
        } else {
1423
            $responseFormat = null;
1424
        }
1425
        return $responseFormat;
1426
    }
1427
1428
    /**
1429
     * Return the same response format for one and multiplete results
1430
     *
1431
     * @param array $responseBody
1432
     * @return array
1433
     */
1434
    public function unifyResponseFormat($responseBody)
1435
    {
1436
        if (!is_array($responseBody) || array_key_exists('message',
1437
                $responseBody)) { //Unifi response format
1438
            $response = $responseBody;
1439
        } else {
1440
            $evidence = $this->getResponseEvidence();
1441
            if (array_key_exists($evidence, $responseBody)) {
1442
                $response        = [];
1443
                $evidenceContent = $responseBody[$evidence];
1444
                if (array_key_exists(0, $evidenceContent)) {
1445
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1446
                } else {
1447
                    $response[$evidence][0] = $evidenceContent; //One result
1448
                }
1449
            } else {
1450
                if (isset($responseBody['priloha'])) {
1451
                    $response = $responseBody['priloha'];
1452
                } else {
1453
                    $response = $responseBody;
1454
                }
1455
            }
1456
        }
1457
        return $response;
1458
    }
1459
1460
    /**
1461
     * Obtain structure for current (or given) evidence
1462
     *
1463
     * @param string $evidence
1464
     * @return array Evidence structure
1465
     */
1466 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...
1467
    {
1468
        $columnsInfo = null;
1469
        if (is_null($evidence)) {
1470
            $evidence = $this->getEvidence();
1471
        }
1472
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1473
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1474
            $columnsInfo = Properties::$$propsName;
1475
        }
1476
        return $columnsInfo;
1477
    }
1478
1479
    /**
1480
     * Obtain actions for current (or given) evidence
1481
     *
1482
     * @param string $evidence
1483
     * @return array Evidence structure
1484
     */
1485 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...
1486
    {
1487
        $actionsInfo = null;
1488
        if (is_null($evidence)) {
1489
            $evidence = $this->getEvidence();
1490
        }
1491
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1492
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1493
            $actionsInfo = Actions::$$propsName;
1494
        }
1495
        return $actionsInfo;
1496
    }
1497
1498
    /**
1499
     * Obtain relations for current (or given) evidence
1500
     *
1501
     * @param string $evidence
1502
     * @return array Evidence structure
1503
     */
1504
    public function getRelationsInfo($evidence = null)
1505
    {
1506
        $relationsInfo = null;
1507
        if (is_null($evidence)) {
1508
            $evidence = $this->getEvidence();
1509
        }
1510
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1511
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1512
            $relationsInfo = Relations::$$propsName;
1513
        }
1514
        return $relationsInfo;
1515
    }
1516
1517
    /**
1518
     * Obtain info for current (or given) evidence
1519
     *
1520
     * @param string $evidence
1521
     * @return array Evidence info
1522
     */
1523 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...
1524
    {
1525
        $evidencesInfo = null;
1526
        if (is_null($evidence)) {
1527
            $evidence = $this->getEvidence();
1528
        }
1529
        if (isset(EvidenceList::$evidences[$evidence])) {
1530
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1531
        }
1532
        return $evidencesInfo;
1533
    }
1534
1535
    /**
1536
     * Obtain name for current (or given) evidence path
1537
     *
1538
     * @param string $evidence Evidence Path
1539
     * @return array Evidence info
1540
     */
1541 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...
1542
    {
1543
        $evidenceName = null;
1544
        if (is_null($evidence)) {
1545
            $evidence = $this->getEvidence();
1546
        }
1547
        if (isset(EvidenceList::$name[$evidence])) {
1548
            $evidenceName = EvidenceList::$name[$evidence];
1549
        }
1550
        return $evidenceName;
1551
    }
1552
1553
    /**
1554
     * Perform given action (if availble) on current evidence/record
1555
     * @url https://demo.flexibee.eu/devdoc/actions
1556
     *
1557
     * @param string $action one of evidence actions
1558
     * @param string $method ext|int External method call operation in URL.
1559
     *                               Internal add the @action element to request body
1560
     */
1561
    public function performAction($action, $method = 'ext')
1562
    {
1563
        $actionsAvailble = $this->getActionsInfo();
1564
1565
        if (is_array($actionsAvailble) && array_key_exists($action,
1566
                $actionsAvailble)) {
1567
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1568
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1569
                case 'ONLY_WITH_INSTANCE': //Add instance
1570
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1571
                    break;
1572
1573
                default:
1574
                    $urlSuffix = '/'.$action;
1575
                    break;
1576
            }
1577
1578
            switch ($method) {
1579
                case 'int':
1580
                    $this->setAction($action);
1581
                    $this->setPostFields($this->jsonizeData($this->getData()));
1582
                    $result = $this->performRequest(null, 'POST');
1583
                    break;
1584
1585
                default:
1586
                    $result = $this->performRequest($urlSuffix, 'GET');
1587
                    break;
1588
            }
1589
        } else {
1590
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1591
                $action, $this->getEvidence()));
1592
        }
1593
1594
        return $result;
1595
    }
1596
1597
    /**
1598
     * Save current object to file
1599
     *
1600
     * @param string $destfile path to file
1601
     */
1602
    public function saveResponseToFile($destfile)
1603
    {
1604
        if (strlen($this->lastCurlResponse)) {
1605
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1606
        }
1607
        file_put_contents($destfile, $this->lastCurlResponse);
1608
    }
1609
1610
    /**
1611
     * Obtain established relations listing
1612
     *
1613
     * @return array Null or Relations
1614
     */
1615
    public function getVazby()
1616
    {
1617
        $vazby = $this->getDataValue('vazby');
1618
        if (is_null($vazby)) {
1619
            $vazby = $this->getColumnsFromFlexibee('*',
0 ignored issues
show
Documentation introduced by
'*' is of type string, but the function expects a array<integer,string>.

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...
1620
                ['relations' => 'vazby', 'id' => $this->getRecordID()]);
1621
            $vazby = $vazby[0]['vazby'];
1622
        }
1623
        return $vazby;
1624
    }
1625
1626
    /**
1627
     * Gives You URL for Current Record in FlexiBee web interface
1628
     *
1629
     * @return string url
1630
     */
1631
    public function getFlexiBeeURL()
1632
    {
1633
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1634
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1635
                : '';
1636
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1637
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1638
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1639
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1640
        $pass       = ($user || $pass) ? "$pass@" : '';
1641
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1642
        return $scheme.$user.$pass.$host.$port.$path;
1643
    }
1644
1645
    /**
1646
     * Set Record Key
1647
     *
1648
     * @param int|string $myKeyValue
1649
     * @return boolean
1650
     */
1651
    public function setMyKey($myKeyValue)
1652
    {
1653
        $res = parent::setMyKey($myKeyValue);
1654
        $this->updateApiURL();
1655
        return $res;
1656
    }
1657
1658
    /**
1659
     * Set or get ignore not found pages flag
1660
     *
1661
     * @param boolean $ignore set flag to
1662
     *
1663
     * @return boolean get flag state
1664
     */
1665
    public function ignore404($ignore = null)
1666
    {
1667
        if (!is_null($ignore)) {
1668
            $this->ignoreNotFound = $ignore;
1669
        }
1670
        return $this->ignoreNotFound;
1671
    }
1672
1673
    /**
1674
     * Send Document by mail
1675
     *
1676
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1677
     *
1678
     * @param string $to
1679
     * @param string $subject
1680
     * @param string $body Email Text
1681
     *
1682
     * @return int http response code
1683
     */
1684
    public function sendByMail($to, $subject, $body, $cc = null)
1685
    {
1686
        $this->setPostFields($body);
1687
        $result = $this->doCurlRequest($this->getEvidenceURL().'/'.
1688
            urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1689
            , 'PUT', 'xml');
1690
        return $result == 200;
1691
    }
1692
1693
    /**
1694
     * Send all unsent Invoices by mail
1695
     *
1696
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1697
     * @return int http response code
1698
     */
1699
    public function sendUnsent()
1700
    {
1701
        return $this->doCurlRequest($this->getEvidenceURL().'/automaticky-odeslat-neodeslane',
1702
                'PUT', 'xml');
1703
    }
1704
1705
    /**
1706
     * FlexiBee date to PHP DateTime
1707
     *
1708
     * @param string $flexidate
1709
     *
1710
     * @return \DateTime | false
1711
     */
1712
    public static function flexiDateToDateTime($flexidate)
1713
    {
1714
        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 1714 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...
1715
    }
1716
1717
    /**
1718
     * Získá dokument v daném formátu
1719
     * Obtain document in given format
1720
     *
1721
     * @param string $format  pdf/csv/xml/json/ ...
1722
     *
1723
     * @return string|null filename downloaded or none
1724
     */
1725
    public function getInFormat($format)
1726
    {
1727
        $response = null;
1728
        if ($this->setFormat($format)) {
1729
            if (($this->doCurlRequest(($format == 'html') ? $this->apiURL.'?inDesktopApp=true'
1730
                            : $this->apiURL, 'GET') == 200)) {
1731
                $response = $this->lastCurlResponse;
1732
            }
1733
        }
1734
        return $response;
1735
    }
1736
1737
    /**
1738
     * Uloží dokument v daném formátu do složky v systému souborů
1739
     * Save document in given format to directory in filesystem
1740
     *
1741
     * @param string $format  pdf/csv/xml/json/ ...
1742
     * @param string $destDir where to put file (prefix)
1743
     *
1744
     * @return string|null filename downloaded or none
1745
     */
1746
    public function downloadInFormat($format, $destDir = './')
1747
    {
1748
        $fileOnDisk = null;
1749
        if ($this->setFormat($format)) {
1750
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1751
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1752
                    $this->lastCurlResponse) !== false)) {
1753
                $fileOnDisk = $downloadTo;
1754
            }
1755
        }
1756
        return $fileOnDisk;
1757
    }
1758
1759
    /**
1760
     * Compile and send Report about Error500 to FlexiBee developers
1761
     * If FlexiBee is running on localost try also include java backtrace
1762
     *
1763
     * @param array $errorResponse result of parseError();
1764
     */
1765
    public function error500Reporter($errorResponse)
1766
    {
1767
        $ur = str_replace('/c/'.$this->company, '',
1768
            str_replace($this->url, '', $this->curlInfo['url']));
1769
        if (!array_key_exists($ur, $this->reports)) {
1770
            $tmpdir   = sys_get_temp_dir();
1771
            $myTime   = $this->curlInfo['when'];
1772
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
1773
            file_put_contents($curlname,
1774
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
1775
1776
            $report = new \Ease\Mailer($this->reportRecipient,
1777
                'Error report 500 - '.$ur);
1778
1779
            $d     = dir($tmpdir);
1780
            while (false !== ($entry = $d->read())) {
1781
                if (strstr($entry, $myTime)) {
1782
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
1783
                    $mime = Formats::suffixToContentType($ext);
1784
                    $report->addFile($tmpdir.'/'.$entry,
1785
                        empty($mime) ? 'text/plain' : $mime);
1786
                }
1787
            }
1788
            $d->close();
1789
1790
            if ((strstr($this->url, '://localhost') || strstr($this->url,
1791
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
1792
1793
                $fl = fopen("/var/log/flexibee.log", "r");
1794
                if ($fl) {
1795
                    $tracelog = [];
1796
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
1797
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
1798
                        $char = fgetc($fl);
1799
                        if ($char === "\n") {
1800
                            $tracelog[] = $output[$ln];
1801
                            if (strstr($output[$ln], $errorResponse['message'])) {
1802
                                break;
1803
                            }
1804
                            $ln++;
1805
                            continue;
1806
                        }
1807
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
1808
                                : '');
1809
                    }
1810
1811
                    $trace     = implode("\n", array_reverse($tracelog));
1812
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
1813
                    file_put_contents($tracefile, $trace);
1814
                    $report->addItem("\n\n".$trace);
1815
                    fclose($fl);
1816
                }
1817
            } else {
1818
                $report->addItem($errorResponse['message']);
1819
            }
1820
1821
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
1822
1823
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
1824
                    JSON_PRETTY_PRINT));
1825
1826
            if ($report->send()) {
1827
                $this->reports[$ur] = $myTime;
1828
            }
1829
        }
1830
    }
1831
}
1832