Completed
Push — master ( 14dc45...6a7b8b )
by Vítězslav
08:50
created

FlexiBeeRO::recordExists()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 17
rs 8.8571
cc 5
eloc 11
nc 4
nop 1
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 data z FlexiBee.
638
     *
639
     * @param string $suffix dotaz
640
     */
641
    public function loadFlexiData($suffix = null)
642
    {
643
        return $this->takeData($this->getFlexiData($suffix));
644
    }
645
646
    /**
647
     * Načte řádek dat z FlexiBee.
648
     *
649
     * @param int $recordID id požadovaného záznamu
650
     *
651
     * @return array
652
     */
653
    public function getFlexiRow($recordID)
654
    {
655
        $record   = null;
656
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
657
        if (isset($response[$this->evidence])) {
658
            $record = $response[$this->evidence][0];
659
        }
660
661
        return $record;
662
    }
663
664
    /**
665
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
666
     *
667
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
668
     * @param array $conditions pole podmínek   - rendrují se do ()
669
     * @param array $urlParams  pole parametrů  - rendrují za ?
670
     */
671
    public function extractUrlParams(&$conditions, &$urlParams)
672
    {
673
        foreach ($this->urlParams as $urlParam) {
674
            if (isset($conditions[$urlParam])) {
675
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
676
            }
677
        }
678
    }
679
680
    /**
681
     * Načte data z FlexiBee.
682
     *
683
     * @param string $suffix     dotaz
684
     * @param string|array $conditions Volitelný filtrovací výraz
685
     */
686
    public function getFlexiData($suffix = null, $conditions = null)
687
    {
688
        $urlParams = $this->defaultUrlParams;
689
        if (!is_null($conditions)) {
690
            if (is_array($conditions)) {
691
                $this->extractUrlParams($conditions, $urlParams);
692
                $conditions = $this->flexiUrl($conditions);
693
            }
694
695
            if (strlen($conditions) && ($conditions[0] != '/')) {
696
                $conditions = '/'.rawurlencode('('.($conditions).')');
697
            }
698
        } else {
699
            $conditions = '';
700
        }
701
        if (strlen($suffix)) {
702
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
703
                'GET');
704
        } else {
705
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
706
                'GET');
707
        }
708
        if (isset($transactions[$this->evidence])) {
709
            $result = $transactions[$this->evidence];
710
        } else {
711
            $result = $transactions;
712
        }
713
714
        return $result;
715
    }
716
717
    /**
718
     * Načte záznam z FlexiBee.
719
     *
720
     * @param int $id ID záznamu
721
     *
722
     * @return int počet načtených položek
723
     */
724 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...
725
    {
726
        $data = [];
727
        if (is_null($id)) {
728
            $id = $this->getMyKey();
729
        }
730
731
        $flexidata = $this->getFlexiData(null, '/'.$id);
732
        if (count($flexidata) == 1) {
733
            $data = current($flexidata);
734
        }
735
        return $this->takeData($data);
736
    }
737
738
    /**
739
     * Převede data do Json formátu pro FlexiBee.
740
     *
741
     * @param array $data
742
     *
743
     * @return string
744
     */
745
    public function jsonizeData($data)
746
    {
747
        $jsonize = [
748
            $this->nameSpace => [
749
                '@version' => $this->protoVersion,
750
                $this->evidence => $this->objectToID($data),
751
            ],
752
        ];
753
754
        if (!is_null($this->action)) {
755
            $jsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
756
            $this->action                                         = null;
757
        }
758
759
        return json_encode($jsonize);
760
    }
761
762
    /**
763
     * Test if given record ID exists in FlexiBee.
764
     *
765
     * @param string|int $identifer
766
     */
767
    public function idExists($identifer = null)
768
    {
769
        if (is_null($identifer)) {
770
            $identifer = $this->getMyKey();
771
        }
772
        $flexiData = $this->getFlexiData(
773
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
774
775
        return $flexiData;
776
    }
777
778
    /**
779
     * Test if given record exists in FlexiBee.
780
     *
781
     * @param array $data
782
     * @return boolean Record presence status
783
     */
784
    public function recordExists($data = null)
785
    {
786
        $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...
787
        if (is_null($data)) {
788
            $data = $this->getData();
789
        }
790
791
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
792
            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...
793
794
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))) {
795
            $found = false;
796
        } else {
797
            $found = true;
798
        }
799
        return $found;
800
    }
801
802
    /**
803
     * Vrací z FlexiBee sloupečky podle podmínek.
804
     *
805
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
806
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
807
     *                                     sloupečku
808
     * @return array
809
     */
810 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...
811
    {
812
        if (is_int($conditions)) {
813
            $conditions = [$this->getmyKeyColumn() => $conditions];
814
        }
815
816
        $flexiData = $this->getFlexiData('', $conditions);
817
818
        if (!is_null($indexBy)) {
819
            $flexiData = $this->reindexArrayBy($flexiData);
820
        }
821
822
        return $flexiData;
823
    }
824
825
    /**
826
     * Vrací z FlexiBee sloupečky podle podmínek.
827
     *
828
     * @param string[] $columnsList seznam položek
829
     * @param array    $conditions  pole podmínek nebo ID záznamu
830
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
831
     *
832
     * @return array
833
     */
834
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
835
                                           $indexBy = null)
836
    {
837
        if (($columnsList != '*') && !count($columnsList)) {
838
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
839
840
            return;
841
        }
842
843
        if (is_int($conditions)) {
844
            $conditions = [$this->getmyKeyColumn() => $conditions];
845
        }
846
847
        if (is_array($columnsList)) {
848
            $columns = implode(',', array_unique($columnsList));
849
        } else {
850
            $columns = $columnsList;
851
        }
852
853
        $flexiData = $this->getFlexiData('detail=custom:'.$columns, $conditions);
854
855
        if (!is_null($indexBy)) {
856
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
857
        }
858
859
        return $flexiData;
860
    }
861
862
    /**
863
     * Vrací kód záznamu.
864
     *
865
     * @param mixed $data
866
     *
867
     * @todo papat i string
868
     *
869
     * @return string
870
     */
871
    public function getKod($data = null, $unique = true)
872
    {
873
        $kod = null;
874
875
        if (is_null($data)) {
876
            $data = $this->getData();
877
        }
878
879
        if (is_string($data)) {
880
            $data = [$this->nameColumn => $data];
881
        }
882
883
        if (isset($data['kod'])) {
884
            $kod = $data['kod'];
885
        } else {
886
            if (isset($data[$this->nameColumn])) {
887
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
888
                    \Ease\Sand::rip($data[$this->nameColumn]));
889
            } else {
890
                if (isset($data[$this->myKeyColumn])) {
891
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
892
                }
893
            }
894
        }
895
896
        if (!strlen($kod)) {
897
            $kod = 'NOTSET';
898
        }
899
900
        if (strlen($kod) > 18) {
901
            $kodfinal = strtoupper(substr($kod, 0, 18));
902
        } else {
903
            $kodfinal = strtoupper($kod);
904
        }
905
906
        if ($unique) {
907
            $counter = 0;
908
            if (count($this->codes)) {
909
                foreach ($this->codes as $codesearch => $keystring) {
910
                    if (strstr($codesearch, $kodfinal)) {
911
                        ++$counter;
912
                    }
913
                }
914
            }
915
            if ($counter) {
916
                $kodfinal = $kodfinal.$counter;
917
            }
918
919
            $this->codes[$kodfinal] = $kod;
920
        }
921
922
        return $kodfinal;
923
    }
924
925
    /**
926
     * Write Operation Result.
927
     *
928
     * @param array  $resultData
929
     * @param string $url        URL
930
     * @return boolean Log save success
931
     */
932
    public function logResult($resultData = null, $url = null)
933
    {
934
        $logResult = false;
935
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
936
            if (isset($resultData['message'])) {
937
                $this->addStatusMessage($resultData['message'], 'warning');
938
            }
939
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
940
                'warning');
941
            unset($url);
942
        }
943
        if (is_null($resultData)) {
944
            $resultData = $this->lastResult;
945
        }
946
        if (isset($url)) {
947
            $this->logger->addStatusMessage(urldecode($url));
948
        }
949
950
        if (isset($resultData['results'])) {
951
            $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...
952
            if ($resultData['success'] == 'false') {
953
                $status = 'error';
954
            } else {
955
                $status = 'success';
956
            }
957
            foreach ($resultData['results'] as $result) {
958
                if (isset($result['request-id'])) {
959
                    $rid = $result['request-id'];
960
                } else {
961
                    $rid = '';
962
                }
963
                if (isset($result['errors'])) {
964
                    foreach ($result['errors'] as $error) {
965
                        $message = $error['message'];
966
                        if (isset($error['for'])) {
967
                            $message .= ' for: '.$error['for'];
968
                        }
969
                        if (isset($error['value'])) {
970
                            $message .= ' value:'.$error['value'];
971
                        }
972
                        if (isset($error['code'])) {
973
                            $message .= ' code:'.$error['code'];
974
                        }
975
                        $this->addStatusMessage($rid.': '.$message, $status);
976
                    }
977
                }
978
            }
979
        }
980
981
        if (is_object($this->logger)) {
982
            $logResult = $this->logger->flush(get_class($this));
983
        }
984
        return $logResult;
985
    }
986
987
    /**
988
     * Save RAW Curl Request & Response to files in Temp directory
989
     */
990
    public function saveDebugFiles()
991
    {
992
        $tmpdir = sys_get_temp_dir();
993
        file_put_contents($tmpdir.'/request-'.$this->evidence.'-'.microtime().'.'.$this->format,
994
            $this->postFields);
995
        file_put_contents($tmpdir.'/response-'.$this->evidence.'-'.microtime().'.'.$this->format,
996
            $this->lastCurlResponse);
997
    }
998
999
    /**
1000
     * Připraví data pro odeslání do FlexiBee
1001
     * 
1002
     * @param string $data
1003
     */
1004
    public function setPostFields($data)
1005
    {
1006
        $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...
1007
    }
1008
1009
    /**
1010
     * Generuje fragment url pro filtrování.
1011
     *
1012
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1013
     *
1014
     * @param array  $data
1015
     * @param string $operator default and/or
1016
     *
1017
     * @return string
1018
     */
1019
    public static function flexiUrl(array $data, $operator = 'and')
1020
    {
1021
        $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...
1022
        $parts    = [];
1023
1024
        foreach ($data as $column => $value) {
1025
            if (is_integer($data[$column]) || is_float($data[$column])) {
1026
                $parts[$column] = $column.' eq '.$data[$column];
1027
            } elseif (is_bool($data[$column])) {
1028
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1029
            } elseif (is_null($data[$column])) {
1030
                $parts[$column] = $column." is null";
1031
            } elseif ($value == '!null') {
1032
                $parts[$column] = $column." is not null";
1033
            } else {
1034
                $parts[$column] = $column." eq '".$data[$column]."'";
1035
            }
1036
        }
1037
1038
        $flexiUrl = implode(' '.$operator.' ', $parts);
1039
1040
        return $flexiUrl;
1041
    }
1042
1043
    /**
1044
     * Vrací identifikátor objektu code: nebo id:
1045
     *
1046
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1047
     * @return string indentifikátor záznamu reprezentovaného objektem
1048
     */
1049
    public function __toString()
1050
    {
1051
        $myCode = $this->getDataValue('kod');
1052
        if ($myCode) {
1053
            $id = 'code:'.$myCode;
1054
        } else {
1055
            $id = $this->getDataValue('id');
1056
            if (is_null($id)) {
1057
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1058
                    'warning');
1059
            }
1060
        }
1061
        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...
1062
    }
1063
1064
    /**
1065
     * Gives you FlexiPeeHP class name for Given Evidence
1066
     *
1067
     * @param string $evidence
1068
     * @return string Class name
1069
     */
1070
    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...
1071
    {
1072
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1073
    }
1074
1075
    /**
1076
     * Vrací hodnotu daného externího ID
1077
     *
1078
     * @param string $want Which ? If empty,you obtain the first one.
1079
     * @return string
1080
     */
1081
    public function getExternalID($want = null)
1082
    {
1083
        $extid = null;
1084
        $ids   = $this->getDataValue('external-ids');
1085
        if (is_null($want)) {
1086
            if (count($ids)) {
1087
                $extid = current($ids);
1088
            }
1089
        } else {
1090
            if (!is_null($ids)) {
1091
                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...
1092
                    if (strstr($id, 'ext:'.$want)) {
1093
                        $extid = str_replace('ext:'.$want.':', '', $id);
1094
                    }
1095
                }
1096
            }
1097
        }
1098
        return $extid;
1099
    }
1100
1101
    /**
1102
     * Vrací aktuální globální verzi změn
1103
     *
1104
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1105
     * @return type
1106
     */
1107
    public function getGlobalVersion()
1108
    {
1109
        $globalVersion = null;
1110
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1111
            $this->getFlexiData(null,
1112
                ['add-global-version' => 'true', 'limit' => 1]);
1113
        }
1114
1115
        if (isset($this->lastResult['@globalVersion'])) {
1116
            $globalVersion = intval($this->lastResult['@globalVersion']);
1117
        }
1118
1119
        return $globalVersion;
1120
    }
1121
1122
}
1123