Completed
Push — master ( 72193e...4c91b5 )
by Vítězslav
03:18
created

FlexiBee::__destruct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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->curlInit();
153
    }
154
155
    public function curlInit()
156
    {
157
        $this->curl = \curl_init(); // create curl resource
158
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
159
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
160
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
161
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
162
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
163
        curl_setopt($this->curl, CURLOPT_VERBOSE, true); // For debugging
164
        curl_setopt($this->curl, CURLOPT_USERPWD,
165
            $this->user.':'.$this->password); // set username and password
166
    }
167
168
    /**
169
     * Nastaví Agendu pro Komunikaci.
170
     *
171
     * @param string $agenda
172
     */
173
    public function setAgenda($agenda)
174
    {
175
        $this->agenda = $agenda;
176
    }
177
178
    /**
179
     * Převede rekurzivně Objekt na pole.
180
     *
181
     * @param object $data
182
     *
183
     * @return array
184
     */
185
    public static function object2array($data)
186
    {
187
        if (!is_object($data) && !is_array($data)) {
188
            return $data;
189
        }
190
        if (is_object($data)) {
191
            $data = get_object_vars($data);
192
        }
193
194
        return array_map('self::object2array', $data);
195
    }
196
197
    /**
198
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
199
     *
200
     * @param string $urlSuffix část URL za identifikátorem firmy.
201
     * @param string $method HTTP/REST metoda
202
     * @param string $format Requested format
203
     */
204
    public function performRequest($urlSuffix = null, $method = 'GET',
205
                                   $format = null)
206
    {
207
        if (is_null($format)) {
208
            $format = $this->format;
209
        }
210
        if (is_null($urlSuffix)) {
211
            $urlSuffix = $this->agenda.'.'.$format;
212
        }
213
        $url = $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
214
        curl_setopt($this->curl, CURLOPT_URL, $url);
215
// Nastavení samotné operace
216
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method);
217
218
// Proveď samotnou operaci
219
        $response = curl_exec($this->curl);
220
221
        $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...
222
223
        $responseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
224
225
        if ($responseCode != 200 && $responseCode != 201) {
226
            $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...
227
            $response    = (json_encode(json_decode($response, true, 10),
228
                    JSON_PRETTY_PRINT));
229
230
            $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
231
                function ($match) {
232
                return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8',
233
                    'UCS-2BE');
234
            }, $response);
235
236
            if ($responseCode == 400) {
237
                $this->logResult(self::object2array(current(json_decode($response))));
238
            } else {
239
                $this->addStatusMessage(sprintf(_('Při operaci nastala chyba (HTTP %d): <pre>%s</pre> %s'),
240
                        curl_getinfo($this->curl, CURLINFO_HTTP_CODE),
241
                        stripslashes($response), $this->error), 'error');
242
                $this->addStatusMessage($url);
243
            }
244
            if ($response == 'null') {
245
                return;
246
            }
247
248
            return self::object2array(current(json_decode($response)));
249
        }
250
251
        // Parse response
252
        switch ($format) {
253
            case 'json':
254
                $decoded = json_decode($response, true, 10);
255
                if (isset($decoded[$this->nameSpace][$this->resultField][0]['id'])) {
256
                    $this->lastInsertedID = $decoded[$this->nameSpace][$this->resultField][0]['id'];
257
                } else {
258
                    $this->lastInsertedID = null;
259
                }
260
//                $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...
261
//                $this->addStatusMessage($decodeError);
262
263
                break;
264
            case 'xml':
265
                $decoded = simplexml_load_string($response);
266
                $decoded = self::xml2array($decoded);
267
                break;
268
        }
269
270
        // Get response body root automatically
271
        if (isset($decoded[$this->nameSpace])) {
272
            $decoded = $decoded[$this->nameSpace];
273
        }
274
275
        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...
276
    }
277
278
    /**
279
     * Give you last inserted record ID
280
     * 
281
     * @return int
282
     */
283
    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...
284
    {
285
        return $this->lastInsertedID;
286
    }
287
288
    /**
289
     * Convert XML to array.
290
     * 
291
     * @param string $xml
292
     *
293
     * @return array
294
     */
295
    public static function xml2array($xml)
296
    {
297
        $arr = [];
298
        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...
299
            $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...
300
            if (count($r->children()) == 0) {
301
                $arr[$r->getName()] = strval($r);
302
            } else {
303
                $arr[$r->getName()][] = self::xml2array($r);
304
            }
305
        }
306
307
        return $arr;
308
    }
309
310
    /**
311
     * Odpojení od FlexiBee.
312
     */
313
    public function disconnect()
314
    {
315
        if (is_resource($this->curl)) {
316
            curl_close($this->curl);
317
        }
318
    }
319
320
    public function __destruct()
321
    {
322
        $this->disconnect();
323
    }
324
325
    /**
326
     * Načte data z FlexiBee.
327
     *
328
     * @param string $suffix dotaz
329
     */
330
    public function loadFlexiData($suffix = null)
331
    {
332
        $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...
333
    }
334
335
    /**
336
     * Načte řádek dat z FlexiBee
337
     *
338
     * @param int $recordID
339
     * @return array
340
     */
341
    public function getFlexiRow($recordID)
342
    {
343
        $record   = null;
344
        $response = $this->performRequest($this->agenda.'/'.$recordID.'.json');
345
        if (isset($response[$this->agenda])) {
346
            $record = $response[$this->agenda][0];
347
        }
348
        return $record;
349
    }
350
351
    /**
352
     * Načte data z FlexiBee.
353
     *
354
     * @param string $suffix     dotaz
355
     * @param string $conditions Volitelný filtrovací výraz
356
     */
357
    public function getFlexiData($suffix = null, $conditions = null)
358
    {
359
        if (!is_null($conditions)) {
360
            if ($conditions[0] != '/') {
361
                $conditions = '/'.rawurlencode('('.($conditions).')');
362
            }
363
        } else {
364
            $conditions = '';
365
        }
366
        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...
367
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format.'?'.$suffix,
368
                'GET');
369
        } else {
370
            $transactions = $this->performRequest($this->agenda.$conditions.'.'.$this->format,
371
                'GET');
372
        }
373
        if (isset($transactions[$this->agenda])) {
374
            $result = $transactions[$this->agenda];
375
        } else {
376
            $result = $transactions;
377
        }
378
        return $result;
379
    }
380
381
    /**
382
     * Načte záznam z FlexiBee.
383
     *
384
     * @param int $id ID záznamu
385
     *
386
     * @return int počet načtených položek
387
     */
388
    public function loadFromFlexiBee($id = null)
389
    {
390
        if (is_null($id)) {
391
            $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...
392
        }
393
394
        return $this->takeData($this->getFlexiData('/'.$id));
395
    }
396
397
    /**
398
     * Uloží data do FlexiBee.
399
     *
400
     * @param array $data
401
     *
402
     * @return array výsledek
403
     */
404 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...
405
    {
406
        if (is_null($data)) {
407
            $data = $this->getData();
408
        }
409
410
        $jsonizedData = $this->jsonizeData($data);
411
412
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
413
414
        return $this->performRequest($this->agenda.'.json', 'PUT');
415
    }
416
417
    /**
418
     * Převede data do Json formátu pro FlexiBee.
419
     *
420
     * @param array $data
421
     *
422
     * @return string
423
     */
424
    public function jsonizeData($data)
425
    {
426
        $jsonize = [
427
            $this->nameSpace => [
428
                '@version' => $this->protoVersion,
429
                $this->agenda => $data,
430
            ],
431
        ];
432
433
        return json_encode($jsonize);
434
    }
435
436
    /**
437
     * Uloží záznam.
438
     *
439
     * @param array $data
440
     *
441
     * @return array odpověď
442
     */
443 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...
444
    {
445
        if (is_null($data)) {
446
            $data = $this->getData();
447
        }
448
        $jsonizedData = $this->jsonizeData($data);
449
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $jsonizedData);
450
451
        return $this->performRequest($this->agenda.'.json', 'PUT');
452
    }
453
454
    /**
455
     * Test if given record ID exists in FlexiBee
456
     *
457
     * @param string|int $identifer
458
     */
459
    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...
460
    {
461
        if (is_null($identifer)) {
462
            $identifer = $this->getMyKey();
463
        }
464
        $flexiData = $this->getFlexiData(
465
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
466
        return $flexiData;
467
    }
468
469
    /**
470
     * Test if given record exists in FlexiBee
471
     *
472
     * @param array $data
473
     */
474
    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...
475
    {
476
        if (is_null($data)) {
477
            $data = $this->getData();
478
        }
479
480
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
481
            self::flexiUrl($data));
482
        return $res;
483
    }
484
485
    /**
486
     * Vrací z FlexiBee sloupečky podle podmínek.
487
     *
488
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
489
     * @param array|string     $orderBy     třídit dle
490
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
491
     *                                      sloupečku
492
     * @param int              $limit       maximální počet vrácených záznamů
493
     *
494
     * @return array
495
     */
496
    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...
497
                                       $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...
498
    {
499
500
        if (is_int($conditions)) {
501
            $conditions = [$this->getmyKeyColumn() => $conditions];
502
        }
503
504
        $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...
505
506 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...
507
            $flexiData2 = [];
508
            foreach ($flexiData as $dataID => $data) {
509
                $flexiData2[$data[$indexBy]] = $data;
510
            }
511
            $flexiData = $flexiData2;
512
        }
513
514
        return $flexiData;
515
    }
516
517
    /**
518
     * Vrací z FlexiBee sloupečky podle podmínek.
519
     *
520
     * @param array            $columnsList seznam položek
521
     * @param array|int|string $conditions  pole podmínek nebo ID záznamu
522
     * @param array|string     $orderBy     třídit dle
523
     * @param string           $indexBy     klice vysledku naplnit hodnotou ze
524
     *                                      sloupečku
525
     * @param int              $limit       maximální počet vrácených záznamů
526
     *
527
     * @return array
528
     */
529
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
530
                                           $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...
531
                                           $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...
532
    {
533
        if (($columnsList != '*') && !count($columnsList)) {
534
            $this->error('getColumnsFromFlexiBee: Missing ColumnList');
535
536
            return;
537
        }
538
539
        if (is_int($conditions)) {
540
            $conditions = [$this->getmyKeyColumn() => $conditions];
541
        }
542
543
        if (is_array($columnsList)) {
544
            $columns = implode(',', array_unique($columnsList));
545
        } else {
546
            $columns = $columnsList;
547
        }
548
549
        $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...
550
551 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...
552
            $flexiData2 = [];
553
            foreach ($flexiData as $dataID => $data) {
554
                $flexiData2[$data[$indexBy]] = $data;
555
            }
556
            $flexiData = $flexiData2;
557
        }
558
559
        return $flexiData;
560
    }
561
562
    /**
563
     * Vrací kód záznamu.
564
     *
565
     * @param array $data
566
     * @todo papat i string
567
     *
568
     * @return string
569
     */
570
    public function getKod($data = null, $unique = true)
571
    {
572
        $kod = null;
573
574
        if (is_null($data)) {
575
            $data = $this->getData();
576
        }
577
578
        if (isset($data['kod'])) {
579
            $kod = $data['kod'];
580
        } else {
581
            if (isset($data[$this->nameColumn])) {
582
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
583
                    \Ease\Sand::rip($data[$this->nameColumn]));
584
            } else {
585
                if (isset($data[$this->myKeyColumn])) {
586
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
587
                }
588
            }
589
        }
590
591
        if (strlen($kod) > 18) {
592
            $kodfinal = substr($kod, 0, 18);
593
        } else {
594
            $kodfinal = $kod;
595
        }
596
597
        if ($unique) {
598
            $counter = 0;
599
            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...
600
                foreach ($this->codes as $codesearch) {
601
                    if (!strlen($codesearch)) {
602
                        echo 'Error';
603
                    }
604
                    if (strstr($codesearch, $kodfinal)) {
605
                        $counter++;
606
                    }
607
                }
608
            }
609
            if ($counter) {
610
                $kodfinal = $kodfinal.$counter;
611
            }
612
613
            $this->codes[$kodfinal] = $kod;
614
        }
615
        return strtoupper($kodfinal);
616
    }
617
618
    /**
619
     * Vyhledavani v záznamech objektu FlexiBee.
620
     *
621
     * @param string $what hledaný výraz
622
     *
623
     * @return array pole výsledků
624
     */
625
    public function searchString($what)
626
    {
627
        $results   = [];
628
        $conds     = [];
629
        $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...
630
        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...
631
            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...
632
                == true)) {
633
                if ($keyword == $this->nameColumn) {
634
                    $this->nameColumn = $this->myKeyColumn;
635
                }
636
                continue;
637
            }
638
            switch ($keywordInfo) {
639
                case 'INT':
640 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...
641
                    if (is_numeric($what)) {
642
                        $conds[]   = "($keyword = ".$what.')';
643
                        $columns[] = "$keyword";
644
                    }
645
                    break;
646
                case 'TEXT':
647 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...
648
                    if (is_string($what)) {
649
                        $conds[]   = "( $keyword like '".$what."')";
650
                        $columns[] = "$keyword";
651
                    }
652
                    break;
653
                default:
654
                    break;
655
            }
656
        }
657
658
//        $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...
659
660
        $res = $this->getColumnsFromFlexibee($columns, implode(' or ', $conds));
661
662
        foreach ($res as $result) {
663
            $occurences = '';
664
            foreach ($result as $key => $value) {
665
                if (is_array($value)) {
666
                    continue;
667
                }
668
                if (mb_stristr($value, $what)) {
669
                    $occurences .= '('.$key.': '.$value.')';
670
                }
671
            }
672
            $results[$result[$this->myKeyColumn]] = [$this->nameColumn => $result[$this->nameColumn],
673
                'what' => $occurences];
674
        }
675
676
        return $results;
677
    }
678
679
    /**
680
     * Write Operation Result.
681
     * 
682
     * @param array $resultData
683
     * @param string $url URL
684
     */
685
    public function logResult($resultData, $url = null)
686
    {
687
        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...
688
            $this->logger->addStatusMessage($url);
689
        }
690
691
        if (isset($resultData['results'])) {
692
            $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...
693
            if ($resultData['success'] == 'false') {
694
                $status = 'error';
695
            } else {
696
                $status = 'success';
697
            }
698
            foreach ($resultData['results'] as $result) {
699
                if (isset($result['request-id'])) {
700
                    $rid = $result['request-id'];
701
                } else {
702
                    $rid = '';
703
                }
704
                if (isset($result['errors'])) {
705
                    foreach ($result['errors'] as $error) {
706
                        $this->logger->addStatusMessage($rid.': '.$error['message'],
707
                            $status);
708
                    }
709
                }
710
            }
711
        }
712
        if (is_object($this->logger)) {
713
            $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...
714
        }
715
    }
716
717
    /**
718
     * Generuje fragment url pro filtrování
719
     *
720
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
721
     * @param array $data
722
     * @param string $operator and/or
723
     * @return string
724
     */
725
    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...
726
    {
727
        $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...
728
        $parts    = [];
729
730
        foreach ($data as $column => $value) {
731
            if (is_numeric($data[$column])) {
732
                $parts[$column] = $column.' = '.$data[$column];
733
            } else {
734
                $parts[$column] = $column." = '".$data[$column]."'";
735
            }
736
        }
737
738
        $flexiUrl = implode(' '.$operator.' ', $parts);
739
        return $flexiUrl;
740
    }
741
}