Passed
Push — master ( 5b9f35...ae1426 )
by Vítězslav
03:16
created

FlexiBeeRO::getSubItems()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 4
nop 0
crap 3
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-2018 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\Sand
17
{
18
    /**
19
     * Where to get JSON files with evidence stricture etc.
20
     * @var string
21
     */
22
    public static $infoDir = __DIR__.'/../../static';
23
24
    /**
25
     * Version of FlexiPeeHP library
26
     *
27
     * @var string
28
     */
29
    public static $libVersion = '1.17';
30
31
    /**
32
     * Základní namespace pro komunikaci s FlexiBee.
33
     * Basic namespace for communication with FlexiBee
34
     *
35
     * @var string Jmený prostor datového bloku odpovědi
36
     */
37
    public $nameSpace = 'winstrom';
38
39
    /**
40
     * URL of object data in FlexiBee
41
     * @var string url
42
     */
43
    public $apiURL = null;
44
45
    /**
46
     * Datový blok v poli odpovědi.
47
     * Data block in response field.
48
     *
49
     * @var string
50
     */
51
    public $resultField = 'results';
52
53
    /**
54
     * Verze protokolu použitého pro komunikaci.
55
     * Communication protocol version used.
56
     *
57
     * @var string Verze použitého API
58
     */
59
    public $protoVersion = '1.0';
60
61
    /**
62
     * Evidence užitá objektem.
63
     * Evidence used by object
64
     *
65
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
66
     * @var string
67
     */
68
    public $evidence = null;
69
70
    /**
71
     * Výchozí formát pro komunikaci.
72
     * Default communication format.
73
     *
74
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
75
     *
76
     * @var string json|xml|...
77
     */
78
    public $format = 'json';
79
80
    /**
81
     * formát příchozí odpovědi
82
     * response format
83
     *
84
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
85
     *
86
     * @var string json|xml|...
87
     */
88
    public $responseFormat = 'json';
89
90
    /**
91
     * Curl Handle.
92
     *
93
     * @var resource
94
     */
95
    public $curl = null;
96
97
    /**
98
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
99
     * @var string
100
     */
101
    public $company = null;
102
103
    /**
104
     * Server[:port]
105
     * @var string
106
     */
107
    public $url = null;
108
109
    /**
110
     * REST API Username
111
     * @var string
112
     */
113
    public $user = null;
114
115
    /**
116
     * REST API Password
117
     * @var string
118
     */
119
    public $password = null;
120
121
    /**
122
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
123
     */
124
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
125
126
    /**
127
     * Default additional request url parameters after question mark
128
     *
129
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
130
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
131
     * @var array
132
     */
133
    public $defaultUrlParams = ['limit' => 0];
134
135
    /**
136
     * Identifikační řetězec.
137
     *
138
     * @var string
139
     */
140
    public $init = null;
141
142
    /**
143
     * Sloupeček s názvem.
144
     *
145
     * @var string
146
     */
147
    public $nameColumn = 'nazev';
148
149
    /**
150
     * Sloupeček obsahující datum vložení záznamu do shopu.
151
     *
152
     * @var string
153
     */
154
    public $myCreateColumn = 'false';
155
156
    /**
157
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
158
     *
159
     * @var string
160
     */
161
    public $myLastModifiedColumn = 'lastUpdate';
162
163
    /**
164
     * Klíčový idendifikátor záznamu.
165
     *
166
     * @var string
167
     */
168
    public $fbKeyColumn = 'id';
169
170
    /**
171
     * Informace o posledním HTTP requestu.
172
     *
173
     * @var *
174
     */
175
    public $curlInfo;
176
177
    /**
178
     * Informace o poslední HTTP chybě.
179
     *
180
     * @var string
181
     */
182
    public $lastCurlError = null;
183
184
    /**
185
     * Used codes storage.
186
     *
187
     * @var array
188
     */
189
    public $codes = null;
190
191
    /**
192
     * Last Inserted ID.
193
     *
194
     * @var int
195
     */
196
    public $lastInsertedID = null;
197
198
    /**
199
     * Default Line Prefix.
200
     *
201
     * @var string
202
     */
203
    public $prefix = '/c/';
204
205
    /**
206
     * Raw Content of last curl response
207
     *
208
     * @var string
209
     */
210
    public $lastCurlResponse;
211
212
    /**
213
     * HTTP Response code of last request
214
     *
215
     * @var int
216
     */
217
    public $lastResponseCode = null;
218
219
    /**
220
     * Body data  for next curl POST operation
221
     *
222
     * @var string
223
     */
224
    protected $postFields = null;
225
226
    /**
227
     * Last operation result data or message(s)
228
     *
229
     * @var array
230
     */
231
    public $lastResult = null;
232
233
    /**
234
     * Number from  @rowCount in response
235
     * @var int
236
     */
237
    public $rowCount = null;
238
239
    /**
240
     * Number from  @globalVersion
241
     * @var int
242
     */
243
    public $globalVersion = null;
244
245
    /**
246
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
247
     * @var string filter query
248
     */
249
    public $filter;
250
251
    /**
252
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
253
     * @var string
254
     */
255
    protected $action;
256
257
    /**
258
     * Pole akcí které podporuje ta která evidence
259
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
260
     * @var array
261
     */
262
    public $actionsAvailable = null;
263
264
    /**
265
     * Parmetry pro URL
266
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
267
     * @var array
268
     */
269
    public $urlParams = [
270
        'add-global-version',
271
        'add-row-count',
272
        'as-gui',
273
        'auth',
274
        'authSessionId',
275
        'code-as-id',
276
        'code-in-response',
277
        'delimeter',
278
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
279
        'dir',
280
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
281
        'encoding',
282
        'export-settings',
283
        'fail-on-warning',
284
        'filter',
285
        'format',
286
        'idUcetniObdobi',
287
        'includes',
288
        'inDesktopApp', // Note: Undocumented function (html only)
289
        'limit',
290
        'mode',
291
        'no-ext-ids',
292
        'no-http-errors',
293
        'no-ids',
294
        'only-ext-ids',
295
        'order',
296
        'relations',
297
        'report-lang',
298
        'report-name',
299
        'report-sign',
300
        'skupina-stitku',
301
        'sort',
302
        'start',
303
        'stitky-as-ids',
304
        'use-ext-id',
305
        'use-internal-id',
306
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
307
    ];
308
309
    /**
310
     * Session ID
311
     * @var string
312
     */
313
    public $authSessionId = null;
314
315
    /**
316
     * Save 404 results to log ?
317
     * @var boolean
318
     */
319
    protected $ignoreNotFound = false;
320
321
    /**
322
     * Array of errors caused by last request
323
     * @var array
324
     */
325
    private $errors = [];
326
327
    /**
328
     * List of Error500 reports sent
329
     * @var array
330
     */
331
    private $reports = [];
332
333
    /**
334
     * Send Error500 Report to
335
     * @var string email address
336
     */
337
    public $reportRecipient = '[email protected]';
338
339
    /**
340 70
     * Formating string for \DateTime::format() for datetime columns
341
     * @var string
342 70
     */
343
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
344 70
345 70
    /**
346 70
     * Formating string for \DateTime::format() for date columns
347 70
     * @var string
348 22
     */
349 22
    static public $DateFormat = 'Y-m-d';
350 70
351
    /**
352
     * Last Request response stats
353
     * @var array 
354
     */
355
    private $responseStats = null;
356
357
    /**
358 71
     * Chained Objects
359
     * @var array
360 71
     */
361 71
    public $chained = [];
362 71
363 71
    /**
364 71
     * We Connect to server by default
365 23
     * @var boolean
366 23
     */
367 71
    public $offline = false;
368 71
369 23
    /**
370 23
     * Override cURL timeout
371 71
     * @var int seconds
372
     */
373
    public $timeout = null;
374 71
375 71
    /**
376 71
     * Class for read only interaction with FlexiBee.
377
     *
378
     * @param mixed $init default record id or initial data
379
     * @param array $options Connection settings and other options override
380
     */
381
    public function __construct($init = null, $options = [])
382
    {
383
        $this->init = $init;
384
385 48
        parent::__construct();
386
        $this->setUp($options);
387 48
        $this->curlInit();
388
        if (!empty($init)) {
389
            $this->processInit($init);
390 48
        }
391 48
    }
392 48
393
    /**
394 48
     * SetUp Object to be ready for work
395
     *
396
     * @param array $options Object Options ( user,password,authSessionId
397
     *                                        company,url,evidence,
398
     *                                        prefix,defaultUrlParams,debug,
399 94
     *                                        detail,offline,filter,ignore404
400
     *                                        timeout
401 94
     */
402 94
    public function setUp($options = [])
403 94
    {
404 94
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
405 94
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
406 94
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
407 94
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
408 94
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
409 94
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
410 94
        if (!empty($this->authSessionId)) {
411
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
412
        }
413
        if (isset($options['evidence'])) {
414
            $this->setEvidence($options['evidence']);
415
        }
416
        $this->setupProperty($options, 'defaultUrlParams');
417
        if (isset($options['prefix'])) {
418
            $this->setPrefix($options['prefix']);
419
        }
420
        if (array_key_exists('detail', $options)) {
421
            $this->defaultUrlParams['detail'] = $options['detail'];
422
        }
423 13
        $this->setupProperty($options, 'filter');
424
        if (array_key_exists('offline', $options)) {
425 13
            $this->offline = (boolean) $options['offline'];
426 10
        }
427 13
428 13
        if (array_key_exists('ignore404', $options)) {
429 13
            $this->ignore404($options['ignore404']);
430 10
        }
431 10
432 10
        $this->setupProperty($options, 'debug');
433 8
        $this->updateApiURL();
434
    }
435 13
436
    /**
437
     * Set up one of properties
438
     *
439
     * @param array  $options  array of given properties
440
     * @param string $name     name of property to process
441
     * @param string $constant load default property value from constant
442 23
     */
443
    public function setupProperty($options, $name, $constant = null)
444
    {
445 23
        if (array_key_exists($name, $options)) {
446 23
            $this->$name = $options[$name];
447 23
        } else {
448 23
            if (property_exists($this, $name) && !empty($constant) && defined($constant)) {
449 23
                $this->$name = constant($constant);
450 23
            }
451 23
        }
452 23
    }
453 23
454 23
    /**
455 23
     * Get Current connection options for use in another object
456 23
     *
457 23
     * @return array usable as second constructor parameter
458 23
     */
459 23
    public function getConnectionOptions()
460 23
    {
461 23
        $conOpts = ['url' => $this->url];
462 23
        if (empty($this->authSessionId)) {
463
            $conOpts ['user']    = $this->user;
464
            $conOpts['password'] = $this->password;
465
        } else {
466
            $conOpts['authSessionId'] = $this->authSessionId;
467
        }
468
        $company = $this->getCompany();
469
        if (!empty($company)) {
470
            $conOpts['company'] = $company;
471 23
        }
472
        if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
473 23
            $conOpts['timeout'] = $this->timeout;
474 23
        }
475
        return $conOpts;
476
    }
477
478
    /**
479
     * Inicializace CURL
480 23
     *
481 23
     * @return boolean Online Status
482 23
     */
483 23
    public function curlInit()
484 23
    {
485
        if ($this->offline === false) {
486
            $this->curl = \curl_init(); // create curl resource
487
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
488
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
489
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
490
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
491
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
492
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
493
            if (empty($this->authSessionId)) {
494 23
                curl_setopt($this->curl, CURLOPT_USERPWD,
495
                    $this->user.':'.$this->password); // set username and password
496 23
            }
497 23
            if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
498 23
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
499 23
            }
500
        }
501
        return !$this->offline;
502
    }
503 23
504 23
    /**
505
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
506
     *
507 20
     *  * 234                              - interní číslo záznamu k načtení
508 20
     *  * code:LOPATA                      - kód záznamu
509
     *  * BAGR                             - kód záznamu k načtení
510 20
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
511 3
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
512 3
     *
513 3
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
514 3
     */
515 23
    public function processInit($init)
516 23
    {
517 23
        if (is_integer($init)) {
518
            $this->loadFromFlexiBee($init);
519
        } elseif (is_array($init)) {
520
            $this->takeData($init);
521
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
522
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init)
523
                            : $init)));
524
        } else {
525
            $this->loadFromFlexiBee($init);
526 69
        }
527
    }
528 69
529
    /**
530
     * Set Data Field value
531
     *
532
     * @param string $columnName field name
533
     * @param mixed  $value      field data value
534
     *
535
     * @return bool Success
536
     */
537 23
    public function setDataValue($columnName, $value)
538
    {
539 23
        switch ($columnName) {
540 23
            case 'kod':
541
                $value = self::uncode($value); //Alwyas uncode "kod" column
542
                break;
543
            default:
544
                break;
545
        }
546
        if (is_object($value)) {
547
            switch (get_class($value)) {
548 23
                case 'DateTime':
549
                    $columnInfo = $this->getColumnInfo($columnName);
550 23
                    switch ($columnInfo['type']) {
551
                        case 'date':
552
                            $value = self::dateToFlexiDate($value);
553
                            break;
554
                        case 'datetime':
555
                            $value = self::dateToFlexiDateTime($value);
556
                            break;
557
                    }
558 25
                    break;
559
            }
560 25
        }
561 25
        return parent::setDataValue($columnName, $value);
562
    }
563
564 25
    /**
565 1
     * PHP Date object to FlexiBee date format
566 1
     * 
567 24
     * @param \DateTime $date
568 24
     */
569 24
    public static function dateToFlexiDate($date)
570 25
    {
571 25
        return $date->format(self::$DateFormat);
572
    }
573
574
    /**
575
     * PHP Date object to FlexiBee date format
576
     * 
577
     * @param \DateTime $dateTime
578
     */
579
    public static function dateToFlexiDateTime($dateTime)
580
    {
581 23
        return $dateTime->format(self::$DateTimeFormat);
582
    }
583 23
584 23
    /**
585 23
     * Set URL prefix
586 23
     *
587 23
     * @param string $prefix
588 23
     */
589 23
    public function setPrefix($prefix)
590 23
    {
591 23
        switch ($prefix) {
592 23
            case 'a': //Access
593 23
            case 'c': //Company
594 23
            case 'u': //User
595 23
            case 'g': //License Groups
596
            case 'admin':
597
            case 'status':
598
            case 'login-logout':
599 23
                $this->prefix = '/'.$prefix.'/';
600
                break;
601
            case null:
602
            case '':
603
            case '/':
604
                $this->prefix = '';
605
                break;
606
            default:
607
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
608
        }
609 23
    }
610
611 23
    /**
612 23
     * Set communication format.
613 22
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
614 22
     *
615 23
     * @param string $format
616 17
     * 
617 17
     * @return boolen format is availble
0 ignored issues
show
Bug introduced by
The type FlexiPeeHP\boolen was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
618 17
     */
619 17
    public function setFormat($format)
620 23
    {
621
        $result = true;
622
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
623
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
624 23
                === false) {
625
                $result = false;
626
            }
627
        }
628
        if ($result === true) {
629
            $this->format = $format;
630
            $this->updateApiURL();
631
        }
632
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type boolean which is incompatible with the documented return type FlexiPeeHP\boolen.
Loading history...
633
    }
634 68
635
    /**
636 68
     * Nastaví Evidenci pro Komunikaci.
637 68
     * Set evidence for communication
638 68
     *
639 62
     * @param string $evidence evidence pathName to use
640 62
     * 
641 68
     * @return boolean evidence switching status
642
     */
643
    public function setEvidence($evidence)
644
    {
645
        switch ($this->prefix) {
646
            case '/c/':
647
                if ($this->debug === true) {
648
                    if (array_key_exists($evidence, EvidenceList::$name)) {
649
                        $this->evidence = $evidence;
650
                        $result         = true;
651 23
                    } else {
652
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
653 23
                                $evidence));
654 23
                    }
655 23
                } else {
656 23
                    $this->evidence = $evidence;
657 23
                    $result         = true;
658 23
                }
659 23
                break;
660 23
            default:
661 23
                $this->evidence = $evidence;
662
                $result         = true;
663
                break;
664
        }
665
        $this->updateApiURL();
666
        return $result;
667 48
    }
668
669 48
    /**
670 48
     * Vrací právě používanou evidenci pro komunikaci
671 48
     * Obtain current used evidence
672
     *
673
     * @return string
674 48
     */
675 48
    public function getEvidence()
676
    {
677
        return $this->evidence;
678
    }
679
680
    /**
681
     * Set used company.
682
     * Nastaví Firmu.
683
     *
684
     * @param string $company
685
     */
686 23
    public function setCompany($company)
687
    {
688 23
        $this->company = $company;
689 23
    }
690 23
691 23
    /**
692 23
     * Obtain company now used
693 23
     * Vrací právě používanou firmu
694 23
     *
695 23
     * @return string
696 23
     */
697 23
    public function getCompany()
698 23
    {
699 23
        return $this->company;
700 23
    }
701
702
    /**
703 23
     * Vrací název evidence použité v odpovědích z FlexiBee
704 23
     *
705 23
     * @return string
706
     */
707
    public function getResponseEvidence()
708 23
    {
709
        switch ($this->evidence) {
710
            case 'c':
711
                $evidence = 'company';
712
                break;
713
            case 'evidence-list':
714
                $evidence = 'evidence';
715
                break;
716
            default:
717
                $evidence = $this->getEvidence();
718 23
                break;
719
        }
720 23
        return $evidence;
721
    }
722
723
    /**
724
     * Převede rekurzivně Objekt na pole.
725
     *
726
     * @param object|array $object
727
     *
728
     * @return array
729
     */
730
    public static function object2array($object)
731 25
    {
732
        $result = null;
733
        if (is_object($object)) {
734 25
            $objectData = get_object_vars($object);
735
            if (is_array($objectData) && count($objectData)) {
736 25
                $result = array_map('self::object2array', $objectData);
737
            }
738 25
        } else {
739 4
            if (is_array($object)) {
0 ignored issues
show
introduced by
The condition is_array($object) is always true.
Loading history...
740 4
                foreach ($object as $item => $value) {
741 22
                    $result[$item] = self::object2array($value);
742
                }
743
            } else {
744 25
                $result = $object;
745
            }
746 25
        }
747 25
748
        return $result;
749
    }
750
751
    /**
752
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
753
     *
754
     * @param object|array $object
755
     *
756
     * @return array
757
     */
758 3
    public static function objectToID($object)
759
    {
760 3
        $resultID = null;
761
        if (is_object($object) && method_exists($object, '__toString')
762 3
        ) {
763 3
            $resultID = $object->__toString();
764 3
        } else {
765
            if (is_array($object)) {
766
                foreach ($object as $item => $value) {
767
                    $resultID[$item] = self::objectToID($value);
768
                }
769
            } else { //String
770
                $resultID = $object;
771
            }
772
        }
773 3
774
        return $resultID;
775 3
    }
776
777
    /**
778
     * Return basic URL for used Evidence
779
     *
780
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
781
     *
782
     * @return string Evidence URL
783
     */
784
    public function getEvidenceURL()
785 3
    {
786
        $evidenceUrl = $this->url.$this->prefix.$this->company;
787 3
        $evidence    = $this->getEvidence();
788 3
        if (!empty($evidence)) {
789 3
            $evidenceUrl .= '/'.$evidence;
790 3
        }
791
        return $evidenceUrl;
792
    }
793 3
794
    /**
795
     * Add suffix to Evidence URL
796
     *
797 3
     * @param string $urlSuffix
798
     *
799
     * @return string
800
     */
801
    public function evidenceUrlWithSuffix($urlSuffix)
802
    {
803
        $evidenceUrl = $this->getEvidenceUrl();
804
        if (!empty($urlSuffix)) {
805
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
806
                != '?')) {
807
                $evidenceUrl .= '/';
808
            }
809
            $evidenceUrl .= $urlSuffix;
810
        }
811
        return $evidenceUrl;
812
    }
813
814
    /**
815
     * Update $this->apiURL
816
     */
817
    public function updateApiURL()
818
    {
819
        $this->apiURL = $this->getEvidenceURL();
820 3
        $id = $this->getRecordID();
821
        if(empty($id)){
822 3
            $id = $this->getRecordCode();
823
        }
824 3
        if (!empty($id)) {
825
            $this->apiURL .= '/'.self::urlEncode($id);
826
        }
827
        $this->apiURL .= '.'.$this->format;
828
    }
829
    /*   
830
     * Add Default Url params to given url if not overrided
831
     *
832 3
     * @param string $urlRaw
833 3
     *
834 3
     * @return string url with default params added
835
     */
836
837 3
    public function addDefaultUrlParams($urlRaw)
838
    {
839
        return \Ease\Shared::addUrlParams($urlRaw, $this->defaultUrlParams,
840 3
                false);
841
    }
842
843
    /**
844
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
845
     *
846
     * @param string $urlSuffix část URL za identifikátorem firmy.
847
     * @param string $method    HTTP/REST metoda
848
     * @param string $format    Requested format
849
     * 
850
     * @return array|boolean Výsledek operace
851
     */
852
    public function performRequest($urlSuffix = null, $method = 'GET',
853
                                   $format = null)
854
    {
855
        $this->rowCount      = null;
856
        $this->responseStats = [];
857
858
        if (preg_match('/^http/', $urlSuffix)) {
859
            $url = $urlSuffix;
860 3
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
861
            $url = $this->url.$urlSuffix;
862
        } else {
863
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
864
        }
865
866
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
867
            $method, $format);
868
869
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
870
                    $this->responseFormat), $responseCode);
871
    }
872
873
    /**
874
     * Parse Raw FlexiBee response in several formats
875
     *
876
     * @param string $responseRaw raw response body
877
     * @param string $format      Raw Response format json|xml|etc
878
     *
879
     * @return array
880
     */
881
    public function rawResponseToArray($responseRaw, $format)
882
    {
883
        $responseDecoded = [];
884
        if (!empty(trim($responseRaw))) {
885
            switch ($format) {
886
                case 'json':
887
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
888
                    break;
889
                case 'xml':
890 3
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
891
                    break;
892 3
                case 'txt':
893 3
                default:
894 3
                    $responseDecoded = [$this->lastCurlResponse];
895 3
                    break;
896
            }
897 3
        }
898
        return $responseDecoded;
899 3
    }
900
901 3
    /**
902
     * Convert FlexiBee Response JSON to Array
903 3
     *
904
     * @param string $rawJson
905 3
     *
906 3
     * @return array
907 3
     */
908 3
    public function rawJsonToArray($rawJson)
909 3
    {
910 3
        $responseDecoded = json_decode($rawJson, true, 10);
911 3
        $decodeError     = json_last_error_msg();
912 3
        if ($decodeError == 'No error') {
913 3
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
914 3
                $responseDecoded = $responseDecoded[$this->nameSpace];
915 3
            }
916 3
        } else {
917 3
            $this->addStatusMessage('JSON Decoder: '.$decodeError, 'error');
918
            $this->addStatusMessage($rawJson, 'debug');
919 3
        }
920
        return $responseDecoded;
921
    }
922 3
923 3
    /**
924 3
     * Convert FlexiBee Response XML to Array
925 3
     *
926 3
     * @param string $rawXML
927 3
     *
928 3
     * @return array
929 3
     */
930 3
    public function rawXmlToArray($rawXML)
931
    {
932
        return self::xml2array($rawXML);
933
    }
934
935 3
    /**
936
     * Parse Response array
937
     *
938
     * @param array $responseDecoded
939 3
     * @param int $responseCode Request Response Code
940
     *
941
     * @return array main data part of response
942
     */
943
    public function parseResponse($responseDecoded, $responseCode)
944
    {
945
        if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
946
            $mainResult          = $this->unifyResponseFormat($responseDecoded);
947
            $this->responseStats = array_key_exists('stats', $responseDecoded) ? (isset($responseDecoded['stats'][0])
948
                    ? $responseDecoded['stats'][0] : $responseDecoded['stats']) : null;
949 23
        } else {
950
            $mainResult = $responseDecoded;
951 23
        }
952 23
        switch ($responseCode) {
953 23
            case 201: //Success Write
954 23
            case 200: //Success Read
955 15
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
956 15
                    $this->lastResult = $mainResult;
957 15
                    if (isset($responseDecoded['@rowCount'])) {
958 23
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
959
                    }
960
                    if (isset($responseDecoded['@globalVersion'])) {
961
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
962
                    }
963
                }
964
                break;
965
966
            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...
967
                if ($this->debug === true) {
968 23
                    $this->error500Reporter($responseDecoded);
969
                }
970 23
            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...
971 23
                if ($this->ignoreNotFound === true) {
972 23
                    break;
973 23
                }
974 23
            case 400: //Bad Request parameters
975
            default: //Something goes wrong
976 23
                $this->addStatusMessage($this->lastResponseCode.': '.$this->curlInfo['url'],
977 23
                    'warning');
978 23
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
979 23
                    $this->parseError($responseDecoded);
980 23
                }
981
                $this->logResult($responseDecoded, $this->curlInfo['url']);
982 23
                break;
983 23
        }
984 23
        return $mainResult;
985
    }
986
987
    /**
988
     * Parse error message response
989
     *
990 1
     * @param array $responseDecoded
991
     * 
992 1
     * @return int number of errors processed
993 1
     */
994 1
    public function parseError(array $responseDecoded)
995 1
    {
996 1
        if (array_key_exists('results', $responseDecoded)) {
997
            $this->errors = $responseDecoded['results'][0]['errors'];
998
            foreach ($this->errors as $errorInfo) {
999
                $this->addStatusMessage($errorInfo['message'], 'error');
1000
                if (array_key_exists('for', $errorInfo)) {
1001 1
                    unset($errorInfo['message']);
1002
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1003 1
                }
1004 1
            }
1005
        } else {
1006
            if (array_key_exists('message', $responseDecoded)) {
1007
                $this->errors = [['message' => $responseDecoded['message']]];
1008
            }
1009
        }
1010
        return count($this->errors);
1011
    }
1012
1013 23
    /**
1014
     * Vykonej HTTP požadavek
1015 23
     *
1016 23
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1017 22
     * @param string $url    URL požadavku
1018
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1019
     * @param string $format požadovaný formát komunikace
1020
     * 
1021 22
     * @return int HTTP Response CODE
1022
     */
1023
    public function doCurlRequest($url, $method, $format = null)
1024
    {
1025
        if (is_null($format)) {
1026
            $format = $this->format;
1027
        }
1028
        curl_setopt($this->curl, CURLOPT_URL, $url);
1029
// Nastavení samotné operace
1030
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1031
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1032
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1033
1034
        $httpHeaders = $this->defaultHttpHeaders;
1035
1036
        $formats = Formats::bySuffix();
1037
1038
        if (!isset($httpHeaders['Accept'])) {
1039
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1040
        }
1041
        if (!isset($httpHeaders['Content-Type'])) {
1042
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1043
        }
1044
        $httpHeadersFinal = [];
1045
        foreach ($httpHeaders as $key => $value) {
1046
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1047
                $value .= ' v'.self::$libVersion;
1048
            }
1049
            $httpHeadersFinal[] = $key.': '.$value;
1050
        }
1051
1052
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1053
1054
// Proveď samotnou operaci
1055
        $this->lastCurlResponse            = curl_exec($this->curl);
1056
        $this->curlInfo                    = curl_getinfo($this->curl);
1057
        $this->curlInfo['when']            = microtime();
1058
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1059 15
        $this->responseFormat              = isset($this->curlInfo['content_type'])
1060
                ? Formats::contentTypeToSuffix($this->curlInfo['content_type']) : 'txt';
1061 15
        $this->lastResponseCode            = $this->curlInfo['http_code'];
1062 15
        $this->lastCurlError               = curl_error($this->curl);
1063
        if (strlen($this->lastCurlError)) {
1064 15
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1065 8
                    $this->lastResponseCode, $this->lastCurlError), 'error');
1066 7
        }
1067 7
1068 7
        if ($this->debug === true) {
1069
            $this->saveDebugFiles();
1070 8
        }
1071 1
1072 1
        return $this->lastResponseCode;
1073 8
    }
1074
1075 15
    /**
1076 4
     * Nastaví druh prováděné akce.
1077 4
     *
1078 4
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1079
     * @param string $action
1080
     * 
1081
     * @return boolean
1082
     */
1083 4
    public function setAction($action)
1084
    {
1085 15
        $result           = false;
1086
        $actionsAvailable = $this->getActionsInfo();
1087 15
        if (is_array($actionsAvailable) && array_key_exists($action,
1088 15
                $actionsAvailable)) {
1089
            $this->action = $action;
1090
            $result       = true;
1091 15
        }
1092
        return $result;
1093 15
    }
1094 15
1095 15
    /**
1096
     * Convert XML to array.
1097 15
     *
1098
     * @param string $xml
1099 15
     *
1100 15
     * @return array
1101 15
     */
1102 9
    public static function xml2array($xml)
1103 9
    {
1104 6
        $arr = [];
1105 6
        if (!empty($xml)) {
1106 9
            if (is_string($xml)) {
0 ignored issues
show
introduced by
The condition is_string($xml) is always true.
Loading history...
1107 6
                $xml = simplexml_load_string($xml);
1108
            }
1109
            foreach ($xml->attributes() as $a) {
1110 15
                $arr['@'.$a->getName()] = strval($a);
1111
            }
1112
            foreach ($xml->children() as $r) {
1113
                if (count($r->children()) == 0) {
1114
                    $arr[$r->getName()] = strval($r);
1115
                } else {
1116
                    $arr[$r->getName()][] = self::xml2array($r);
1117
                }
1118
            }
1119
        }
1120
        return $arr;
1121 23
    }
1122
1123 23
    /**
1124 23
     * Odpojení od FlexiBee.
1125 23
     */
1126 23
    public function disconnect()
1127 23
    {
1128
        if (is_resource($this->curl)) {
1129
            curl_close($this->curl);
1130
        }
1131 23
        $this->curl = null;
1132
    }
1133
1134
    /**
1135 23
     * Disconnect CURL befere pass away
1136 22
     */
1137 22
    public function __destruct()
1138 9
    {
1139 9
        $this->disconnect();
1140 22
    }
1141
1142
    /**
1143
     * Načte řádek dat z FlexiBee.
1144
     *
1145
     * @param int $recordID id požadovaného záznamu
1146
     *
1147
     * @return array
1148
     */
1149
    public function getFlexiRow($recordID)
1150
    {
1151 6
        $record   = null;
1152
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
1153
        if (isset($response[$this->evidence])) {
1154 6
            $record = $response[$this->evidence][0];
1155 6
        }
1156 6
1157 6
        return $record;
1158 6
    }
1159
1160 6
    /**
1161
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1162
     *
1163
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1164
     * @param array $conditions pole podmínek   - rendrují se do ()
1165 6
     * @param array $urlParams  pole parametrů  - rendrují za ?
1166
     */
1167
    public function extractUrlParams(&$conditions, &$urlParams)
1168
    {
1169 6
        foreach ($this->urlParams as $urlParam) {
1170
            if (isset($conditions[$urlParam])) {
1171
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
1172
            }
1173
        }
1174
    }
1175
1176
    /**
1177 16
     * convert unicode to entities for use with FlexiBee queries
1178
     *
1179 16
     * @param string $urlRaw
1180 9
     * 
1181 9
     * @return string
1182 16
     */
1183 16
    public static function urlEncode($urlRaw)
1184 16
    {
1185
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1186 16
    }
1187 16
1188 16
    /**
1189 15
     * Načte data z FlexiBee.
1190 15
     *
1191
     * @param string $suffix     dotaz
1192
     * @param string|array $conditions Volitelný filtrovací výraz
1193
     *
1194
     * @return array Data obtained
1195
     */
1196
    public function getFlexiData($suffix = null, $conditions = null)
1197
    {
1198
        $finalUrl  = '';
1199 15
        $urlParams = $this->defaultUrlParams;
1200
1201
        if (!empty($conditions)) {
1202 15
            if (is_array($conditions)) {
1203 10
                $this->extractUrlParams($conditions, $urlParams);
1204 10
                $conditions = $this->flexiUrl($conditions);
1205 15
            }
1206 15
1207 15
            if (strlen($conditions) && ($conditions[0] != '/')) {
1208 15
                $conditions = '('.self::urlEncode($conditions).')';
1209
            }
1210 14
        }
1211 14
1212 14
        if (strlen($suffix)) {
1213 14
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1214 10
                $finalUrl = $suffix;
1215
            } else {
1216 14
                if (preg_match('/^(code|ext):(.*)/', $suffix, $matches)) {
1217 14
                    $finalUrl = $matches[1].':'.rawurlencode($matches[2]);
1218
                }
1219
            }
1220
        }
1221
1222
        $finalUrl .= $conditions;
1223
1224
        if (count($urlParams)) {
1225
            if (strstr($finalUrl, '?')) {
1226
                $finalUrl .= '&';
1227
            } else {
1228
                $finalUrl .= '?';
1229
            }
1230
            $finalUrl .= http_build_query($urlParams, null, '&',
1231
                PHP_QUERY_RFC3986);
1232
        }
1233
1234
        $transactions = $this->performRequest($finalUrl, 'GET');
1235
1236
        $responseEvidence = $this->getResponseEvidence();
1237
        if (is_array($transactions) && array_key_exists($responseEvidence,
1238
                $transactions)) {
1239
            $result = $transactions[$responseEvidence];
1240
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
1241
                $result = null; // Response is empty Array
1242
            }
1243
        } else {
1244
            $result = $transactions;
1245
        }
1246
1247
        return $result;
1248
    }
1249
1250
    /**
1251
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1252 15
     * Read FlexiBee record and store it inside od object
1253
     *
1254
     * @param int $id ID or conditions
1255 15
     *
1256 15
     * @return int počet načtených položek
1257 15
     */
1258
    public function loadFromFlexiBee($id = null)
1259 15
    {
1260 15
        $data = [];
1261 15
        if (is_null($id)) {
1262 15
            $id = $this->getMyKey();
1263 15
        }
1264 15
        if (is_array($id)) {
0 ignored issues
show
introduced by
The condition is_array($id) is always false.
Loading history...
1265 15
            $id = rawurlencode('('.self::flexiUrl($id).')');
1266 15
        } else if (preg_match('/^ext:/', $id)) {
1267
            $id = self::urlEncode($id);
1268 15
        } else if (preg_match('/^code:/', $id)) {
1269
            $id = self::code(self::urlEncode(self::uncode($id)));
1270
        }
1271 15
1272
        $flexidata    = $this->getFlexiData($this->getEvidenceUrl().'/'.$id);
1273
        $this->apiURL = $this->curlInfo['url'];
1274 15
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1275 15
            $data = current($flexidata);
1276 15
        }
1277 15
        return $this->takeData($data);
1278 15
    }
1279
1280 15
    /**
1281
     * Set Filter code for requests
1282 15
     *
1283
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1284 15
     *
1285 9
     * @param array|string $filter filter formula or ['key'=>'value']
1286 9
     *
1287
     * @return string Filter code
1288 15
     */
1289
    public function setFilter($filter)
1290
    {
1291
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1292
    }
1293
1294
    /**
1295
     * Převede data do Json formátu pro FlexiBee.
1296
     * Convert data to FlexiBee like Json format
1297
     *
1298
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1299 23
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1300
     *
1301 23
     * @param array $data    object data
1302
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1303 23
     *
1304 23
     * @return string
1305 23
     */
1306
    public function getJsonizedData($data = null, $options = 0)
1307 23
    {
1308 23
        if (is_null($data)) {
1309 23
            $data = $this->getData();
1310
        }
1311 23
1312 23
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1313 23
            $this->getDataForJSON($data));
1314 23
        $jsonRaw       = json_encode([$this->nameSpace => $dataToJsonize],
1315 23
            $options);
1316 23
1317 23
        return $jsonRaw;
1318 23
    }
1319 23
1320 23
    /**
1321
     * Get Data Fragment specific for current object
1322
     *
1323
     * @param array $data
1324 23
     *
1325 23
     * @return array
1326 23
     */
1327
    public function getDataForJSON($data = null)
1328 23
    {
1329 23
        if (is_null($data)) {
1330 23
            $data = $this->getData();
1331 23
        }
1332
1333
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1334 23
1335 23
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1336 23
            $dataForJson[$this->evidence.'@action'] = $this->action;
1337 23
            $this->action                           = null;
1338 23
        }
1339 23
1340 23
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1341 23
            $dataForJson[$this->evidence.'@filter'] = $this->filter;
1342 23
        }
1343 23
1344 23
1345 23
        foreach ($this->chained as $chained) {
1346
            $chainedData = $chained->getDataForJSON();
1347 23
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1348 23
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1349
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1350 23
                        $dataBackup                          = $dataForJson[$chainedItemEvidence];
1351
                        $dataForJson[$chainedItemEvidence]   = [];
1352
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1353
                    }
1354
                    if (array_key_exists(0, $chainedItemData)) {
1355
                        foreach ($chainedItemData as $chainedItem) {
1356
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1357
                        }
1358
                    } else {
1359
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1360 23
                    }
1361
                } else {
1362 23
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1363 23
                }
1364 23
            }
1365
        }
1366
1367 23
1368 23
        return $dataForJson;
1369 23
    }
1370 23
1371 23
    /**
1372
     * Join another FlexiPeeHP Object
1373
     *
1374 23
     * @param FlexiBeeRO $object
1375 23
     *
1376 23
     * @return boolean adding to stack success
1377
     */
1378 23
    public function join(&$object)
1379 23
    {
1380 23
        $result = true;
1381 23
        if (method_exists($object, 'getDataForJSON')) {
1382 23
            $this->chained[] = $object;
1383
        } else {
1384 23
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1385 23
        }
1386 23
1387 23
        return $result;
1388 23
    }
1389
1390 23
    /**
1391 23
     * Test if given record ID exists in FlexiBee.
1392 23
     *
1393 23
     * @param mixed $identifer presence state
1394
     *
1395
     * @return boolean
1396 23
     */
1397
    public function idExists($identifer = null)
1398
    {
1399 23
        if (is_null($identifer)) {
1400
            $identifer = $this->getMyKey();
1401
        }
1402 23
        $ignorestate = $this->ignore404();
1403 23
        $this->ignore404(true);
1404 23
        $this->getFlexiData(null,
1405 23
            [
1406 23
                'detail' => 'custom:'.$this->getKeyColumn(),
1407 23
                $this->getKeyColumn() => $identifer
1408
        ]);
1409
        $this->ignore404($ignorestate);
1410
        return $this->lastResponseCode == 200;
1411
    }
1412
1413
    /**
1414
     * Test if given record exists in FlexiBee.
1415
     *
1416
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1417
     * 
1418
     * @return boolean Record presence status
1419
     */
1420
    public function recordExists($data = [])
1421
    {
1422
1423
        if (empty($data)) {
1424
            $data = $this->getData();
1425
        }
1426
        $ignorestate = $this->ignore404();
1427
        $this->ignore404(true);
1428
        $keyColumn   = $this->getKeyColumn();
1429
        $res         = $this->getColumnsFromFlexibee([$keyColumn],
1430
            is_array($data) ? $data : [$keyColumn => $data]);
1431
1432
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false'))
1433
            || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1434
            $found = false;
1435
        } else {
1436
            $found = true;
1437
        }
1438
        $this->ignore404($ignorestate);
1439
        return $found;
1440
    }
1441
1442
    /**
1443
     * Subitems - ex. items of invoice
1444 23
     * 
1445
     * @return array of document items or null
1446 23
     */
1447
    public function getSubItems()
1448 23
    {
1449 23
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury')
1450 23
                : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu'): null);
1451 23
    }
1452 23
1453 23
    /**
1454 23
     * Vrací z FlexiBee sloupečky podle podmínek.
1455 23
     *
1456 23
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1457
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1458 23
     *                                     sloupečku
1459 23
     * @return array
1460 23
     */
1461 23
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1462 23
    {
1463
        if (is_int($conditions)) {
1464
            $conditions = [$this->getmyKeyColumn() => $conditions];
0 ignored issues
show
Bug introduced by
The method getmyKeyColumn() does not exist on FlexiPeeHP\FlexiBeeRO. Did you maybe mean getKeyColumn()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1464
            $conditions = [$this->/** @scrutinizer ignore-call */ getmyKeyColumn() => $conditions];

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
1465 23
        }
1466 23
1467
        $flexiData = $this->getFlexiData('', $conditions);
1468
1469 23
        if (!is_null($indexBy)) {
1470
            $flexiData = $this->reindexArrayBy($flexiData);
1471 23
        }
1472 23
1473
        return $flexiData;
1474 23
    }
1475
1476
    /**
1477 23
     * Vrací z FlexiBee sloupečky podle podmínek.
1478 23
     *
1479
     * @param string[] $columnsList seznam položek
1480
     * @param array    $conditions  pole podmínek nebo ID záznamu
1481
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1482
     *
1483
     * @return array
1484
     */
1485
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1486
                                           $indexBy = null)
1487
    {
1488
        $detail = 'full';
1489 65
        switch (gettype($columnsList)) {
1490
            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...
1491 65
                $conditions = [$this->getmyKeyColumn() => $conditions];
1492 65
            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...
1493
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1494
                        $columnsList)) {
1495 65
                    $columnsList[] = $indexBy;
1496 65
                }
1497
                $columns = implode(',', array_unique($columnsList));
1498
                $detail  = 'custom:'.$columns;
1499
            default:
1500
                switch ($columnsList) {
1501 65
                    case 'id':
1502
                        $detail = 'id';
1503
                        break;
1504
                    case 'summary':
1505
                        $detail = 'summary';
1506
                        break;
1507
                    default:
1508
                        break;
1509
                }
1510
                break;
1511 71
        }
1512
1513 71
        $conditions['detail'] = $detail;
1514
1515
        $flexiData = $this->getFlexiData(null, $conditions);
1516
1517
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1518
                $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1519
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1520
        }
1521
1522 23
        return $flexiData;
1523
    }
1524 23
1525
    /**
1526
     * Vrací kód záznamu.
1527
     * Obtain record CODE
1528
     *
1529
     * @param mixed $data
1530
     *
1531
     * @return string
1532 15
     */
1533
    public function getKod($data = null, $unique = true)
1534 15
    {
1535 15
        $kod = null;
1536 15
1537 15
        if (is_null($data)) {
1538 15
            $data = $this->getData();
1539 9
        }
1540 9
1541 15
        if (is_string($data)) {
1542
            $data = [$this->nameColumn => $data];
1543
        }
1544
1545
        if (isset($data['kod'])) {
1546
            $kod = $data['kod'];
1547
        } else {
1548
            if (isset($data[$this->nameColumn])) {
1549
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1550 23
                    \Ease\Sand::rip($data[$this->nameColumn]));
1551
            } else {
1552 23
                if (isset($data[$this->keyColumn])) {
1553 23
                    $kod = \Ease\Sand::rip($data[$this->keyColumn]);
1554 23
                }
1555 23
            }
1556 23
            $kod = substr($kod, 0, 20);
1557 23
        }
1558 23
1559 23
        if (!strlen($kod)) {
1560 23
            $kod = 'NOTSET';
1561 23
        }
1562 23
1563 23
        if (strlen($kod) > 18) {
1564 23
            $kodfinal = strtoupper(substr($kod, 0, 18));
1565 23
        } else {
1566
            $kodfinal = strtoupper($kod);
1567 23
        }
1568
1569
        if ($unique) {
1570
            $counter = 0;
1571
            if (!empty($this->codes) && count($this->codes)) {
1572
                foreach ($this->codes as $codesearch => $keystring) {
1573
                    if (strstr($codesearch, $kodfinal)) {
1574
                        ++$counter;
1575
                    }
1576
                }
1577 22
            }
1578
            if ($counter) {
1579 22
                $kodfinal = $kodfinal.$counter;
1580
            }
1581 21
1582
            $this->codes[$kodfinal] = $kod;
1583
        }
1584
1585
        return self::code($kodfinal);
1586
    }
1587
1588
    /**
1589 22
     * Write Operation Result.
1590
     *
1591 22
     * @param array  $resultData
1592 22
     * @param string $url        URL
1593 22
     * 
1594
     * @return boolean Log save success
1595
     */
1596 22
    public function logResult($resultData = null, $url = null)
1597
    {
1598
        $logResult = false;
1599
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1600
            if (isset($resultData['message'])) {
1601
                $this->addStatusMessage($resultData['message'], 'warning');
1602
            }
1603
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1604
                'warning');
1605 22
            unset($url);
1606
        }
1607 22
        if (is_null($resultData)) {
1608 22
            $resultData = $this->lastResult;
1609 22
        }
1610 22
        if (isset($url)) {
1611 22
            $this->logger->addStatusMessage($this->lastResponseCode.':'.urldecode($url));
1612 22
        }
1613 22
1614 22
        if (isset($resultData['results'])) {
1615 22
            if ($resultData['success'] == 'false') {
1616 22
                $status = 'error';
1617 22
            } else {
1618 22
                $status = 'success';
1619
            }
1620 22
            foreach ($resultData['results'] as $result) {
1621
                if (isset($result['request-id'])) {
1622
                    $rid = $result['request-id'];
1623
                } else {
1624
                    $rid = '';
1625
                }
1626
                if (isset($result['errors'])) {
1627
                    foreach ($result['errors'] as $error) {
1628
                        $message = $error['message'];
1629
                        if (isset($error['for'])) {
1630
                            $message .= ' for: '.$error['for'];
1631
                        }
1632 22
                        if (isset($error['value'])) {
1633
                            $message .= ' value:'.$error['value'];
1634
                        }
1635
                        if (isset($error['code'])) {
1636
                            $message .= ' code:'.$error['code'];
1637
                        }
1638
                        $this->addStatusMessage($rid.': '.$message, $status);
1639
                    }
1640
                }
1641 23
            }
1642
        }
1643 23
        return $logResult;
1644 23
    }
1645 23
1646 23
    /**
1647 16
     * Save RAW Curl Request & Response to files in Temp directory
1648 16
     */
1649 23
    public function saveDebugFiles()
1650
    {
1651
        $tmpdir   = sys_get_temp_dir();
1652
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1653
        $reqname  = $tmpdir.'/request-'.$fname;
1654
        $respname = $tmpdir.'/response-'.$fname;
1655
        file_put_contents($reqname, $this->postFields);
1656
        file_put_contents($respname, $this->lastCurlResponse);
1657
    }
1658 23
1659
    /**
1660 23
     * Připraví data pro odeslání do FlexiBee
1661 23
     *
1662 23
     * @param string $data
1663 23
     */
1664 23
    public function setPostFields($data)
1665 23
    {
1666 23
        $this->postFields = $data;
1667 23
    }
1668 23
1669
    /**
1670
     * Get Content ready to be send as POST body
1671
     * @return string
1672
     */
1673
    public function getPostFields()
1674
    {
1675
        return $this->postFields;
1676
    }
1677 23
1678
    /**
1679 23
     * Generuje fragment url pro filtrování.
1680 23
     *
1681 23
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1682 23
     *
1683 23
     * @param array  $data   key=>values; value can bee class DatePeriod
1684 23
     * @param string $joiner default and/or
1685 13
     * @param string $defop  default operator
1686 13
     *
1687 23
     * @return string
1688
     */
1689
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1690
    {
1691
        $parts = [];
1692
1693
        foreach ($data as $column => $value) {
1694
            if (!is_numeric($column)) {
1695
                if (is_integer($data[$column]) || is_float($data[$column])) {
1696 23
                    $parts[$column] = $column.' eq \''.$data[$column].'\'';
1697
                } elseif (is_bool($data[$column])) {
1698 23
                    $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1699 23
                } elseif (is_null($data[$column])) {
1700 23
                    $parts[$column] = $column." is null";
1701 23
                } elseif (is_object($data[$column])) {
1702 23
                    switch (get_class($data[$column])) {
1703 16
                        case 'DatePeriod':
1704 16
                            $parts[$column] = $column . " between '".$data[$column]->getStartDate()->format(self::$DateFormat)."' '".$data[$column]->getEndDate()->format(self::$DateFormat)."'";
1705 23
                            break;
1706
                        default:
1707
                            $parts[$column] = $column ." $defop '". $data[$column]."'";
1708
                            break;
1709
                    }
1710
                } else {
1711
                    switch ($value) {
1712
                        case '!null':
1713
                            $parts[$column] = $column." is not null";
1714 23
                            break;
1715
                        case 'is empty':
1716 23
                        case 'is not empty':
1717 23
                            $parts[$column] = $column.' '.$value;
1718 23
                            break;
1719 23
                        default:
1720 23
                            switch (explode(' ', trim($value))[0]) {
1721 16
                                case 'like':
1722 16
                                case 'begins':
1723 23
                                case 'ends':
1724
                                    $parts[$column] = $column         .= ' '.$value;
1725
                                    break;
1726
                                default:
1727
                            if ($column == 'stitky') {
1728
                                $parts[$column] = $column."='".self::code($data[$column])."'";
1729
                            } else {
1730
                                $parts[$column] = $column." $defop '".$data[$column]."'";
1731 23
                            }
1732
                            break;
1733 23
                    }
1734 1
1735 1
                            break;
1736 23
                }
1737 23
                }
1738
            } else {
1739
                $parts[] = $value;
1740
            }
1741
        }
1742
        return implode(' '.$joiner.' ', $parts);
1743
    }
1744 20
1745
    /**
1746 20
     * Obtain record/object numeric identificator id:
1747 20
     * Vrací číselný identifikátor objektu id:
1748 20
     *
1749 20
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1750
     *
1751
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1752
     */
1753
    public function getRecordID()
1754
    {
1755 20
        $id = $this->getDataValue('id');
1756
        return is_null($id) ? null : is_numeric($id) ? intval($id) : $id;
1757
    }
1758
1759
    /**
1760
     * Obtain record/object identificator code:
1761
     * Vrací identifikátor objektu code:
1762
     *
1763
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1764
     *
1765
     * @return string record code identifier
1766
     */
1767
    public function getRecordCode()
1768
    {
1769
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1770
    }
1771
1772
    /**
1773
     * Obtain record/object identificator extId: code: or id:
1774
     * Vrací identifikátor objektu extId: code: nebo id:
1775
     *
1776
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1777
     *
1778
     * @return string|int|null record code identifier
1779
     */
1780
    public function getRecordIdent()
1781
    {
1782
        $ident = $this->getExternalID();
1783
        if (empty($ident)) {
1784
            $ident = $this->getRecordCode();
1785
        }
1786
        if (empty($ident)) {
1787
            $ident = $this->getRecordID();
1788
        }
1789
        return $ident;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ident also could return the type array which is incompatible with the documented return type null|integer|string.
Loading history...
1790
    }
1791
1792
    /**
1793
     * Obtain record/object identificator code: or id:
1794
     * Vrací identifikátor objektu code: nebo id:
1795
     *
1796
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1797
     * 
1798
     * @return string indentifikátor záznamu reprezentovaného objektem
1799
     */
1800
    public function __toString()
1801
    {
1802
        return strval($this->getRecordIdent());
1803
    }
1804
1805
    /**
1806
     * Gives you FlexiPeeHP class name for Given Evidence
1807
     *
1808
     * @param string $evidence
1809
     * 
1810
     * @return string Class name
1811
     */
1812
    public static function evidenceToClassName($evidence)
1813
    {
1814
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1815
    }
1816
1817
    /**
1818
     * Obtain ID of first record in evidence
1819
     *
1820
     * @return string|null id or null if no records
1821
     */
1822
    public function getFirstRecordID()
1823
    {
1824
        $firstID    = null;
1825
        $keyColumn  = $this->getKeyColumn();
1826
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1827
            ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1828
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1829
            $firstID = current($firstIdRaw)[$keyColumn];
1830
        }
1831
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1832
    }
1833
1834
    /**
1835
     * Vrací hodnotu daného externího ID
1836
     *
1837
     * @param string $want Namespace Selector. If empty,you obtain the first one.
1838
     * 
1839
     * @return string|array one id or array if multiplete
1840
     */
1841
    public function getExternalID($want = null)
1842
    {
1843
        $extid = null;
1844
        $ids   = $this->getDataValue('external-ids');
1845 23
        if (is_null($want)) {
1846
            if (!empty($ids)) {
1847 23
                $extid = current($ids);
1848
            }
1849
        } else {
1850
            if (!is_null($ids) && is_array($ids)) {
1851
                foreach ($ids as $id) {
1852
                    if (strstr($id, 'ext:'.$want)) {
1853
                        if (is_null($extid)) {
1854
                            $extid = str_replace('ext:'.$want.':', '', $id);
1855
                        } else {
1856
                            if (is_array($extid)) {
1857 23
                                $extid[] = str_replace('ext:'.$want.':', '', $id);
1858
                            } else {
1859 23
                                $extid = [$extid, str_replace('ext:'.$want.':',
1860
                                        '', $id)];
1861
                            }
1862
                        }
1863
                    }
1864
                }
1865
            }
1866
        }
1867
        return $extid;
1868
    }
1869
1870
    /**
1871
     * Obtain actual GlobalVersion
1872
     * Vrací aktuální globální verzi změn
1873
     *
1874
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1875
     * 
1876
     * @return type
0 ignored issues
show
Bug introduced by
The type FlexiPeeHP\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1877
     */
1878
    public function getGlobalVersion()
1879
    {
1880
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
1881
1882
        return $this->globalVersion;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->globalVersion returns the type integer which is incompatible with the documented return type FlexiPeeHP\type.
Loading history...
1883
    }
1884
1885
    /**
1886
     * Gives you current ApiURL with given format suffix
1887
     * 
1888
     * @param string $format json|html|xml|...
1889
     * 
1890
     * @return string API URL for current record or object/evidence
1891
     */
1892
    public function getApiURL($format = null)
1893
    {
1894
        $apiUrl = str_replace(['.'.$this->format, '?limit=0'], '', $this->apiURL);
1895
        return $apiUrl.(empty($format) ? '' : '.'.$format );
1896
    }
1897
1898
    /**
1899
     * Obtain content type of last response
1900
     *
1901
     * @return string
1902
     */
1903
    public function getResponseFormat()
1904
    {
1905
        if (isset($this->curlInfo['content_type'])) {
1906
            $responseFormat = $this->curlInfo['content_type'];
1907
        } else {
1908
            $responseFormat = null;
1909
        }
1910
        return $responseFormat;
1911
    }
1912
1913
    /**
1914
     * Return the same response format for one and multiplete results
1915
     *
1916
     * @param array $responseBody
1917
     * 
1918
     * @return array
1919
     */
1920
    public function unifyResponseFormat($responseBody)
1921
    {
1922
        if (!is_array($responseBody) || array_key_exists('message',
0 ignored issues
show
introduced by
The condition is_array($responseBody) is always true.
Loading history...
1923
                $responseBody)) { //Unifi response format
1924
            $response = $responseBody;
1925
        } else {
1926
            $evidence = $this->getResponseEvidence();
1927
            if (array_key_exists($evidence, $responseBody)) {
1928
                $response        = [];
1929
                $evidenceContent = $responseBody[$evidence];
1930
                if (array_key_exists(0, $evidenceContent)) {
1931
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1932
                } else {
1933
                    $response[$evidence][0] = $evidenceContent; //One result
1934
                }
1935
            } else {
1936
                if (isset($responseBody['priloha'])) {
1937
                    $response = $responseBody['priloha'];
1938
                } else {
1939
                    if (array_key_exists('results', $responseBody)) {
1940
                        $response = $responseBody['results'];
1941
                    } else {
1942
                        $response = $responseBody;
1943
                    }
1944
                }
1945
            }
1946
        }
1947
        return $response;
1948
    }
1949
1950
    /**
1951
     * Obtain structure for current (or given) evidence
1952
     *
1953
     * @param string $evidence
1954
     * 
1955
     * @return array Evidence structure
1956
     */
1957
    public function getColumnsInfo($evidence = null)
1958
    {
1959
        $columnsInfo = null;
1960
        $infoSource  = self::$infoDir.'/Properties.'.(empty($evidence) ? $this->getEvidence()
1961
                : $evidence).'.json';
1962
        if (file_exists($infoSource)) {
1963
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
1964
        }
1965
        return $columnsInfo;
1966
    }
1967
1968
    /**
1969
     * Gives you properties for (current) evidence column
1970
     *
1971
     * @param string $column    name of column
1972
     * @param string $evidence  evidence name if different
1973
     *
1974
     * @return array column properties or null if column not exits
1975
     */
1976
    public function getColumnInfo($column, $evidence = null)
1977
    {
1978
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence()
1979
                : $evidence);
1980
        return is_array($columnsInfo) ? array_key_exists($column, $columnsInfo) ? $columnsInfo[$column]
0 ignored issues
show
introduced by
The condition is_array($columnsInfo) is always true.
Loading history...
1981
                : null : null;
1982
    }
1983
1984
    /**
1985
     * Obtain actions for current (or given) evidence
1986
     *
1987
     * @param string $evidence
1988
     * 
1989
     * @return array Evidence structure
1990
     */
1991
    public function getActionsInfo($evidence = null)
1992
    {
1993
        $actionsInfo = null;
1994
        if (is_null($evidence)) {
1995
            $evidence = $this->getEvidence();
1996
        }
1997
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1998
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1999
            $actionsInfo = Actions::$$propsName;
2000
        }
2001
        return $actionsInfo;
2002
    }
2003
2004
    /**
2005
     * Obtain relations for current (or given) evidence
2006
     *
2007
     * @param string $evidence
2008
     * 
2009
     * @return array Evidence structure
2010
     */
2011
    public function getRelationsInfo($evidence = null)
2012
    {
2013
        $relationsInfo = null;
2014
        if (is_null($evidence)) {
2015
            $evidence = $this->getEvidence();
2016
        }
2017
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2018
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2019
            $relationsInfo = Relations::$$propsName;
2020
        }
2021
        return $relationsInfo;
2022
    }
2023
2024
    /**
2025
     * Obtain info for current (or given) evidence
2026
     *
2027
     * @param string $evidence
2028
     * 
2029
     * @return array Evidence info
2030
     */
2031
    public function getEvidenceInfo($evidence = null)
2032
    {
2033
        $evidencesInfo = null;
2034
        if (is_null($evidence)) {
2035 23
            $evidence = $this->getEvidence();
2036
        }
2037 23
        if (isset(EvidenceList::$evidences[$evidence])) {
2038 23
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2039 23
            $propsName     = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2040 23
            if (isset(Formats::$$propsName)) {
2041
                $evidencesInfo['formats'] = Formats::$$propsName;
2042
            }
2043
        }
2044
        return $evidencesInfo;
2045
    }
2046
2047
    /**
2048
     * Obtain name for current (or given) evidence path
2049
     *
2050
     * @param string $evidence Evidence Path
2051
     * 
2052
     * @return array Evidence info
2053
     */
2054
    public function getEvidenceName($evidence = null)
2055
    {
2056
        $evidenceName = null;
2057
        if (is_null($evidence)) {
2058
            $evidence = $this->getEvidence();
2059
        }
2060
        if (isset(EvidenceList::$name[$evidence])) {
2061
            $evidenceName = EvidenceList::$name[$evidence];
2062
        }
2063
        return $evidenceName;
2064
    }
2065
2066
    /**
2067
     * Save current object to file
2068
     *
2069
     * @param string $destfile path to file
2070
     */
2071
    public function saveResponseToFile($destfile)
2072
    {
2073
        if (strlen($this->lastCurlResponse)) {
2074
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2075
        }
2076
        file_put_contents($destfile, $this->lastCurlResponse);
2077
    }
2078
2079
    /**
2080
     * Obtain established relations listing
2081
     *
2082
     * @return array Null or Relations
2083
     */
2084
    public function getVazby($id = null)
2085
    {
2086
        if (is_null($id)) {
2087
            $id = $this->getRecordID();
2088
        }
2089
        if (!empty($id)) {
2090
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2091
                ['relations' => 'vazby', 'id' => $id]);
2092
            $vazby    = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby']
2093
                    : null;
2094
        } else {
2095
            throw new \Exception(_('ID requied to get record relations '));
2096
        }
2097
        return $vazby;
2098
    }
2099
2100
    /**
2101
     * Gives You URL for Current Record in FlexiBee web interface
2102
     *
2103
     * @return string url
2104
     */
2105
    public function getFlexiBeeURL()
2106
    {
2107
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
2108
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
2109
                : '';
2110
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2111
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
2112
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2113
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
2114
        $pass       = ($user || $pass) ? "$pass@" : '';
2115
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2116
        return $scheme.$user.$pass.$host.$port.$path;
2117
    }
2118
2119
    /**
2120
     * Set Record Key
2121
     *
2122
     * @param int|string $myKeyValue
2123
     * 
2124
     * @return boolean
2125
     */
2126
    public function setMyKey($myKeyValue)
2127
    {
2128
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2129
            $extIds = $this->getDataValue('external-ids');
2130
            if (!empty($extIds) && count($extIds)) {
2131
                $extIds = array_combine($extIds, $extIds);
2132
            }
2133
            $extIds[$myKeyValue] = $myKeyValue;
2134
            $res                 = $this->setDataValue('external-ids', $extIds);
2135
        } else {
2136
            $res = parent::setMyKey($myKeyValue);
2137
        }
2138
        $this->updateApiURL();
2139
        return $res;
2140
    }
2141
2142
    /**
2143
     * Set or get ignore not found pages flag
2144
     *
2145
     * @param boolean $ignore set flag to
2146
     *
2147
     * @return boolean get flag state
2148
     */
2149
    public function ignore404($ignore = null)
2150
    {
2151
        if (!is_null($ignore)) {
2152
            $this->ignoreNotFound = $ignore;
2153
        }
2154
        return $this->ignoreNotFound;
2155
    }
2156
2157
    /**
2158
     * Send Document by mail
2159
     *
2160
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2161
     *
2162
     * @param string $to         Email ecipient
2163
     * @param string $subject    Email Subject
2164
     * @param string $body       Email Text
2165
     *
2166
     * @return int http response code
2167
     */
2168
    public function sendByMail($to, $subject, $body, $cc = null)
2169
    {
2170
        $this->setPostFields($body);
2171
2172
        $this->performRequest(rawurlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
2173
            , 'PUT', 'xml');
2174
2175
        return $this->lastResponseCode == 200;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->lastResponseCode == 200 returns the type boolean which is incompatible with the documented return type integer.
Loading history...
2176
    }
2177
2178
    /**
2179
     * Send all unsent Documents by eMail
2180
     *
2181
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2182
     * 
2183
     * @return int http response code
2184
     */
2185
    public function sendUnsent()
2186
    {
2187
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
2188
                'xml');
2189
    }
2190
2191
    /**
2192
     * FlexiBee date to PHP DateTime conversion
2193
     *
2194
     * @param string $flexidate 2017-05-26+02:00
2195
     *
2196
     * @return \DateTime | false
2197
     */
2198
    public static function flexiDateToDateTime($flexidate)
2199
    {
2200
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat.'O'
2201
                    : self::$DateFormat, $flexidate)->setTime(0, 0);
2202
    }
2203
2204
    /**
2205
     * FlexiBee dateTime to PHP DateTime conversion
2206
     *
2207
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2208
     *
2209
     * @return \DateTime | false
2210
     */
2211
    public static function flexiDateTimeToDateTime($flexidatetime)
2212
    {
2213
        if (strchr($flexidatetime, '.')) { //NewFormat
2214
            $format = self::$DateTimeFormat;
2215
        } else { // Old format
2216
            $format = 'Y-m-d\TH:i:s+P';
2217
        }
2218
        return \DateTime::createFromFormat($format, $flexidatetime);
2219
    }
2220
2221
    /**
2222
     * Získá dokument v daném formátu
2223
     * Obtain document in given format
2224
     *
2225
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2226
     *
2227
     * @param string  $format     pdf/csv/xml/json/ ...
2228
     * @param string  $reportName Template used to generate PDF
2229
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2230
     * @param boolean $sign       sign resulting PDF by certificate ?
2231
     *
2232
     * @return string|null filename downloaded or none
2233
     */
2234
    public function getInFormat($format, $reportName = null, $lang = null,$sign = false)
2235
    {
2236
        $response = null;
2237
        if ($this->setFormat($format)) {
2238
            $urlParams = [];
2239
            switch ($format) {
2240
                case 'pdf':
2241
                    switch ($lang) {
2242
                        case 'cs':
2243
                        case 'sk':
2244
                        case 'en':
2245
                        case 'de':
2246
                            $urlParams['report-lang'] = $lang;
2247
                            break;
2248
                        case null:
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $lang of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2249
                            break;
2250
                        default:
2251
                            throw new \Ease\Exception('Unknown language '.$lang.' for PDF export');
2252
                            break;
2253
                    }
2254
                    if(boolval($sign) === true){
2255
                        $urlParams['report-sign'] = 'true';
2256
                    }
2257
                    break;
2258
                case 'html':
2259
                    $urlParams['inDesktopApp'] = 'true';
2260
                    break;
2261
            }
2262
            if (!empty($reportName)) {
2263
                $urlParams['report-name'] = $reportName;
2264
            }
2265
            if (($this->doCurlRequest(\Ease\Shared::addUrlParams($this->apiURL,
2266
                        $urlParams), 'GET') == 200)) {
2267
                $response = $this->lastCurlResponse;
2268
            }
2269
        }
2270
        return $response;
2271
    }
2272
2273
    /**
2274
     * Uloží dokument v daném formátu do složky v systému souborů
2275
     * Save document in given format to directory in filesystem
2276
     *
2277
     * @param string $format  pdf/csv/xml/json/ ...
2278
     * @param string $destDir where to put file (prefix)
2279
     * @param string $reportName Template used to generate PDF
2280
     *
2281
     * @return string|null filename downloaded or none
2282
     */
2283
    public function downloadInFormat($format, $destDir = './',
2284
                                     $reportName = null)
2285
    {
2286
        $fileOnDisk   = null;
2287
        $formatBackup = $this->format;
2288
        if ($this->setFormat($format)) {
2289
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
2290
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Shared::addUrlParams($this->apiURL,
2291
                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2292
                    $this->lastCurlResponse) !== false)) {
2293
                $fileOnDisk = $downloadTo;
2294
            }
2295
            $this->setFormat($formatBackup);
2296
        }
2297
        return $fileOnDisk;
2298
    }
2299
2300
    
2301
    /**
2302
     * Take data for object
2303
     *
2304
     * @param array $data Data to keep
2305
     * 
2306
     * @return int number of records taken
2307
     */
2308
    public function takeData($data)
2309
    {
2310
        $result = parent::takeData($data);
2311
        if(array_key_exists($this->getKeyColumn(), $data) || array_key_exists('kod', $data)){
2312
            $this->updateApiURL();
2313
        }
2314
        return $result;
2315
    }    
2316
    
2317
    /**
2318
     * Get Current Evidence reports listing
2319
     * 
2320
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2321
     * 
2322
     * @return array
2323
     */
2324
    public function getReportsInfo()
2325
    {
2326
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL().'/reports');
2327
        return (array_key_exists('reports', $reportsRaw) && array_key_exists('report',
2328
                $reportsRaw['reports']) ) ? self::reindexArrayBy($reportsRaw['reports']['report'],
2329
                'reportId') : [];
2330
    }
2331
2332
    /**
2333
     * Compile and send Report about Error500 to FlexiBee developers
2334
     * If FlexiBee is running on localost try also include java backtrace
2335
     *
2336
     * @param array $errorResponse result of parseError();
2337
     */
2338
    public function error500Reporter($errorResponse)
2339
    {
2340
        $ur = str_replace('/c/'.$this->company, '',
2341
            str_replace($this->url, '', $this->curlInfo['url']));
2342
        if (!array_key_exists($ur, $this->reports)) {
2343
            $tmpdir   = sys_get_temp_dir();
2344
            $myTime   = $this->curlInfo['when'];
2345
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
2346
            file_put_contents($curlname,
2347
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2348
2349
            $report = new \Ease\Mailer($this->reportRecipient,
2350
                'Error report 500 - '.$ur);
2351
2352
            $d     = dir($tmpdir);
2353
            while (false !== ($entry = $d->read())) {
2354
                if (strstr($entry, $myTime)) {
2355
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
2356
                    $mime = Formats::suffixToContentType($ext);
2357
                    $report->addFile($tmpdir.'/'.$entry,
2358
                        empty($mime) ? 'text/plain' : $mime);
2359
                }
2360
            }
2361
            $d->close();
2362
2363
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2364
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
2365
2366
                $fl = fopen('/var/log/'.'flexibee.log', 'r');
2367
                if ($fl) {
0 ignored issues
show
introduced by
$fl is of type resource|false, thus it always evaluated to false.
Loading history...
2368
                    $tracelog = [];
2369
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2370
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
2371
                        $char = fgetc($fl);
2372
                        if ($char === "\n") {
2373
                            $tracelog[] = $output[$ln];
2374
                            if (strstr($output[$ln], $errorResponse['message'])) {
2375
                                break;
2376
                            }
2377
                            $ln++;
2378
                            continue;
2379
                        }
2380
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
2381
                                : '');
2382
                    }
2383
2384
                    $trace     = implode("\n", array_reverse($tracelog));
2385
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
2386
                    file_put_contents($tracefile, $trace);
2387
                    $report->addItem("\n\n".$trace);
2388
                    fclose($fl);
2389
                }
2390
            } else {
2391
                $report->addItem($errorResponse['message']);
2392
            }
2393
2394
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
2395
2396
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
2397
                    JSON_PRETTY_PRINT));
2398
2399
            if ($report->send()) {
2400
                $this->reports[$ur] = $myTime;
2401
            }
2402
        }
2403
    }
2404
2405
    /**
2406
     * Returns code:CODE
2407
     *
2408
     * @param string $code
2409
     *
2410
     * @return string
2411
     */
2412
    public static function code($code)
2413
    {
2414
        return ((substr($code,0,4) == 'ext:') ? $code :  'code:'.strtoupper(self::uncode($code)));
2415
    }
2416
2417
    /**
2418
     * Returns CODE without code: prefix
2419
     *
2420
     * @param string $code
2421
     *
2422
     * @return string
2423
     */
2424
    public static function uncode($code)
2425
    {
2426
        return str_replace(['code:', 'code%3A'], '', $code);
2427
    }
2428
2429
    /**
2430
     * Remove all @ items from array
2431
     *
2432
     * @param array $data original data
2433
     *
2434
     * @return array data without @ columns
2435
     */
2436
    public static function arrayCleanUP($data)
2437
    {
2438
        return array_filter(
2439
            $data,
2440
            function ($key) {
2441
            return !strchr($key, '@');
2442
        }, ARRAY_FILTER_USE_KEY);
2443
    }
2444
2445
    /**
2446
     * Add Info about used user, server and libraries
2447
     *
2448
     * @param string $additions Additional note text
2449
     */
2450
    public function logBanner($additions = null)
2451
    {
2452
        $this->addStatusMessage('FlexiBee '.str_replace('://',
2453
                '://'.$this->user.'@', $this->getApiUrl()).' FlexiPeeHP v'.self::$libVersion.' (FlexiBee '.EvidenceList::$version.') EasePHP Framework v'.\Ease\Atom::$frameworkVersion.' '.$additions,
2454
            'debug');
2455
    }
2456
2457
    /**
2458
     * Reconnect After unserialization
2459
     */
2460
    public function __wakeup()
2461
    {
2462
        parent::__wakeup();
2463
        $this->curlInit();
2464
    }
2465
}
2466