Completed
Push — master ( 596467...bf19e6 )
by Vítězslav
11:06
created

FlexiBeeRO::getResponseEvidence()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

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...
442
443
        if (is_null($format)) {
444
            $format = $this->format;
445
        }
446
447
        switch ($responseCode) {
448
            case 200:
449
            case 201:
450
                // Parse response
451
                $responseDecoded = [];
452
453
                switch ($format) {
454
                    case 'json':
455
                        $responseDecoded = json_decode($this->lastCurlResponse,
456
                            true, 10);
457
                        if (($method == 'PUT') && isset($responseDecoded[$this->nameSpace][$this->resultField][0]['id'])) {
458
                            $this->lastInsertedID = $responseDecoded[$this->nameSpace][$this->resultField][0]['id'];
459
                            $this->setMyKey($this->lastInsertedID);
460
                        } else {
461
                            $this->lastInsertedID = null;
462
                        }
463
                        $decodeError = json_last_error_msg();
464
                        if ($decodeError != 'No error') {
465
                            $this->addStatusMessage($decodeError, 'error');
466
                        }
467
                        break;
468
                    case 'xml':
469
                        if (strlen($this->lastCurlResponse)) {
470
                            $responseDecoded = self::xml2array($this->lastCurlResponse);
471
                        } else {
472
                            $responseDecoded = null;
473
                        }
474
                        break;
475
                }
476
477
478
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
479
480
                break;
481
482
            default: //Some goes wrong
483
                $this->lastCurlError = curl_error($this->curl);
484
                switch ($format) {
485
                    case 'json':
486
                        $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
487
                            function ($match) {
488
                            return mb_convert_encoding(pack('H*', $match[1]),
489
                                'UTF-8', 'UCS-2BE');
490
                        }, $this->lastCurlResponse);
491
                        $response = (json_encode(json_decode($response, true, 10),
492
                                JSON_PRETTY_PRINT));
493
                        break;
494
                    case 'xml':
495
                        if (strlen($this->lastCurlResponse)) {
496
                            $response = self::xml2array($this->lastCurlResponse);
497
                        }
498
                        break;
499
                }
500
501
                if (is_array($response)) {
502
                    $result = urldecode(http_build_query($response));
0 ignored issues
show
Bug introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
503
                } elseif (strlen($response) && ($response != 'null')) {
504
                    $result = urldecode(http_build_query(self::object2array(current(json_decode($response)))));
505
                } else {
506
                    $result = null;
507
                }
508
509
                if ($response == 'null') {
510
                    if ($this->lastResponseCode == 200) {
511
                        $response = true;
512
                    } else {
513
                        $response = null;
514
                    }
515
                } else {
516
                    if (is_string($response)) {
517
                        $response = self::object2array(current(json_decode($response)));
518
                    }
519
                }
520
521
                if (is_array($response) && ($this->lastResponseCode == 400)) {
522
                    $this->logResult($response, $url);
523
                } else {
524
                    $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
525
                            curl_getinfo($this->curl, CURLINFO_HTTP_CODE),
526
                            $result, $this->lastCurlError), 'error');
527
                    $this->addStatusMessage($url, 'info');
528
                    if (count($this->postFields)) {
529
                        if (is_array($result)) {
530
                            $this->addStatusMessage(urldecode(http_build_query($this->postFields)),
531
                                'debug');
532
                        } else {
533
                            $this->addStatusMessage(urldecode(http_build_query($this->getData())),
534
                                'debug');
535
                        }
536
                    }
537
                }
538
539
                break;
540
        }
541
        return $response;
542
    }
543
544
    /**
545
     * Vykonej HTTP požadavek
546
     *
547
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
548
     * @param string $url    URL požadavku
549
     * @param strinf $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
550
     * @param string $format požadovaný formát komunikace
551
     * @return int HTTP Response CODE
552
     */
553
    public function doCurlRequest($url, $method, $format = null)
554
    {
555
        if (is_null($format)) {
556
            $format = $this->format;
557
        }
558
        curl_setopt($this->curl, CURLOPT_URL, $url);
559
// Nastavení samotné operace
560
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
561
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
562
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
563
564
        $httpHeaders = $this->defaultHttpHeaders;
565
        switch ($format) {
566
            case 'json':
567
                $httpHeaders['Accept']       = 'application/json';
568
                $httpHeaders['Content-Type'] = 'application/json';
569
570
                break;
571
            case 'xml':
572
                $httpHeaders['Accept']       = 'application/xml';
573
                $httpHeaders['Content-Type'] = 'application/xml';
574
                break;
575
        }
576
577
        $httpHeadersFinal = [];
578
        foreach ($httpHeaders as $key => $value) {
579
            $httpHeadersFinal[] = $key.': '.$value;
580
        }
581
582
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
583
584
// Proveď samotnou operaci
585
        $this->lastCurlResponse = curl_exec($this->curl);
586
587
        $this->info = curl_getinfo($this->curl);
588
589
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
590
        return $this->lastResponseCode;
591
    }
592
593
    /**
594
     * Nastaví druh prováděné akce.
595
     *
596
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
597
     * @param string $action
598
     * @return boolean
599
     */
600
    public function setAction($action)
601
    {
602
        $result = false;
603
        if (is_null($this->actionsAvailable)) {
604
            $this->action = $action;
605
            $result       = true;
606
        } else {
607
            if (array_search($action, $this->actionsAvailable)) {
608
                $this->action = $action;
609
                $result       = true;
610
            }
611
        }
612
        return $result;
613
    }
614
615
    /**
616
     * Convert XML to array.
617
     *
618
     * @param string $xml
619
     *
620
     * @return array
621
     */
622
    public static function xml2array($xml)
623
    {
624
        $arr = [];
625
626
        if (is_string($xml)) {
627
            $xml = simplexml_load_string($xml);
628
        }
629
630
        foreach ($xml->children() as $r) {
631
            if (count($r->children()) == 0) {
632
                $arr[$r->getName()] = strval($r);
633
            } else {
634
                $arr[$r->getName()][] = self::xml2array($r);
635
            }
636
        }
637
638
        return $arr;
639
    }
640
641
    /**
642
     * Odpojení od FlexiBee.
643
     */
644
    public function disconnect()
645
    {
646
        if (is_resource($this->curl)) {
647
            curl_close($this->curl);
648
        }
649
        $this->curl = null;
650
    }
651
652
    public function __destruct()
653
    {
654
        $this->disconnect();
655
    }
656
657
    /**
658
     * Načte řádek dat z FlexiBee.
659
     *
660
     * @param int $recordID id požadovaného záznamu
661
     *
662
     * @return array
663
     */
664
    public function getFlexiRow($recordID)
665
    {
666
        $record   = null;
667
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
668
        if (isset($response[$this->evidence])) {
669
            $record = $response[$this->evidence][0];
670
        }
671
672
        return $record;
673
    }
674
675
    /**
676
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
677
     *
678
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
679
     * @param array $conditions pole podmínek   - rendrují se do ()
680
     * @param array $urlParams  pole parametrů  - rendrují za ?
681
     */
682
    public function extractUrlParams(&$conditions, &$urlParams)
683
    {
684
        foreach ($this->urlParams as $urlParam) {
685
            if (isset($conditions[$urlParam])) {
686
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
687
            }
688
        }
689
    }
690
691
    /**
692
     * Načte data z FlexiBee.
693
     *
694
     * @param string $suffix     dotaz
695
     * @param string|array $conditions Volitelný filtrovací výraz
696
     */
697
    public function getFlexiData($suffix = null, $conditions = null)
698
    {
699
        $urlParams = $this->defaultUrlParams;
700
        if (!is_null($conditions)) {
701
            if (is_array($conditions)) {
702
                $this->extractUrlParams($conditions, $urlParams);
703
                $conditions = $this->flexiUrl($conditions);
704
            }
705
706
            if (strlen($conditions) && ($conditions[0] != '/')) {
707
                $conditions = '/'.rawurlencode('('.($conditions).')');
708
            }
709
        } else {
710
            $conditions = '';
711
        }
712
        if (strlen($suffix)) {
713
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
714
                'GET');
715
        } else {
716
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
717
                'GET');
718
        }
719
        if (isset($transactions[$this->evidence])) {
720
            $result = $transactions[$this->evidence];
721
        } else {
722
            $result = $transactions;
723
        }
724
725
        return $result;
726
    }
727
728
    /**
729
     * Načte záznam z FlexiBee.
730
     *
731
     * @param int $id ID záznamu
732
     *
733
     * @return int počet načtených položek
734
     */
735 View Code Duplication
    public function loadFromFlexiBee($id = 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...
736
    {
737
        $data = [];
738
        if (is_null($id)) {
739
            $id = $this->getMyKey();
740
        }
741
742
        $flexidata = $this->getFlexiData(null, '/'.$id);
743
        if (count($flexidata) == 1) {
744
            $data = current($flexidata);
745
        }
746
        return $this->takeData($data);
747
    }
748
749
    /**
750
     * Převede data do Json formátu pro FlexiBee.
751
     *
752
     * @param array $data
753
     *
754
     * @return string
755
     */
756
    public function jsonizeData($data)
757
    {
758
        $jsonize = [
759
            $this->nameSpace => [
760
                '@version' => $this->protoVersion,
761
                $this->evidence => $this->objectToID($data),
762
            ],
763
        ];
764
765
        if (!is_null($this->action)) {
766
            $jsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
767
            $this->action                                         = null;
768
        }
769
770
        return json_encode($jsonize);
771
    }
772
773
    /**
774
     * Test if given record ID exists in FlexiBee.
775
     *
776
     * @param string|int $identifer
777
     */
778
    public function idExists($identifer = null)
779
    {
780
        if (is_null($identifer)) {
781
            $identifer = $this->getMyKey();
782
        }
783
        $flexiData = $this->getFlexiData(
784
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
785
786
        return $flexiData;
787
    }
788
789
    /**
790
     * Test if given record exists in FlexiBee.
791
     *
792
     * @param array $data
793
     * @return boolean Record presence status
794
     */
795
    public function recordExists($data = null)
796
    {
797
        $found = null;
0 ignored issues
show
Unused Code introduced by
$found 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...
798
        if (is_null($data)) {
799
            $data = $this->getData();
800
        }
801
802
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
803
            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...
804
805
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
806
            || !count($res[0])) {
807
            $found = false;
808
        } else {
809
            $found = true;
810
        }
811
        return $found;
812
    }
813
814
    /**
815
     * Vrací z FlexiBee sloupečky podle podmínek.
816
     *
817
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
818
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
819
     *                                     sloupečku
820
     * @return array
821
     */
822 View Code Duplication
    public function getAllFromFlexibee($conditions = null, $indexBy = 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...
823
    {
824
        if (is_int($conditions)) {
825
            $conditions = [$this->getmyKeyColumn() => $conditions];
826
        }
827
828
        $flexiData = $this->getFlexiData('', $conditions);
829
830
        if (!is_null($indexBy)) {
831
            $flexiData = $this->reindexArrayBy($flexiData);
832
        }
833
834
        return $flexiData;
835
    }
836
837
    /**
838
     * Vrací z FlexiBee sloupečky podle podmínek.
839
     *
840
     * @param string[] $columnsList seznam položek
841
     * @param array    $conditions  pole podmínek nebo ID záznamu
842
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
843
     *
844
     * @return array
845
     */
846
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
847
                                           $indexBy = null)
848
    {
849
        if (($columnsList != '*') && !count($columnsList)) {
850
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
851
852
            return;
853
        }
854
855
        if (is_int($conditions)) {
856
            $conditions = [$this->getmyKeyColumn() => $conditions];
857
        }
858
859
        if (is_array($columnsList)) {
860
            $columns = implode(',', array_unique($columnsList));
861
        } else {
862
            $columns = $columnsList;
863
        }
864
865
        $flexiData = $this->getFlexiData('detail=custom:'.$columns, $conditions);
866
867
        if (!is_null($indexBy)) {
868
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
869
        }
870
871
        return $flexiData;
872
    }
873
874
    /**
875
     * Vrací kód záznamu.
876
     *
877
     * @param mixed $data
878
     *
879
     * @return string
880
     */
881
    public function getKod($data = null, $unique = true)
882
    {
883
        $kod = null;
884
885
        if (is_null($data)) {
886
            $data = $this->getData();
887
        }
888
889
        if (is_string($data)) {
890
            $data = [$this->nameColumn => $data];
891
        }
892
893
        if (isset($data['kod'])) {
894
            $kod = $data['kod'];
895
        } else {
896
            if (isset($data[$this->nameColumn])) {
897
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
898
                    \Ease\Sand::rip($data[$this->nameColumn]));
899
            } else {
900
                if (isset($data[$this->myKeyColumn])) {
901
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
902
                }
903
            }
904
        }
905
906
        if (!strlen($kod)) {
907
            $kod = 'NOTSET';
908
        }
909
910
        if (strlen($kod) > 18) {
911
            $kodfinal = strtoupper(substr($kod, 0, 18));
912
        } else {
913
            $kodfinal = strtoupper($kod);
914
        }
915
916
        if ($unique) {
917
            $counter = 0;
918
            if (count($this->codes)) {
919
                foreach ($this->codes as $codesearch => $keystring) {
920
                    if (strstr($codesearch, $kodfinal)) {
921
                        ++$counter;
922
                    }
923
                }
924
            }
925
            if ($counter) {
926
                $kodfinal = $kodfinal.$counter;
927
            }
928
929
            $this->codes[$kodfinal] = $kod;
930
        }
931
932
        return $kodfinal;
933
    }
934
935
    /**
936
     * Write Operation Result.
937
     *
938
     * @param array  $resultData
939
     * @param string $url        URL
940
     * @return boolean Log save success
941
     */
942
    public function logResult($resultData = null, $url = null)
943
    {
944
        $logResult = false;
945
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
946
            if (isset($resultData['message'])) {
947
                $this->addStatusMessage($resultData['message'], 'warning');
948
            }
949
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
950
                'warning');
951
            unset($url);
952
        }
953
        if (is_null($resultData)) {
954
            $resultData = $this->lastResult;
955
        }
956
        if (isset($url)) {
957
            $this->logger->addStatusMessage(urldecode($url));
958
        }
959
960
        if (isset($resultData['results'])) {
961
            $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...
962
            if ($resultData['success'] == 'false') {
963
                $status = 'error';
964
            } else {
965
                $status = 'success';
966
            }
967
            foreach ($resultData['results'] as $result) {
968
                if (isset($result['request-id'])) {
969
                    $rid = $result['request-id'];
970
                } else {
971
                    $rid = '';
972
                }
973
                if (isset($result['errors'])) {
974
                    foreach ($result['errors'] as $error) {
975
                        $message = $error['message'];
976
                        if (isset($error['for'])) {
977
                            $message .= ' for: '.$error['for'];
978
                        }
979
                        if (isset($error['value'])) {
980
                            $message .= ' value:'.$error['value'];
981
                        }
982
                        if (isset($error['code'])) {
983
                            $message .= ' code:'.$error['code'];
984
                        }
985
                        $this->addStatusMessage($rid.': '.$message, $status);
986
                    }
987
                }
988
            }
989
        }
990
991
        if (is_object($this->logger)) {
992
            $logResult = $this->logger->flush(get_class($this));
993
        }
994
        return $logResult;
995
    }
996
997
    /**
998
     * Save RAW Curl Request & Response to files in Temp directory
999
     */
1000
    public function saveDebugFiles()
1001
    {
1002
        $tmpdir = sys_get_temp_dir();
1003
        file_put_contents($tmpdir.'/request-'.$this->evidence.'-'.microtime().'.'.$this->format,
1004
            $this->postFields);
1005
        file_put_contents($tmpdir.'/response-'.$this->evidence.'-'.microtime().'.'.$this->format,
1006
            $this->lastCurlResponse);
1007
    }
1008
1009
    /**
1010
     * Připraví data pro odeslání do FlexiBee
1011
     * 
1012
     * @param string $data
1013
     */
1014
    public function setPostFields($data)
1015
    {
1016
        $this->postFields = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data of type string is incompatible with the declared type array of property $postFields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
1017
    }
1018
1019
    /**
1020
     * Generuje fragment url pro filtrování.
1021
     *
1022
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1023
     *
1024
     * @param array  $data
1025
     * @param string $operator default and/or
1026
     *
1027
     * @return string
1028
     */
1029
    public static function flexiUrl(array $data, $operator = 'and')
1030
    {
1031
        $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...
1032
        $parts    = [];
1033
1034
        foreach ($data as $column => $value) {
1035
            if (is_integer($data[$column]) || is_float($data[$column])) {
1036
                $parts[$column] = $column.' eq '.$data[$column];
1037
            } elseif (is_bool($data[$column])) {
1038
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1039
            } elseif (is_null($data[$column])) {
1040
                $parts[$column] = $column." is null";
1041
            } elseif ($value == '!null') {
1042
                $parts[$column] = $column." is not null";
1043
            } else {
1044
                $parts[$column] = $column." eq '".$data[$column]."'";
1045
            }
1046
        }
1047
1048
        $flexiUrl = implode(' '.$operator.' ', $parts);
1049
1050
        return $flexiUrl;
1051
    }
1052
1053
    /**
1054
     * Vrací identifikátor objektu code: nebo id:
1055
     *
1056
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1057
     * @return string indentifikátor záznamu reprezentovaného objektem
1058
     */
1059
    public function __toString()
1060
    {
1061
        $myCode = $this->getDataValue('kod');
1062
        if ($myCode) {
1063
            $id = 'code:'.$myCode;
1064
        } else {
1065
            $id = $this->getDataValue('id');
1066
            if (is_null($id)) {
1067
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1068
                    'warning');
1069
            }
1070
        }
1071
        return $id;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $id; (object|integer|double|string|array|boolean|null) is incompatible with the return type of the parent method Ease\Sand::__toString of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
1072
    }
1073
1074
    /**
1075
     * Gives you FlexiPeeHP class name for Given Evidence
1076
     *
1077
     * @param string $evidence
1078
     * @return string Class name
1079
     */
1080
    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...
1081
    {
1082
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1083
    }
1084
1085
    /**
1086
     * Vrací hodnotu daného externího ID
1087
     *
1088
     * @param string $want Which ? If empty,you obtain the first one.
1089
     * @return string
1090
     */
1091
    public function getExternalID($want = null)
1092
    {
1093
        $extid = null;
1094
        $ids   = $this->getDataValue('external-ids');
1095
        if (is_null($want)) {
1096
            if (count($ids)) {
1097
                $extid = current($ids);
1098
            }
1099
        } else {
1100
            if (!is_null($ids)) {
1101
                foreach ($ids as $id) {
0 ignored issues
show
Bug introduced by
The expression $ids of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1102
                    if (strstr($id, 'ext:'.$want)) {
1103
                        $extid = str_replace('ext:'.$want.':', '', $id);
1104
                    }
1105
                }
1106
            }
1107
        }
1108
        return $extid;
1109
    }
1110
1111
    /**
1112
     * Vrací aktuální globální verzi změn
1113
     *
1114
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1115
     * @return type
1116
     */
1117
    public function getGlobalVersion()
1118
    {
1119
        $globalVersion = null;
1120
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1121
            $this->getFlexiData(null,
1122
                ['add-global-version' => 'true', 'limit' => 1]);
1123
        }
1124
1125
        if (isset($this->lastResult['@globalVersion'])) {
1126
            $globalVersion = intval($this->lastResult['@globalVersion']);
1127
        }
1128
1129
        return $globalVersion;
1130
    }
1131
1132
    /**
1133
     * Return the same response format for one and multiplete results
1134
     * 
1135
     * @param array $responseRaw
1136
     * @return array
1137
     */
1138
    public function unifyResponseFormat($responseRaw)
1139
    {
1140
        $response = null;
1141
        if (is_array($responseRaw)) {
1142
            // Get response body root automatically
1143
            if (array_key_exists($this->nameSpace, $responseRaw)) { //Unifi response format
1144
                $responseBody = $responseRaw[$this->nameSpace];
1145
                if (array_key_exists($this->evidence, $responseBody)) {
1146
                    $evidenceContent = $responseBody[$this->evidence];
1147
                    if (array_key_exists(0, $evidenceContent)) {
1148
                        $response[$this->evidence] = $evidenceContent; //Multiplete Results
1149
                    } else {
1150
                        $response[$this->evidence][0] = $evidenceContent; //One result
1151
                    }
1152
                } else {
1153
                    $response = $responseBody;
1154
                }
1155
            } else {
1156
                $response = $responseRaw;
1157
            }
1158
        }
1159
        return $response;
1160
    }
1161
1162
}
1163