Completed
Push — master ( 68f225...5edd48 )
by Vítězslav
04:44
created

FlexiBeeRO::processRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 1
c 1
b 0
f 1
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 * FlexiPeeHP - Třída pro čtení z FlexiBee.
4
 *
5
 * @author     Vítězslav Dvořák <[email protected]>
6
 * @copyright  (C) 2015,2016 Spoje.Net
7
 */
8
9
namespace FlexiPeeHP;
10
11
class FlexiBeeRO extends \Ease\Brick
12
{
13
    /**
14
     * Základní namespace pro komunikaci s FlexiBEE.
15
     *
16
     * @var string Jmený prostor datového bloku odpovědi
17
     */
18
    public $nameSpace = 'winstrom';
19
20
    /**
21
     * Datový blok v poli odpovědi.
22
     *
23
     * @var string
24
     */
25
    public $resultField = 'results';
26
27
    /**
28
     * Verze protokolu použitého pro komunikaci.
29
     *
30
     * @var string Verze použitého API
31
     */
32
    public $protoVersion = '1.0';
33
34
    /**
35
     * Evidence užitá objektem.
36
     *
37
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
38
     * @var string
39
     */
40
    public $evidence = null;
41
42
    /**
43
     * Výchozí formát pro komunikaci.
44
     *
45
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
46
     *
47
     * @var string json|xml|...
48
     */
49
    public $format = 'json';
50
51
    /**
52
     * Curl Handle.
53
     *
54
     * @var resource
55
     */
56
    public $curl = null;
57
58
    /**
59
     * @var type
60
     */
61
    public $company = FLEXIBEE_COMPANY;
62
63
    /**
64
     * @var string
65
     */
66
    public $url = FLEXIBEE_URL;
67
68
    /**
69
     * @var string
70
     */
71
    public $user = FLEXIBEE_LOGIN;
72
73
    /**
74
     * @var string
75
     */
76
    public $password = FLEXIBEE_PASSWORD;
77
78
    /**
79
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
80
     */
81
    public $defaultHttpHeaders = ['User-Agent: FlexiPeeHP'];
82
83
    /**
84
     * Identifikační řetězec.
85
     *
86
     * @var string
87
     */
88
    public $init = null;
89
90
    /**
91
     * Sloupeček s názvem.
92
     *
93
     * @var string
94
     */
95
    public $nameColumn = 'nazev';
96
97
    /**
98
     * Sloupeček obsahující datum vložení záznamu do shopu.
99
     *
100
     * @var string
101
     */
102
    public $myCreateColumn = 'false';
103
104
    /**
105
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
106
     *
107
     * @var string
108
     */
109
    public $myLastModifiedColumn = 'lastUpdate';
110
111
    /**
112
     * Klíčový idendifikátor záznamu.
113
     *
114
     * @var string
115
     */
116
    public $fbKeyColumn = 'id';
117
118
    /**
119
     * Informace o posledním HTTP requestu.
120
     *
121
     * @var array
122
     */
123
    public $info;
124
125
    /**
126
     * Informace o poslední HTTP chybě.
127
     *
128
     * @var array
129
     */
130
    public $error;
131
132
    /**
133
     * Used codes storage.
134
     *
135
     * @var array
136
     */
137
    public $codes = null;
138
139
    /**
140
     * Last Inserted ID.
141
     *
142
     * @var int
143
     */
144
    public $lastInsertedID = null;
145
146
    /**
147
     * Default Line Prefix.
148
     *
149
     * @var string
150
     */
151
    public $prefix = '/c/';
152
153
    /**
154
     * HTTP Response code of last request
155
     *
156
     * @var int
157
     */
158
    public $lastResponseCode = null;
159
160
    /**
161
     * Array of fields for next curl POST operation
162
     *
163
     * @var array
164
     */
165
    protected $postFields = [];
166
167
    /**
168
     * Last operation result data or message(s)
169
     *
170
     * @var array
171
     */
172
    public $lastResult = null;
173
174
    /**
175
     * Třída pro práci s FlexiBee.
176
     *
177
     * @param string $init výchozí selektor dat
178
     */
179
    public function __construct($init = null)
180
    {
181
        $this->init = $init;
182
183
        parent::__construct();
184
        $this->curlInit();
185
    }
186
187
    public function curlInit()
188
    {
189
        $this->curl = \curl_init(); // create curl resource
190
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
191
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
192
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
193
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
194
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
195
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
196
        curl_setopt($this->curl, CURLOPT_USERPWD,
197
            $this->user.':'.$this->password); // set username and password
198
    }
199
200
    /**
201
     * Nastaví Agendu pro Komunikaci.
202
     *
203
     * @param string $evidence
204
     */
205
    public function setEvidence($evidence)
206
    {
207
        $this->evidence = $evidence;
208
    }
209
210
    /**
211
     * Převede rekurzivně Objekt na pole.
212
     *
213
     * @param object|array $object
214
     *
215
     * @return array
216
     */
217
    public static function object2array($object)
218
    {
219
        $result = null;
220
        if (is_object($object)) {
221
            $objectData = get_object_vars($object);
222
            if (is_array($objectData) && count($objectData)) {
223
                $result = array_map('self::object2array', $objectData);
224
            }
225
        } else {
226
            if (is_array($object)) {
227
                foreach ($object as $item => $value) {
228
                    $result[$item] = self::object2array($value);
229
                }
230
            } else {
231
                $result = $object;
232
            }
233
        }
234
235
        return $result;
236
    }
237
238
    /**
239
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
240
     *
241
     * @param string $urlSuffix část URL za identifikátorem firmy.
242
     * @param string $method    HTTP/REST metoda
243
     * @param string $format    Requested format
244
     */
245
    public function performRequest($urlSuffix = null, $method = 'GET',
246
                                   $format = null)
247
    {
248
        if (is_null($format)) {
249
            $format = $this->format;
250
        }
251
        if (is_null($urlSuffix)) {
252
            $urlSuffix = $this->evidence.'.'.$format;
253
        }
254
        $url = $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
255
        curl_setopt($this->curl, CURLOPT_URL, $url);
256
// Nastavení samotné operace
257
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
258
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
259
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
260
261
        $httpHeaders = $this->defaultHttpHeaders;
262
        switch ($format) {
263
            case 'json':
264
                $httpHeaders[] = 'Accept: application/json';
265
                break;
266
            case 'xml':
267
                $httpHeaders[] = 'Accept: application/xml';
268
                break;
269
270
            default:
271
                break;
272
        }
273
274
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeaders);
275
276
// Proveď samotnou operaci
277
        $response = curl_exec($this->curl);
278
279
        $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...
280
281
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
282
283
        if ($this->lastResponseCode != 200 && $this->lastResponseCode != 201) {
284
            $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...
285
            switch ($format) {
286
                case 'json':
287
                    $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
288
                        function ($match) {
289
                        return mb_convert_encoding(pack('H*', $match[1]),
290
                            'UTF-8', 'UCS-2BE');
291
                    }, $response);
292
                    $response = (json_encode(json_decode($response, true, 10),
293
                            JSON_PRETTY_PRINT));
294
                    break;
295
                case 'xml':
296
                    if (strlen($response)) {
297
                        $response = self::xml2array($response);
298
                    }
299
                    break;
300
            }
301
302
            if (is_array($response)) {
303
                $result = urldecode(http_build_query($response));
304
            } elseif (strlen($response) && ($response != 'null')) {
305
                $result = urldecode(http_build_query(self::object2array(current(json_decode($response)))));
306
            } else {
307
                $result = null;
308
            }
309
310
            if ($response == 'null') {
311
                if ($this->lastResponseCode == 200) {
312
                    $response = true;
313
                } else {
314
                    $response = null;
315
                }
316
            } else {
317
                if (is_string($response)) {
318
                    $response = self::object2array(current(json_decode($response)));
319
                }
320
            }
321
322
            if ($this->lastResponseCode == 400) {
323
                $this->logResult($response);
324
            } else {
325
                $this->addStatusMessage(sprintf('Error (HTTP %d): <pre>%s</pre> %s',
326
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE), $result,
327
                        $this->error), 'error');
328
                $this->addStatusMessage($url, 'info');
329
                if ($this->postFields) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->postFields 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...
330
                    $this->addStatusMessage(urldecode(http_build_query($this->postFields)),
331
                        'debug');
332
                }
333
            }
334
335
336
            return $response;
337
        }
338
339
        // Parse response
340
        switch ($format) {
341
            case 'json':
342
                $decoded = json_decode($response, true, 10);
343
                if (($method == 'PUT') && isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
344
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
345
                } else {
346
                    $this->lastInsertedID = null;
347
                }
348
//                $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...
349
//                $this->addStatusMessage($decodeError);
350
351
                break;
352
            case 'xml':
353
                if (strlen($response)) {
354
                    $decoded = self::xml2array($response);
355
                } else {
356
                    $decoded = null;
357
                }
358
                break;
359
        }
360
361
        // Get response body root automatically
362
        if (isset($decoded[$this->nameSpace])) {
363
            $decoded = $decoded[$this->nameSpace];
364
        }
365
366
        $this->lastResult = $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...
Documentation Bug introduced by
It seems like $decoded of type * is incompatible with the declared type array of property $lastResult.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

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