Test Failed
Push — master ( 9cdcc0...4bcdf2 )
by Vítězslav
03:44
created

FlexiBeeRO   D

Complexity

Total Complexity 269

Size/Duplication

Total Lines 1751
Duplicated Lines 3.66 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 64
loc 1751
rs 4
c 0
b 0
f 0
wmc 269
lcom 1
cbo 4

57 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
F setUp() 0 40 16
A curlInit() 0 12 1
A processInit() 0 10 4
C setPrefix() 0 22 11
A setFormat() 0 15 4
A setEvidence() 0 21 3
A getEvidence() 0 4 1
A setCompany() 0 4 1
A getCompany() 0 4 1
A getResponseEvidence() 0 15 3
B object2array() 9 20 6
A objectToID() 9 17 4
A getEvidenceURL() 0 9 3
A updateApiURL() 0 9 2
F performRequest() 0 159 37
C doCurlRequest() 0 39 7
A setAction() 0 10 2
A xml2array() 0 18 4
A disconnect() 0 7 2
A __destruct() 0 4 1
A getFlexiRow() 0 10 2
A extractUrlParams() 0 8 3
D getFlexiData() 0 38 10
A loadFromFlexiBee() 0 14 4
A jsonizeData() 0 16 2
A idExists() 0 10 2
B recordExists() 0 18 6
A getAllFromFlexibee() 0 14 3
C getColumnsFromFlexibee() 0 40 12
D getKod() 0 53 13
C logResult() 0 50 15
A saveDebugFiles() 0 8 1
A setPostFields() 0 4 1
D flexiUrl() 0 32 10
B getRecordID() 0 14 5
A __toString() 0 4 1
A evidenceToClassName() 0 4 1
B getExternalID() 0 19 7
A getGlobalVersion() 0 14 4
A getResponseFormat() 0 9 2
B unifyResponseFormat() 0 28 6
A getColumnsInfo() 12 12 3
A getActionsInfo() 12 12 3
A getRelationsInfo() 0 12 3
A getEvidenceInfo() 11 11 3
A getEvidenceName() 11 11 3
B performAction() 0 37 6
A saveResponseToFile() 0 7 2
A getVazby() 0 10 2
C getFlexiBeeURL() 0 13 9
A setMyKey() 0 6 1
A ignore404() 0 7 2
A sendByMail() 0 8 1
A sendUnsent() 0 5 1
A flexiDateToDateTime() 0 4 1
A downloadInFormat() 0 12 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like FlexiBeeRO often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FlexiBeeRO, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * FlexiPeeHP - Read Only Access to FlexiBee class.
4
 *
5
 * @author     Vítězslav Dvořák <[email protected]>
6
 * @copyright  (C) 2015-2017 Spoje.Net
7
 */
8
9
namespace FlexiPeeHP;
10
11
/**
12
 * Základní třída pro čtení z FlexiBee
13
 *
14
 * @url https://demo.flexibee.eu/devdoc/
15
 */
16
class FlexiBeeRO extends \Ease\Brick
17
{
18
    /**
19
     * Version of FlexiPeeHP library
20
     *
21
     * @var string
22
     */
23
    static public $libVersion = '1.6.4.2';
24
25
    /**
26
     * Availble Formats.
27
     *
28
     * @see https://www.flexibee.eu/api/dokumentace/ref/format-types/
29
     * @var array formats known to flexibee
30
     */
31
    static public $formats = [
32
        'JS' => ['desc' => 'JavaScropt',
33
            'suffix' => 'js', 'content-type' => 'application/javascript', 'import' => false],
34
        'CSS' => ['desc' => 'Kaskádový styl',
35
            'suffix' => 'css', 'content-type' => 'text/css', 'import' => false],
36
        'HTML' => ['desc' => 'HTML stránka pro zobrazení informací na webové stránce.',
37
            'suffix' => 'html', 'content-type' => 'text/html', 'import' => false],
38
        'XML' => ['desc' => 'Strojově čitelná struktura ve formátu XML.', 'suffix' => 'xml',
39
            'content-type' => 'application/xml', 'import' => true],
40
        'JSON' => ['desc' => 'Strojově čitelná struktura ve formátu JSON. ', 'suffix' => 'json',
41
            'content-type' => 'application/json', 'import' => true],
42
        'CSV' => ['desc' => 'Tabulkový výstup do formátu CSV (Column Separated Values).',
43
            'suffix' => 'csv', 'content-type' => 'text/csv', 'import' => true],
44
        'DBF' => ['desc' => 'Databázový výstup ve formátu DBF (dBase).', 'suffix' => 'dbf',
45
            'content-type' => 'application/dbf', 'import' => true],
46
        'XLS' => ['desc' => 'Tabulkový výstup ve formátu Excel.', 'suffix' => 'xls',
47
            'content-type' => 'application/ms-excel', 'import' => true],
48
        'ISDOC' => ['desc' => 'e-faktura ISDOC.', 'suffix' => 'isdoc', 'content-type' => 'application/x-isdoc',
49
            'import' => false],
50
        'ISDOCx' => ['desc' => 'e-faktura ISDOC s PDF přílohou', 'suffix' => 'isdocx',
51
            'content-type' => 'application/x-isdocx',
52
            'import' => false],
53
        'EDI' => ['desc' => 'Elektronická výměna data (EDI) ve formátu INHOUSE.',
54
            'suffix' => 'edi', 'content-type' => 'application/x-edi-inhouse', 'import' => 'objednavka-prijata'],
55
        'PDF' => ['desc' => 'Generování tiskového reportu. Jedná se o stejnou funkci která je dostupná v aplikaci. Export do PDF',
56
            'suffix' => 'pdf', 'content-type' => 'application/pdf', 'import' => false],
57
        'vCard' => ['desc' => 'Výstup adresáře do formátu elektronické vizitky vCard.',
58
            'suffix' => 'vcf', 'content-type' => 'text/vcard', 'import' => false],
59
        'iCalendar' => ['desc' => 'Výstup do kalendáře ve formátu iCalendar. Lze takto exportovat události, ale také třeba splatnosti u přijatých či vydaných faktur.',
60
            'suffix' => 'ical', 'content-type' => 'text/calendar', 'import' => false]
61
    ];
62
63
    /**
64
     * Základní namespace pro komunikaci s FlexiBee.
65
     * Basic namespace for communication with FlexiBee
66
     *
67
     * @var string Jmený prostor datového bloku odpovědi
68
     */
69
    public $nameSpace = 'winstrom';
70
71
    /**
72
     * URL of object data in FlexiBee
73
     * @var string url
74
     */
75
    public $apiURL = null;
76
77
    /**
78
     * Datový blok v poli odpovědi.
79
     * Data block in response field.
80
     *
81
     * @var string
82
     */
83
    public $resultField = 'results';
84
85
    /**
86
     * Verze protokolu použitého pro komunikaci.
87
     * Communication protocol version used.
88
     *
89
     * @var string Verze použitého API
90
     */
91
    public $protoVersion = '1.0';
92
93
    /**
94
     * Evidence užitá objektem.
95
     * Evidence used by object
96
     *
97
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
98
     * @var string
99
     */
100
    public $evidence = null;
101
102
    /**
103
     * Výchozí formát pro komunikaci.
104
     * Default communication format.
105
     *
106
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
107
     *
108
     * @var string json|xml|...
109
     */
110
    public $format = 'json';
111
112
    /**
113
     * Curl Handle.
114
     *
115
     * @var resource
116
     */
117
    public $curl = null;
118
119
    /**
120
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
121
     * @var string
122
     */
123
    public $company = null;
124
125
    /**
126
     * Server[:port]
127
     * @var string
128
     */
129
    public $url = null;
130
131
    /**
132
     * REST API Username
133
     * @var string
134
     */
135
    public $user = null;
136
137
    /**
138
     * REST API Password
139
     * @var string
140
     */
141
    public $password = null;
142
143
    /**
144
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
145
     */
146
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
147
148
    /**
149
     * Default additional request url parameters after question mark
150
     *
151
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
152
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
153
     * @var array
154
     */
155
    public $defaultUrlParams = ['limit' => 0];
156
157
    /**
158
     * Identifikační řetězec.
159
     *
160
     * @var string
161
     */
162
    public $init = null;
163
164
    /**
165
     * Sloupeček s názvem.
166
     *
167
     * @var string
168
     */
169
    public $nameColumn = 'nazev';
170
171
    /**
172
     * Sloupeček obsahující datum vložení záznamu do shopu.
173
     *
174
     * @var string
175
     */
176
    public $myCreateColumn = 'false';
177
178
    /**
179
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
180
     *
181
     * @var string
182
     */
183
    public $myLastModifiedColumn = 'lastUpdate';
184
185
    /**
186
     * Klíčový idendifikátor záznamu.
187
     *
188
     * @var string
189
     */
190
    public $fbKeyColumn = 'id';
191
192
    /**
193
     * Informace o posledním HTTP requestu.
194
     *
195
     * @var *
196
     */
197
    public $info;
198
199
    /**
200
     * Informace o poslední HTTP chybě.
201
     *
202
     * @var string
203
     */
204
    public $lastCurlError = null;
205
206
    /**
207
     * Used codes storage.
208
     *
209
     * @var array
210
     */
211
    public $codes = null;
212
213
    /**
214
     * Last Inserted ID.
215
     *
216
     * @var int
217
     */
218
    public $lastInsertedID = null;
219
220
    /**
221
     * Default Line Prefix.
222
     *
223
     * @var string
224
     */
225
    public $prefix = '/c/';
226
227
    /**
228
     * Raw Content of last curl response
229
     *
230
     * @var string
231
     */
232
    public $lastCurlResponse;
233
234
    /**
235
     * HTTP Response code of last request
236
     *
237
     * @var int
238
     */
239
    public $lastResponseCode = null;
240
241
    /**
242
     * Body data  for next curl POST operation
243
     *
244
     * @var string
245
     */
246
    protected $postFields = null;
247
248
    /**
249
     * Last operation result data or message(s)
250
     *
251
     * @var array
252
     */
253
    public $lastResult = null;
254
255
    /**
256
     * Nuber from  @rowCount
257
     * @var int
258
     */
259
    public $rowCount = null;
260
261
    /**
262
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
263
     * @var string
264
     */
265
    protected $action;
266
267
    /**
268
     * Pole akcí které podporuje ta která evidence
269
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
270
     * @var array
271
     */
272
    public $actionsAvailable = null;
273
274
    /**
275
     * Parmetry pro URL
276
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
277
     * @var array
278
     */
279
    public $urlParams = [
280
        'idUcetniObdobi',
281
        'dry-run',
282
        'fail-on-warning',
283
        'report-name',
284
        'report-lang',
285
        'report-sign',
286
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
287
        'mode',
288
        'limit',
289
        'start',
290
        'order',
291
        'sort',
292
        'add-row-count',
293
        'relations',
294
        'includes',
295
        'use-ext-id',
296
        'use-internal-id',
297
        'stitky-as-ids',
298
        'only-ext-ids',
299
        'no-ext-ids',
300
        'no-ids',
301
        'code-as-id',
302
        'no-http-errors',
303
        'export-settings',
304
        'as-gui',
305
        'code-in-response',
306
        'add-global-version',
307
        'encoding',
308
        'delimeter',
309
        'format',
310
        'auth',
311
        'skupina-stitku',
312
        'dir',
313
        'relations',
314
        'relations',
315
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
316
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
317
        'inDesktopApp' // Note: Undocumented function (html only)
318
    ];
319
320
    /**
321
     * Save 404 results to log ?
322
     * @var boolean
323
     */
324
    protected $ignoreNotFound = false;
325
326
    /**
327
     * Class for read only interaction with FlexiBee.
328
     *
329
     * @param mixed $init default record id or initial data
330
     * @param array $options Connection settings override
331
     */
332
    public function __construct($init = null, $options = [])
333
    {
334
        $this->init = $init;
335
336
        parent::__construct();
337
        $this->setUp($options);
338
        $this->curlInit();
339
        if (!is_null($init)) {
340
            $this->processInit($init);
341
        }
342
    }
343
344
    /**
345
     * SetUp Object to be ready for connect
346
     *
347
     * @param array $options Object Options (company,url,user,password,evidence,
348
     *                                       prefix,debug)
349
     */
350
    public function setUp($options = [])
351
    {
352
        if (isset($options['company'])) {
353
            $this->company = $options['company'];
354
        } else {
355
            if (is_null($this->company) && defined('FLEXIBEE_COMPANY')) {
356
                $this->company = constant('FLEXIBEE_COMPANY');
357
            }
358
        }
359
        if (isset($options['url'])) {
360
            $this->url = $options['url'];
361
        } else {
362
            if (is_null($this->url) && defined('FLEXIBEE_URL')) {
363
                $this->url = constant('FLEXIBEE_URL');
364
            }
365
        }
366
        if (isset($options['user'])) {
367
            $this->user = $options['user'];
368
        } else {
369
            if (is_null($this->user) && defined('FLEXIBEE_LOGIN')) {
370
                $this->user = constant('FLEXIBEE_LOGIN');
371
            }
372
        }
373
        if (isset($options['password'])) {
374
            $this->password = $options['password'];
375
        } else {
376
            if (is_null($this->password) && defined('FLEXIBEE_PASSWORD')) {
377
                $this->password = constant('FLEXIBEE_PASSWORD');
378
            }
379
        }
380
        if (isset($options['evidence'])) {
381
            $this->setEvidence($options['evidence']);
382
        }
383
        if (isset($options['prefix'])) {
384
            $this->setPrefix($options['prefix']);
385
        }
386
        if (isset($options['debug'])) {
387
            $this->debug = $options['debug'];
388
        }
389
    }
390
391
    /**
392
     * Inicializace CURL
393
     */
394
    public function curlInit()
395
    {
396
        $this->curl = \curl_init(); // create curl resource
397
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
398
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
399
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
400
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
401
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
402
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
403
        curl_setopt($this->curl, CURLOPT_USERPWD,
404
            $this->user.':'.$this->password); // set username and password
405
    }
406
407
    /**
408
     * Zinicializuje objekt dle daných dat
409
     *
410
     * @param mixed $init
411
     */
412
    public function processInit($init)
413
    {
414
        if (is_integer($init)) {
415
            $this->loadFromFlexiBee($init);
416
        } elseif (is_array($init)) {
417
            $this->takeData($init);
418
        } elseif (strstr($init, 'code:')) {
419
            $this->loadFromFlexiBee($init);
420
        }
421
    }
422
423
    /**
424
     * Set URL prefix
425
     *
426
     * @param string $prefix
427
     */
428
    public function setPrefix($prefix)
429
    {
430
        switch ($prefix) {
431
            case 'a': //Access
432
            case 'c': //Company
433
            case 'u': //User
434
            case 'g': //License Groups
435
            case 'admin':
436
            case 'status':
437
            case 'login-logout':
438
                $this->prefix = '/'.$prefix.'/';
439
                break;
440
            case null:
441
            case '':
442
            case '/':
443
                $this->prefix = '';
444
                break;
445
            default:
446
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
447
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
448
        }
449
    }
450
451
    /**
452
     * Set communication format.
453
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
454
     *
455
     * @param string $format
456
     * @return boolen format is availble
457
     */
458
    public function setFormat($format)
459
    {
460
        $result       = true;
461
        if ($this->debug === true) {
462
            $evidence = lcfirst(FlexiBeeRO::evidenceToClassName($this->getEvidence()));
463
            if (array_key_exists($format, array_flip(Formats::$$evidence)) === false) {
464
                $result = false;
465
            }
466
        }
467
        if ($result === true) {
468
            $this->format = $format;
469
            $this->updateApiURL();
470
        }
471
        return $result;
472
    }
473
474
    /**
475
     * Nastaví Evidenci pro Komunikaci.
476
     * Set evidence for communication
477
     *
478
     * @param string $evidence evidence pathName to use
479
     * @return boolean evidence switching status
480
     */
481
    public function setEvidence($evidence)
482
    {
483
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result 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...
484
        switch ($this->prefix) {
485
            case '/c/':
486
                if (array_key_exists($evidence, EvidenceList::$name)) {
487
                    $this->evidence = $evidence;
488
                    $result         = true;
489
                } else {
490
                    throw new \Exception(sprintf('Try to set unsupported evidence %s',
491
                        $evidence));
492
                }
493
                break;
494
            default:
495
                $this->evidence = $evidence;
496
                $result         = true;
497
                break;
498
        }
499
        $this->updateApiURL();
500
        return $result;
501
    }
502
503
    /**
504
     * Vrací právě používanou evidenci pro komunikaci
505
     * Obtain current used evidence
506
     *
507
     * @return string
508
     */
509
    public function getEvidence()
510
    {
511
        return $this->evidence;
512
    }
513
514
    /**
515
     * Set used company.
516
     * Nastaví Firmu.
517
     *
518
     * @param string $company
519
     */
520
    public function setCompany($company)
521
    {
522
        $this->company = $company;
523
    }
524
525
    /**
526
     * Obtain company now used
527
     * Vrací právě používanou firmu
528
     *
529
     * @return string
530
     */
531
    public function getCompany()
532
    {
533
        return $this->company;
534
    }
535
536
    /**
537
     * Vrací název evidence použité v odpovědích z FlexiBee
538
     *
539
     * @return string
540
     */
541
    public function getResponseEvidence()
542
    {
543
        switch ($this->evidence) {
544
            case 'c':
545
                $evidence = 'company';
546
                break;
547
            case 'evidence-list':
548
                $evidence = 'evidences';
549
                break;
550
            default:
551
                $evidence = $this->getEvidence();
552
                break;
553
        }
554
        return $evidence;
555
    }
556
557
    /**
558
     * Převede rekurzivně Objekt na pole.
559
     *
560
     * @param object|array $object
561
     *
562
     * @return array
563
     */
564
    public static function object2array($object)
565
    {
566
        $result = null;
567
        if (is_object($object)) {
568
            $objectData = get_object_vars($object);
569
            if (is_array($objectData) && count($objectData)) {
570
                $result = array_map('self::object2array', $objectData);
571
            }
572 View Code Duplication
        } else {
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...
573
            if (is_array($object)) {
574
                foreach ($object as $item => $value) {
575
                    $result[$item] = self::object2array($value);
576
                }
577
            } else {
578
                $result = $object;
579
            }
580
        }
581
582
        return $result;
583
    }
584
585
    /**
586
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
587
     *
588
     * @param object|array $object
589
     *
590
     * @return array
591
     */
592
    public static function objectToID($object)
593
    {
594
        $result = null;
595
        if (is_object($object)) {
596
            $result = $object->__toString();
597 View Code Duplication
        } else {
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...
598
            if (is_array($object)) {
599
                foreach ($object as $item => $value) {
600
                    $result[$item] = self::objectToID($value);
601
                }
602
            } else { //String
603
                $result = $object;
604
            }
605
        }
606
607
        return $result;
608
    }
609
610
    /**
611
     * Return basic URL for used Evidence
612
     *
613
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
614
     * @param string $urlSuffix
615
     */
616
    public function getEvidenceURL($urlSuffix = null)
617
    {
618
        if (is_null($urlSuffix)) {
619
            $urlSuffix = $this->getEvidence();
620
        } elseif ($urlSuffix[0] == ';') {
621
            $urlSuffix = $this->getEvidence().$urlSuffix;
622
        }
623
        return $this->url.$this->prefix.$this->company.'/'.$urlSuffix;
624
    }
625
626
    /**
627
     * Update $this->apiURL
628
     */
629
    public function updateApiURL()
630
    {
631
        $this->apiURL = $this->getEvidenceURL();
632
        $id           = $this->__toString();
633
        if (!is_null($id)) {
634
            $this->apiURL .= '/'.urlencode($id);
635
        }
636
        $this->apiURL .= '.'.$this->format;
637
    }
638
639
    /**
640
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
641
     *
642
     * @param string $urlSuffix část URL za identifikátorem firmy.
643
     * @param string $method    HTTP/REST metoda
644
     * @param string $format    Requested format
645
     * @return array|boolean Výsledek operace
646
     */
647
    public function performRequest($urlSuffix = null, $method = 'GET',
648
                                   $format = null)
649
    {
650
        $response       = null;
651
        $result         = null;
0 ignored issues
show
Unused Code introduced by
$result 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...
652
        $this->rowCount = null;
653
654
        if (preg_match('/^http/', $urlSuffix)) {
655
            $url = $urlSuffix;
656
        } else {
657
            $url = $this->getEvidenceURL($urlSuffix);
658
        }
659
660
        $responseCode = $this->doCurlRequest($url, $method, $format);
661
662
        if (is_null($format)) {
663
            $format = $this->format;
664
        }
665
666
        switch ($responseCode) {
667
            case 200:
668
            case 201:
669
// Parse response
670
                $responseDecoded = [];
0 ignored issues
show
Unused Code introduced by
$responseDecoded 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...
671
672
                switch ($format) {
673
                    case 'json':
674
                        $responseDecoded = json_decode($this->lastCurlResponse,
675
                            true, 10);
676
                        if (($method == 'PUT') && isset($responseDecoded[$this->nameSpace][$this->resultField][0]['id'])) {
677
                            $this->lastInsertedID = $responseDecoded[$this->nameSpace][$this->resultField][0]['id'];
678
                            $this->setMyKey($this->lastInsertedID);
679
                            $this->apiURL         = $this->getEvidenceURL().'/'.$this->lastInsertedID;
680
                        } else {
681
                            $this->lastInsertedID = null;
682
                            if (isset($responseDecoded[$this->nameSpace]['@rowCount'])) {
683
                                $this->rowCount = (int) $responseDecoded[$this->nameSpace]['@rowCount'];
684
                            }
685
                        }
686
                        $decodeError = json_last_error_msg();
687
                        if ($decodeError != 'No error') {
688
                            $this->addStatusMessage($decodeError, 'error');
689
                        }
690
                        break;
691
                    case 'xml':
692
                        if (strlen($this->lastCurlResponse)) {
693
                            $responseDecoded = self::xml2array($this->lastCurlResponse);
694
                        } else {
695
                            $responseDecoded = null;
696
                        }
697
                        break;
698
                    case 'txt':
699
                    default:
700
                        $responseDecoded = $this->lastCurlResponse;
701
                        break;
702
                }
703
704
705
                $response         = $this->lastResult = $this->unifyResponseFormat($responseDecoded);
706
707
                break;
708
709
            default: //Some goes wrong
710
                $this->lastCurlError = curl_error($this->curl);
711
                switch ($format) {
712
                    case 'json':
713
                        $response = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/',
714
                            function ($match) {
715
                            return mb_convert_encoding(pack('H*', $match[1]),
716
                                'UTF-8', 'UCS-2BE');
717
                        }, $this->lastCurlResponse);
718
                        $response = (json_encode(json_decode($response, true, 10),
719
                                JSON_PRETTY_PRINT));
720
                        break;
721
                    case 'xml':
722
                        if (strlen($this->lastCurlResponse)) {
723
                            $response = self::xml2array($this->lastCurlResponse);
724
                        }
725
                        break;
726
                    case 'txt':
727
                    default:
728
                        $response = $this->lastCurlResponse;
729
                        break;
730
                }
731
732
                if (is_array($response)) {
733
                    $result = urldecode(http_build_query($response));
0 ignored issues
show
Unused Code introduced by
$result 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...
734
                } elseif (strlen($response) && ($response != 'null')) {
735
                    $decoded = json_decode($response);
736
                    if (is_array($decoded)) {
737
                        $result = urldecode(http_build_query(self::object2array(current($decoded))));
0 ignored issues
show
Unused Code introduced by
$result 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...
738
                    }
739
                } else {
740
                    $result = null;
0 ignored issues
show
Unused Code introduced by
$result 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...
741
                }
742
743
                if ($response == 'null') {
744
                    if ($this->lastResponseCode == 200) {
745
                        $response = true;
746
                    } else {
747
                        $response = null;
748
                    }
749
                } else {
750
                    if (is_string($response)) {
751
                        $decoded = json_decode($response);
752
                        if (is_array($decoded)) {
753
                            $response = self::object2array(current($decoded));
754
                        }
755
                    }
756
                }
757
758
                if (is_array($response) && ($this->lastResponseCode == 400)) {
759
                    $this->logResult($response, $url);
760
                } else {
761
                    $responseDecoded = json_decode($this->lastCurlResponse,
762
                        true, 10);
763
764
                    if (is_array($responseDecoded) && array_key_exists('results',
765
                            $responseDecoded[$this->nameSpace])) {
766
                        $errors = $responseDecoded[$this->nameSpace]['results'][0]['errors'];
767
                    } else {
768
                        $errors = null;
769
                    }
770
771
                    if (!is_array($errors)) {
772
                        $errors[]['message'] = '';
773
                    }
774
775
                    if (( $responseCode == 404 ) && ($this->ignoreNotFound === true)) {
776
                        break;
777
                    }
778
                    foreach ($errors as $error) {
779
                        $this->addStatusMessage(sprintf('Error (HTTP %d): %s %s',
780
                                $responseCode,
781
                                implode('; ', $error)
782
                                , $this->lastCurlError), 'error');
783
                    }
784
785
                    $this->addStatusMessage($url, 'info');
786
                    if (!empty($this->postFields) && $this->debug === true) {
787
                        if (is_array($this->postFields)) {
788
                            $this->addStatusMessage(urldecode(http_build_query($this->postFields)),
789
                                'debug');
790
                        } else {
791
                            $this->addStatusMessage(urldecode($this->postFields),
792
                                'debug');
793
                        }
794
                    }
795
                }
796
797
                break;
798
        }
799
800
        if ($this->debug === true) {
801
            $this->saveDebugFiles();
802
        }
803
804
        return $response;
805
    }
806
807
    /**
808
     * Vykonej HTTP požadavek
809
     *
810
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
811
     * @param string $url    URL požadavku
812
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
813
     * @param string $format požadovaný formát komunikace
814
     * @return int HTTP Response CODE
815
     */
816
    public function doCurlRequest($url, $method, $format = null)
817
    {
818
        if (is_null($format)) {
819
            $format = $this->format;
820
        }
821
        curl_setopt($this->curl, CURLOPT_URL, $url);
822
// Nastavení samotné operace
823
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
824
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
825
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
826
827
        $httpHeaders = $this->defaultHttpHeaders;
828
829
        $formats = $this->reindexArrayBy(self::$formats, 'suffix');
830
831
        if (!isset($httpHeaders['Accept'])) {
832
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
833
        }
834
        if (!isset($httpHeaders['Content-Type'])) {
835
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
836
        }
837
        $httpHeadersFinal = [];
838
        foreach ($httpHeaders as $key => $value) {
839
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
840
                $value .= ' v'.self::$libVersion;
841
            }
842
            $httpHeadersFinal[] = $key.': '.$value;
843
        }
844
845
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
846
847
// Proveď samotnou operaci
848
        $this->lastCurlResponse = curl_exec($this->curl);
849
850
        $this->info = curl_getinfo($this->curl);
851
852
        $this->lastResponseCode = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
853
        return $this->lastResponseCode;
854
    }
855
856
    /**
857
     * Nastaví druh prováděné akce.
858
     *
859
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
860
     * @param string $action
861
     * @return boolean
862
     */
863
    public function setAction($action)
864
    {
865
        $result           = false;
866
        $actionsAvailable = $this->getActionsInfo();
867
        if (array_key_exists($action, $actionsAvailable)) {
868
            $this->action = $action;
869
            $result       = true;
870
        }
871
        return $result;
872
    }
873
874
    /**
875
     * Convert XML to array.
876
     *
877
     * @param string $xml
878
     *
879
     * @return array
880
     */
881
    public static function xml2array($xml)
882
    {
883
        $arr = [];
884
885
        if (is_string($xml)) {
886
            $xml = simplexml_load_string($xml);
887
        }
888
889
        foreach ($xml->children() as $r) {
890
            if (count($r->children()) == 0) {
891
                $arr[$r->getName()] = strval($r);
892
            } else {
893
                $arr[$r->getName()][] = self::xml2array($r);
894
            }
895
        }
896
897
        return $arr;
898
    }
899
900
    /**
901
     * Odpojení od FlexiBee.
902
     */
903
    public function disconnect()
904
    {
905
        if (is_resource($this->curl)) {
906
            curl_close($this->curl);
907
        }
908
        $this->curl = null;
909
    }
910
911
    /**
912
     * Disconnect CURL befere pass away
913
     */
914
    public function __destruct()
915
    {
916
        $this->disconnect();
917
    }
918
919
    /**
920
     * Načte řádek dat z FlexiBee.
921
     *
922
     * @param int $recordID id požadovaného záznamu
923
     *
924
     * @return array
925
     */
926
    public function getFlexiRow($recordID)
927
    {
928
        $record   = null;
929
        $response = $this->performRequest($this->evidence.'/'.$recordID.'.json');
930
        if (isset($response[$this->evidence])) {
931
            $record = $response[$this->evidence][0];
932
        }
933
934
        return $record;
935
    }
936
937
    /**
938
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
939
     *
940
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
941
     * @param array $conditions pole podmínek   - rendrují se do ()
942
     * @param array $urlParams  pole parametrů  - rendrují za ?
943
     */
944
    public function extractUrlParams(&$conditions, &$urlParams)
945
    {
946
        foreach ($this->urlParams as $urlParam) {
947
            if (isset($conditions[$urlParam])) {
948
                \Ease\Sand::divDataArray($conditions, $urlParams, $urlParam);
949
            }
950
        }
951
    }
952
953
    /**
954
     * Načte data z FlexiBee.
955
     *
956
     * @param string $suffix     dotaz
957
     * @param string|array $conditions Volitelný filtrovací výraz
958
     */
959
    public function getFlexiData($suffix = null, $conditions = null)
960
    {
961
        $urlParams = $this->defaultUrlParams;
962
        if (!is_null($conditions)) {
963
            if (is_array($conditions)) {
964
                $this->extractUrlParams($conditions, $urlParams);
965
                $conditions = $this->flexiUrl($conditions);
966
            }
967
968
            if (strlen($conditions) && ($conditions[0] != '/')) {
969
                $conditions = '/'.rawurlencode('('.($conditions).')');
970
            }
971
        } else {
972
            $conditions = '';
973
        }
974
975
        if (preg_match('/^http/', $suffix)) {
976
            $transactions = $this->performRequest($suffix, 'GET');
977
        } else {
978
            if (strlen($suffix)) {
979
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.$suffix.'&'.http_build_query($urlParams),
980
                    'GET');
981
            } else {
982
                $transactions = $this->performRequest($this->evidence.$conditions.'.'.$this->format.'?'.http_build_query($urlParams),
983
                    'GET');
984
            }
985
        }
986
        if (isset($transactions[$this->evidence])) {
987
            $result = $transactions[$this->evidence];
988
            if ((count($result) == 1) && (count(current($result)) == 0 )) {
989
                $result = null; // Response is empty Array
990
            }
991
        } else {
992
            $result = $transactions;
993
        }
994
995
        return $result;
996
    }
997
998
    /**
999
     * Načte záznam z FlexiBee.
1000
     *
1001
     * @param int $id ID záznamu
1002
     *
1003
     * @return int počet načtených položek
1004
     */
1005
    public function loadFromFlexiBee($id = null)
1006
    {
1007
        $data = [];
1008
        if (is_null($id)) {
1009
            $id = $this->getMyKey();
1010
        }
1011
1012
        $flexidata    = $this->getFlexiData(null, '/'.$id);
1013
        $this->apiURL = $this->info['url'];
1014
        if (is_array($flexidata) && (count($flexidata) == 1)) {
1015
            $data = current($flexidata);
1016
        }
1017
        return $this->takeData($data);
1018
    }
1019
1020
    /**
1021
     * Převede data do Json formátu pro FlexiBee.
1022
     * Convert data to FlexiBee like Json format
1023
     *
1024
     * @param array $data
1025
     *
1026
     * @return string
1027
     */
1028
    public function jsonizeData($data)
1029
    {
1030
        $jsonize = [
1031
            $this->nameSpace => [
1032
                '@version' => $this->protoVersion,
1033
                $this->evidence => $this->objectToID($data),
1034
            ],
1035
        ];
1036
1037
        if (!is_null($this->action)) {
1038
            $jsonize[$this->nameSpace][$this->evidence.'@action'] = $this->action;
1039
            $this->action                                         = null;
1040
        }
1041
1042
        return json_encode($jsonize);
1043
    }
1044
1045
    /**
1046
     * Test if given record ID exists in FlexiBee.
1047
     *
1048
     * @param string|int $identifer
1049
     */
1050
    public function idExists($identifer = null)
1051
    {
1052
        if (is_null($identifer)) {
1053
            $identifer = $this->getMyKey();
1054
        }
1055
        $flexiData = $this->getFlexiData(
1056
            'detail=custom:'.$this->getmyKeyColumn(), $identifer);
1057
1058
        return $flexiData;
1059
    }
1060
1061
    /**
1062
     * Test if given record exists in FlexiBee.
1063
     *
1064
     * @param array $data
1065
     * @return boolean Record presence status
1066
     */
1067
    public function recordExists($data = null)
1068
    {
1069
1070
        if (is_null($data)) {
1071
            $data = $this->getData();
1072
        }
1073
1074
        $res = $this->getColumnsFromFlexibee([$this->myKeyColumn],
1075
            self::flexiUrl($data));
0 ignored issues
show
Documentation introduced by
self::flexiUrl($data) is of type string, but the function expects a array|null.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1076
1077
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1078
            || !count($res[0])) {
1079
            $found = false;
1080
        } else {
1081
            $found = true;
1082
        }
1083
        return $found;
1084
    }
1085
1086
    /**
1087
     * Vrací z FlexiBee sloupečky podle podmínek.
1088
     *
1089
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1090
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1091
     *                                     sloupečku
1092
     * @return array
1093
     */
1094
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1095
    {
1096
        if (is_int($conditions)) {
1097
            $conditions = [$this->getmyKeyColumn() => $conditions];
1098
        }
1099
1100
        $flexiData = $this->getFlexiData('', $conditions);
1101
1102
        if (!is_null($indexBy)) {
1103
            $flexiData = $this->reindexArrayBy($flexiData);
1104
        }
1105
1106
        return $flexiData;
1107
    }
1108
1109
    /**
1110
     * Vrací z FlexiBee sloupečky podle podmínek.
1111
     *
1112
     * @param string[] $columnsList seznam položek
1113
     * @param array    $conditions  pole podmínek nebo ID záznamu
1114
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1115
     *
1116
     * @return array
1117
     */
1118
    public function getColumnsFromFlexibee($columnsList, $conditions = null,
1119
                                           $indexBy = null)
1120
    {
1121
        if (is_int($conditions)) {
1122
            $conditions = [$this->getmyKeyColumn() => $conditions];
1123
        }
1124
1125
        if ($columnsList != '*') {
1126
            if (is_array($columnsList)) {
1127
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1128
                        $columnsList)) {
1129
                    $columnsList[] = $indexBy;
1130
                }
1131
                $columns = implode(',', array_unique($columnsList));
1132
            } else {
1133
                $columns = $columnsList;
1134
            }
1135
            $detail = 'custom:'.$columns;
0 ignored issues
show
Unused Code introduced by
$detail 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...
1136
        }
1137
        switch ($columnsList) {
1138
            case 'id':
1139
                $detail = 'id';
1140
                break;
1141
            case 'summary':
1142
                $detail = 'summary';
1143
                break;
1144
            case 'full':
1145
            default:
1146
                $detail = 'full';
1147
                break;
1148
        }
1149
1150
        $flexiData = $this->getFlexiData('detail='.$detail, $conditions);
1151
1152
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1153
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1154
        }
1155
1156
        return $flexiData;
1157
    }
1158
1159
    /**
1160
     * Vrací kód záznamu.
1161
     *
1162
     * @param mixed $data
1163
     *
1164
     * @return string
1165
     */
1166
    public function getKod($data = null, $unique = true)
1167
    {
1168
        $kod = null;
1169
1170
        if (is_null($data)) {
1171
            $data = $this->getData();
1172
        }
1173
1174
        if (is_string($data)) {
1175
            $data = [$this->nameColumn => $data];
1176
        }
1177
1178
        if (isset($data['kod'])) {
1179
            $kod = $data['kod'];
1180
        } else {
1181
            if (isset($data[$this->nameColumn])) {
1182
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1183
                    \Ease\Sand::rip($data[$this->nameColumn]));
1184
            } else {
1185
                if (isset($data[$this->myKeyColumn])) {
1186
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1187
                }
1188
            }
1189
        }
1190
1191
        if (!strlen($kod)) {
1192
            $kod = 'NOTSET';
1193
        }
1194
1195
        if (strlen($kod) > 18) {
1196
            $kodfinal = strtoupper(substr($kod, 0, 18));
1197
        } else {
1198
            $kodfinal = strtoupper($kod);
1199
        }
1200
1201
        if ($unique) {
1202
            $counter = 0;
1203
            if (count($this->codes)) {
1204
                foreach ($this->codes as $codesearch => $keystring) {
1205
                    if (strstr($codesearch, $kodfinal)) {
1206
                        ++$counter;
1207
                    }
1208
                }
1209
            }
1210
            if ($counter) {
1211
                $kodfinal = $kodfinal.$counter;
1212
            }
1213
1214
            $this->codes[$kodfinal] = $kod;
1215
        }
1216
1217
        return $kodfinal;
1218
    }
1219
1220
    /**
1221
     * Write Operation Result.
1222
     *
1223
     * @param array  $resultData
1224
     * @param string $url        URL
1225
     * @return boolean Log save success
1226
     */
1227
    public function logResult($resultData = null, $url = null)
1228
    {
1229
        $logResult = false;
1230
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1231
            if (isset($resultData['message'])) {
1232
                $this->addStatusMessage($resultData['message'], 'warning');
1233
            }
1234
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1235
                'warning');
1236
            unset($url);
1237
        }
1238
        if (is_null($resultData)) {
1239
            $resultData = $this->lastResult;
1240
        }
1241
        if (isset($url)) {
1242
            $this->logger->addStatusMessage(urldecode($url));
1243
        }
1244
1245
        if (isset($resultData['results'])) {
1246
            $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...
1247
            if ($resultData['success'] == 'false') {
1248
                $status = 'error';
1249
            } else {
1250
                $status = 'success';
1251
            }
1252
            foreach ($resultData['results'] as $result) {
1253
                if (isset($result['request-id'])) {
1254
                    $rid = $result['request-id'];
1255
                } else {
1256
                    $rid = '';
1257
                }
1258
                if (isset($result['errors'])) {
1259
                    foreach ($result['errors'] as $error) {
1260
                        $message = $error['message'];
1261
                        if (isset($error['for'])) {
1262
                            $message .= ' for: '.$error['for'];
1263
                        }
1264
                        if (isset($error['value'])) {
1265
                            $message .= ' value:'.$error['value'];
1266
                        }
1267
                        if (isset($error['code'])) {
1268
                            $message .= ' code:'.$error['code'];
1269
                        }
1270
                        $this->addStatusMessage($rid.': '.$message, $status);
1271
                    }
1272
                }
1273
            }
1274
        }
1275
        return $logResult;
1276
    }
1277
1278
    /**
1279
     * Save RAW Curl Request & Response to files in Temp directory
1280
     */
1281
    public function saveDebugFiles()
1282
    {
1283
        $tmpdir = sys_get_temp_dir();
1284
        file_put_contents($tmpdir.'/request-'.$this->evidence.'-'.microtime().'.'.$this->format,
1285
            $this->postFields);
1286
        file_put_contents($tmpdir.'/response-'.$this->evidence.'-'.microtime().'.'.$this->format,
1287
            $this->lastCurlResponse);
1288
    }
1289
1290
    /**
1291
     * Připraví data pro odeslání do FlexiBee
1292
     *
1293
     * @param string $data
1294
     */
1295
    public function setPostFields($data)
1296
    {
1297
        $this->postFields = $data;
1298
    }
1299
1300
    /**
1301
     * Generuje fragment url pro filtrování.
1302
     *
1303
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1304
     *
1305
     * @param array  $data
1306
     * @param string $joiner default and/or
1307
     * @param string $defop  default operator
1308
     *
1309
     * @return string
1310
     */
1311
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1312
    {
1313
        $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...
1314
        $parts    = [];
1315
1316
        foreach ($data as $column => $value) {
1317
            if (is_integer($data[$column]) || is_float($data[$column])) {
1318
                $parts[$column] = $column.' eq \''.$data[$column].'\'';
1319
            } elseif (is_bool($data[$column])) {
1320
                $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1321
            } elseif (is_null($data[$column])) {
1322
                $parts[$column] = $column." is null";
1323
            } else {
1324
                switch ($value) {
1325
                    case '!null':
1326
                        $parts[$column] = $column." is not null";
1327
                        break;
1328
                    case 'is empty':
1329
                    case 'is not empty':
1330
                        $parts[$column] = $column.' '.$value;
1331
                        break;
1332
                    default:
1333
                        $parts[$column] = $column." $defop '".$data[$column]."'";
1334
                        break;
1335
                }
1336
            }
1337
        }
1338
1339
        $flexiUrl = implode(' '.$joiner.' ', $parts);
1340
1341
        return $flexiUrl;
1342
    }
1343
1344
    /**
1345
     * Obtain record/object identificator code: or id:
1346
     * Vrací identifikátor objektu code: nebo id:
1347
     *
1348
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1349
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1350
     */
1351
    public function getRecordID()
1352
    {
1353
        $myCode = $this->getDataValue('kod');
1354
        if ($myCode) {
1355
            $id = 'code:'.$myCode;
1356
        } else {
1357
            $id = $this->getDataValue('id');
1358
            if (($this->debug === true) && is_null($id)) {
1359
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1360
                    'warning');
1361
            }
1362
        }
1363
        return is_numeric($id) ? intval($id) : strval($id);
1364
    }
1365
1366
    /**
1367
     * Obtain record/object identificator code: or id:
1368
     * Vrací identifikátor objektu code: nebo id:
1369
     *
1370
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1371
     * @return string indentifikátor záznamu reprezentovaného objektem
1372
     */
1373
    public function __toString()
1374
    {
1375
        return strval($this->getRecordID());
1376
    }
1377
1378
    /**
1379
     * Gives you FlexiPeeHP class name for Given Evidence
1380
     *
1381
     * @param string $evidence
1382
     * @return string Class name
1383
     */
1384
    static public function evidenceToClassName($evidence)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
1385
    {
1386
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1387
    }
1388
1389
    /**
1390
     * Vrací hodnotu daného externího ID
1391
     *
1392
     * @param string $want Which ? If empty,you obtain the first one.
1393
     * @return string
1394
     */
1395
    public function getExternalID($want = null)
1396
    {
1397
        $extid = null;
1398
        $ids   = $this->getDataValue('external-ids');
1399
        if (is_null($want)) {
1400
            if (count($ids)) {
1401
                $extid = current($ids);
1402
            }
1403
        } else {
1404
            if (!is_null($ids) && is_array($ids)) {
1405
                foreach ($ids as $id) {
1406
                    if (strstr($id, 'ext:'.$want)) {
1407
                        $extid = str_replace('ext:'.$want.':', '', $id);
1408
                    }
1409
                }
1410
            }
1411
        }
1412
        return $extid;
1413
    }
1414
1415
    /**
1416
     * Obtain actual GlobalVersion
1417
     * Vrací aktuální globální verzi změn
1418
     *
1419
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1420
     * @return type
1421
     */
1422
    public function getGlobalVersion()
1423
    {
1424
        $globalVersion = null;
1425
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1426
            $this->getFlexiData(null,
1427
                ['add-global-version' => 'true', 'limit' => 1]);
1428
        }
1429
1430
        if (isset($this->lastResult['@globalVersion'])) {
1431
            $globalVersion = intval($this->lastResult['@globalVersion']);
1432
        }
1433
1434
        return $globalVersion;
1435
    }
1436
1437
    /**
1438
     * Obtain content type of last response
1439
     *
1440
     * @return string
1441
     */
1442
    public function getResponseFormat()
1443
    {
1444
        if (isset($this->info['content_type'])) {
1445
            $responseFormat = $this->info['content_type'];
1446
        } else {
1447
            $responseFormat = null;
1448
        }
1449
        return $responseFormat;
1450
    }
1451
1452
    /**
1453
     * Return the same response format for one and multiplete results
1454
     *
1455
     * @param array $responseRaw
1456
     * @return array
1457
     */
1458
    public function unifyResponseFormat($responseRaw)
1459
    {
1460
        $response = $responseRaw;
1461
        $evidence = $this->getResponseEvidence();
1462
        if (is_array($responseRaw)) {
1463
// Get response body root automatically
1464
            if (array_key_exists($this->nameSpace, $responseRaw)) { //Unifi response format
1465
                $responseBody = $responseRaw[$this->nameSpace];
1466
                if (array_key_exists($evidence, $responseBody)) {
1467
                    $evidenceContent = $responseBody[$evidence];
1468
                    if (array_key_exists(0, $evidenceContent)) {
1469
                        $response[$evidence] = $evidenceContent; //Multiplete Results
1470
                    } else {
1471
                        $response[$evidence][0] = $evidenceContent; //One result
1472
                    }
1473
                } else {
1474
                    if (isset($responseBody['priloha'])) {
1475
                        $response = $responseBody['priloha'];
1476
                    } else {
1477
                        $response = $responseBody;
1478
                    }
1479
                }
1480
            } else {
1481
                $response = $responseRaw;
1482
            }
1483
        }
1484
        return $response;
1485
    }
1486
1487
    /**
1488
     * Obtain structure for current (or given) evidence
1489
     *
1490
     * @param string $evidence
1491
     * @return array Evidence structure
1492
     */
1493 View Code Duplication
    public function getColumnsInfo($evidence = 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...
1494
    {
1495
        $columnsInfo = null;
1496
        if (is_null($evidence)) {
1497
            $evidence = $this->getEvidence();
1498
        }
1499
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1500
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1501
            $columnsInfo = Properties::$$propsName;
1502
        }
1503
        return $columnsInfo;
1504
    }
1505
1506
    /**
1507
     * Obtain actions for current (or given) evidence
1508
     *
1509
     * @param string $evidence
1510
     * @return array Evidence structure
1511
     */
1512 View Code Duplication
    public function getActionsInfo($evidence = 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...
1513
    {
1514
        $actionsInfo = null;
1515
        if (is_null($evidence)) {
1516
            $evidence = $this->getEvidence();
1517
        }
1518
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1519
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1520
            $actionsInfo = Actions::$$propsName;
1521
        }
1522
        return $actionsInfo;
1523
    }
1524
1525
    /**
1526
     * Obtain relations for current (or given) evidence
1527
     *
1528
     * @param string $evidence
1529
     * @return array Evidence structure
1530
     */
1531
    public function getRelationsInfo($evidence = null)
1532
    {
1533
        $relationsInfo = null;
1534
        if (is_null($evidence)) {
1535
            $evidence = $this->getEvidence();
1536
        }
1537
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1538
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1539
            $relationsInfo = Relations::$$propsName;
1540
        }
1541
        return $relationsInfo;
1542
    }
1543
1544
    /**
1545
     * Obtain info for current (or given) evidence
1546
     *
1547
     * @param string $evidence
1548
     * @return array Evidence info
1549
     */
1550 View Code Duplication
    public function getEvidenceInfo($evidence = 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...
1551
    {
1552
        $evidencesInfo = null;
1553
        if (is_null($evidence)) {
1554
            $evidence = $this->getEvidence();
1555
        }
1556
        if (isset(EvidenceList::$evidences[$evidence])) {
1557
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1558
        }
1559
        return $evidencesInfo;
1560
    }
1561
1562
    /**
1563
     * Obtain name for current (or given) evidence path
1564
     *
1565
     * @param string $evidence Evidence Path
1566
     * @return array Evidence info
1567
     */
1568 View Code Duplication
    public function getEvidenceName($evidence = 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...
1569
    {
1570
        $evidenceName = null;
1571
        if (is_null($evidence)) {
1572
            $evidence = $this->getEvidence();
1573
        }
1574
        if (isset(EvidenceList::$name[$evidence])) {
1575
            $evidenceName = EvidenceList::$name[$evidence];
1576
        }
1577
        return $evidenceName;
1578
    }
1579
1580
    /**
1581
     * Perform given action (if availble) on current evidence/record
1582
     * @url https://demo.flexibee.eu/devdoc/actions
1583
     *
1584
     * @param string $action one of evidence actions
1585
     * @param string $method ext|int External method call operation in URL.
1586
     *                               Internal add the @action element to request body
1587
     */
1588
    public function performAction($action, $method = 'ext')
1589
    {
1590
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result 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...
1591
1592
        $actionsAvailble = $this->getActionsInfo();
1593
1594
        if (is_array($actionsAvailble) && array_key_exists($action,
1595
                $actionsAvailble)) {
1596
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1597
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1598
                case 'ONLY_WITH_INSTANCE': //Add instance
1599
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1600
                    break;
1601
1602
                default:
1603
                    $urlSuffix = '/'.$action;
1604
                    break;
1605
            }
1606
1607
            switch ($method) {
1608
                case 'int':
1609
                    $this->setAction($action);
1610
                    $this->setPostFields($this->jsonizeData($this->getData()));
1611
                    $result = $this->performRequest(null, 'POST');
1612
                    break;
1613
1614
                default:
1615
                    $result = $this->performRequest($urlSuffix, 'GET');
1616
                    break;
1617
            }
1618
        } else {
1619
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1620
                $action, $this->getEvidence()));
1621
        }
1622
1623
        return $result;
1624
    }
1625
1626
    /**
1627
     * Save current object to file
1628
     *
1629
     * @param string $destfile path to file
1630
     */
1631
    public function saveResponseToFile($destfile)
1632
    {
1633
        if (strlen($this->lastCurlResponse)) {
1634
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1635
        }
1636
        file_put_contents($destfile, $this->lastCurlResponse);
1637
    }
1638
1639
    /**
1640
     * Obtain established relations listing
1641
     *
1642
     * @return array Null or Relations
1643
     */
1644
    public function getVazby()
1645
    {
1646
        $vazby = $this->getDataValue('vazby');
1647
        if (is_null($vazby)) {
1648
            $vazby = $this->getColumnsFromFlexibee('*',
0 ignored issues
show
Documentation introduced by
'*' is of type string, but the function expects a array<integer,string>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1649
                ['relations' => 'vazby', 'id' => $this->getRecordID()]);
1650
            $vazby = $vazby[0]['vazby'];
1651
        }
1652
        return $vazby;
1653
    }
1654
1655
    /**
1656
     * Gives You URL for Current Record in FlexiBee web interface
1657
     *
1658
     * @return string url
1659
     */
1660
    public function getFlexiBeeURL()
1661
    {
1662
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1663
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1664
                : '';
1665
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1666
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1667
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1668
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1669
        $pass       = ($user || $pass) ? "$pass@" : '';
1670
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1671
        return $scheme.$user.$pass.$host.$port.$path;
1672
    }
1673
1674
    /**
1675
     * Set Record Key
1676
     *
1677
     * @param int|string $myKeyValue
1678
     * @return boolean
1679
     */
1680
    public function setMyKey($myKeyValue)
1681
    {
1682
        $res = parent::setMyKey($myKeyValue);
1683
        $this->updateApiURL();
1684
        return $res;
1685
    }
1686
1687
    /**
1688
     * Set or get ignore not found pages flag
1689
     *
1690
     * @param boolean $ignore set flag to
1691
     *
1692
     * @return boolean get flag state
1693
     */
1694
    public function ignore404($ignore = null)
1695
    {
1696
        if (!is_null($ignore)) {
1697
            $this->ignoreNotFound;
1698
        }
1699
        return $this->ignoreNotFound;
1700
    }
1701
1702
    /**
1703
     * Send Document by mail
1704
     *
1705
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1706
     *
1707
     * @param string $to
1708
     * @param string $subject
1709
     * @param string $body Email Text
1710
     *
1711
     * @return int http response code
1712
     */
1713
    public function sendByMail($to, $subject, $body, $cc = null)
1714
    {
1715
        $this->setPostFields($body);
1716
        $result = $this->doCurlRequest($this->getEvidenceURL().'/'.
1717
            urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1718
            , 'PUT', 'xml');
1719
        return $result == 200;
1720
    }
1721
1722
    /**
1723
     * Send all unsent Invoices by mail
1724
     *
1725
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1726
     * @return int http response code
1727
     */
1728
    public function sendUnsent()
1729
    {
1730
        return $this->doCurlRequest($this->getEvidenceURL().'/automaticky-odeslat-neodeslane',
1731
                'PUT', 'xml');
1732
    }
1733
1734
    /**
1735
     * FlexiBee date to PHP DateTime
1736
     *
1737
     * @param string $flexidate
1738
     * @return \DateTime
1739
     */
1740
    public static function flexiDateToDateTime($flexidate)
1741
    {
1742
        return \DateTime::createFromFormat('Y-m-jO', $flexidate);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression \DateTime::createFromFor...('Y-m-jO', $flexidate); of type DateTime|false adds false to the return on line 1742 which is incompatible with the return type documented by FlexiPeeHP\FlexiBeeRO::flexiDateToDateTime of type DateTime. It seems like you forgot to handle an error condition.
Loading history...
1743
    }
1744
1745
    /**
1746
     * Uloží dokument v daném formátu do složky v systému souborů
1747
     * Save document in given format to directory in filesystem
1748
     *
1749
     * @param string $format  pdf/csv/xml/json/ ...
1750
     * @param string $destDir where to put file (prefix)
1751
     * 
1752
     * @return string|null filename downloaded or none
1753
     */
1754
    public function downloadInFormat($format, $destDir = './')
1755
    {
1756
        $fileOnDisk = null;
1757
        if ($this->setFormat($format)) {
1758
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1759
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1760
                    $this->lastCurlResponse) !== false)) {
1761
                $fileOnDisk = $downloadTo;
1762
            }
1763
        }
1764
        return $fileOnDisk;
1765
    }
1766
}
1767