Passed
Push — master ( ae1426...3d4a24 )
by Vítězslav
04:02
created

FlexiBeeRO::addDefaultUrlParams()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * FlexiPeeHP - Read Only Access to FlexiBee class.
4
 *
5
 * @author     Vítězslav Dvořák <[email protected]>
6
 * @copyright  (C) 2015-2018 Spoje.Net
7
 */
8
9
namespace FlexiPeeHP;
10
11
/**
12
 * Základní třída pro čtení z FlexiBee
13
 *
14
 * @url https://demo.flexibee.eu/devdoc/
15
 */
16
class FlexiBeeRO extends \Ease\Sand
17
{
18
    /**
19
     * Where to get JSON files with evidence stricture etc.
20
     * @var string
21
     */
22
    public static $infoDir = __DIR__.'/../../static';
23
24
    /**
25
     * Version of FlexiPeeHP library
26
     *
27
     * @var string
28
     */
29
    public static $libVersion = '1.17';
30
31
    /**
32
     * Základní namespace pro komunikaci s FlexiBee.
33
     * Basic namespace for communication with FlexiBee
34
     *
35
     * @var string Jmený prostor datového bloku odpovědi
36
     */
37
    public $nameSpace = 'winstrom';
38
39
    /**
40
     * URL of object data in FlexiBee
41
     * @var string url
42
     */
43
    public $apiURL = null;
44
45
    /**
46
     * Datový blok v poli odpovědi.
47
     * Data block in response field.
48
     *
49
     * @var string
50
     */
51
    public $resultField = 'results';
52
53
    /**
54
     * Verze protokolu použitého pro komunikaci.
55
     * Communication protocol version used.
56
     *
57
     * @var string Verze použitého API
58
     */
59
    public $protoVersion = '1.0';
60
61
    /**
62
     * Evidence užitá objektem.
63
     * Evidence used by object
64
     *
65
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
66
     * @var string
67
     */
68
    public $evidence = null;
69
70
    /**
71
     * Výchozí formát pro komunikaci.
72
     * Default communication format.
73
     *
74
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
75
     *
76
     * @var string json|xml|...
77
     */
78
    public $format = 'json';
79
80
    /**
81
     * formát příchozí odpovědi
82
     * response format
83
     *
84
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
85
     *
86
     * @var string json|xml|...
87
     */
88
    public $responseFormat = 'json';
89
90
    /**
91
     * Curl Handle.
92
     *
93
     * @var resource
94
     */
95
    public $curl = null;
96
97
    /**
98
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
99
     * @var string
100
     */
101
    public $company = null;
102
103
    /**
104
     * Server[:port]
105
     * @var string
106
     */
107
    public $url = null;
108
109
    /**
110
     * REST API Username
111
     * @var string
112
     */
113
    public $user = null;
114
115
    /**
116
     * REST API Password
117
     * @var string
118
     */
119
    public $password = null;
120
121
    /**
122
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
123
     */
124
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
125
126
    /**
127
     * Default additional request url parameters after question mark
128
     *
129
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
130
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
131
     * @var array
132
     */
133
    public $defaultUrlParams = ['limit' => 0];
134
135
    /**
136
     * Identifikační řetězec.
137
     *
138
     * @var string
139
     */
140
    public $init = null;
141
142
    /**
143
     * Sloupeček s názvem.
144
     *
145
     * @var string
146
     */
147
    public $nameColumn = 'nazev';
148
149
    /**
150
     * Sloupeček obsahující datum vložení záznamu do shopu.
151
     *
152
     * @var string
153
     */
154
    public $myCreateColumn = 'false';
155
156
    /**
157
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
158
     *
159
     * @var string
160
     */
161
    public $myLastModifiedColumn = 'lastUpdate';
162
163
    /**
164
     * Klíčový idendifikátor záznamu.
165
     *
166
     * @var string
167
     */
168
    public $fbKeyColumn = 'id';
169
170
    /**
171
     * Informace o posledním HTTP requestu.
172
     *
173
     * @var *
174
     */
175
    public $curlInfo;
176
177
    /**
178
     * Informace o poslední HTTP chybě.
179
     *
180
     * @var string
181
     */
182
    public $lastCurlError = null;
183
184
    /**
185
     * Used codes storage.
186
     *
187
     * @var array
188
     */
189
    public $codes = null;
190
191
    /**
192
     * Last Inserted ID.
193
     *
194
     * @var int
195
     */
196
    public $lastInsertedID = null;
197
198
    /**
199
     * Default Line Prefix.
200
     *
201
     * @var string
202
     */
203
    public $prefix = '/c/';
204
205
    /**
206
     * Raw Content of last curl response
207
     *
208
     * @var string
209
     */
210
    public $lastCurlResponse;
211
212
    /**
213
     * HTTP Response code of last request
214
     *
215
     * @var int
216
     */
217
    public $lastResponseCode = null;
218
219
    /**
220
     * Body data  for next curl POST operation
221
     *
222
     * @var string
223
     */
224
    protected $postFields = null;
225
226
    /**
227
     * Last operation result data or message(s)
228
     *
229
     * @var array
230
     */
231
    public $lastResult = null;
232
233
    /**
234
     * Number from  @rowCount in response
235
     * @var int
236
     */
237
    public $rowCount = null;
238
239
    /**
240
     * Number from  @globalVersion
241
     * @var int
242
     */
243
    public $globalVersion = null;
244
245
    /**
246
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
247
     * @var string filter query
248
     */
249
    public $filter;
250
251
    /**
252
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
253
     * @var string
254
     */
255
    protected $action;
256
257
    /**
258
     * Pole akcí které podporuje ta která evidence
259
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
260
     * @var array
261
     */
262
    public $actionsAvailable = null;
263
264
    /**
265
     * Parmetry pro URL
266
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
267
     * @var array
268
     */
269
    public $urlParams = [
270
        'add-global-version',
271
        'add-row-count',
272
        'as-gui',
273
        'auth',
274
        'authSessionId',
275
        'code-as-id',
276
        'code-in-response',
277
        'delimeter',
278
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
279
        'dir',
280
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
281
        'encoding',
282
        'export-settings',
283
        'fail-on-warning',
284
        'filter',
285
        'format',
286
        'idUcetniObdobi',
287
        'includes',
288
        'inDesktopApp', // Note: Undocumented function (html only)
289
        'limit',
290
        'mode',
291
        'no-ext-ids',
292
        'no-http-errors',
293
        'no-ids',
294
        'only-ext-ids',
295
        'order',
296
        'relations',
297
        'report-lang',
298
        'report-name',
299
        'report-sign',
300
        'skupina-stitku',
301
        'sort',
302
        'start',
303
        'stitky-as-ids',
304
        'use-ext-id',
305
        'use-internal-id',
306
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
307
    ];
308
309
    /**
310
     * Session ID
311
     * @var string
312
     */
313
    public $authSessionId = null;
314
315
    /**
316
     * Token obtained during login procedure
317
     * @var string 
318
     */
319
    public $refreshToken = null;
320
321
    /**
322
     * Save 404 results to log ?
323
     * @var boolean
324
     */
325
    protected $ignoreNotFound = false;
326
327
    /**
328
     * Array of errors caused by last request
329
     * @var array
330
     */
331
    private $errors = [];
332
333
    /**
334
     * List of Error500 reports sent
335
     * @var array
336
     */
337
    private $reports = [];
338
339
    /**
340 70
     * Send Error500 Report to
341
     * @var string email address
342 70
     */
343
    public $reportRecipient = '[email protected]';
344 70
345 70
    /**
346 70
     * Formating string for \DateTime::format() for datetime columns
347 70
     * @var string
348 22
     */
349 22
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
350 70
351
    /**
352
     * Formating string for \DateTime::format() for date columns
353
     * @var string
354
     */
355
    static public $DateFormat = 'Y-m-d';
356
357
    /**
358 71
     * Last Request response stats
359
     * @var array 
360 71
     */
361 71
    private $responseStats = null;
362 71
363 71
    /**
364 71
     * Chained Objects
365 23
     * @var array
366 23
     */
367 71
    public $chained = [];
368 71
369 23
    /**
370 23
     * We Connect to server by default
371 71
     * @var boolean
372
     */
373
    public $offline = false;
374 71
375 71
    /**
376 71
     * Override cURL timeout
377
     * @var int seconds
378
     */
379
    public $timeout = null;
380
381
    /**
382
     * Class for read only interaction with FlexiBee.
383
     *
384
     * @param mixed $init default record id or initial data
385 48
     * @param array $options Connection settings and other options override
386
     */
387 48
    public function __construct($init = null, $options = [])
388
    {
389
        $this->init = $init;
390 48
391 48
        parent::__construct();
392 48
        $this->setUp($options);
393
        $this->curlInit();
394 48
        if (!empty($init)) {
395
            $this->processInit($init);
396
        }
397
    }
398
399 94
    /**
400
     * SetUp Object to be ready for work
401 94
     *
402 94
     * @param array $options Object Options ( user,password,authSessionId
403 94
     *                                        company,url,evidence,
404 94
     *                                        prefix,defaultUrlParams,debug,
405 94
     *                                        detail,offline,filter,ignore404
406 94
     *                                        timeout
407 94
     */
408 94
    public function setUp($options = [])
409 94
    {
410 94
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
411
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
412
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
413
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
414
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
415
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
416
        if (!empty($this->authSessionId)) {
417
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
418
        }
419
        if (isset($options['evidence'])) {
420
            $this->setEvidence($options['evidence']);
421
        }
422
        $this->setupProperty($options, 'defaultUrlParams');
423 13
        if (isset($options['prefix'])) {
424
            $this->setPrefix($options['prefix']);
425 13
        }
426 10
        if (array_key_exists('detail', $options)) {
427 13
            $this->defaultUrlParams['detail'] = $options['detail'];
428 13
        }
429 13
        $this->setupProperty($options, 'filter');
430 10
        if (array_key_exists('offline', $options)) {
431 10
            $this->offline = (boolean) $options['offline'];
432 10
        }
433 8
434
        if (array_key_exists('ignore404', $options)) {
435 13
            $this->ignore404($options['ignore404']);
436
        }
437
438
        $this->setupProperty($options, 'debug');
439
        $this->updateApiURL();
440
    }
441
442 23
    /**
443
     * Set up one of properties
444
     *
445 23
     * @param array  $options  array of given properties
446 23
     * @param string $name     name of property to process
447 23
     * @param string $constant load default property value from constant
448 23
     */
449 23
    public function setupProperty($options, $name, $constant = null)
450 23
    {
451 23
        if (array_key_exists($name, $options)) {
452 23
            $this->$name = $options[$name];
453 23
        } else {
454 23
            if (property_exists($this, $name) && !empty($constant) && defined($constant)) {
455 23
                $this->$name = constant($constant);
456 23
            }
457 23
        }
458 23
    }
459 23
460 23
    /**
461 23
     * Get Current connection options for use in another object
462 23
     *
463
     * @return array usable as second constructor parameter
464
     */
465
    public function getConnectionOptions()
466
    {
467
        $conOpts = ['url' => $this->url];
468
        if (empty($this->authSessionId)) {
469
            $conOpts ['user']    = $this->user;
470
            $conOpts['password'] = $this->password;
471 23
        } else {
472
            $conOpts['authSessionId'] = $this->authSessionId;
473 23
        }
474 23
        $company = $this->getCompany();
475
        if (!empty($company)) {
476
            $conOpts['company'] = $company;
477
        }
478
        if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
479
            $conOpts['timeout'] = $this->timeout;
480 23
        }
481 23
        return $conOpts;
482 23
    }
483 23
484 23
    /**
485
     * Inicializace CURL
486
     *
487
     * @return boolean Online Status
488
     */
489
    public function curlInit()
490
    {
491
        if ($this->offline === false) {
492
            $this->curl = \curl_init(); // create curl resource
493
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
494 23
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
495
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
496 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
497 23
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
498 23
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
499 23
            if (empty($this->authSessionId)) {
500
                curl_setopt($this->curl, CURLOPT_USERPWD,
501
                    $this->user.':'.$this->password); // set username and password
502
            }
503 23
            if (!is_null($this->timeout)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
504 23
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
505
            }
506
        }
507 20
        return !$this->offline;
508 20
    }
509
510 20
    /**
511 3
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
512 3
     *
513 3
     *  * 234                              - interní číslo záznamu k načtení
514 3
     *  * code:LOPATA                      - kód záznamu
515 23
     *  * BAGR                             - kód záznamu k načtení
516 23
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
517 23
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
518
     *
519
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
520
     */
521
    public function processInit($init)
522
    {
523
        if (is_integer($init)) {
524
            $this->loadFromFlexiBee($init);
525
        } elseif (is_array($init)) {
526 69
            $this->takeData($init);
527
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
528 69
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init)
529
                            : $init)));
530
        } else {
531
            $this->loadFromFlexiBee($init);
532
        }
533
    }
534
535
    /**
536
     * Set Data Field value
537 23
     *
538
     * @param string $columnName field name
539 23
     * @param mixed  $value      field data value
540 23
     *
541
     * @return bool Success
542
     */
543
    public function setDataValue($columnName, $value)
544
    {
545
        switch ($columnName) {
546
            case 'kod':
547
                $value = self::uncode($value); //Alwyas uncode "kod" column
548 23
                break;
549
            default:
550 23
                break;
551
        }
552
        if (is_object($value)) {
553
            switch (get_class($value)) {
554
                case 'DateTime':
555
                    $columnInfo = $this->getColumnInfo($columnName);
556
                    switch ($columnInfo['type']) {
557
                        case 'date':
558 25
                            $value = self::dateToFlexiDate($value);
559
                            break;
560 25
                        case 'datetime':
561 25
                            $value = self::dateToFlexiDateTime($value);
562
                            break;
563
                    }
564 25
                    break;
565 1
            }
566 1
        }
567 24
        return parent::setDataValue($columnName, $value);
568 24
    }
569 24
570 25
    /**
571 25
     * PHP Date object to FlexiBee date format
572
     * 
573
     * @param \DateTime $date
574
     */
575
    public static function dateToFlexiDate($date)
576
    {
577
        return $date->format(self::$DateFormat);
578
    }
579
580
    /**
581 23
     * PHP Date object to FlexiBee date format
582
     * 
583 23
     * @param \DateTime $dateTime
584 23
     */
585 23
    public static function dateToFlexiDateTime($dateTime)
586 23
    {
587 23
        return $dateTime->format(self::$DateTimeFormat);
588 23
    }
589 23
590 23
    /**
591 23
     * Set URL prefix
592 23
     *
593 23
     * @param string $prefix
594 23
     */
595 23
    public function setPrefix($prefix)
596
    {
597
        switch ($prefix) {
598
            case 'a': //Access
599 23
            case 'c': //Company
600
            case 'u': //User
601
            case 'g': //License Groups
602
            case 'admin':
603
            case 'status':
604
            case 'login-logout':
605
                $this->prefix = '/'.$prefix.'/';
606
                break;
607
            case null:
608
            case '':
609 23
            case '/':
610
                $this->prefix = '';
611 23
                break;
612 23
            default:
613 22
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
614 22
        }
615 23
    }
616 17
617 17
    /**
618 17
     * Set communication format.
619 17
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
620 23
     *
621
     * @param string $format
622
     * 
623
     * @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...
624 23
     */
625
    public function setFormat($format)
626
    {
627
        $result = true;
628
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
629
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
630
                === false) {
631
                $result = false;
632
            }
633
        }
634 68
        if ($result === true) {
635
            $this->format = $format;
636 68
            $this->updateApiURL();
637 68
        }
638 68
        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...
639 62
    }
640 62
641 68
    /**
642
     * Nastaví Evidenci pro Komunikaci.
643
     * Set evidence for communication
644
     *
645
     * @param string $evidence evidence pathName to use
646
     * 
647
     * @return boolean evidence switching status
648
     */
649
    public function setEvidence($evidence)
650
    {
651 23
        switch ($this->prefix) {
652
            case '/c/':
653 23
                if ($this->debug === true) {
654 23
                    if (array_key_exists($evidence, EvidenceList::$name)) {
655 23
                        $this->evidence = $evidence;
656 23
                        $result         = true;
657 23
                    } else {
658 23
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
659 23
                            $evidence));
660 23
                    }
661 23
                } else {
662
                    $this->evidence = $evidence;
663
                    $result         = true;
664
                }
665
                break;
666
            default:
667 48
                $this->evidence = $evidence;
668
                $result         = true;
669 48
                break;
670 48
        }
671 48
        $this->updateApiURL();
672
        return $result;
673
    }
674 48
675 48
    /**
676
     * Vrací právě používanou evidenci pro komunikaci
677
     * Obtain current used evidence
678
     *
679
     * @return string
680
     */
681
    public function getEvidence()
682
    {
683
        return $this->evidence;
684
    }
685
686 23
    /**
687
     * Set used company.
688 23
     * Nastaví Firmu.
689 23
     *
690 23
     * @param string $company
691 23
     */
692 23
    public function setCompany($company)
693 23
    {
694 23
        $this->company = $company;
695 23
    }
696 23
697 23
    /**
698 23
     * Obtain company now used
699 23
     * Vrací právě používanou firmu
700 23
     *
701
     * @return string
702
     */
703 23
    public function getCompany()
704 23
    {
705 23
        return $this->company;
706
    }
707
708 23
    /**
709
     * Vrací název evidence použité v odpovědích z FlexiBee
710
     *
711
     * @return string
712
     */
713
    public function getResponseEvidence()
714
    {
715
        switch ($this->evidence) {
716
            case 'c':
717
                $evidence = 'company';
718 23
                break;
719
            case 'evidence-list':
720 23
                $evidence = 'evidence';
721
                break;
722
            default:
723
                $evidence = $this->getEvidence();
724
                break;
725
        }
726
        return $evidence;
727
    }
728
729
    /**
730
     * Převede rekurzivně Objekt na pole.
731 25
     *
732
     * @param object|array $object
733
     *
734 25
     * @return array
735
     */
736 25
    public static function object2array($object)
737
    {
738 25
        $result = null;
739 4
        if (is_object($object)) {
740 4
            $objectData = get_object_vars($object);
741 22
            if (is_array($objectData) && count($objectData)) {
742
                $result = array_map('self::object2array', $objectData);
743
            }
744 25
        } else {
745
            if (is_array($object)) {
0 ignored issues
show
introduced by
The condition is_array($object) is always true.
Loading history...
746 25
                foreach ($object as $item => $value) {
747 25
                    $result[$item] = self::object2array($value);
748
                }
749
            } else {
750
                $result = $object;
751
            }
752
        }
753
754
        return $result;
755
    }
756
757
    /**
758 3
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
759
     *
760 3
     * @param object|array $object
761
     *
762 3
     * @return array
763 3
     */
764 3
    public static function objectToID($object)
765
    {
766
        $resultID = null;
767
        if (is_object($object) && method_exists($object, '__toString')
768
        ) {
769
            $resultID = $object->__toString();
770
        } else {
771
            if (is_array($object)) {
772
                foreach ($object as $item => $value) {
773 3
                    $resultID[$item] = self::objectToID($value);
774
                }
775 3
            } else { //String
776
                $resultID = $object;
777
            }
778
        }
779
780
        return $resultID;
781
    }
782
783
    /**
784
     * Return basic URL for used Evidence
785 3
     *
786
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
787 3
     *
788 3
     * @return string Evidence URL
789 3
     */
790 3
    public function getEvidenceURL()
791
    {
792
        $evidenceUrl = $this->url.$this->prefix.$this->company;
793 3
        $evidence    = $this->getEvidence();
794
        if (!empty($evidence)) {
795
            $evidenceUrl .= '/'.$evidence;
796
        }
797 3
        return $evidenceUrl;
798
    }
799
800
    /**
801
     * Add suffix to Evidence URL
802
     *
803
     * @param string $urlSuffix
804
     *
805
     * @return string
806
     */
807
    public function evidenceUrlWithSuffix($urlSuffix)
808
    {
809
        $evidenceUrl = $this->getEvidenceUrl();
810
        if (!empty($urlSuffix)) {
811
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
812
                != '?')) {
813
                $evidenceUrl .= '/';
814
            }
815
            $evidenceUrl .= $urlSuffix;
816
        }
817
        return $evidenceUrl;
818
    }
819
820 3
    /**
821
     * Update $this->apiURL
822 3
     */
823
    public function updateApiURL()
824 3
    {
825
        $this->apiURL = $this->getEvidenceURL();
826
        $id           = $this->getRecordID();
827
        if (empty($id)) {
828
            $id = $this->getRecordCode();
829
        }
830
        if (!empty($id)) {
831
            $this->apiURL .= '/'.self::urlEncode($id);
832 3
        }
833 3
        $this->apiURL .= '.'.$this->format;
834 3
    }
835
    /*
836
     * Add Default Url params to given url if not overrided
837 3
     *
838
     * @param string $urlRaw
839
     *
840 3
     * @return string url with default params added
841
     */
842
843
    public function addDefaultUrlParams($urlRaw)
844
    {
845
        return \Ease\Shared::addUrlParams($urlRaw, $this->defaultUrlParams,
846
                false);
847
    }
848
849
    /**
850
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
851
     *
852
     * @param string $urlSuffix část URL za identifikátorem firmy.
853
     * @param string $method    HTTP/REST metoda
854
     * @param string $format    Requested format
855
     * 
856
     * @return array|boolean Výsledek operace
857
     */
858
    public function performRequest($urlSuffix = null, $method = 'GET',
859
                                   $format = null)
860 3
    {
861
        $this->rowCount      = null;
862
        $this->responseStats = [];
863
864
        if (preg_match('/^http/', $urlSuffix)) {
865
            $url = $urlSuffix;
866
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
867
            $url = $this->url.$urlSuffix;
868
        } else {
869
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
870
        }
871
872
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
873
            $method, $format);
874
875
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
876
                    $this->responseFormat), $responseCode);
877
    }
878
879
    /**
880
     * Parse Raw FlexiBee response in several formats
881
     *
882
     * @param string $responseRaw raw response body
883
     * @param string $format      Raw Response format json|xml|etc
884
     *
885
     * @return array
886
     */
887
    public function rawResponseToArray($responseRaw, $format)
888
    {
889
        $responseDecoded = [];
890 3
        if (!empty(trim($responseRaw))) {
891
            switch ($format) {
892 3
                case 'json':
893 3
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
894 3
                    break;
895 3
                case 'xml':
896
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
897 3
                    break;
898
                case 'txt':
899 3
                default:
900
                    $responseDecoded = [$this->lastCurlResponse];
901 3
                    break;
902
            }
903 3
        }
904
        return $responseDecoded;
905 3
    }
906 3
907 3
    /**
908 3
     * Convert FlexiBee Response JSON to Array
909 3
     *
910 3
     * @param string $rawJson
911 3
     *
912 3
     * @return array
913 3
     */
914 3
    public function rawJsonToArray($rawJson)
915 3
    {
916 3
        $responseDecoded = json_decode($rawJson, true, 10);
917 3
        $decodeError     = json_last_error_msg();
918
        if ($decodeError == 'No error') {
919 3
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
920
                $responseDecoded = $responseDecoded[$this->nameSpace];
921
            }
922 3
        } else {
923 3
            $this->addStatusMessage('JSON Decoder: '.$decodeError, 'error');
924 3
            $this->addStatusMessage($rawJson, 'debug');
925 3
        }
926 3
        return $responseDecoded;
927 3
    }
928 3
929 3
    /**
930 3
     * Convert FlexiBee Response XML to Array
931
     *
932
     * @param string $rawXML
933
     *
934
     * @return array
935 3
     */
936
    public function rawXmlToArray($rawXML)
937
    {
938
        return self::xml2array($rawXML);
939 3
    }
940
941
    /**
942
     * Parse Response array
943
     *
944
     * @param array $responseDecoded
945
     * @param int $responseCode Request Response Code
946
     *
947
     * @return array main data part of response
948
     */
949 23
    public function parseResponse($responseDecoded, $responseCode)
950
    {
951 23
        if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
952 23
            $mainResult          = $this->unifyResponseFormat($responseDecoded);
953 23
            $this->responseStats = array_key_exists('stats', $responseDecoded) ? (isset($responseDecoded['stats'][0])
954 23
                    ? $responseDecoded['stats'][0] : $responseDecoded['stats']) : null;
955 15
        } else {
956 15
            $mainResult = $responseDecoded;
957 15
        }
958 23
        switch ($responseCode) {
959
            case 201: //Success Write
960
            case 200: //Success Read
961
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
962
                    $this->lastResult = $mainResult;
963
                    if (isset($responseDecoded['@rowCount'])) {
964
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
965
                    }
966
                    if (isset($responseDecoded['@globalVersion'])) {
967
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
968 23
                    }
969
                }
970 23
                break;
971 23
972 23
            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...
973 23
                if ($this->debug === true) {
974 23
                    $this->error500Reporter($responseDecoded);
975
                }
976 23
            case 404: // Page not found
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
977 23
                if ($this->ignoreNotFound === true) {
978 23
                    break;
979 23
                }
980 23
            case 400: //Bad Request parameters
981
            default: //Something goes wrong
982 23
                $this->addStatusMessage($this->lastResponseCode.': '.$this->curlInfo['url'],
983 23
                    'warning');
984 23
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
985
                    $this->parseError($responseDecoded);
986
                }
987
                $this->logResult($responseDecoded, $this->curlInfo['url']);
988
                break;
989
        }
990 1
        return $mainResult;
991
    }
992 1
993 1
    /**
994 1
     * Parse error message response
995 1
     *
996 1
     * @param array $responseDecoded
997
     * 
998
     * @return int number of errors processed
999
     */
1000
    public function parseError(array $responseDecoded)
1001 1
    {
1002
        if (array_key_exists('results', $responseDecoded)) {
1003 1
            $this->errors = $responseDecoded['results'][0]['errors'];
1004 1
            foreach ($this->errors as $errorInfo) {
1005
                $this->addStatusMessage($errorInfo['message'], 'error');
1006
                if (array_key_exists('for', $errorInfo)) {
1007
                    unset($errorInfo['message']);
1008
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1009
                }
1010
            }
1011
        } else {
1012
            if (array_key_exists('message', $responseDecoded)) {
1013 23
                $this->errors = [['message' => $responseDecoded['message']]];
1014
            }
1015 23
        }
1016 23
        return count($this->errors);
1017 22
    }
1018
1019
    /**
1020
     * Vykonej HTTP požadavek
1021 22
     *
1022
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1023
     * @param string $url    URL požadavku
1024
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1025
     * @param string $format požadovaný formát komunikace
1026
     * 
1027
     * @return int HTTP Response CODE
1028
     */
1029
    public function doCurlRequest($url, $method, $format = null)
1030
    {
1031
        if (is_null($format)) {
1032
            $format = $this->format;
1033
        }
1034
        curl_setopt($this->curl, CURLOPT_URL, $url);
1035
// Nastavení samotné operace
1036
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1037
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1038
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1039
1040
        $httpHeaders = $this->defaultHttpHeaders;
1041
1042
        $formats = Formats::bySuffix();
1043
1044
        if (!isset($httpHeaders['Accept'])) {
1045
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1046
        }
1047
        if (!isset($httpHeaders['Content-Type'])) {
1048
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1049
        }
1050
        $httpHeadersFinal = [];
1051
        foreach ($httpHeaders as $key => $value) {
1052
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1053
                $value .= ' v'.self::$libVersion;
1054
            }
1055
            $httpHeadersFinal[] = $key.': '.$value;
1056
        }
1057
1058
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1059 15
1060
// Proveď samotnou operaci
1061 15
        $this->lastCurlResponse            = curl_exec($this->curl);
1062 15
        $this->curlInfo                    = curl_getinfo($this->curl);
1063
        $this->curlInfo['when']            = microtime();
1064 15
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1065 8
        $this->responseFormat              = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1066 7
            $url);
1067 7
        $this->lastResponseCode            = $this->curlInfo['http_code'];
1068 7
        $this->lastCurlError               = curl_error($this->curl);
1069
        if (strlen($this->lastCurlError)) {
1070 8
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1071 1
                    $this->lastResponseCode, $this->lastCurlError), 'error');
1072 1
        }
1073 8
1074
        if ($this->debug === true) {
1075 15
            $this->saveDebugFiles();
1076 4
        }
1077 4
1078 4
        return $this->lastResponseCode;
1079
    }
1080
1081
    /**
1082
     * Obtain json for application/json
1083 4
     * 
1084
     * @param string $contentType
1085 15
     * @param string $url
1086
     * 
1087 15
     * @return string response format
1088 15
     */
1089
    public function contentTypeToResponseFormat($contentType, $url = null)
1090
    {
1091 15
        if (!empty($url)) {
1092
            $url = parse_url($url, PHP_URL_PATH);
1093 15
        }
1094 15
1095 15
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1096
                strpos($contentType, ';')) : $contentType;
1097 15
1098
        switch ($url) {
1099 15
            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...
1100 15
                $responseFormat = 'json';
1101 15
                break;
1102 9
            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...
1103 9
                switch ($contentTypeClean) {
1104 6
                    case 'text/javascript':
1105 6
                        $responseFormat = 'js';
1106 9
                        break;
1107 6
1108
                    default:
1109
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1110 15
                        break;
1111
                }
1112
                break;
1113
        }
1114
1115
        return $responseFormat;
1116
    }
1117
1118
    /**
1119
     * Nastaví druh prováděné akce.
1120
     *
1121 23
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1122
     * @param string $action
1123 23
     * 
1124 23
     * @return boolean
1125 23
     */
1126 23
    public function setAction($action)
1127 23
    {
1128
        $result           = false;
1129
        $actionsAvailable = $this->getActionsInfo();
1130
        if (is_array($actionsAvailable) && array_key_exists($action,
1131 23
                $actionsAvailable)) {
1132
            $this->action = $action;
1133
            $result       = true;
1134
        }
1135 23
        return $result;
1136 22
    }
1137 22
1138 9
    /**
1139 9
     * Convert XML to array.
1140 22
     *
1141
     * @param string $xml
1142
     *
1143
     * @return array
1144
     */
1145
    public static function xml2array($xml)
1146
    {
1147
        $arr = [];
1148
        if (!empty($xml)) {
1149
            if (is_string($xml)) {
0 ignored issues
show
introduced by
The condition is_string($xml) is always true.
Loading history...
1150
                $xml = simplexml_load_string($xml);
1151 6
            }
1152
            foreach ($xml->attributes() as $a) {
1153
                $arr['@'.$a->getName()] = strval($a);
1154 6
            }
1155 6
            foreach ($xml->children() as $r) {
1156 6
                if (count($r->children()) == 0) {
1157 6
                    $arr[$r->getName()] = strval($r);
1158 6
                } else {
1159
                    $arr[$r->getName()][] = self::xml2array($r);
1160 6
                }
1161
            }
1162
        }
1163
        return $arr;
1164
    }
1165 6
1166
    /**
1167
     * Odpojení od FlexiBee.
1168
     */
1169 6
    public function disconnect()
1170
    {
1171
        if (is_resource($this->curl)) {
1172
            curl_close($this->curl);
1173
        }
1174
        $this->curl = null;
1175
    }
1176
1177 16
    /**
1178
     * Disconnect CURL befere pass away
1179 16
     */
1180 9
    public function __destruct()
1181 9
    {
1182 16
        $this->disconnect();
1183 16
    }
1184 16
1185
    /**
1186 16
     * Načte řádek dat z FlexiBee.
1187 16
     *
1188 16
     * @param int $recordID id požadovaného záznamu
1189 15
     *
1190 15
     * @return array
1191
     */
1192
    public function getFlexiRow($recordID)
1193
    {
1194
        $record   = null;
1195
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
1196
        if (isset($response[$this->evidence])) {
1197
            $record = $response[$this->evidence][0];
1198
        }
1199 15
1200
        return $record;
1201
    }
1202 15
1203 10
    /**
1204 10
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1205 15
     *
1206 15
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1207 15
     * @param array $conditions pole podmínek   - rendrují se do ()
1208 15
     * @param array $urlParams  pole parametrů  - rendrují za ?
1209
     */
1210 14
    public function extractUrlParams(&$conditions, &$urlParams)
1211 14
    {
1212 14
        foreach ($this->urlParams as $urlParam) {
1213 14
            if (isset($conditions[$urlParam])) {
1214 10
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
1215
            }
1216 14
        }
1217 14
    }
1218
1219
    /**
1220
     * convert unicode to entities for use with FlexiBee queries
1221
     *
1222
     * @param string $urlRaw
1223
     * 
1224
     * @return string
1225
     */
1226
    public static function urlEncode($urlRaw)
1227
    {
1228
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1229
    }
1230
1231
    /**
1232
     * Načte data z FlexiBee.
1233
     *
1234
     * @param string $suffix     dotaz
1235
     * @param string|array $conditions Volitelný filtrovací výraz
1236
     *
1237
     * @return array Data obtained
1238
     */
1239
    public function getFlexiData($suffix = null, $conditions = null)
1240
    {
1241
        $finalUrl  = '';
1242
        $urlParams = $this->defaultUrlParams;
1243
1244
        if (!empty($conditions)) {
1245
            if (is_array($conditions)) {
1246
                $this->extractUrlParams($conditions, $urlParams);
1247
                $conditions = $this->flexiUrl($conditions);
1248
            }
1249
1250
            if (strlen($conditions) && ($conditions[0] != '/')) {
1251
                $conditions = '('.self::urlEncode($conditions).')';
1252 15
            }
1253
        }
1254
1255 15
        if (strlen($suffix)) {
1256 15
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1257 15
                $finalUrl = $suffix;
1258
            } else {
1259 15
                if (preg_match('/^(code|ext):(.*)/', $suffix, $matches)) {
1260 15
                    $finalUrl = $matches[1].':'.rawurlencode($matches[2]);
1261 15
                }
1262 15
            }
1263 15
        }
1264 15
1265 15
        $finalUrl .= $conditions;
1266 15
1267
        if (count($urlParams)) {
1268 15
            if (strstr($finalUrl, '?')) {
1269
                $finalUrl .= '&';
1270
            } else {
1271 15
                $finalUrl .= '?';
1272
            }
1273
            $finalUrl .= http_build_query($urlParams, null, '&',
1274 15
                PHP_QUERY_RFC3986);
1275 15
        }
1276 15
1277 15
        $transactions = $this->performRequest($finalUrl, 'GET');
1278 15
1279
        $responseEvidence = $this->getResponseEvidence();
1280 15
        if (is_array($transactions) && array_key_exists($responseEvidence,
1281
                $transactions)) {
1282 15
            $result = $transactions[$responseEvidence];
1283
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
1284 15
                $result = null; // Response is empty Array
1285 9
            }
1286 9
        } else {
1287
            $result = $transactions;
1288 15
        }
1289
1290
        return $result;
1291
    }
1292
1293
    /**
1294
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1295
     * Read FlexiBee record and store it inside od object
1296
     *
1297
     * @param int $id ID or conditions
1298
     *
1299 23
     * @return int počet načtených položek
1300
     */
1301 23
    public function loadFromFlexiBee($id = null)
1302
    {
1303 23
        $data = [];
1304 23
        if (is_null($id)) {
1305 23
            $id = $this->getMyKey();
1306
        }
1307 23
        if (is_array($id)) {
0 ignored issues
show
introduced by
The condition is_array($id) is always false.
Loading history...
1308 23
            $id = rawurlencode('('.self::flexiUrl($id).')');
1309 23
        } else if (preg_match('/^ext:/', $id)) {
1310
            $id = self::urlEncode($id);
1311 23
        } else if (preg_match('/^code:/', $id)) {
1312 23
            $id = self::code(self::urlEncode(self::uncode($id)));
1313 23
        }
1314 23
1315 23
        $flexidata    = $this->getFlexiData($this->getEvidenceUrl().'/'.$id);
1316 23
        $this->apiURL = $this->curlInfo['url'];
1317 23
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1318 23
            $data = current($flexidata);
1319 23
        }
1320 23
        return $this->takeData($data);
1321
    }
1322
1323
    /**
1324 23
     * Set Filter code for requests
1325 23
     *
1326 23
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1327
     *
1328 23
     * @param array|string $filter filter formula or ['key'=>'value']
1329 23
     *
1330 23
     * @return string Filter code
1331 23
     */
1332
    public function setFilter($filter)
1333
    {
1334 23
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1335 23
    }
1336 23
1337 23
    /**
1338 23
     * Převede data do Json formátu pro FlexiBee.
1339 23
     * Convert data to FlexiBee like Json format
1340 23
     *
1341 23
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1342 23
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1343 23
     *
1344 23
     * @param array $data    object data
1345 23
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1346
     *
1347 23
     * @return string
1348 23
     */
1349
    public function getJsonizedData($data = null, $options = 0)
1350 23
    {
1351
        if (is_null($data)) {
1352
            $data = $this->getData();
1353
        }
1354
1355
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1356
            $this->getDataForJSON($data));
1357
        $jsonRaw       = json_encode([$this->nameSpace => $dataToJsonize],
1358
            $options);
1359
1360 23
        return $jsonRaw;
1361
    }
1362 23
1363 23
    /**
1364 23
     * Get Data Fragment specific for current object
1365
     *
1366
     * @param array $data
1367 23
     *
1368 23
     * @return array
1369 23
     */
1370 23
    public function getDataForJSON($data = null)
1371 23
    {
1372
        if (is_null($data)) {
1373
            $data = $this->getData();
1374 23
        }
1375 23
1376 23
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1377
1378 23
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1379 23
            $dataForJson[$this->evidence.'@action'] = $this->action;
1380 23
            $this->action                           = null;
1381 23
        }
1382 23
1383
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1384 23
            $dataForJson[$this->evidence.'@filter'] = $this->filter;
1385 23
        }
1386 23
1387 23
1388 23
        foreach ($this->chained as $chained) {
1389
            $chainedData = $chained->getDataForJSON();
1390 23
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1391 23
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1392 23
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1393 23
                        $dataBackup                          = $dataForJson[$chainedItemEvidence];
1394
                        $dataForJson[$chainedItemEvidence]   = [];
1395
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1396 23
                    }
1397
                    if (array_key_exists(0, $chainedItemData)) {
1398
                        foreach ($chainedItemData as $chainedItem) {
1399 23
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1400
                        }
1401
                    } else {
1402 23
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1403 23
                    }
1404 23
                } else {
1405 23
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1406 23
                }
1407 23
            }
1408
        }
1409
1410
1411
        return $dataForJson;
1412
    }
1413
1414
    /**
1415
     * Join another FlexiPeeHP Object
1416
     *
1417
     * @param FlexiBeeRO $object
1418
     *
1419
     * @return boolean adding to stack success
1420
     */
1421
    public function join(&$object)
1422
    {
1423
        $result = true;
1424
        if (method_exists($object, 'getDataForJSON')) {
1425
            $this->chained[] = $object;
1426
        } else {
1427
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1428
        }
1429
1430
        return $result;
1431
    }
1432
1433
    /**
1434
     * Test if given record ID exists in FlexiBee.
1435
     *
1436
     * @param mixed $identifer presence state
1437
     *
1438
     * @return boolean
1439
     */
1440
    public function idExists($identifer = null)
1441
    {
1442
        if (is_null($identifer)) {
1443
            $identifer = $this->getMyKey();
1444 23
        }
1445
        $ignorestate = $this->ignore404();
1446 23
        $this->ignore404(true);
1447
        $this->getFlexiData(null,
1448 23
            [
1449 23
            'detail' => 'custom:'.$this->getKeyColumn(),
1450 23
            $this->getKeyColumn() => $identifer
1451 23
        ]);
1452 23
        $this->ignore404($ignorestate);
1453 23
        return $this->lastResponseCode == 200;
1454 23
    }
1455 23
1456 23
    /**
1457
     * Test if given record exists in FlexiBee.
1458 23
     *
1459 23
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1460 23
     * 
1461 23
     * @return boolean Record presence status
1462 23
     */
1463
    public function recordExists($data = [])
1464
    {
1465 23
1466 23
        if (empty($data)) {
1467
            $data = $this->getData();
1468
        }
1469 23
        $ignorestate = $this->ignore404();
1470
        $this->ignore404(true);
1471 23
        $keyColumn   = $this->getKeyColumn();
1472 23
        $res         = $this->getColumnsFromFlexibee([$keyColumn],
1473
            is_array($data) ? $data : [$keyColumn => $data]);
1474 23
1475
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false'))
1476
            || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1477 23
            $found = false;
1478 23
        } else {
1479
            $found = true;
1480
        }
1481
        $this->ignore404($ignorestate);
1482
        return $found;
1483
    }
1484
1485
    /**
1486
     * Subitems - ex. items of invoice
1487
     * 
1488
     * @return array of document items or null
1489 65
     */
1490
    public function getSubItems()
1491 65
    {
1492 65
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury')
1493
                : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu')
1494
                : null);
1495 65
    }
1496 65
1497
    /**
1498
     * Vrací z FlexiBee sloupečky podle podmínek.
1499
     *
1500
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1501 65
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1502
     *                                     sloupečku
1503
     * @return array
1504
     */
1505
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1506
    {
1507
        if (is_int($conditions)) {
1508
            $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

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