Test Failed
Push — master ( 730ebc...389a66 )
by Vítězslav
06:37
created

FlexiBeeRO   D

Complexity

Total Complexity 291

Size/Duplication

Total Lines 1912
Duplicated Lines 2.77 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 70.62%

Importance

Changes 0
Metric Value
dl 53
loc 1912
ccs 601
cts 851
cp 0.7062
rs 4.4102
c 0
b 0
f 0
wmc 291
lcom 1
cbo 6

68 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A setUp() 0 16 3
B setupProperty() 0 10 5
A curlInit() 0 12 1
B processInit() 0 13 5
C setPrefix() 0 21 11
B setFormat() 0 15 6
A setEvidence() 0 20 3
A getEvidence() 0 4 1
A setCompany() 0 4 1
A getCompany() 0 4 1
A getResponseEvidence() 0 15 3
B object2array() 0 20 6
A objectToID() 0 17 4
A getEvidenceURL() 0 9 2
B evidenceUrlWithSuffix() 0 12 5
A updateApiURL() 0 9 2
B rawResponseToArray() 0 26 6
A performRequest() 0 18 3
C parseResponse() 0 39 11
A parseError() 0 11 3
C doCurlRequest() 0 51 10
A setAction() 0 11 3
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
C getFlexiData() 0 53 16
B loadFromFlexiBee() 0 16 5
A jsonizeData() 7 20 3
A idExists() 0 11 2
B recordExists() 0 18 6
A getAllFromFlexibee() 0 14 3
D getColumnsFromFlexibee() 0 38 10
D getKod() 0 53 13
C logResult() 0 49 15
A saveDebugFiles() 0 9 1
A setPostFields() 0 4 1
C flexiUrl() 0 36 12
B getRecordID() 0 14 5
A __toString() 0 4 1
A evidenceToClassName() 0 4 1
A getFirstRecordID() 0 10 2
B getExternalID() 0 19 7
A getGlobalVersion() 0 14 4
A getResponseFormat() 0 9 2
B unifyResponseFormat() 0 25 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 35 6
A saveResponseToFile() 0 7 2
A getVazby() 0 15 4
C getFlexiBeeURL() 0 13 9
A setMyKey() 0 6 1
A ignore404() 0 7 2
A sendByMail() 0 7 1
A sendUnsent() 0 5 1
A flexiDateToDateTime() 0 4 1
A getInFormat() 0 11 4
A downloadInFormat() 0 12 4
C error500Reporter() 0 66 14
A code() 0 4 1
A uncode() 0 4 1
A __wakeup() 0 5 1

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
    public static $libVersion = '1.6.4.2';
24
25
    /**
26
     * Základní namespace pro komunikaci s FlexiBee.
27
     * Basic namespace for communication with FlexiBee
28
     *
29
     * @var string Jmený prostor datového bloku odpovědi
30
     */
31
    public $nameSpace = 'winstrom';
32
33
    /**
34
     * URL of object data in FlexiBee
35
     * @var string url
36
     */
37
    public $apiURL = null;
38
39
    /**
40
     * Datový blok v poli odpovědi.
41
     * Data block in response field.
42
     *
43
     * @var string
44
     */
45
    public $resultField = 'results';
46
47
    /**
48
     * Verze protokolu použitého pro komunikaci.
49
     * Communication protocol version used.
50
     *
51
     * @var string Verze použitého API
52
     */
53
    public $protoVersion = '1.0';
54
55
    /**
56
     * Evidence užitá objektem.
57
     * Evidence used by object
58
     *
59
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
60
     * @var string
61
     */
62
    public $evidence = null;
63
64
    /**
65
     * Výchozí formát pro komunikaci.
66
     * Default communication format.
67
     *
68
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
69
     *
70
     * @var string json|xml|...
71
     */
72
    public $format = 'json';
73
74
    /**
75
     * formát příchozí odpovědi
76
     * response format
77
     *
78
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
79
     *
80
     * @var string json|xml|...
81
     */
82
    public $responseFormat = 'json';
83
84
    /**
85
     * Curl Handle.
86
     *
87
     * @var resource
88
     */
89
    public $curl = null;
90
91
    /**
92
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
93
     * @var string
94
     */
95
    public $company = null;
96
97
    /**
98
     * Server[:port]
99
     * @var string
100
     */
101
    public $url = null;
102
103
    /**
104
     * REST API Username
105
     * @var string
106
     */
107
    public $user = null;
108
109
    /**
110
     * REST API Password
111
     * @var string
112
     */
113
    public $password = null;
114
115
    /**
116
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
117
     */
118
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
119
120
    /**
121
     * Default additional request url parameters after question mark
122
     *
123
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
124
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
125
     * @var array
126
     */
127
    public $defaultUrlParams = ['limit' => 0];
128
129
    /**
130
     * Identifikační řetězec.
131
     *
132
     * @var string
133
     */
134
    public $init = null;
135
136
    /**
137
     * Sloupeček s názvem.
138
     *
139
     * @var string
140
     */
141
    public $nameColumn = 'nazev';
142
143
    /**
144
     * Sloupeček obsahující datum vložení záznamu do shopu.
145
     *
146
     * @var string
147
     */
148
    public $myCreateColumn = 'false';
149
150
    /**
151
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
152
     *
153
     * @var string
154
     */
155
    public $myLastModifiedColumn = 'lastUpdate';
156
157
    /**
158
     * Klíčový idendifikátor záznamu.
159
     *
160
     * @var string
161
     */
162
    public $fbKeyColumn = 'id';
163
164
    /**
165
     * Informace o posledním HTTP requestu.
166
     *
167
     * @var *
168
     */
169
    public $curlInfo;
170
171
    /**
172
     * Informace o poslední HTTP chybě.
173
     *
174
     * @var string
175
     */
176
    public $lastCurlError = null;
177
178
    /**
179
     * Used codes storage.
180
     *
181
     * @var array
182
     */
183
    public $codes = null;
184
185
    /**
186
     * Last Inserted ID.
187
     *
188
     * @var int
189
     */
190
    public $lastInsertedID = null;
191
192
    /**
193
     * Default Line Prefix.
194
     *
195
     * @var string
196
     */
197
    public $prefix = '/c/';
198
199
    /**
200
     * Raw Content of last curl response
201
     *
202
     * @var string
203
     */
204
    public $lastCurlResponse;
205
206
    /**
207
     * HTTP Response code of last request
208
     *
209
     * @var int
210
     */
211
    public $lastResponseCode = null;
212
213
    /**
214
     * Body data  for next curl POST operation
215
     *
216
     * @var string
217
     */
218
    protected $postFields = null;
219
220
    /**
221
     * Last operation result data or message(s)
222
     *
223
     * @var array
224
     */
225
    public $lastResult = null;
226
227
    /**
228
     * Nuber from  @rowCount
229
     * @var int
230
     */
231
    public $rowCount = null;
232
233
    /**
234
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
235
     * @var string filter query
236
     */
237
    public $filter;
238
239
    /**
240
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
241
     * @var string
242
     */
243
    protected $action;
244
245
    /**
246
     * Pole akcí které podporuje ta která evidence
247
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
248
     * @var array
249
     */
250
    public $actionsAvailable = null;
251
252
    /**
253
     * Parmetry pro URL
254
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
255
     * @var array
256
     */
257
    public $urlParams = [
258
        'idUcetniObdobi',
259
        'dry-run',
260
        'fail-on-warning',
261
        'report-name',
262
        'report-lang',
263
        'report-sign',
264
        'detail', //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
265
        'mode',
266
        'limit',
267
        'start',
268
        'order',
269
        'sort',
270
        'add-row-count',
271
        'relations',
272
        'includes',
273
        'use-ext-id',
274
        'use-internal-id',
275
        'stitky-as-ids',
276
        'only-ext-ids',
277
        'no-ext-ids',
278
        'no-ids',
279
        'code-as-id',
280
        'no-http-errors',
281
        'export-settings',
282
        'as-gui',
283
        'code-in-response',
284
        'add-global-version',
285
        'encoding',
286
        'delimeter',
287
        'format',
288
        'auth',
289
        'skupina-stitku',
290
        'dir',
291
        'relations',
292
        'relations',
293
        'xpath', // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
294
        'dry-run', // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
295
        'inDesktopApp' // Note: Undocumented function (html only)
296
    ];
297
298
    /**
299
     * Save 404 results to log ?
300
     * @var boolean
301
     */
302
    protected $ignoreNotFound = false;
303
304
    /**
305
     * Array of errors caused by last request
306
     * @var array
307
     */
308
    private $errors = [];
309
310
    /**
311
     * List of Error500 reports sent
312
     * @var array
313
     */
314
    private $reports = [];
315
316
    /**
317
     * Send Error500 Report to
318
     * @var string email address
319
     */
320
    public $reportRecipient = '[email protected]';
321
322
    /**
323
     * Class for read only interaction with FlexiBee.
324
     *
325
     * @param mixed $init default record id or initial data
326
     * @param array $options Connection settings override
327
     */
328 24
    public function __construct($init = null, $options = [])
329
    {
330 24
        $this->init = $init;
331
332 24
        parent::__construct();
333 24
        $this->setUp($options);
334 24
        $this->curlInit();
335 24
        if (!empty($init)) {
336 22
            $this->processInit($init);
337 22
        }
338 24
    }
339
340
    /**
341
     * SetUp Object to be ready for connect
342
     *
343
     * @param array $options Object Options (company,url,user,password,evidence,
344
     *                                       prefix,defaultUrlParams,debug)
345
     */
346 47
    public function setUp($options = [])
347
    {
348 47
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
349 47
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
350 47
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
351 47
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
352 47
        if (isset($options['evidence'])) {
353 45
            $this->setEvidence($options['evidence']);
354 45
        }
355 47
        $this->setupProperty($options, 'defaultUrlParams');
356 47
        if (isset($options['prefix'])) {
357 45
            $this->setPrefix($options['prefix']);
358 45
        }
359 47
        $this->setupProperty($options, 'debug');
360 47
        $this->updateApiURL();
361 47
    }
362
363
    /**
364
     * Set up one of properties
365
     *
366
     * @param array  $options  array of given properties
367
     * @param string $name     name of property to process
368
     * @param string $constant load default property value from constant
369
     */
370 24
    public function setupProperty($options, $name, $constant = null)
371
    {
372 24
        if (isset($options[$name])) {
373 22
            $this->$name = $options[$name];
374 22
        } else {
375 24
            if (is_null($this->$name) && !empty($constant) && defined($constant)) {
376 24
                $this->$name = constant($constant);
377 24
            }
378
        }
379 24
    }
380
381
    /**
382
     * Inicializace CURL
383
     */
384 70
    public function curlInit()
385
    {
386 70
        $this->curl = \curl_init(); // create curl resource
387 70
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
388 70
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
389 70
        curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
390 70
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
391 70
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
392 70
        curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
393 70
        curl_setopt($this->curl, CURLOPT_USERPWD,
394 70
            $this->user.':'.$this->password); // set username and password
395 70
    }
396
397
    /**
398
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
399
     *
400
     *  * 234                              - interní číslo záznamu k načtení
401
     *  * code:LOPATA                      - kód záznamu
402
     *  * BAGR                             - kód záznamu ka načtení
403
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
404
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
405
     *
406
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
407
     */
408 44
    public function processInit($init)
409
    {
410 44
        if (is_integer($init)) {
411 42
            $this->loadFromFlexiBee($init);
412 44
        } elseif (is_array($init)) {
413 22
            $this->takeData($init);
414 22
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
415
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->getEvidenceURL($init)
0 ignored issues
show
Unused Code introduced by
The call to FlexiBeeRO::getEvidenceURL() has too many arguments starting with $init.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

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

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...
1092
1093
        if (!count($res) || (isset($res['success']) && ($res['success'] == 'false'))
1094
            || !count($res[0])) {
1095
            $found = false;
1096
        } else {
1097
            $found = true;
1098
        }
1099
        return $found;
1100
    }
1101
1102
    /**
1103
     * Vrací z FlexiBee sloupečky podle podmínek.
1104
     *
1105
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1106
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1107
     *                                     sloupečku
1108
     * @return array
1109
     */
1110
    public function getAllFromFlexibee($conditions = null, $indexBy = null)
1111
    {
1112
        if (is_int($conditions)) {
1113
            $conditions = [$this->getmyKeyColumn() => $conditions];
1114
        }
1115
1116
        $flexiData = $this->getFlexiData('', $conditions);
1117
1118
        if (!is_null($indexBy)) {
1119
            $flexiData = $this->reindexArrayBy($flexiData);
1120
        }
1121
1122
        return $flexiData;
1123
    }
1124
1125
    /**
1126
     * Vrací z FlexiBee sloupečky podle podmínek.
1127
     *
1128 23
     * @param string[] $columnsList seznam položek
1129
     * @param array    $conditions  pole podmínek nebo ID záznamu
1130
     * @param string   $indexBy     Sloupeček podle kterého indexovat záznamy
1131 23
     *
1132 23
     * @return array
1133 23
     */
1134
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1135 23
                                           $indexBy = null)
1136 23
    {
1137 23
        $detail = 'full';
1138 23
        switch (gettype($columnsList)) {
1139 23
            case 'integer': //Record ID
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1140 23
                $conditions = [$this->getmyKeyColumn() => $conditions];
1141 23
            case 'array': //Few Conditions
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1142 23
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1143
                        $columnsList)) {
1144 23
                    $columnsList[] = $indexBy;
1145
                }
1146
                $columns = implode(',', array_unique($columnsList));
1147 23
                $detail  = 'custom:'.$columns;
1148
            default:
1149
                switch ($columnsList) {
1150 23
                    case 'id':
1151 23
                        $detail = 'id';
1152 23
                        break;
1153 23
                    case 'summary':
1154 23
                        $detail = 'summary';
1155
                        break;
1156 23
                    default:
1157
                        break;
1158 23
                }
1159
                break;
1160 23
        }
1161 21
1162 18
        $conditions['detail'] = $detail;
1163
1164 20
        $flexiData = $this->getFlexiData(null, $conditions);
1165
1166
        if (!is_null($indexBy) && count($flexiData) && count(current($flexiData))) {
1167
            $flexiData = $this->reindexArrayBy($flexiData, $indexBy);
1168
        }
1169
1170
        return $flexiData;
1171
    }
1172
1173
    /**
1174
     * Vrací kód záznamu.
1175 23
     * Obtain record CODE
1176
     *
1177 23
     * @param mixed $data
1178
     *
1179 23
     * @return string
1180 23
     */
1181 23
    public function getKod($data = null, $unique = true)
1182
    {
1183 23
        $kod = null;
1184 23
1185 23
        if (is_null($data)) {
1186
            $data = $this->getData();
1187 23
        }
1188 23
1189 23
        if (is_string($data)) {
1190 23
            $data = [$this->nameColumn => $data];
1191 23
        }
1192 23
1193 23
        if (isset($data['kod'])) {
1194 23
            $kod = $data['kod'];
1195 23
        } else {
1196 23
            if (isset($data[$this->nameColumn])) {
1197
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1198
                    \Ease\Sand::rip($data[$this->nameColumn]));
1199
            } else {
1200 23
                if (isset($data[$this->myKeyColumn])) {
1201 23
                    $kod = \Ease\Sand::rip($data[$this->myKeyColumn]);
1202 23
                }
1203
            }
1204 23
        }
1205 23
1206 23
        if (!strlen($kod)) {
1207 23
            $kod = 'NOTSET';
1208
        }
1209
1210 23
        if (strlen($kod) > 18) {
1211 23
            $kodfinal = strtoupper(substr($kod, 0, 18));
1212 23
        } else {
1213 23
            $kodfinal = strtoupper($kod);
1214 23
        }
1215 23
1216 23
        if ($unique) {
1217 23
            $counter = 0;
1218 23
            if (count($this->codes)) {
1219 23
                foreach ($this->codes as $codesearch => $keystring) {
1220 23
                    if (strstr($codesearch, $kodfinal)) {
1221 23
                        ++$counter;
1222
                    }
1223 23
                }
1224 23
            }
1225
            if ($counter) {
1226 23
                $kodfinal = $kodfinal.$counter;
1227
            }
1228
1229
            $this->codes[$kodfinal] = $kod;
1230
        }
1231
1232
        return $kodfinal;
1233
    }
1234
1235
    /**
1236 32
     * Write Operation Result.
1237
     *
1238 32
     * @param array  $resultData
1239 32
     * @param string $url        URL
1240 31
     * @return boolean Log save success
1241 8
     */
1242 8
    public function logResult($resultData = null, $url = null)
1243 31
    {
1244 31
        $logResult = false;
1245 31
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1246 31
            if (isset($resultData['message'])) {
1247 32
                $this->addStatusMessage($resultData['message'], 'warning');
1248
            }
1249
            $this->addStatusMessage('Error '.$this->lastResponseCode.': '.urldecode($url),
1250 32
                'warning');
1251 24
            unset($url);
1252 24
        }
1253
        if (is_null($resultData)) {
1254 32
            $resultData = $this->lastResult;
1255 23
        }
1256 23
        if (isset($url)) {
1257 23
            $this->logger->addStatusMessage($this->lastResponseCode.':'.urldecode($url));
1258 23
        }
1259
1260 23
        if (isset($resultData['results'])) {
1261 23
            if ($resultData['success'] == 'false') {
1262 23
                $status = 'error';
1263 23
            } else {
1264 23
                $status = 'success';
1265
            }
1266 23
            foreach ($resultData['results'] as $result) {
1267 23
                if (isset($result['request-id'])) {
1268 23
                    $rid = $result['request-id'];
1269 23
                } else {
1270
                    $rid = '';
1271
                }
1272 23
                if (isset($result['errors'])) {
1273
                    foreach ($result['errors'] as $error) {
1274
                        $message = $error['message'];
1275 23
                        if (isset($error['for'])) {
1276
                            $message .= ' for: '.$error['for'];
1277
                        }
1278 23
                        if (isset($error['value'])) {
1279 23
                            $message .= ' value:'.$error['value'];
1280 23
                        }
1281 23
                        if (isset($error['code'])) {
1282 23
                            $message .= ' code:'.$error['code'];
1283 32
                        }
1284
                        $this->addStatusMessage($rid.': '.$message, $status);
1285
                    }
1286
                }
1287
            }
1288
        }
1289
        return $logResult;
1290
    }
1291
1292
    /**
1293
     * Save RAW Curl Request & Response to files in Temp directory
1294
     */
1295
    public function saveDebugFiles()
1296
    {
1297
        $tmpdir   = sys_get_temp_dir();
1298
        $fname    = $this->evidence.'-'.$this->curlInfo['when'].'.'.$this->format;
1299
        $reqname  = $tmpdir.'/request-'.$fname;
1300
        $respname = $tmpdir.'/response-'.$fname;
1301
        file_put_contents($reqname, $this->postFields);
1302
        file_put_contents($respname, $this->lastCurlResponse);
1303
    }
1304
1305
    /**
1306
     * Připraví data pro odeslání do FlexiBee
1307
     *
1308
     * @param string $data
1309
     */
1310
    public function setPostFields($data)
1311
    {
1312
        $this->postFields = $data;
1313
    }
1314
1315
    /**
1316
     * Generuje fragment url pro filtrování.
1317
     *
1318
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1319
     *
1320 23
     * @param array  $data
1321
     * @param string $joiner default and/or
1322 23
     * @param string $defop  default operator
1323
     *
1324 23
     * @return string
1325 23
     */
1326 23
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq')
1327 23
    {
1328 23
        $parts = [];
1329 23
1330 23
        foreach ($data as $column => $value) {
1331 23
            if (!is_numeric($column)) {
1332 23
                if (is_integer($data[$column]) || is_float($data[$column])) {
1333
                    $parts[$column] = $column.' eq \''.$data[$column].'\'';
1334 23
                } elseif (is_bool($data[$column])) {
1335 23
                    $parts[$column] = $data[$column] ? $column.' eq true' : $column.' eq false';
1336 23
                } elseif (is_null($data[$column])) {
1337 23
                    $parts[$column] = $column." is null";
1338 23
                } else {
1339
                    switch ($value) {
1340
                        case '!null':
1341 23
                            $parts[$column] = $column." is not null";
1342 23
                            break;
1343
                        case 'is empty':
1344
                        case 'is not empty':
1345 23
                            $parts[$column] = $column.' '.$value;
1346
                            break;
1347 23
                        default:
1348 23
                            if ($column == 'stitky') {
1349
                                $parts[$column] = $column."='".self::code($data[$column])."'";
1350 23
                            } else {
1351
                                $parts[$column] = $column." $defop '".$data[$column]."'";
1352
                            }
1353 23
                            break;
1354 23
                    }
1355
                }
1356
            } else {
1357
                $parts[] = $value;
1358
            }
1359
        }
1360
        return implode(' '.$joiner.' ', $parts);
1361
    }
1362
1363
    /**
1364 47
     * Obtain record/object identificator code: or id:
1365
     * Vrací identifikátor objektu code: nebo id:
1366 47
     *
1367 47
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1368 33
     * @return string|int indentifikátor záznamu reprezentovaného objektem
1369 33
     */
1370 47
    public function getRecordID()
1371 47
    {
1372 9
        $myCode = $this->getDataValue('kod');
1373 9
        if ($myCode) {
1374 9
            $id = 'code:'.$myCode;
1375
        } else {
1376 47
            $id = $this->getDataValue('id');
1377
            if (($this->debug === true) && is_null($id)) {
1378
                $this->addToLog('Object Data does not contain code: or id: cannot match with statement!',
1379
                    'warning');
1380
            }
1381
        }
1382
        return is_numeric($id) ? intval($id) : strval($id);
1383
    }
1384
1385
    /**
1386 47
     * Obtain record/object identificator code: or id:
1387
     * Vrací identifikátor objektu code: nebo id:
1388 47
     *
1389
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1390
     * @return string indentifikátor záznamu reprezentovaného objektem
1391
     */
1392
    public function __toString()
1393
    {
1394
        return strval($this->getRecordID());
1395
    }
1396
1397 23
    /**
1398
     * Gives you FlexiPeeHP class name for Given Evidence
1399 23
     *
1400
     * @param string $evidence
1401
     * @return string Class name
1402
     */
1403
    public static function evidenceToClassName($evidence)
1404
    {
1405
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1406
    }
1407 22
1408
    /**
1409 22
     * Obtain ID of first record in evidence
1410 22
     *
1411 22
     * @return string|null id or null if no records
1412 19
     */
1413 19
    public function getFirstRecordID()
1414 19
    {
1415 19
        $firstID    = null;
1416
        $firstIdRaw = $this->getColumnsFromFlexibee(['id'],
1417
            ['limit' => 1, 'order' => 'id'], 'id');
1418
        if (count($firstIdRaw)) {
1419
            $firstID = (int) current($firstIdRaw)['id'];
1420
        }
1421
        return $firstID;
1422
    }
1423
1424 23
    /**
1425
     * Vrací hodnotu daného externího ID
1426 23
     *
1427 23
     * @param string $want Which ? If empty,you obtain the first one.
1428 23
     * @return string
1429
     */
1430
    public function getExternalID($want = null)
1431
    {
1432
        $extid = null;
1433 23
        $ids   = $this->getDataValue('external-ids');
1434
        if (is_null($want)) {
1435
            if (count($ids)) {
1436
                $extid = current($ids);
1437
            }
1438
        } else {
1439
            if (!is_null($ids) && is_array($ids)) {
1440
                foreach ($ids as $id) {
1441 23
                    if (strstr($id, 'ext:'.$want)) {
1442
                        $extid = str_replace('ext:'.$want.':', '', $id);
1443
                    }
1444
                }
1445
            }
1446
        }
1447
        return $extid;
1448
    }
1449
1450
    /**
1451 22
     * Obtain actual GlobalVersion
1452
     * Vrací aktuální globální verzi změn
1453 22
     *
1454 22
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
1455 22
     * @return type
1456 22
     */
1457 22
    public function getGlobalVersion()
1458
    {
1459 22
        $globalVersion = null;
1460
        if (!count($this->lastResult) || !isset($this->lastResult['@globalVersion'])) {
1461
            $this->getFlexiData(null,
1462
                ['add-global-version' => 'true', 'limit' => 1]);
1463 22
        }
1464
1465
        if (isset($this->lastResult['@globalVersion'])) {
1466
            $globalVersion = intval($this->lastResult['@globalVersion']);
1467
        }
1468
1469
        return $globalVersion;
1470
    }
1471 23
1472
    /**
1473 23
     * Obtain content type of last response
1474 23
     *
1475 23
     * @return string
1476
     */
1477
    public function getResponseFormat()
1478 23
    {
1479
        if (isset($this->curlInfo['content_type'])) {
1480
            $responseFormat = $this->curlInfo['content_type'];
1481
        } else {
1482
            $responseFormat = null;
1483
        }
1484
        return $responseFormat;
1485
    }
1486
1487 35
    /**
1488
     * Return the same response format for one and multiplete results
1489 35
     *
1490 35
     * @param array $responseBody
1491 22
     * @return array
1492 22
     */
1493 35
    public function unifyResponseFormat($responseBody)
1494 35
    {
1495 35
        if (!is_array($responseBody) || array_key_exists('message',
1496 35
                $responseBody)) { //Unifi response format
1497 35
            $response = $responseBody;
1498 35
        } else {
1499 35
            $evidence = $this->getResponseEvidence();
1500 22
            if (array_key_exists($evidence, $responseBody)) {
1501
                $response        = [];
1502 35
                $evidenceContent = $responseBody[$evidence];
1503
                if (array_key_exists(0, $evidenceContent)) {
1504
                    $response[$evidence] = $evidenceContent; //Multiplete Results
1505
                } else {
1506
                    $response[$evidence][0] = $evidenceContent; //One result
1507
                }
1508
            } else {
1509
                if (isset($responseBody['priloha'])) {
1510 35
                    $response = $responseBody['priloha'];
1511
                } else {
1512
                    $response = $responseBody;
1513
                }
1514
            }
1515
        }
1516
        return $response;
1517
    }
1518
1519 23
    /**
1520
     * Obtain structure for current (or given) evidence
1521 23
     *
1522 23
     * @param string $evidence
1523 23
     * @return array Evidence structure
1524 23
     */
1525 23 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...
1526 23
    {
1527 21
        $columnsInfo = null;
1528 21
        if (is_null($evidence)) {
1529 23
            $evidence = $this->getEvidence();
1530
        }
1531
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1532
        if (isset(\FlexiPeeHP\Properties::$$propsName)) {
1533
            $columnsInfo = Properties::$$propsName;
1534
        }
1535
        return $columnsInfo;
1536
    }
1537
1538 23
    /**
1539
     * Obtain actions for current (or given) evidence
1540 23
     *
1541 23
     * @param string $evidence
1542 23
     * @return array Evidence structure
1543 23
     */
1544 23 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...
1545 23
    {
1546 21
        $actionsInfo = null;
1547 21
        if (is_null($evidence)) {
1548 23
            $evidence = $this->getEvidence();
1549
        }
1550
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1551
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
1552
            $actionsInfo = Actions::$$propsName;
1553
        }
1554
        return $actionsInfo;
1555
    }
1556
1557 23
    /**
1558
     * Obtain relations for current (or given) evidence
1559 23
     *
1560 23
     * @param string $evidence
1561 23
     * @return array Evidence structure
1562 23
     */
1563 23
    public function getRelationsInfo($evidence = null)
1564 23
    {
1565 19
        $relationsInfo = null;
1566 19
        if (is_null($evidence)) {
1567 23
            $evidence = $this->getEvidence();
1568
        }
1569
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
1570
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
1571
            $relationsInfo = Relations::$$propsName;
1572
        }
1573
        return $relationsInfo;
1574
    }
1575
1576 23
    /**
1577
     * Obtain info for current (or given) evidence
1578 23
     *
1579 23
     * @param string $evidence
1580 23
     * @return array Evidence info
1581 23
     */
1582 23 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...
1583 16
    {
1584 16
        $evidencesInfo = null;
1585 23
        if (is_null($evidence)) {
1586
            $evidence = $this->getEvidence();
1587
        }
1588
        if (isset(EvidenceList::$evidences[$evidence])) {
1589
            $evidencesInfo = EvidenceList::$evidences[$evidence];
1590
        }
1591
        return $evidencesInfo;
1592
    }
1593
1594 23
    /**
1595
     * Obtain name for current (or given) evidence path
1596 23
     *
1597 23
     * @param string $evidence Evidence Path
1598 23
     * @return array Evidence info
1599 23
     */
1600 23 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...
1601 16
    {
1602 16
        $evidenceName = null;
1603 23
        if (is_null($evidence)) {
1604
            $evidence = $this->getEvidence();
1605
        }
1606
        if (isset(EvidenceList::$name[$evidence])) {
1607
            $evidenceName = EvidenceList::$name[$evidence];
1608
        }
1609
        return $evidenceName;
1610
    }
1611
1612
    /**
1613
     * Perform given action (if availble) on current evidence/record
1614 15
     * @url https://demo.flexibee.eu/devdoc/actions
1615
     *
1616 15
     * @param string $action one of evidence actions
1617
     * @param string $method ext|int External method call operation in URL.
1618 15
     *                               Internal add the @action element to request body
1619 15
     */
1620 15
    public function performAction($action, $method = 'ext')
1621 15
    {
1622 15
        $actionsAvailble = $this->getActionsInfo();
1623
1624
        if (is_array($actionsAvailble) && array_key_exists($action,
1625
                $actionsAvailble)) {
1626 15
            switch ($actionsAvailble[$action]['actionMakesSense']) {
1627 15
                case 'ONLY_WITH_INSTANCE_AND_NOT_IN_EDIT':
1628 15
                case 'ONLY_WITH_INSTANCE': //Add instance
1629 15
                    $urlSuffix = '/'.$this->__toString().'/'.$action.'.'.$this->format;
1630
                    break;
1631
1632 15
                default:
1633
                    $urlSuffix = '/'.$action;
1634
                    break;
1635
            }
1636
1637
            switch ($method) {
1638 15
                case 'int':
1639 15
                    $this->setAction($action);
1640 15
                    $this->setPostFields($this->jsonizeData($this->getData()));
1641 15
                    $result = $this->performRequest(null, 'POST');
1642 15
                    break;
1643
1644
                default:
1645
                    $result = $this->performRequest($urlSuffix, 'GET');
1646
                    break;
1647 15
            }
1648
        } else {
1649
            throw new \Exception(sprintf(_('Unsupported action %s for evidence %s'),
1650
                $action, $this->getEvidence()));
1651
        }
1652
1653
        return $result;
1654
    }
1655 23
1656
    /**
1657 23
     * Save current object to file
1658 1
     *
1659 1
     * @param string $destfile path to file
1660 23
     */
1661 23
    public function saveResponseToFile($destfile)
1662
    {
1663
        if (strlen($this->lastCurlResponse)) {
1664
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
1665
        }
1666
        file_put_contents($destfile, $this->lastCurlResponse);
1667
    }
1668 9
1669
    /**
1670 9
     * Obtain established relations listing
1671 9
     *
1672 9
     * @return array Null or Relations
1673 9
     */
1674 7
    public function getVazby($id = null)
1675 7
    {
1676 7
        if (is_null($id)) {
1677 4
            $id = $this->getRecordID();
1678 4
        }
1679 2
        if (!empty($id)) {
1680
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
1681 4
                ['relations' => 'vazby', 'id' => $id]);
1682
            $vazby    = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby']
1683
                    : null;
1684
        } else {
1685
            throw new \Exception(_('ID requied to get record relations '));
1686
        }
1687
        return $vazby;
1688
    }
1689
1690
    /**
1691
     * Gives You URL for Current Record in FlexiBee web interface
1692
     *
1693
     * @return string url
1694
     */
1695
    public function getFlexiBeeURL()
1696
    {
1697
        $parsed_url = parse_url(str_replace('.'.$this->format, '', $this->apiURL));
1698
        $scheme     = isset($parsed_url['scheme']) ? $parsed_url['scheme'].'://'
1699
                : '';
1700
        $host       = isset($parsed_url['host']) ? $parsed_url['host'] : '';
1701
        $port       = isset($parsed_url['port']) ? ':'.$parsed_url['port'] : '';
1702
        $user       = isset($parsed_url['user']) ? $parsed_url['user'] : '';
1703
        $pass       = isset($parsed_url['pass']) ? ':'.$parsed_url['pass'] : '';
1704
        $pass       = ($user || $pass) ? "$pass@" : '';
1705
        $path       = isset($parsed_url['path']) ? $parsed_url['path'] : '';
1706
        return $scheme.$user.$pass.$host.$port.$path;
1707
    }
1708
1709
    /**
1710
     * Set Record Key
1711
     *
1712
     * @param int|string $myKeyValue
1713
     * @return boolean
1714
     */
1715
    public function setMyKey($myKeyValue)
1716
    {
1717
        $res = parent::setMyKey($myKeyValue);
1718
        $this->updateApiURL();
1719
        return $res;
1720
    }
1721
1722
    /**
1723
     * Set or get ignore not found pages flag
1724
     *
1725
     * @param boolean $ignore set flag to
1726
     *
1727
     * @return boolean get flag state
1728
     */
1729
    public function ignore404($ignore = null)
1730
    {
1731
        if (!is_null($ignore)) {
1732
            $this->ignoreNotFound = $ignore;
1733
        }
1734
        return $this->ignoreNotFound;
1735
    }
1736
1737
    /**
1738
     * Send Document by mail
1739
     *
1740
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1741
     *
1742
     * @param string $to
1743
     * @param string $subject
1744
     * @param string $body Email Text
1745
     *
1746
     * @return int http response code
1747
     */
1748
    public function sendByMail($to, $subject, $body, $cc = null)
1749
    {
1750
        $this->setPostFields($body);
1751
        $result = $this->doCurlRequest(urlencode($this->getRecordID()).'/odeslani-dokladu?to='.$to.'&subject='.urlencode($subject).'&cc='.$cc
1752
            , 'PUT', 'xml');
1753
        return $result == 200;
1754
    }
1755
1756
    /**
1757
     * Send all unsent Invoices by mail
1758
     *
1759
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
1760
     * @return int http response code
1761
     */
1762
    public function sendUnsent()
1763
    {
1764
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
1765
                'xml');
1766
    }
1767
1768
    /**
1769
     * FlexiBee date to PHP DateTime
1770
     *
1771
     * @param string $flexidate
1772
     *
1773
     * @return \DateTime | false
1774
     */
1775
    public static function flexiDateToDateTime($flexidate)
1776
    {
1777
        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 1777 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...
1778
    }
1779
1780
    /**
1781
     * Získá dokument v daném formátu
1782
     * Obtain document in given format
1783
     *
1784
     * @param string $format  pdf/csv/xml/json/ ...
1785
     *
1786
     * @return string|null filename downloaded or none
1787
     */
1788
    public function getInFormat($format)
1789
    {
1790
        $response = null;
1791
        if ($this->setFormat($format)) {
1792
            if (($this->doCurlRequest(($format == 'html') ? $this->apiURL.'?inDesktopApp=true'
1793
                            : $this->apiURL, 'GET') == 200)) {
1794
                $response = $this->lastCurlResponse;
1795
            }
1796
        }
1797
        return $response;
1798
    }
1799
1800
    /**
1801
     * Uloží dokument v daném formátu do složky v systému souborů
1802
     * Save document in given format to directory in filesystem
1803
     *
1804
     * @param string $format  pdf/csv/xml/json/ ...
1805
     * @param string $destDir where to put file (prefix)
1806
     *
1807
     * @return string|null filename downloaded or none
1808
     */
1809
    public function downloadInFormat($format, $destDir = './')
1810
    {
1811
        $fileOnDisk = null;
1812
        if ($this->setFormat($format)) {
1813
            $downloadTo = $destDir.$this->getEvidence().'_'.$this->getMyKey().'.'.$format;
1814
            if (($this->doCurlRequest($this->apiURL, 'GET') == 200) && (file_put_contents($downloadTo,
1815
                    $this->lastCurlResponse) !== false)) {
1816
                $fileOnDisk = $downloadTo;
1817
            }
1818
        }
1819
        return $fileOnDisk;
1820
    }
1821
1822
    /**
1823
     * Compile and send Report about Error500 to FlexiBee developers
1824
     * If FlexiBee is running on localost try also include java backtrace
1825
     *
1826
     * @param array $errorResponse result of parseError();
1827
     */
1828
    public function error500Reporter($errorResponse)
1829
    {
1830
        $ur = str_replace('/c/'.$this->company, '',
1831
            str_replace($this->url, '', $this->curlInfo['url']));
1832
        if (!array_key_exists($ur, $this->reports)) {
1833
            $tmpdir   = sys_get_temp_dir();
1834
            $myTime   = $this->curlInfo['when'];
1835
            $curlname = $tmpdir.'/curl-'.$this->evidence.'-'.$myTime.'.json';
1836
            file_put_contents($curlname,
1837
                json_encode($this->curlInfo, JSON_PRETTY_PRINT));
1838
1839
            $report = new \Ease\Mailer($this->reportRecipient,
1840
                'Error report 500 - '.$ur);
1841
1842
            $d     = dir($tmpdir);
1843
            while (false !== ($entry = $d->read())) {
1844
                if (strstr($entry, $myTime)) {
1845
                    $ext  = pathinfo($tmpdir.'/'.$entry, PATHINFO_EXTENSION);
1846
                    $mime = Formats::suffixToContentType($ext);
1847
                    $report->addFile($tmpdir.'/'.$entry,
1848
                        empty($mime) ? 'text/plain' : $mime);
1849
                }
1850
            }
1851
            $d->close();
1852
1853
            if ((strstr($this->url, '://localhost') || strstr($this->url,
1854
                    '://127.')) && file_exists('/var/log/flexibee.log')) {
1855
1856
                $fl = fopen("/var/log/flexibee.log", "r");
1857
                if ($fl) {
1858
                    $tracelog = [];
1859
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
1860
                            $x_pos, SEEK_END) !== -1; $x_pos--) {
1861
                        $char = fgetc($fl);
1862
                        if ($char === "\n") {
1863
                            $tracelog[] = $output[$ln];
1864
                            if (strstr($output[$ln], $errorResponse['message'])) {
1865
                                break;
1866
                            }
1867
                            $ln++;
1868
                            continue;
1869
                        }
1870
                        $output[$ln] = $char.((array_key_exists($ln, $output)) ? $output[$ln]
1871
                                : '');
1872
                    }
1873
1874
                    $trace     = implode("\n", array_reverse($tracelog));
1875
                    $tracefile = $tmpdir.'/trace-'.$this->evidence.'-'.$myTime.'.log';
1876
                    file_put_contents($tracefile, $trace);
1877
                    $report->addItem("\n\n".$trace);
1878
                    fclose($fl);
1879
                }
1880
            } else {
1881
                $report->addItem($errorResponse['message']);
1882
            }
1883
1884
            $licenseInfo = $this->performRequest($this->url.'/default-license.json');
1885
1886
            $report->addItem("\n\n".json_encode($licenseInfo['license'],
1887
                    JSON_PRETTY_PRINT));
1888
1889
            if ($report->send()) {
1890
                $this->reports[$ur] = $myTime;
1891
            }
1892
        }
1893
    }
1894
1895
    /**
1896
     * Returns code:CODE
1897
     *
1898
     * @param string $code
1899
     *
1900
     * @return string
1901
     */
1902
    public static function code($code)
1903
    {
1904
        return 'code:'.self::uncode($code);
1905
    }
1906
1907
    /**
1908
     * Returns CODE without code: prefix
1909
     *
1910
     * @param string $code
1911
     *
1912
     * @return string
1913
     */
1914
    public static function uncode($code)
1915
    {
1916
        return str_replace('code:', '', $code);
1917
    }
1918
1919
    /**
1920
     * Reconnect After unserialization
1921
     */
1922
    public function __wakeup()
1923
    {
1924
        parent::__wakeup();
1925
        $this->curlInit();
1926
    }
1927
}
1928