Completed
Push — master ( 8d9cf8...669f46 )
by Vítězslav
04:09
created

FlexiBee::xml2array()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 11
c 2
b 0
f 0
nc 6
nop 1
dl 0
loc 19
ccs 13
cts 13
cp 1
crap 4
rs 9.2
1
<?php
2
/**
3
 * System.Spoje.Net - 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
     * Agenda užitá objektem.
36
     *
37
     * @var string
38
     */
39
    public $agenda = 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
     * Třída pro práci s FlexiBee.
149
     *
150
     * @param string $init výchozí selektor dat
151
     */
152 26
    public function __construct($init = null)
153
    {
154 26
        $this->init = $init;
155
156 26
        parent::__construct();
157 26
        $this->curlInit();
158 26
    }
159
160 26
    public function curlInit()
161
    {
162 26
        $this->curl = \curl_init(); // create curl resource
163 26
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
164 26
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
165 26
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
166 26
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
167 26
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
168 26
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
169 26
        curl_setopt($this->curl, CURLOPT_USERPWD,
170 26
            $this->user.':'.$this->password); // set username and password
171 26
    }
172
173
    /**
174
     * Nastaví Agendu pro Komunikaci.
175
     *
176
     * @param string $agenda
177
     */
178 13
    public function setAgenda($agenda)
179
    {
180 13
        $this->agenda = $agenda;
181 13
    }
182
183
    /**
184
     * Převede rekurzivně Objekt na pole.
185
     *
186
     * @param object|array $object
187
     *
188
     * @return array
189
     */
190 13
    public static function object2array($object)
191
    {
192 13
        $result = null;
193 13
        if (is_object($object)) {
194 13
            $objectData = get_object_vars($object);
195 13
            if (is_array($objectData) && count($objectData)) {
196 13
                $result = array_map('self::object2array', $objectData);
197 13
            }
198 13
        } else {
199 13
            if (is_array($object)) {
200 13
                foreach ($object as $item => $value) {
201 13
                    $result[$item] = self::object2array($value);
202 13
                }
203 13
            } else {
204 13
                $result = $object;
205
            }
206
        }
207
208 13
        return $result;
209
    }
210
211
    /**
212
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
213
     *
214
     * @param string $urlSuffix část URL za identifikátorem firmy.
215
     * @param string $method    HTTP/REST metoda
216
     * @param string $format    Requested format
217
     */
218 13
    public function performRequest($urlSuffix = null, $method = 'GET',
219
                                   $format = null)
220
    {
221 13
        if (is_null($format)) {
222 13
            $format = $this->format;
223 13
        }
224 13
        if (is_null($urlSuffix)) {
225 2
            $urlSuffix = $this->agenda.'.'.$format;
226 2
        }
227 13
        $url = $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
228 13
        curl_setopt($this->curl, CURLOPT_URL, $url);
229
// Nastavení samotné operace
230 13
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
231
232
// Proveď samotnou operaci
233 13
        $response = curl_exec($this->curl);
234
235 13
        $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...
236
237 13
        $responseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
238
239 13
        if ($responseCode != 200 && $responseCode != 201) {
240 13
            $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...
241 13
            $response    = (json_encode(json_decode($response, true, 10),
242 13
                    JSON_PRETTY_PRINT));
243
244 13
            $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
245 13
                function ($match) {
246 13
                return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8',
247 13
                    'UCS-2BE');
248 13
            }, $response);
249
250 13
            if ($responseCode == 400) {
251 1
                $this->logResult(self::object2array(current(json_decode($response))));
0 ignored issues
show
Bug introduced by
It seems like self::object2array(curre...son_decode($response))) targeting FlexiPeeHP\FlexiBee::object2array() can also be of type null; however, FlexiPeeHP\FlexiBee::logResult() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
252 1
            } else {
253 13
                $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
254 13
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE),
255 13
                        stripslashes($response), $this->error), 'error');
256 13
                $this->addStatusMessage($url);
257
            }
258 13
            if ($response == 'null') {
259
                return;
260
            }
261
262 13
            return self::object2array(current(json_decode($response)));
263
        }
264
265
        // Parse response
266
        switch ($format) {
267 12
            case 'json':
268 12
                $decoded = json_decode($response, true, 10);
269 12
                if (($method == 'PUT') && isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
270
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
271
                } else {
272 12
                    $this->lastInsertedID = null;
273
                }
274
//                $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...
275
//                $this->addStatusMessage($decodeError);
276
277 12
                break;
278 2
            case 'xml':
279 2
                $decoded = self::xml2array($response);
280 2
                break;
281
        }
282
283
        // Get response body root automatically
284 12
        if (isset($decoded[$this->nameSpace])) {
285 12
            $decoded = $decoded[$this->nameSpace];
286 12
        }
287
288 12
        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...
289
    }
290
291
    /**
292
     * Give you last inserted record ID.
293
     * 
294
     * @return int
295
     */
296
    public function getLastInsertedId()
297
    {
298
        return $this->lastInsertedID;
299
    }
300
301
    /**
302
     * Convert XML to array.
303
     * 
304
     * @param string $xml
305
     *
306
     * @return array
307
     */
308 13
    public static function xml2array($xml)
309
    {
310 13
        $arr = [];
311
312 13
        if (is_string($xml)) {
313 13
            $xml = simplexml_load_string($xml);
314 13
        }
315
316 13
        foreach ($xml->children() as $r) {
317 13
            $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...
318 13
            if (count($r->children()) == 0) {
319 13
                $arr[$r->getName()] = strval($r);
320 13
            } else {
321 13
                $arr[$r->getName()][] = self::xml2array($r);
322
            }
323 13
        }
324
325 13
        return $arr;
326
    }
327
328
    /**
329
     * Odpojení od FlexiBee.
330
     */
331 14
    public function disconnect()
332
    {
333 14
        if (is_resource($this->curl)) {
334 14
            curl_close($this->curl);
335 14
        }
336 14
        $this->curl = null;
337 14
    }
338
339 14
    public function __destruct()
340
    {
341 14
        $this->disconnect();
342 14
    }
343
344
    /**
345
     * Načte data z FlexiBee.
346
     *
347
     * @param string $suffix dotaz
348
     */
349
    public function loadFlexiData($suffix = null)
350
    {
351
        return $this->takeData($this->getFlexiData($suffix));
352
    }
353
354
    /**
355
     * Načte řádek dat z FlexiBee.
356
     *
357
     * @param int $recordID id požadovaného záznamu
358
     *
359
     * @return array
360
     */
361 13
    public function getFlexiRow($recordID)
362
    {
363 13
        $record   = null;
364 13
        $response = $this->performRequest($this->agenda.'/'.$recordID.'.json');
365 13
        if (isset($response[$this->agenda])) {
366 9
            $record = $response[$this->agenda][0];
367 9
        }
368
369 13
        return $record;
370
    }
371
372
    /**
373
     * Načte data z FlexiBee.
374
     *
375
     * @param string $suffix     dotaz
376
     * @param string $conditions Volitelný filtrovací výraz
377
     */
378 12
    public function getFlexiData($suffix = null, $conditions = null)
379
    {
380 12
        if (!is_null($conditions)) {
381 10
            if ($conditions[0] != '/') {
382 10
                $conditions = '/'.rawurlencode('('.($conditions).')');
383 10
            }
384 10
        } else {
385 12
            $conditions = '';
386
        }
387 12
        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...
388
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format.'?'.$suffix,
389
                'GET');
390
        } else {
391 12
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format,
392 12
                'GET');
393
        }
394 12
        if (isset($transactions[$this->agenda])) {
395 10
            $result = $transactions[$this->agenda];
396 10
        } else {
397 2
            $result = $transactions;
398
        }
399
400 12
        return $result;
401
    }
402
403
    /**
404
     * Načte záznam z FlexiBee.
405
     *
406
     * @param int $id ID záznamu
407
     *
408
     * @return int počet načtených položek
409
     */
410 13
    public function loadFromFlexiBee($id = null)
411
    {
412 13
        if (is_null($id)) {
413 13
            $id = $this->getMyKey();
414 13
        }
415
416 13
        return $this->takeData($this->getFlexiData('/'.$id));
417
    }
418
419
    /**
420
     * Uloží data do FlexiBee.
421
     *
422
     * @param array $data
423
     *
424
     * @return array výsledek
425
     */
426 View Code Duplication
    public function saveToFlexiBee($data = 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...
427
    {
428
        if (is_null($data)) {
429
            $data = $this->getData();
430
        }
431
432
        $jsonizedData = $this->jsonizeData($data);
433
434
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
435
436
        return $this->performRequest($this->agenda.'.'.$this->format, 'PUT');
437
    }
438
439
    /**
440
     * Převede data do Json formátu pro FlexiBee.
441
     *
442
     * @param array $data
443
     *
444
     * @return string
445
     */
446 13
    public function jsonizeData($data)
447
    {
448
        $jsonize = [
449 13
            $this->nameSpace => [
450 13
                '@version' => $this->protoVersion,
451 13
                $this->agenda => $data,
452 13
            ],
453 13
        ];
454
455 13
        return json_encode($jsonize);
456
    }
457
458
    /**
459
     * Uloží záznam.
460
     *
461
     * @param array $data
462
     *
463
     * @return array odpověď
464
     */
465 View Code Duplication
    public function insertToFlexiBee($data = 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...
466
    {
467
        if (is_null($data)) {
468
            $data = $this->getData();
469
        }
470
        $jsonizedData = $this->jsonizeData($data);
471
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
472
473
        return $this->performRequest($this->agenda.'.'.$this->format, 'PUT');
474
    }
475
476
    /**
477
     * Test if given record ID exists in FlexiBee.
478
     *
479
     * @param string|int $identifer
480
     */
481
    public function idExists($identifer = null)
482
    {
483
        if (is_null($identifer)) {
484
            $identifer = $this->getMyKey();
485
        }
486
        $flexiData = $this->getFlexiData(
487
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
488
489
        return $flexiData;
490
    }
491
492
    /**
493
     * Test if given record exists in FlexiBee.
494
     *
495
     * @param array $data
496
     */
497
    public function recordExists($data = null)
498
    {
499
        if (is_null($data)) {
500
            $data = $this->getData();
501
        }
502
503
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
504
            self::flexiUrl($data));
505
506
        return $res;
507
    }
508
509
    /**
510
     * Vrací z FlexiBee sloupečky podle podmínek.
511
     *
512
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
513
     * @param array|string     $orderBy    třídit dle
514
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
515
     *                                     sloupečku
516
     * @param int              $limit      maximální počet vrácených záznamů
517
     *
518
     * @return array
519
     */
520
    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...
521
                                       $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...
522
    {
523
        if (is_int($conditions)) {
524
            $conditions = [$this->getmyKeyColumn() => $conditions];
525
        }
526
527
        $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...
528
529 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...
530
            $flexiData2 = [];
531
            foreach ($flexiData as $dataID => $data) {
532
                $flexiData2[$data[$indexBy]] = $data;
533
            }
534
            $flexiData = $flexiData2;
535
        }
536
537
        return $flexiData;
538
    }
539
540
    /**
541
     * Vrací z FlexiBee sloupečky podle podmínek.
542
     *
543
     * @param string[]         $columnsList seznam položek
544
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
545
     * @param array|string     $orderBy     třídit dle
546
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
547
     *                                      sloupečku
548
     * @param int              $limit       maximální počet vrácených záznamů
549
     *
550
     * @return array
551
     */
552
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
553
                                           $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...
554
                                           $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...
555
    {
556
        if (($columnsList != '*') && !count($columnsList)) {
557
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
558
559
            return;
560
        }
561
562
        if (is_int($conditions)) {
563
            $conditions = [$this->getmyKeyColumn() => $conditions];
564
        }
565
566
        if (is_array($columnsList)) {
567
            $columns = implode(',', array_unique($columnsList));
568
        } else {
569
            $columns = $columnsList;
570
        }
571
572
        $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...
573
574 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...
575
            $flexiData2 = [];
576
            foreach ($flexiData as $dataID => $data) {
577
                $flexiData2[$data[$indexBy]] = $data;
578
            }
579
            $flexiData = $flexiData2;
580
        }
581
582
        return $flexiData;
583
    }
584
585
    /**
586
     * Vrací kód záznamu.
587
     *
588
     * @param array $data
589
     *
590
     * @todo papat i string
591
     *
592
     * @return string
593
     */
594
    public function getKod($data = null, $unique = true)
595
    {
596
        $kod = null;
597
598
        if (is_null($data)) {
599
            $data = $this->getData();
600
        }
601
602
        if (isset($data['kod'])) {
603
            $kod = $data['kod'];
604
        } else {
605
            if (isset($data[$this->nameColumn])) {
606
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
607
                    \Ease\Sand::rip($data[$this->nameColumn]));
608
            } else {
609
                if (isset($data[$this->myKeyColumn])) {
610
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
611
                }
612
            }
613
        }
614
615
        if (strlen($kod) > 18) {
616
            $kodfinal = substr($kod, 0, 18);
617
        } else {
618
            $kodfinal = $kod;
619
        }
620
621
        if ($unique) {
622
            $counter = 0;
623
            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...
624
                foreach ($this->codes as $codesearch) {
625
                    if (!strlen($codesearch)) {
626
                        echo 'Error';
627
                    }
628
                    if (strstr($codesearch, $kodfinal)) {
629
                        ++$counter;
630
                    }
631
                }
632
            }
633
            if ($counter) {
634
                $kodfinal = $kodfinal.$counter;
635
            }
636
637
            $this->codes[$kodfinal] = $kod;
638
        }
639
640
        return strtoupper($kodfinal);
641
    }
642
643
    /**
644
     * Vyhledavani v záznamech objektu FlexiBee.
645
     *
646
     * @param string $what hledaný výraz
647
     *
648
     * @return array pole výsledků
649
     */
650
    public function searchString($what)
651
    {
652
        $results   = [];
653
        $conds     = [];
654
        $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...
655
        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...
656
            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...
657
                == true)) {
658
                if ($keyword == $this->nameColumn) {
659
                    $this->nameColumn = $this->myKeyColumn;
660
                }
661
                continue;
662
            }
663
            switch ($keywordInfo) {
664
                case 'INT':
665 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...
666
                    if (is_numeric($what)) {
667
                        $conds[]   = "($keyword = ".$what.')';
668
                        $columns[] = "$keyword";
669
                    }
670
                    break;
671
                case 'TEXT':
672 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...
673
                    if (is_string($what)) {
674
                        $conds[]   = "( $keyword like '".$what."')";
675
                        $columns[] = "$keyword";
676
                    }
677
                    break;
678
                default:
679
                    break;
680
            }
681
        }
682
683
//        $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...
684
685
        $res = $this->getColumnsFromFlexibee($columns, implode(' or ', $conds));
686
687
        foreach ($res as $result) {
688
            $occurences = '';
689
            foreach ($result as $key => $value) {
690
                if (is_array($value)) {
691
                    continue;
692
                }
693
                if (mb_stristr($value, $what)) {
694
                    $occurences .= '('.$key.': '.$value.')';
695
                }
696
            }
697
            $results[$result[$this->myKeyColumn]] = [$this->nameColumn => $result[$this->nameColumn],
698
                'what' => $occurences,];
699
        }
700
701
        return $results;
702
    }
703
704
    /**
705
     * Write Operation Result.
706
     * 
707
     * @param array  $resultData
708
     * @param string $url        URL
709
     */
710 13
    public function logResult($resultData, $url = null)
711
    {
712 13
        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...
713 13
            $this->logger->addStatusMessage($url);
714 13
        }
715
716 13
        if (isset($resultData['results'])) {
717 13
            $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...
718 13
            if ($resultData['success'] == 'false') {
719 13
                $status = 'error';
720 13
            } else {
721 13
                $status = 'success';
722
            }
723 13
            foreach ($resultData['results'] as $result) {
724 13
                if (isset($result['request-id'])) {
725 13
                    $rid = $result['request-id'];
726 13
                } else {
727 13
                    $rid = '';
728
                }
729 13
                if (isset($result['errors'])) {
730 13
                    foreach ($result['errors'] as $error) {
731 13
                        $this->logger->addStatusMessage($rid.': '.$error['message'],
732 13
                            $status);
733 13
                    }
734 13
                }
735 13
            }
736 13
        }
737 13
        if (is_object($this->logger)) {
738 13
            $this->logger->flush(get_class($this));
0 ignored issues
show
Bug introduced by
The method flush() does not seem to exist on object<Ease\Logger>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
739 13
        }
740 13
    }
741
742
    /**
743
     * Generuje fragment url pro filtrování.
744
     *
745
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
746
     *
747
     * @param array  $data
748
     * @param string $operator and/or
749
     *
750
     * @return string
751
     */
752 13
    public static function flexiUrl(array $data, $operator = 'and')
753
    {
754 13
        $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...
755 13
        $parts    = [];
756
757 13
        foreach ($data as $column => $value) {
758 13
            if (is_numeric($data[$column])) {
759 13
                $parts[$column] = $column.' = '.$data[$column];
760 13
            } else {
761 13
                $parts[$column] = $column." = '".$data[$column]."'";
762
            }
763 13
        }
764
765 13
        $flexiUrl = implode(' '.$operator.' ', $parts);
766
767 13
        return $flexiUrl;
768
    }
769
}