Test Failed
Push — master ( 8206db...a53cfb )
by Vítězslav
04:57
created

FlexiBeeRO::evidenceUrlWithSuffix()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 3
nop 1
dl 0
loc 11
rs 9.2
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)
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
    }
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
     *
612
     * @return string Evidence URL
613
     */
614
    public function getEvidenceURL()
615
    {
616
        $evidenceUrl = $this->url.$this->prefix.$this->company;
617
        $evidence    = $this->getEvidence();
618
        if (!empty($evidence)) {
619
            $evidenceUrl .= '/'.$evidence;
620
        }
621
        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] != ';')) {
636
                $evidenceUrl .= '/';
637
            }
638
            $evidenceUrl .= $urlSuffix;
639
        }
640
        return $evidenceUrl;
641
    }
642
643
    /**
644
     * Update $this->apiURL
645
     */
646
    public function updateApiURL()
647
    {
648
        $this->apiURL = $this->getEvidenceURL();
649
        $id           = $this->__toString();
650
        if (!empty($id)) {
651
            $this->apiURL .= '/'.urlencode($id);
652
        }
653
        $this->apiURL .= '.'.$this->format;
654
    }
655
656
    /**
657
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
658
     *
659
     * @param string $urlSuffix část URL za identifikátorem firmy.
660
     * @param string $method    HTTP/REST metoda
661
     * @param string $format    Requested format
662
     * @return array|boolean Výsledek operace
663
     */
664
    public function performRequest($urlSuffix = null, $method = 'GET',
665
                                   $format = null)
666
    {
667
        $this->rowCount = null;
668
669
        if (preg_match('/^http/', $urlSuffix)) {
670
            $url = $urlSuffix;
671
        } elseif ($urlSuffix[0] == '/') {
672
            $url = $this->url.$urlSuffix;
673
        } else {
674
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
675
        }
676
677
        $responseCode = $this->doCurlRequest($url, $method, $format);
678
679
        return strlen($this->lastCurlResponse) ? $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
680
                    $this->responseFormat), $responseCode) : null;
681
    }
682
683
    /**
684
     * Parse Raw FlexiBee response in several formats
685
     *
686
     * @param string $responseRaw raw response body
687
     * @param string $format      Raw Response format json|xml|etc
688
     *
689
     * @return array
690
     */
691
    public function rawResponseToArray($responseRaw, $format)
692
    {
693
        switch ($format) {
694
            case 'json':
695
                $responseDecoded = json_decode($responseRaw, true, 10);
696
                $decodeError     = json_last_error_msg();
697
                if ($decodeError == 'No error') {
698
                    if (array_key_exists($this->nameSpace, $responseDecoded)) {
699
                        $responseDecoded = $responseDecoded[$this->nameSpace];
700
                    }
701
                } else {
702
                    $this->addStatusMessage('JSON Decoder: '.$decodeError,
703
                        'error');
704
                    $this->addStatusMessage($responseRaw, 'debug');
705
                }
706
                break;
707
            case 'xml':
708
                $responseDecoded = self::xml2array($this->lastCurlResponse);
709
                break;
710
            case 'txt':
711
            default:
712
                $responseDecoded = $this->lastCurlResponse;
713
                break;
714
        }
715
        return $responseDecoded;
716
    }
717
718
    /**
719
     * Parse Response array
720
     *
721
     * @param array $responseDecoded
722
     * @param int $responseCode Request Response Code
723
     *
724
     * @return array main data part of response
725
     */
726
    public function parseResponse($responseDecoded, $responseCode)
727
    {
728
        $response = null;
729
        switch ($responseCode) {
730
            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...
731
                if (isset($responseDecoded[$this->resultField][0]['id'])) {
732
                    $this->lastInsertedID = $responseDecoded[$this->resultField][0]['id'];
733
                    $this->setMyKey($this->lastInsertedID);
734
                    $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
735
                } else {
736
                    $this->lastInsertedID = null;
737
                }
738
            case 200: //Success Read
739
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
740
                if (isset($responseDecoded['@rowCount'])) {
741
                    $this->rowCount = (int) $responseDecoded['@rowCount'];
742
                }
743
                break;
744
745
            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...
746
                if ($this->debug === true) {
747
                    $this->error500Reporter($responseDecoded);
748
                }
749
            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...
750
                if ($this->ignoreNotFound === true) {
751
                    break;
752
                }
753
            case 400: //Bad Request parameters
754
            default: //Something goes wrong
755
                $this->addStatusMessage($this->curlInfo['url'], 'warning');
756
                if (is_array($responseDecoded)) {
757
                    $this->parseError($responseDecoded);
758
                }
759
                $this->logResult($responseDecoded, $this->curlInfo['url']);
760
                break;
761
        }
762
        return $response;
763
    }
764
765
    /**
766
     * Parse error message response
767
     *
768
     * @param array $responseDecoded
769
     * @return int number of errors processed
770
     */
771
    public function parseError(array $responseDecoded)
772
    {
773
        if (array_key_exists('results', $responseDecoded)) {
774
            $this->errors = $responseDecoded['results'][0]['errors'];
775
        } else {
776
            if (array_key_exists('message', $responseDecoded)) {
777
                $this->errors = [['message' => $responseDecoded['message']]];
778
            }
779
        }
780
        return count($this->errors);
781
    }
782
783
    /**
784
     * Vykonej HTTP požadavek
785
     *
786
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
787
     * @param string $url    URL požadavku
788
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
789
     * @param string $format požadovaný formát komunikace
790
     * @return int HTTP Response CODE
791
     */
792
    public function doCurlRequest($url, $method, $format = null)
793
    {
794
        if (is_null($format)) {
795
            $format = $this->format;
796
        }
797
        curl_setopt($this->curl, CURLOPT_URL, $url);
798
// Nastavení samotné operace
799
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
800
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
801
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
802
803
        $httpHeaders = $this->defaultHttpHeaders;
804
805
        $formats = Formats::bySuffix();
806
807
        if (!isset($httpHeaders['Accept'])) {
808
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
809
        }
810
        if (!isset($httpHeaders['Content-Type'])) {
811
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
812
        }
813
        $httpHeadersFinal = [];
814
        foreach ($httpHeaders as $key => $value) {
815
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
816
                $value .= ' v'.self::$libVersion;
817
            }
818
            $httpHeadersFinal[] = $key.': '.$value;
819
        }
820
821
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
822
823
// Proveď samotnou operaci
824
        $this->lastCurlResponse            = curl_exec($this->curl);
825
        $this->curlInfo                    = curl_getinfo($this->curl);
826
        $this->curlInfo['when']            = microtime();
827
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
828
        $this->responseFormat              = Formats::contentTypeToSuffix($this->curlInfo['content_type']);
829
        $this->lastResponseCode            = $this->curlInfo['http_code'];
830
        $this->lastCurlError               = curl_error($this->curl);
831
        if (strlen($this->lastCurlError)) {
832
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
833
                    $this->lastResponseCode, $this->lastCurlError), 'error');
834
        }
835
836
        if ($this->debug === true) {
837
            $this->saveDebugFiles();
838
        }
839
840
        return $this->lastResponseCode;
841
    }
842
843
    /**
844
     * Nastaví druh prováděné akce.
845
     *
846
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
847
     * @param string $action
848
     * @return boolean
849
     */
850
    public function setAction($action)
851
    {
852
        $result           = false;
853
        $actionsAvailable = $this->getActionsInfo();
854
        if (is_array($actionsAvailable) && array_key_exists($action,
855
                $actionsAvailable)) {
856
            $this->action = $action;
857
            $result       = true;
858
        }
859
        return $result;
860
    }
861
862
    /**
863
     * Convert XML to array.
864
     *
865
     * @param string $xml
866
     *
867
     * @return array
868
     */
869
    public static function xml2array($xml)
870
    {
871
        $arr = [];
872
873
        if (is_string($xml)) {
874
            $xml = simplexml_load_string($xml);
875
        }
876
877
        foreach ($xml->children() as $r) {
878
            if (count($r->children()) == 0) {
879
                $arr[$r->getName()] = strval($r);
880
            } else {
881
                $arr[$r->getName()][] = self::xml2array($r);
882
            }
883
        }
884
885
        return $arr;
886
    }
887
888
    /**
889
     * Odpojení od FlexiBee.
890
     */
891
    public function disconnect()
892
    {
893
        if (is_resource($this->curl)) {
894
            curl_close($this->curl);
895
        }
896
        $this->curl = null;
897
    }
898
899
    /**
900
     * Disconnect CURL befere pass away
901
     */
902
    public function __destruct()
903
    {
904
        $this->disconnect();
905
    }
906
907
    /**
908
     * Načte řádek dat z FlexiBee.
909
     *
910
     * @param int $recordID id požadovaného záznamu
911
     *
912
     * @return array
913
     */
914
    public function getFlexiRow($recordID)
915
    {
916
        $record   = null;
917
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
918
        if (isset($response[$this->evidence])) {
919
            $record = $response[$this->evidence][0];
920
        }
921
922
        return $record;
923
    }
924
925
    /**
926
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
927
     *
928
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
929
     * @param array $conditions pole podmínek   - rendrují se do ()
930
     * @param array $urlParams  pole parametrů  - rendrují za ?
931
     */
932
    public function extractUrlParams(&$conditions, &$urlParams)
933
    {
934
        foreach ($this->urlParams as $urlParam) {
935
            if (isset($conditions[$urlParam])) {
936
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
937
            }
938
        }
939
    }
940
941
    /**
942
     * Načte data z FlexiBee.
943
     *
944
     * @param string $suffix     dotaz
945
     * @param string|array $conditions Volitelný filtrovací výraz
946
     */
947
    public function getFlexiData($suffix = null, $conditions = null)
948
    {
949
        $urlParams = $this->defaultUrlParams;
950
        if (!is_null($conditions)) {
951
            if (is_array($conditions)) {
952
                $this->extractUrlParams($conditions, $urlParams);
953
                $conditions = $this->flexiUrl($conditions);
954
            }
955
956
            if (strlen($conditions) && ($conditions[0] != '/')) {
957
                $conditions = rawurlencode('('.($conditions).')');
958
            }
959
        } else {
960
            $conditions = '';
961
        }
962
963
        if (preg_match('/^http/', $suffix) || ($suffix[0] == '/')) {
964
            $transactions = $this->performRequest($suffix, 'GET');
965
        } else {
966
            if (strlen($suffix)) {
967
                $transactions = $this->performRequest($conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
968
                    'GET');
969
            } else {
970
                $transactions = $this->performRequest($conditions.'.'.$this->format.'?'.http_build_query($urlParams),
971
                    'GET');
972
            }
973
        }
974
        $responseEvidence = $this->getResponseEvidence();
975
        if (is_array($transactions) && array_key_exists($responseEvidence,
976
                $transactions)) {
977
            $result = $transactions[$responseEvidence];
978
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
979
                $result = null; // Response is empty Array
980
            }
981
        } else {
982
            $result = $transactions;
983
        }
984
985
        return $result;
986
    }
987
988
    /**
989
     * Načte záznam z FlexiBee a uloží v sobě jeho data
990
     * Read FlexiBee record and store it inside od object
991
     *
992
     * @param int|array $id ID or conditions
993
     *
994
     * @return int počet načtených položek
995
     */
996
    public function loadFromFlexiBee($id = null)
997
    {
998
        $data = [];
999
        if (is_null($id)) {
1000
            $id = $this->getMyKey();
1001
        }
1002
1003
        $flexidata = $this->getFlexiData(null, is_array($id) ? $id : '/'.$id);
1004
1005
        $this->apiURL = $this->curlInfo['url'];
1006
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1007
            $data = current($flexidata);
1008
        }
1009
        return $this->takeData($data);
1010
    }
1011
1012
    /**
1013
     * Převede data do Json formátu pro FlexiBee.
1014
     * Convert data to FlexiBee like Json format
1015
     *
1016
     * @param array $data
1017
     *
1018
     * @return string
1019
     */
1020
    public function jsonizeData($data)
1021
    {
1022
        $dataToJsonize = [
1023
            $this->nameSpace => [
1024
                '@version' => $this->protoVersion,
1025
                $this->evidence => $this->objectToID($data),
1026
            ],
1027
        ];
1028
1029 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...
1030
            $dataToJsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1031
            $this->action                                               = null;
1032
        }
1033
1034 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...
1035
            $dataToJsonize[$this->nameSpace][$this->evidence.'@filter'] = $this->filter;
1036
        }
1037
1038
        return json_encode($dataToJsonize);
1039
    }
1040
1041
    /**
1042
     * Test if given record ID exists in FlexiBee.
1043
     *
1044
     * @param string|int $identifer
1045
     */
1046
    public function idExists($identifer = null)
1047
    {
1048
        if (is_null($identifer)) {
1049
            $identifer = $this->getMyKey();
1050
        }
1051
        $flexiData = $this->getFlexiData(
1052
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
1053
1054
        return $flexiData;
1055
    }
1056
1057
    /**
1058
     * Test if given record exists in FlexiBee.
1059
     *
1060
     * @param array $data
1061
     * @return boolean Record presence status
1062
     */
1063
    public function recordExists($data = [])
1064
    {
1065
1066
        if (empty($data)) {
1067
            $data = $this->getData();
1068
        }
1069
1070
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1071
            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...
1072
1073
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1074
            || !count($res[0])) {
1075
            $found = false;
1076
        } else {
1077
            $found = true;
1078
        }
1079
        return $found;
1080
    }
1081
1082
    /**
1083
     * Vrací z FlexiBee sloupečky podle podmínek.
1084
     *
1085
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1086
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1087
     *                                     sloupečku
1088
     * @return array
1089
     */
1090
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1091
    {
1092
        if (is_int($conditions)) {
1093
            $conditions = [$this->getmyKeyColumn() => $conditions];
1094
        }
1095
1096
        $flexiData = $this->getFlexiData('', $conditions);
1097
1098
        if (!is_null($indexBy)) {
1099
            $flexiData = $this->reindexArrayBy($flexiData);
1100
        }
1101
1102
        return $flexiData;
1103
    }
1104
1105
    /**
1106
     * Vrací z FlexiBee sloupečky podle podmínek.
1107
     *
1108
     * @param string[] $columnsList seznam položek
1109
     * @param array    $conditions  pole podmínek nebo ID záznamu
1110
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1111
     *
1112
     * @return array
1113
     */
1114
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1115
                                           $indexBy = null)
1116
    {
1117
        $detail = 'full';
1118
        switch (gettype($columnsList)) {
1119
            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...
1120
                $conditions = [$this->getmyKeyColumn() => $conditions];
1121
            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...
1122
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1123
                        $columnsList)) {
1124
                    $columnsList[] = $indexBy;
1125
                }
1126
                $columns = implode(',', array_unique($columnsList));
1127
                $detail  = 'custom:'.$columns;
1128
            default:
1129
                switch ($columnsList) {
1130
                    case 'id':
1131
                        $detail = 'id';
1132
                        break;
1133
                    case 'summary':
1134
                        $detail = 'summary';
1135
                        break;
1136
                    default:
1137
                        break;
1138
                }
1139
                break;
1140
        }
1141
1142
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1143
1144
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1145
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1146
        }
1147
1148
        return $flexiData;
1149
    }
1150
1151
    /**
1152
     * Vrací kód záznamu.
1153
     * Obtain record CODE
1154
     *
1155
     * @param mixed $data
1156
     *
1157
     * @return string
1158
     */
1159
    public function getKod($data = null, $unique = true)
1160
    {
1161
        $kod = null;
1162
1163
        if (is_null($data)) {
1164
            $data = $this->getData();
1165
        }
1166
1167
        if (is_string($data)) {
1168
            $data = [$this->nameColumn => $data];
1169
        }
1170
1171
        if (isset($data['kod'])) {
1172
            $kod = $data['kod'];
1173
        } else {
1174
            if (isset($data[$this->nameColumn])) {
1175
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1176
                    \Ease\Sand::rip($data[$this->nameColumn]));
1177
            } else {
1178
                if (isset($data[$this->myKeyColumn])) {
1179
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1180
                }
1181
            }
1182
        }
1183
1184
        if (!strlen($kod)) {
1185
            $kod = 'NOTSET';
1186
        }
1187
1188
        if (strlen($kod) > 18) {
1189
            $kodfinal = strtoupper(substr($kod, 0, 18));
1190
        } else {
1191
            $kodfinal = strtoupper($kod);
1192
        }
1193
1194
        if ($unique) {
1195
            $counter = 0;
1196
            if (count($this->codes)) {
1197
                foreach ($this->codes as $codesearch => $keystring) {
1198
                    if (strstr($codesearch, $kodfinal)) {
1199
                        ++$counter;
1200
                    }
1201
                }
1202
            }
1203
            if ($counter) {
1204
                $kodfinal = $kodfinal.$counter;
1205
            }
1206
1207
            $this->codes[$kodfinal] = $kod;
1208
        }
1209
1210
        return $kodfinal;
1211
    }
1212
1213
    /**
1214
     * Write Operation Result.
1215
     *
1216
     * @param array  $resultData
1217
     * @param string $url        URL
1218
     * @return boolean Log save success
1219
     */
1220
    public function logResult($resultData = null, $url = null)
1221
    {
1222
        $logResult = false;
1223
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1224
            if (isset($resultData['message'])) {
1225
                $this->addStatusMessage($resultData['message'], 'warning');
1226
            }
1227
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1228
                'warning');
1229
            unset($url);
1230
        }
1231
        if (is_null($resultData)) {
1232
            $resultData = $this->lastResult;
1233
        }
1234
        if (isset($url)) {
1235
            $this->logger->addStatusMessage(urldecode($url));
1236
        }
1237
1238
        if (isset($resultData['results'])) {
1239
            if ($resultData['success'] == 'false') {
1240
                $status = 'error';
1241
            } else {
1242
                $status = 'success';
1243
            }
1244
            foreach ($resultData['results'] as $result) {
1245
                if (isset($result['request-id'])) {
1246
                    $rid = $result['request-id'];
1247
                } else {
1248
                    $rid = '';
1249
                }
1250
                if (isset($result['errors'])) {
1251
                    foreach ($result['errors'] as $error) {
1252
                        $message = $error['message'];
1253
                        if (isset($error['for'])) {
1254
                            $message .= ' for: '.$error['for'];
1255
                        }
1256
                        if (isset($error['value'])) {
1257
                            $message .= ' value:'.$error['value'];
1258
                        }
1259
                        if (isset($error['code'])) {
1260
                            $message .= ' code:'.$error['code'];
1261
                        }
1262
                        $this->addStatusMessage($rid.': '.$message, $status);
1263
                    }
1264
                }
1265
            }
1266
        }
1267
        return $logResult;
1268
    }
1269
1270
    /**
1271
     * Save RAW Curl Request & Response to files in Temp directory
1272
     */
1273
    public function saveDebugFiles()
1274
    {
1275
        $tmpdir   = sys_get_temp_dir();
1276
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1277
        $reqname  = $tmpdir.'/request-'.$fname;
1278
        $respname = $tmpdir.'/response-'.$fname;
1279
        file_put_contents($reqname, $this->postFields);
1280
        file_put_contents($respname, $this->lastCurlResponse);
1281
    }
1282
1283
    /**
1284
     * Připraví data pro odeslání do FlexiBee
1285
     *
1286
     * @param string $data
1287
     */
1288
    public function setPostFields($data)
1289
    {
1290
        $this->postFields = $data;
1291
    }
1292
1293
    /**
1294
     * Generuje fragment url pro filtrování.
1295
     *
1296
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1297
     *
1298
     * @param array  $data
1299
     * @param string $joiner default and/or
1300
     * @param string $defop  default operator
1301
     *
1302
     * @return string
1303
     */
1304
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1305
    {
1306
        $parts = [];
1307
1308
        foreach ($data as $column => $value) {
1309
            if (is_integer($data[$column]) || is_float($data[$column])) {
1310
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1311
            } elseif (is_bool($data[$column])) {
1312
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1313
            } elseif (is_null($data[$column])) {
1314
                $parts[$column] = $column." is null";
1315
            } else {
1316
                switch ($value) {
1317
                    case '!null':
1318
                        $parts[$column] = $column." is not null";
1319
                        break;
1320
                    case 'is empty':
1321
                    case 'is not empty':
1322
                        $parts[$column] = $column.' '.$value;
1323
                        break;
1324
                    default:
1325
                        if ($column == 'stitky') {
1326
                            $parts[$column] = $column."='code:".$data[$column]."'";
1327
                        } else {
1328
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1329
                        }
1330
                        break;
1331
                }
1332
            }
1333
        }
1334
        return implode(' '.$joiner.' ', $parts);
1335
    }
1336
1337
    /**
1338
     * Obtain record/object identificator code: or id:
1339
     * Vrací identifikátor objektu code: nebo id:
1340
     *
1341
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1342
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1343
     */
1344
    public function getRecordID()
1345
    {
1346
        $myCode = $this->getDataValue('kod');
1347
        if ($myCode) {
1348
            $id = 'code:'.$myCode;
1349
        } else {
1350
            $id = $this->getDataValue('id');
1351
            if (($this->debug === true) && is_null($id)) {
1352
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1353
                    'warning');
1354
            }
1355
        }
1356
        return is_numeric($id) ? intval($id) : strval($id);
1357
    }
1358
1359
    /**
1360
     * Obtain record/object identificator code: or id:
1361
     * Vrací identifikátor objektu code: nebo id:
1362
     *
1363
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1364
     * @return string indentifikátor záznamu reprezentovaného objektem
1365
     */
1366
    public function __toString()
1367
    {
1368
        return strval($this->getRecordID());
1369
    }
1370
1371
    /**
1372
     * Gives you FlexiPeeHP class name for Given Evidence
1373
     *
1374
     * @param string $evidence
1375
     * @return string Class name
1376
     */
1377
    public static function evidenceToClassName($evidence)
1378
    {
1379
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1380
    }
1381
1382
    /**
1383
     * Vrací hodnotu daného externího ID
1384
     *
1385
     * @param string $want Which ? If empty,you obtain the first one.
1386
     * @return string
1387
     */
1388
    public function getExternalID($want = null)
1389
    {
1390
        $extid = null;
1391
        $ids   = $this->getDataValue('external-ids');
1392
        if (is_null($want)) {
1393
            if (count($ids)) {
1394
                $extid = current($ids);
1395
            }
1396
        } else {
1397
            if (!is_null($ids) && is_array($ids)) {
1398
                foreach ($ids as $id) {
1399
                    if (strstr($id, 'ext:'.$want)) {
1400
                        $extid = str_replace('ext:'.$want.':', '', $id);
1401
                    }
1402
                }
1403
            }
1404
        }
1405
        return $extid;
1406
    }
1407
1408
    /**
1409
     * Obtain actual GlobalVersion
1410
     * Vrací aktuální globální verzi změn
1411
     *
1412
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1413
     * @return type
1414
     */
1415
    public function getGlobalVersion()
1416
    {
1417
        $globalVersion = null;
1418
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1419
            $this->getFlexiData(null,
1420
                ['add-global-version' => 'true', 'limit' => 1]);
1421
        }
1422
1423
        if (isset($this->lastResult['@globalVersion'])) {
1424
            $globalVersion = intval($this->lastResult['@globalVersion']);
1425
        }
1426
1427
        return $globalVersion;
1428
    }
1429
1430
    /**
1431
     * Obtain content type of last response
1432
     *
1433
     * @return string
1434
     */
1435
    public function getResponseFormat()
1436
    {
1437
        if (isset($this->curlInfo['content_type'])) {
1438
            $responseFormat = $this->curlInfo['content_type'];
1439
        } else {
1440
            $responseFormat = null;
1441
        }
1442
        return $responseFormat;
1443
    }
1444
1445
    /**
1446
     * Return the same response format for one and multiplete results
1447
     *
1448
     * @param array $responseBody
1449
     * @return array
1450
     */
1451
    public function unifyResponseFormat($responseBody)
1452
    {
1453
        if (!is_array($responseBody) || array_key_exists('message',
1454
                $responseBody)) { //Unifi response format
1455
            $response = $responseBody;
1456
        } else {
1457
            $evidence = $this->getResponseEvidence();
1458
            if (array_key_exists($evidence, $responseBody)) {
1459
                $response        = [];
1460
                $evidenceContent = $responseBody[$evidence];
1461
                if (array_key_exists(0, $evidenceContent)) {
1462
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1463
                } else {
1464
                    $response[$evidence][0] = $evidenceContent; //One result
1465
                }
1466
            } else {
1467
                if (isset($responseBody['priloha'])) {
1468
                    $response = $responseBody['priloha'];
1469
                } else {
1470
                    $response = $responseBody;
1471
                }
1472
            }
1473
        }
1474
        return $response;
1475
    }
1476
1477
    /**
1478
     * Obtain structure for current (or given) evidence
1479
     *
1480
     * @param string $evidence
1481
     * @return array Evidence structure
1482
     */
1483 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...
1484
    {
1485
        $columnsInfo = null;
1486
        if (is_null($evidence)) {
1487
            $evidence = $this->getEvidence();
1488
        }
1489
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1490
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1491
            $columnsInfo = Properties::$$propsName;
1492
        }
1493
        return $columnsInfo;
1494
    }
1495
1496
    /**
1497
     * Obtain actions for current (or given) evidence
1498
     *
1499
     * @param string $evidence
1500
     * @return array Evidence structure
1501
     */
1502 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...
1503
    {
1504
        $actionsInfo = null;
1505
        if (is_null($evidence)) {
1506
            $evidence = $this->getEvidence();
1507
        }
1508
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1509
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1510
            $actionsInfo = Actions::$$propsName;
1511
        }
1512
        return $actionsInfo;
1513
    }
1514
1515
    /**
1516
     * Obtain relations for current (or given) evidence
1517
     *
1518
     * @param string $evidence
1519
     * @return array Evidence structure
1520
     */
1521
    public function getRelationsInfo($evidence = null)
1522
    {
1523
        $relationsInfo = null;
1524
        if (is_null($evidence)) {
1525
            $evidence = $this->getEvidence();
1526
        }
1527
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1528
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1529
            $relationsInfo = Relations::$$propsName;
1530
        }
1531
        return $relationsInfo;
1532
    }
1533
1534
    /**
1535
     * Obtain info for current (or given) evidence
1536
     *
1537
     * @param string $evidence
1538
     * @return array Evidence info
1539
     */
1540 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...
1541
    {
1542
        $evidencesInfo = null;
1543
        if (is_null($evidence)) {
1544
            $evidence = $this->getEvidence();
1545
        }
1546
        if (isset(EvidenceList::$evidences[$evidence])) {
1547
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1548
        }
1549
        return $evidencesInfo;
1550
    }
1551
1552
    /**
1553
     * Obtain name for current (or given) evidence path
1554
     *
1555
     * @param string $evidence Evidence Path
1556
     * @return array Evidence info
1557
     */
1558 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...
1559
    {
1560
        $evidenceName = null;
1561
        if (is_null($evidence)) {
1562
            $evidence = $this->getEvidence();
1563
        }
1564
        if (isset(EvidenceList::$name[$evidence])) {
1565
            $evidenceName = EvidenceList::$name[$evidence];
1566
        }
1567
        return $evidenceName;
1568
    }
1569
1570
    /**
1571
     * Perform given action (if availble) on current evidence/record
1572
     * @url https://demo.flexibee.eu/devdoc/actions
1573
     *
1574
     * @param string $action one of evidence actions
1575
     * @param string $method ext|int External method call operation in URL.
1576
     *                               Internal add the @action element to request body
1577
     */
1578
    public function performAction($action, $method = 'ext')
1579
    {
1580
        $actionsAvailble = $this->getActionsInfo();
1581
1582
        if (is_array($actionsAvailble) && array_key_exists($action,
1583
                $actionsAvailble)) {
1584
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1585
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1586
                case 'ONLY_WITH_INSTANCE': //Add instance
1587
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1588
                    break;
1589
1590
                default:
1591
                    $urlSuffix = '/'.$action;
1592
                    break;
1593
            }
1594
1595
            switch ($method) {
1596
                case 'int':
1597
                    $this->setAction($action);
1598
                    $this->setPostFields($this->jsonizeData($this->getData()));
1599
                    $result = $this->performRequest(null, 'POST');
1600
                    break;
1601
1602
                default:
1603
                    $result = $this->performRequest($urlSuffix, 'GET');
1604
                    break;
1605
            }
1606
        } else {
1607
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1608
                $action, $this->getEvidence()));
1609
        }
1610
1611
        return $result;
1612
    }
1613
1614
    /**
1615
     * Save current object to file
1616
     *
1617
     * @param string $destfile path to file
1618
     */
1619
    public function saveResponseToFile($destfile)
1620
    {
1621
        if (strlen($this->lastCurlResponse)) {
1622
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1623
        }
1624
        file_put_contents($destfile, $this->lastCurlResponse);
1625
    }
1626
1627
    /**
1628
     * Obtain established relations listing
1629
     *
1630
     * @return array Null or Relations
1631
     */
1632
    public function getVazby()
1633
    {
1634
        $vazby = $this->getDataValue('vazby');
1635
        if (is_null($vazby)) {
1636
            $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...
1637
                ['relations' => 'vazby', 'id' => $this->getRecordID()]);
1638
            $vazby = $vazby[0]['vazby'];
1639
        }
1640
        return $vazby;
1641
    }
1642
1643
    /**
1644
     * Gives You URL for Current Record in FlexiBee web interface
1645
     *
1646
     * @return string url
1647
     */
1648
    public function getFlexiBeeURL()
1649
    {
1650
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1651
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1652
                : '';
1653
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1654
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1655
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1656
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1657
        $pass       = ($user || $pass) ? "$pass@" : '';
1658
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1659
        return $scheme.$user.$pass.$host.$port.$path;
1660
    }
1661
1662
    /**
1663
     * Set Record Key
1664
     *
1665
     * @param int|string $myKeyValue
1666
     * @return boolean
1667
     */
1668
    public function setMyKey($myKeyValue)
1669
    {
1670
        $res = parent::setMyKey($myKeyValue);
1671
        $this->updateApiURL();
1672
        return $res;
1673
    }
1674
1675
    /**
1676
     * Set or get ignore not found pages flag
1677
     *
1678
     * @param boolean $ignore set flag to
1679
     *
1680
     * @return boolean get flag state
1681
     */
1682
    public function ignore404($ignore = null)
1683
    {
1684
        if (!is_null($ignore)) {
1685
            $this->ignoreNotFound = $ignore;
1686
        }
1687
        return $this->ignoreNotFound;
1688
    }
1689
1690
    /**
1691
     * Send Document by mail
1692
     *
1693
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1694
     *
1695
     * @param string $to
1696
     * @param string $subject
1697
     * @param string $body Email Text
1698
     *
1699
     * @return int http response code
1700
     */
1701
    public function sendByMail($to, $subject, $body, $cc = null)
1702
    {
1703
        $this->setPostFields($body);
1704
        $result = $this->doCurlRequest($this->getEvidenceURL().'/'.
1705
            urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1706
            , 'PUT', 'xml');
1707
        return $result == 200;
1708
    }
1709
1710
    /**
1711
     * Send all unsent Invoices by mail
1712
     *
1713
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1714
     * @return int http response code
1715
     */
1716
    public function sendUnsent()
1717
    {
1718
        return $this->doCurlRequest($this->getEvidenceURL().'/automaticky-odeslat-neodeslane',
1719
                'PUT', 'xml');
1720
    }
1721
1722
    /**
1723
     * FlexiBee date to PHP DateTime
1724
     *
1725
     * @param string $flexidate
1726
     *
1727
     * @return \DateTime | false
1728
     */
1729
    public static function flexiDateToDateTime($flexidate)
1730
    {
1731
        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 1731 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...
1732
    }
1733
1734
    /**
1735
     * Získá dokument v daném formátu
1736
     * Obtain document in given format
1737
     *
1738
     * @param string $format  pdf/csv/xml/json/ ...
1739
     *
1740
     * @return string|null filename downloaded or none
1741
     */
1742
    public function getInFormat($format)
1743
    {
1744
        $response = null;
1745
        if ($this->setFormat($format)) {
1746
            if (($this->doCurlRequest(($format == 'html') ? $this->apiURL.'?inDesktopApp=true'
1747
                            : $this->apiURL, 'GET') == 200)) {
1748
                $response = $this->lastCurlResponse;
1749
            }
1750
        }
1751
        return $response;
1752
    }
1753
1754
    /**
1755
     * Uloží dokument v daném formátu do složky v systému souborů
1756
     * Save document in given format to directory in filesystem
1757
     *
1758
     * @param string $format  pdf/csv/xml/json/ ...
1759
     * @param string $destDir where to put file (prefix)
1760
     *
1761
     * @return string|null filename downloaded or none
1762
     */
1763
    public function downloadInFormat($format, $destDir = './')
1764
    {
1765
        $fileOnDisk = null;
1766
        if ($this->setFormat($format)) {
1767
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1768
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1769
                    $this->lastCurlResponse) !== false)) {
1770
                $fileOnDisk = $downloadTo;
1771
            }
1772
        }
1773
        return $fileOnDisk;
1774
    }
1775
1776
    /**
1777
     * Compile and send Report about Error500 to FlexiBee developers
1778
     * If FlexiBee is running on localost try also include java backtrace
1779
     *
1780
     * @param array $errorResponse result of parseError();
1781
     */
1782
    public function error500Reporter($errorResponse)
1783
    {
1784
        $ur = str_replace('/c/'.$this->company, '',
1785
            str_replace($this->url, '', $this->curlInfo['url']));
1786
        if (!array_key_exists($ur, $this->reports)) {
1787
            $tmpdir   = sys_get_temp_dir();
1788
            $myTime   = $this->curlInfo['when'];
1789
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
1790
            file_put_contents($curlname,
1791
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
1792
1793
            $report = new \Ease\Mailer($this->reportRecipient,
1794
                'Error report 500 - '.$ur);
1795
1796
            $d     = dir($tmpdir);
1797
            while (false !== ($entry = $d->read())) {
1798
                if (strstr($entry, $myTime)) {
1799
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
1800
                    $mime = Formats::suffixToContentType($ext);
1801
                    $report->addFile($tmpdir.'/'.$entry,
1802
                        empty($mime) ? 'text/plain' : $mime);
1803
                }
1804
            }
1805
            $d->close();
1806
1807
            if ((strstr($this->url, '://localhost') || strstr($this->url,
1808
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
1809
1810
                $fl = fopen("/var/log/flexibee.log", "r");
1811
                if ($fl) {
1812
                    $tracelog = [];
1813
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
1814
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
1815
                        $char = fgetc($fl);
1816
                        if ($char === "\n") {
1817
                            $tracelog[] = $output[$ln];
1818
                            if (strstr($output[$ln], $errorResponse['message'])) {
1819
                                break;
1820
                            }
1821
                            $ln++;
1822
                            continue;
1823
                        }
1824
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
1825
                                : '');
1826
                    }
1827
1828
                    $trace     = implode("\n", array_reverse($tracelog));
1829
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
1830
                    file_put_contents($tracefile, $trace);
1831
                    $report->addItem("\n\n".$trace);
1832
                    fclose($fl);
1833
                }
1834
            } else {
1835
                $report->addItem($errorResponse['message']);
1836
            }
1837
1838
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
1839
1840
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
1841
                    JSON_PRETTY_PRINT));
1842
1843
            if ($report->send()) {
1844
                $this->reports[$ur] = $myTime;
1845
            }
1846
        }
1847
    }
1848
}
1849