Completed
Push — master ( 0dc5c4...fea5ff )
by Vítězslav
03:55
created

FlexiBee::saveToFlexiBee()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 6
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 12
ccs 0
cts 5
cp 0
crap 6
rs 9.4285
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
            } elseif (strlen($response) && ($response != 'null')) {
278 16
                $result = http_build_query(self::object2array(current(json_decode($response))));
279
            } else {
280
                $result = null;
281 16
            }
282 2
283 2
            if ($this->lastResponseCode == 400) {
284 16
                $this->logResult($result);
0 ignored issues
show
Documentation introduced by
$result is of type string|null, 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...
285 16
            } else {
286 16
                $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
287 16
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE), $result,
288
                        $this->error), 'error');
289 16
                $this->addStatusMessage($url, 'info');
290
                $this->addStatusMessage($this->postFields, 'debug');
0 ignored issues
show
Documentation introduced by
$this->postFields is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
291
            }
292
            if ($response == 'null') {
293
                if ($this->lastResponseCode == 200) {
294
                    $response = true;
295
                } else {
296 16
                    $response = null;
297 16
                }
298 16
            } else {
299
                if (is_string($response)) {
300 16
                    $response = self::object2array(current(json_decode($response)));
301
                }
302
            }
303
            return $response;
304
        }
305 14
306 14
        // Parse response
307 14
        switch ($format) {
308
            case 'json':
309
                $decoded = json_decode($response, true, 10);
310 14
                if (($method == 'PUT') && isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
311
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
312
                } else {
313
                    $this->lastInsertedID = null;
314
                }
315 14
//                $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...
316 3
//                $this->addStatusMessage($decodeError);
317 3
318 3
                break;
319 3
            case 'xml':
320
                if (strlen($response)) {
321
                    $decoded = self::xml2array($response);
322 3
                } else {
323
                    $decoded = null;
324
                }
325
                break;
326 14
        }
327 14
328 14
        // Get response body root automatically
329
        if (isset($decoded[$this->nameSpace])) {
330 14
            $decoded = $decoded[$this->nameSpace];
331
        }
332
333
        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...
334
    }
335
336
    /**
337
     * Give you last inserted record ID.
338
     * 
339
     * @return int
340
     */
341
    public function getLastInsertedId()
342
    {
343
        return $this->lastInsertedID;
344
    }
345
346
    /**
347
     * Convert XML to array.
348
     * 
349
     * @param string $xml
350 16
     *
351
     * @return array
352 16
     */
353
    public static function xml2array($xml)
354 16
    {
355 16
        $arr = [];
356 16
357
        if (is_string($xml)) {
358 16
            $xml = simplexml_load_string($xml);
359 16
        }
360 16
361 16
        foreach ($xml->children() as $r) {
362 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...
363 16
            if (count($r->children()) == 0) {
364
                $arr[$r->getName()] = strval($r);
365 16
            } else {
366
                $arr[$r->getName()][] = self::xml2array($r);
367 16
            }
368
        }
369
370
        return $arr;
371
    }
372
373 17
    /**
374
     * Odpojení od FlexiBee.
375 17
     */
376 17
    public function disconnect()
377 17
    {
378 17
        if (is_resource($this->curl)) {
379 17
            curl_close($this->curl);
380
        }
381 17
        $this->curl = null;
382
    }
383 17
384 17
    public function __destruct()
385
    {
386
        $this->disconnect();
387
    }
388
389
    /**
390
     * Načte data z FlexiBee.
391
     *
392
     * @param string $suffix dotaz
393
     */
394
    public function loadFlexiData($suffix = null)
395
    {
396
        return $this->takeData($this->getFlexiData($suffix));
397
    }
398
399
    /**
400
     * Načte řádek dat z FlexiBee.
401
     *
402
     * @param int $recordID id požadovaného záznamu
403 16
     *
404
     * @return array
405 16
     */
406 16
    public function getFlexiRow($recordID)
407 16
    {
408 9
        $record   = null;
409 9
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
410
        if (isset($response[$this->evidence])) {
411 16
            $record = $response[$this->evidence][0];
412
        }
413
414
        return $record;
415
    }
416
417
    /**
418
     * Načte data z FlexiBee.
419
     *
420 15
     * @param string $suffix     dotaz
421
     * @param string $conditions Volitelný filtrovací výraz
422 15
     */
423 10
    public function getFlexiData($suffix = null, $conditions = null)
424 10
    {
425 10
        if (!is_null($conditions)) {
426 10
            if ($conditions[0] != '/') {
427 15
                $conditions = '/'.rawurlencode('('.($conditions).')');
428
            }
429 15
        } else {
430
            $conditions = '';
431
        }
432
        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...
433 15
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix,
434 15
                'GET');
435
        } else {
436 15
            $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format,
437 12
                'GET');
438 12
        }
439 3
        if (isset($transactions[$this->evidence])) {
440
            $result = $transactions[$this->evidence];
441
        } else {
442 15
            $result = $transactions;
443
        }
444
445
        return $result;
446
    }
447
448
    /**
449
     * Načte záznam z FlexiBee.
450
     *
451
     * @param int $id ID záznamu
452 16
     *
453
     * @return int počet načtených položek
454 16
     */
455 16
    public function loadFromFlexiBee($id = null)
456 16
    {
457
        if (is_null($id)) {
458 16
            $id = $this->getMyKey();
459
        }
460
461
        return $this->takeData($this->getFlexiData('/'.$id));
462
    }
463
464
    /**
465
     * Převede data do Json formátu pro FlexiBee.
466
     *
467
     * @param array $data
468
     *
469
     * @return string
470
     */
471
    public function jsonizeData($data)
472
    {
473
        $jsonize = [
474
            $this->nameSpace => [
475
                '@version' => $this->protoVersion,
476
                $this->evidence => $data,
477
            ],
478
        ];
479
480
        return json_encode($jsonize);
481
    }
482
483
    /**
484
     * Uloží záznam.
485
     *
486
     * @param array $data
487
     *
488 16
     * @return array odpověď
489
     */
490
    public function insertToFlexiBee($data = null)
491 16
    {
492 16
        if (is_null($data)) {
493 16
            $data = $this->getData();
494 16
        }
495 16
        $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...
496
        return $this->performRequest($this->evidence.'.'.$this->format, 'PUT');
497 16
    }
498
499
    /**
500
     * Test if given record ID exists in FlexiBee.
501
     *
502
     * @param string|int $identifer
503
     */
504
    public function idExists($identifer = null)
505
    {
506
        if (is_null($identifer)) {
507
            $identifer = $this->getMyKey();
508
        }
509
        $flexiData = $this->getFlexiData(
510
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
511
512
        return $flexiData;
513
    }
514
515
    /**
516
     * Test if given record exists in FlexiBee.
517
     *
518
     * @param array $data
519
     */
520
    public function recordExists($data = null)
521
    {
522
        if (is_null($data)) {
523
            $data = $this->getData();
524
        }
525
526
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
527
            self::flexiUrl($data));
528
529
        return $res;
530
    }
531
532
    /**
533
     * Vrací z FlexiBee sloupečky podle podmínek.
534
     *
535
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
536
     * @param array|string     $orderBy    třídit dle
537
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
538
     *                                     sloupečku
539
     * @param int              $limit      maximální počet vrácených záznamů
540
     *
541
     * @return array
542
     */
543
    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...
544
                                       $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...
545
    {
546
        if (is_int($conditions)) {
547
            $conditions = [$this->getmyKeyColumn() => $conditions];
548
        }
549
550
        $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...
551
552 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...
553
            $flexiData2 = [];
554
            foreach ($flexiData as $dataID => $data) {
555
                $flexiData2[$data[$indexBy]] = $data;
556
            }
557
            $flexiData = $flexiData2;
558
        }
559
560
        return $flexiData;
561
    }
562
563
    /**
564
     * Vrací z FlexiBee sloupečky podle podmínek.
565
     *
566
     * @param string[]         $columnsList seznam položek
567
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
568
     * @param array|string     $orderBy     třídit dle
569
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
570
     *                                      sloupečku
571
     * @param int              $limit       maximální počet vrácených záznamů
572
     *
573
     * @return array
574
     */
575
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
576
                                           $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...
577
                                           $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...
578
    {
579
        if (($columnsList != '*') && !count($columnsList)) {
580
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
581
582
            return;
583
        }
584
585
        if (is_int($conditions)) {
586
            $conditions = [$this->getmyKeyColumn() => $conditions];
587
        }
588
589
        if (is_array($columnsList)) {
590
            $columns = implode(',', array_unique($columnsList));
591
        } else {
592
            $columns = $columnsList;
593
        }
594
595
        $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...
596
597 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...
598
            $flexiData2 = [];
599
            foreach ($flexiData as $dataID => $data) {
600
                $flexiData2[$data[$indexBy]] = $data;
601
            }
602
            $flexiData = $flexiData2;
603
        }
604
605
        return $flexiData;
606
    }
607
608
    /**
609
     * Vrací kód záznamu.
610
     *
611
     * @param mixed $data
612
     *
613
     * @todo papat i string
614
     *
615
     * @return string
616
     */
617
    public function getKod($data = null, $unique = true)
618
    {
619
        $kod = null;
620
621
        if (is_null($data)) {
622
            $data = $this->getData();
623
        }
624
625
        if (is_string($data)) {
626
            $data = [$this->nameColumn => $data];
627
        }
628
629
        if (isset($data['kod'])) {
630
            $kod = $data['kod'];
631
        } else {
632
            if (isset($data[$this->nameColumn])) {
633
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
634 16
                    \Ease\Sand::rip($data[$this->nameColumn]));
635
            } else {
636 16
                if (isset($data[$this->myKeyColumn])) {
637
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
638 16
                }
639 16
            }
640 16
        }
641
642 16
        if (!strlen($kod)) {
643 16
            $kod = 'NOTSET';
644 16
        }
645
646 16
        if (strlen($kod) > 18) {
647 16
            $kodfinal = strtoupper(substr($kod, 0, 18));
648 16
        } else {
649 16
            $kodfinal = strtoupper($kod);
650 16
        }
651 16
652 16
        if ($unique) {
653 16
            $counter = 0;
654 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...
655 16
                foreach ($this->codes as $codesearch => $keystring) {
656
                    if (strstr($codesearch, $kodfinal)) {
657
                        ++$counter;
658
                    }
659 16
                }
660 16
            }
661 16
            if ($counter) {
662
                $kodfinal = $kodfinal.$counter;
663 16
            }
664 16
665 16
            $this->codes[$kodfinal] = $kod;
666 16
        }
667
668
        return $kodfinal;
669 16
    }
670 16
671 16
    /**
672 16
     * Vyhledavani v záznamech objektu FlexiBee.
673 16
     *
674 16
     * @param string $what hledaný výraz
675 16
     *
676 16
     * @return array pole výsledků
677 16
     */
678 16
    public function searchString($what)
679 16
    {
680 16
        $results   = [];
681
        $conds     = [];
682 16
        $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...
683 16
        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...
684
            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...
685 16
                == true)) {
686
                if ($keyword == $this->nameColumn) {
687
                    $this->nameColumn = $this->myKeyColumn;
688
                }
689
                continue;
690
            }
691
            switch ($keywordInfo) {
692
                case 'INT':
693 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...
694
                    if (is_numeric($what)) {
695
                        $conds[]   = "($keyword = ".$what.')';
696
                        $columns[] = "$keyword";
697
                    }
698
                    break;
699
                case 'TEXT':
700 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...
701
                    if (is_string($what)) {
702
                        $conds[]   = "( $keyword like '".$what."')";
703
                        $columns[] = "$keyword";
704
                    }
705
                    break;
706
                default:
707
                    break;
708
            }
709
        }
710
711
//        $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...
712
713
        $res = $this->getColumnsFromFlexibee($columns, implode(' or ', $conds));
714
715
        foreach ($res as $result) {
716
            $occurences = '';
717
            foreach ($result as $key => $value) {
718
                if (is_array($value)) {
719
                    continue;
720
                }
721
                if (mb_stristr($value, $what)) {
722
                    $occurences .= '('.$key.': '.$value.')';
723
                }
724
            }
725
            $results[$result[$this->myKeyColumn]] = [$this->nameColumn => $result[$this->nameColumn],
726
                'what' => $occurences,];
727
        }
728
729
        return $results;
730
    }
731
732
    /**
733
     * Write Operation Result.
734
     * 
735
     * @param array  $resultData
736
     * @param string $url        URL
737
     */
738
    public function logResult($resultData, $url = null)
739
    {
740
        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...
741
            $this->logger->addStatusMessage($url);
742
        }
743
744
        if (isset($resultData['results'])) {
745
            $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...
746
            if ($resultData['success'] == 'false') {
747
                $status = 'error';
748
            } else {
749
                $status = 'success';
750
            }
751
            foreach ($resultData['results'] as $result) {
752
                if (isset($result['request-id'])) {
753
                    $rid = $result['request-id'];
754
                } else {
755 16
                    $rid = '';
756
                }
757 16
                if (isset($result['errors'])) {
758 16
                    foreach ($result['errors'] as $error) {
759 16
                        $message = $error['message'];
760
                        if (isset($error['for'])) {
761 16
                            $message.=' for: '.$error['for'];
762 16
                        }
763 16
                        if (isset($error['value'])) {
764 16
                            $message.=' value:'.$error['value'];
765 16
                        }
766 16
                        if (isset($error['code'])) {
767
                            $message.=' code:'.$error['code'];
768 16
                        }
769 16
                        $this->logger->addStatusMessage($rid.': '.$message,
770 16
                            $status);
771 16
                    }
772 16
                }
773
            }
774 16
        }
775 16
        if (is_object($this->logger)) {
776 16
            $this->logger->flush(get_class($this));
777 16
        }
778
    }
779
780 16
    /**
781
     * Generuje fragment url pro filtrování.
782
     *
783 16
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
784
     *
785
     * @param array  $data
786 16
     * @param string $operator and/or
787 16
     *
788 16
     * @return string
789 16
     */
790 16
    public static function flexiUrl(array $data, $operator = 'and')
791 16
    {
792 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...
793 16
        $parts    = [];
794 16
795 16
        foreach ($data as $column => $value) {
796
            if (is_numeric($data[$column])) {
797
                $parts[$column] = $column.' = '.$data[$column];
798
            } else {
799
                $parts[$column] = $column." = '".$data[$column]."'";
800
            }
801
        }
802
803
        $flexiUrl = implode(' '.$operator.' ', $parts);
804
805
        return $flexiUrl;
806
    }
807 16
808
    /**
809 16
     * Smaže záznam
810 16
     *
811
     * @param int|string $id identifikátor záznamu
812 16
     * @return boolean Response code is 200 ?
813 16
     */
814 16
    public function deleteFromFlexiBee($id)
815 16
    {
816 16
        $this->performRequest($this->evidence.'/'.$id.'.'.$this->format,
817
            'DELETE');
818 16
        return $this->lastResponseCode == 200;
819
    }
820
}