Completed
Push — master ( 6a7b8b...b9479e )
by Vítězslav
04:53
created

FlexiBeeRO::loadFlexiData()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 2
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
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
    ];
246
247
    /**
248
     * Třída pro práci s FlexiBee.
249
     *
250
     * @param mixed $init výchozí selektor dat
251
     */
252
    public function __construct($init = null)
253
    {
254
        $this->init = $init;
255
256
        parent::__construct();
257
        $this->setUp();
258
        $this->curlInit();
259
        if (!is_null($init)) {
260
            $this->processInit($init);
261
        }
262
    }
263
264
    /**
265
     * SetUp Object to be ready for connect
266
     */
267
    public function setUp()
268
    {
269
        if (is_null($this->company) && defined('FLEXIBEE_COMPANY')) {
270
            $this->company = constant('FLEXIBEE_COMPANY');
271
        }
272
        if (is_null($this->url) && defined('FLEXIBEE_URL')) {
273
            $this->url = constant('FLEXIBEE_URL');
274
        }
275
276
        if (is_null($this->user) && defined('FLEXIBEE_LOGIN')) {
277
            $this->user = constant('FLEXIBEE_LOGIN');
278
        }
279
280
        if (is_null($this->password) && defined('FLEXIBEE_PASSWORD')) {
281
            $this->password = constant('FLEXIBEE_PASSWORD');
282
        }
283
    }
284
285
    /**
286
     * Inicializace CURL
287
     */
288
    public function curlInit()
289
    {
290
        $this->curl = \curl_init(); // create curl resource
291
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
292
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
293
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
294
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
295
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
296
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
297
        curl_setopt($this->curl, CURLOPT_USERPWD,
298
            $this->user.':'.$this->password); // set username and password
299
    }
300
301
    /**
302
     * Zinicializuje objekt dle daných dat
303
     * 
304
     * @param mixed $init
305
     */
306
    public function processInit($init)
307
    {
308
        if (is_integer($init)) {
309
            $this->loadFromFlexiBee($init);
310
        } elseif (is_array($init)) {
311
            $this->takeData($init);
312
        } elseif (strstr($init, 'code:')) {
313
            $this->loadFromFlexiBee($init);
314
        }
315
    }
316
317
    /**
318
     * Nastaví Evidenci pro Komunikaci.
319
     *
320
     * @param string $evidence
321
     */
322
    public function setEvidence($evidence)
323
    {
324
        $this->evidence = $evidence;
325
    }
326
327
    /**
328
     * Vrací právě používanou evidenci pro komunikaci
329
     * 
330
     * @return string
331
     */
332
    public function getEvidence()
333
    {
334
        return $this->evidence;
335
    }
336
337
    /**
338
     * Převede rekurzivně Objekt na pole.
339
     *
340
     * @param object|array $object
341
     *
342
     * @return array
343
     */
344
    public static function object2array($object)
345
    {
346
        $result = null;
347
        if (is_object($object)) {
348
            $objectData = get_object_vars($object);
349
            if (is_array($objectData) && count($objectData)) {
350
                $result = array_map('self::object2array', $objectData);
351
            }
352 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...
353
            if (is_array($object)) {
354
                foreach ($object as $item => $value) {
355
                    $result[$item] = self::object2array($value);
356
                }
357
            } else {
358
                $result = $object;
359
            }
360
        }
361
362
        return $result;
363
    }
364
365
    /**
366
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
367
     *
368
     * @param object|array $object
369
     *
370
     * @return array
371
     */
372
    public static function objectToID($object)
373
    {
374
        $result = null;
375
        if (is_object($object)) {
376
            $result = $object->__toString();
377 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...
378
            if (is_array($object)) {
379
                foreach ($object as $item => $value) {
380
                    $result[$item] = self::objectToID($value);
381
                }
382
            } else { //String
383
                $result = $object;
384
            }
385
        }
386
387
        return $result;
388
    }
389
390
    /**
391
     * Vrací základní URL pro užitou evidenci
392
     *
393
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
394
     * @param string $urlSuffix
395
     */
396
    public function getEvidenceURL($urlSuffix = null)
397
    {
398
        if (is_null($urlSuffix)) {
399
            $urlSuffix = $this->evidence;
400
        } elseif ($urlSuffix[0] == ';') {
401
            $urlSuffix = $this->evidence.$urlSuffix;
402
        }
403
        return $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
404
    }
405
406
    /**
407
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
408
     *
409
     * @param string $urlSuffix část URL za identifikátorem firmy.
410
     * @param string $method    HTTP/REST metoda
411
     * @param string $format    Requested format
412
     * @return array|boolean Výsledek operace
413
     */
414
    public function performRequest($urlSuffix = null, $method = 'GET',
415
                                   $format = null)
416
    {
417
418
        $url = $this->getEvidenceURL($urlSuffix);
419
420
        $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...
421
422
        if (is_null($format)) {
423
            $format = $this->format;
424
        }
425
426
        switch ($responseCode) {
427
            case 200:
428
            case 201:
429
                // Parse response
430
                $responseDecoded = [];
431
432
                switch ($format) {
433
                    case 'json':
434
                        $responseDecoded = json_decode($this->lastCurlResponse,
435
                            true, 10);
436
                        if (($method == 'PUT') && isset($responseDecoded[$this->nameSpace][$this->resultField][0]['id'])) {
437
                            $this->lastInsertedID = $responseDecoded[$this->nameSpace][$this->resultField][0]['id'];
438
                            $this->setMyKey($this->lastInsertedID);
439
                        } else {
440
                            $this->lastInsertedID = null;
441
                        }
442
                        $decodeError = json_last_error_msg();
443
                        if ($decodeError != 'No error') {
444
                            $this->addStatusMessage($decodeError, 'error');
445
                        }
446
                        break;
447
                    case 'xml':
448
                        if (strlen($this->lastCurlResponse)) {
449
                            $responseDecoded = self::xml2array($this->lastCurlResponse);
450
                        } else {
451
                            $responseDecoded = null;
452
                        }
453
                        break;
454
                }
455
456
                // Get response body root automatically
457
                if (isset($responseDecoded[$this->nameSpace])) {
458
                    $responseDecoded = $responseDecoded[$this->nameSpace];
459
                }
460
461
                $this->lastResult = $responseDecoded;
0 ignored issues
show
Documentation Bug introduced by
It seems like $responseDecoded of type * is incompatible with the declared type array of property $lastResult.

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...
462
                $response         = $responseDecoded;
463
464
                break;
465
466
            default: //Some goes wrong
467
                $this->lastCurlError = curl_error($this->curl);
468
                switch ($format) {
469
                    case 'json':
470
                        $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
471
                            function ($match) {
472
                            return mb_convert_encoding(pack('H*', $match[1]),
473
                                'UTF-8', 'UCS-2BE');
474
                        }, $this->lastCurlResponse);
475
                        $response = (json_encode(json_decode($response, true, 10),
476
                                JSON_PRETTY_PRINT));
477
                        break;
478
                    case 'xml':
479
                        if (strlen($this->lastCurlResponse)) {
480
                            $response = self::xml2array($this->lastCurlResponse);
481
                        }
482
                        break;
483
                }
484
485
                if (is_array($response)) {
486
                    $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...
487
                } elseif (strlen($response) && ($response != 'null')) {
488
                    $result = urldecode(http_build_query(self::object2array(current(json_decode($response)))));
489
                } else {
490
                    $result = null;
491
                }
492
493
                if ($response == 'null') {
494
                    if ($this->lastResponseCode == 200) {
495
                        $response = true;
496
                    } else {
497
                        $response = null;
498
                    }
499
                } else {
500
                    if (is_string($response)) {
501
                        $response = self::object2array(current(json_decode($response)));
502
                    }
503
                }
504
505
                if (is_array($response) && ($this->lastResponseCode == 400)) {
506
                    $this->logResult($response, $url);
507
                } else {
508
                    $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
509
                            curl_getinfo($this->curl, CURLINFO_HTTP_CODE),
510
                            $result, $this->lastCurlError), 'error');
511
                    $this->addStatusMessage($url, 'info');
512
                    if (count($this->postFields)) {
513
                        $this->addStatusMessage(urldecode(http_build_query($this->postFields)),
514
                            'debug');
515
                    }
516
                }
517
518
                break;
519
        }
520
        return $response;
521
    }
522
523
    /**
524
     * Vykonej HTTP požadavek
525
     *
526
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
527
     * @param string $url    URL požadavku
528
     * @param strinf $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
529
     * @param string $format požadovaný formát komunikace
530
     * @return int HTTP Response CODE
531
     */
532
    public function doCurlRequest($url, $method, $format = null)
533
    {
534
        if (is_null($format)) {
535
            $format = $this->format;
536
        }
537
        curl_setopt($this->curl, CURLOPT_URL, $url);
538
// Nastavení samotné operace
539
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
540
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
541
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
542
543
        $httpHeaders = $this->defaultHttpHeaders;
544
        switch ($format) {
545
            case 'json':
546
                $httpHeaders['Accept']       = 'application/json';
547
                $httpHeaders['Content-Type'] = 'application/json';
548
549
                break;
550
            case 'xml':
551
                $httpHeaders['Accept']       = 'application/xml';
552
                $httpHeaders['Content-Type'] = 'application/xml';
553
                break;
554
        }
555
556
        $httpHeadersFinal = [];
557
        foreach ($httpHeaders as $key => $value) {
558
            $httpHeadersFinal[] = $key.': '.$value;
559
        }
560
561
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
562
563
// Proveď samotnou operaci
564
        $this->lastCurlResponse = curl_exec($this->curl);
565
566
        $this->info = curl_getinfo($this->curl);
567
568
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
569
        return $this->lastResponseCode;
570
    }
571
572
    /**
573
     * Nastaví druh prováděné akce.
574
     *
575
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
576
     * @param string $action
577
     * @return boolean
578
     */
579
    public function setAction($action)
580
    {
581
        $result = false;
582
        if (is_null($this->actionsAvailable)) {
583
            $this->action = $action;
584
            $result       = true;
585
        } else {
586
            if (array_search($action, $this->actionsAvailable)) {
587
                $this->action = $action;
588
                $result       = true;
589
            }
590
        }
591
        return $result;
592
    }
593
594
    /**
595
     * Convert XML to array.
596
     *
597
     * @param string $xml
598
     *
599
     * @return array
600
     */
601
    public static function xml2array($xml)
602
    {
603
        $arr = [];
604
605
        if (is_string($xml)) {
606
            $xml = simplexml_load_string($xml);
607
        }
608
609
        foreach ($xml->children() as $r) {
610
            if (count($r->children()) == 0) {
611
                $arr[$r->getName()] = strval($r);
612
            } else {
613
                $arr[$r->getName()][] = self::xml2array($r);
614
            }
615
        }
616
617
        return $arr;
618
    }
619
620
    /**
621
     * Odpojení od FlexiBee.
622
     */
623
    public function disconnect()
624
    {
625
        if (is_resource($this->curl)) {
626
            curl_close($this->curl);
627
        }
628
        $this->curl = null;
629
    }
630
631
    public function __destruct()
632
    {
633
        $this->disconnect();
634
    }
635
636
    /**
637
     * Načte řádek dat z FlexiBee.
638
     *
639
     * @param int $recordID id požadovaného záznamu
640
     *
641
     * @return array
642
     */
643
    public function getFlexiRow($recordID)
644
    {
645
        $record   = null;
646
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
647
        if (isset($response[$this->evidence])) {
648
            $record = $response[$this->evidence][0];
649
        }
650
651
        return $record;
652
    }
653
654
    /**
655
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
656
     *
657
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
658
     * @param array $conditions pole podmínek   - rendrují se do ()
659
     * @param array $urlParams  pole parametrů  - rendrují za ?
660
     */
661
    public function extractUrlParams(&$conditions, &$urlParams)
662
    {
663
        foreach ($this->urlParams as $urlParam) {
664
            if (isset($conditions[$urlParam])) {
665
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
666
            }
667
        }
668
    }
669
670
    /**
671
     * Načte data z FlexiBee.
672
     *
673
     * @param string $suffix     dotaz
674
     * @param string|array $conditions Volitelný filtrovací výraz
675
     */
676
    public function getFlexiData($suffix = null, $conditions = null)
677
    {
678
        $urlParams = $this->defaultUrlParams;
679
        if (!is_null($conditions)) {
680
            if (is_array($conditions)) {
681
                $this->extractUrlParams($conditions, $urlParams);
682
                $conditions = $this->flexiUrl($conditions);
683
            }
684
685
            if (strlen($conditions) && ($conditions[0] != '/')) {
686
                $conditions = '/'.rawurlencode('('.($conditions).')');
687
            }
688
        } else {
689
            $conditions = '';
690
        }
691
        if (strlen($suffix)) {
692
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
693
                'GET');
694
        } else {
695
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
696
                'GET');
697
        }
698
        if (isset($transactions[$this->evidence])) {
699
            $result = $transactions[$this->evidence];
700
        } else {
701
            $result = $transactions;
702
        }
703
704
        return $result;
705
    }
706
707
    /**
708
     * Načte záznam z FlexiBee.
709
     *
710
     * @param int $id ID záznamu
711
     *
712
     * @return int počet načtených položek
713
     */
714 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...
715
    {
716
        $data = [];
717
        if (is_null($id)) {
718
            $id = $this->getMyKey();
719
        }
720
721
        $flexidata = $this->getFlexiData(null, '/'.$id);
722
        if (count($flexidata) == 1) {
723
            $data = current($flexidata);
724
        }
725
        return $this->takeData($data);
726
    }
727
728
    /**
729
     * Převede data do Json formátu pro FlexiBee.
730
     *
731
     * @param array $data
732
     *
733
     * @return string
734
     */
735
    public function jsonizeData($data)
736
    {
737
        $jsonize = [
738
            $this->nameSpace => [
739
                '@version' => $this->protoVersion,
740
                $this->evidence => $this->objectToID($data),
741
            ],
742
        ];
743
744
        if (!is_null($this->action)) {
745
            $jsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
746
            $this->action                                         = null;
747
        }
748
749
        return json_encode($jsonize);
750
    }
751
752
    /**
753
     * Test if given record ID exists in FlexiBee.
754
     *
755
     * @param string|int $identifer
756
     */
757
    public function idExists($identifer = null)
758
    {
759
        if (is_null($identifer)) {
760
            $identifer = $this->getMyKey();
761
        }
762
        $flexiData = $this->getFlexiData(
763
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
764
765
        return $flexiData;
766
    }
767
768
    /**
769
     * Test if given record exists in FlexiBee.
770
     *
771
     * @param array $data
772
     * @return boolean Record presence status
773
     */
774
    public function recordExists($data = null)
775
    {
776
        $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...
777
        if (is_null($data)) {
778
            $data = $this->getData();
779
        }
780
781
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
782
            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...
783
784
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))) {
785
            $found = false;
786
        } else {
787
            $found = true;
788
        }
789
        return $found;
790
    }
791
792
    /**
793
     * Vrací z FlexiBee sloupečky podle podmínek.
794
     *
795
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
796
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
797
     *                                     sloupečku
798
     * @return array
799
     */
800 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...
801
    {
802
        if (is_int($conditions)) {
803
            $conditions = [$this->getmyKeyColumn() => $conditions];
804
        }
805
806
        $flexiData = $this->getFlexiData('', $conditions);
807
808
        if (!is_null($indexBy)) {
809
            $flexiData = $this->reindexArrayBy($flexiData);
810
        }
811
812
        return $flexiData;
813
    }
814
815
    /**
816
     * Vrací z FlexiBee sloupečky podle podmínek.
817
     *
818
     * @param string[] $columnsList seznam položek
819
     * @param array    $conditions  pole podmínek nebo ID záznamu
820
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
821
     *
822
     * @return array
823
     */
824
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
825
                                           $indexBy = null)
826
    {
827
        if (($columnsList != '*') && !count($columnsList)) {
828
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
829
830
            return;
831
        }
832
833
        if (is_int($conditions)) {
834
            $conditions = [$this->getmyKeyColumn() => $conditions];
835
        }
836
837
        if (is_array($columnsList)) {
838
            $columns = implode(',', array_unique($columnsList));
839
        } else {
840
            $columns = $columnsList;
841
        }
842
843
        $flexiData = $this->getFlexiData('detail=custom:'.$columns, $conditions);
844
845
        if (!is_null($indexBy)) {
846
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
847
        }
848
849
        return $flexiData;
850
    }
851
852
    /**
853
     * Vrací kód záznamu.
854
     *
855
     * @param mixed $data
856
     *
857
     * @return string
858
     */
859
    public function getKod($data = null, $unique = true)
860
    {
861
        $kod = null;
862
863
        if (is_null($data)) {
864
            $data = $this->getData();
865
        }
866
867
        if (is_string($data)) {
868
            $data = [$this->nameColumn => $data];
869
        }
870
871
        if (isset($data['kod'])) {
872
            $kod = $data['kod'];
873
        } else {
874
            if (isset($data[$this->nameColumn])) {
875
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
876
                    \Ease\Sand::rip($data[$this->nameColumn]));
877
            } else {
878
                if (isset($data[$this->myKeyColumn])) {
879
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
880
                }
881
            }
882
        }
883
884
        if (!strlen($kod)) {
885
            $kod = 'NOTSET';
886
        }
887
888
        if (strlen($kod) > 18) {
889
            $kodfinal = strtoupper(substr($kod, 0, 18));
890
        } else {
891
            $kodfinal = strtoupper($kod);
892
        }
893
894
        if ($unique) {
895
            $counter = 0;
896
            if (count($this->codes)) {
897
                foreach ($this->codes as $codesearch => $keystring) {
898
                    if (strstr($codesearch, $kodfinal)) {
899
                        ++$counter;
900
                    }
901
                }
902
            }
903
            if ($counter) {
904
                $kodfinal = $kodfinal.$counter;
905
            }
906
907
            $this->codes[$kodfinal] = $kod;
908
        }
909
910
        return $kodfinal;
911
    }
912
913
    /**
914
     * Write Operation Result.
915
     *
916
     * @param array  $resultData
917
     * @param string $url        URL
918
     * @return boolean Log save success
919
     */
920
    public function logResult($resultData = null, $url = null)
921
    {
922
        $logResult = false;
923
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
924
            if (isset($resultData['message'])) {
925
                $this->addStatusMessage($resultData['message'], 'warning');
926
            }
927
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
928
                'warning');
929
            unset($url);
930
        }
931
        if (is_null($resultData)) {
932
            $resultData = $this->lastResult;
933
        }
934
        if (isset($url)) {
935
            $this->logger->addStatusMessage(urldecode($url));
936
        }
937
938
        if (isset($resultData['results'])) {
939
            $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...
940
            if ($resultData['success'] == 'false') {
941
                $status = 'error';
942
            } else {
943
                $status = 'success';
944
            }
945
            foreach ($resultData['results'] as $result) {
946
                if (isset($result['request-id'])) {
947
                    $rid = $result['request-id'];
948
                } else {
949
                    $rid = '';
950
                }
951
                if (isset($result['errors'])) {
952
                    foreach ($result['errors'] as $error) {
953
                        $message = $error['message'];
954
                        if (isset($error['for'])) {
955
                            $message .= ' for: '.$error['for'];
956
                        }
957
                        if (isset($error['value'])) {
958
                            $message .= ' value:'.$error['value'];
959
                        }
960
                        if (isset($error['code'])) {
961
                            $message .= ' code:'.$error['code'];
962
                        }
963
                        $this->addStatusMessage($rid.': '.$message, $status);
964
                    }
965
                }
966
            }
967
        }
968
969
        if (is_object($this->logger)) {
970
            $logResult = $this->logger->flush(get_class($this));
971
        }
972
        return $logResult;
973
    }
974
975
    /**
976
     * Save RAW Curl Request & Response to files in Temp directory
977
     */
978
    public function saveDebugFiles()
979
    {
980
        $tmpdir = sys_get_temp_dir();
981
        file_put_contents($tmpdir.'/request-'.$this->evidence.'-'.microtime().'.'.$this->format,
982
            $this->postFields);
983
        file_put_contents($tmpdir.'/response-'.$this->evidence.'-'.microtime().'.'.$this->format,
984
            $this->lastCurlResponse);
985
    }
986
987
    /**
988
     * Připraví data pro odeslání do FlexiBee
989
     * 
990
     * @param string $data
991
     */
992
    public function setPostFields($data)
993
    {
994
        $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...
995
    }
996
997
    /**
998
     * Generuje fragment url pro filtrování.
999
     *
1000
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1001
     *
1002
     * @param array  $data
1003
     * @param string $operator default and/or
1004
     *
1005
     * @return string
1006
     */
1007
    public static function flexiUrl(array $data, $operator = 'and')
1008
    {
1009
        $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...
1010
        $parts    = [];
1011
1012
        foreach ($data as $column => $value) {
1013
            if (is_integer($data[$column]) || is_float($data[$column])) {
1014
                $parts[$column] = $column.' eq '.$data[$column];
1015
            } elseif (is_bool($data[$column])) {
1016
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1017
            } elseif (is_null($data[$column])) {
1018
                $parts[$column] = $column." is null";
1019
            } elseif ($value == '!null') {
1020
                $parts[$column] = $column." is not null";
1021
            } else {
1022
                $parts[$column] = $column." eq '".$data[$column]."'";
1023
            }
1024
        }
1025
1026
        $flexiUrl = implode(' '.$operator.' ', $parts);
1027
1028
        return $flexiUrl;
1029
    }
1030
1031
    /**
1032
     * Vrací identifikátor objektu code: nebo id:
1033
     *
1034
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1035
     * @return string indentifikátor záznamu reprezentovaného objektem
1036
     */
1037
    public function __toString()
1038
    {
1039
        $myCode = $this->getDataValue('kod');
1040
        if ($myCode) {
1041
            $id = 'code:'.$myCode;
1042
        } else {
1043
            $id = $this->getDataValue('id');
1044
            if (is_null($id)) {
1045
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1046
                    'warning');
1047
            }
1048
        }
1049
        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...
1050
    }
1051
1052
    /**
1053
     * Gives you FlexiPeeHP class name for Given Evidence
1054
     *
1055
     * @param string $evidence
1056
     * @return string Class name
1057
     */
1058
    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...
1059
    {
1060
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1061
    }
1062
1063
    /**
1064
     * Vrací hodnotu daného externího ID
1065
     *
1066
     * @param string $want Which ? If empty,you obtain the first one.
1067
     * @return string
1068
     */
1069
    public function getExternalID($want = null)
1070
    {
1071
        $extid = null;
1072
        $ids   = $this->getDataValue('external-ids');
1073
        if (is_null($want)) {
1074
            if (count($ids)) {
1075
                $extid = current($ids);
1076
            }
1077
        } else {
1078
            if (!is_null($ids)) {
1079
                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...
1080
                    if (strstr($id, 'ext:'.$want)) {
1081
                        $extid = str_replace('ext:'.$want.':', '', $id);
1082
                    }
1083
                }
1084
            }
1085
        }
1086
        return $extid;
1087
    }
1088
1089
    /**
1090
     * Vrací aktuální globální verzi změn
1091
     *
1092
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1093
     * @return type
1094
     */
1095
    public function getGlobalVersion()
1096
    {
1097
        $globalVersion = null;
1098
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1099
            $this->getFlexiData(null,
1100
                ['add-global-version' => 'true', 'limit' => 1]);
1101
        }
1102
1103
        if (isset($this->lastResult['@globalVersion'])) {
1104
            $globalVersion = intval($this->lastResult['@globalVersion']);
1105
        }
1106
1107
        return $globalVersion;
1108
    }
1109
1110
}
1111