Completed
Push — master ( 7ac129...e64ee2 )
by Vítězslav
03:14
created

FlexiBee::getAllFromFlexibee()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 11

Duplication

Lines 7
Ratio 35 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 7
loc 20
rs 9.2
cc 4
eloc 11
nc 4
nop 4
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
     * @var string Jmený prostor datového bloku odpovědi
16
     */
17
    public $nameSpace = 'winstrom';
18
19
    /**
20
     * Datový blok v poli odpovědi
21
     *
22
     * @var string
23
     */
24
    public $resultField = 'results';
25
26
    /**
27
     * Verze protokolu použitého pro komunikaci.
28
     * @var string Verze použitého API
29
     */
30
    public $protoVersion = '1.0';
31
32
    /**
33
     * Agenda užitá objektem.
34
     *
35
     * @var string
36
     */
37
    public $agenda = null;
38
39
    /**
40
     * Výchozí formát pro komunikaci.
41
     *
42
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
43
     *
44
     * @var string json|xml|...
45
     */
46
    public $format = 'json';
47
48
    /**
49
     * Curl Handle.
50
     *
51
     * @var resource
52
     */
53
    public $curl = null;
54
55
    /**
56
     * @var type
57
     */
58
    public $company = FLEXIBEE_COMPANY;
59
60
    /**
61
     * @var string
62
     */
63
    public $url = FLEXIBEE_URL;
64
65
    /**
66
     * @var string
67
     */
68
    public $user = FLEXIBEE_LOGIN;
69
70
    /**
71
     * @var string
72
     */
73
    public $password = FLEXIBEE_PASSWORD;
74
75
    /**
76
     * Identifikační řetězec.
77
     *
78
     * @var string
79
     */
80
    public $init = null;
81
82
    /**
83
     * Sloupeček s názvem.
84
     *
85
     * @var string
86
     */
87
    public $nameColumn = 'nazev';
88
89
    /**
90
     * Sloupeček obsahující datum vložení záznamu do shopu.
91
     *
92
     * @var string
93
     */
94
    public $myCreateColumn = 'false';
95
96
    /**
97
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
98
     *
99
     * @var string
100
     */
101
    public $myLastModifiedColumn = 'lastUpdate';
102
103
    /**
104
     * Klíčový idendifikátor záznamu.
105
     *
106
     * @var string
107
     */
108
    public $fbKeyColumn = 'id';
109
110
    /**
111
     * Informace o posledním HTTP requestu.
112
     *
113
     * @var array
114
     */
115
    public $info;
116
117
    /**
118
     * Informace o poslední HTTP chybě.
119
     *
120
     * @var array
121
     */
122
    public $error;
123
124
    /**
125
     * Used codes storage
126
     * @var array
127
     */
128
    public $codes = null;
129
130
    /**
131
     * Last Inserted ID
132
     * @var int
133
     */
134
    public $lastInsertedID = null;
135
136
    /**
137
     * Default Line Prefix
138
     * @var string
139
     */
140
    public $prefix = '/c/';
141
142
    /**
143
     * Třída pro práci s FlexiBee.
144
     *
145
     * @param string $init výchozí selektor dat
146
     */
147
    public function __construct($init = null)
148
    {
149
        $this->init = $init;
150
151
        parent::__construct();
152
        $this->curl = \curl_init(); // create curl resource
153
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
154
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
155
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
156
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
157
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
158
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
159
        curl_setopt($this->curl, CURLOPT_USERPWD,
160
            $this->user.':'.$this->password); // set username and password
161
    }
162
163
    /**
164
     * Nastaví Agendu pro Komunikaci.
165
     *
166
     * @param string $agenda
167
     */
168
    public function setAgenda($agenda)
169
    {
170
        $this->agenda = $agenda;
171
    }
172
173
    /**
174
     * Převede rekurzivně Objekt na pole.
175
     *
176
     * @param object $data
177
     *
178
     * @return array
179
     */
180
    public static function object2array($data)
181
    {
182
        if (!is_object($data) && !is_array($data)) {
183
            return $data;
184
        }
185
        if (is_object($data)) {
186
            $data = get_object_vars($data);
187
        }
188
189
        return array_map('self::object2array', $data);
190
    }
191
192
    /**
193
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
194
     *
195
     * @param string $urlSuffix část URL za identifikátorem firmy.
196
     * @param string $method HTTP/REST metoda
197
     * @param string $format Requested format
198
     */
199
    public function performRequest($urlSuffix = null, $method = 'GET',
200
                                   $format = null)
201
    {
202
        if (is_null($format)) {
203
            $format = $this->format;
204
        }
205
        if (is_null($urlSuffix)) {
206
            $urlSuffix = $this->agenda.'.'.$format;
207
        }
208
        $url = $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
209
        curl_setopt($this->curl, CURLOPT_URL, $url);
210
// Nastavení samotné operace
211
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
212
213
// Proveď samotnou operaci
214
        $response = curl_exec($this->curl);
215
216
        $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...
217
218
        $responseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
219
220
        if ($responseCode != 200 && $responseCode != 201) {
221
            $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...
222
            $response    = (json_encode(json_decode($response, true, 10),
223
                    JSON_PRETTY_PRINT));
224
225
            $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
226
                function ($match) {
227
                return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8',
228
                    'UCS-2BE');
229
            }, $response);
230
231
            if ($responseCode == 400) {
232
                $this->logResult(self::object2array(current(json_decode($response))));
233
            } else {
234
                $this->addStatusMessage(sprintf(_('Při operaci nastala chyba (HTTP %d): <pre>%s</pre> %s'),
235
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE),
236
                        stripslashes($response), $this->error), 'error');
237
                $this->addStatusMessage($url);
238
            }
239
            if ($response == 'null') {
240
                return;
241
            }
242
243
            return self::object2array(current(json_decode($response)));
244
        }
245
246
        // Parse response
247
        switch ($format) {
248
            case 'json':
249
                $decoded = json_decode($response, true, 10);
250
                if (isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
251
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
252
                } else {
253
                    $this->lastInsertedID = null;
254
                }
255
//                $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...
256
//                $this->addStatusMessage($decodeError);
257
258
                break;
259
            case 'xml':
260
                $decoded = simplexml_load_string($response);
261
                $decoded = self::xml2array($decoded);
262
                break;
263
        }
264
265
        // Get response body root automatically
266
        if (isset($decoded[$this->nameSpace])) {
267
            $decoded = $decoded[$this->nameSpace];
268
        }
269
270
        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...
271
    }
272
273
    /**
274
     * Give you last inserted record ID
275
     * 
276
     * @return int
277
     */
278
    function getLastImportId()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
279
    {
280
        return $this->lastInsertedID;
281
    }
282
283
    /**
284
     * Convert XML to array.
285
     * 
286
     * @param string $xml
287
     *
288
     * @return array
289
     */
290
    public static function xml2array($xml)
291
    {
292
        $arr = [];
293
        foreach ($xml->children() as $r) {
0 ignored issues
show
Bug introduced by
The method children cannot be called on $xml (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
294
            $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...
295
            if (count($r->children()) == 0) {
296
                $arr[$r->getName()] = strval($r);
297
            } else {
298
                $arr[$r->getName()][] = self::xml2array($r);
299
            }
300
        }
301
302
        return $arr;
303
    }
304
305
    /**
306
     * Odpojení od FlexiBee.
307
     */
308
    public function disconnect()
309
    {
310
        if (is_resource($this->curl)) {
311
            curl_close($this->curl);
312
        }
313
    }
314
315
    public function __destruct()
316
    {
317
        $this->disconnect();
318
    }
319
320
    /**
321
     * Načte data z FlexiBee.
322
     *
323
     * @param string $suffix dotaz
324
     */
325
    public function loadFlexiData($suffix = null)
326
    {
327
        $this->setListingData($this->getFlexiData($suffix));
0 ignored issues
show
Bug introduced by
The method setListingData() does not seem to exist on object<FlexiPeeHP\FlexiBee>.

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...
328
    }
329
330
    /**
331
     * Načte řádek dat z FlexiBee
332
     *
333
     * @param int $recordID
334
     * @return array
335
     */
336
    public function getFlexiRow($recordID)
337
    {
338
        $record   = null;
339
        $response = $this->performRequest($this->agenda.'/'.$recordID.'.json');
340
        if (isset($response[$this->agenda])) {
341
            $record = $response[$this->agenda][0];
342
        }
343
        return $record;
344
    }
345
346
    /**
347
     * Načte data z FlexiBee.
348
     *
349
     * @param string $suffix     dotaz
350
     * @param string $conditions Volitelný filtrovací výraz
351
     */
352
    public function getFlexiData($suffix = null, $conditions = null)
353
    {
354
        if (!is_null($conditions)) {
355
            if ($conditions[0] != '/') {
356
                $conditions = '/'.rawurlencode('('.($conditions).')');
357
            }
358
        } else {
359
            $conditions = '';
360
        }
361
        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...
362
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format.'?'.$suffix,
363
                'GET');
364
        } else {
365
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format,
366
                'GET');
367
        }
368
        if (isset($transactions[$this->agenda])) {
369
            $result = $transactions[$this->agenda];
370
        } else {
371
            $result = $transactions;
372
        }
373
        return $result;
374
    }
375
376
    /**
377
     * Načte záznam z FlexiBee.
378
     *
379
     * @param int $id ID záznamu
380
     *
381
     * @return int počet načtených položek
382
     */
383
    public function loadFromFlexiBee($id = null)
384
    {
385
        if (is_null($id)) {
386
            $id = $this->getId();
0 ignored issues
show
Bug introduced by
The method getId() does not seem to exist on object<FlexiPeeHP\FlexiBee>.

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...
387
        }
388
389
        return $this->takeData($this->getFlexiData('/'.$id));
390
    }
391
392
    /**
393
     * Uloží data do FlexiBee.
394
     *
395
     * @param array $data
396
     *
397
     * @return array výsledek
398
     */
399 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...
400
    {
401
        if (is_null($data)) {
402
            $data = $this->getData();
403
        }
404
405
        $jsonizedData = $this->jsonizeData($data);
406
407
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
408
409
        return $this->performRequest($this->agenda.'.json', 'PUT');
410
    }
411
412
    /**
413
     * Převede data do Json formátu pro FlexiBee.
414
     *
415
     * @param array $data
416
     *
417
     * @return string
418
     */
419
    public function jsonizeData($data)
420
    {
421
        $jsonize = [
422
            $this->nameSpace => [
423
                '@version' => $this->protoVersion,
424
                $this->agenda => $data,
425
            ],
426
        ];
427
428
        return json_encode($jsonize);
429
    }
430
431
    /**
432
     * Uloží záznam.
433
     *
434
     * @param array $data
435
     *
436
     * @return array odpověď
437
     */
438 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...
439
    {
440
        if (is_null($data)) {
441
            $data = $this->getData();
442
        }
443
        $jsonizedData = $this->jsonizeData($data);
444
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
445
446
        return $this->performRequest($this->agenda.'.json', 'PUT');
447
    }
448
449
    /**
450
     * Test if given record ID exists in FlexiBee
451
     *
452
     * @param string|int $identifer
453
     */
454
    function idExists($identifer = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
455
    {
456
        if (is_null($identifer)) {
457
            $identifer = $this->getMyKey();
458
        }
459
        $flexiData = $this->getFlexiData(
460
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
461
        return $flexiData;
462
    }
463
464
    /**
465
     * Test if given record exists in FlexiBee
466
     *
467
     * @param array $data
468
     */
469
    function recordExists($data = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
470
    {
471
        if (is_null($data)) {
472
            $data = $this->getData();
473
        }
474
475
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
476
            self::flexiUrl($data));
477
        return $res;
478
    }
479
480
    /**
481
     * Vrací z FlexiBee sloupečky podle podmínek.
482
     *
483
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
484
     * @param array|string     $orderBy     třídit dle
485
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
486
     *                                      sloupečku
487
     * @param int              $limit       maximální počet vrácených záznamů
488
     *
489
     * @return array
490
     */
491
    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...
492
                                       $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...
493
    {
494
495
        if (is_int($conditions)) {
496
            $conditions = [$this->getmyKeyColumn() => $conditions];
497
        }
498
499
        $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...
500
501 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...
502
            $flexiData2 = [];
503
            foreach ($flexiData as $dataID => $data) {
504
                $flexiData2[$data[$indexBy]] = $data;
505
            }
506
            $flexiData = $flexiData2;
507
        }
508
509
        return $flexiData;
510
    }
511
512
    /**
513
     * Vrací z FlexiBee sloupečky podle podmínek.
514
     *
515
     * @param array            $columnsList seznam položek
516
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
517
     * @param array|string     $orderBy     třídit dle
518
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
519
     *                                      sloupečku
520
     * @param int              $limit       maximální počet vrácených záznamů
521
     *
522
     * @return array
523
     */
524
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
525
                                           $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...
526
                                           $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...
527
    {
528
        if (($columnsList != '*') && !count($columnsList)) {
529
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
530
531
            return;
532
        }
533
534
        if (is_int($conditions)) {
535
            $conditions = [$this->getmyKeyColumn() => $conditions];
536
        }
537
538
        if (is_array($columnsList)) {
539
            $columns = implode(',', array_unique($columnsList));
540
        } else {
541
            $columns = $columnsList;
542
        }
543
544
        $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...
545
546 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...
547
            $flexiData2 = [];
548
            foreach ($flexiData as $dataID => $data) {
549
                $flexiData2[$data[$indexBy]] = $data;
550
            }
551
            $flexiData = $flexiData2;
552
        }
553
554
        return $flexiData;
555
    }
556
557
    /**
558
     * Vrací kód záznamu.
559
     *
560
     * @param array $data
561
     * @todo papat i string
562
     *
563
     * @return string
564
     */
565
    public function getKod($data = null, $unique = true)
566
    {
567
        $kod = null;
568
569
        if (is_null($data)) {
570
            $data = $this->getData();
571
        }
572
573
        if (isset($data['kod'])) {
574
            $kod = $data['kod'];
575
        } else {
576
            if (isset($data[$this->nameColumn])) {
577
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
578
                    \Ease\Sand::rip($data[$this->nameColumn]));
579
            } else {
580
                if (isset($data[$this->myKeyColumn])) {
581
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
582
                }
583
            }
584
        }
585
586
        if (strlen($kod) > 18) {
587
            $kodfinal = substr($kod, 0, 18);
588
        } else {
589
            $kodfinal = $kod;
590
        }
591
592
        if ($unique) {
593
            $counter = 0;
594
            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...
595
                foreach ($this->codes as $codesearch) {
596
                    if (!strlen($codesearch)) {
597
                        echo 'Error';
598
                    }
599
                    if (strstr($codesearch, $kodfinal)) {
600
                        $counter++;
601
                    }
602
                }
603
            }
604
            if ($counter) {
605
                $kodfinal = $kodfinal.$counter;
606
            }
607
608
            $this->codes[$kodfinal] = $kod;
609
        }
610
        return strtoupper($kodfinal);
611
    }
612
613
    /**
614
     * Vyhledavani v záznamech objektu FlexiBee.
615
     *
616
     * @param string $what hledaný výraz
617
     *
618
     * @return array pole výsledků
619
     */
620
    public function searchString($what)
621
    {
622
        $results   = [];
623
        $conds     = [];
624
        $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...
625
        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...
626
            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...
627
                == true)) {
628
                if ($keyword == $this->nameColumn) {
629
                    $this->nameColumn = $this->myKeyColumn;
630
                }
631
                continue;
632
            }
633
            switch ($keywordInfo) {
634
                case 'INT':
635 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...
636
                    if (is_numeric($what)) {
637
                        $conds[]   = "($keyword = ".$what.')';
638
                        $columns[] = "$keyword";
639
                    }
640
                    break;
641
                case 'TEXT':
642 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...
643
                    if (is_string($what)) {
644
                        $conds[]   = "( $keyword like '".$what."')";
645
                        $columns[] = "$keyword";
646
                    }
647
                    break;
648
                default:
649
                    break;
650
            }
651
        }
652
653
//        $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...
654
655
        $res = $this->getColumnsFromFlexibee($columns, implode(' or ', $conds));
656
657
        foreach ($res as $result) {
658
            $occurences = '';
659
            foreach ($result as $key => $value) {
660
                if (is_array($value)) {
661
                    continue;
662
                }
663
                if (mb_stristr($value, $what)) {
664
                    $occurences .= '('.$key.': '.$value.')';
665
                }
666
            }
667
            $results[$result[$this->myKeyColumn]] = [$this->nameColumn => $result[$this->nameColumn],
668
                'what' => $occurences];
669
        }
670
671
        return $results;
672
    }
673
674
    /**
675
     * Write Operation Result.
676
     * 
677
     * @param array $resultData
678
     * @param string $url URL
679
     */
680
    public function logResult($resultData, $url = null)
681
    {
682
        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...
683
            $this->logger->addStatusMessage($url);
684
        }
685
686
        if (isset($resultData['results'])) {
687
            $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...
688
            if ($resultData['success'] == 'false') {
689
                $status = 'error';
690
            } else {
691
                $status = 'success';
692
            }
693
            foreach ($resultData['results'] as $result) {
694
                if (isset($result['request-id'])) {
695
                    $rid = $result['request-id'];
696
                } else {
697
                    $rid = '';
698
                }
699
                if (isset($result['errors'])) {
700
                    foreach ($result['errors'] as $error) {
701
                        $this->logger->addStatusMessage($rid.': '.$error['message'],
702
                            $status);
703
                    }
704
                }
705
            }
706
        }
707
        if (is_object($this->logger)) {
708
            $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...
709
        }
710
    }
711
712
    /**
713
     * Generuje fragment url pro filtrování
714
     *
715
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
716
     * @param array $data
717
     * @param string $operator and/or
718
     * @return string
719
     */
720
    static function flexiUrl($data, $operator = 'and')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
721
    {
722
        $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...
723
        $parts    = [];
724
725
        foreach ($data as $column => $value) {
726
            if (is_numeric($data[$column])) {
727
                $parts[$column] = $column.' = '.$data[$column];
728
            } else {
729
                $parts[$column] = $column." = '".$data[$column]."'";
730
            }
731
        }
732
733
        $flexiUrl = implode(' '.$operator.' ', $parts);
734
        return $flexiUrl;
735
    }
736
}