Passed
Push — master ( c9fc13...74c932 )
by Vítězslav
04:34
created

FlexiBeeRO::updateColumnsInfo()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 8
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 4
nc 6
nop 2
crap 20
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
     * Token obtained during login procedure
317
     * @var string 
318
     */
319
    public $refreshToken = null;
320
321
    /**
322
     * Save 404 results to log ?
323
     * @var boolean
324
     */
325
    protected $ignoreNotFound = false;
326
327
    /**
328
     * Array of errors caused by last request
329
     * @var array
330
     */
331
    private $errors = [];
332
333
    /**
334
     * List of Error500 reports sent
335
     * @var array
336
     */
337
    private $reports = [];
338
339
    /**
340 70
     * Send Error500 Report to
341
     * @var string email address
342 70
     */
343
    public $reportRecipient = '[email protected]';
344 70
345 70
    /**
346 70
     * Formating string for \DateTime::format() for datetime columns
347 70
     * @var string
348 22
     */
349 22
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
350 70
351
    /**
352
     * Formating string for \DateTime::format() for date columns
353
     * @var string
354
     */
355
    static public $DateFormat = 'Y-m-d';
356
357
    /**
358 71
     * Last Request response stats
359
     * @var array 
360 71
     */
361 71
    private $responseStats = null;
362 71
363 71
    /**
364 71
     * Chained Objects
365 23
     * @var array
366 23
     */
367 71
    public $chained = [];
368 71
369 23
    /**
370 23
     * We Connect to server by default
371 71
     * @var boolean
372
     */
373
    public $offline = false;
374 71
375 71
    /**
376 71
     * Override cURL timeout
377
     * @var int seconds
378
     */
379
    public $timeout = null;
380
381
    /**
382
     * Columns Info for serveral evidencies
383
     * @var array 
384
     */
385 48
    private $columnsInfo = null;
386
387 48
    /**
388
     * Class for read only interaction with FlexiBee.
389
     *
390 48
     * @param mixed $init default record id or initial data
391 48
     * @param array $options Connection settings and other options override
392 48
     */
393
    public function __construct($init = null, $options = [])
394 48
    {
395
        $this->init = $init;
396
397
        parent::__construct();
398
        $this->setUp($options);
399 94
        $this->curlInit();
400
        if (!empty($init)) {
401 94
            $this->processInit($init);
402 94
        }
403 94
    }
404 94
405 94
    /**
406 94
     * Set internal Object name
407 94
     *
408 94
     * @param string $objectName
409 94
     *
410 94
     * @return string Jméno objektu
411
     */
412
    public function setObjectName($objectName = null)
413
    {
414
        return parent::setObjectName(is_null($objectName) ? ( empty($this->getRecordIdent()) ? $this->getObjectName() : $this->getRecordIdent().'@'.$this->getObjectName() )
415
                    : $objectName);
416
    }
417
418
    /**
419
     * SetUp Object to be ready for work
420
     *
421
     * @param array $options Object Options ( user,password,authSessionId
422
     *                                        company,url,evidence,
423 13
     *                                        prefix,defaultUrlParams,debug,
424
     *                                        detail,offline,filter,ignore404
425 13
     *                                        timeout
426 10
     */
427 13
    public function setUp($options = [])
428 13
    {
429 13
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
430 10
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
431 10
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
432 10
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
433 8
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
434
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
435 13
        if (!empty($this->authSessionId)) {
436
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
437
        }
438
        if (isset($options['evidence'])) {
439
            $this->setEvidence($options['evidence']);
440
        }
441
        $this->setupProperty($options, 'defaultUrlParams');
442 23
        if (isset($options['prefix'])) {
443
            $this->setPrefix($options['prefix']);
444
        }
445 23
        if (array_key_exists('detail', $options)) {
446 23
            $this->defaultUrlParams['detail'] = $options['detail'];
447 23
        }
448 23
        $this->setupProperty($options, 'filter');
449 23
        if (array_key_exists('offline', $options)) {
450 23
            $this->offline = (boolean) $options['offline'];
451 23
        }
452 23
453 23
        if (array_key_exists('ignore404', $options)) {
454 23
            $this->ignore404($options['ignore404']);
455 23
        }
456 23
457 23
        $this->setupProperty($options, 'debug');
458 23
        $this->updateApiURL();
459 23
    }
460 23
461 23
    /**
462 23
     * Set up one of properties
463
     *
464
     * @param array  $options  array of given properties
465
     * @param string $name     name of property to process
466
     * @param string $constant load default property value from constant
467
     */
468
    public function setupProperty($options, $name, $constant = null)
469
    {
470
        if (array_key_exists($name, $options)) {
471 23
            $this->$name = $options[$name];
472
        } else {
473 23
            if (property_exists($this, $name) && !empty($constant) && defined($constant)) {
474 23
                $this->$name = constant($constant);
475
            }
476
        }
477
    }
478
479
    /**
480 23
     * Get Current connection options for use in another object
481 23
     *
482 23
     * @return array usable as second constructor parameter
483 23
     */
484 23
    public function getConnectionOptions()
485
    {
486
        $conOpts = ['url' => $this->url];
487
        if (empty($this->authSessionId)) {
488
            $conOpts ['user']    = $this->user;
489
            $conOpts['password'] = $this->password;
490
        } else {
491
            $conOpts['authSessionId'] = $this->authSessionId;
492
        }
493
        $company = $this->getCompany();
494 23
        if (!empty($company)) {
495
            $conOpts['company'] = $company;
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
            $conOpts['timeout'] = $this->timeout;
499 23
        }
500
        return $conOpts;
501
    }
502
503 23
    /**
504 23
     * Inicializace CURL
505
     *
506
     * @return boolean Online Status
507 20
     */
508 20
    public function curlInit()
509
    {
510 20
        if ($this->offline === false) {
511 3
            $this->curl = \curl_init(); // create curl resource
512 3
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
513 3
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
514 3
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
515 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
516 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
517 23
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
518
            if (empty($this->authSessionId)) {
519
                curl_setopt($this->curl, CURLOPT_USERPWD,
520
                    $this->user.':'.$this->password); // set username and password
521
            }
522
            if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
523
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
524
            }
525
        }
526 69
        return !$this->offline;
527
    }
528 69
529
    /**
530
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
531
     *
532
     *  * 234                              - interní číslo záznamu k načtení
533
     *  * code:LOPATA                      - kód záznamu
534
     *  * BAGR                             - kód záznamu k načtení
535
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
536
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
537 23
     *
538
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
539 23
     */
540 23
    public function processInit($init)
541
    {
542
        if (is_integer($init)) {
543
            $this->loadFromFlexiBee($init);
544
        } elseif (is_array($init)) {
545
            $this->takeData($init);
546
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
547
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init)
548 23
                            : $init)));
549
        } else {
550 23
            $this->loadFromFlexiBee($init);
551
        }
552
    }
553
554
    /**
555
     * Set Data Field value
556
     *
557
     * @param string $columnName field name
558 25
     * @param mixed  $value      field data value
559
     *
560 25
     * @return bool Success
561 25
     */
562
    public function setDataValue($columnName, $value)
563
    {
564 25
        switch ($columnName) {
565 1
            case 'kod':
566 1
                $value = self::uncode($value); //Alwyas uncode "kod" column
567 24
                break;
568 24
            default:
569 24
                break;
570 25
        }
571 25
        if (is_object($value)) {
572
            switch (get_class($value)) {
573
                case 'DateTime':
574
                    $columnInfo = $this->getColumnInfo($columnName);
575
                    switch ($columnInfo['type']) {
576
                        case 'date':
577
                            $value = self::dateToFlexiDate($value);
578
                            break;
579
                        case 'datetime':
580
                            $value = self::dateToFlexiDateTime($value);
581 23
                            break;
582
                    }
583 23
                    break;
584 23
            }
585 23
        }
586 23
        return parent::setDataValue($columnName, $value);
587 23
    }
588 23
589 23
    /**
590 23
     * PHP Date object to FlexiBee date format
591 23
     * 
592 23
     * @param \DateTime $date
593 23
     */
594 23
    public static function dateToFlexiDate($date)
595 23
    {
596
        return $date->format(self::$DateFormat);
597
    }
598
599 23
    /**
600
     * PHP Date object to FlexiBee date format
601
     * 
602
     * @param \DateTime $dateTime
603
     */
604
    public static function dateToFlexiDateTime($dateTime)
605
    {
606
        return $dateTime->format(self::$DateTimeFormat);
607
    }
608
609 23
    /**
610
     * Set URL prefix
611 23
     *
612 23
     * @param string $prefix
613 22
     */
614 22
    public function setPrefix($prefix)
615 23
    {
616 17
        switch ($prefix) {
617 17
            case 'a': //Access
618 17
            case 'c': //Company
619 17
            case 'u': //User
620 23
            case 'g': //License Groups
621
            case 'admin':
622
            case 'status':
623
            case 'login-logout':
624 23
                $this->prefix = '/'.$prefix.'/';
625
                break;
626
            case null:
627
            case '':
628
            case '/':
629
                $this->prefix = '';
630
                break;
631
            default:
632
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
633
        }
634 68
    }
635
636 68
    /**
637 68
     * Set communication format.
638 68
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
639 62
     *
640 62
     * @param string $format
641 68
     * 
642
     * @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...
643
     */
644
    public function setFormat($format)
645
    {
646
        $result = true;
647
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
648
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
649
                === false) {
650
                $result = false;
651 23
            }
652
        }
653 23
        if ($result === true) {
654 23
            $this->format = $format;
655 23
            $this->updateApiURL();
656 23
        }
657 23
        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...
658 23
    }
659 23
660 23
    /**
661 23
     * Nastaví Evidenci pro Komunikaci.
662
     * Set evidence for communication
663
     *
664
     * @param string $evidence evidence pathName to use
665
     * 
666
     * @return boolean evidence switching status
667 48
     */
668
    public function setEvidence($evidence)
669 48
    {
670 48
        switch ($this->prefix) {
671 48
            case '/c/':
672
                if ($this->debug === true) {
673
                    if (array_key_exists($evidence, EvidenceList::$name)) {
674 48
                        $this->evidence = $evidence;
675 48
                        $result         = true;
676
                    } else {
677
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
678
                            $evidence));
679
                    }
680
                } else {
681
                    $this->evidence = $evidence;
682
                    $result         = true;
683
                }
684
                break;
685
            default:
686 23
                $this->evidence = $evidence;
687
                $result         = true;
688 23
                break;
689 23
        }
690 23
        $this->updateApiURL();
691 23
        return $result;
692 23
    }
693 23
694 23
    /**
695 23
     * Vrací právě používanou evidenci pro komunikaci
696 23
     * Obtain current used evidence
697 23
     *
698 23
     * @return string
699 23
     */
700 23
    public function getEvidence()
701
    {
702
        return $this->evidence;
703 23
    }
704 23
705 23
    /**
706
     * Set used company.
707
     * Nastaví Firmu.
708 23
     *
709
     * @param string $company
710
     */
711
    public function setCompany($company)
712
    {
713
        $this->company = $company;
714
    }
715
716
    /**
717
     * Obtain company now used
718 23
     * Vrací právě používanou firmu
719
     *
720 23
     * @return string
721
     */
722
    public function getCompany()
723
    {
724
        return $this->company;
725
    }
726
727
    /**
728
     * Vrací název evidence použité v odpovědích z FlexiBee
729
     *
730
     * @return string
731 25
     */
732
    public function getResponseEvidence()
733
    {
734 25
        switch ($this->evidence) {
735
            case 'c':
736 25
                $evidence = 'company';
737
                break;
738 25
            case 'evidence-list':
739 4
                $evidence = 'evidence';
740 4
                break;
741 22
            default:
742
                $evidence = $this->getEvidence();
743
                break;
744 25
        }
745
        return $evidence;
746 25
    }
747 25
748
    /**
749
     * Převede rekurzivně Objekt na pole.
750
     *
751
     * @param object|array $object
752
     *
753
     * @return array
754
     */
755
    public static function object2array($object)
756
    {
757
        $result = null;
758 3
        if (is_object($object)) {
759
            $objectData = get_object_vars($object);
760 3
            if (is_array($objectData) && count($objectData)) {
761
                $result = array_map('self::object2array', $objectData);
762 3
            }
763 3
        } else {
764 3
            if (is_array($object)) {
0 ignored issues
show
introduced by
The condition is_array($object) is always true.
Loading history...
765
                foreach ($object as $item => $value) {
766
                    $result[$item] = self::object2array($value);
767
                }
768
            } else {
769
                $result = $object;
770
            }
771
        }
772
773 3
        return $result;
774
    }
775 3
776
    /**
777
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
778
     *
779
     * @param object|array $object
780
     *
781
     * @return array
782
     */
783
    public static function objectToID($object)
784
    {
785 3
        $resultID = null;
786
        if (is_object($object) && method_exists($object, '__toString')
787 3
        ) {
788 3
            $resultID = $object->__toString();
789 3
        } else {
790 3
            if (is_array($object)) {
791
                foreach ($object as $item => $value) {
792
                    $resultID[$item] = self::objectToID($value);
793 3
                }
794
            } else { //String
795
                $resultID = $object;
796
            }
797 3
        }
798
799
        return $resultID;
800
    }
801
802
    /**
803
     * Return basic URL for used Evidence
804
     *
805
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
806
     *
807
     * @return string Evidence URL
808
     */
809
    public function getEvidenceURL()
810
    {
811
        $evidenceUrl = $this->url.$this->prefix.$this->company;
812
        $evidence    = $this->getEvidence();
813
        if (!empty($evidence)) {
814
            $evidenceUrl .= '/'.$evidence;
815
        }
816
        return $evidenceUrl;
817
    }
818
819
    /**
820 3
     * Add suffix to Evidence URL
821
     *
822 3
     * @param string $urlSuffix
823
     *
824 3
     * @return string
825
     */
826
    public function evidenceUrlWithSuffix($urlSuffix)
827
    {
828
        $evidenceUrl = $this->getEvidenceUrl();
829
        if (!empty($urlSuffix)) {
830
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
831
                != '?')) {
832 3
                $evidenceUrl .= '/';
833 3
            }
834 3
            $evidenceUrl .= $urlSuffix;
835
        }
836
        return $evidenceUrl;
837 3
    }
838
839
    /**
840 3
     * Update $this->apiURL
841
     */
842
    public function updateApiURL()
843
    {
844
        $this->apiURL = $this->getEvidenceURL();
845
        $id           = $this->getRecordID();
846
        if (empty($id)) {
847
            $id = $this->getRecordCode();
848
        }
849
        if (!empty($id)) {
850
            $this->apiURL .= '/'.self::urlEncode($id);
851
        }
852
        $this->apiURL .= '.'.$this->format;
853
    }
854
    /*
855
     * Add Default Url params to given url if not overrided
856
     *
857
     * @param string $urlRaw
858
     *
859
     * @return string url with default params added
860 3
     */
861
862
    public function addDefaultUrlParams($urlRaw)
863
    {
864
        return \Ease\Shared::addUrlParams($urlRaw, $this->defaultUrlParams,
865
                false);
866
    }
867
868
    /**
869
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
870
     *
871
     * @param string $urlSuffix část URL za identifikátorem firmy.
872
     * @param string $method    HTTP/REST metoda
873
     * @param string $format    Requested format
874
     * 
875
     * @return array|boolean Výsledek operace
876
     */
877
    public function performRequest($urlSuffix = null, $method = 'GET',
878
                                   $format = null)
879
    {
880
        $this->rowCount      = null;
881
        $this->responseStats = [];
882
883
        if (preg_match('/^http/', $urlSuffix)) {
884
            $url = $urlSuffix;
885
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
886
            $url = $this->url.$urlSuffix;
887
        } else {
888
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
889
        }
890 3
891
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
892 3
            $method, $format);
893 3
894 3
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
895 3
                    $this->responseFormat), $responseCode);
896
    }
897 3
898
    /**
899 3
     * Parse Raw FlexiBee response in several formats
900
     *
901 3
     * @param string $responseRaw raw response body
902
     * @param string $format      Raw Response format json|xml|etc
903 3
     *
904
     * @return array
905 3
     */
906 3
    public function rawResponseToArray($responseRaw, $format)
907 3
    {
908 3
        $responseDecoded = [];
909 3
        if (!empty(trim($responseRaw))) {
910 3
            switch ($format) {
911 3
                case 'json':
912 3
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
913 3
                    break;
914 3
                case 'xml':
915 3
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
916 3
                    break;
917 3
                case 'txt':
918
                default:
919 3
                    $responseDecoded = [$this->lastCurlResponse];
920
                    break;
921
            }
922 3
        }
923 3
        return $responseDecoded;
924 3
    }
925 3
926 3
    /**
927 3
     * Convert FlexiBee Response JSON to Array
928 3
     *
929 3
     * @param string $rawJson
930 3
     *
931
     * @return array
932
     */
933
    public function rawJsonToArray($rawJson)
934
    {
935 3
        $responseDecoded = json_decode($rawJson, true, 10);
936
        $decodeError     = json_last_error_msg();
937
        if ($decodeError == 'No error') {
938
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
939 3
                $responseDecoded = $responseDecoded[$this->nameSpace];
940
            }
941
        } else {
942
            $this->addStatusMessage('JSON Decoder: '.$decodeError, 'error');
943
            $this->addStatusMessage($rawJson, 'debug');
944
        }
945
        return $responseDecoded;
946
    }
947
948
    /**
949 23
     * Convert FlexiBee Response XML to Array
950
     *
951 23
     * @param string $rawXML
952 23
     *
953 23
     * @return array
954 23
     */
955 15
    public function rawXmlToArray($rawXML)
956 15
    {
957 15
        return self::xml2array($rawXML);
958 23
    }
959
960
    /**
961
     * Parse Response array
962
     *
963
     * @param array $responseDecoded
964
     * @param int $responseCode Request Response Code
965
     *
966
     * @return array main data part of response
967
     */
968 23
    public function parseResponse($responseDecoded, $responseCode)
969
    {
970 23
        if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
971 23
            $mainResult          = $this->unifyResponseFormat($responseDecoded);
972 23
            $this->responseStats = array_key_exists('stats', $responseDecoded) ? (isset($responseDecoded['stats'][0])
973 23
                    ? $responseDecoded['stats'][0] : $responseDecoded['stats']) : null;
974 23
        } else {
975
            $mainResult = $responseDecoded;
976 23
        }
977 23
        switch ($responseCode) {
978 23
            case 201: //Success Write
979 23
            case 200: //Success Read
980 23
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
981
                    $this->lastResult = $mainResult;
982 23
                    if (isset($responseDecoded['@rowCount'])) {
983 23
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
984 23
                    }
985
                    if (isset($responseDecoded['@globalVersion'])) {
986
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
987
                    }
988
                }
989
                break;
990 1
991
            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...
992 1
                if ($this->debug === true) {
993 1
                    $this->error500Reporter($responseDecoded);
994 1
                }
995 1
            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...
996 1
                if ($this->ignoreNotFound === true) {
997
                    break;
998
                }
999
            case 400: //Bad Request parameters
1000
            default: //Something goes wrong
1001 1
                $this->addStatusMessage($this->lastResponseCode.': '.$this->curlInfo['url'],
1002
                    'warning');
1003 1
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
1004 1
                    $this->parseError($responseDecoded);
1005
                }
1006
                $this->logResult($responseDecoded, $this->curlInfo['url']);
1007
                break;
1008
        }
1009
        return $mainResult;
1010
    }
1011
1012
    /**
1013 23
     * Parse error message response
1014
     *
1015 23
     * @param array $responseDecoded
1016 23
     * 
1017 22
     * @return int number of errors processed
1018
     */
1019
    public function parseError(array $responseDecoded)
1020
    {
1021 22
        if (array_key_exists('results', $responseDecoded)) {
1022
            $this->errors = $responseDecoded['results'][0]['errors'];
1023
            foreach ($this->errors as $errorInfo) {
1024
                $this->addStatusMessage($errorInfo['message'], 'error');
1025
                if (array_key_exists('for', $errorInfo)) {
1026
                    unset($errorInfo['message']);
1027
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1028
                }
1029
            }
1030
        } else {
1031
            if (array_key_exists('message', $responseDecoded)) {
1032
                $this->errors = [['message' => $responseDecoded['message']]];
1033
            }
1034
        }
1035
        return count($this->errors);
1036
    }
1037
1038
    /**
1039
     * Vykonej HTTP požadavek
1040
     *
1041
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1042
     * @param string $url    URL požadavku
1043
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1044
     * @param string $format požadovaný formát komunikace
1045
     * 
1046
     * @return int HTTP Response CODE
1047
     */
1048
    public function doCurlRequest($url, $method, $format = null)
1049
    {
1050
        if (is_null($format)) {
1051
            $format = $this->format;
1052
        }
1053
        curl_setopt($this->curl, CURLOPT_URL, $url);
1054
// Nastavení samotné operace
1055
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1056
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1057
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1058
1059 15
        $httpHeaders = $this->defaultHttpHeaders;
1060
1061 15
        $formats = Formats::bySuffix();
1062 15
1063
        if (!isset($httpHeaders['Accept'])) {
1064 15
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1065 8
        }
1066 7
        if (!isset($httpHeaders['Content-Type'])) {
1067 7
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1068 7
        }
1069
        $httpHeadersFinal = [];
1070 8
        foreach ($httpHeaders as $key => $value) {
1071 1
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1072 1
                $value .= ' v'.self::$libVersion;
1073 8
            }
1074
            $httpHeadersFinal[] = $key.': '.$value;
1075 15
        }
1076 4
1077 4
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1078 4
1079
// Proveď samotnou operaci
1080
        $this->lastCurlResponse            = curl_exec($this->curl);
1081
        $this->curlInfo                    = curl_getinfo($this->curl);
1082
        $this->curlInfo['when']            = microtime();
1083 4
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1084
        $this->responseFormat              = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1085 15
            $url);
1086
        $this->lastResponseCode            = $this->curlInfo['http_code'];
1087 15
        $this->lastCurlError               = curl_error($this->curl);
1088 15
        if (strlen($this->lastCurlError)) {
1089
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1090
                    $this->lastResponseCode, $this->lastCurlError), 'error');
1091 15
        }
1092
1093 15
        if ($this->debug === true) {
1094 15
            $this->saveDebugFiles();
1095 15
        }
1096
1097 15
        return $this->lastResponseCode;
1098
    }
1099 15
1100 15
    /**
1101 15
     * Obtain json for application/json
1102 9
     * 
1103 9
     * @param string $contentType
1104 6
     * @param string $url
1105 6
     * 
1106 9
     * @return string response format
1107 6
     */
1108
    public function contentTypeToResponseFormat($contentType, $url = null)
1109
    {
1110 15
        if (!empty($url)) {
1111
            $url = parse_url($url, PHP_URL_PATH);
1112
        }
1113
1114
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1115
                strpos($contentType, ';')) : $contentType;
1116
1117
        switch ($url) {
1118
            case '/login-logout/login';
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1119
                $responseFormat = 'json';
1120
                break;
1121 23
            default :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a DEFAULT statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in the default statement.

switch ($expr) {
    default : //wrong
        doSomething();
        break;
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1122
                switch ($contentTypeClean) {
1123 23
                    case 'text/javascript':
1124 23
                        $responseFormat = 'js';
1125 23
                        break;
1126 23
1127 23
                    default:
1128
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1129
                        break;
1130
                }
1131 23
                break;
1132
        }
1133
1134
        return $responseFormat;
1135 23
    }
1136 22
1137 22
    /**
1138 9
     * Nastaví druh prováděné akce.
1139 9
     *
1140 22
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1141
     * @param string $action
1142
     * 
1143
     * @return boolean
1144
     */
1145
    public function setAction($action)
1146
    {
1147
        $result           = false;
1148
        $actionsAvailable = $this->getActionsInfo();
1149
        if (is_array($actionsAvailable) && array_key_exists($action,
1150
                $actionsAvailable)) {
1151 6
            $this->action = $action;
1152
            $result       = true;
1153
        }
1154 6
        return $result;
1155 6
    }
1156 6
1157 6
    /**
1158 6
     * Convert XML to array.
1159
     *
1160 6
     * @param string $xml
1161
     *
1162
     * @return array
1163
     */
1164
    public static function xml2array($xml)
1165 6
    {
1166
        $arr = [];
1167
        if (!empty($xml)) {
1168
            if (is_string($xml)) {
0 ignored issues
show
introduced by
The condition is_string($xml) is always true.
Loading history...
1169 6
                $xml = simplexml_load_string($xml);
1170
            }
1171
            foreach ($xml->attributes() as $a) {
1172
                $arr['@'.$a->getName()] = strval($a);
1173
            }
1174
            foreach ($xml->children() as $r) {
1175
                if (count($r->children()) == 0) {
1176
                    $arr[$r->getName()] = strval($r);
1177 16
                } else {
1178
                    $arr[$r->getName()][] = self::xml2array($r);
1179 16
                }
1180 9
            }
1181 9
        }
1182 16
        return $arr;
1183 16
    }
1184 16
1185
    /**
1186 16
     * Odpojení od FlexiBee.
1187 16
     */
1188 16
    public function disconnect()
1189 15
    {
1190 15
        if (is_resource($this->curl)) {
1191
            curl_close($this->curl);
1192
        }
1193
        $this->curl = null;
1194
    }
1195
1196
    /**
1197
     * Disconnect CURL befere pass away
1198
     */
1199 15
    public function __destruct()
1200
    {
1201
        $this->disconnect();
1202 15
    }
1203 10
1204 10
    /**
1205 15
     * Načte řádek dat z FlexiBee.
1206 15
     *
1207 15
     * @param int $recordID id požadovaného záznamu
1208 15
     *
1209
     * @return array
1210 14
     */
1211 14
    public function getFlexiRow($recordID)
1212 14
    {
1213 14
        $record   = null;
1214 10
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
1215
        if (isset($response[$this->evidence])) {
1216 14
            $record = $response[$this->evidence][0];
1217 14
        }
1218
1219
        return $record;
1220
    }
1221
1222
    /**
1223
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1224
     *
1225
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1226
     * @param array $conditions pole podmínek   - rendrují se do ()
1227
     * @param array $urlParams  pole parametrů  - rendrují za ?
1228
     */
1229
    public function extractUrlParams(&$conditions, &$urlParams)
1230
    {
1231
        foreach ($this->urlParams as $urlParam) {
1232
            if (isset($conditions[$urlParam])) {
1233
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
1234
            }
1235
        }
1236
    }
1237
1238
    /**
1239
     * convert unicode to entities for use with FlexiBee queries
1240
     *
1241
     * @param string $urlRaw
1242
     * 
1243
     * @return string
1244
     */
1245
    public static function urlEncode($urlRaw)
1246
    {
1247
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1248
    }
1249
1250
    /**
1251
     * Načte data z FlexiBee.
1252 15
     *
1253
     * @param string $suffix     dotaz
1254
     * @param string|array $conditions Volitelný filtrovací výraz
1255 15
     *
1256 15
     * @return array Data obtained
1257 15
     */
1258
    public function getFlexiData($suffix = null, $conditions = null)
1259 15
    {
1260 15
        $finalUrl  = '';
1261 15
        $urlParams = $this->defaultUrlParams;
1262 15
1263 15
        if (!empty($conditions)) {
1264 15
            if (is_array($conditions)) {
1265 15
                $this->extractUrlParams($conditions, $urlParams);
1266 15
                $conditions = $this->flexiUrl($conditions);
1267
            }
1268 15
1269
            if (strlen($conditions) && ($conditions[0] != '/')) {
1270
                $conditions = '('.self::urlEncode($conditions).')';
1271 15
            }
1272
        }
1273
1274 15
        if (strlen($suffix)) {
1275 15
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1276 15
                $finalUrl = $suffix;
1277 15
            } else {
1278 15
                if (preg_match('/^(code|ext):(.*)/', $suffix, $matches)) {
1279
                    $finalUrl = $matches[1].':'.rawurlencode($matches[2]);
1280 15
                }
1281
            }
1282 15
        }
1283
1284 15
        $finalUrl .= $conditions;
1285 9
1286 9
        if (count($urlParams)) {
1287
            if (strstr($finalUrl, '?')) {
1288 15
                $finalUrl .= '&';
1289
            } else {
1290
                $finalUrl .= '?';
1291
            }
1292
            $finalUrl .= http_build_query($urlParams, null, '&',
1293
                PHP_QUERY_RFC3986);
1294
        }
1295
1296
        $transactions = $this->performRequest($finalUrl, 'GET');
1297
1298
        $responseEvidence = $this->getResponseEvidence();
1299 23
        if (is_array($transactions) && array_key_exists($responseEvidence,
1300
                $transactions)) {
1301 23
            $result = $transactions[$responseEvidence];
1302
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
1303 23
                $result = null; // Response is empty Array
1304 23
            }
1305 23
        } else {
1306
            $result = $transactions;
1307 23
        }
1308 23
1309 23
        return $result;
1310
    }
1311 23
1312 23
    /**
1313 23
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1314 23
     * Read FlexiBee record and store it inside od object
1315 23
     *
1316 23
     * @param int $id ID or conditions
1317 23
     *
1318 23
     * @return int počet načtených položek
1319 23
     */
1320 23
    public function loadFromFlexiBee($id = null)
1321
    {
1322
        $data = [];
1323
        if (is_null($id)) {
1324 23
            $id = $this->getMyKey();
1325 23
        }
1326 23
        if (is_array($id)) {
0 ignored issues
show
introduced by
The condition is_array($id) is always false.
Loading history...
1327
            $id = rawurlencode('('.self::flexiUrl($id).')');
1328 23
        } else if (preg_match('/^ext:/', $id)) {
1329 23
            $id = self::urlEncode($id);
1330 23
        } else if (preg_match('/^code:/', $id)) {
1331 23
            $id = self::code(self::urlEncode(self::uncode($id)));
1332
        }
1333
1334 23
        $flexidata    = $this->getFlexiData($this->getEvidenceUrl().'/'.$id);
1335 23
        $this->apiURL = $this->curlInfo['url'];
1336 23
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1337 23
            $data = current($flexidata);
1338 23
        }
1339 23
        return $this->takeData($data);
1340 23
    }
1341 23
1342 23
    /**
1343 23
     * Set Filter code for requests
1344 23
     *
1345 23
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1346
     *
1347 23
     * @param array|string $filter filter formula or ['key'=>'value']
1348 23
     *
1349
     * @return string Filter code
1350 23
     */
1351
    public function setFilter($filter)
1352
    {
1353
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1354
    }
1355
1356
    /**
1357
     * Převede data do Json formátu pro FlexiBee.
1358
     * Convert data to FlexiBee like Json format
1359
     *
1360 23
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1361
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1362 23
     *
1363 23
     * @param array $data    object data
1364 23
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1365
     *
1366
     * @return string
1367 23
     */
1368 23
    public function getJsonizedData($data = null, $options = 0)
1369 23
    {
1370 23
        if (is_null($data)) {
1371 23
            $data = $this->getData();
1372
        }
1373
1374 23
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1375 23
            $this->getDataForJSON($data));
1376 23
        $jsonRaw       = json_encode([$this->nameSpace => $dataToJsonize],
1377
            $options);
1378 23
1379 23
        return $jsonRaw;
1380 23
    }
1381 23
1382 23
    /**
1383
     * Get Data Fragment specific for current object
1384 23
     *
1385 23
     * @param array $data
1386 23
     *
1387 23
     * @return array
1388 23
     */
1389
    public function getDataForJSON($data = null)
1390 23
    {
1391 23
        if (is_null($data)) {
1392 23
            $data = $this->getData();
1393 23
        }
1394
1395
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1396 23
1397
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1398
            $dataForJson[$this->evidence.'@action'] = $this->action;
1399 23
            $this->action                           = null;
1400
        }
1401
1402 23
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1403 23
            $dataForJson[$this->evidence.'@filter'] = $this->filter;
1404 23
        }
1405 23
1406 23
1407 23
        foreach ($this->chained as $chained) {
1408
            $chainedData = $chained->getDataForJSON();
1409
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1410
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1411
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1412
                        $dataBackup                          = $dataForJson[$chainedItemEvidence];
1413
                        $dataForJson[$chainedItemEvidence]   = [];
1414
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1415
                    }
1416
                    if (array_key_exists(0, $chainedItemData)) {
1417
                        foreach ($chainedItemData as $chainedItem) {
1418
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1419
                        }
1420
                    } else {
1421
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1422
                    }
1423
                } else {
1424
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1425
                }
1426
            }
1427
        }
1428
1429
1430
        return $dataForJson;
1431
    }
1432
1433
    /**
1434
     * Join another FlexiPeeHP Object
1435
     *
1436
     * @param FlexiBeeRO $object
1437
     *
1438
     * @return boolean adding to stack success
1439
     */
1440
    public function join(&$object)
1441
    {
1442
        $result = true;
1443
        if (method_exists($object, 'getDataForJSON')) {
1444 23
            $this->chained[] = $object;
1445
        } else {
1446 23
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1447
        }
1448 23
1449 23
        return $result;
1450 23
    }
1451 23
1452 23
    /**
1453 23
     * Test if given record ID exists in FlexiBee.
1454 23
     *
1455 23
     * @param mixed $identifer presence state
1456 23
     *
1457
     * @return boolean
1458 23
     */
1459 23
    public function idExists($identifer = null)
1460 23
    {
1461 23
        if (is_null($identifer)) {
1462 23
            $identifer = $this->getMyKey();
1463
        }
1464
        $ignorestate = $this->ignore404();
1465 23
        $this->ignore404(true);
1466 23
        $this->getFlexiData(null,
1467
            [
1468
            'detail' => 'custom:'.$this->getKeyColumn(),
1469 23
            $this->getKeyColumn() => $identifer
1470
        ]);
1471 23
        $this->ignore404($ignorestate);
1472 23
        return $this->lastResponseCode == 200;
1473
    }
1474 23
1475
    /**
1476
     * Test if given record exists in FlexiBee.
1477 23
     *
1478 23
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1479
     * 
1480
     * @return boolean Record presence status
1481
     */
1482
    public function recordExists($data = [])
1483
    {
1484
1485
        if (empty($data)) {
1486
            $data = $this->getData();
1487
        }
1488
        $ignorestate = $this->ignore404();
1489 65
        $this->ignore404(true);
1490
        $keyColumn   = $this->getKeyColumn();
1491 65
        $res         = $this->getColumnsFromFlexibee([$keyColumn],
1492 65
            is_array($data) ? $data : [$keyColumn => $data]);
1493
1494
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false'))
1495 65
            || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1496 65
            $found = false;
1497
        } else {
1498
            $found = true;
1499
        }
1500
        $this->ignore404($ignorestate);
1501 65
        return $found;
1502
    }
1503
1504
    /**
1505
     * Subitems - ex. items of invoice
1506
     * 
1507
     * @return array of document items or null
1508
     */
1509
    public function getSubItems()
1510
    {
1511 71
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury')
1512
                : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu')
1513 71
                : null);
1514
    }
1515
1516
    /**
1517
     * Vrací z FlexiBee sloupečky podle podmínek.
1518
     *
1519
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1520
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1521
     *                                     sloupečku
1522 23
     * @return array
1523
     */
1524 23
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1525
    {
1526
        if (is_int($conditions)) {
1527
            $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

1527
            $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...
1528
        }
1529
1530
        $flexiData = $this->getFlexiData('', $conditions);
1531
1532 15
        if (!is_null($indexBy)) {
1533
            $flexiData = $this->reindexArrayBy($flexiData);
1534 15
        }
1535 15
1536 15
        return $flexiData;
1537 15
    }
1538 15
1539 9
    /**
1540 9
     * Vrací z FlexiBee sloupečky podle podmínek.
1541 15
     *
1542
     * @param string[] $columnsList seznam položek
1543
     * @param array    $conditions  pole podmínek nebo ID záznamu
1544
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1545
     *
1546
     * @return array
1547
     */
1548
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1549
                                           $indexBy = null)
1550 23
    {
1551
        $detail = 'full';
1552 23
        switch (gettype($columnsList)) {
1553 23
            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...
1554 23
                $conditions = [$this->getmyKeyColumn() => $conditions];
1555 23
            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...
1556 23
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1557 23
                        $columnsList)) {
1558 23
                    $columnsList[] = $indexBy;
1559 23
                }
1560 23
                $columns = implode(',', array_unique($columnsList));
1561 23
                $detail  = 'custom:'.$columns;
1562 23
            default:
1563 23
                switch ($columnsList) {
1564 23
                    case 'id':
1565 23
                        $detail = 'id';
1566
                        break;
1567 23
                    case 'summary':
1568
                        $detail = 'summary';
1569
                        break;
1570
                    default:
1571
                        break;
1572
                }
1573
                break;
1574
        }
1575
1576
        $conditions['detail'] = $detail;
1577 22
1578
        $flexiData = $this->getFlexiData(null, $conditions);
1579 22
1580
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1581 21
                $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1582
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1583
        }
1584
1585
        return $flexiData;
1586
    }
1587
1588
    /**
1589 22
     * Vrací kód záznamu.
1590
     * Obtain record CODE
1591 22
     *
1592 22
     * @param mixed $data
1593 22
     *
1594
     * @return string
1595
     */
1596 22
    public function getKod($data = null, $unique = true)
1597
    {
1598
        $kod = null;
1599
1600
        if (is_null($data)) {
1601
            $data = $this->getData();
1602
        }
1603
1604
        if (is_string($data)) {
1605 22
            $data = [$this->nameColumn => $data];
1606
        }
1607 22
1608 22
        if (isset($data['kod'])) {
1609 22
            $kod = $data['kod'];
1610 22
        } else {
1611 22
            if (isset($data[$this->nameColumn])) {
1612 22
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1613 22
                    \Ease\Sand::rip($data[$this->nameColumn]));
1614 22
            } else {
1615 22
                if (isset($data[$this->keyColumn])) {
1616 22
                    $kod = \Ease\Sand::rip($data[$this->keyColumn]);
1617 22
                }
1618 22
            }
1619
            $kod = substr($kod, 0, 20);
1620 22
        }
1621
1622
        if (!strlen($kod)) {
1623
            $kod = 'NOTSET';
1624
        }
1625
1626
        if (strlen($kod) > 18) {
1627
            $kodfinal = strtoupper(substr($kod, 0, 18));
1628
        } else {
1629
            $kodfinal = strtoupper($kod);
1630
        }
1631
1632 22
        if ($unique) {
1633
            $counter = 0;
1634
            if (!empty($this->codes) && count($this->codes)) {
1635
                foreach ($this->codes as $codesearch => $keystring) {
1636
                    if (strstr($codesearch, $kodfinal)) {
1637
                        ++$counter;
1638
                    }
1639
                }
1640
            }
1641 23
            if ($counter) {
1642
                $kodfinal = $kodfinal.$counter;
1643 23
            }
1644 23
1645 23
            $this->codes[$kodfinal] = $kod;
1646 23
        }
1647 16
1648 16
        return self::code($kodfinal);
1649 23
    }
1650
1651
    /**
1652
     * Write Operation Result.
1653
     *
1654
     * @param array  $resultData
1655
     * @param string $url        URL
1656
     * 
1657
     * @return boolean Log save success
1658 23
     */
1659
    public function logResult($resultData = null, $url = null)
1660 23
    {
1661 23
        $logResult = false;
1662 23
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1663 23
            if (isset($resultData['message'])) {
1664 23
                $this->addStatusMessage($resultData['message'], 'warning');
1665 23
            }
1666 23
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1667 23
                'warning');
1668 23
            unset($url);
1669
        }
1670
        if (is_null($resultData)) {
1671
            $resultData = $this->lastResult;
1672
        }
1673
        if (isset($url)) {
1674
            $this->logger->addStatusMessage($this->lastResponseCode.':'.urldecode($url));
1675
        }
1676
1677 23
        if (isset($resultData['results'])) {
1678
            if ($resultData['success'] == 'false') {
1679 23
                $status = 'error';
1680 23
            } else {
1681 23
                $status = 'success';
1682 23
            }
1683 23
            foreach ($resultData['results'] as $result) {
1684 23
                if (isset($result['request-id'])) {
1685 13
                    $rid = $result['request-id'];
1686 13
                } else {
1687 23
                    $rid = '';
1688
                }
1689
                if (isset($result['errors'])) {
1690
                    foreach ($result['errors'] as $error) {
1691
                        $message = $error['message'];
1692
                        if (isset($error['for'])) {
1693
                            $message .= ' for: '.$error['for'];
1694
                        }
1695
                        if (isset($error['value'])) {
1696 23
                            $message .= ' value:'.$error['value'];
1697
                        }
1698 23
                        if (isset($error['code'])) {
1699 23
                            $message .= ' code:'.$error['code'];
1700 23
                        }
1701 23
                        $this->addStatusMessage($rid.': '.$message, $status);
1702 23
                    }
1703 16
                }
1704 16
            }
1705 23
        }
1706
        return $logResult;
1707
    }
1708
1709
    /**
1710
     * Save RAW Curl Request & Response to files in Temp directory
1711
     */
1712
    public function saveDebugFiles()
1713
    {
1714 23
        $tmpdir   = sys_get_temp_dir();
1715
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1716 23
        $reqname  = $tmpdir.'/request-'.$fname;
1717 23
        $respname = $tmpdir.'/response-'.$fname;
1718 23
        file_put_contents($reqname, $this->postFields);
1719 23
        file_put_contents($respname, $this->lastCurlResponse);
1720 23
    }
1721 16
1722 16
    /**
1723 23
     * Připraví data pro odeslání do FlexiBee
1724
     *
1725
     * @param string $data
1726
     */
1727
    public function setPostFields($data)
1728
    {
1729
        $this->postFields = $data;
1730
    }
1731 23
1732
    /**
1733 23
     * Get Content ready to be send as POST body
1734 1
     * @return string
1735 1
     */
1736 23
    public function getPostFields()
1737 23
    {
1738
        return $this->postFields;
1739
    }
1740
1741
    /**
1742
     * Generuje fragment url pro filtrování.
1743
     *
1744 20
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1745
     *
1746 20
     * @param array  $data   key=>values; value can bee class DatePeriod
1747 20
     * @param string $joiner default and/or
1748 20
     * @param string $defop  default operator
1749 20
     *
1750
     * @return string
1751
     */
1752
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1753
    {
1754
        $parts = [];
1755 20
1756
        foreach ($data as $column => $value) {
1757
            if (!is_numeric($column)) {
1758
                if (is_integer($data[$column]) || is_float($data[$column])) {
1759
                    $parts[$column] = $column.' eq \''.$data[$column].'\'';
1760
                } elseif (is_bool($data[$column])) {
1761
                    $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1762
                } elseif (is_null($data[$column])) {
1763
                    $parts[$column] = $column." is null";
1764
                } elseif (is_object($data[$column])) {
1765
                    switch (get_class($data[$column])) {
1766
                        case 'DatePeriod':
1767
                            $parts[$column] = $column." between '".$data[$column]->getStartDate()->format(self::$DateFormat)."' '".$data[$column]->getEndDate()->format(self::$DateFormat)."'";
1768
                            break;
1769
                        default:
1770
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1771
                            break;
1772
                    }
1773
                } else {
1774
                    switch ($value) {
1775
                        case '!null':
1776
                            $parts[$column] = $column." is not null";
1777
                            break;
1778
                        case 'is empty':
1779
                        case 'is not empty':
1780
                            $parts[$column] = $column.' '.$value;
1781
                            break;
1782
                        default:
1783
                            switch (explode(' ', trim($value))[0]) {
1784
                                case 'like':
1785
                                case 'begins':
1786
                                case 'ends':
1787
                                    $parts[$column] = $column         .= ' '.$value;
1788
                                    break;
1789
                                default:
1790
                                    if ($column == 'stitky') {
1791
                                        $parts[$column] = $column."='".self::code($data[$column])."'";
1792
                                    } else {
1793
                                        $parts[$column] = $column." $defop '".$data[$column]."'";
1794
                                    }
1795
                                    break;
1796
                            }
1797
1798
                            break;
1799
                    }
1800
                }
1801
            } else {
1802
                $parts[] = $value;
1803
            }
1804
        }
1805
        return implode(' '.$joiner.' ', $parts);
1806
    }
1807
1808
    /**
1809
     * Obtain record/object numeric identificator id:
1810
     * Vrací číselný identifikátor objektu id:
1811
     *
1812
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1813
     *
1814
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1815
     */
1816
    public function getRecordID()
1817
    {
1818
        $id = $this->getDataValue('id');
1819
        return is_null($id) ? null : is_numeric($id) ? intval($id) : $id;
1820
    }
1821
1822
    /**
1823
     * Obtain record/object identificator code:
1824
     * Vrací identifikátor objektu code:
1825
     *
1826
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1827
     *
1828
     * @return string record code identifier
1829
     */
1830
    public function getRecordCode()
1831
    {
1832
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1833
    }
1834
1835
    /**
1836
     * Obtain record/object identificator extId: code: or id:
1837
     * Vrací identifikátor objektu extId: code: nebo id:
1838
     *
1839
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1840
     *
1841
     * @return string|int|null record code identifier
1842
     */
1843
    public function getRecordIdent()
1844
    {
1845 23
        $ident = $this->getExternalID();
1846
        if (empty($ident)) {
1847 23
            $ident = $this->getRecordCode();
1848
        }
1849
        if (empty($ident)) {
1850
            $ident = $this->getRecordID();
1851
        }
1852
        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...
1853
    }
1854
1855
    /**
1856
     * Obtain record/object identificator code: or id:
1857 23
     * Vrací identifikátor objektu code: nebo id:
1858
     *
1859 23
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1860
     * 
1861
     * @return string indentifikátor záznamu reprezentovaného objektem
1862
     */
1863
    public function __toString()
1864
    {
1865
        return strval($this->getRecordIdent());
1866
    }
1867
1868
    /**
1869
     * Gives you FlexiPeeHP class name for Given Evidence
1870
     *
1871
     * @param string $evidence
1872
     * 
1873
     * @return string Class name
1874
     */
1875
    public static function evidenceToClassName($evidence)
1876
    {
1877
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1878
    }
1879
1880
    /**
1881
     * Obtain ID of first record in evidence
1882
     *
1883
     * @return string|null id or null if no records
1884
     */
1885
    public function getFirstRecordID()
1886
    {
1887
        $firstID    = null;
1888
        $keyColumn  = $this->getKeyColumn();
1889
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1890
            ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1891
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1892
            $firstID = current($firstIdRaw)[$keyColumn];
1893
        }
1894
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1895
    }
1896
1897
    /**
1898
     * Vrací hodnotu daného externího ID
1899
     *
1900
     * @param string $want Namespace Selector. If empty,you obtain the first one.
1901
     * 
1902
     * @return string|array one id or array if multiplete
1903
     */
1904
    public function getExternalID($want = null)
1905
    {
1906
        $extid = null;
1907
        $ids   = $this->getDataValue('external-ids');
1908
        if (is_null($want)) {
1909
            if (!empty($ids)) {
1910
                $extid = current($ids);
1911
            }
1912
        } else {
1913
            if (!is_null($ids) && is_array($ids)) {
1914
                foreach ($ids as $id) {
1915
                    if (strstr($id, 'ext:'.$want)) {
1916
                        if (is_null($extid)) {
1917
                            $extid = str_replace('ext:'.$want.':', '', $id);
1918
                        } else {
1919
                            if (is_array($extid)) {
1920
                                $extid[] = str_replace('ext:'.$want.':', '', $id);
1921
                            } else {
1922
                                $extid = [$extid, str_replace('ext:'.$want.':',
1923
                                        '', $id)];
1924
                            }
1925
                        }
1926
                    }
1927
                }
1928
            }
1929
        }
1930
        return $extid;
1931
    }
1932
1933
    /**
1934
     * Obtain actual GlobalVersion
1935
     * Vrací aktuální globální verzi změn
1936
     *
1937
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1938
     * 
1939
     * @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...
1940
     */
1941
    public function getGlobalVersion()
1942
    {
1943
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
1944
1945
        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...
1946
    }
1947
1948
    /**
1949
     * Gives you current ApiURL with given format suffix
1950
     * 
1951
     * @param string $format json|html|xml|...
1952
     * 
1953
     * @return string API URL for current record or object/evidence
1954
     */
1955
    public function getApiURL($format = null)
1956
    {
1957
        $apiUrl = str_replace(['.'.$this->format, '?limit=0'], '', $this->apiURL);
1958
        return $apiUrl.(empty($format) ? '' : '.'.$format );
1959
    }
1960
1961
    /**
1962
     * Obtain content type of last response
1963
     *
1964
     * @return string
1965
     */
1966
    public function getResponseFormat()
1967
    {
1968
        return $this->responseFormat;
1969
    }
1970
1971
    /**
1972
     * Return the same response format for one and multiplete results
1973
     *
1974
     * @param array $responseBody
1975
     * 
1976
     * @return array
1977
     */
1978
    public function unifyResponseFormat($responseBody)
1979
    {
1980
        if (!is_array($responseBody) || array_key_exists('message',
0 ignored issues
show
introduced by
The condition is_array($responseBody) is always true.
Loading history...
1981
                $responseBody)) { //Unifi response format
1982
            $response = $responseBody;
1983
        } else {
1984
            $evidence = $this->getResponseEvidence();
1985
            if (array_key_exists($evidence, $responseBody)) {
1986
                $response        = [];
1987
                $evidenceContent = $responseBody[$evidence];
1988
                if (array_key_exists(0, $evidenceContent)) {
1989
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1990
                } else {
1991
                    $response[$evidence][0] = $evidenceContent; //One result
1992
                }
1993
            } else {
1994
                if (isset($responseBody['priloha'])) {
1995
                    $response = $responseBody['priloha'];
1996
                } else {
1997
                    if (array_key_exists('results', $responseBody)) {
1998
                        $response = $responseBody['results'];
1999
                    } else {
2000
                        $response = $responseBody;
2001
                    }
2002
                }
2003
            }
2004
        }
2005
        return $response;
2006
    }
2007
2008
    /**
2009
     * Obtain structure for current (or given) evidence
2010
     *
2011
     * @param string $evidence
2012
     * 
2013
     * @return array Evidence structure
2014
     */
2015
    public function getOfflineColumnsInfo($evidence = null)
2016
    {
2017
        $columnsInfo = null;
2018
        $infoSource  = self::$infoDir.'/Properties.'.(empty($evidence) ? $this->getEvidence()
2019
                : $evidence).'.json';
2020
        if (file_exists($infoSource)) {
2021
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2022
        }
2023
        return $columnsInfo;
2024
    }
2025
2026
    /**
2027
     * Obtain Current evidence Live structure
2028
     * 
2029
     * @param string $evidence
2030
     * 
2031
     * @return array structure
2032
     */
2033
    public function getOnlineColumnsInfo($evidence = null)
2034
    {
2035 23
        $properties = [];
2036
        $evidence   = is_null($evidence) ? $this->getEvidence() : $evidence;
2037 23
        $flexinfo   = $this->performRequest('/c/'.$this->company.'/'.$evidence.'/properties.json');
2038 23
        if (count($flexinfo) && array_key_exists('properties', $flexinfo)) {
2039 23
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2040 23
                $key                      = $evidenceProperty['propertyName'];
2041
                $properties[$key]         = $evidenceProperty;
2042
                $properties[$key]['name'] = $evidenceProperty['name'];
2043
                $properties[$key]['type'] = $evidenceProperty['type'];
2044
                if (array_key_exists('url', $evidenceProperty)) {
2045
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2046
                        $evidenceProperty['url']);
2047
                }
2048
            }
2049
        }
2050
        return $properties;
2051
    }
2052
2053
    /**
2054
     * Update evidence info from array or online from properties.json or offline
2055
     * 
2056
     * @param array  $columnsInfo
2057
     * @param string $evidence
2058
     */
2059
    public function updateColumnsInfo($columnsInfo = null, $evidence = null)
2060
    {
2061
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2062
        if (is_null($columnsInfo)) {
2063
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence)
2064
                    : $this->getOnlineColumnsInfo($evidence);
2065
        } else {
2066
            $this->columnsInfo[$evidence] = $columnsInfo;
2067
        }
2068
    }
2069
2070
    /**
2071
     * Gives you evidence structure. You can obtain current online by pre-calling:
2072
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2073
     * 
2074
     * @param string $evidence
2075
     * 
2076
     * @return array
2077
     */
2078
    public function getColumnsInfo($evidence = null)
2079
    {
2080
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2081
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2082
            $this->updateColumnsInfo($evidence,
0 ignored issues
show
Bug introduced by
$evidence of type string is incompatible with the type array expected by parameter $columnsInfo of FlexiPeeHP\FlexiBeeRO::updateColumnsInfo(). ( Ignorable by Annotation )

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

2082
            $this->updateColumnsInfo(/** @scrutinizer ignore-type */ $evidence,
Loading history...
2083
                $this->getOfflineColumnsInfo($evidence));
0 ignored issues
show
Bug introduced by
$this->getOfflineColumnsInfo($evidence) of type array is incompatible with the type string expected by parameter $evidence of FlexiPeeHP\FlexiBeeRO::updateColumnsInfo(). ( Ignorable by Annotation )

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

2083
                /** @scrutinizer ignore-type */ $this->getOfflineColumnsInfo($evidence));
Loading history...
2084
        }
2085
        return $this->columnsInfo[$evidence];
2086
    }
2087
2088
    /**
2089
     * Gives you properties for (current) evidence column
2090
     *
2091
     * @param string $column    name of column
2092
     * @param string $evidence  evidence name if different
2093
     *
2094
     * @return array column properties or null if column not exits
2095
     */
2096
    public function getColumnInfo($column, $evidence = null)
2097
    {
2098
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence()
2099
                : $evidence);
2100
        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...
2101
                : null : null;
2102
    }
2103
2104
    /**
2105
     * Obtain actions for current (or given) evidence
2106
     *
2107
     * @param string $evidence
2108
     * 
2109
     * @return array Evidence structure
2110
     */
2111
    public function getActionsInfo($evidence = null)
2112
    {
2113
        $actionsInfo = null;
2114
        if (is_null($evidence)) {
2115
            $evidence = $this->getEvidence();
2116
        }
2117
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2118
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2119
            $actionsInfo = Actions::$$propsName;
2120
        }
2121
        return $actionsInfo;
2122
    }
2123
2124
    /**
2125
     * Obtain relations for current (or given) evidence
2126
     *
2127
     * @param string $evidence
2128
     * 
2129
     * @return array Evidence structure
2130
     */
2131
    public function getRelationsInfo($evidence = null)
2132
    {
2133
        $relationsInfo = null;
2134
        if (is_null($evidence)) {
2135
            $evidence = $this->getEvidence();
2136
        }
2137
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2138
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2139
            $relationsInfo = Relations::$$propsName;
2140
        }
2141
        return $relationsInfo;
2142
    }
2143
2144
    /**
2145
     * Obtain info for current (or given) evidence
2146
     *
2147
     * @param string $evidence
2148
     * 
2149
     * @return array Evidence info
2150
     */
2151
    public function getEvidenceInfo($evidence = null)
2152
    {
2153
        $evidencesInfo = null;
2154
        if (is_null($evidence)) {
2155
            $evidence = $this->getEvidence();
2156
        }
2157
        if (isset(EvidenceList::$evidences[$evidence])) {
2158
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2159
            $propsName     = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2160
            if (isset(Formats::$$propsName)) {
2161
                $evidencesInfo['formats'] = Formats::$$propsName;
2162
            }
2163
        }
2164
        return $evidencesInfo;
2165
    }
2166
2167
    /**
2168
     * Obtain name for current (or given) evidence path
2169
     *
2170
     * @param string $evidence Evidence Path
2171
     * 
2172
     * @return array Evidence info
2173
     */
2174
    public function getEvidenceName($evidence = null)
2175
    {
2176
        $evidenceName = null;
2177
        if (is_null($evidence)) {
2178
            $evidence = $this->getEvidence();
2179
        }
2180
        if (isset(EvidenceList::$name[$evidence])) {
2181
            $evidenceName = EvidenceList::$name[$evidence];
2182
        }
2183
        return $evidenceName;
2184
    }
2185
2186
    /**
2187
     * Save current object to file
2188
     *
2189
     * @param string $destfile path to file
2190
     */
2191
    public function saveResponseToFile($destfile)
2192
    {
2193
        if (strlen($this->lastCurlResponse)) {
2194
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2195
        }
2196
        file_put_contents($destfile, $this->lastCurlResponse);
2197
    }
2198
2199
    /**
2200
     * Obtain established relations listing
2201
     *
2202
     * @return array Null or Relations
2203
     */
2204
    public function getVazby($id = null)
2205
    {
2206
        if (is_null($id)) {
2207
            $id = $this->getRecordID();
2208
        }
2209
        if (!empty($id)) {
2210
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2211
                ['relations' => 'vazby', 'id' => $id]);
2212
            $vazby    = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby']
2213
                    : null;
2214
        } else {
2215
            throw new \Exception(_('ID requied to get record relations '));
2216
        }
2217
        return $vazby;
2218
    }
2219
2220
    /**
2221
     * Gives You URL for Current Record in FlexiBee web interface
2222
     *
2223
     * @return string url
2224
     */
2225
    public function getFlexiBeeURL()
2226
    {
2227
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
2228
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
2229
                : '';
2230
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2231
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
2232
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2233
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
2234
        $pass       = ($user || $pass) ? "$pass@" : '';
2235
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2236
        return $scheme.$user.$pass.$host.$port.$path;
2237
    }
2238
2239
    /**
2240
     * Set Record Key
2241
     *
2242
     * @param int|string $myKeyValue
2243
     * 
2244
     * @return boolean
2245
     */
2246
    public function setMyKey($myKeyValue)
2247
    {
2248
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2249
            $extIds = $this->getDataValue('external-ids');
2250
            if (!empty($extIds) && count($extIds)) {
2251
                $extIds = array_combine($extIds, $extIds);
2252
            }
2253
            $extIds[$myKeyValue] = $myKeyValue;
2254
            $res                 = $this->setDataValue('external-ids', $extIds);
2255
        } else {
2256
            $res = parent::setMyKey($myKeyValue);
2257
        }
2258
        $this->updateApiURL();
2259
        return $res;
2260
    }
2261
2262
    /**
2263
     * Set or get ignore not found pages flag
2264
     *
2265
     * @param boolean $ignore set flag to
2266
     *
2267
     * @return boolean get flag state
2268
     */
2269
    public function ignore404($ignore = null)
2270
    {
2271
        if (!is_null($ignore)) {
2272
            $this->ignoreNotFound = $ignore;
2273
        }
2274
        return $this->ignoreNotFound;
2275
    }
2276
2277
    /**
2278
     * Send Document by mail
2279
     *
2280
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2281
     *
2282
     * @param string $to         Email ecipient
2283
     * @param string $subject    Email Subject
2284
     * @param string $body       Email Text
2285
     *
2286
     * @return int http response code
2287
     */
2288
    public function sendByMail($to, $subject, $body, $cc = null)
2289
    {
2290
        $this->setPostFields($body);
2291
2292
        $this->performRequest(rawurlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
2293
            , 'PUT', 'xml');
2294
2295
        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...
2296
    }
2297
2298
    /**
2299
     * Send all unsent Documents by eMail
2300
     *
2301
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2302
     * 
2303
     * @return int http response code
2304
     */
2305
    public function sendUnsent()
2306
    {
2307
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
2308
                'xml');
2309
    }
2310
2311
    /**
2312
     * FlexiBee date to PHP DateTime conversion
2313
     *
2314
     * @param string $flexidate 2017-05-26+02:00
2315
     *
2316
     * @return \DateTime | false
2317
     */
2318
    public static function flexiDateToDateTime($flexidate)
2319
    {
2320
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat.'O'
2321
                    : self::$DateFormat, $flexidate)->setTime(0, 0);
2322
    }
2323
2324
    /**
2325
     * FlexiBee dateTime to PHP DateTime conversion
2326
     *
2327
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2328
     *
2329
     * @return \DateTime | false
2330
     */
2331
    public static function flexiDateTimeToDateTime($flexidatetime)
2332
    {
2333
        if (strchr($flexidatetime, '.')) { //NewFormat
2334
            $format = self::$DateTimeFormat;
2335
        } else { // Old format
2336
            $format = 'Y-m-d\TH:i:s+P';
2337
        }
2338
        return \DateTime::createFromFormat($format, $flexidatetime);
2339
    }
2340
2341
    /**
2342
     * Získá dokument v daném formátu
2343
     * Obtain document in given format
2344
     *
2345
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2346
     *
2347
     * @param string  $format     pdf/csv/xml/json/ ...
2348
     * @param string  $reportName Template used to generate PDF
2349
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2350
     * @param boolean $sign       sign resulting PDF by certificate ?
2351
     *
2352
     * @return string|null filename downloaded or none
2353
     */
2354
    public function getInFormat($format, $reportName = null, $lang = null,
2355
                                $sign = false)
2356
    {
2357
        $response = null;
2358
        if ($this->setFormat($format)) {
2359
            $urlParams = [];
2360
            switch ($format) {
2361
                case 'pdf':
2362
                    switch ($lang) {
2363
                        case 'cs':
2364
                        case 'sk':
2365
                        case 'en':
2366
                        case 'de':
2367
                            $urlParams['report-lang'] = $lang;
2368
                            break;
2369
                        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...
2370
                            break;
2371
                        default:
2372
                            throw new \Ease\Exception('Unknown language '.$lang.' for PDF export');
2373
                            break;
2374
                    }
2375
                    if (boolval($sign) === true) {
2376
                        $urlParams['report-sign'] = 'true';
2377
                    }
2378
                    break;
2379
                case 'html':
2380
                    $urlParams['inDesktopApp'] = 'true';
2381
                    break;
2382
            }
2383
            if (!empty($reportName)) {
2384
                $urlParams['report-name'] = $reportName;
2385
            }
2386
            if (($this->doCurlRequest(\Ease\Shared::addUrlParams($this->apiURL,
2387
                        $urlParams), 'GET') == 200)) {
2388
                $response = $this->lastCurlResponse;
2389
            }
2390
        }
2391
        return $response;
2392
    }
2393
2394
    /**
2395
     * Uloží dokument v daném formátu do složky v systému souborů
2396
     * Save document in given format to directory in filesystem
2397
     *
2398
     * @param string $format  pdf/csv/xml/json/ ...
2399
     * @param string $destDir where to put file (prefix)
2400
     * @param string $reportName Template used to generate PDF
2401
     *
2402
     * @return string|null filename downloaded or none
2403
     */
2404
    public function downloadInFormat($format, $destDir = './',
2405
                                     $reportName = null)
2406
    {
2407
        $fileOnDisk   = null;
2408
        $formatBackup = $this->format;
2409
        if ($this->setFormat($format)) {
2410
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
2411
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Shared::addUrlParams($this->apiURL,
2412
                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2413
                    $this->lastCurlResponse) !== false)) {
2414
                $fileOnDisk = $downloadTo;
2415
            }
2416
            $this->setFormat($formatBackup);
2417
        }
2418
        return $fileOnDisk;
2419
    }
2420
2421
    /**
2422
     * Take data for object
2423
     *
2424
     * @param array $data Data to keep
2425
     * 
2426
     * @return int number of records taken
2427
     */
2428
    public function takeData($data)
2429
    {
2430
        $result = parent::takeData($data);
2431
        if (array_key_exists($this->getKeyColumn(), $data) || array_key_exists('kod',
2432
                $data)) {
2433
            $this->updateApiURL();
2434
        }
2435
        return $result;
2436
    }
2437
2438
    /**
2439
     * Get Current Evidence reports listing
2440
     * 
2441
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2442
     * 
2443
     * @return array
2444
     */
2445
    public function getReportsInfo()
2446
    {
2447
        $reports    = [];
2448
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL().'/reports');
2449
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports'])
2450
            && array_key_exists('report', $reportsRaw['reports']) &&
2451
            !empty($reportsRaw['reports']['report'])) {
2452
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
2453
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2454
            } else {
2455
                $reports = self::reindexArrayBy($reportsRaw['reports']['report'],
2456
                        'reportId');
2457
            }
2458
        }
2459
        return $reports;
2460
    }
2461
2462
    /**
2463
     * Request authSessionId from current server
2464
     * 
2465
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2466
     * 
2467
     * @param string $username
2468
     * @param string $password
2469
     * @param string $otp       optional onetime password
2470
     * 
2471
     * @return string authUserId or null in case of problems
2472
     */
2473
    public function requestAuthSessionID($username, $password, $otp = null)
2474
    {
2475
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2476
            'password' => $password] : ['username' => $username, 'password' => $password,
2477
            'otp' => $otp]);
2478
        $response         = $this->performRequest('/login-logout/login', 'POST',
2479
            'json');
2480
        if (array_key_exists('refreshToken', $response)) {
2481
            $this->refreshToken = $response['refreshToken'];
2482
        } else {
2483
            $this->refreshToken = null;
2484
        }
2485
        return array_key_exists('authSessionId', $response) ? $response['authSessionId']
2486
                : null;
2487
    }
2488
2489
    /**
2490
     * Try to Sign in current user to FlexiBee and keep authSessionId
2491
     * 
2492
     * @return boolen sign in success
2493
     */
2494
    public function login()
2495
    {
2496
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2497
            $this->password);
2498
        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 FlexiPeeHP\boolen.
Loading history...
2499
    }
2500
2501
    /**
2502
     * End (current's user) session
2503
     * 
2504
     * 
2505
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2506
     * 
2507
     * @param string $username force username to sign off
2508
     * 
2509
     * @return array server response
2510
     */
2511
    public function logout($username = null)
2512
    {
2513
        return $this->performRequest('/status/user/'.(is_null($username) ? $this->user
2514
                    : $username).'/logout', 'POST');
2515
    }
2516
2517
    /**
2518
     * Compile and send Report about Error500 to FlexiBee developers
2519
     * If FlexiBee is running on localost try also include java backtrace
2520
     *
2521
     * @param array $errorResponse result of parseError();
2522
     */
2523
    public function error500Reporter($errorResponse)
2524
    {
2525
        $ur = str_replace('/c/'.$this->company, '',
2526
            str_replace($this->url, '', $this->curlInfo['url']));
2527
        if (!array_key_exists($ur, $this->reports)) {
2528
            $tmpdir   = sys_get_temp_dir();
2529
            $myTime   = $this->curlInfo['when'];
2530
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
2531
            file_put_contents($curlname,
2532
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2533
2534
            $report = new \Ease\Mailer($this->reportRecipient,
2535
                'Error report 500 - '.$ur);
2536
2537
            $d     = dir($tmpdir);
2538
            while (false !== ($entry = $d->read())) {
2539
                if (strstr($entry, $myTime)) {
2540
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
2541
                    $mime = Formats::suffixToContentType($ext);
2542
                    $report->addFile($tmpdir.'/'.$entry,
2543
                        empty($mime) ? 'text/plain' : $mime);
2544
                }
2545
            }
2546
            $d->close();
2547
2548
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2549
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
2550
2551
                $fl = fopen('/var/log/'.'flexibee.log', 'r');
2552
                if ($fl) {
0 ignored issues
show
introduced by
$fl is of type resource|false, thus it always evaluated to false.
Loading history...
2553
                    $tracelog = [];
2554
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2555
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
2556
                        $char = fgetc($fl);
2557
                        if ($char === "\n") {
2558
                            $tracelog[] = $output[$ln];
2559
                            if (strstr($output[$ln], $errorResponse['message'])) {
2560
                                break;
2561
                            }
2562
                            $ln++;
2563
                            continue;
2564
                        }
2565
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
2566
                                : '');
2567
                    }
2568
2569
                    $trace     = implode("\n", array_reverse($tracelog));
2570
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
2571
                    file_put_contents($tracefile, $trace);
2572
                    $report->addItem("\n\n".$trace);
2573
                    fclose($fl);
2574
                }
2575
            } else {
2576
                $report->addItem($errorResponse['message']);
2577
            }
2578
2579
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
2580
2581
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
2582
                    JSON_PRETTY_PRINT));
2583
2584
            if ($report->send()) {
2585
                $this->reports[$ur] = $myTime;
2586
            }
2587
        }
2588
    }
2589
2590
    /**
2591
     * Returns code:CODE
2592
     *
2593
     * @param string $code
2594
     *
2595
     * @return string
2596
     */
2597
    public static function code($code)
2598
    {
2599
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:'.strtoupper(self::uncode($code)));
2600
    }
2601
2602
    /**
2603
     * Returns CODE without code: prefix
2604
     *
2605
     * @param string $code
2606
     *
2607
     * @return string
2608
     */
2609
    public static function uncode($code)
2610
    {
2611
        return str_replace(['code:', 'code%3A'], '', $code);
2612
    }
2613
2614
    /**
2615
     * Remove all @ items from array
2616
     *
2617
     * @param array $data original data
2618
     *
2619
     * @return array data without @ columns
2620
     */
2621
    public static function arrayCleanUP($data)
2622
    {
2623
        return array_filter(
2624
            $data,
2625
            function ($key) {
2626
            return !strchr($key, '@');
2627
        }, ARRAY_FILTER_USE_KEY);
2628
    }
2629
2630
    /**
2631
     * Add Info about used user, server and libraries
2632
     *
2633
     * @param string $additions Additional note text
2634
     */
2635
    public function logBanner($additions = null)
2636
    {
2637
        $this->addStatusMessage('FlexiBee '.str_replace('://',
2638
                '://'.$this->user.'@', $this->getApiUrl()).' FlexiPeeHP v'.self::$libVersion.' (FlexiBee '.EvidenceList::$version.') EasePHP Framework v'.\Ease\Atom::$frameworkVersion.' '.$additions,
2639
            'debug');
2640
    }
2641
2642
    /**
2643
     * Reconnect After unserialization
2644
     */
2645
    public function __wakeup()
2646
    {
2647
        parent::__wakeup();
2648
        $this->curlInit();
2649
    }
2650
}
2651