Completed
Push — master ( b78bd2...cecb0e )
by Vítězslav
03:52
created

FlexiBeeRO::reload()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
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.20.2';
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 = [];
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())
415
                    ? $this->getObjectName() : $this->getRecordIdent().'@'.$this->getObjectName() )
416
                    : $objectName);
417
    }
418
419
    /**
420
     * SetUp Object to be ready for work
421
     *
422
     * @param array $options Object Options ( user,password,authSessionId
423 13
     *                                        company,url,evidence,
424
     *                                        prefix,defaultUrlParams,debug,
425 13
     *                                        detail,offline,filter,ignore404
426 10
     *                                        timeout
427 13
     */
428 13
    public function setUp($options = [])
429 13
    {
430 10
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
431 10
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
432 10
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
433 8
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
434
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
435 13
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
436
        if (!empty($this->authSessionId)) {
437
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
438
        }
439
        if (isset($options['evidence'])) {
440
            $this->setEvidence($options['evidence']);
441
        }
442 23
        $this->setupProperty($options, 'defaultUrlParams');
443
        if (isset($options['prefix'])) {
444
            $this->setPrefix($options['prefix']);
445 23
        }
446 23
        if (array_key_exists('detail', $options)) {
447 23
            $this->defaultUrlParams['detail'] = $options['detail'];
448 23
        }
449 23
        $this->setupProperty($options, 'filter');
450 23
        if (array_key_exists('offline', $options)) {
451 23
            $this->offline = (boolean) $options['offline'];
452 23
        }
453 23
454 23
        if (array_key_exists('ignore404', $options)) {
455 23
            $this->ignore404($options['ignore404']);
456 23
        }
457 23
458 23
        $this->setupProperty($options, 'debug');
459 23
        $this->updateApiURL();
460 23
    }
461 23
462 23
    /**
463
     * Set up one of properties
464
     *
465
     * @param array  $options  array of given properties
466
     * @param string $name     name of property to process
467
     * @param string $constant load default property value from constant
468
     */
469
    public function setupProperty($options, $name, $constant = null)
470
    {
471 23
        if (array_key_exists($name, $options)) {
472
            $this->$name = $options[$name];
473 23
        } else {
474 23
            if (property_exists($this, $name) && !empty($constant) && defined($constant)) {
475
                $this->$name = constant($constant);
476
            }
477
        }
478
    }
479
480 23
    /**
481 23
     * Get Current connection options for use in another object
482 23
     *
483 23
     * @return array usable as second constructor parameter
484 23
     */
485
    public function getConnectionOptions()
486
    {
487
        $conOpts = ['url' => $this->url];
488
        if (empty($this->authSessionId)) {
489
            $conOpts ['user']    = $this->user;
490
            $conOpts['password'] = $this->password;
491
        } else {
492
            $conOpts['authSessionId'] = $this->authSessionId;
493
        }
494 23
        $company = $this->getCompany();
495
        if (!empty($company)) {
496 23
            $conOpts['company'] = $company;
497 23
        }
498 23
        if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
499 23
            $conOpts['timeout'] = $this->timeout;
500
        }
501
        return $conOpts;
502
    }
503 23
504 23
    /**
505
     * Inicializace CURL
506
     *
507 20
     * @return boolean Online Status
508 20
     */
509
    public function curlInit()
510 20
    {
511 3
        if ($this->offline === false) {
512 3
            $this->curl = \curl_init(); // create curl resource
513 3
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
514 3
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
515 23
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
516 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
517 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
518
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
519
            if (empty($this->authSessionId)) {
520
                curl_setopt($this->curl, CURLOPT_USERPWD,
521
                    $this->user.':'.$this->password); // set username and password
522
            }
523
            if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
524
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
525
            }
526 69
        }
527
        return !$this->offline;
528 69
    }
529
530
    /**
531
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
532
     *
533
     *  * 234                              - interní číslo záznamu k načtení
534
     *  * code:LOPATA                      - kód záznamu
535
     *  * BAGR                             - kód záznamu k načtení
536
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
537 23
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
538
     *
539 23
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
540 23
     */
541
    public function processInit($init)
542
    {
543
        if (is_integer($init)) {
544
            $this->loadFromFlexiBee($init);
545
        } elseif (is_array($init)) {
546
            $this->takeData($init);
547
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
548 23
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init)
549
                            : $init)));
550 23
        } else {
551
            $this->loadFromFlexiBee($init);
552
        }
553
    }
554
555
    /**
556
     * Set Data Field value
557
     *
558 25
     * @param string $columnName field name
559
     * @param mixed  $value      field data value
560 25
     *
561 25
     * @return bool Success
562
     */
563
    public function setDataValue($columnName, $value)
564 25
    {
565 1
        switch ($columnName) {
566 1
            case 'kod':
567 24
                $value = self::uncode($value); //Alwyas uncode "kod" column
568 24
                break;
569 24
            default:
570 25
                break;
571 25
        }
572
        if (is_object($value)) {
573
            switch (get_class($value)) {
574
                case 'DateTime':
575
                    $columnInfo = $this->getColumnInfo($columnName);
576
                    switch ($columnInfo['type']) {
577
                        case 'date':
578
                            $value = self::dateToFlexiDate($value);
579
                            break;
580
                        case 'datetime':
581 23
                            $value = self::dateToFlexiDateTime($value);
582
                            break;
583 23
                    }
584 23
                    break;
585 23
            }
586 23
        }
587 23
        return parent::setDataValue($columnName, $value);
588 23
    }
589 23
590 23
    /**
591 23
     * PHP Date object to FlexiBee date format
592 23
     * 
593 23
     * @param \DateTime $date
594 23
     */
595 23
    public static function dateToFlexiDate($date)
596
    {
597
        return $date->format(self::$DateFormat);
598
    }
599 23
600
    /**
601
     * PHP Date object to FlexiBee date format
602
     * 
603
     * @param \DateTime $dateTime
604
     */
605
    public static function dateToFlexiDateTime($dateTime)
606
    {
607
        return $dateTime->format(self::$DateTimeFormat);
608
    }
609 23
610
    /**
611 23
     * Set URL prefix
612 23
     *
613 22
     * @param string $prefix
614 22
     */
615 23
    public function setPrefix($prefix)
616 17
    {
617 17
        switch ($prefix) {
618 17
            case 'a': //Access
619 17
            case 'c': //Company
620 23
            case 'u': //User
621
            case 'g': //License Groups
622
            case 'admin':
623
            case 'status':
624 23
            case 'login-logout':
625
                $this->prefix = '/'.$prefix.'/';
626
                break;
627
            case null:
628
            case '':
629
            case '/':
630
                $this->prefix = '';
631
                break;
632
            default:
633
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
634 68
        }
635
    }
636 68
637 68
    /**
638 68
     * Set communication format.
639 62
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
640 62
     *
641 68
     * @param string $format
642
     * 
643
     * @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...
644
     */
645
    public function setFormat($format)
646
    {
647
        $result = true;
648
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
649
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
650
                === false) {
651 23
                $result = false;
652
            }
653 23
        }
654 23
        if ($result === true) {
655 23
            $this->format = $format;
656 23
            $this->updateApiURL();
657 23
        }
658 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...
659 23
    }
660 23
661 23
    /**
662
     * Nastaví Evidenci pro Komunikaci.
663
     * Set evidence for communication
664
     *
665
     * @param string $evidence evidence pathName to use
666
     * 
667 48
     * @return boolean evidence switching status
668
     */
669 48
    public function setEvidence($evidence)
670 48
    {
671 48
        switch ($this->prefix) {
672
            case '/c/':
673
                if ($this->debug === true) {
674 48
                    if (array_key_exists($evidence, EvidenceList::$name)) {
675 48
                        $this->evidence = $evidence;
676
                        $result         = true;
677
                    } else {
678
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
679
                            $evidence));
680
                    }
681
                } else {
682
                    $this->evidence = $evidence;
683
                    $result         = true;
684
                }
685
                break;
686 23
            default:
687
                $this->evidence = $evidence;
688 23
                $result         = true;
689 23
                break;
690 23
        }
691 23
        $this->updateApiURL();
692 23
        return $result;
693 23
    }
694 23
695 23
    /**
696 23
     * Vrací právě používanou evidenci pro komunikaci
697 23
     * Obtain current used evidence
698 23
     *
699 23
     * @return string
700 23
     */
701
    public function getEvidence()
702
    {
703 23
        return $this->evidence;
704 23
    }
705 23
706
    /**
707
     * Set used company.
708 23
     * Nastaví Firmu.
709
     *
710
     * @param string $company
711
     */
712
    public function setCompany($company)
713
    {
714
        $this->company = $company;
715
    }
716
717
    /**
718 23
     * Obtain company now used
719
     * Vrací právě používanou firmu
720 23
     *
721
     * @return string
722
     */
723
    public function getCompany()
724
    {
725
        return $this->company;
726
    }
727
728
    /**
729
     * Vrací název evidence použité v odpovědích z FlexiBee
730
     *
731 25
     * @return string
732
     */
733
    public function getResponseEvidence()
734 25
    {
735
        switch ($this->evidence) {
736 25
            case 'c':
737
                $evidence = 'company';
738 25
                break;
739 4
            case 'evidence-list':
740 4
                $evidence = 'evidence';
741 22
                break;
742
            default:
743
                $evidence = $this->getEvidence();
744 25
                break;
745
        }
746 25
        return $evidence;
747 25
    }
748
749
    /**
750
     * Převede rekurzivně Objekt na pole.
751
     *
752
     * @param object|array $object
753
     *
754
     * @return array
755
     */
756
    public static function object2array($object)
757
    {
758 3
        $result = null;
759
        if (is_object($object)) {
760 3
            $objectData = get_object_vars($object);
761
            if (is_array($objectData) && count($objectData)) {
762 3
                $result = array_map('self::object2array', $objectData);
763 3
            }
764 3
        } else {
765
            if (is_array($object)) {
0 ignored issues
show
introduced by
The condition is_array($object) is always true.
Loading history...
766
                foreach ($object as $item => $value) {
767
                    $result[$item] = self::object2array($value);
768
                }
769
            } else {
770
                $result = $object;
771
            }
772
        }
773 3
774
        return $result;
775 3
    }
776
777
    /**
778
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
779
     *
780
     * @param object|array $object
781
     *
782
     * @return array
783
     */
784
    public static function objectToID($object)
785 3
    {
786
        $resultID = null;
787 3
        if (is_object($object) && method_exists($object, '__toString')
788 3
        ) {
789 3
            $resultID = $object->__toString();
790 3
        } else {
791
            if (is_array($object)) {
792
                foreach ($object as $item => $value) {
793 3
                    $resultID[$item] = self::objectToID($value);
794
                }
795
            } else { //String
796
                $resultID = $object;
797 3
            }
798
        }
799
800
        return $resultID;
801
    }
802
803
    /**
804
     * Return basic URL for used Evidence
805
     *
806
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
807
     *
808
     * @return string Evidence URL
809
     */
810
    public function getEvidenceURL()
811
    {
812
        $evidenceUrl = $this->url.$this->prefix.$this->company;
813
        $evidence    = $this->getEvidence();
814
        if (!empty($evidence)) {
815
            $evidenceUrl .= '/'.$evidence;
816
        }
817
        return $evidenceUrl;
818
    }
819
820 3
    /**
821
     * Add suffix to Evidence URL
822 3
     *
823
     * @param string $urlSuffix
824 3
     *
825
     * @return string
826
     */
827
    public function evidenceUrlWithSuffix($urlSuffix)
828
    {
829
        $evidenceUrl = $this->getEvidenceUrl();
830
        if (!empty($urlSuffix)) {
831
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
832 3
                != '?')) {
833 3
                $evidenceUrl .= '/';
834 3
            }
835
            $evidenceUrl .= $urlSuffix;
836
        }
837 3
        return $evidenceUrl;
838
    }
839
840 3
    /**
841
     * Update $this->apiURL
842
     */
843
    public function updateApiURL()
844
    {
845
        $this->apiURL = $this->getEvidenceURL();
846
        $id           = $this->getRecordID();
847
        if (empty($id)) {
848
            $id = $this->getRecordCode();
849
        }
850
        if (!empty($id)) {
851
            $this->apiURL .= '/'.self::urlEncode($id);
852
        }
853
        $this->apiURL .= '.'.$this->format;
854
    }
855
    /*
856
     * Add Default Url params to given url if not overrided
857
     *
858
     * @param string $urlRaw
859
     *
860 3
     * @return string url with default params added
861
     */
862
863
    public function addDefaultUrlParams($urlRaw)
864
    {
865
        return \Ease\Shared::addUrlParams($urlRaw, $this->defaultUrlParams,
866
                false);
867
    }
868
869
    /**
870
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
871
     *
872
     * @param string $urlSuffix část URL za identifikátorem firmy.
873
     * @param string $method    HTTP/REST metoda
874
     * @param string $format    Requested format
875
     * 
876
     * @return array|boolean Výsledek operace
877
     */
878
    public function performRequest($urlSuffix = null, $method = 'GET',
879
                                   $format = null)
880
    {
881
        $this->rowCount      = null;
882
        $this->responseStats = [];
883
884
        if (preg_match('/^http/', $urlSuffix)) {
885
            $url = $urlSuffix;
886
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
887
            $url = $this->url.$urlSuffix;
888
        } else {
889
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
890 3
        }
891
892 3
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
893 3
            $method, $format);
894 3
895 3
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
896
                    $this->responseFormat), $responseCode);
897 3
    }
898
899 3
    /**
900
     * Parse Raw FlexiBee response in several formats
901 3
     *
902
     * @param string $responseRaw raw response body
903 3
     * @param string $format      Raw Response format json|xml|etc
904
     *
905 3
     * @return array
906 3
     */
907 3
    public function rawResponseToArray($responseRaw, $format)
908 3
    {
909 3
        $responseDecoded = [];
910 3
        if (!empty(trim($responseRaw))) {
911 3
            switch ($format) {
912 3
                case 'json':
913 3
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
914 3
                    break;
915 3
                case 'xml':
916 3
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
917 3
                    break;
918
                case 'txt':
919 3
                default:
920
                    $responseDecoded = [$this->lastCurlResponse];
921
                    break;
922 3
            }
923 3
        }
924 3
        return $responseDecoded;
925 3
    }
926 3
927 3
    /**
928 3
     * Convert FlexiBee Response JSON to Array
929 3
     *
930 3
     * @param string $rawJson
931
     *
932
     * @return array
933
     */
934
    public function rawJsonToArray($rawJson)
935 3
    {
936
        $responseDecoded = json_decode($rawJson, true, 10);
937
        $decodeError     = json_last_error_msg();
938
        if ($decodeError == 'No error') {
939 3
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
940
                $responseDecoded = $responseDecoded[$this->nameSpace];
941
            }
942
        } else {
943
            $this->addStatusMessage('JSON Decoder: '.$decodeError, 'error');
944
            $this->addStatusMessage($rawJson, 'debug');
945
        }
946
        return $responseDecoded;
947
    }
948
949 23
    /**
950
     * Convert FlexiBee Response XML to Array
951 23
     *
952 23
     * @param string $rawXML
953 23
     *
954 23
     * @return array
955 15
     */
956 15
    public function rawXmlToArray($rawXML)
957 15
    {
958 23
        return self::xml2array($rawXML);
959
    }
960
961
    /**
962
     * Parse Response array
963
     *
964
     * @param array $responseDecoded
965
     * @param int $responseCode Request Response Code
966
     *
967
     * @return array main data part of response
968 23
     */
969
    public function parseResponse($responseDecoded, $responseCode)
970 23
    {
971 23
        if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
972 23
            $mainResult          = $this->unifyResponseFormat($responseDecoded);
973 23
            $this->responseStats = array_key_exists('stats', $responseDecoded) ? (isset($responseDecoded['stats'][0])
974 23
                    ? $responseDecoded['stats'][0] : $responseDecoded['stats']) : null;
975
        } else {
976 23
            $mainResult = $responseDecoded;
977 23
        }
978 23
        switch ($responseCode) {
979 23
            case 201: //Success Write
980 23
            case 200: //Success Read
981
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
982 23
                    $this->lastResult = $mainResult;
983 23
                    if (isset($responseDecoded['@rowCount'])) {
984 23
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
985
                    }
986
                    if (isset($responseDecoded['@globalVersion'])) {
987
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
988
                    }
989
                }
990 1
                break;
991
992 1
            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...
993 1
                if ($this->debug === true) {
994 1
                    $this->error500Reporter($responseDecoded);
995 1
                }
996 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...
997
                if ($this->ignoreNotFound === true) {
998
                    break;
999
                }
1000
            case 400: //Bad Request parameters
1001 1
            default: //Something goes wrong
1002
                $this->addStatusMessage($this->lastResponseCode.': '.$this->curlInfo['url'],
1003 1
                    'warning');
1004 1
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
1005
                    $this->parseError($responseDecoded);
1006
                }
1007
                $this->logResult($responseDecoded, $this->curlInfo['url']);
1008
                break;
1009
        }
1010
        return $mainResult;
1011
    }
1012
1013 23
    /**
1014
     * Parse error message response
1015 23
     *
1016 23
     * @param array $responseDecoded
1017 22
     * 
1018
     * @return int number of errors processed
1019
     */
1020
    public function parseError(array $responseDecoded)
1021 22
    {
1022
        if (array_key_exists('results', $responseDecoded)) {
1023
            $this->errors = $responseDecoded['results'][0]['errors'];
1024
            foreach ($this->errors as $errorInfo) {
1025
                $this->addStatusMessage($errorInfo['message'], 'error');
1026
                if (array_key_exists('for', $errorInfo)) {
1027
                    unset($errorInfo['message']);
1028
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1029
                }
1030
            }
1031
        } else {
1032
            if (array_key_exists('message', $responseDecoded)) {
1033
                $this->errors = [['message' => $responseDecoded['message']]];
1034
            }
1035
        }
1036
        return count($this->errors);
1037
    }
1038
1039
    /**
1040
     * Vykonej HTTP požadavek
1041
     *
1042
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1043
     * @param string $url    URL požadavku
1044
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1045
     * @param string $format požadovaný formát komunikace
1046
     * 
1047
     * @return int HTTP Response CODE
1048
     */
1049
    public function doCurlRequest($url, $method, $format = null)
1050
    {
1051
        if (is_null($format)) {
1052
            $format = $this->format;
1053
        }
1054
        curl_setopt($this->curl, CURLOPT_URL, $url);
1055
// Nastavení samotné operace
1056
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1057
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1058
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1059 15
1060
        $httpHeaders = $this->defaultHttpHeaders;
1061 15
1062 15
        $formats = Formats::bySuffix();
1063
1064 15
        if (!isset($httpHeaders['Accept'])) {
1065 8
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1066 7
        }
1067 7
        if (!isset($httpHeaders['Content-Type'])) {
1068 7
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1069
        }
1070 8
        $httpHeadersFinal = [];
1071 1
        foreach ($httpHeaders as $key => $value) {
1072 1
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1073 8
                $value .= ' v'.self::$libVersion;
1074
            }
1075 15
            $httpHeadersFinal[] = $key.': '.$value;
1076 4
        }
1077 4
1078 4
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1079
1080
// Proveď samotnou operaci
1081
        $this->lastCurlResponse            = curl_exec($this->curl);
1082
        $this->curlInfo                    = curl_getinfo($this->curl);
1083 4
        $this->curlInfo['when']            = microtime();
1084
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1085 15
        $this->responseFormat              = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1086
            $url);
1087 15
        $this->lastResponseCode            = $this->curlInfo['http_code'];
1088 15
        $this->lastCurlError               = curl_error($this->curl);
1089
        if (strlen($this->lastCurlError)) {
1090
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1091 15
                    $this->lastResponseCode, $this->lastCurlError), 'error');
1092
        }
1093 15
1094 15
        if ($this->debug === true) {
1095 15
            $this->saveDebugFiles();
1096
        }
1097 15
1098
        return $this->lastResponseCode;
1099 15
    }
1100 15
1101 15
    /**
1102 9
     * Obtain json for application/json
1103 9
     * 
1104 6
     * @param string $contentType
1105 6
     * @param string $url
1106 9
     * 
1107 6
     * @return string response format
1108
     */
1109
    public function contentTypeToResponseFormat($contentType, $url = null)
1110 15
    {
1111
        if (!empty($url)) {
1112
            $url = parse_url($url, PHP_URL_PATH);
1113
        }
1114
1115
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1116
                strpos($contentType, ';')) : $contentType;
1117
1118
        switch ($url) {
1119
            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...
1120
                $responseFormat = 'json';
1121 23
                break;
1122
            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...
1123 23
                switch ($contentTypeClean) {
1124 23
                    case 'text/javascript':
1125 23
                        $responseFormat = 'js';
1126 23
                        break;
1127 23
1128
                    default:
1129
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1130
                        break;
1131 23
                }
1132
                break;
1133
        }
1134
1135 23
        return $responseFormat;
1136 22
    }
1137 22
1138 9
    /**
1139 9
     * Nastaví druh prováděné akce.
1140 22
     *
1141
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1142
     * @param string $action
1143
     * 
1144
     * @return boolean
1145
     */
1146
    public function setAction($action)
1147
    {
1148
        $result           = false;
1149
        $actionsAvailable = $this->getActionsInfo();
1150
        if (is_array($actionsAvailable) && array_key_exists($action,
1151 6
                $actionsAvailable)) {
1152
            $this->action = $action;
1153
            $result       = true;
1154 6
        }
1155 6
        return $result;
1156 6
    }
1157 6
1158 6
    /**
1159
     * Convert XML to array.
1160 6
     *
1161
     * @param string $xml
1162
     *
1163
     * @return array
1164
     */
1165 6
    public static function xml2array($xml)
1166
    {
1167
        $arr = [];
1168
        if (!empty($xml)) {
1169 6
            if (is_string($xml)) {
0 ignored issues
show
introduced by
The condition is_string($xml) is always true.
Loading history...
1170
                $xml = simplexml_load_string($xml);
1171
            }
1172
            foreach ($xml->attributes() as $a) {
1173
                $arr['@'.$a->getName()] = strval($a);
1174
            }
1175
            foreach ($xml->children() as $r) {
1176
                if (count($r->children()) == 0) {
1177 16
                    $arr[$r->getName()] = strval($r);
1178
                } else {
1179 16
                    $arr[$r->getName()][] = self::xml2array($r);
1180 9
                }
1181 9
            }
1182 16
        }
1183 16
        return $arr;
1184 16
    }
1185
1186 16
    /**
1187 16
     * Odpojení od FlexiBee.
1188 16
     */
1189 15
    public function disconnect()
1190 15
    {
1191
        if (is_resource($this->curl)) {
1192
            curl_close($this->curl);
1193
        }
1194
        $this->curl = null;
1195
    }
1196
1197
    /**
1198
     * Disconnect CURL befere pass away
1199 15
     */
1200
    public function __destruct()
1201
    {
1202 15
        $this->disconnect();
1203 10
    }
1204 10
1205 15
    /**
1206 15
     * Načte řádek dat z FlexiBee.
1207 15
     *
1208 15
     * @param int $recordID id požadovaného záznamu
1209
     *
1210 14
     * @return array
1211 14
     */
1212 14
    public function getFlexiRow($recordID)
1213 14
    {
1214 10
        $record   = null;
1215
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
1216 14
        if (isset($response[$this->evidence])) {
1217 14
            $record = $response[$this->evidence][0];
1218
        }
1219
1220
        return $record;
1221
    }
1222
1223
    /**
1224
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1225
     *
1226
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1227
     * @param array $conditions pole podmínek   - rendrují se do ()
1228
     * @param array $urlParams  pole parametrů  - rendrují za ?
1229
     */
1230
    public function extractUrlParams(&$conditions, &$urlParams)
1231
    {
1232
        foreach ($this->urlParams as $urlParam) {
1233
            if (isset($conditions[$urlParam])) {
1234
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
1235
            }
1236
        }
1237
    }
1238
1239
    /**
1240
     * convert unicode to entities for use with FlexiBee queries
1241
     *
1242
     * @param string $urlRaw
1243
     * 
1244
     * @return string
1245
     */
1246
    public static function urlEncode($urlRaw)
1247
    {
1248
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1249
    }
1250
1251
    /**
1252 15
     * Načte data z FlexiBee.
1253
     *
1254
     * @param string $suffix     dotaz
1255 15
     * @param string|array       $conditions Custom filters or modifiers
1256 15
     *
1257 15
     * @return array Data obtained
1258
     */
1259 15
    public function getFlexiData($suffix = null, $conditions = null)
1260 15
    {
1261 15
        $finalUrl          = '';
1262 15
        $evidenceToRestore = null;
1263 15
        $urlParams         = $this->defaultUrlParams;
1264 15
1265 15
        if (!empty($conditions)) {
1266 15
            if (is_array($conditions)) {
1267
                $this->extractUrlParams($conditions, $urlParams);
1268 15
                if (array_key_exists('evidence', $conditions)) {
1269
                    $evidenceToRestore = $this->getEvidence();
1270
                    $this->setEvidence($conditions['evidence']);
1271 15
                    unset($conditions['evidence']);
1272
                }
1273
                $conditions = $this->flexiUrl($conditions);
1274 15
            }
1275 15
1276 15
            if (strlen($conditions) && ($conditions[0] != '/')) {
1277 15
                $conditions = '('.self::urlEncode($conditions).')';
1278 15
            }
1279
        }
1280 15
1281
        if (strlen($suffix)) {
1282 15
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1283
                $finalUrl = $suffix;
1284 15
            } else {
1285 9
                if (preg_match('/^(code|ext):(.*)/', $suffix)) {
1286 9
                    $finalUrl = self::urlizeId($suffix);
1287
                } else {
1288 15
                    $finalUrl = $suffix;
1289
                }
1290
            }
1291
        }
1292
1293
        $finalUrl .= $conditions;
1294
1295
        if (count($urlParams)) {
1296
            if (strstr($finalUrl, '?')) {
1297
                $finalUrl .= '&';
1298
            } else {
1299 23
                $finalUrl .= '?';
1300
            }
1301 23
            $finalUrl .= http_build_query($urlParams, null, '&',
1302
                PHP_QUERY_RFC3986);
1303 23
        }
1304 23
        
1305 23
        $transactions = $this->performRequest($finalUrl, 'GET');
1306
        $responseEvidence = $this->getResponseEvidence();
1307 23
        if (is_array($transactions) && array_key_exists($responseEvidence,
1308 23
                $transactions)) {
1309 23
            $result = $transactions[$responseEvidence];
1310
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
1311 23
                $result = null; // Response is empty Array
1312 23
            }
1313 23
        } else {
1314 23
            $result = $transactions;
1315 23
        }
1316 23
        if (!is_null($evidenceToRestore)) {
1317 23
            $this->setEvidence($evidenceToRestore);
1318 23
        }
1319 23
        return $result;
1320 23
    }
1321
1322
    /**
1323
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1324 23
     * Read FlexiBee record and store it inside od object
1325 23
     *
1326 23
     * @param int $id ID or conditions
1327
     *
1328 23
     * @return int počet načtených položek
1329 23
     */
1330 23
    public function loadFromFlexiBee($id = null)
1331 23
    {
1332
        $data = [];
1333
        if (is_null($id)) {
1334 23
            $id = $this->getMyKey();
1335 23
        }
1336 23
        $flexidata = $this->getFlexiData($this->getEvidenceUrl().'/'.self::urlizeId($id));
1337 23
        if ($this->lastResponseCode == 200) {
1338 23
            $this->apiURL = $this->curlInfo['url'];
1339 23
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1340 23
                $data = current($flexidata);
1341 23
            }
1342 23
        }
1343 23
        return $this->takeData($data);
1344 23
    }
1345 23
1346
    /**
1347 23
     * Reload current record from FlexiBee
1348 23
     * 
1349
     * @return boolean 
1350 23
     */
1351
    public function reload()
1352
    {
1353
        $id = $this->getRecordIdent();
1354
        $this->dataReset();
1355
        $this->loadFromFlexiBee($id);
0 ignored issues
show
Bug introduced by
It seems like $id can also be of type string; however, parameter $id of FlexiPeeHP\FlexiBeeRO::loadFromFlexiBee() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

1355
        $this->loadFromFlexiBee(/** @scrutinizer ignore-type */ $id);
Loading history...
1356
        return $this->lastResponseCode == 200;
1357
    }
1358
1359
    /**
1360 23
     * Set Filter code for requests
1361
     *
1362 23
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1363 23
     *
1364 23
     * @param array|string $filter filter formula or ['key'=>'value']
1365
     *
1366
     * @return string Filter code
1367 23
     */
1368 23
    public function setFilter($filter)
1369 23
    {
1370 23
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1371 23
    }
1372
1373
    /**
1374 23
     * Převede data do Json formátu pro FlexiBee.
1375 23
     * Convert data to FlexiBee like Json format
1376 23
     *
1377
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1378 23
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1379 23
     *
1380 23
     * @param array $data    object data
1381 23
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1382 23
     *
1383
     * @return string
1384 23
     */
1385 23
    public function getJsonizedData($data = null, $options = 0)
1386 23
    {
1387 23
        if (is_null($data)) {
1388 23
            $data = $this->getData();
1389
        }
1390 23
1391 23
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1392 23
            $this->getDataForJSON($data));
1393 23
        $jsonRaw       = json_encode([$this->nameSpace => $dataToJsonize],
1394
            $options);
1395
1396 23
        return $jsonRaw;
1397
    }
1398
1399 23
    /**
1400
     * Get Data Fragment specific for current object
1401
     *
1402 23
     * @param array $data
1403 23
     *
1404 23
     * @return array
1405 23
     */
1406 23
    public function getDataForJSON($data = null)
1407 23
    {
1408
        if (is_null($data)) {
1409
            $data = $this->getData();
1410
        }
1411
1412
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1413
1414
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1415
            $dataForJson[$this->evidence.'@action'] = $this->action;
1416
            $this->action                           = null;
1417
        }
1418
1419
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1420
            $dataForJson[$this->evidence.'@filter'] = $this->filter;
1421
        }
1422
1423
1424
        foreach ($this->chained as $chained) {
1425
            $chainedData = $chained->getDataForJSON();
1426
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1427
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1428
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1429
                        $dataBackup                          = $dataForJson[$chainedItemEvidence];
1430
                        $dataForJson[$chainedItemEvidence]   = [];
1431
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1432
                    }
1433
                    if (array_key_exists(0, $chainedItemData)) {
1434
                        foreach ($chainedItemData as $chainedItem) {
1435
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1436
                        }
1437
                    } else {
1438
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1439
                    }
1440
                } else {
1441
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1442
                }
1443
            }
1444 23
        }
1445
1446 23
1447
        return $dataForJson;
1448 23
    }
1449 23
1450 23
    /**
1451 23
     * Join another FlexiPeeHP Object
1452 23
     *
1453 23
     * @param FlexiBeeRO $object
1454 23
     *
1455 23
     * @return boolean adding to stack success
1456 23
     */
1457
    public function join(&$object)
1458 23
    {
1459 23
        $result = true;
1460 23
        if (method_exists($object, 'getDataForJSON')) {
1461 23
            $this->chained[] = $object;
1462 23
        } else {
1463
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1464
        }
1465 23
1466 23
        return $result;
1467
    }
1468
1469 23
    /**
1470
     * Prepare record ID to use in URL
1471 23
     * 
1472 23
     * @param mixed $id
1473
     * 
1474 23
     * @return string id ready for use in URL
1475
     */
1476
    public static function urlizeId($id)
1477 23
    {
1478 23
        if (is_array($id)) {
1479
            $id = rawurlencode('('.self::flexiUrl($id).')');
1480
        } else if (preg_match('/^ext:/', $id)) {
1481
            $id = self::urlEncode($id);
1482
        } else if (preg_match('/^code:/', $id)) {
1483
            $id = self::code(self::urlEncode(self::uncode($id)));
1484
        }
1485
        return $id;
1486
    }
1487
1488
    /**
1489 65
     * Test if given record ID exists in FlexiBee.
1490
     *
1491 65
     * @param mixed $identifer presence state
1492 65
     *
1493
     * @return boolean
1494
     */
1495 65
    public function idExists($identifer = null)
1496 65
    {
1497
        if (is_null($identifer)) {
1498
            $identifer = $this->getMyKey();
1499
        }
1500
        $ignorestate = $this->ignore404();
1501 65
        $this->ignore404(true);
1502
        $this->getFlexiData(null,
1503
            [
1504
            'detail' => 'custom:'.$this->getKeyColumn(),
1505
            $this->getKeyColumn() => $identifer
1506
        ]);
1507
        $this->ignore404($ignorestate);
1508
        return $this->lastResponseCode == 200;
1509
    }
1510
1511 71
    /**
1512
     * Test if given record exists in FlexiBee.
1513 71
     *
1514
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1515
     * 
1516
     * @return boolean Record presence status
1517
     */
1518
    public function recordExists($data = [])
1519
    {
1520
1521
        if (empty($data)) {
1522 23
            $data = $this->getData();
1523
        }
1524 23
        $ignorestate = $this->ignore404();
1525
        $this->ignore404(true);
1526
        $keyColumn   = $this->getKeyColumn();
1527
        $res         = $this->getColumnsFromFlexibee([$keyColumn],
1528
            is_array($data) ? $data : [$keyColumn => $data]);
1529
1530
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false'))
1531
            || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1532 15
            $found = false;
1533
        } else {
1534 15
            $found = true;
1535 15
        }
1536 15
        $this->ignore404($ignorestate);
1537 15
        return $found;
1538 15
    }
1539 9
1540 9
    /**
1541 15
     * Subitems - ex. items of invoice
1542
     * 
1543
     * @return array of document items or null
1544
     */
1545
    public function getSubItems()
1546
    {
1547
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury')
1548
                : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu')
1549
                : null);
1550 23
    }
1551
1552 23
    /**
1553 23
     * Vrací z FlexiBee sloupečky podle podmínek.
1554 23
     *
1555 23
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1556 23
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1557 23
     *                                     sloupečku
1558 23
     * @return array
1559 23
     */
1560 23
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1561 23
    {
1562 23
        if (is_int($conditions)) {
1563 23
            $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

1563
            $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...
1564 23
        }
1565 23
1566
        $flexiData = $this->getFlexiData('', $conditions);
1567 23
1568
        if (!is_null($indexBy)) {
1569
            $flexiData = $this->reindexArrayBy($flexiData);
1570
        }
1571
1572
        return $flexiData;
1573
    }
1574
1575
    /**
1576
     * Vrací z FlexiBee sloupečky podle podmínek.
1577 22
     *
1578
     * @param string[] $columnsList seznam položek
1579 22
     * @param array    $conditions  pole podmínek nebo ID záznamu
1580
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1581 21
     *
1582
     * @return array
1583
     */
1584
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1585
                                           $indexBy = null)
1586
    {
1587
        $detail = 'full';
1588
        switch (gettype($columnsList)) {
1589 22
            case 'integer': //Record ID
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1590
                $conditions = [$this->getmyKeyColumn() => $conditions];
1591 22
            case 'array': //Few Conditions
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1592 22
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1593 22
                        $columnsList)) {
1594
                    $columnsList[] = $indexBy;
1595
                }
1596 22
                $columns = implode(',', array_unique($columnsList));
1597
                $detail  = 'custom:'.$columns;
1598
            default:
1599
                switch ($columnsList) {
1600
                    case 'id':
1601
                        $detail = 'id';
1602
                        break;
1603
                    case 'summary':
1604
                        $detail = 'summary';
1605 22
                        break;
1606
                    default:
1607 22
                        break;
1608 22
                }
1609 22
                break;
1610 22
        }
1611 22
1612 22
        $conditions['detail'] = $detail;
1613 22
1614 22
        $flexiData = $this->getFlexiData(null, $conditions);
1615 22
1616 22
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1617 22
                $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1618 22
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1619
        }
1620 22
1621
        return $flexiData;
1622
    }
1623
1624
    /**
1625
     * Vrací kód záznamu.
1626
     * Obtain record CODE
1627
     *
1628
     * @param mixed $data
1629
     *
1630
     * @return string
1631
     */
1632 22
    public function getKod($data = null, $unique = true)
1633
    {
1634
        $kod = null;
1635
1636
        if (is_null($data)) {
1637
            $data = $this->getData();
1638
        }
1639
1640
        if (is_string($data)) {
1641 23
            $data = [$this->nameColumn => $data];
1642
        }
1643 23
1644 23
        if (isset($data['kod'])) {
1645 23
            $kod = $data['kod'];
1646 23
        } else {
1647 16
            if (isset($data[$this->nameColumn])) {
1648 16
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1649 23
                    \Ease\Sand::rip($data[$this->nameColumn]));
1650
            } else {
1651
                if (isset($data[$this->keyColumn])) {
1652
                    $kod = \Ease\Sand::rip($data[$this->keyColumn]);
1653
                }
1654
            }
1655
            $kod = substr($kod, 0, 20);
1656
        }
1657
1658 23
        if (!strlen($kod)) {
1659
            $kod = 'NOTSET';
1660 23
        }
1661 23
1662 23
        if (strlen($kod) > 18) {
1663 23
            $kodfinal = strtoupper(substr($kod, 0, 18));
1664 23
        } else {
1665 23
            $kodfinal = strtoupper($kod);
1666 23
        }
1667 23
1668 23
        if ($unique) {
1669
            $counter = 0;
1670
            if (!empty($this->codes) && count($this->codes)) {
1671
                foreach ($this->codes as $codesearch => $keystring) {
1672
                    if (strstr($codesearch, $kodfinal)) {
1673
                        ++$counter;
1674
                    }
1675
                }
1676
            }
1677 23
            if ($counter) {
1678
                $kodfinal = $kodfinal.$counter;
1679 23
            }
1680 23
1681 23
            $this->codes[$kodfinal] = $kod;
1682 23
        }
1683 23
1684 23
        return self::code($kodfinal);
1685 13
    }
1686 13
1687 23
    /**
1688
     * Write Operation Result.
1689
     *
1690
     * @param array  $resultData
1691
     * @param string $url        URL
1692
     * 
1693
     * @return boolean Log save success
1694
     */
1695
    public function logResult($resultData = null, $url = null)
1696 23
    {
1697
        $logResult = false;
1698 23
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1699 23
            if (isset($resultData['message'])) {
1700 23
                $this->addStatusMessage($resultData['message'], 'warning');
1701 23
            }
1702 23
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1703 16
                'warning');
1704 16
            unset($url);
1705 23
        }
1706
        if (is_null($resultData)) {
1707
            $resultData = $this->lastResult;
1708
        }
1709
        if (isset($url)) {
1710
            $this->logger->addStatusMessage($this->lastResponseCode.':'.urldecode($url));
1711
        }
1712
1713
        if (isset($resultData['results'])) {
1714 23
            if ($resultData['success'] == 'false') {
1715
                $status = 'error';
1716 23
            } else {
1717 23
                $status = 'success';
1718 23
            }
1719 23
            foreach ($resultData['results'] as $result) {
1720 23
                if (isset($result['request-id'])) {
1721 16
                    $rid = $result['request-id'];
1722 16
                } else {
1723 23
                    $rid = '';
1724
                }
1725
                if (isset($result['errors'])) {
1726
                    foreach ($result['errors'] as $error) {
1727
                        $message = $error['message'];
1728
                        if (isset($error['for'])) {
1729
                            $message .= ' for: '.$error['for'];
1730
                        }
1731 23
                        if (isset($error['value'])) {
1732
                            $message .= ' value:'.$error['value'];
1733 23
                        }
1734 1
                        if (isset($error['code'])) {
1735 1
                            $message .= ' code:'.$error['code'];
1736 23
                        }
1737 23
                        $this->addStatusMessage($rid.': '.$message, $status);
1738
                    }
1739
                }
1740
            }
1741
        }
1742
        return $logResult;
1743
    }
1744 20
1745
    /**
1746 20
     * Save RAW Curl Request & Response to files in Temp directory
1747 20
     */
1748 20
    public function saveDebugFiles()
1749 20
    {
1750
        $tmpdir   = sys_get_temp_dir();
1751
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1752
        $reqname  = $tmpdir.'/request-'.$fname;
1753
        $respname = $tmpdir.'/response-'.$fname;
1754
        file_put_contents($reqname, $this->postFields);
1755 20
        file_put_contents($respname, $this->lastCurlResponse);
1756
    }
1757
1758
    /**
1759
     * Připraví data pro odeslání do FlexiBee
1760
     *
1761
     * @param string $data
1762
     */
1763
    public function setPostFields($data)
1764
    {
1765
        $this->postFields = $data;
1766
    }
1767
1768
    /**
1769
     * Get Content ready to be send as POST body
1770
     * @return string
1771
     */
1772
    public function getPostFields()
1773
    {
1774
        return $this->postFields;
1775
    }
1776
1777
    /**
1778
     * Generuje fragment url pro filtrování.
1779
     *
1780
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1781
     *
1782
     * @param array  $data   key=>values; value can bee class DatePeriod
1783
     * @param string $joiner default and/or
1784
     * @param string $defop  default operator
1785
     *
1786
     * @return string
1787
     */
1788
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1789
    {
1790
        $parts = [];
1791
1792
        foreach ($data as $column => $value) {
1793
            if (!is_numeric($column)) {
1794
                if (is_integer($data[$column]) || is_float($data[$column])) {
1795
                    $parts[$column] = $column.' eq \''.$data[$column].'\'';
1796
                } elseif (is_bool($data[$column])) {
1797
                    $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1798
                } elseif (is_null($data[$column])) {
1799
                    $parts[$column] = $column." is null";
1800
                } elseif (is_object($data[$column])) {
1801
                    switch (get_class($data[$column])) {
1802
                        case 'DatePeriod':
1803
                            $parts[$column] = $column." between '".$data[$column]->getStartDate()->format(self::$DateFormat)."' '".$data[$column]->getEndDate()->format(self::$DateFormat)."'";
1804
                            break;
1805
                        case 'DateTime':
1806
                            $parts[$column] = $column." eq '".$data[$column]->format(self::$DateFormat)."'";
1807
                            break;
1808
                        default:
1809
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1810
                            break;
1811
                    }
1812
                } else {
1813
                    switch ($value) {
1814
                        case '!null':
1815
                            $parts[$column] = $column." is not null";
1816
                            break;
1817
                        case 'is empty':
1818
                        case 'is not empty':
1819
                            $parts[$column] = $column.' '.$value;
1820
                            break;
1821
                        default:
1822
                            switch (explode(' ', trim($value))[0]) {
1823
                                case 'like':
1824
                                case 'begins':
1825
                                case 'ends':
1826
                                    $parts[$column] = $column         .= ' '.$value;
1827
                                    break;
1828
                                default:
1829
                                    if ($column == 'stitky') {
1830
                                        $parts[$column] = $column."='".self::code($data[$column])."'";
1831
                                    } else {
1832
                                        $parts[$column] = $column." $defop '".$data[$column]."'";
1833
                                    }
1834
                                    break;
1835
                            }
1836
1837
                            break;
1838
                    }
1839
                }
1840
            } else {
1841
                $parts[] = $value;
1842
            }
1843
        }
1844
        return implode(' '.$joiner.' ', $parts);
1845 23
    }
1846
1847 23
    /**
1848
     * Obtain record/object numeric identificator id:
1849
     * Vrací číselný identifikátor objektu id:
1850
     *
1851
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1852
     *
1853
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1854
     */
1855
    public function getRecordID()
1856
    {
1857 23
        $id = $this->getDataValue('id');
1858
        return is_null($id) ? null : is_numeric($id) ? intval($id) : $id;
1859 23
    }
1860
1861
    /**
1862
     * Obtain record/object identificator code:
1863
     * Vrací identifikátor objektu code:
1864
     *
1865
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1866
     *
1867
     * @return string record code identifier
1868
     */
1869
    public function getRecordCode()
1870
    {
1871
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1872
    }
1873
1874
    /**
1875
     * Obtain record/object identificator extId: code: or id:
1876
     * Vrací identifikátor objektu extId: code: nebo id:
1877
     *
1878
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1879
     *
1880
     * @return string|int|null record code identifier
1881
     */
1882
    public function getRecordIdent()
1883
    {
1884
        $ident = $this->getExternalID();
1885
        if (empty($ident)) {
1886
            $ident = $this->getRecordCode();
1887
        }
1888
        if (empty($ident)) {
1889
            $ident = $this->getRecordID();
1890
        }
1891
        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 integer|null|string.
Loading history...
1892
    }
1893
1894
    /**
1895
     * Obtain record/object identificator code: or id:
1896
     * Vrací identifikátor objektu code: nebo id:
1897
     *
1898
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1899
     * 
1900
     * @return string indentifikátor záznamu reprezentovaného objektem
1901
     */
1902
    public function __toString()
1903
    {
1904
        return strval($this->getRecordIdent());
1905
    }
1906
1907
    /**
1908
     * Gives you FlexiPeeHP class name for Given Evidence
1909
     *
1910
     * @param string $evidence
1911
     * 
1912
     * @return string Class name
1913
     */
1914
    public static function evidenceToClassName($evidence)
1915
    {
1916
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1917
    }
1918
1919
    /**
1920
     * Obtain ID of first record in evidence
1921
     *
1922
     * @return string|null id or null if no records
1923
     */
1924
    public function getFirstRecordID()
1925
    {
1926
        $firstID    = null;
1927
        $keyColumn  = $this->getKeyColumn();
1928
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1929
            ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1930
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1931
            $firstID = current($firstIdRaw)[$keyColumn];
1932
        }
1933
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1934
    }
1935
1936
    /**
1937
     * Vrací hodnotu daného externího ID
1938
     *
1939
     * @param string $want Namespace Selector. If empty,you obtain the first one.
1940
     * 
1941
     * @return string|array one id or array if multiplete
1942
     */
1943
    public function getExternalID($want = null)
1944
    {
1945
        $extid = null;
1946
        $ids   = $this->getDataValue('external-ids');
1947
        if (is_null($want)) {
1948
            if (!empty($ids)) {
1949
                $extid = current($ids);
1950
            }
1951
        } else {
1952
            if (!is_null($ids) && is_array($ids)) {
1953
                foreach ($ids as $id) {
1954
                    if (strstr($id, 'ext:'.$want)) {
1955
                        if (is_null($extid)) {
1956
                            $extid = str_replace('ext:'.$want.':', '', $id);
1957
                        } else {
1958
                            if (is_array($extid)) {
1959
                                $extid[] = str_replace('ext:'.$want.':', '', $id);
1960
                            } else {
1961
                                $extid = [$extid, str_replace('ext:'.$want.':',
1962
                                        '', $id)];
1963
                            }
1964
                        }
1965
                    }
1966
                }
1967
            }
1968
        }
1969
        return $extid;
1970
    }
1971
1972
    /**
1973
     * Obtain actual GlobalVersion
1974
     * Vrací aktuální globální verzi změn
1975
     *
1976
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1977
     * 
1978
     * @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...
1979
     */
1980
    public function getGlobalVersion()
1981
    {
1982
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
1983
1984
        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...
1985
    }
1986
1987
    /**
1988
     * Gives you current ApiURL with given format suffix
1989
     * 
1990
     * @param string $format json|html|xml|...
1991
     * 
1992
     * @return string API URL for current record or object/evidence
1993
     */
1994
    public function getApiURL($format = null)
1995
    {
1996
        $apiUrl = str_replace(['.'.$this->format, '?limit=0'], '', $this->apiURL);
1997
        return $apiUrl.(empty($format) ? '' : '.'.$format );
1998
    }
1999
2000
    /**
2001
     * Obtain content type of last response
2002
     *
2003
     * @return string
2004
     */
2005
    public function getResponseFormat()
2006
    {
2007
        return $this->responseFormat;
2008
    }
2009
2010
    /**
2011
     * Return the same response format for one and multiplete results
2012
     *
2013
     * @param array $responseBody
2014
     * 
2015
     * @return array
2016
     */
2017
    public function unifyResponseFormat($responseBody)
2018
    {
2019
        if (!is_array($responseBody) || array_key_exists('message',
0 ignored issues
show
introduced by
The condition is_array($responseBody) is always true.
Loading history...
2020
                $responseBody)) { //Unifi response format
2021
            $response = $responseBody;
2022
        } else {
2023
            $evidence = $this->getResponseEvidence();
2024
            if (array_key_exists($evidence, $responseBody)) {
2025
                $response        = [];
2026
                $evidenceContent = $responseBody[$evidence];
2027
                if (array_key_exists(0, $evidenceContent)) {
2028
                    $response[$evidence] = $evidenceContent; //Multiplete Results
2029
                } else {
2030
                    $response[$evidence][0] = $evidenceContent; //One result
2031
                }
2032
            } else {
2033
                if (isset($responseBody['priloha'])) {
2034
                    $response = $responseBody['priloha'];
2035 23
                } else {
2036
                    if (array_key_exists('results', $responseBody)) {
2037 23
                        $response = $responseBody['results'];
2038 23
                    } else {
2039 23
                        $response = $responseBody;
2040 23
                    }
2041
                }
2042
            }
2043
        }
2044
        return $response;
2045
    }
2046
2047
    /**
2048
     * Obtain structure for current (or given) evidence
2049
     *
2050
     * @param string $evidence
2051
     * 
2052
     * @return array Evidence structure
2053
     */
2054
    public function getOfflineColumnsInfo($evidence = null)
2055
    {
2056
        $columnsInfo = null;
2057
        $infoSource  = self::$infoDir.'/Properties.'.(empty($evidence) ? $this->getEvidence()
2058
                : $evidence).'.json';
2059
        if (file_exists($infoSource)) {
2060
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2061
        }
2062
        return $columnsInfo;
2063
    }
2064
2065
    /**
2066
     * Obtain Current evidence Live structure
2067
     * 
2068
     * @param string $evidence
2069
     * 
2070
     * @return array structure
2071
     */
2072
    public function getOnlineColumnsInfo($evidence = null)
2073
    {
2074
        $properties = [];
2075
        $evidence   = is_null($evidence) ? $this->getEvidence() : $evidence;
2076
        $flexinfo   = $this->performRequest('/c/'.$this->company.'/'.$evidence.'/properties.json');
2077
        if (count($flexinfo) && array_key_exists('properties', $flexinfo)) {
2078
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2079
                $key                      = $evidenceProperty['propertyName'];
2080
                $properties[$key]         = $evidenceProperty;
2081
                $properties[$key]['name'] = $evidenceProperty['name'];
2082
                $properties[$key]['type'] = $evidenceProperty['type'];
2083
                if (array_key_exists('url', $evidenceProperty)) {
2084
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2085
                        $evidenceProperty['url']);
2086
                }
2087
            }
2088
        }
2089
        return $properties;
2090
    }
2091
2092
    /**
2093
     * Update evidence info from array or online from properties.json or offline
2094
     * 
2095
     * @param array  $columnsInfo
2096
     * @param string $evidence
2097
     */
2098
    public function updateColumnsInfo($columnsInfo = null, $evidence = null)
2099
    {
2100
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2101
        if (is_null($columnsInfo)) {
2102
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence)
2103
                    : $this->getOnlineColumnsInfo($evidence);
2104
        } else {
2105
            $this->columnsInfo[$evidence] = $columnsInfo;
2106
        }
2107
    }
2108
2109
    /**
2110
     * Gives you evidence structure. You can obtain current online by pre-calling:
2111
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2112
     * 
2113
     * @param string $evidence
2114
     * 
2115
     * @return array
2116
     */
2117
    public function getColumnsInfo($evidence = null)
2118
    {
2119
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2120
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2121
            $this->updateColumnsInfo($this->getOfflineColumnsInfo($evidence),
2122
                $evidence);
2123
        }
2124
        return $this->columnsInfo[$evidence];
2125
    }
2126
2127
    /**
2128
     * Gives you properties for (current) evidence column
2129
     *
2130
     * @param string $column    name of column
2131
     * @param string $evidence  evidence name if different
2132
     *
2133
     * @return array column properties or null if column not exits
2134
     */
2135
    public function getColumnInfo($column, $evidence = null)
2136
    {
2137
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence()
2138
                : $evidence);
2139
        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...
2140
                : null : null;
2141
    }
2142
2143
    /**
2144
     * Obtain actions for current (or given) evidence
2145
     *
2146
     * @param string $evidence
2147
     * 
2148
     * @return array Evidence structure
2149
     */
2150
    public function getActionsInfo($evidence = null)
2151
    {
2152
        $actionsInfo = null;
2153
        if (is_null($evidence)) {
2154
            $evidence = $this->getEvidence();
2155
        }
2156
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2157
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2158
            $actionsInfo = Actions::$$propsName;
2159
        }
2160
        return $actionsInfo;
2161
    }
2162
2163
    /**
2164
     * Obtain relations for current (or given) evidence
2165
     *
2166
     * @param string $evidence
2167
     * 
2168
     * @return array Evidence structure
2169
     */
2170
    public function getRelationsInfo($evidence = null)
2171
    {
2172
        $relationsInfo = null;
2173
        if (is_null($evidence)) {
2174
            $evidence = $this->getEvidence();
2175
        }
2176
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2177
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2178
            $relationsInfo = Relations::$$propsName;
2179
        }
2180
        return $relationsInfo;
2181
    }
2182
2183
    /**
2184
     * Obtain info for current (or given) evidence
2185
     *
2186
     * @param string $evidence
2187
     * 
2188
     * @return array Evidence info
2189
     */
2190
    public function getEvidenceInfo($evidence = null)
2191
    {
2192
        $evidencesInfo = null;
2193
        if (is_null($evidence)) {
2194
            $evidence = $this->getEvidence();
2195
        }
2196
        if (isset(EvidenceList::$evidences[$evidence])) {
2197
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2198
            $propsName     = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2199
            if (isset(Formats::$$propsName)) {
2200
                $evidencesInfo['formats'] = Formats::$$propsName;
2201
            }
2202
        }
2203
        return $evidencesInfo;
2204
    }
2205
2206
    /**
2207
     * Obtain name for current (or given) evidence path
2208
     *
2209
     * @param string $evidence Evidence Path
2210
     * 
2211
     * @return array Evidence info
2212
     */
2213
    public function getEvidenceName($evidence = null)
2214
    {
2215
        $evidenceName = null;
2216
        if (is_null($evidence)) {
2217
            $evidence = $this->getEvidence();
2218
        }
2219
        if (isset(EvidenceList::$name[$evidence])) {
2220
            $evidenceName = EvidenceList::$name[$evidence];
2221
        }
2222
        return $evidenceName;
2223
    }
2224
2225
    /**
2226
     * Save current object to file
2227
     *
2228
     * @param string $destfile path to file
2229
     */
2230
    public function saveResponseToFile($destfile)
2231
    {
2232
        if (strlen($this->lastCurlResponse)) {
2233
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2234
        }
2235
        file_put_contents($destfile, $this->lastCurlResponse);
2236
    }
2237
2238
    /**
2239
     * Obtain established relations listing
2240
     *
2241
     * @return array Null or Relations
2242
     */
2243
    public function getVazby($id = null)
2244
    {
2245
        if (is_null($id)) {
2246
            $id = $this->getRecordID();
2247
        }
2248
        if (!empty($id)) {
2249
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2250
                ['relations' => 'vazby', 'id' => $id]);
2251
            $vazby    = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby']
2252
                    : null;
2253
        } else {
2254
            throw new \Exception(_('ID requied to get record relations '));
2255
        }
2256
        return $vazby;
2257
    }
2258
2259
    /**
2260
     * Gives You URL for Current Record in FlexiBee web interface
2261
     *
2262
     * @return string url
2263
     */
2264
    public function getFlexiBeeURL()
2265
    {
2266
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
2267
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
2268
                : '';
2269
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2270
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
2271
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2272
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
2273
        $pass       = ($user || $pass) ? "$pass@" : '';
2274
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2275
        return $scheme.$user.$pass.$host.$port.$path;
2276
    }
2277
2278
    /**
2279
     * Set Record Key
2280
     *
2281
     * @param int|string $myKeyValue
2282
     * 
2283
     * @return boolean
2284
     */
2285
    public function setMyKey($myKeyValue)
2286
    {
2287
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2288
            $extIds = $this->getDataValue('external-ids');
2289
            if (!empty($extIds) && count($extIds)) {
2290
                $extIds = array_combine($extIds, $extIds);
2291
            }
2292
            $extIds[$myKeyValue] = $myKeyValue;
2293
            $res                 = $this->setDataValue('external-ids', $extIds);
2294
        } else {
2295
            $res = parent::setMyKey($myKeyValue);
2296
        }
2297
        $this->updateApiURL();
2298
        return $res;
2299
    }
2300
2301
    /**
2302
     * Set or get ignore not found pages flag
2303
     *
2304
     * @param boolean $ignore set flag to
2305
     *
2306
     * @return boolean get flag state
2307
     */
2308
    public function ignore404($ignore = null)
2309
    {
2310
        if (!is_null($ignore)) {
2311
            $this->ignoreNotFound = $ignore;
2312
        }
2313
        return $this->ignoreNotFound;
2314
    }
2315
2316
    /**
2317
     * Send Document by mail
2318
     *
2319
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2320
     *
2321
     * @param string $to         Email ecipient
2322
     * @param string $subject    Email Subject
2323
     * @param string $body       Email Text
2324
     *
2325
     * @return int http response code
2326
     */
2327
    public function sendByMail($to, $subject, $body, $cc = null)
2328
    {
2329
        $this->setPostFields($body);
2330
2331
        $this->performRequest(rawurlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
2332
            , 'PUT', 'xml');
2333
2334
        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...
2335
    }
2336
2337
    /**
2338
     * Send all unsent Documents by eMail
2339
     *
2340
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2341
     * 
2342
     * @return int http response code
2343
     */
2344
    public function sendUnsent()
2345
    {
2346
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
2347
                'xml');
2348
    }
2349
2350
    /**
2351
     * FlexiBee date to PHP DateTime conversion
2352
     *
2353
     * @param string $flexidate 2017-05-26 or 2017-05-26+02:00
2354
     *
2355
     * @return \DateTime | false
2356
     */
2357
    public static function flexiDateToDateTime($flexidate)
2358
    {
2359
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat.'O'
2360
                    : self::$DateFormat, $flexidate)->setTime(0, 0);
2361
    }
2362
2363
    /**
2364
     * FlexiBee dateTime to PHP DateTime conversion
2365
     *
2366
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2367
     *
2368
     * @return \DateTime | false
2369
     */
2370
    public static function flexiDateTimeToDateTime($flexidatetime)
2371
    {
2372
        if (strchr($flexidatetime, '.')) { //NewFormat
2373
            $format = self::$DateTimeFormat;
2374
        } else { // Old format
2375
            $format = 'Y-m-d\TH:i:s+P';
2376
        }
2377
        return \DateTime::createFromFormat($format, $flexidatetime);
2378
    }
2379
2380
    /**
2381
     * Získá dokument v daném formátu
2382
     * Obtain document in given format
2383
     *
2384
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2385
     *
2386
     * @param string  $format     pdf/csv/xml/json/ ...
2387
     * @param string  $reportName Template used to generate PDF
2388
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2389
     * @param boolean $sign       sign resulting PDF by certificate ?
2390
     *
2391
     * @return string|null filename downloaded or none
2392
     */
2393
    public function getInFormat($format, $reportName = null, $lang = null,
2394
                                $sign = false)
2395
    {
2396
        $response = null;
2397
        if ($this->setFormat($format)) {
2398
            $urlParams = [];
2399
            switch ($format) {
2400
                case 'pdf':
2401
                    switch ($lang) {
2402
                        case 'cs':
2403
                        case 'sk':
2404
                        case 'en':
2405
                        case 'de':
2406
                            $urlParams['report-lang'] = $lang;
2407
                            break;
2408
                        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...
2409
                            break;
2410
                        default:
2411
                            throw new \Ease\Exception('Unknown language '.$lang.' for PDF export');
2412
                            break;
2413
                    }
2414
                    if (boolval($sign) === true) {
2415
                        $urlParams['report-sign'] = 'true';
2416
                    }
2417
                    break;
2418
                case 'html':
2419
                    $urlParams['inDesktopApp'] = 'true';
2420
                    break;
2421
            }
2422
            if (!empty($reportName)) {
2423
                $urlParams['report-name'] = $reportName;
2424
            }
2425
            if (($this->doCurlRequest(\Ease\Shared::addUrlParams($this->apiURL,
2426
                        $urlParams), 'GET') == 200)) {
2427
                $response = $this->lastCurlResponse;
2428
            }
2429
        }
2430
        return $response;
2431
    }
2432
2433
    /**
2434
     * Uloží dokument v daném formátu do složky v systému souborů
2435
     * Save document in given format to directory in filesystem
2436
     *
2437
     * @param string $format  pdf/csv/xml/json/ ...
2438
     * @param string $destDir where to put file (prefix)
2439
     * @param string $reportName Template used to generate PDF
2440
     *
2441
     * @return string|null filename downloaded or none
2442
     */
2443
    public function downloadInFormat($format, $destDir = './',
2444
                                     $reportName = null)
2445
    {
2446
        $fileOnDisk   = null;
2447
        $formatBackup = $this->format;
2448
        if ($this->setFormat($format)) {
2449
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
2450
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Shared::addUrlParams($this->apiURL,
2451
                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2452
                    $this->lastCurlResponse) !== false)) {
2453
                $fileOnDisk = $downloadTo;
2454
            }
2455
            $this->setFormat($formatBackup);
2456
        }
2457
        return $fileOnDisk;
2458
    }
2459
2460
    /**
2461
     * Take data for object
2462
     *
2463
     * @param array $data Data to keep
2464
     * 
2465
     * @return int number of records taken
2466
     */
2467
    public function takeData($data)
2468
    {
2469
        $result = parent::takeData($data);
2470
        if (array_key_exists($this->getKeyColumn(), $data) || array_key_exists('kod',
2471
                $data)) {
2472
            $this->updateApiURL();
2473
        }
2474
        return $result;
2475
    }
2476
2477
    /**
2478
     * Get Current Evidence reports listing
2479
     * 
2480
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2481
     * 
2482
     * @return array
2483
     */
2484
    public function getReportsInfo()
2485
    {
2486
        $reports    = [];
2487
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL().'/reports');
2488
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports'])
2489
            && array_key_exists('report', $reportsRaw['reports']) &&
2490
            !empty($reportsRaw['reports']['report'])) {
2491
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
2492
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2493
            } else {
2494
                $reports = self::reindexArrayBy($reportsRaw['reports']['report'],
2495
                        'reportId');
2496
            }
2497
        }
2498
        return $reports;
2499
    }
2500
2501
    /**
2502
     * Request authSessionId from current server
2503
     * 
2504
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2505
     * 
2506
     * @param string $username
2507
     * @param string $password
2508
     * @param string $otp       optional onetime password
2509
     * 
2510
     * @return string authUserId or null in case of problems
2511
     */
2512
    public function requestAuthSessionID($username, $password, $otp = null)
2513
    {
2514
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2515
            'password' => $password] : ['username' => $username, 'password' => $password,
2516
            'otp' => $otp]);
2517
        $response         = $this->performRequest('/login-logout/login', 'POST',
2518
            'json');
2519
        if (array_key_exists('refreshToken', $response)) {
2520
            $this->refreshToken = $response['refreshToken'];
2521
        } else {
2522
            $this->refreshToken = null;
2523
        }
2524
        return array_key_exists('authSessionId', $response) ? $response['authSessionId']
2525
                : null;
2526
    }
2527
2528
    /**
2529
     * Try to Sign in current user to FlexiBee and keep authSessionId
2530
     * 
2531
     * @return boolen sign in success
2532
     */
2533
    public function login()
2534
    {
2535
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2536
            $this->password);
2537
        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...
2538
    }
2539
2540
    /**
2541
     * End (current's user) session
2542
     * 
2543
     * 
2544
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2545
     * 
2546
     * @param string $username force username to sign off
2547
     * 
2548
     * @return array server response
2549
     */
2550
    public function logout($username = null)
2551
    {
2552
        return $this->performRequest('/status/user/'.(is_null($username) ? $this->user
2553
                    : $username).'/logout', 'POST');
2554
    }
2555
2556
    /**
2557
     * Compile and send Report about Error500 to FlexiBee developers
2558
     * If FlexiBee is running on localost try also include java backtrace
2559
     *
2560
     * @param array $errorResponse result of parseError();
2561
     */
2562
    public function error500Reporter($errorResponse)
2563
    {
2564
        $ur = str_replace('/c/'.$this->company, '',
2565
            str_replace($this->url, '', $this->curlInfo['url']));
2566
        if (!array_key_exists($ur, $this->reports)) {
2567
            $tmpdir   = sys_get_temp_dir();
2568
            $myTime   = $this->curlInfo['when'];
2569
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
2570
            file_put_contents($curlname,
2571
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2572
2573
            $report = new \Ease\Mailer($this->reportRecipient,
2574
                'Error report 500 - '.$ur);
2575
2576
            $d     = dir($tmpdir);
2577
            while (false !== ($entry = $d->read())) {
2578
                if (strstr($entry, $myTime)) {
2579
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
2580
                    $mime = Formats::suffixToContentType($ext);
2581
                    $report->addFile($tmpdir.'/'.$entry,
2582
                        empty($mime) ? 'text/plain' : $mime);
2583
                }
2584
            }
2585
            $d->close();
2586
2587
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2588
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
2589
2590
                $fl = fopen('/var/log/'.'flexibee.log', 'r');
2591
                if ($fl) {
0 ignored issues
show
introduced by
$fl is of type false|resource, thus it always evaluated to false.
Loading history...
2592
                    $tracelog = [];
2593
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2594
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
2595
                        $char = fgetc($fl);
2596
                        if ($char === "\n") {
2597
                            $tracelog[] = $output[$ln];
2598
                            if (strstr($output[$ln], $errorResponse['message'])) {
2599
                                break;
2600
                            }
2601
                            $ln++;
2602
                            continue;
2603
                        }
2604
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
2605
                                : '');
2606
                    }
2607
2608
                    $trace     = implode("\n", array_reverse($tracelog));
2609
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
2610
                    file_put_contents($tracefile, $trace);
2611
                    $report->addItem("\n\n".$trace);
2612
                    fclose($fl);
2613
                }
2614
            } else {
2615
                $report->addItem($errorResponse['message']);
2616
            }
2617
2618
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
2619
2620
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
2621
                    JSON_PRETTY_PRINT));
2622
2623
            if ($report->send()) {
2624
                $this->reports[$ur] = $myTime;
2625
            }
2626
        }
2627
    }
2628
2629
    /**
2630
     * Returns code:CODE
2631
     *
2632
     * @param string $code
2633
     *
2634
     * @return string
2635
     */
2636
    public static function code($code)
2637
    {
2638
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:'.strtoupper(self::uncode($code)));
2639
    }
2640
2641
    /**
2642
     * Returns CODE without code: prefix
2643
     *
2644
     * @param string $code
2645
     *
2646
     * @return string
2647
     */
2648
    public static function uncode($code)
2649
    {
2650
        return str_replace(['code:', 'code%3A'], '', $code);
2651
    }
2652
2653
    /**
2654
     * Remove all @ items from array
2655
     *
2656
     * @param array $data original data
2657
     *
2658
     * @return array data without @ columns
2659
     */
2660
    public static function arrayCleanUP($data)
2661
    {
2662
        return array_filter(
2663
            $data,
2664
            function ($key) {
2665
            return !strchr($key, '@');
2666
        }, ARRAY_FILTER_USE_KEY);
2667
    }
2668
2669
    /**
2670
     * Add Info about used user, server and libraries
2671
     *
2672
     * @param string $additions Additional note text
2673
     */
2674
    public function logBanner($additions = null)
2675
    {
2676
        $this->addStatusMessage('FlexiBee '.str_replace('://',
2677
                '://'.$this->user.'@', $this->getApiUrl()).' FlexiPeeHP v'.self::$libVersion.' (FlexiBee '.EvidenceList::$version.') EasePHP Framework v'.\Ease\Atom::$frameworkVersion.' '.$additions,
2678
            'debug');
2679
    }
2680
2681
    /**
2682
     * Reconnect After unserialization
2683
     */
2684
    public function __wakeup()
2685
    {
2686
        parent::__wakeup();
2687
        $this->curlInit();
2688
    }
2689
}
2690