Completed
Push — master ( 48d54d...aba11b )
by Vítězslav
04:04
created

FlexiBee::disconnect()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 7
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
crap 2
1
<?php
2
/**
3
 * FlexiPeeHP - Třída pro práci s 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 FlexiBee 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
     * @var string
38
     */
39
    public $evidence = null;
40
41
    /**
42
     * Výchozí formát pro komunikaci.
43
     *
44
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
45
     *
46
     * @var string json|xml|...
47
     */
48
    public $format = 'json';
49
50
    /**
51
     * Curl Handle.
52
     *
53
     * @var resource
54
     */
55
    public $curl = null;
56
57
    /**
58
     * @var type
59
     */
60
    public $company = FLEXIBEE_COMPANY;
61
62
    /**
63
     * @var string
64
     */
65
    public $url = FLEXIBEE_URL;
66
67
    /**
68
     * @var string
69
     */
70
    public $user = FLEXIBEE_LOGIN;
71
72
    /**
73
     * @var string
74
     */
75
    public $password = FLEXIBEE_PASSWORD;
76
77
    /**
78
     * Identifikační řetězec.
79
     *
80
     * @var string
81
     */
82
    public $init = null;
83
84
    /**
85
     * Sloupeček s názvem.
86
     *
87
     * @var string
88
     */
89
    public $nameColumn = 'nazev';
90
91
    /**
92
     * Sloupeček obsahující datum vložení záznamu do shopu.
93
     *
94
     * @var string
95
     */
96
    public $myCreateColumn = 'false';
97
98
    /**
99
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
100
     *
101
     * @var string
102
     */
103
    public $myLastModifiedColumn = 'lastUpdate';
104
105
    /**
106
     * Klíčový idendifikátor záznamu.
107
     *
108
     * @var string
109
     */
110
    public $fbKeyColumn = 'id';
111
112
    /**
113
     * Informace o posledním HTTP requestu.
114
     *
115
     * @var array
116
     */
117
    public $info;
118
119
    /**
120
     * Informace o poslední HTTP chybě.
121
     *
122
     * @var array
123
     */
124
    public $error;
125
126
    /**
127
     * Used codes storage.
128
     *
129
     * @var array
130
     */
131
    public $codes = null;
132
133
    /**
134
     * Last Inserted ID.
135
     *
136
     * @var int
137
     */
138
    public $lastInsertedID = null;
139
140
    /**
141
     * Default Line Prefix.
142
     *
143
     * @var string
144
     */
145
    public $prefix = '/c/';
146
147
    /**
148
     * HTTP Response code of last request
149
     * 
150
     * @var int
151
     */
152
    public $lastResponseCode = null;
153
154
    /**
155
     * Array of fields for next curl POST operation
156
     * 
157
     * @var array
158
     */
159
    protected $postFields = [];
160
161
    /**
162
     * Třída pro práci s FlexiBee.
163
     *
164
     * @param string $init výchozí selektor dat
165
     */
166 32
    public function __construct($init = null)
167
    {
168 32
        $this->init = $init;
169
170 32
        parent::__construct();
171 32
        $this->curlInit();
172 32
    }
173
174 32
    public function curlInit()
175
    {
176 32
        $this->curl = \curl_init(); // create curl resource
177 32
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
178 32
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
179 32
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
180 32
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
181 32
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
182 32
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
183 32
        curl_setopt($this->curl, CURLOPT_USERPWD,
184 32
            $this->user.':'.$this->password); // set username and password
185 32
    }
186
187
    /**
188
     * Nastaví Agendu pro Komunikaci.
189
     *
190
     * @param string $evidence
191
     */
192 16
    public function setEvidence($evidence)
193
    {
194 16
        $this->evidence = $evidence;
195 16
    }
196
197
    /**
198
     * Převede rekurzivně Objekt na pole.
199
     *
200
     * @param object|array $object
201
     *
202
     * @return array
203
     */
204 16
    public static function object2array($object)
205
    {
206 16
        $result = null;
207 16
        if (is_object($object)) {
208 16
            $objectData = get_object_vars($object);
209 16
            if (is_array($objectData) && count($objectData)) {
210 16
                $result = array_map('self::object2array', $objectData);
211 16
            }
212 16
        } else {
213 16
            if (is_array($object)) {
214 16
                foreach ($object as $item => $value) {
215 16
                    $result[$item] = self::object2array($value);
216 16
                }
217 16
            } else {
218 16
                $result = $object;
219
            }
220
        }
221
222 16
        return $result;
223
    }
224
225
    /**
226
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
227
     *
228
     * @param string $urlSuffix část URL za identifikátorem firmy.
229
     * @param string $method    HTTP/REST metoda
230
     * @param string $format    Requested format
231
     */
232 16
    public function performRequest($urlSuffix = null, $method = 'GET',
233
                                   $format = null)
234
    {
235 16
        if (is_null($format)) {
236 16
            $format = $this->format;
237 16
        }
238 16
        if (is_null($urlSuffix)) {
239 3
            $urlSuffix = $this->evidence.'.'.$format;
240 3
        }
241 16
        $url = $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
242 16
        curl_setopt($this->curl, CURLOPT_URL, $url);
243
// Nastavení samotné operace
244 16
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
245
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
246 16
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
247
248
249
// Proveď samotnou operaci
250 16
        $response = curl_exec($this->curl);
251
252 16
        $this->info = curl_getinfo($this->curl);
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_getinfo($this->curl) of type * is incompatible with the declared type array of property $info.

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...
253
254 16
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
255
256 16
        if ($this->lastResponseCode != 200 && $this->lastResponseCode != 201) {
257 16
            $this->error = curl_error($this->curl);
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_error($this->curl) of type string is incompatible with the declared type array of property $error.

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...
258
            switch ($format) {
259 16
                case 'json':
260 16
                    $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
261 16
                        function ($match) {
262
                        return mb_convert_encoding(pack('H*', $match[1]),
263
                            'UTF-8', 'UCS-2BE');
264 16
                    }, $response);
265 16
                    $response = (json_encode(json_decode($response, true, 10),
266 16
                            JSON_PRETTY_PRINT));
267 16
                    break;
268
                case 'xml':
269
                    if (strlen($response)) {
270
                        $response = self::xml2array($response);
271
                    }
272
                    break;
273
            }
274
275 16
            if (is_array($response)) {
276
                $result = http_build_query($response);
277
            } else {
278 16
                $result = http_build_query(self::object2array(current(json_decode($response))));
279
            }
280
281 16
            if ($this->lastResponseCode == 400) {
282 2
                $this->logResult($result);
0 ignored issues
show
Documentation introduced by
$result is of type string, but the function expects a array.

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...
283 2
            } else {
284 16
                $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
285 16
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE), $result,
286 16
                        $this->error), 'error');
287 16
                $this->addStatusMessage($url);
288
            }
289 16
            if ($response == 'null') {
290
                if ($this->lastResponseCode == 200) {
291
                    $response = true;
292
                } else {
293
                    $response = null;
294
                }
295
            } else {
296 16
                if (is_string($response)) {
297 16
                    $response = self::object2array(current(json_decode($response)));
298 16
                }
299
            }
300 16
            return $response;
301
        }
302
303
        // Parse response
304
        switch ($format) {
305 14
            case 'json':
306 14
                $decoded = json_decode($response, true, 10);
307 14
                if (($method == 'PUT') && isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
308
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
309
                } else {
310 14
                    $this->lastInsertedID = null;
311
                }
312
//                $decodeError = json_last_error_msg();
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
313
//                $this->addStatusMessage($decodeError);
314
315 14
                break;
316 3
            case 'xml':
317 3
                if (strlen($response)) {
318 3
                    $decoded = self::xml2array($response);
319 3
                } else {
320
                    $decoded = null;
321
                }
322 3
                break;
323
        }
324
325
        // Get response body root automatically
326 14
        if (isset($decoded[$this->nameSpace])) {
327 14
            $decoded = $decoded[$this->nameSpace];
328 14
        }
329
330 14
        return $decoded;
0 ignored issues
show
Bug introduced by
The variable $decoded 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...
331
    }
332
333
    /**
334
     * Give you last inserted record ID.
335
     * 
336
     * @return int
337
     */
338
    public function getLastInsertedId()
339
    {
340
        return $this->lastInsertedID;
341
    }
342
343
    /**
344
     * Convert XML to array.
345
     * 
346
     * @param string $xml
347
     *
348
     * @return array
349
     */
350 16
    public static function xml2array($xml)
351
    {
352 16
        $arr = [];
353
354 16
        if (is_string($xml)) {
355 16
            $xml = simplexml_load_string($xml);
356 16
        }
357
358 16
        foreach ($xml->children() as $r) {
359 16
            $t = [];
0 ignored issues
show
Unused Code introduced by
$t 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...
360 16
            if (count($r->children()) == 0) {
361 16
                $arr[$r->getName()] = strval($r);
362 16
            } else {
363 16
                $arr[$r->getName()][] = self::xml2array($r);
364
            }
365 16
        }
366
367 16
        return $arr;
368
    }
369
370
    /**
371
     * Odpojení od FlexiBee.
372
     */
373 17
    public function disconnect()
374
    {
375 17
        if (is_resource($this->curl)) {
376 17
            curl_close($this->curl);
377 17
        }
378 17
        $this->curl = null;
379 17
    }
380
381 17
    public function __destruct()
382
    {
383 17
        $this->disconnect();
384 17
    }
385
386
    /**
387
     * Načte data z FlexiBee.
388
     *
389
     * @param string $suffix dotaz
390
     */
391
    public function loadFlexiData($suffix = null)
392
    {
393
        return $this->takeData($this->getFlexiData($suffix));
394
    }
395
396
    /**
397
     * Načte řádek dat z FlexiBee.
398
     *
399
     * @param int $recordID id požadovaného záznamu
400
     *
401
     * @return array
402
     */
403 16
    public function getFlexiRow($recordID)
404
    {
405 16
        $record   = null;
406 16
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
407 16
        if (isset($response[$this->evidence])) {
408 9
            $record = $response[$this->evidence][0];
409 9
        }
410
411 16
        return $record;
412
    }
413
414
    /**
415
     * Načte data z FlexiBee.
416
     *
417
     * @param string $suffix     dotaz
418
     * @param string $conditions Volitelný filtrovací výraz
419
     */
420 15
    public function getFlexiData($suffix = null, $conditions = null)
421
    {
422 15
        if (!is_null($conditions)) {
423 10
            if ($conditions[0] != '/') {
424 10
                $conditions = '/'.rawurlencode('('.($conditions).')');
425 10
            }
426 10
        } else {
427 15
            $conditions = '';
428
        }
429 15
        if ($suffix) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $suffix of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
430
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix,
431
                'GET');
432
        } else {
433 15
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format,
434 15
                'GET');
435
        }
436 15
        if (isset($transactions[$this->evidence])) {
437 12
            $result = $transactions[$this->evidence];
438 12
        } else {
439 3
            $result = $transactions;
440
        }
441
442 15
        return $result;
443
    }
444
445
    /**
446
     * Načte záznam z FlexiBee.
447
     *
448
     * @param int $id ID záznamu
449
     *
450
     * @return int počet načtených položek
451
     */
452 16
    public function loadFromFlexiBee($id = null)
453
    {
454 16
        if (is_null($id)) {
455 16
            $id = $this->getMyKey();
456 16
        }
457
458 16
        return $this->takeData($this->getFlexiData('/'.$id));
459
    }
460
461
    /**
462
     * Uloží data do FlexiBee.
463
     *
464
     * @param array $data
465
     *
466
     * @return array výsledek
467
     */
468
    public function saveToFlexiBee($data = null)
469
    {
470
        if (is_null($data)) {
471
            $data = $this->getData();
472
        }
473
474
        $jsonizedData = $this->jsonizeData($data);
475
476
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
477
478
        return $this->performRequest($this->evidence.'.'.$this->format, 'PUT');
479
    }
480
481
    /**
482
     * Převede data do Json formátu pro FlexiBee.
483
     *
484
     * @param array $data
485
     *
486
     * @return string
487
     */
488 16
    public function jsonizeData($data)
489
    {
490
        $jsonize = [
491 16
            $this->nameSpace => [
492 16
                '@version' => $this->protoVersion,
493 16
                $this->evidence => $data,
494 16
            ],
495 16
        ];
496
497 16
        return json_encode($jsonize);
498
    }
499
500
    /**
501
     * Uloží záznam.
502
     *
503
     * @param array $data
504
     *
505
     * @return array odpověď
506
     */
507
    public function insertToFlexiBee($data = null)
508
    {
509
        if (is_null($data)) {
510
            $data = $this->getData();
511
        }
512
        $this->postFields = $this->jsonizeData($data);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->jsonizeData($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...
513
        return $this->performRequest($this->evidence.'.'.$this->format, 'PUT');
514
    }
515
516
    /**
517
     * Test if given record ID exists in FlexiBee.
518
     *
519
     * @param string|int $identifer
520
     */
521
    public function idExists($identifer = null)
522
    {
523
        if (is_null($identifer)) {
524
            $identifer = $this->getMyKey();
525
        }
526
        $flexiData = $this->getFlexiData(
527
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
528
529
        return $flexiData;
530
    }
531
532
    /**
533
     * Test if given record exists in FlexiBee.
534
     *
535
     * @param array $data
536
     */
537
    public function recordExists($data = null)
538
    {
539
        if (is_null($data)) {
540
            $data = $this->getData();
541
        }
542
543
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
544
            self::flexiUrl($data));
545
546
        return $res;
547
    }
548
549
    /**
550
     * Vrací z FlexiBee sloupečky podle podmínek.
551
     *
552
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
553
     * @param array|string     $orderBy    třídit dle
554
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
555
     *                                     sloupečku
556
     * @param int              $limit      maximální počet vrácených záznamů
557
     *
558
     * @return array
559
     */
560
    public function getAllFromFlexibee($conditions = null, $orderBy = null,
0 ignored issues
show
Unused Code introduced by
The parameter $orderBy is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
561
                                       $indexBy = null, $limit = null)
0 ignored issues
show
Unused Code introduced by
The parameter $limit is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
562
    {
563
        if (is_int($conditions)) {
564
            $conditions = [$this->getmyKeyColumn() => $conditions];
565
        }
566
567
        $flexiData = $this->getFlexiData('', $conditions);
0 ignored issues
show
Bug introduced by
It seems like $conditions can also be of type array; however, FlexiPeeHP\FlexiBee::getFlexiData() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
568
569 View Code Duplication
        if ($indexBy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $indexBy of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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...
570
            $flexiData2 = [];
571
            foreach ($flexiData as $dataID => $data) {
572
                $flexiData2[$data[$indexBy]] = $data;
573
            }
574
            $flexiData = $flexiData2;
575
        }
576
577
        return $flexiData;
578
    }
579
580
    /**
581
     * Vrací z FlexiBee sloupečky podle podmínek.
582
     *
583
     * @param string[]         $columnsList seznam položek
584
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
585
     * @param array|string     $orderBy     třídit dle
586
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
587
     *                                      sloupečku
588
     * @param int              $limit       maximální počet vrácených záznamů
589
     *
590
     * @return array
591
     */
592
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
593
                                           $orderBy = null, $indexBy = null,
0 ignored issues
show
Unused Code introduced by
The parameter $orderBy is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
594
                                           $limit = null)
0 ignored issues
show
Unused Code introduced by
The parameter $limit is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
595
    {
596
        if (($columnsList != '*') && !count($columnsList)) {
597
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
598
599
            return;
600
        }
601
602
        if (is_int($conditions)) {
603
            $conditions = [$this->getmyKeyColumn() => $conditions];
604
        }
605
606
        if (is_array($columnsList)) {
607
            $columns = implode(',', array_unique($columnsList));
608
        } else {
609
            $columns = $columnsList;
610
        }
611
612
        $flexiData = $this->getFlexiData('detail=custom:'.$columns, $conditions);
0 ignored issues
show
Bug introduced by
It seems like $conditions can also be of type array; however, FlexiPeeHP\FlexiBee::getFlexiData() does only seem to accept string|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
613
614 View Code Duplication
        if ($indexBy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $indexBy of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
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...
615
            $flexiData2 = [];
616
            foreach ($flexiData as $dataID => $data) {
617
                $flexiData2[$data[$indexBy]] = $data;
618
            }
619
            $flexiData = $flexiData2;
620
        }
621
622
        return $flexiData;
623
    }
624
625
    /**
626
     * Vrací kód záznamu.
627
     *
628
     * @param mixed $data
629
     *
630
     * @todo papat i string
631
     *
632
     * @return string
633
     */
634 16
    public function getKod($data = null, $unique = true)
635
    {
636 16
        $kod = null;
637
638 16
        if (is_null($data)) {
639 16
            $data = $this->getData();
640 16
        }
641
642 16
        if (is_string($data)) {
643 16
            $data = [$this->nameColumn => $data];
644 16
        }
645
646 16
        if (isset($data['kod'])) {
647 16
            $kod = $data['kod'];
648 16
        } else {
649 16
            if (isset($data[$this->nameColumn])) {
650 16
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
651 16
                    \Ease\Sand::rip($data[$this->nameColumn]));
652 16
            } else {
653 16
                if (isset($data[$this->myKeyColumn])) {
654 16
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
655 16
                }
656
            }
657
        }
658
659 16
        if (!strlen($kod)) {
660 16
            $kod = 'NOTSET';
661 16
        }
662
663 16
        if (strlen($kod) > 18) {
664 16
            $kodfinal = strtoupper(substr($kod, 0, 18));
665 16
        } else {
666 16
            $kodfinal = strtoupper($kod);
667
        }
668
669 16
        if ($unique) {
670 16
            $counter = 0;
671 16
            if ($this->codes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->codes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
672 16
                foreach ($this->codes as $codesearch => $keystring) {
673 16
                    if (strstr($codesearch, $kodfinal)) {
674 16
                        ++$counter;
675 16
                    }
676 16
                }
677 16
            }
678 16
            if ($counter) {
679 16
                $kodfinal = $kodfinal.$counter;
680 16
            }
681
682 16
            $this->codes[$kodfinal] = $kod;
683 16
        }
684
685 16
        return $kodfinal;
686
    }
687
688
    /**
689
     * Vyhledavani v záznamech objektu FlexiBee.
690
     *
691
     * @param string $what hledaný výraz
692
     *
693
     * @return array pole výsledků
694
     */
695
    public function searchString($what)
696
    {
697
        $results   = [];
698
        $conds     = [];
699
        $columns[] = $this->myKeyColumn;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$columns was never initialized. Although not strictly required by PHP, it is generally a good practice to add $columns = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
700
        foreach ($this->useKeywords as $keyword => $keywordInfo) {
0 ignored issues
show
Bug introduced by
The property useKeywords does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
701
            if (isset($this->keywordsInfo[$keyword]['virtual']) && ($this->keywordsInfo[$keyword]['virtual']
0 ignored issues
show
Bug introduced by
The property keywordsInfo does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
702
                == true)) {
703
                if ($keyword == $this->nameColumn) {
704
                    $this->nameColumn = $this->myKeyColumn;
705
                }
706
                continue;
707
            }
708
            switch ($keywordInfo) {
709
                case 'INT':
710 View Code Duplication
                case 'FLOAT':
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...
711
                    if (is_numeric($what)) {
712
                        $conds[]   = "($keyword = ".$what.')';
713
                        $columns[] = "$keyword";
714
                    }
715
                    break;
716
                case 'TEXT':
717 View Code Duplication
                case 'STRING':
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...
718
                    if (is_string($what)) {
719
                        $conds[]   = "( $keyword like '".$what."')";
720
                        $columns[] = "$keyword";
721
                    }
722
                    break;
723
                default:
724
                    break;
725
            }
726
        }
727
728
//        $res = \Ease\Shared::db()->queryToArray('SELECT ' . implode(',', $columns) . ',' . $this->nameColumn . ' FROM ' . $this->myTable . ' WHERE ' . implode(' OR ', $conds) . ' ORDER BY ' . $this->nameColumn, $this->myKeyColumn);
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
729
730
        $res = $this->getColumnsFromFlexibee($columns, implode(' or ', $conds));
731
732
        foreach ($res as $result) {
733
            $occurences = '';
734
            foreach ($result as $key => $value) {
735
                if (is_array($value)) {
736
                    continue;
737
                }
738
                if (mb_stristr($value, $what)) {
739
                    $occurences .= '('.$key.': '.$value.')';
740
                }
741
            }
742
            $results[$result[$this->myKeyColumn]] = [$this->nameColumn => $result[$this->nameColumn],
743
                'what' => $occurences,];
744
        }
745
746
        return $results;
747
    }
748
749
    /**
750
     * Write Operation Result.
751
     * 
752
     * @param array  $resultData
753
     * @param string $url        URL
754
     */
755 16
    public function logResult($resultData, $url = null)
756
    {
757 16
        if ($url) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $url of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
758 16
            $this->logger->addStatusMessage($url);
759 16
        }
760
761 16
        if (isset($resultData['results'])) {
762 16
            $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...
763 16
            if ($resultData['success'] == 'false') {
764 16
                $status = 'error';
765 16
            } else {
766 16
                $status = 'success';
767
            }
768 16
            foreach ($resultData['results'] as $result) {
769 16
                if (isset($result['request-id'])) {
770 16
                    $rid = $result['request-id'];
771 16
                } else {
772 16
                    $rid = '';
773
                }
774 16
                if (isset($result['errors'])) {
775 16
                    foreach ($result['errors'] as $error) {
776 16
                        $message = $error['message'];
777 16
                        if (isset($error['for'])) {
778
                            $message.=' for: '.$error['for'];
779
                        }
780 16
                        if (isset($error['value'])) {
781
                            $message.=' value:'.$error['value'];
782
                        }
783 16
                        if (isset($error['code'])) {
784
                            $message.=' code:'.$error['code'];
785
                        }
786 16
                        $this->logger->addStatusMessage($rid.': '.$message,
787 16
                            $status);
788 16
                    }
789 16
                }
790 16
            }
791 16
        }
792 16
        if (is_object($this->logger)) {
793 16
            $this->logger->flush(get_class($this));
794 16
        }
795 16
    }
796
797
    /**
798
     * Generuje fragment url pro filtrování.
799
     *
800
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
801
     *
802
     * @param array  $data
803
     * @param string $operator and/or
804
     *
805
     * @return string
806
     */
807 16
    public static function flexiUrl(array $data, $operator = 'and')
808
    {
809 16
        $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...
810 16
        $parts    = [];
811
812 16
        foreach ($data as $column => $value) {
813 16
            if (is_numeric($data[$column])) {
814 16
                $parts[$column] = $column.' = '.$data[$column];
815 16
            } else {
816 16
                $parts[$column] = $column." = '".$data[$column]."'";
817
            }
818 16
        }
819
820 16
        $flexiUrl = implode(' '.$operator.' ', $parts);
821
822 16
        return $flexiUrl;
823
    }
824
825
    /**
826
     * Smaže záznam
827
     *
828
     * @param int|string $id identifikátor záznamu
829
     * @return boolean Response code is 200 ?
830
     */
831
    public function deleteFromFlexiBee($id)
832
    {
833
        $this->performRequest($this->evidence.'/'.$id.'.'.$this->format,
834
            'DELETE');
835
        return $this->lastResponseCode == 200;
836
    }
837
}