Test Failed
Pull Request — master (#3)
by Vítězslav
02:22
created

FlexiBeeRO::parseResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
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-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
    static public $libVersion = '1.6.4.2';
24
25
    /**
26
     * Availble Formats.
27
     *
28
     * @see https://www.flexibee.eu/api/dokumentace/ref/format-types/
29
     * @var array formats known to flexibee
30
     */
31
    static public $formats = [
32
        'JS' => ['desc' => 'JavaScropt',
33
            'suffix' => 'js', 'content-type' => 'application/javascript', 'import' => false],
34
        'CSS' => ['desc' => 'Kaskádový styl',
35
            'suffix' => 'css', 'content-type' => 'text/css', 'import' => false],
36
        'HTML' => ['desc' => 'HTML stránka pro zobrazení informací na webové stránce.',
37
            'suffix' => 'html', 'content-type' => 'text/html', 'import' => false],
38
        'XML' => ['desc' => 'Strojově čitelná struktura ve formátu XML.', 'suffix' => 'xml',
39
            'content-type' => 'application/xml', 'import' => true],
40
        'JSON' => ['desc' => 'Strojově čitelná struktura ve formátu JSON. ', 'suffix' => 'json',
41
            'content-type' => 'application/json', 'import' => true],
42
        'CSV' => ['desc' => 'Tabulkový výstup do formátu CSV (Column Separated Values).',
43
            'suffix' => 'csv', 'content-type' => 'text/csv', 'import' => true],
44
        'DBF' => ['desc' => 'Databázový výstup ve formátu DBF (dBase).', 'suffix' => 'dbf',
45
            'content-type' => 'application/dbf', 'import' => true],
46
        'XLS' => ['desc' => 'Tabulkový výstup ve formátu Excel.', 'suffix' => 'xls',
47
            'content-type' => 'application/ms-excel', 'import' => true],
48
        'ISDOC' => ['desc' => 'e-faktura ISDOC.', 'suffix' => 'isdoc', 'content-type' => 'application/x-isdoc',
49
            'import' => false],
50
        'ISDOCx' => ['desc' => 'e-faktura ISDOC s PDF přílohou', 'suffix' => 'isdocx',
51
            'content-type' => 'application/x-isdocx',
52
            'import' => false],
53
        'EDI' => ['desc' => 'Elektronická výměna data (EDI) ve formátu INHOUSE.',
54
            'suffix' => 'edi', 'content-type' => 'application/x-edi-inhouse', 'import' => 'objednavka-prijata'],
55
        'PDF' => ['desc' => 'Generování tiskového reportu. Jedná se o stejnou funkci která je dostupná v aplikaci. Export do PDF',
56
            'suffix' => 'pdf', 'content-type' => 'application/pdf', 'import' => false],
57
        'vCard' => ['desc' => 'Výstup adresáře do formátu elektronické vizitky vCard.',
58
            'suffix' => 'vcf', 'content-type' => 'text/vcard', 'import' => false],
59
        'iCalendar' => ['desc' => 'Výstup do kalendáře ve formátu iCalendar. Lze takto exportovat události, ale také třeba splatnosti u přijatých či vydaných faktur.',
60
            'suffix' => 'ical', 'content-type' => 'text/calendar', 'import' => false]
61
    ];
62
63
    /**
64
     * Základní namespace pro komunikaci s FlexiBee.
65
     * Basic namespace for communication with FlexiBee
66
     *
67
     * @var string Jmený prostor datového bloku odpovědi
68
     */
69
    public $nameSpace = 'winstrom';
70
71
    /**
72
     * URL of object data in FlexiBee
73
     * @var string url
74
     */
75
    public $apiURL = null;
76
77
    /**
78
     * Datový blok v poli odpovědi.
79
     * Data block in response field.
80
     *
81
     * @var string
82
     */
83
    public $resultField = 'results';
84
85
    /**
86
     * Verze protokolu použitého pro komunikaci.
87
     * Communication protocol version used.
88
     *
89
     * @var string Verze použitého API
90
     */
91
    public $protoVersion = '1.0';
92
93
    /**
94
     * Evidence užitá objektem.
95
     * Evidence used by object
96
     *
97
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
98
     * @var string
99
     */
100
    public $evidence = null;
101
102
    /**
103
     * Výchozí formát pro komunikaci.
104
     * Default communication format.
105
     *
106
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
107
     *
108
     * @var string json|xml|...
109
     */
110
    public $format = 'json';
111
112
    /**
113
     * formát příchozí odpovědi
114
     * response format
115
     *
116
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
117
     *
118
     * @var string json|xml|...
119
     */
120
    public $responseFormat = 'json';
121
122
    /**
123
     * Curl Handle.
124
     *
125
     * @var resource
126
     */
127
    public $curl = null;
128
129
    /**
130
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
131
     * @var string
132
     */
133
    public $company = null;
134
135
    /**
136
     * Server[:port]
137
     * @var string
138
     */
139
    public $url = null;
140
141
    /**
142
     * REST API Username
143
     * @var string
144
     */
145
    public $user = null;
146
147
    /**
148
     * REST API Password
149
     * @var string
150
     */
151
    public $password = null;
152
153
    /**
154
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
155
     */
156
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
157
158
    /**
159
     * Default additional request url parameters after question mark
160
     *
161
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
162
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
163
     * @var array
164
     */
165
    public $defaultUrlParams = ['limit' => 0];
166
167
    /**
168
     * Identifikační řetězec.
169
     *
170
     * @var string
171
     */
172
    public $init = null;
173
174
    /**
175
     * Sloupeček s názvem.
176
     *
177
     * @var string
178
     */
179
    public $nameColumn = 'nazev';
180
181
    /**
182
     * Sloupeček obsahující datum vložení záznamu do shopu.
183
     *
184
     * @var string
185
     */
186
    public $myCreateColumn = 'false';
187
188
    /**
189
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
190
     *
191
     * @var string
192
     */
193
    public $myLastModifiedColumn = 'lastUpdate';
194
195
    /**
196
     * Klíčový idendifikátor záznamu.
197
     *
198
     * @var string
199
     */
200
    public $fbKeyColumn = 'id';
201
202
    /**
203
     * Informace o posledním HTTP requestu.
204
     *
205
     * @var *
206
     */
207
    public $info;
208
209
    /**
210
     * Informace o poslední HTTP chybě.
211
     *
212
     * @var string
213
     */
214
    public $lastCurlError = null;
215
216
    /**
217
     * Used codes storage.
218
     *
219
     * @var array
220
     */
221
    public $codes = null;
222
223
    /**
224
     * Last Inserted ID.
225
     *
226
     * @var int
227
     */
228
    public $lastInsertedID = null;
229
230
    /**
231
     * Default Line Prefix.
232
     *
233
     * @var string
234
     */
235
    public $prefix = '/c/';
236
237
    /**
238
     * Raw Content of last curl response
239
     *
240
     * @var string
241
     */
242
    public $lastCurlResponse;
243
244
    /**
245
     * HTTP Response code of last request
246
     *
247
     * @var int
248
     */
249
    public $lastResponseCode = null;
250
251
    /**
252
     * Body data  for next curl POST operation
253
     *
254
     * @var string
255
     */
256
    protected $postFields = null;
257
258
    /**
259
     * Last operation result data or message(s)
260
     *
261
     * @var array
262
     */
263
    public $lastResult = null;
264
265
    /**
266
     * Nuber from  @rowCount
267
     * @var int
268
     */
269
    public $rowCount = null;
270
271
    /**
272
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
273
     * @var string
274
     */
275
    protected $action;
276
277
    /**
278
     * Pole akcí které podporuje ta která evidence
279
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
280
     * @var array
281
     */
282
    public $actionsAvailable = null;
283
284
    /**
285
     * Parmetry pro URL
286
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
287
     * @var array
288
     */
289
    public $urlParams = [
290
        'idUcetniObdobi',
291
        'dry-run',
292
        'fail-on-warning',
293
        'report-name',
294
        'report-lang',
295
        'report-sign',
296
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
297
        'mode',
298
        'limit',
299
        'start',
300
        'order',
301
        'sort',
302
        'add-row-count',
303
        'relations',
304
        'includes',
305
        'use-ext-id',
306
        'use-internal-id',
307
        'stitky-as-ids',
308
        'only-ext-ids',
309
        'no-ext-ids',
310
        'no-ids',
311
        'code-as-id',
312
        'no-http-errors',
313
        'export-settings',
314
        'as-gui',
315
        'code-in-response',
316
        'add-global-version',
317
        'encoding',
318
        'delimeter',
319
        'format',
320
        'auth',
321
        'skupina-stitku',
322
        'dir',
323
        'relations',
324
        'relations',
325
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
326
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
327
        'inDesktopApp' // Note: Undocumented function (html only)
328
    ];
329
330
    /**
331
     * Save 404 results to log ?
332
     * @var boolean
333
     */
334
    protected $ignoreNotFound = false;
335
336
    /**
337
     * Class for read only interaction with FlexiBee.
338
     *
339
     * @param mixed $init default record id or initial data
340
     * @param array $options Connection settings override
341
     */
342
    public function __construct($init = null, $options = [])
343
    {
344
        $this->init = $init;
345
346
        parent::__construct();
347
        $this->setUp($options);
348
        $this->curlInit();
349
        if (!is_null($init)) {
350
            $this->processInit($init);
351
        }
352
    }
353
354
    /**
355
     * SetUp Object to be ready for connect
356
     *
357
     * @param array $options Object Options (company,url,user,password,evidence,
358
     *                                       prefix,debug)
359
     */
360
    public function setUp($options = [])
361
    {
362
        if (isset($options['company'])) {
363
            $this->company = $options['company'];
364
        } else {
365
            if (is_null($this->company) && defined('FLEXIBEE_COMPANY')) {
366
                $this->company = constant('FLEXIBEE_COMPANY');
367
            }
368
        }
369
        if (isset($options['url'])) {
370
            $this->url = $options['url'];
371
        } else {
372
            if (is_null($this->url) && defined('FLEXIBEE_URL')) {
373
                $this->url = constant('FLEXIBEE_URL');
374
            }
375
        }
376
        if (isset($options['user'])) {
377
            $this->user = $options['user'];
378
        } else {
379
            if (is_null($this->user) && defined('FLEXIBEE_LOGIN')) {
380
                $this->user = constant('FLEXIBEE_LOGIN');
381
            }
382
        }
383
        if (isset($options['password'])) {
384
            $this->password = $options['password'];
385
        } else {
386
            if (is_null($this->password) && defined('FLEXIBEE_PASSWORD')) {
387
                $this->password = constant('FLEXIBEE_PASSWORD');
388
            }
389
        }
390
        if (isset($options['evidence'])) {
391
            $this->setEvidence($options['evidence']);
392
        }
393
        if (isset($options['prefix'])) {
394
            $this->setPrefix($options['prefix']);
395
        }
396
        if (isset($options['debug'])) {
397
            $this->debug = $options['debug'];
398
        }
399
    }
400
401
    /**
402
     * Inicializace CURL
403
     */
404
    public function curlInit()
405
    {
406
        $this->curl = \curl_init(); // create curl resource
407
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
408
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
409
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
410
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
411
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
412
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
413
        curl_setopt($this->curl, CURLOPT_USERPWD,
414
            $this->user.':'.$this->password); // set username and password
415
    }
416
417
    /**
418
     * Zinicializuje objekt dle daných dat
419
     *
420
     * @param mixed $init
421
     */
422
    public function processInit($init)
423
    {
424
        if (is_integer($init)) {
425
            $this->loadFromFlexiBee($init);
426
        } elseif (is_array($init)) {
427
            $this->takeData($init);
428
        } elseif (strstr($init, 'code:')) {
429
            $this->loadFromFlexiBee($init);
430
        }
431
    }
432
433
    /**
434
     * Set URL prefix
435
     *
436
     * @param string $prefix
437
     */
438
    public function setPrefix($prefix)
439
    {
440
        switch ($prefix) {
441
            case 'a': //Access
442
            case 'c': //Company
443
            case 'u': //User
444
            case 'g': //License Groups
445
            case 'admin':
446
            case 'status':
447
            case 'login-logout':
448
                $this->prefix = '/'.$prefix.'/';
449
                break;
450
            case null:
451
            case '':
452
            case '/':
453
                $this->prefix = '';
454
                break;
455
            default:
456
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
457
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
458
        }
459
    }
460
461
    /**
462
     * Set communication format.
463
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
464
     *
465
     * @param string $format
466
     * @return boolen format is availble
467
     */
468
    public function setFormat($format)
469
    {
470
        $result = true;
471
        if ($this->debug === true) {
472
            $evidence = lcfirst(FlexiBeeRO::evidenceToClassName($this->getEvidence()));
473
            if (array_key_exists($format, array_flip(Formats::$$evidence)) === false) {
474
                $result = false;
475
            }
476
        }
477
        if ($result === true) {
478
            $this->format = $format;
479
            $this->updateApiURL();
480
        }
481
        return $result;
482
    }
483
484
    /**
485
     * Nastaví Evidenci pro Komunikaci.
486
     * Set evidence for communication
487
     *
488
     * @param string $evidence evidence pathName to use
489
     * @return boolean evidence switching status
490
     */
491
    public function setEvidence($evidence)
492
    {
493
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
494
        switch ($this->prefix) {
495
            case '/c/':
496
                if (array_key_exists($evidence, EvidenceList::$name)) {
497
                    $this->evidence = $evidence;
498
                    $result         = true;
499
                } else {
500
                    throw new \Exception(sprintf('Try to set unsupported evidence %s',
501
                        $evidence));
502
                }
503
                break;
504
            default:
505
                $this->evidence = $evidence;
506
                $result         = true;
507
                break;
508
        }
509
        $this->updateApiURL();
510
        return $result;
511
    }
512
513
    /**
514
     * Vrací právě používanou evidenci pro komunikaci
515
     * Obtain current used evidence
516
     *
517
     * @return string
518
     */
519
    public function getEvidence()
520
    {
521
        return $this->evidence;
522
    }
523
524
    /**
525
     * Set used company.
526
     * Nastaví Firmu.
527
     *
528
     * @param string $company
529
     */
530
    public function setCompany($company)
531
    {
532
        $this->company = $company;
533
    }
534
535
    /**
536
     * Obtain company now used
537
     * Vrací právě používanou firmu
538
     *
539
     * @return string
540
     */
541
    public function getCompany()
542
    {
543
        return $this->company;
544
    }
545
546
    /**
547
     * Vrací název evidence použité v odpovědích z FlexiBee
548
     *
549
     * @return string
550
     */
551
    public function getResponseEvidence()
552
    {
553
        switch ($this->evidence) {
554
            case 'c':
555
                $evidence = 'company';
556
                break;
557
            case 'evidence-list':
558
                $evidence = 'evidences';
559
                break;
560
            default:
561
                $evidence = $this->getEvidence();
562
                break;
563
        }
564
        return $evidence;
565
    }
566
567
    /**
568
     * Převede rekurzivně Objekt na pole.
569
     *
570
     * @param object|array $object
571
     *
572
     * @return array
573
     */
574
    public static function object2array($object)
575
    {
576
        $result = null;
577
        if (is_object($object)) {
578
            $objectData = get_object_vars($object);
579
            if (is_array($objectData) && count($objectData)) {
580
                $result = array_map('self::object2array', $objectData);
581
            }
582 View Code Duplication
        } else {
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...
583
            if (is_array($object)) {
584
                foreach ($object as $item => $value) {
585
                    $result[$item] = self::object2array($value);
586
                }
587
            } else {
588
                $result = $object;
589
            }
590
        }
591
592
        return $result;
593
    }
594
595
    /**
596
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
597
     *
598
     * @param object|array $object
599
     *
600
     * @return array
601
     */
602
    public static function objectToID($object)
603
    {
604
        $result = null;
605
        if (is_object($object)) {
606
            $result = $object->__toString();
607 View Code Duplication
        } else {
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...
608
            if (is_array($object)) {
609
                foreach ($object as $item => $value) {
610
                    $result[$item] = self::objectToID($value);
611
                }
612
            } else { //String
613
                $result = $object;
614
            }
615
        }
616
617
        return $result;
618
    }
619
620
    /**
621
     * Return basic URL for used Evidence
622
     *
623
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
624
     * @param string $urlSuffix
625
     */
626
    public function getEvidenceURL($urlSuffix = null)
627
    {
628
        if (is_null($urlSuffix)) {
629
            $urlSuffix = $this->getEvidence();
630
        } elseif ($urlSuffix[0] == ';') {
631
            $urlSuffix = $this->getEvidence().$urlSuffix;
632
        }
633
        return $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
634
    }
635
636
    /**
637
     * Update $this->apiURL
638
     */
639
    public function updateApiURL()
640
    {
641
        $this->apiURL = $this->getEvidenceURL();
642
        $id           = $this->__toString();
643
        if (!is_null($id)) {
644
            $this->apiURL .= '/'.urlencode($id);
645
        }
646
        $this->apiURL .= '.'.$this->format;
647
    }
648
649
    /**
650
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
651
     *
652
     * @param string $urlSuffix část URL za identifikátorem firmy.
653
     * @param string $method    HTTP/REST metoda
654
     * @param string $format    Requested format
655
     * @return array|boolean Výsledek operace
656
     */
657
    public function performRequest($urlSuffix = null, $method = 'GET',
658
                                   $format = null)
659
    {
660
        $response       = null;
661
        $result         = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
662
        $this->rowCount = null;
663
664
        if (preg_match('/^http/', $urlSuffix)) {
665
            $url = $urlSuffix;
666
        } else {
667
            $url = $this->getEvidenceURL($urlSuffix);
668
        }
669
670
        $responseCode = $this->doCurlRequest($url, $method, $format);
671
672
        $responseArray = $this->rawResponseToArray($this->lastCurlResponse,
0 ignored issues
show
Unused Code introduced by
$responseArray is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
673
            $format);
674
675
        if (is_null($format)) {
676
            $format = $this->format;
677
        }
678
679
        switch ($responseCode) {
680
            case 200:
681
            case 201:
682
// Parse response
683
                $responseDecoded = [];
0 ignored issues
show
Unused Code introduced by
$responseDecoded is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
684
                $responseDecoded = $this->parseResponse($respnseArray);
0 ignored issues
show
Bug introduced by
The variable $respnseArray does not exist. Did you mean $responseArray?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
685
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
686
687
                break;
688
689
            default: //Some goes wrong
690
                $this->lastCurlError = curl_error($this->curl);
691
                switch ($format) {
692
                    case 'json':
693
                        $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
694
                            function ($match) {
695
                            return mb_convert_encoding(pack('H*', $match[1]),
696
                                'UTF-8', 'UCS-2BE');
697
                        }, $this->lastCurlResponse);
698
                        $response = (json_encode(json_decode($response, true, 10),
699
                                JSON_PRETTY_PRINT));
700
                        break;
701
                    case 'xml':
702
                        if (strlen($this->lastCurlResponse)) {
703
                            $response = self::xml2array($this->lastCurlResponse);
704
                        }
705
                        break;
706
                    case 'txt':
707
                    default:
708
                        $response = $this->lastCurlResponse;
709
                        break;
710
                }
711
712
                if (is_array($response)) {
713
                    $result = urldecode(http_build_query($response));
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
714
                } elseif (strlen($response) && ($response != 'null')) {
715
                    $decoded = json_decode($response);
716
                    if (is_array($decoded)) {
717
                        $result = urldecode(http_build_query(self::object2array(current($decoded))));
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
718
                    }
719
                } else {
720
                    $result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
721
                }
722
723
                if ($response == 'null') {
724
                    if ($this->lastResponseCode == 200) {
725
                        $response = true;
726
                    } else {
727
                        $response = null;
728
                    }
729
                } else {
730
                    if (is_string($response)) {
731
                        $decoded = json_decode($response);
732
                        if (is_array($decoded)) {
733
                            $response = self::object2array(current($decoded));
734
                        }
735
                    }
736
                }
737
738
                if (is_array($response) && ($this->lastResponseCode == 400)) {
739
                    $this->logResult($response, $url);
740
                } else {
741
                    $responseDecoded = json_decode($this->lastCurlResponse,
742
                        true, 10);
743
744
                    if (is_array($responseDecoded) && array_key_exists('results',
745
                            $responseDecoded[$this->nameSpace])) {
746
                        $errors = $responseDecoded[$this->nameSpace]['results'][0]['errors'];
747
                    } else {
748
                        $errors = null;
749
                    }
750
751
                    if (!is_array($errors)) {
752
                        $errors[]['message'] = '';
753
                    }
754
755
                    if (( $responseCode == 404 ) && ($this->ignoreNotFound === true)) {
756
                        break;
757
                    }
758
                    foreach ($errors as $error) {
759
                        $this->addStatusMessage(sprintf('Error (HTTP %d): %s %s',
760
                                $responseCode,
761
                                implode('; ', $error)
762
                                , $this->lastCurlError), 'error');
763
                    }
764
765
                    $this->addStatusMessage($url, 'info');
766
                    if (!empty($this->postFields) && $this->debug === true) {
767
                        if (is_array($this->postFields)) {
768
                            $this->addStatusMessage(urldecode(http_build_query($this->postFields)),
769
                                'debug');
770
                        } else {
771
                            $this->addStatusMessage(urldecode($this->postFields),
772
                                'debug');
773
                        }
774
                    }
775
                }
776
777
                break;
778
        }
779
780
        if ($this->debug === true) {
781
            $this->saveDebugFiles();
782
        }
783
784
        return $response;
785
    }
786
787
    /**
788
     * Parse Raw FlexiBee response in several formats
789
     *
790
     * @param string $responseRaw
791
     * @param string $format
792
     *
793
     * @return array
794
     */
795
    public function rawResponseToArray($responseRaw, $format)
796
    {
797
        switch ($format) {
798
            case 'json':
799
                $responseDecoded = json_decode($responseRaw, true, 10);
800
                if (($method == 'PUT') && isset($responseDecoded[$this->nameSpace][$this->resultField][0]['id'])) {
0 ignored issues
show
Bug introduced by
The variable $method does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
801
                    $this->lastInsertedID = $responseDecoded[$this->nameSpace][$this->resultField][0]['id'];
802
                    $this->setMyKey($this->lastInsertedID);
803
                    $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
804
                } else {
805
                    $this->lastInsertedID = null;
806
                    if (isset($responseDecoded[$this->nameSpace]['@rowCount'])) {
807
                        $this->rowCount = (int) $responseDecoded[$this->nameSpace]['@rowCount'];
808
                    }
809
                }
810
                $decodeError = json_last_error_msg();
811
                if ($decodeError != 'No error') {
812
                    $this->addStatusMessage($decodeError, 'error');
813
                }
814
                break;
815
            case 'xml':
816
                if (strlen($this->lastCurlResponse)) {
817
                    $responseDecoded = self::xml2array($this->lastCurlResponse);
818
                } else {
819
                    $responseDecoded = null;
820
                }
821
                break;
822
            case 'txt':
823
            default:
824
                $responseDecoded = $this->lastCurlResponse;
825
                break;
826
        }
827
        return $responseDecoded;
828
    }
829
830
    public function parseResponse($responseArray)
831
    {
832
        return $responseArray;
833
    }
834
835
    /**
836
     * Vykonej HTTP požadavek
837
     *
838
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
839
     * @param string $url    URL požadavku
840
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
841
     * @param string $format požadovaný formát komunikace
842
     * @return int HTTP Response CODE
843
     */
844
    public function doCurlRequest($url, $method, $format = null)
845
    {
846
        if (is_null($format)) {
847
            $format = $this->format;
848
        }
849
        curl_setopt($this->curl, CURLOPT_URL, $url);
850
// Nastavení samotné operace
851
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
852
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
853
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
854
855
        $httpHeaders = $this->defaultHttpHeaders;
856
857
        $formats = $this->reindexArrayBy(self::$formats, 'suffix');
858
859
        if (!isset($httpHeaders['Accept'])) {
860
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
861
        }
862
        if (!isset($httpHeaders['Content-Type'])) {
863
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
864
        }
865
        $httpHeadersFinal = [];
866
        foreach ($httpHeaders as $key => $value) {
867
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
868
                $value .= ' v'.self::$libVersion;
869
            }
870
            $httpHeadersFinal[] = $key.': '.$value;
871
        }
872
873
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
874
875
// Proveď samotnou operaci
876
        $this->lastCurlResponse = curl_exec($this->curl);
877
        $this->info             = curl_getinfo($this->curl);
878
        $this->responseFormat   = Formats::contentTypeToSuffix($this->info['content_type']);
0 ignored issues
show
Bug introduced by
The method contentTypeToSuffix() does not seem to exist on object<FlexiPeeHP\Formats>.

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...
879
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
880
        return $this->lastResponseCode;
881
    }
882
883
    /**
884
     * Nastaví druh prováděné akce.
885
     *
886
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
887
     * @param string $action
888
     * @return boolean
889
     */
890
    public function setAction($action)
891
    {
892
        $result           = false;
893
        $actionsAvailable = $this->getActionsInfo();
894
        if (array_key_exists($action, $actionsAvailable)) {
895
            $this->action = $action;
896
            $result       = true;
897
        }
898
        return $result;
899
    }
900
901
    /**
902
     * Convert XML to array.
903
     *
904
     * @param string $xml
905
     *
906
     * @return array
907
     */
908
    public static function xml2array($xml)
909
    {
910
        $arr = [];
911
912
        if (is_string($xml)) {
913
            $xml = simplexml_load_string($xml);
914
        }
915
916
        foreach ($xml->children() as $r) {
917
            if (count($r->children()) == 0) {
918
                $arr[$r->getName()] = strval($r);
919
            } else {
920
                $arr[$r->getName()][] = self::xml2array($r);
921
            }
922
        }
923
924
        return $arr;
925
    }
926
927
    /**
928
     * Odpojení od FlexiBee.
929
     */
930
    public function disconnect()
931
    {
932
        if (is_resource($this->curl)) {
933
            curl_close($this->curl);
934
        }
935
        $this->curl = null;
936
    }
937
938
    /**
939
     * Disconnect CURL befere pass away
940
     */
941
    public function __destruct()
942
    {
943
        $this->disconnect();
944
    }
945
946
    /**
947
     * Načte řádek dat z FlexiBee.
948
     *
949
     * @param int $recordID id požadovaného záznamu
950
     *
951
     * @return array
952
     */
953
    public function getFlexiRow($recordID)
954
    {
955
        $record   = null;
956
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
957
        if (isset($response[$this->evidence])) {
958
            $record = $response[$this->evidence][0];
959
        }
960
961
        return $record;
962
    }
963
964
    /**
965
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
966
     *
967
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
968
     * @param array $conditions pole podmínek   - rendrují se do ()
969
     * @param array $urlParams  pole parametrů  - rendrují za ?
970
     */
971
    public function extractUrlParams(&$conditions, &$urlParams)
972
    {
973
        foreach ($this->urlParams as $urlParam) {
974
            if (isset($conditions[$urlParam])) {
975
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
976
            }
977
        }
978
    }
979
980
    /**
981
     * Načte data z FlexiBee.
982
     *
983
     * @param string $suffix     dotaz
984
     * @param string|array $conditions Volitelný filtrovací výraz
985
     */
986
    public function getFlexiData($suffix = null, $conditions = null)
987
    {
988
        $urlParams = $this->defaultUrlParams;
989
        if (!is_null($conditions)) {
990
            if (is_array($conditions)) {
991
                $this->extractUrlParams($conditions, $urlParams);
992
                $conditions = $this->flexiUrl($conditions);
993
            }
994
995
            if (strlen($conditions) && ($conditions[0] != '/')) {
996
                $conditions = '/'.rawurlencode('('.($conditions).')');
997
            }
998
        } else {
999
            $conditions = '';
1000
        }
1001
1002
        if (preg_match('/^http/', $suffix)) {
1003
            $transactions = $this->performRequest($suffix, 'GET');
1004
        } else {
1005
            if (strlen($suffix)) {
1006
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
1007
                    'GET');
1008
            } else {
1009
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
1010
                    'GET');
1011
            }
1012
        }
1013
        if (isset($transactions[$this->evidence])) {
1014
            $result = $transactions[$this->evidence];
1015
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
1016
                $result = null; // Response is empty Array
1017
            }
1018
        } else {
1019
            $result = $transactions;
1020
        }
1021
1022
        return $result;
1023
    }
1024
1025
    /**
1026
     * Načte záznam z FlexiBee.
1027
     *
1028
     * @param int $id ID záznamu
1029
     *
1030
     * @return int počet načtených položek
1031
     */
1032
    public function loadFromFlexiBee($id = null)
1033
    {
1034
        $data = [];
1035
        if (is_null($id)) {
1036
            $id = $this->getMyKey();
1037
        }
1038
1039
        $flexidata    = $this->getFlexiData(null, '/'.$id);
1040
        $this->apiURL = $this->info['url'];
1041
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1042
            $data = current($flexidata);
1043
        }
1044
        return $this->takeData($data);
1045
    }
1046
1047
    /**
1048
     * Převede data do Json formátu pro FlexiBee.
1049
     * Convert data to FlexiBee like Json format
1050
     *
1051
     * @param array $data
1052
     *
1053
     * @return string
1054
     */
1055
    public function jsonizeData($data)
1056
    {
1057
        $jsonize = [
1058
            $this->nameSpace => [
1059
                '@version' => $this->protoVersion,
1060
                $this->evidence => $this->objectToID($data),
1061
            ],
1062
        ];
1063
1064
        if (!is_null($this->action)) {
1065
            $jsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1066
            $this->action                                         = null;
1067
        }
1068
1069
        return json_encode($jsonize);
1070
    }
1071
1072
    /**
1073
     * Test if given record ID exists in FlexiBee.
1074
     *
1075
     * @param string|int $identifer
1076
     */
1077
    public function idExists($identifer = null)
1078
    {
1079
        if (is_null($identifer)) {
1080
            $identifer = $this->getMyKey();
1081
        }
1082
        $flexiData = $this->getFlexiData(
1083
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
1084
1085
        return $flexiData;
1086
    }
1087
1088
    /**
1089
     * Test if given record exists in FlexiBee.
1090
     *
1091
     * @param array $data
1092
     * @return boolean Record presence status
1093
     */
1094
    public function recordExists($data = null)
1095
    {
1096
1097
        if (is_null($data)) {
1098
            $data = $this->getData();
1099
        }
1100
1101
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1102
            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...
1103
1104
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1105
            || !count($res[0])) {
1106
            $found = false;
1107
        } else {
1108
            $found = true;
1109
        }
1110
        return $found;
1111
    }
1112
1113
    /**
1114
     * Vrací z FlexiBee sloupečky podle podmínek.
1115
     *
1116
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1117
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1118
     *                                     sloupečku
1119
     * @return array
1120
     */
1121
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1122
    {
1123
        if (is_int($conditions)) {
1124
            $conditions = [$this->getmyKeyColumn() => $conditions];
1125
        }
1126
1127
        $flexiData = $this->getFlexiData('', $conditions);
1128
1129
        if (!is_null($indexBy)) {
1130
            $flexiData = $this->reindexArrayBy($flexiData);
1131
        }
1132
1133
        return $flexiData;
1134
    }
1135
1136
    /**
1137
     * Vrací z FlexiBee sloupečky podle podmínek.
1138
     *
1139
     * @param string[] $columnsList seznam položek
1140
     * @param array    $conditions  pole podmínek nebo ID záznamu
1141
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1142
     *
1143
     * @return array
1144
     */
1145
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1146
                                           $indexBy = null)
1147
    {
1148
        if (is_int($conditions)) {
1149
            $conditions = [$this->getmyKeyColumn() => $conditions];
1150
        }
1151
1152
        if ($columnsList != '*') {
1153
            if (is_array($columnsList)) {
1154
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1155
                        $columnsList)) {
1156
                    $columnsList[] = $indexBy;
1157
                }
1158
                $columns = implode(',', array_unique($columnsList));
1159
            } else {
1160
                $columns = $columnsList;
1161
            }
1162
            $detail = 'custom:'.$columns;
0 ignored issues
show
Unused Code introduced by
$detail is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1163
        }
1164
        switch ($columnsList) {
1165
            case 'id':
1166
                $detail = 'id';
1167
                break;
1168
            case 'summary':
1169
                $detail = 'summary';
1170
                break;
1171
            case 'full':
1172
            default:
1173
                $detail = 'full';
1174
                break;
1175
        }
1176
1177
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1178
1179
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1180
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1181
        }
1182
1183
        return $flexiData;
1184
    }
1185
1186
    /**
1187
     * Vrací kód záznamu.
1188
     *
1189
     * @param mixed $data
1190
     *
1191
     * @return string
1192
     */
1193
    public function getKod($data = null, $unique = true)
1194
    {
1195
        $kod = null;
1196
1197
        if (is_null($data)) {
1198
            $data = $this->getData();
1199
        }
1200
1201
        if (is_string($data)) {
1202
            $data = [$this->nameColumn => $data];
1203
        }
1204
1205
        if (isset($data['kod'])) {
1206
            $kod = $data['kod'];
1207
        } else {
1208
            if (isset($data[$this->nameColumn])) {
1209
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1210
                    \Ease\Sand::rip($data[$this->nameColumn]));
1211
            } else {
1212
                if (isset($data[$this->myKeyColumn])) {
1213
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1214
                }
1215
            }
1216
        }
1217
1218
        if (!strlen($kod)) {
1219
            $kod = 'NOTSET';
1220
        }
1221
1222
        if (strlen($kod) > 18) {
1223
            $kodfinal = strtoupper(substr($kod, 0, 18));
1224
        } else {
1225
            $kodfinal = strtoupper($kod);
1226
        }
1227
1228
        if ($unique) {
1229
            $counter = 0;
1230
            if (count($this->codes)) {
1231
                foreach ($this->codes as $codesearch => $keystring) {
1232
                    if (strstr($codesearch, $kodfinal)) {
1233
                        ++$counter;
1234
                    }
1235
                }
1236
            }
1237
            if ($counter) {
1238
                $kodfinal = $kodfinal.$counter;
1239
            }
1240
1241
            $this->codes[$kodfinal] = $kod;
1242
        }
1243
1244
        return $kodfinal;
1245
    }
1246
1247
    /**
1248
     * Write Operation Result.
1249
     *
1250
     * @param array  $resultData
1251
     * @param string $url        URL
1252
     * @return boolean Log save success
1253
     */
1254
    public function logResult($resultData = null, $url = null)
1255
    {
1256
        $logResult = false;
1257
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1258
            if (isset($resultData['message'])) {
1259
                $this->addStatusMessage($resultData['message'], 'warning');
1260
            }
1261
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1262
                'warning');
1263
            unset($url);
1264
        }
1265
        if (is_null($resultData)) {
1266
            $resultData = $this->lastResult;
1267
        }
1268
        if (isset($url)) {
1269
            $this->logger->addStatusMessage(urldecode($url));
1270
        }
1271
1272
        if (isset($resultData['results'])) {
1273
            $status = null;
0 ignored issues
show
Unused Code introduced by
$status is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1274
            if ($resultData['success'] == 'false') {
1275
                $status = 'error';
1276
            } else {
1277
                $status = 'success';
1278
            }
1279
            foreach ($resultData['results'] as $result) {
1280
                if (isset($result['request-id'])) {
1281
                    $rid = $result['request-id'];
1282
                } else {
1283
                    $rid = '';
1284
                }
1285
                if (isset($result['errors'])) {
1286
                    foreach ($result['errors'] as $error) {
1287
                        $message = $error['message'];
1288
                        if (isset($error['for'])) {
1289
                            $message .= ' for: '.$error['for'];
1290
                        }
1291
                        if (isset($error['value'])) {
1292
                            $message .= ' value:'.$error['value'];
1293
                        }
1294
                        if (isset($error['code'])) {
1295
                            $message .= ' code:'.$error['code'];
1296
                        }
1297
                        $this->addStatusMessage($rid.': '.$message, $status);
1298
                    }
1299
                }
1300
            }
1301
        }
1302
        return $logResult;
1303
    }
1304
1305
    /**
1306
     * Save RAW Curl Request & Response to files in Temp directory
1307
     */
1308
    public function saveDebugFiles()
1309
    {
1310
        $tmpdir = sys_get_temp_dir();
1311
        file_put_contents($tmpdir.'/request-'.$this->evidence.'-'.microtime().'.'.$this->format,
1312
            $this->postFields);
1313
        file_put_contents($tmpdir.'/response-'.$this->evidence.'-'.microtime().'.'.$this->format,
1314
            $this->lastCurlResponse);
1315
    }
1316
1317
    /**
1318
     * Připraví data pro odeslání do FlexiBee
1319
     *
1320
     * @param string $data
1321
     */
1322
    public function setPostFields($data)
1323
    {
1324
        $this->postFields = $data;
1325
    }
1326
1327
    /**
1328
     * Generuje fragment url pro filtrování.
1329
     *
1330
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1331
     *
1332
     * @param array  $data
1333
     * @param string $joiner default and/or
1334
     * @param string $defop  default operator
1335
     *
1336
     * @return string
1337
     */
1338
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1339
    {
1340
        $flexiUrl = '';
0 ignored issues
show
Unused Code introduced by
$flexiUrl is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1341
        $parts    = [];
1342
1343
        foreach ($data as $column => $value) {
1344
            if (is_integer($data[$column]) || is_float($data[$column])) {
1345
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1346
            } elseif (is_bool($data[$column])) {
1347
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1348
            } elseif (is_null($data[$column])) {
1349
                $parts[$column] = $column." is null";
1350
            } else {
1351
                switch ($value) {
1352
                    case '!null':
1353
                        $parts[$column] = $column." is not null";
1354
                        break;
1355
                    case 'is empty':
1356
                    case 'is not empty':
1357
                        $parts[$column] = $column.' '.$value;
1358
                        break;
1359
                    default:
1360
                        $parts[$column] = $column." $defop '".$data[$column]."'";
1361
                        break;
1362
                }
1363
            }
1364
        }
1365
1366
        $flexiUrl = implode(' '.$joiner.' ', $parts);
1367
1368
        return $flexiUrl;
1369
    }
1370
1371
    /**
1372
     * Obtain record/object identificator code: or id:
1373
     * Vrací identifikátor objektu code: nebo id:
1374
     *
1375
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1376
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1377
     */
1378
    public function getRecordID()
1379
    {
1380
        $myCode = $this->getDataValue('kod');
1381
        if ($myCode) {
1382
            $id = 'code:'.$myCode;
1383
        } else {
1384
            $id = $this->getDataValue('id');
1385
            if (($this->debug === true) && is_null($id)) {
1386
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1387
                    'warning');
1388
            }
1389
        }
1390
        return is_numeric($id) ? intval($id) : strval($id);
1391
    }
1392
1393
    /**
1394
     * Obtain record/object identificator code: or id:
1395
     * Vrací identifikátor objektu code: nebo id:
1396
     *
1397
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1398
     * @return string indentifikátor záznamu reprezentovaného objektem
1399
     */
1400
    public function __toString()
1401
    {
1402
        return strval($this->getRecordID());
1403
    }
1404
1405
    /**
1406
     * Gives you FlexiPeeHP class name for Given Evidence
1407
     *
1408
     * @param string $evidence
1409
     * @return string Class name
1410
     */
1411
    static public function evidenceToClassName($evidence)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
1412
    {
1413
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1414
    }
1415
1416
    /**
1417
     * Vrací hodnotu daného externího ID
1418
     *
1419
     * @param string $want Which ? If empty,you obtain the first one.
1420
     * @return string
1421
     */
1422
    public function getExternalID($want = null)
1423
    {
1424
        $extid = null;
1425
        $ids   = $this->getDataValue('external-ids');
1426
        if (is_null($want)) {
1427
            if (count($ids)) {
1428
                $extid = current($ids);
1429
            }
1430
        } else {
1431
            if (!is_null($ids) && is_array($ids)) {
1432
                foreach ($ids as $id) {
1433
                    if (strstr($id, 'ext:'.$want)) {
1434
                        $extid = str_replace('ext:'.$want.':', '', $id);
1435
                    }
1436
                }
1437
            }
1438
        }
1439
        return $extid;
1440
    }
1441
1442
    /**
1443
     * Obtain actual GlobalVersion
1444
     * Vrací aktuální globální verzi změn
1445
     *
1446
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1447
     * @return type
1448
     */
1449
    public function getGlobalVersion()
1450
    {
1451
        $globalVersion = null;
1452
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1453
            $this->getFlexiData(null,
1454
                ['add-global-version' => 'true', 'limit' => 1]);
1455
        }
1456
1457
        if (isset($this->lastResult['@globalVersion'])) {
1458
            $globalVersion = intval($this->lastResult['@globalVersion']);
1459
        }
1460
1461
        return $globalVersion;
1462
    }
1463
1464
    /**
1465
     * Obtain content type of last response
1466
     *
1467
     * @return string
1468
     */
1469
    public function getResponseFormat()
1470
    {
1471
        if (isset($this->info['content_type'])) {
1472
            $responseFormat = $this->info['content_type'];
1473
        } else {
1474
            $responseFormat = null;
1475
        }
1476
        return $responseFormat;
1477
    }
1478
1479
    /**
1480
     * Return the same response format for one and multiplete results
1481
     *
1482
     * @param array $responseRaw
1483
     * @return array
1484
     */
1485
    public function unifyResponseFormat($responseRaw)
1486
    {
1487
        $response = $responseRaw;
1488
        $evidence = $this->getResponseEvidence();
1489
        if (is_array($responseRaw)) {
1490
// Get response body root automatically
1491
            if (array_key_exists($this->nameSpace, $responseRaw)) { //Unifi response format
1492
                $responseBody = $responseRaw[$this->nameSpace];
1493
                if (array_key_exists($evidence, $responseBody)) {
1494
                    $evidenceContent = $responseBody[$evidence];
1495
                    if (array_key_exists(0, $evidenceContent)) {
1496
                        $response[$evidence] = $evidenceContent; //Multiplete Results
1497
                    } else {
1498
                        $response[$evidence][0] = $evidenceContent; //One result
1499
                    }
1500
                } else {
1501
                    if (isset($responseBody['priloha'])) {
1502
                        $response = $responseBody['priloha'];
1503
                    } else {
1504
                        $response = $responseBody;
1505
                    }
1506
                }
1507
            } else {
1508
                $response = $responseRaw;
1509
            }
1510
        }
1511
        return $response;
1512
    }
1513
1514
    /**
1515
     * Obtain structure for current (or given) evidence
1516
     *
1517
     * @param string $evidence
1518
     * @return array Evidence structure
1519
     */
1520 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...
1521
    {
1522
        $columnsInfo = null;
1523
        if (is_null($evidence)) {
1524
            $evidence = $this->getEvidence();
1525
        }
1526
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1527
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1528
            $columnsInfo = Properties::$$propsName;
1529
        }
1530
        return $columnsInfo;
1531
    }
1532
1533
    /**
1534
     * Obtain actions for current (or given) evidence
1535
     *
1536
     * @param string $evidence
1537
     * @return array Evidence structure
1538
     */
1539 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...
1540
    {
1541
        $actionsInfo = null;
1542
        if (is_null($evidence)) {
1543
            $evidence = $this->getEvidence();
1544
        }
1545
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1546
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1547
            $actionsInfo = Actions::$$propsName;
1548
        }
1549
        return $actionsInfo;
1550
    }
1551
1552
    /**
1553
     * Obtain relations for current (or given) evidence
1554
     *
1555
     * @param string $evidence
1556
     * @return array Evidence structure
1557
     */
1558
    public function getRelationsInfo($evidence = null)
1559
    {
1560
        $relationsInfo = null;
1561
        if (is_null($evidence)) {
1562
            $evidence = $this->getEvidence();
1563
        }
1564
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1565
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1566
            $relationsInfo = Relations::$$propsName;
1567
        }
1568
        return $relationsInfo;
1569
    }
1570
1571
    /**
1572
     * Obtain info for current (or given) evidence
1573
     *
1574
     * @param string $evidence
1575
     * @return array Evidence info
1576
     */
1577 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...
1578
    {
1579
        $evidencesInfo = null;
1580
        if (is_null($evidence)) {
1581
            $evidence = $this->getEvidence();
1582
        }
1583
        if (isset(EvidenceList::$evidences[$evidence])) {
1584
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1585
        }
1586
        return $evidencesInfo;
1587
    }
1588
1589
    /**
1590
     * Obtain name for current (or given) evidence path
1591
     *
1592
     * @param string $evidence Evidence Path
1593
     * @return array Evidence info
1594
     */
1595 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...
1596
    {
1597
        $evidenceName = null;
1598
        if (is_null($evidence)) {
1599
            $evidence = $this->getEvidence();
1600
        }
1601
        if (isset(EvidenceList::$name[$evidence])) {
1602
            $evidenceName = EvidenceList::$name[$evidence];
1603
        }
1604
        return $evidenceName;
1605
    }
1606
1607
    /**
1608
     * Perform given action (if availble) on current evidence/record
1609
     * @url https://demo.flexibee.eu/devdoc/actions
1610
     *
1611
     * @param string $action one of evidence actions
1612
     * @param string $method ext|int External method call operation in URL.
1613
     *                               Internal add the @action element to request body
1614
     */
1615
    public function performAction($action, $method = 'ext')
1616
    {
1617
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1618
1619
        $actionsAvailble = $this->getActionsInfo();
1620
1621
        if (is_array($actionsAvailble) && array_key_exists($action,
1622
                $actionsAvailble)) {
1623
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1624
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1625
                case 'ONLY_WITH_INSTANCE': //Add instance
1626
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1627
                    break;
1628
1629
                default:
1630
                    $urlSuffix = '/'.$action;
1631
                    break;
1632
            }
1633
1634
            switch ($method) {
1635
                case 'int':
1636
                    $this->setAction($action);
1637
                    $this->setPostFields($this->jsonizeData($this->getData()));
1638
                    $result = $this->performRequest(null, 'POST');
1639
                    break;
1640
1641
                default:
1642
                    $result = $this->performRequest($urlSuffix, 'GET');
1643
                    break;
1644
            }
1645
        } else {
1646
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1647
                $action, $this->getEvidence()));
1648
        }
1649
1650
        return $result;
1651
    }
1652
1653
    /**
1654
     * Save current object to file
1655
     *
1656
     * @param string $destfile path to file
1657
     */
1658
    public function saveResponseToFile($destfile)
1659
    {
1660
        if (strlen($this->lastCurlResponse)) {
1661
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1662
        }
1663
        file_put_contents($destfile, $this->lastCurlResponse);
1664
    }
1665
1666
    /**
1667
     * Obtain established relations listing
1668
     *
1669
     * @return array Null or Relations
1670
     */
1671
    public function getVazby()
1672
    {
1673
        $vazby = $this->getDataValue('vazby');
1674
        if (is_null($vazby)) {
1675
            $vazby = $this->getColumnsFromFlexibee('*',
0 ignored issues
show
Documentation introduced by
'*' is of type string, but the function expects a array<integer,string>.

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...
1676
                ['relations' => 'vazby', 'id' => $this->getRecordID()]);
1677
            $vazby = $vazby[0]['vazby'];
1678
        }
1679
        return $vazby;
1680
    }
1681
1682
    /**
1683
     * Gives You URL for Current Record in FlexiBee web interface
1684
     *
1685
     * @return string url
1686
     */
1687
    public function getFlexiBeeURL()
1688
    {
1689
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1690
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1691
                : '';
1692
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1693
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1694
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1695
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1696
        $pass       = ($user || $pass) ? "$pass@" : '';
1697
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1698
        return $scheme.$user.$pass.$host.$port.$path;
1699
    }
1700
1701
    /**
1702
     * Set Record Key
1703
     *
1704
     * @param int|string $myKeyValue
1705
     * @return boolean
1706
     */
1707
    public function setMyKey($myKeyValue)
1708
    {
1709
        $res = parent::setMyKey($myKeyValue);
1710
        $this->updateApiURL();
1711
        return $res;
1712
    }
1713
1714
    /**
1715
     * Set or get ignore not found pages flag
1716
     *
1717
     * @param boolean $ignore set flag to
1718
     *
1719
     * @return boolean get flag state
1720
     */
1721
    public function ignore404($ignore = null)
1722
    {
1723
        if (!is_null($ignore)) {
1724
            $this->ignoreNotFound = $ignore;
1725
        }
1726
        return $this->ignoreNotFound;
1727
    }
1728
1729
    /**
1730
     * Send Document by mail
1731
     *
1732
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1733
     *
1734
     * @param string $to
1735
     * @param string $subject
1736
     * @param string $body Email Text
1737
     *
1738
     * @return int http response code
1739
     */
1740
    public function sendByMail($to, $subject, $body, $cc = null)
1741
    {
1742
        $this->setPostFields($body);
1743
        $result = $this->doCurlRequest($this->getEvidenceURL().'/'.
1744
            urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1745
            , 'PUT', 'xml');
1746
        return $result == 200;
1747
    }
1748
1749
    /**
1750
     * Send all unsent Invoices by mail
1751
     *
1752
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1753
     * @return int http response code
1754
     */
1755
    public function sendUnsent()
1756
    {
1757
        return $this->doCurlRequest($this->getEvidenceURL().'/automaticky-odeslat-neodeslane',
1758
                'PUT', 'xml');
1759
    }
1760
1761
    /**
1762
     * FlexiBee date to PHP DateTime
1763
     *
1764
     * @param string $flexidate
1765
     * @return \DateTime
1766
     */
1767
    public static function flexiDateToDateTime($flexidate)
1768
    {
1769
        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 1769 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...
1770
    }
1771
1772
    /**
1773
     * Uloží dokument v daném formátu do složky v systému souborů
1774
     * Save document in given format to directory in filesystem
1775
     *
1776
     * @param string $format  pdf/csv/xml/json/ ...
1777
     * @param string $destDir where to put file (prefix)
1778
     * 
1779
     * @return string|null filename downloaded or none
1780
     */
1781
    public function downloadInFormat($format, $destDir = './')
1782
    {
1783
        $fileOnDisk = null;
1784
        if ($this->setFormat($format)) {
1785
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1786
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1787
                    $this->lastCurlResponse) !== false)) {
1788
                $fileOnDisk = $downloadTo;
1789
            }
1790
        }
1791
        return $fileOnDisk;
1792
    }
1793
}
1794