Test Failed
Push — master ( fcbfd8...15faa7 )
by Vítězslav
14:07
created

FlexiBeeRO::loadFromFlexiBee()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 8
nop 1
dl 0
loc 16
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/**
3
 * FlexiPeeHP - Read Only Access to FlexiBee class.
4
 *
5
 * @author     Vítězslav Dvořák <[email protected]>
6
 * @copyright  (C) 2015-2017 Spoje.Net
7
 */
8
9
namespace FlexiPeeHP;
10
11
/**
12
 * Základní třída pro čtení z FlexiBee
13
 *
14
 * @url https://demo.flexibee.eu/devdoc/
15
 */
16
class FlexiBeeRO extends \Ease\Brick
17
{
18
    /**
19
     * Version of FlexiPeeHP library
20
     *
21
     * @var string
22
     */
23
    public static $libVersion = '1.6.4.2';
24
25
    /**
26
     * Základní namespace pro komunikaci s FlexiBee.
27
     * Basic namespace for communication with FlexiBee
28
     *
29
     * @var string Jmený prostor datového bloku odpovědi
30
     */
31
    public $nameSpace = 'winstrom';
32
33
    /**
34
     * URL of object data in FlexiBee
35
     * @var string url
36
     */
37
    public $apiURL = null;
38
39
    /**
40
     * Datový blok v poli odpovědi.
41
     * Data block in response field.
42
     *
43
     * @var string
44
     */
45
    public $resultField = 'results';
46
47
    /**
48
     * Verze protokolu použitého pro komunikaci.
49
     * Communication protocol version used.
50
     *
51
     * @var string Verze použitého API
52
     */
53
    public $protoVersion = '1.0';
54
55
    /**
56
     * Evidence užitá objektem.
57
     * Evidence used by object
58
     *
59
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
60
     * @var string
61
     */
62
    public $evidence = null;
63
64
    /**
65
     * Výchozí formát pro komunikaci.
66
     * Default communication format.
67
     *
68
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
69
     *
70
     * @var string json|xml|...
71
     */
72
    public $format = 'json';
73
74
    /**
75
     * formát příchozí odpovědi
76
     * response format
77
     *
78
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
79
     *
80
     * @var string json|xml|...
81
     */
82
    public $responseFormat = 'json';
83
84
    /**
85
     * Curl Handle.
86
     *
87
     * @var resource
88
     */
89
    public $curl = null;
90
91
    /**
92
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
93
     * @var string
94
     */
95
    public $company = null;
96
97
    /**
98
     * Server[:port]
99
     * @var string
100
     */
101
    public $url = null;
102
103
    /**
104
     * REST API Username
105
     * @var string
106
     */
107
    public $user = null;
108
109
    /**
110
     * REST API Password
111
     * @var string
112
     */
113
    public $password = null;
114
115
    /**
116
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
117
     */
118
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
119
120
    /**
121
     * Default additional request url parameters after question mark
122
     *
123
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
124
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
125
     * @var array
126
     */
127
    public $defaultUrlParams = ['limit' => 0];
128
129
    /**
130
     * Identifikační řetězec.
131
     *
132
     * @var string
133
     */
134
    public $init = null;
135
136
    /**
137
     * Sloupeček s názvem.
138
     *
139
     * @var string
140
     */
141
    public $nameColumn = 'nazev';
142
143
    /**
144
     * Sloupeček obsahující datum vložení záznamu do shopu.
145
     *
146
     * @var string
147
     */
148
    public $myCreateColumn = 'false';
149
150
    /**
151
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
152
     *
153
     * @var string
154
     */
155
    public $myLastModifiedColumn = 'lastUpdate';
156
157
    /**
158
     * Klíčový idendifikátor záznamu.
159
     *
160
     * @var string
161
     */
162
    public $fbKeyColumn = 'id';
163
164
    /**
165
     * Informace o posledním HTTP requestu.
166
     *
167
     * @var *
168
     */
169
    public $curlInfo;
170
171
    /**
172
     * Informace o poslední HTTP chybě.
173
     *
174
     * @var string
175
     */
176
    public $lastCurlError = null;
177
178
    /**
179
     * Used codes storage.
180
     *
181
     * @var array
182
     */
183
    public $codes = null;
184
185
    /**
186
     * Last Inserted ID.
187
     *
188
     * @var int
189
     */
190
    public $lastInsertedID = null;
191
192
    /**
193
     * Default Line Prefix.
194
     *
195
     * @var string
196
     */
197
    public $prefix = '/c/';
198
199
    /**
200
     * Raw Content of last curl response
201
     *
202
     * @var string
203
     */
204
    public $lastCurlResponse;
205
206
    /**
207
     * HTTP Response code of last request
208
     *
209
     * @var int
210
     */
211
    public $lastResponseCode = null;
212
213
    /**
214
     * Body data  for next curl POST operation
215
     *
216
     * @var string
217
     */
218
    protected $postFields = null;
219
220
    /**
221
     * Last operation result data or message(s)
222
     *
223
     * @var array
224
     */
225
    public $lastResult = null;
226
227
    /**
228
     * Nuber from  @rowCount
229
     * @var int
230
     */
231
    public $rowCount = null;
232
233
    /**
234
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
235
     * @var string filter query
236
     */
237
    public $filter;
238
239
    /**
240
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
241
     * @var string
242
     */
243
    protected $action;
244
245
    /**
246
     * Pole akcí které podporuje ta která evidence
247
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
248
     * @var array
249
     */
250
    public $actionsAvailable = null;
251
252
    /**
253
     * Parmetry pro URL
254
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
255
     * @var array
256
     */
257
    public $urlParams = [
258
        'idUcetniObdobi',
259
        'dry-run',
260
        'fail-on-warning',
261
        'report-name',
262
        'report-lang',
263
        'report-sign',
264
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
265
        'mode',
266
        'limit',
267
        'start',
268
        'order',
269
        'sort',
270
        'add-row-count',
271
        'relations',
272
        'includes',
273
        'use-ext-id',
274
        'use-internal-id',
275
        'stitky-as-ids',
276
        'only-ext-ids',
277
        'no-ext-ids',
278
        'no-ids',
279
        'code-as-id',
280
        'no-http-errors',
281
        'export-settings',
282
        'as-gui',
283
        'code-in-response',
284
        'add-global-version',
285
        'encoding',
286
        'delimeter',
287
        'format',
288
        'auth',
289
        'skupina-stitku',
290
        'dir',
291
        'relations',
292
        'relations',
293
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
294
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
295
        'inDesktopApp' // Note: Undocumented function (html only)
296
    ];
297
298
    /**
299
     * Save 404 results to log ?
300
     * @var boolean
301
     */
302
    protected $ignoreNotFound = false;
303
304
    /**
305
     * Array of errors caused by last request
306
     * @var array
307
     */
308
    private $errors = [];
309
310
    /**
311
     * List of Error500 reports sent
312
     * @var array
313
     */
314
    private $reports = [];
315
316
    /**
317
     * Send Error500 Report to
318
     * @var string email address
319
     */
320
    public $reportRecipient = '[email protected]';
321
322
    /**
323
     * Class for read only interaction with FlexiBee.
324
     *
325
     * @param mixed $init default record id or initial data
326
     * @param array $options Connection settings override
327
     */
328
    public function __construct($init = null, $options = [])
329
    {
330
        $this->init = $init;
331
332
        parent::__construct();
333
        $this->setUp($options);
334
        $this->curlInit();
335
        if (!empty($init)) {
336
            $this->processInit($init);
337
        }
338
    }
339
340
    /**
341
     * SetUp Object to be ready for connect
342
     *
343
     * @param array $options Object Options (company,url,user,password,evidence,
344
     *                                       prefix,defaultUrlParams,debug)
345
     */
346
    public function setUp($options = [])
347
    {
348
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
349
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
350
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
351
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
352
        if (isset($options['evidence'])) {
353
            $this->setEvidence($options['evidence']);
354
        }
355
        $this->setupProperty($options, 'defaultUrlParams');
356
        if (isset($options['prefix'])) {
357
            $this->setPrefix($options['prefix']);
358
        }
359
        $this->setupProperty($options, 'debug');
360
        $this->updateApiURL();
361
    }
362
363
    /**
364
     * Set up one of properties
365
     *
366
     * @param array  $options  array of given properties
367
     * @param string $name     name of property to process
368
     * @param string $constant load default property value from constant
369
     */
370
    public function setupProperty($options, $name, $constant = null)
371
    {
372
        if (isset($options[$name])) {
373
            $this->$name = $options[$name];
374
        } else {
375
            if (is_null($this->$name) && !empty($constant) && defined($constant)) {
376
                $this->$name = constant($constant);
377
            }
378
        }
379
    }
380
381
    /**
382
     * Inicializace CURL
383
     */
384
    public function curlInit()
385
    {
386
        $this->curl = \curl_init(); // create curl resource
387
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
388
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
389
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
390
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
391
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
392
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
393
        curl_setopt($this->curl, CURLOPT_USERPWD,
394
            $this->user.':'.$this->password); // set username and password
395
    }
396
397
    /**
398
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
399
     *
400
     *  * 234                              - interní číslo záznamu k načtení
401
     *  * code:LOPATA                      - kód záznamu
402
     *  * BAGR                             - kód záznamu ka načtení
403
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
404
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
405
     *
406
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
407
     */
408
    public function processInit($init)
409
    {
410
        if (is_integer($init)) {
411
            $this->loadFromFlexiBee($init);
412
        } elseif (is_array($init)) {
413
            $this->takeData($init);
414
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
415
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->getEvidenceURL($init)
0 ignored issues
show
Unused Code introduced by
The call to FlexiBeeRO::getEvidenceURL() has too many arguments starting with $init.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
416
                            : $init)));
417
        } else {
418
            $this->loadFromFlexiBee('code:'.str_replace('code:', '', $init));
419
        }
420
    }
421
422
    /**
423
     * Set URL prefix
424
     *
425
     * @param string $prefix
426
     */
427
    public function setPrefix($prefix)
428
    {
429
        switch ($prefix) {
430
            case 'a': //Access
431
            case 'c': //Company
432
            case 'u': //User
433
            case 'g': //License Groups
434
            case 'admin':
435
            case 'status':
436
            case 'login-logout':
437
                $this->prefix = '/'.$prefix.'/';
438
                break;
439
            case null:
440
            case '':
441
            case '/':
442
                $this->prefix = '';
443
                break;
444
            default:
445
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
446
        }
447
    }
448
449
    /**
450
     * Set communication format.
451
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
452
     *
453
     * @param string $format
454
     * @return boolen format is availble
455
     */
456
    public function setFormat($format)
457
    {
458
        $result = true;
459
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
460
            if (array_key_exists($format, array_flip(Formats::$$this->evidence))
461
                === false) {
462
                $result = false;
463
            }
464
        }
465
        if ($result === true) {
466
            $this->format = $format;
467
            $this->updateApiURL();
468
        }
469
        return $result;
470
    }
471
472
    /**
473
     * Nastaví Evidenci pro Komunikaci.
474
     * Set evidence for communication
475
     *
476
     * @param string $evidence evidence pathName to use
477
     * @return boolean evidence switching status
478
     */
479
    public function setEvidence($evidence)
480
    {
481
        switch ($this->prefix) {
482
            case '/c/':
483
                if (array_key_exists($evidence, EvidenceList::$name)) {
484
                    $this->evidence = $evidence;
485
                    $result         = true;
486
                } else {
487
                    throw new \Exception(sprintf('Try to set unsupported evidence %s',
488
                        $evidence));
489
                }
490
                break;
491
            default:
492
                $this->evidence = $evidence;
493
                $result         = true;
494
                break;
495
        }
496
        $this->updateApiURL();
497
        return $result;
498
    }
499
500
    /**
501
     * Vrací právě používanou evidenci pro komunikaci
502
     * Obtain current used evidence
503
     *
504
     * @return string
505
     */
506
    public function getEvidence()
507
    {
508
        return $this->evidence;
509
    }
510
511
    /**
512
     * Set used company.
513
     * Nastaví Firmu.
514
     *
515
     * @param string $company
516
     */
517
    public function setCompany($company)
518
    {
519
        $this->company = $company;
520
    }
521
522
    /**
523
     * Obtain company now used
524
     * Vrací právě používanou firmu
525
     *
526
     * @return string
527
     */
528
    public function getCompany()
529
    {
530
        return $this->company;
531
    }
532
533
    /**
534
     * Vrací název evidence použité v odpovědích z FlexiBee
535
     *
536
     * @return string
537
     */
538
    public function getResponseEvidence()
539
    {
540
        switch ($this->evidence) {
541
            case 'c':
542
                $evidence = 'company';
543
                break;
544
            case 'evidence-list':
545
                $evidence = 'evidence';
546
                break;
547
            default:
548
                $evidence = $this->getEvidence();
549
                break;
550
        }
551
        return $evidence;
552
    }
553
554
    /**
555
     * Převede rekurzivně Objekt na pole.
556
     *
557
     * @param object|array $object
558
     *
559
     * @return array
560
     */
561
    public static function object2array($object)
562
    {
563
        $result = null;
564
        if (is_object($object)) {
565
            $objectData = get_object_vars($object);
566
            if (is_array($objectData) && count($objectData)) {
567
                $result = array_map('self::object2array', $objectData);
568
            }
569
        } else {
570
            if (is_array($object)) {
571
                foreach ($object as $item => $value) {
572
                    $result[$item] = self::object2array($value);
573
                }
574
            } else {
575
                $result = $object;
576
            }
577
        }
578
579
        return $result;
580
    }
581
582
    /**
583
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
584
     *
585
     * @param object|array $object
586
     *
587
     * @return array
588
     */
589
    public static function objectToID($object)
590
    {
591
        $resultID = null;
592
        if (is_object($object)) {
593
            $resultID = $object->__toString();
594
        } else {
595
            if (is_array($object)) {
596
                foreach ($object as $item => $value) {
597
                    $resultID[$item] = self::objectToID($value);
598
                }
599
            } else { //String
600
                $resultID = $object;
601
            }
602
        }
603
604
        return $resultID;
605
    }
606
607
    /**
608
     * Return basic URL for used Evidence
609
     *
610
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
611
     *
612
     * @return string Evidence URL
613
     */
614
    public function getEvidenceURL()
615
    {
616
        $evidenceUrl = $this->url.$this->prefix.$this->company;
617
        $evidence    = $this->getEvidence();
618
        if (!empty($evidence)) {
619
            $evidenceUrl .= '/'.$evidence;
620
        }
621
        return $evidenceUrl;
622
    }
623
624
    /**
625
     * Add suffix to Evidence URL
626
     *
627
     * @param string $urlSuffix
628
     *
629
     * @return string
630
     */
631
    public function evidenceUrlWithSuffix($urlSuffix)
632
    {
633
        $evidenceUrl = $this->getEvidenceUrl();
634
        if (!empty($urlSuffix)) {
635
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0]
636
                != '?')) {
637
                $evidenceUrl .= '/';
638
            }
639
            $evidenceUrl .= $urlSuffix;
640
        }
641
        return $evidenceUrl;
642
    }
643
644
    /**
645
     * Update $this->apiURL
646
     */
647
    public function updateApiURL()
648
    {
649
        $this->apiURL = $this->getEvidenceURL();
650
        $id           = $this->__toString();
651
        if (!empty($id)) {
652
            $this->apiURL .= '/'.urlencode($id);
653
        }
654
        $this->apiURL .= '.'.$this->format;
655
    }
656
657
    /**
658
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
659
     *
660
     * @param string $urlSuffix část URL za identifikátorem firmy.
661
     * @param string $method    HTTP/REST metoda
662
     * @param string $format    Requested format
663
     * @return array|boolean Výsledek operace
664
     */
665
    public function performRequest($urlSuffix = null, $method = 'GET',
666
                                   $format = null)
667
    {
668
        $this->rowCount = null;
669
670
        if (preg_match('/^http/', $urlSuffix)) {
671
            $url = $urlSuffix;
672
        } elseif ($urlSuffix[0] == '/') {
673
            $url = $this->url.$urlSuffix;
674
        } else {
675
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
676
        }
677
678
        $responseCode = $this->doCurlRequest($url, $method, $format);
679
680
        return strlen($this->lastCurlResponse) ? $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
681
                    $this->responseFormat), $responseCode) : null;
682
    }
683
684
    /**
685
     * Parse Raw FlexiBee response in several formats
686
     *
687
     * @param string $responseRaw raw response body
688
     * @param string $format      Raw Response format json|xml|etc
689
     *
690
     * @return array
691
     */
692
    public function rawResponseToArray($responseRaw, $format)
693
    {
694
        switch ($format) {
695
            case 'json':
696
                $responseDecoded = json_decode($responseRaw, true, 10);
697
                $decodeError     = json_last_error_msg();
698
                if ($decodeError == 'No error') {
699
                    if (array_key_exists($this->nameSpace, $responseDecoded)) {
700
                        $responseDecoded = $responseDecoded[$this->nameSpace];
701
                    }
702
                } else {
703
                    $this->addStatusMessage('JSON Decoder: '.$decodeError,
704
                        'error');
705
                    $this->addStatusMessage($responseRaw, 'debug');
706
                }
707
                break;
708
            case 'xml':
709
                $responseDecoded = self::xml2array($this->lastCurlResponse);
710
                break;
711
            case 'txt':
712
            default:
713
                $responseDecoded = $this->lastCurlResponse;
714
                break;
715
        }
716
        return $responseDecoded;
717
    }
718
719
    /**
720
     * Parse Response array
721
     *
722
     * @param array $responseDecoded
723
     * @param int $responseCode Request Response Code
724
     *
725
     * @return array main data part of response
726
     */
727
    public function parseResponse($responseDecoded, $responseCode)
728
    {
729
        $response = null;
730
        switch ($responseCode) {
731
            case 201: //Success Write
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
732
                if (isset($responseDecoded[$this->resultField][0]['id'])) {
733
                    $this->lastInsertedID = $responseDecoded[$this->resultField][0]['id'];
734
                    $this->setMyKey($this->lastInsertedID);
735
                    $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
736
                } else {
737
                    $this->lastInsertedID = null;
738
                }
739
            case 200: //Success Read
740
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
741
                if (isset($responseDecoded['@rowCount'])) {
742
                    $this->rowCount = (int) $responseDecoded['@rowCount'];
743
                }
744
                break;
745
746
            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...
747
                if ($this->debug === true) {
748
                    $this->error500Reporter($responseDecoded);
749
                }
750
            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...
751
                if ($this->ignoreNotFound === true) {
752
                    break;
753
                }
754
            case 400: //Bad Request parameters
755
            default: //Something goes wrong
756
                $this->addStatusMessage($this->curlInfo['url'], 'warning');
757
                if (is_array($responseDecoded)) {
758
                    $this->parseError($responseDecoded);
759
                }
760
                $this->logResult($responseDecoded, $this->curlInfo['url']);
761
                break;
762
        }
763
        return $response;
764
    }
765
766
    /**
767
     * Parse error message response
768
     *
769
     * @param array $responseDecoded
770
     * @return int number of errors processed
771
     */
772
    public function parseError(array $responseDecoded)
773
    {
774
        if (array_key_exists('results', $responseDecoded)) {
775
            $this->errors = $responseDecoded['results'][0]['errors'];
776
        } else {
777
            if (array_key_exists('message', $responseDecoded)) {
778
                $this->errors = [['message' => $responseDecoded['message']]];
779
            }
780
        }
781
        return count($this->errors);
782
    }
783
784
    /**
785
     * Vykonej HTTP požadavek
786
     *
787
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
788
     * @param string $url    URL požadavku
789
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
790
     * @param string $format požadovaný formát komunikace
791
     * @return int HTTP Response CODE
792
     */
793
    public function doCurlRequest($url, $method, $format = null)
794
    {
795
        if (is_null($format)) {
796
            $format = $this->format;
797
        }
798
        curl_setopt($this->curl, CURLOPT_URL, $url);
799
// Nastavení samotné operace
800
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
801
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
802
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
803
804
        $httpHeaders = $this->defaultHttpHeaders;
805
806
        $formats = Formats::bySuffix();
807
808
        if (!isset($httpHeaders['Accept'])) {
809
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
810
        }
811
        if (!isset($httpHeaders['Content-Type'])) {
812
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
813
        }
814
        $httpHeadersFinal = [];
815
        foreach ($httpHeaders as $key => $value) {
816
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
817
                $value .= ' v'.self::$libVersion;
818
            }
819
            $httpHeadersFinal[] = $key.': '.$value;
820
        }
821
822
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
823
824
// Proveď samotnou operaci
825
        $this->lastCurlResponse            = curl_exec($this->curl);
826
        $this->curlInfo                    = curl_getinfo($this->curl);
827
        $this->curlInfo['when']            = microtime();
828
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
829
        $this->responseFormat              = Formats::contentTypeToSuffix($this->curlInfo['content_type']);
830
        $this->lastResponseCode            = $this->curlInfo['http_code'];
831
        $this->lastCurlError               = curl_error($this->curl);
832
        if (strlen($this->lastCurlError)) {
833
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
834
                    $this->lastResponseCode, $this->lastCurlError), 'error');
835
        }
836
837
        if ($this->debug === true) {
838
            $this->saveDebugFiles();
839
        }
840
841
        return $this->lastResponseCode;
842
    }
843
844
    /**
845
     * Nastaví druh prováděné akce.
846
     *
847
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
848
     * @param string $action
849
     * @return boolean
850
     */
851
    public function setAction($action)
852
    {
853
        $result           = false;
854
        $actionsAvailable = $this->getActionsInfo();
855
        if (is_array($actionsAvailable) && array_key_exists($action,
856
                $actionsAvailable)) {
857
            $this->action = $action;
858
            $result       = true;
859
        }
860
        return $result;
861
    }
862
863
    /**
864
     * Convert XML to array.
865
     *
866
     * @param string $xml
867
     *
868
     * @return array
869
     */
870
    public static function xml2array($xml)
871
    {
872
        $arr = [];
873
874
        if (is_string($xml)) {
875
            $xml = simplexml_load_string($xml);
876
        }
877
878
        foreach ($xml->children() as $r) {
879
            if (count($r->children()) == 0) {
880
                $arr[$r->getName()] = strval($r);
881
            } else {
882
                $arr[$r->getName()][] = self::xml2array($r);
883
            }
884
        }
885
886
        return $arr;
887
    }
888
889
    /**
890
     * Odpojení od FlexiBee.
891
     */
892
    public function disconnect()
893
    {
894
        if (is_resource($this->curl)) {
895
            curl_close($this->curl);
896
        }
897
        $this->curl = null;
898
    }
899
900
    /**
901
     * Disconnect CURL befere pass away
902
     */
903
    public function __destruct()
904
    {
905
        $this->disconnect();
906
    }
907
908
    /**
909
     * Načte řádek dat z FlexiBee.
910
     *
911
     * @param int $recordID id požadovaného záznamu
912
     *
913
     * @return array
914
     */
915
    public function getFlexiRow($recordID)
916
    {
917
        $record   = null;
918
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
919
        if (isset($response[$this->evidence])) {
920
            $record = $response[$this->evidence][0];
921
        }
922
923
        return $record;
924
    }
925
926
    /**
927
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
928
     *
929
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
930
     * @param array $conditions pole podmínek   - rendrují se do ()
931
     * @param array $urlParams  pole parametrů  - rendrují za ?
932
     */
933
    public function extractUrlParams(&$conditions, &$urlParams)
934
    {
935
        foreach ($this->urlParams as $urlParam) {
936
            if (isset($conditions[$urlParam])) {
937
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
938
            }
939
        }
940
    }
941
942
    /**
943
     * Načte data z FlexiBee.
944
     *
945
     * @param string $suffix     dotaz
946
     * @param string|array $conditions Volitelný filtrovací výraz
947
     */
948
    public function getFlexiData($suffix = null, $conditions = null)
949
    {
950
        $urlParams = $this->defaultUrlParams;
951
952
        if (!is_null($conditions)) {
953
            if (is_array($conditions)) {
954
                $this->extractUrlParams($conditions, $urlParams);
955
                $conditions = $this->flexiUrl($conditions);
956
            }
957
958
            if (strlen($conditions) && ($conditions[0] != '/')) {
959
                $conditions = rawurlencode('('.($conditions).')');
960
            }
961
        }
962
963
        if (strlen($suffix)) {
964
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/')) {
965
                $transactions = $this->performRequest($suffix, 'GET');
966
            } else {
967
                $transactions = $this->performRequest($conditions.'?'.$suffix.'&'.http_build_query($urlParams),
968
                    'GET');
969
            }
970
        } else {
971
            $transactions = $this->performRequest($conditions.'?'.http_build_query($urlParams),
972
                'GET');
973
        }
974
975
        $responseEvidence = $this->getResponseEvidence();
976
        if (is_array($transactions) && array_key_exists($responseEvidence,
977
                $transactions)) {
978
            $result = $transactions[$responseEvidence];
979
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
980
                $result = null; // Response is empty Array
981
            }
982
        } else {
983
            $result = $transactions;
984
        }
985
986
        return $result;
987
    }
988
989
    /**
990
     * Načte záznam z FlexiBee a uloží v sobě jeho data
991
     * Read FlexiBee record and store it inside od object
992
     *
993
     * @param int $id ID or conditions
994
     *
995
     * @return int počet načtených položek
996
     */
997
    public function loadFromFlexiBee($id = null)
998
    {
999
        $data = [];
1000
        if (is_null($id)) {
1001
            $id = $this->getMyKey();
1002
        }
1003
        if (is_array($id)) {
1004
            $id = '('.self::flexiUrl($id).')';
1005
        }
1006
        $flexidata    = $this->getFlexiData($this->getEvidenceUrl().'/'.$id);
1007
        $this->apiURL = $this->curlInfo['url'];
1008
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1009
            $data = current($flexidata);
1010
        }
1011
        return $this->takeData($data);
1012
    }
1013
1014
    /**
1015
     * Převede data do Json formátu pro FlexiBee.
1016
     * Convert data to FlexiBee like Json format
1017
     *
1018
     * @param array $data
1019
     *
1020
     * @return string
1021
     */
1022
    public function jsonizeData($data)
1023
    {
1024
        $dataToJsonize = [
1025
            $this->nameSpace => [
1026
                '@version' => $this->protoVersion,
1027
                $this->evidence => $this->objectToID($data),
1028
            ],
1029
        ];
1030
1031 View Code Duplication
        if (!is_null($this->action)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1032
            $dataToJsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1033
            $this->action                                               = null;
1034
        }
1035
1036 View Code Duplication
        if (!is_null($this->filter)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1037
            $dataToJsonize[$this->nameSpace][$this->evidence.'@filter'] = $this->filter;
1038
        }
1039
1040
        return json_encode($dataToJsonize);
1041
    }
1042
1043
    /**
1044
     * Test if given record ID exists in FlexiBee.
1045
     *
1046
     * @param string|int $identifer
1047
     */
1048
    public function idExists($identifer = null)
1049
    {
1050
        if (is_null($identifer)) {
1051
            $identifer = $this->getMyKey();
1052
        }
1053
        $flexiData = $this->getFlexiData(
1054
            'detail=custom:'.$this->getmyKeyColumn(),
1055
            [$this->getmyKeyColumn() => $identifer]);
1056
1057
        return $flexiData;
1058
    }
1059
1060
    /**
1061
     * Test if given record exists in FlexiBee.
1062
     *
1063
     * @param array $data
1064
     * @return boolean Record presence status
1065
     */
1066
    public function recordExists($data = [])
1067
    {
1068
1069
        if (empty($data)) {
1070
            $data = $this->getData();
1071
        }
1072
1073
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1074
            self::flexiUrl($data));
0 ignored issues
show
Documentation introduced by
self::flexiUrl($data) is of type string, but the function expects a array|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1075
1076
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1077
            || !count($res[0])) {
1078
            $found = false;
1079
        } else {
1080
            $found = true;
1081
        }
1082
        return $found;
1083
    }
1084
1085
    /**
1086
     * Vrací z FlexiBee sloupečky podle podmínek.
1087
     *
1088
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1089
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1090
     *                                     sloupečku
1091
     * @return array
1092
     */
1093
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1094
    {
1095
        if (is_int($conditions)) {
1096
            $conditions = [$this->getmyKeyColumn() => $conditions];
1097
        }
1098
1099
        $flexiData = $this->getFlexiData('', $conditions);
1100
1101
        if (!is_null($indexBy)) {
1102
            $flexiData = $this->reindexArrayBy($flexiData);
1103
        }
1104
1105
        return $flexiData;
1106
    }
1107
1108
    /**
1109
     * Vrací z FlexiBee sloupečky podle podmínek.
1110
     *
1111
     * @param string[] $columnsList seznam položek
1112
     * @param array    $conditions  pole podmínek nebo ID záznamu
1113
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1114
     *
1115
     * @return array
1116
     */
1117
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1118
                                           $indexBy = null)
1119
    {
1120
        $detail = 'full';
1121
        switch (gettype($columnsList)) {
1122
            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...
1123
                $conditions = [$this->getmyKeyColumn() => $conditions];
1124
            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...
1125
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1126
                        $columnsList)) {
1127
                    $columnsList[] = $indexBy;
1128
                }
1129
                $columns = implode(',', array_unique($columnsList));
1130
                $detail  = 'custom:'.$columns;
1131
            default:
1132
                switch ($columnsList) {
1133
                    case 'id':
1134
                        $detail = 'id';
1135
                        break;
1136
                    case 'summary':
1137
                        $detail = 'summary';
1138
                        break;
1139
                    default:
1140
                        break;
1141
                }
1142
                break;
1143
        }
1144
1145
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1146
1147
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1148
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1149
        }
1150
1151
        return $flexiData;
1152
    }
1153
1154
    /**
1155
     * Vrací kód záznamu.
1156
     * Obtain record CODE
1157
     *
1158
     * @param mixed $data
1159
     *
1160
     * @return string
1161
     */
1162
    public function getKod($data = null, $unique = true)
1163
    {
1164
        $kod = null;
1165
1166
        if (is_null($data)) {
1167
            $data = $this->getData();
1168
        }
1169
1170
        if (is_string($data)) {
1171
            $data = [$this->nameColumn => $data];
1172
        }
1173
1174
        if (isset($data['kod'])) {
1175
            $kod = $data['kod'];
1176
        } else {
1177
            if (isset($data[$this->nameColumn])) {
1178
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1179
                    \Ease\Sand::rip($data[$this->nameColumn]));
1180
            } else {
1181
                if (isset($data[$this->myKeyColumn])) {
1182
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1183
                }
1184
            }
1185
        }
1186
1187
        if (!strlen($kod)) {
1188
            $kod = 'NOTSET';
1189
        }
1190
1191
        if (strlen($kod) > 18) {
1192
            $kodfinal = strtoupper(substr($kod, 0, 18));
1193
        } else {
1194
            $kodfinal = strtoupper($kod);
1195
        }
1196
1197
        if ($unique) {
1198
            $counter = 0;
1199
            if (count($this->codes)) {
1200
                foreach ($this->codes as $codesearch => $keystring) {
1201
                    if (strstr($codesearch, $kodfinal)) {
1202
                        ++$counter;
1203
                    }
1204
                }
1205
            }
1206
            if ($counter) {
1207
                $kodfinal = $kodfinal.$counter;
1208
            }
1209
1210
            $this->codes[$kodfinal] = $kod;
1211
        }
1212
1213
        return $kodfinal;
1214
    }
1215
1216
    /**
1217
     * Write Operation Result.
1218
     *
1219
     * @param array  $resultData
1220
     * @param string $url        URL
1221
     * @return boolean Log save success
1222
     */
1223
    public function logResult($resultData = null, $url = null)
1224
    {
1225
        $logResult = false;
1226
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1227
            if (isset($resultData['message'])) {
1228
                $this->addStatusMessage($resultData['message'], 'warning');
1229
            }
1230
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1231
                'warning');
1232
            unset($url);
1233
        }
1234
        if (is_null($resultData)) {
1235
            $resultData = $this->lastResult;
1236
        }
1237
        if (isset($url)) {
1238
            $this->logger->addStatusMessage(urldecode($url));
1239
        }
1240
1241
        if (isset($resultData['results'])) {
1242
            if ($resultData['success'] == 'false') {
1243
                $status = 'error';
1244
            } else {
1245
                $status = 'success';
1246
            }
1247
            foreach ($resultData['results'] as $result) {
1248
                if (isset($result['request-id'])) {
1249
                    $rid = $result['request-id'];
1250
                } else {
1251
                    $rid = '';
1252
                }
1253
                if (isset($result['errors'])) {
1254
                    foreach ($result['errors'] as $error) {
1255
                        $message = $error['message'];
1256
                        if (isset($error['for'])) {
1257
                            $message .= ' for: '.$error['for'];
1258
                        }
1259
                        if (isset($error['value'])) {
1260
                            $message .= ' value:'.$error['value'];
1261
                        }
1262
                        if (isset($error['code'])) {
1263
                            $message .= ' code:'.$error['code'];
1264
                        }
1265
                        $this->addStatusMessage($rid.': '.$message, $status);
1266
                    }
1267
                }
1268
            }
1269
        }
1270
        return $logResult;
1271
    }
1272
1273
    /**
1274
     * Save RAW Curl Request & Response to files in Temp directory
1275
     */
1276
    public function saveDebugFiles()
1277
    {
1278
        $tmpdir   = sys_get_temp_dir();
1279
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1280
        $reqname  = $tmpdir.'/request-'.$fname;
1281
        $respname = $tmpdir.'/response-'.$fname;
1282
        file_put_contents($reqname, $this->postFields);
1283
        file_put_contents($respname, $this->lastCurlResponse);
1284
    }
1285
1286
    /**
1287
     * Připraví data pro odeslání do FlexiBee
1288
     *
1289
     * @param string $data
1290
     */
1291
    public function setPostFields($data)
1292
    {
1293
        $this->postFields = $data;
1294
    }
1295
1296
    /**
1297
     * Generuje fragment url pro filtrování.
1298
     *
1299
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1300
     *
1301
     * @param array  $data
1302
     * @param string $joiner default and/or
1303
     * @param string $defop  default operator
1304
     *
1305
     * @return string
1306
     */
1307
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1308
    {
1309
        $parts = [];
1310
1311
        foreach ($data as $column => $value) {
1312
            if (is_integer($data[$column]) || is_float($data[$column])) {
1313
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1314
            } elseif (is_bool($data[$column])) {
1315
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1316
            } elseif (is_null($data[$column])) {
1317
                $parts[$column] = $column." is null";
1318
            } else {
1319
                switch ($value) {
1320
                    case '!null':
1321
                        $parts[$column] = $column." is not null";
1322
                        break;
1323
                    case 'is empty':
1324
                    case 'is not empty':
1325
                        $parts[$column] = $column.' '.$value;
1326
                        break;
1327
                    default:
1328
                        if ($column == 'stitky') {
1329
                            $parts[$column] = $column."='code:".$data[$column]."'";
1330
                        } else {
1331
                            $parts[$column] = $column." $defop '".$data[$column]."'";
1332
                        }
1333
                        break;
1334
                }
1335
            }
1336
        }
1337
        return implode(' '.$joiner.' ', $parts);
1338
    }
1339
1340
    /**
1341
     * Obtain record/object identificator code: or id:
1342
     * Vrací identifikátor objektu code: nebo id:
1343
     *
1344
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1345
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1346
     */
1347
    public function getRecordID()
1348
    {
1349
        $myCode = $this->getDataValue('kod');
1350
        if ($myCode) {
1351
            $id = 'code:'.$myCode;
1352
        } else {
1353
            $id = $this->getDataValue('id');
1354
            if (($this->debug === true) && is_null($id)) {
1355
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1356
                    'warning');
1357
            }
1358
        }
1359
        return is_numeric($id) ? intval($id) : strval($id);
1360
    }
1361
1362
    /**
1363
     * Obtain record/object identificator code: or id:
1364
     * Vrací identifikátor objektu code: nebo id:
1365
     *
1366
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1367
     * @return string indentifikátor záznamu reprezentovaného objektem
1368
     */
1369
    public function __toString()
1370
    {
1371
        return strval($this->getRecordID());
1372
    }
1373
1374
    /**
1375
     * Gives you FlexiPeeHP class name for Given Evidence
1376
     *
1377
     * @param string $evidence
1378
     * @return string Class name
1379
     */
1380
    public static function evidenceToClassName($evidence)
1381
    {
1382
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1383
    }
1384
1385
    /**
1386
     * Obtain ID of first record in evidence
1387
     *
1388
     * @return string|null id or null if no records
1389
     */
1390
    public function getFirstRecordID()
1391
    {
1392
        $firstID    = null;
1393
        $firstIdRaw = $this->getColumnsFromFlexibee(['id'],
1394
            ['limit' => 1, 'order' => 'id'], 'id');
1395
        if (count($firstIdRaw)) {
1396
            $firstID = (int) current($firstIdRaw)['id'];
1397
        }
1398
        return $firstID;
1399
    }
1400
1401
    /**
1402
     * Vrací hodnotu daného externího ID
1403
     *
1404
     * @param string $want Which ? If empty,you obtain the first one.
1405
     * @return string
1406
     */
1407
    public function getExternalID($want = null)
1408
    {
1409
        $extid = null;
1410
        $ids   = $this->getDataValue('external-ids');
1411
        if (is_null($want)) {
1412
            if (count($ids)) {
1413
                $extid = current($ids);
1414
            }
1415
        } else {
1416
            if (!is_null($ids) && is_array($ids)) {
1417
                foreach ($ids as $id) {
1418
                    if (strstr($id, 'ext:'.$want)) {
1419
                        $extid = str_replace('ext:'.$want.':', '', $id);
1420
                    }
1421
                }
1422
            }
1423
        }
1424
        return $extid;
1425
    }
1426
1427
    /**
1428
     * Obtain actual GlobalVersion
1429
     * Vrací aktuální globální verzi změn
1430
     *
1431
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1432
     * @return type
1433
     */
1434
    public function getGlobalVersion()
1435
    {
1436
        $globalVersion = null;
1437
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1438
            $this->getFlexiData(null,
1439
                ['add-global-version' => 'true', 'limit' => 1]);
1440
        }
1441
1442
        if (isset($this->lastResult['@globalVersion'])) {
1443
            $globalVersion = intval($this->lastResult['@globalVersion']);
1444
        }
1445
1446
        return $globalVersion;
1447
    }
1448
1449
    /**
1450
     * Obtain content type of last response
1451
     *
1452
     * @return string
1453
     */
1454
    public function getResponseFormat()
1455
    {
1456
        if (isset($this->curlInfo['content_type'])) {
1457
            $responseFormat = $this->curlInfo['content_type'];
1458
        } else {
1459
            $responseFormat = null;
1460
        }
1461
        return $responseFormat;
1462
    }
1463
1464
    /**
1465
     * Return the same response format for one and multiplete results
1466
     *
1467
     * @param array $responseBody
1468
     * @return array
1469
     */
1470
    public function unifyResponseFormat($responseBody)
1471
    {
1472
        if (!is_array($responseBody) || array_key_exists('message',
1473
                $responseBody)) { //Unifi response format
1474
            $response = $responseBody;
1475
        } else {
1476
            $evidence = $this->getResponseEvidence();
1477
            if (array_key_exists($evidence, $responseBody)) {
1478
                $response        = [];
1479
                $evidenceContent = $responseBody[$evidence];
1480
                if (array_key_exists(0, $evidenceContent)) {
1481
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1482
                } else {
1483
                    $response[$evidence][0] = $evidenceContent; //One result
1484
                }
1485
            } else {
1486
                if (isset($responseBody['priloha'])) {
1487
                    $response = $responseBody['priloha'];
1488
                } else {
1489
                    $response = $responseBody;
1490
                }
1491
            }
1492
        }
1493
        return $response;
1494
    }
1495
1496
    /**
1497
     * Obtain structure for current (or given) evidence
1498
     *
1499
     * @param string $evidence
1500
     * @return array Evidence structure
1501
     */
1502 View Code Duplication
    public function getColumnsInfo($evidence = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1503
    {
1504
        $columnsInfo = null;
1505
        if (is_null($evidence)) {
1506
            $evidence = $this->getEvidence();
1507
        }
1508
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1509
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1510
            $columnsInfo = Properties::$$propsName;
1511
        }
1512
        return $columnsInfo;
1513
    }
1514
1515
    /**
1516
     * Obtain actions for current (or given) evidence
1517
     *
1518
     * @param string $evidence
1519
     * @return array Evidence structure
1520
     */
1521 View Code Duplication
    public function getActionsInfo($evidence = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1522
    {
1523
        $actionsInfo = null;
1524
        if (is_null($evidence)) {
1525
            $evidence = $this->getEvidence();
1526
        }
1527
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1528
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1529
            $actionsInfo = Actions::$$propsName;
1530
        }
1531
        return $actionsInfo;
1532
    }
1533
1534
    /**
1535
     * Obtain relations for current (or given) evidence
1536
     *
1537
     * @param string $evidence
1538
     * @return array Evidence structure
1539
     */
1540
    public function getRelationsInfo($evidence = null)
1541
    {
1542
        $relationsInfo = null;
1543
        if (is_null($evidence)) {
1544
            $evidence = $this->getEvidence();
1545
        }
1546
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1547
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1548
            $relationsInfo = Relations::$$propsName;
1549
        }
1550
        return $relationsInfo;
1551
    }
1552
1553
    /**
1554
     * Obtain info for current (or given) evidence
1555
     *
1556
     * @param string $evidence
1557
     * @return array Evidence info
1558
     */
1559 View Code Duplication
    public function getEvidenceInfo($evidence = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1560
    {
1561
        $evidencesInfo = null;
1562
        if (is_null($evidence)) {
1563
            $evidence = $this->getEvidence();
1564
        }
1565
        if (isset(EvidenceList::$evidences[$evidence])) {
1566
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1567
        }
1568
        return $evidencesInfo;
1569
    }
1570
1571
    /**
1572
     * Obtain name for current (or given) evidence path
1573
     *
1574
     * @param string $evidence Evidence Path
1575
     * @return array Evidence info
1576
     */
1577 View Code Duplication
    public function getEvidenceName($evidence = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1578
    {
1579
        $evidenceName = null;
1580
        if (is_null($evidence)) {
1581
            $evidence = $this->getEvidence();
1582
        }
1583
        if (isset(EvidenceList::$name[$evidence])) {
1584
            $evidenceName = EvidenceList::$name[$evidence];
1585
        }
1586
        return $evidenceName;
1587
    }
1588
1589
    /**
1590
     * Perform given action (if availble) on current evidence/record
1591
     * @url https://demo.flexibee.eu/devdoc/actions
1592
     *
1593
     * @param string $action one of evidence actions
1594
     * @param string $method ext|int External method call operation in URL.
1595
     *                               Internal add the @action element to request body
1596
     */
1597
    public function performAction($action, $method = 'ext')
1598
    {
1599
        $actionsAvailble = $this->getActionsInfo();
1600
1601
        if (is_array($actionsAvailble) && array_key_exists($action,
1602
                $actionsAvailble)) {
1603
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1604
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1605
                case 'ONLY_WITH_INSTANCE': //Add instance
1606
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1607
                    break;
1608
1609
                default:
1610
                    $urlSuffix = '/'.$action;
1611
                    break;
1612
            }
1613
1614
            switch ($method) {
1615
                case 'int':
1616
                    $this->setAction($action);
1617
                    $this->setPostFields($this->jsonizeData($this->getData()));
1618
                    $result = $this->performRequest(null, 'POST');
1619
                    break;
1620
1621
                default:
1622
                    $result = $this->performRequest($urlSuffix, 'GET');
1623
                    break;
1624
            }
1625
        } else {
1626
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1627
                $action, $this->getEvidence()));
1628
        }
1629
1630
        return $result;
1631
    }
1632
1633
    /**
1634
     * Save current object to file
1635
     *
1636
     * @param string $destfile path to file
1637
     */
1638
    public function saveResponseToFile($destfile)
1639
    {
1640
        if (strlen($this->lastCurlResponse)) {
1641
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1642
        }
1643
        file_put_contents($destfile, $this->lastCurlResponse);
1644
    }
1645
1646
    /**
1647
     * Obtain established relations listing
1648
     *
1649
     * @return array Null or Relations
1650
     */
1651
    public function getVazby($id = null)
1652
    {
1653
        if (is_null($id)) {
1654
            $id = $this->getRecordID();
1655
        }
1656
        if (!empty($id)) {
1657
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
1658
                ['relations' => 'vazby', 'id' => $id]);
1659
            $vazby    = $vazbyRaw[0]['vazby'];
1660
        } else {
1661
            throw new \Exception(_('ID requied to get record relations '));
1662
        }
1663
        return $vazby;
1664
    }
1665
1666
    /**
1667
     * Gives You URL for Current Record in FlexiBee web interface
1668
     *
1669
     * @return string url
1670
     */
1671
    public function getFlexiBeeURL()
1672
    {
1673
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1674
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1675
                : '';
1676
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1677
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1678
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1679
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1680
        $pass       = ($user || $pass) ? "$pass@" : '';
1681
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1682
        return $scheme.$user.$pass.$host.$port.$path;
1683
    }
1684
1685
    /**
1686
     * Set Record Key
1687
     *
1688
     * @param int|string $myKeyValue
1689
     * @return boolean
1690
     */
1691
    public function setMyKey($myKeyValue)
1692
    {
1693
        $res = parent::setMyKey($myKeyValue);
1694
        $this->updateApiURL();
1695
        return $res;
1696
    }
1697
1698
    /**
1699
     * Set or get ignore not found pages flag
1700
     *
1701
     * @param boolean $ignore set flag to
1702
     *
1703
     * @return boolean get flag state
1704
     */
1705
    public function ignore404($ignore = null)
1706
    {
1707
        if (!is_null($ignore)) {
1708
            $this->ignoreNotFound = $ignore;
1709
        }
1710
        return $this->ignoreNotFound;
1711
    }
1712
1713
    /**
1714
     * Send Document by mail
1715
     *
1716
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1717
     *
1718
     * @param string $to
1719
     * @param string $subject
1720
     * @param string $body Email Text
1721
     *
1722
     * @return int http response code
1723
     */
1724
    public function sendByMail($to, $subject, $body, $cc = null)
1725
    {
1726
        $this->setPostFields($body);
1727
        $result = $this->doCurlRequest($this->getEvidenceURL().'/'.
1728
            urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1729
            , 'PUT', 'xml');
1730
        return $result == 200;
1731
    }
1732
1733
    /**
1734
     * Send all unsent Invoices by mail
1735
     *
1736
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1737
     * @return int http response code
1738
     */
1739
    public function sendUnsent()
1740
    {
1741
        return $this->doCurlRequest($this->getEvidenceURL().'/automaticky-odeslat-neodeslane',
1742
                'PUT', 'xml');
1743
    }
1744
1745
    /**
1746
     * FlexiBee date to PHP DateTime
1747
     *
1748
     * @param string $flexidate
1749
     *
1750
     * @return \DateTime | false
1751
     */
1752
    public static function flexiDateToDateTime($flexidate)
1753
    {
1754
        return \DateTime::createFromFormat('Y-m-jO', $flexidate);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression \DateTime::createFromFor...('Y-m-jO', $flexidate); of type DateTime|false adds false to the return on line 1754 which is incompatible with the return type documented by FlexiPeeHP\FlexiBeeRO::flexiDateToDateTime of type DateTime. It seems like you forgot to handle an error condition.
Loading history...
1755
    }
1756
1757
    /**
1758
     * Získá dokument v daném formátu
1759
     * Obtain document in given format
1760
     *
1761
     * @param string $format  pdf/csv/xml/json/ ...
1762
     *
1763
     * @return string|null filename downloaded or none
1764
     */
1765
    public function getInFormat($format)
1766
    {
1767
        $response = null;
1768
        if ($this->setFormat($format)) {
1769
            if (($this->doCurlRequest(($format == 'html') ? $this->apiURL.'?inDesktopApp=true'
1770
                            : $this->apiURL, 'GET') == 200)) {
1771
                $response = $this->lastCurlResponse;
1772
            }
1773
        }
1774
        return $response;
1775
    }
1776
1777
    /**
1778
     * Uloží dokument v daném formátu do složky v systému souborů
1779
     * Save document in given format to directory in filesystem
1780
     *
1781
     * @param string $format  pdf/csv/xml/json/ ...
1782
     * @param string $destDir where to put file (prefix)
1783
     *
1784
     * @return string|null filename downloaded or none
1785
     */
1786
    public function downloadInFormat($format, $destDir = './')
1787
    {
1788
        $fileOnDisk = null;
1789
        if ($this->setFormat($format)) {
1790
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1791
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1792
                    $this->lastCurlResponse) !== false)) {
1793
                $fileOnDisk = $downloadTo;
1794
            }
1795
        }
1796
        return $fileOnDisk;
1797
    }
1798
1799
    /**
1800
     * Compile and send Report about Error500 to FlexiBee developers
1801
     * If FlexiBee is running on localost try also include java backtrace
1802
     *
1803
     * @param array $errorResponse result of parseError();
1804
     */
1805
    public function error500Reporter($errorResponse)
1806
    {
1807
        $ur = str_replace('/c/'.$this->company, '',
1808
            str_replace($this->url, '', $this->curlInfo['url']));
1809
        if (!array_key_exists($ur, $this->reports)) {
1810
            $tmpdir   = sys_get_temp_dir();
1811
            $myTime   = $this->curlInfo['when'];
1812
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
1813
            file_put_contents($curlname,
1814
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
1815
1816
            $report = new \Ease\Mailer($this->reportRecipient,
1817
                'Error report 500 - '.$ur);
1818
1819
            $d     = dir($tmpdir);
1820
            while (false !== ($entry = $d->read())) {
1821
                if (strstr($entry, $myTime)) {
1822
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
1823
                    $mime = Formats::suffixToContentType($ext);
1824
                    $report->addFile($tmpdir.'/'.$entry,
1825
                        empty($mime) ? 'text/plain' : $mime);
1826
                }
1827
            }
1828
            $d->close();
1829
1830
            if ((strstr($this->url, '://localhost') || strstr($this->url,
1831
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
1832
1833
                $fl = fopen("/var/log/flexibee.log", "r");
1834
                if ($fl) {
1835
                    $tracelog = [];
1836
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
1837
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
1838
                        $char = fgetc($fl);
1839
                        if ($char === "\n") {
1840
                            $tracelog[] = $output[$ln];
1841
                            if (strstr($output[$ln], $errorResponse['message'])) {
1842
                                break;
1843
                            }
1844
                            $ln++;
1845
                            continue;
1846
                        }
1847
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
1848
                                : '');
1849
                    }
1850
1851
                    $trace     = implode("\n", array_reverse($tracelog));
1852
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
1853
                    file_put_contents($tracefile, $trace);
1854
                    $report->addItem("\n\n".$trace);
1855
                    fclose($fl);
1856
                }
1857
            } else {
1858
                $report->addItem($errorResponse['message']);
1859
            }
1860
1861
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
1862
1863
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
1864
                    JSON_PRETTY_PRINT));
1865
1866
            if ($report->send()) {
1867
                $this->reports[$ur] = $myTime;
1868
            }
1869
        }
1870
    }
1871
}
1872