Completed
Push — master ( 87ae1a...f88e31 )
by Vítězslav
24:47
created

FlexiBeeRO::parseError()   B

Complexity

Conditions 9
Paths 3

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 3
nop 1
dl 0
loc 25
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * FlexiPeeHP - Read Only Access to FlexiBee class.
5
 *
6
 * @author     Vítězslav Dvořák <[email protected]>
7
 * @copyright  (C) 2015-2019 Spoje.Net
8
 */
9
10
namespace FlexiPeeHP;
11
12
/**
13
 * Základní třída pro čtení z FlexiBee
14
 *
15
 * @url https://demo.flexibee.eu/devdoc/
16
 */
17
class FlexiBeeRO extends \Ease\Sand {
18
19
    use \Ease\RecordKey;
20
21
    /**
22
     * Where to get JSON files with evidence stricture etc.
23
     * @var string
24
     */
25
    public static $infoDir = __DIR__ . '/../../static';
26
27
    /**
28
     * Version of FlexiPeeHP library
29
     *
30
     * @var string
31
     */
32
    public static $libVersion = '1.37';
33
34
    /**
35
     * Základní namespace pro komunikaci s FlexiBee.
36
     * Basic namespace for communication with FlexiBee
37
     *
38
     * @var string Jmený prostor datového bloku odpovědi
39
     */
40
    public $nameSpace = 'winstrom';
41
42
    /**
43
     * URL of object data in FlexiBee
44
     * @var string url
45
     */
46
    public $apiURL = null;
47
48
    /**
49
     * Datový blok v poli odpovědi.
50
     * Data block in response field.
51
     *
52
     * @var string
53
     */
54
    public $resultField = 'results';
55
56
    /**
57
     * Verze protokolu použitého pro komunikaci.
58
     * Communication protocol version used.
59
     *
60
     * @var string Verze použitého API
61
     */
62
    public $protoVersion = '1.0';
63
64
    /**
65
     * Evidence užitá objektem.
66
     * Evidence used by object
67
     *
68
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
69
     * @var string
70
     */
71
    public $evidence = null;
72
73
    /**
74
     * Detaily evidence užité objektem
75
     * 
76
     * @var array 
77
     */
78
    public $evidenceInfo = [];
79
80
    /**
81
     * Výchozí formát pro komunikaci.
82
     * Default communication format.
83
     *
84
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
85
     *
86
     * @var string json|xml|...
87
     */
88
    public $format = 'json';
89
90
    /**
91
     * formát příchozí odpovědi
92
     * response format
93
     *
94
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
95
     *
96
     * @var string json|xml|...
97
     */
98
    public $responseFormat = 'json';
99
100
    /**
101
     * Curl Handle.
102
     *
103
     * @var resource
104
     */
105
    public $curl = null;
106
107
    /**
108
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
109
     * @var string
110
     */
111
    public $company = null;
112
113
    /**
114
     * [protocol://]Server[:port]
115
     * @var string
116
     */
117
    public $url = null;
118
119
    /**
120
     * REST API Username
121
     * @var string
122
     */
123
    public $user = null;
124
125
    /**
126
     * REST API Password
127
     * @var string
128
     */
129
    public $password = null;
130
131
    /**
132
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
133
     */
134
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
135
136
    /**
137
     * Default additional request url parameters after question mark
138
     *
139
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
140
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
141
     * @var array
142
     */
143
    public $defaultUrlParams = [];
144
145
    /**
146
     * Identifikační řetězec.
147
     *
148
     * @var string
149
     */
150
    public $init = null;
151
152
    /**
153
     * Sloupeček s názvem.
154
     *
155
     * @var string
156
     */
157
    public $nameColumn = 'nazev';
158
159
    /**
160
     * Sloupeček obsahující datum vložení záznamu do shopu.
161
     *
162
     * @var string
163
     */
164
    public $myCreateColumn = 'false';
165
166
    /**
167
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
168
     *
169
     * @var string
170
     */
171
    public $myLastModifiedColumn = 'lastUpdate';
172
173
    /**
174
     * Klíčový idendifikátor záznamu.
175
     *
176
     * @var string
177
     */
178
    public $fbKeyColumn = 'id';
179
180
    /**
181
     * Informace o posledním HTTP requestu.
182
     *
183
     * @var *
184
     */
185
    public $curlInfo;
186
187
    /**
188
     * Informace o poslední HTTP chybě.
189
     *
190
     * @var string
191
     */
192
    public $lastCurlError = null;
193
194
    /**
195
     * Used codes storage.
196
     *
197
     * @var array
198
     */
199
    public $codes = null;
200
201
    /**
202
     * Last Inserted ID.
203
     *
204
     * @var int
205
     */
206
    public $lastInsertedID = null;
207
208
    /**
209
     * Default Line Prefix.
210
     *
211
     * @var string
212
     */
213
    public $prefix = '/c/';
214
215
    /**
216
     * Raw Content of last curl response
217
     *
218
     * @var string
219
     */
220
    public $lastCurlResponse;
221
222
    /**
223
     * HTTP Response code of last request
224
     *
225
     * @var int
226
     */
227
    public $lastResponseCode = null;
228
229
    /**
230
     * Body data  for next curl POST operation
231
     *
232
     * @var string
233
     */
234
    protected $postFields = null;
235
236
    /**
237
     * Last operation result data or message(s)
238
     *
239
     * @var array
240
     */
241
    public $lastResult = null;
242
243
    /**
244
     * Number from  @rowCount in response
245
     * @var int
246
     */
247
    public $rowCount = null;
248
249
    /**
250
     * Number from  @globalVersion
251
     * @var int
252
     */
253
    public $globalVersion = null;
254
255
    /**
256
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
257
     * @var string filter query
258
     */
259
    public $filter;
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
        'add-global-version' => ['type' => 'boolean', 'description' => 'The response will contain the global version number of the current export'],
281
        'add-row-count' => ['type' => 'boolean', 'description' => 'Adding Total Records to Output (Pagination)'],
282
        'as-gui' => ['type' => 'boolean', 'description' => 'Turns on functions that complement the GUI processing outputs'],
283
        'auth' => ['type' => 'string', 'description' => 'http: Forces login using HTTP authentication, for example, to change the default WUI login method. html: Force HTML form authentication. This can be useful to suppress automatic SSO authentication.'],
284
        'authSessionId' => ['type' => 'string', 'description' => 'Authentification Session ID'],
285
        'code-as-id' => ['type' => 'boolean', 'description' => 'If an object has unique code, it is also exported (except for the <code> element) as <id> code: ... </id>'],
286
        'code-in-response' => ['type' => 'boolean', 'description' => 'The response will contain not only ID and URL for each object, but also code.'],
287
        'delimeter' => ['type' => 'string', 'description' => 'Specifies the input / output file separator in CSV format.',
288
            'example' => ';'],
289
        'detail' => ['type' => 'string', 'description' => 'Definition of the level of detail'], //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
290
        'dir' => ['type' => 'string', 'description' => 'Sorting direction.', 'example' => 'desc'],
291
        'dry-run' => ['type' => 'boolean', 'description' => 'Test run (dry-run)'], // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
292
        'encoding' => ['type' => 'string', 'description' => 'Specifies the encoding of the input / output file in CSV format.'],
293
        'export-settings' => ['type' => 'boolean', 'description' => 'Export one extra entry with current settings at the beginning'],
294
        'fail-on-warning' => ['type' => 'boolean', 'description' => 'If a warning occurs, do not save a record (Data Validation)'],
295
        'filter' => ['type' => 'string', 'description' => 'filter results by this param'],
296
        'format' => ['type' => 'string', 'description' => 'One of the compiled XSL transforms will be applied to the output XML.'],
297
        'idUcetniObdobi' => ['type' => 'string', 'description' => ''], //See: https://www.flexibee.eu/api/dokumentace/ref/stavy-uctu/
298
        'includes' => ['type' => 'string', 'description' => 'Include related detail level object ',
299
            'example' => 'faktura-vydana/stredisko'],
300
        'inDesktopApp' => ['type' => 'boolean', 'description' => 'Hide menu and navigation in html format'], // Note: Undocumented function (html only)
301
        'limit' => ['type' => 'integer', 'description' => 'number of requested results'],
302
        'mode' => ['type' => 'string', 'description' => 'Support for RubyOnRails',
303
            'example' => 'ruby'],
304
        'no-ext-ids' => ['type' => 'boolean', 'description' => 'The answer will not contain external identifiers (performance optimization)'],
305
        'no-http-errors' => ['type' => 'boolean', 'description' => 'If a 4xx error occurs while processing a request, the server sends 200 OK anyway'],
306
        'no-ids' => ['type' => 'boolean', 'description' => 'The response will not contain any primary identifiers (performance optimization). It only affects the main records.'],
307
        'only-ext-ids' => ['type' => 'boolean', 'description' => 'The primary key will not be exported, the <id> elements will only contain the external ID. Similar no-ids, but also affects subevidencies.'],
308
        'order' => ['type' => 'string', 'description' => 'Sorting records', 'example' => 'nazev@A'],
309
        'relations' => ['type' => 'string', 'description' => 'Adding session data (see detail levels) A session overview can be obtained for each record (/ relations).'],
310
        'report-lang' => ['type' => 'string', 'description' => 'The language in which to print the output when exporting to PDF',
311
            'example' => 'en'],
312
        'report-name' => ['type' => 'string', 'description' => 'The name of the printout when exporting to PDF',
313
            'example' => 'invoice'],
314
        'report-sign' => ['type' => 'string', 'description' => 'Whether the PDF should be exported electronically signed'],
315
        'skupina-stitku' => ['type' => 'string', 'description' => 'Enables grouping of labels when exporting by group (multiple labels)'],
316
        'sort' => ['type' => 'string', 'description' => 'Sorting records for ExtJS'],
317
        'start' => ['type' => 'integer', 'description' => 'Pagination'],
318
        'stitky-as-ids' => ['type' => 'boolean', 'description' => 'Labels will be exported and imported not as a code list but as a list of numeric IDs'],
319
        'use-ext-id' => ['type' => 'boolean', 'description' => 'If the object contains an external ESHOP or MY ID, use it as a bind.'],
320
        'use-internal-id' => ['type' => 'boolean', 'description' => 'In addition to the ref and showAs for objects, it also supplies an internalId attribute that contains the internal record ID'],
321
        'xpath' => ['type' => 'string', 'description' => 'Apply XPATH to result',
322
            'example' => '//winstrom/adresar/email/text()'] // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
323
    ];
324
325
    /**
326
     * Session ID
327
     * @var string
328
     */
329
    public $authSessionId = null;
330
331
    /**
332
     * Token obtained during login procedure
333
     * @var string 
334
     */
335
    public $refreshToken = null;
336
337
    /**
338
     * Save 404 results to log ?
339
     * @var boolean
340
     */
341
    protected $ignoreNotFound = false;
342
343
    /**
344
     * Array of errors caused by last request
345
     * @var array
346
     */
347
    private $errors = [];
348
349
    /**
350
     * List of Error500 reports sent
351
     * @var array
352
     */
353
    private $reports = [];
354
355
    /**
356
     * Send Error500 Report to
357
     * @var string email address
358
     */
359
    public $reportRecipient = '[email protected]';
360
361
    /**
362
     * Formating string for \DateTime::format() for datetime columns
363
     * @var string
364
     */
365
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
366
367
    /**
368
     * Formating string for \DateTime::format() for date columns
369
     * @var string
370
     */
371
    static public $DateFormat = 'Y-m-d';
372
373
    /**
374
     * Last Request response stats
375
     * @var array 
376
     */
377
    protected $responseStats = null;
378
379
    /**
380
     * Chained Objects
381
     * @var array
382
     */
383
    public $chained = [];
384
385
    /**
386
     * We Connect to server by default
387
     * @var boolean
388
     */
389
    public $offline = false;
390
391
    /**
392
     * Override cURL timeout
393
     * @var int seconds
394
     */
395
    public $timeout = null;
396
397
    /**
398
     * Columns Info for serveral evidencies
399
     * @var array 
400
     */
401
    private $columnsInfo = [];
402
403
    /**
404
     * Throw Exception in case of FlexiBee error
405
     * @var boolean 
406
     */
407
    public $throwException = false;
408
409
    /**
410
     * Class for read only interaction with FlexiBee.
411
     *
412
     * @param mixed $init default record id or initial data. See processInit()
413
     * @param array $options Connection settings and other options override
414
     */
415
    public function __construct($init = null, $options = []) {
416
        $this->init = $init;
417
418
        $this->setUp($options);
419
        $this->curlInit();
420
        if (!empty($init)) {
421
            $this->processInit($init);
422
        }
423
    }
424
425
    /**
426
     * Set internal Object name
427
     *
428
     * @param string $objectName
429
     *
430
     * @return string Jméno objektu
431
     */
432
    public function setObjectName($objectName = null) {
433
        return parent::setObjectName(is_null($objectName) ? ( empty($this->getRecordIdent()) ? $this->getObjectName() : $this->getRecordIdent() . '@' . $this->getObjectName() ) : $objectName);
434
    }
435
436
    /**
437
     * SetUp Object to be ready for work
438
     *
439
     * @param array $options Object Options ( user,password,authSessionId
440
     *                                        company,url,evidence,
441
     *                                        prefix,defaultUrlParams,debug,
442
     *                                        detail,offline,filter,ignore404
443
     *                                        timeout,companyUrl,ver,throwException
444
     */
445
    public function setUp($options = []) {
446
        if (array_key_exists('ver', $options)) {
447
            $this->protoVersion = $options['ver'];
448
            $this->prefix = 'v' . round($this->protoVersion) . '/c/';
449
        }
450
        if (array_key_exists('companyUrl', $options)) {
451
            $options = array_merge(self::companyUrlToOptions($options['companyUrl']),
452
                    $options);
453
        }
454
455
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
456
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
457
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
458
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
459
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
460
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
461
        if (!empty($this->authSessionId)) {
462
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
463
        }
464
        if (isset($options['evidence'])) {
465
            $this->setEvidence($options['evidence']);
466
        }
467
        $this->setupProperty($options, 'defaultUrlParams');
468
        if (isset($options['prefix'])) {
469
            $this->setPrefix($options['prefix']);
470
        }
471
        if (array_key_exists('detail', $options)) {
472
            $this->defaultUrlParams['detail'] = $options['detail'];
473
        }
474
        $this->setupProperty($options, 'filter');
475
        if (array_key_exists('offline', $options)) {
476
            $this->offline = (boolean) $options['offline'];
477
        }
478
479
        if (array_key_exists('ignore404', $options)) {
480
            $this->ignore404($options['ignore404']);
481
        }
482
483
        $this->setupProperty($options, 'throwException', 'FLEXIBEE_EXCEPTIONS');
484
        $this->setupProperty($options, 'debug');
485
        $this->updateApiURL();
486
    }
487
488
    /**
489
     * Convert companyUrl provided by CustomButton to options array
490
     * 
491
     * @param string $companyUrl
492
     * 
493
     * @return array Options
494
     */
495
    public static function companyUrlToOptions($companyUrl) {
496
        $urlParts = parse_url($companyUrl);
497
        $scheme = isset($urlParts['scheme']) ? $urlParts['scheme'] . '://' : '';
498
        $host = isset($urlParts['host']) ? $urlParts['host'] : '';
499
        $port = isset($urlParts['port']) ? ':' . $urlParts['port'] : '';
500
        $path = isset($urlParts['path']) ? $urlParts['path'] : '';
501
502
        $options['company'] = basename($path);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
503
        $options['url'] = $scheme . $host . $port;
504
        return $options;
505
    }
506
507
    /**
508
     * Get Current connection options for use in another object
509
     *
510
     * @return array usable as second constructor parameter
511
     */
512
    public function getConnectionOptions() {
513
        $conOpts = ['url' => $this->url];
514
        if (empty($this->authSessionId)) {
515
            $conOpts ['user'] = $this->user;
516
            $conOpts['password'] = $this->password;
517
        } else {
518
            $conOpts['authSessionId'] = $this->authSessionId;
519
        }
520
        $company = $this->getCompany();
521
        if (!empty($company)) {
522
            $conOpts['company'] = $company;
523
        }
524
        if (!is_null($this->timeout)) {
525
            $conOpts['timeout'] = $this->timeout;
526
        }
527
        return $conOpts;
528
    }
529
530
    /**
531
     * Export current/given configutation into Environment  
532
     * @param array $opts
533
     */
534
    public function configToEnv($opts = null) {
535
        $options = is_null($opts) ? $this->getConnectionOptions() : $opts;
536
        if(array_key_exists('url', $options)){
537
            putenv('FLEXIBEE_URL='.$options['URL']);
538
        }
539
        if(array_key_exists('user', $options)){
540
            putenv('FLEXIBEE_LOGIN='.$options['user']);
541
        }
542
        if(array_key_exists('password', $options)){
543
            putenv('FLEXIBEE_PASSWORD='.$options['password']);
544
        }
545
        if(array_key_exists('company', $options)){
546
            putenv('FLEXIBEE_COMPANY='.$options['company']);
547
        }
548
        if(array_key_exists('authSessionId', $options)){
549
            putenv('FLEXIBEE_AUTHSESSID='.$options['authSessionId']);
550
        }
551
    }
552
    
553
    /**
554
     * Inicializace CURL
555
     *
556
     * @return boolean Online Status
557
     */
558
    public function curlInit() {
559
        if ($this->offline === false) {
560
            $this->curl = \curl_init(); // create curl resource
561
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
562
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
563
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
564
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
565
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
566
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
567
            if (empty($this->authSessionId)) {
568
                curl_setopt($this->curl, CURLOPT_USERPWD,
569
                        $this->user . ':' . $this->password); // set username and password
570
            }
571
            if (!is_null($this->timeout)) {
572
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
573
            }
574
        }
575
        return !$this->offline;
576
    }
577
578
    /**
579
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
580
     *
581
     *  * 234                              - interní číslo záznamu k načtení
582
     *  * code:LOPATA                      - kód záznamu
583
     *  * BAGR                             - kód záznamu k načtení
584
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
585
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
586
     *
587
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
588
     */
589
    public function processInit($init) {
590
        if (is_integer($init)) {
591
            $this->loadFromFlexiBee($init);
592
        } elseif (is_array($init)) {
593
            $this->takeData($init);
594
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
595
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init) : $init)));
596
        } else {
597
            $this->loadFromFlexiBee($init);
598
        }
599
    }
600
601
    /**
602
     * Set Data Field value
603
     *
604
     * @param string $columnName field name
605
     * @param mixed  $value      field data value
606
     *
607
     * @return bool Success
608
     */
609
    public function setDataValue($columnName, $value) {
610
        switch ($columnName) {
611
            case 'kod':
612
                $value = self::uncode($value); //Alwyas uncode "kod" column
613
614
            default:
615
                if (is_object($value)) {
616
                    switch (get_class($value)) {
617
                        case 'DateTime':
618
                            $columnInfo = $this->getColumnInfo($columnName);
619
                            switch ($columnInfo['type']) {
620
                                case 'date':
621
                                    $value = self::dateToFlexiDate($value);
622
                                    break;
623
                                case 'datetime':
624
                                    $value = self::dateToFlexiDateTime($value);
625
                                    break;
626
                            }
627
                            break;
628
                    }
629
                }
630
                $result = parent::setDataValue($columnName, $value);
631
                break;
632
        }
633
        return $result;
634
    }
635
636
    /**
637
     * PHP Date object to FlexiBee date format
638
     * 
639
     * @param \DateTime $date
640
     */
641
    public static function dateToFlexiDate($date) {
642
        return $date->format(self::$DateFormat);
643
    }
644
645
    /**
646
     * PHP Date object to FlexiBee date format
647
     * 
648
     * @param \DateTime $dateTime
649
     */
650
    public static function dateToFlexiDateTime($dateTime) {
651
        return $dateTime->format(self::$DateTimeFormat);
652
    }
653
654
    /**
655
     * Set URL prefix
656
     *
657
     * @param string $prefix
658
     */
659
    public function setPrefix($prefix) {
660
        switch ($prefix) {
661
            case 'a': //Access
662
            case 'c': //Company
663
            case 'u': //User
664
            case 'g': //License Groups
665
            case 'admin':
666
            case 'status':
667
            case 'login-logout':
668
                $this->prefix = '/' . $prefix . '/';
669
                break;
670
            case null:
671
            case '':
672
            case '/':
673
                $this->prefix = '';
674
                break;
675
            default:
676
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
677
        }
678
    }
679
680
    /**
681
     * Set communication format.
682
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
683
     *
684
     * @param string $format
685
     * 
686
     * @return boolean format is availble
687
     */
688
    public function setFormat($format) {
689
        $result = true;
690
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
691
            if (array_key_exists($format, array_flip(Formats::$$this->evidence)) === false) {
692
                $result = false;
693
            }
694
        }
695
        if ($result === true) {
696
            $this->format = $format;
697
            $this->updateApiURL();
698
        }
699
        return $result;
700
    }
701
702
    /**
703
     * Nastaví Evidenci pro Komunikaci.
704
     * Set evidence for communication
705
     *
706
     * @param string $evidence evidence pathName to use
707
     * 
708
     * @return boolean evidence switching status
709
     */
710
    public function setEvidence($evidence) {
711
        switch ($this->prefix) {
712
            case '/c/':
713
                if ($this->debug === true) {
714
                    if (array_key_exists($evidence, EvidenceList::$name)) {
715
                        $this->evidence = $evidence;
716
                        $result = true;
717
                    } else {
718
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
719
                                        $evidence));
720
                    }
721
                } else {
722
                    $this->evidence = $evidence;
723
                    $result = true;
724
                }
725
                break;
726
            default:
727
                $this->evidence = $evidence;
728
                $result = true;
729
                break;
730
        }
731
        $this->updateApiURL();
732
        $this->evidenceInfo = $this->getEvidenceInfo();
733
        return $result;
734
    }
735
736
    /**
737
     * Vrací právě používanou evidenci pro komunikaci
738
     * Obtain current used evidence
739
     *
740
     * @return string
741
     */
742
    public function getEvidence() {
743
        return $this->evidence;
744
    }
745
746
    /**
747
     * Set used company.
748
     * Nastaví Firmu.
749
     *
750
     * @param string $company
751
     */
752
    public function setCompany($company) {
753
        $this->company = $company;
754
    }
755
756
    /**
757
     * Obtain company now used
758
     * Vrací právě používanou firmu
759
     *
760
     * @return string
761
     */
762
    public function getCompany() {
763
        return $this->company;
764
    }
765
766
    /**
767
     * Vrací název evidence použité v odpovědích z FlexiBee
768
     *
769
     * @return string
770
     */
771
    public function getResponseEvidence() {
772
        switch ($this->evidence) {
773
            case 'c':
774
                $evidence = 'company';
775
                break;
776
            case 'evidence-list':
777
                $evidence = 'evidence';
778
                break;
779
            default:
780
                $evidence = $this->getEvidence();
781
                break;
782
        }
783
        return $evidence;
784
    }
785
786
    /**
787
     * Převede rekurzivně Objekt na pole.
788
     *
789
     * @param object|array $object
790
     *
791
     * @return array
792
     */
793
    public static function object2array($object) {
794
        $result = null;
795
        if (is_object($object)) {
796
            $objectData = get_object_vars($object);
797
            if (is_array($objectData) && count($objectData)) {
798
                $result = array_map('self::object2array', $objectData);
799
            }
800
        } else {
801
            if (is_array($object)) {
802
                foreach ($object as $item => $value) {
803
                    $result[$item] = self::object2array($value);
804
                }
805
            } else {
806
                $result = $object;
807
            }
808
        }
809
810
        return $result;
811
    }
812
813
    /**
814
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
815
     *
816
     * @param object|array $object
817
     *
818
     * @return array
819
     */
820
    public static function objectToID($object) {
821
        $resultID = null;
822
        if (is_object($object) && method_exists($object, '__toString')
823
        ) {
824
            $resultID = $object->__toString();
825
        } else {
826
            if (is_array($object)) {
827
                foreach ($object as $item => $value) {
828
                    $resultID[$item] = self::objectToID($value);
829
                }
830
            } else { //String
831
                $resultID = $object;
832
            }
833
        }
834
835
        return $resultID;
836
    }
837
838
    /**
839
     * Return basic URL for used Evidence
840
     *
841
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
842
     *
843
     * @return string Evidence URL
844
     */
845
    public function getEvidenceURL() {
846
        $evidenceUrl = $this->url . $this->prefix . $this->company;
847
        $evidence = $this->getEvidence();
848
        if (!empty($evidence)) {
849
            $evidenceUrl .= '/' . $evidence;
850
        }
851
        return $evidenceUrl;
852
    }
853
854
    /**
855
     * Add suffix to Evidence URL
856
     *
857
     * @param string $urlSuffix
858
     *
859
     * @return string
860
     */
861
    public function evidenceUrlWithSuffix($urlSuffix) {
862
        $evidenceUrl = $this->getEvidenceUrl();
863
        if (!empty($urlSuffix)) {
864
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0] != '?')) {
865
                $evidenceUrl .= '/';
866
            }
867
            $evidenceUrl .= $urlSuffix;
868
        }
869
        return $evidenceUrl;
870
    }
871
872
    /**
873
     * Update $this->apiURL
874
     */
875
    public function updateApiURL() {
876
        $this->apiURL = $this->getEvidenceURL();
877
        $rowIdentifier = $this->getRecordIdent();
878
        if (empty($rowIdentifier)) {
879
            $rowIdentifier = $this->getRecordCode();
880
            if (empty($rowIdentifier)) {
881
                $rowIdentifier = $this->getExternalID();
882
            }
883
        }
884
        if (!empty($rowIdentifier)) {
885
            $this->apiURL .= '/' . self::urlEncode($rowIdentifier);
886
        }
887
        $this->apiURL .= '.' . $this->format;
888
    }
889
890
    /*
891
     * Add Default Url params to given url if not overrided
892
     *
893
     * @param string $urlRaw
894
     *
895
     * @return string url with default params added
896
     */
897
898
    public function addDefaultUrlParams($urlRaw) {
899
        return \Ease\Functions::addUrlParams($urlRaw, $this->defaultUrlParams,
900
                        false);
901
    }
902
903
    /**
904
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
905
     *
906
     * @param string $urlSuffix část URL za identifikátorem firmy.
907
     * @param string $method    HTTP/REST metoda
908
     * @param string $format    Requested format
909
     * 
910
     * @return array|boolean Výsledek operace
911
     */
912
    public function performRequest($urlSuffix = null, $method = 'GET',
913
            $format = null) {
914
        $this->rowCount = null;
915
        $this->responseStats = [];
916
        $this->errors = [];
917
918
        if (preg_match('/^http/', $urlSuffix)) {
919
            $url = $urlSuffix;
920
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
921
            $url = $this->url . $urlSuffix;
922
        } else {
923
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
924
        }
925
926
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
927
                $method, $format);
928
929
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
930
                                $this->responseFormat), $responseCode);
931
    }
932
933
    /**
934
     * Parse Raw FlexiBee response in several formats
935
     *
936
     * @param string $responseRaw raw response body
937
     * @param string $format      Raw Response format json|xml|etc
938
     *
939
     * @return array
940
     */
941
    public function rawResponseToArray($responseRaw, $format) {
942
        $responseDecoded = [];
943
        if (!empty(trim($responseRaw))) {
944
            switch ($format) {
945
                case 'json':
946
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
947
                    break;
948
                case 'xml':
949
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
950
                    break;
951
                case 'txt':
952
                default:
953
                    $responseDecoded = [$this->lastCurlResponse];
954
                    break;
955
            }
956
        }
957
        return $responseDecoded;
958
    }
959
960
    /**
961
     * Convert FlexiBee Response JSON to Array
962
     *
963
     * @param string $rawJson
964
     *
965
     * @return array
966
     */
967
    public function rawJsonToArray($rawJson) {
968
        $responseDecoded = json_decode($rawJson, true, 10);
969
        $decodeError = json_last_error_msg();
970
        if ($decodeError == 'No error') {
971
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
972
                $responseDecoded = $responseDecoded[$this->nameSpace];
973
            }
974
        } else {
975
            if ($this->debug) {
976
                $this->addStatusMessage('JSON Decoder: ' . $decodeError, 'error');
977
                $this->addStatusMessage($rawJson, 'debug');
978
            }
979
        }
980
        return $responseDecoded;
981
    }
982
983
    /**
984
     * Convert FlexiBee Response XML to Array
985
     *
986
     * @param string $rawXML
987
     *
988
     * @return array
989
     */
990
    public function rawXmlToArray($rawXML) {
991
        return self::xml2array($rawXML);
992
    }
993
994
    /**
995
     * Parse Response array
996
     *
997
     * @param array $responseDecoded
998
     * @param int $responseCode Request Response Code
999
     *
1000
     * @return array main data part of response
1001
     */
1002
    public function parseResponse($responseDecoded, $responseCode) {
1003
        $mainResult = null;
1004
        switch ($responseCode) {
1005
            case 201: //We do not care about Success Write here
1006
                break;
1007
            case 200: //Success Read
1008
1009
                if (is_array($responseDecoded)) {
1010
                    if (isset($responseDecoded['@rowCount'])) {
1011
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
1012
                    }
1013
                    if (isset($responseDecoded['@globalVersion'])) {
1014
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
1015
                    }
1016
1017
                    $mainResult = $this->unifyResponseFormat($responseDecoded);
1018
1019
                    if (array_key_exists('stats', $responseDecoded)) {
1020
                        $this->responseStats = $responseDecoded['stats'];
1021
                    } elseif (!empty($mainResult)) {
1022
                        if (array_key_exists('success', $mainResult) && ($mainResult['success'] == 'false')) {
1023
                            $this->responseStats = ['read' => 0];
1024
                        } elseif (array_key_exists('properties', $mainResult)) {
1025
                            $this->responseStats = ['read' => 1];
1026
                        } else {
1027
                            $responseEvidence = $this->getResponseEvidence();
1028
                            if (!empty($this->rowCount)) {
1029
                                $this->responseStats = ['read' => $this->rowCount];
1030
                            } elseif (array_key_exists($responseEvidence,
1031
                                            $mainResult)) {
1032
                                $this->responseStats = ['read' => count($mainResult[$responseEvidence])];
1033
                            } else {
1034
                                $this->responseStats = ['read' => count($mainResult)];
1035
                            }
1036
                        }
1037
                    }
1038
                } else {
1039
                    $mainResult = $responseDecoded;
1040
                }
1041
1042
                $this->lastResult = $mainResult;
1043
                break;
1044
1045
            case 500: // Internal Server Error
1046
                if ($this->debug === true) {
1047
                    $this->error500Reporter($responseDecoded);
1048
                }
1049
            case 404: // Page not found
1050
                if ($this->ignoreNotFound === true) {
1051
                    break;
1052
                }
1053
            case 400: //Bad Request parameters
1054
            default: //Something goes wrong
1055
                if (is_array($responseDecoded)) {
1056
                    $this->parseError($responseDecoded);
1057
                }
1058
1059
                if ($this->throwException === true) {
1060
                    throw new \Ease\Exception(json_encode($this->getErrors()), $this->lastResponseCode);
1061
                } else {
1062
                    $this->addStatusMessage($this->lastResponseCode . ': ' . $this->curlInfo['url'],
1063
                            'warning');
1064
                    $this->logResult($responseDecoded, $this->curlInfo['url']);
1065
                }
1066
                break;
1067
        }
1068
        return $mainResult;
1069
    }
1070
1071
    /**
1072
     * Parse error message response
1073
     *
1074
     * @param array $responseDecoded
1075
     * 
1076
     * @return int number of errors processed
1077
     */
1078
    public function parseError(array $responseDecoded) {
1079
        if (array_key_exists('results', $responseDecoded)) {
1080
1081
            foreach ($responseDecoded['results'][0]['result'] as $result) {
1082
                if (array_key_exists('errors', $result)) {
1083
                    foreach ($result as $error) {
1084
                        $this->errors[] = current($error);
1085
                    }
1086
                }
1087
            }
1088
1089
            foreach ($this->errors as $errorInfo) {
1090
                $this->addStatusMessage(array_key_exists('error',$errorInfo) ? $errorInfo['error'] : $errorInfo['message'], 'error');
1091
                if (array_key_exists('for', $errorInfo)) {
1092
                    unset($errorInfo['message']);
1093
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1094
                }
1095
            }
1096
        } else {
1097
            if (array_key_exists('message', $responseDecoded)) {
1098
                $this->errors = [['message' => $responseDecoded['message']]];
1099
            }
1100
        }
1101
        return count($this->errors);
1102
    }
1103
1104
    /**
1105
     * Vykonej HTTP požadavek
1106
     *
1107
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1108
     * @param string $url    URL požadavku
1109
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1110
     * @param string $format požadovaný formát komunikace
1111
     * 
1112
     * @return int HTTP Response CODE
1113
     */
1114
    public function doCurlRequest($url, $method, $format = null) {
1115
        if (is_null($format)) {
1116
            $format = $this->format;
1117
        }
1118
        curl_setopt($this->curl, CURLOPT_URL, $url);
1119
// Nastavení samotné operace
1120
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1121
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1122
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1123
1124
        $httpHeaders = $this->defaultHttpHeaders;
1125
1126
        $formats = Formats::bySuffix();
1127
1128
        if (!isset($httpHeaders['Accept'])) {
1129
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1130
        }
1131
        if (!isset($httpHeaders['Content-Type'])) {
1132
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1133
        }
1134
        $httpHeadersFinal = [];
1135
        foreach ($httpHeaders as $key => $value) {
1136
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1137
                $value .= ' v' . self::$libVersion;
1138
            }
1139
            $httpHeadersFinal[] = $key . ': ' . $value;
1140
        }
1141
1142
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1143
1144
// Proveď samotnou operaci
1145
        $this->lastCurlResponse = curl_exec($this->curl);
1146
        $this->curlInfo = curl_getinfo($this->curl);
1147
        $this->curlInfo['when'] = microtime();
1148
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1149
        $this->responseFormat = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1150
                $url);
1151
        $this->lastResponseCode = $this->curlInfo['http_code'];
1152
        $this->lastCurlError = curl_error($this->curl);
1153
        if (strlen($this->lastCurlError)) {
1154
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1155
                            $this->lastResponseCode, $this->lastCurlError), 'error');
1156
        }
1157
1158
        if ($this->debug === true) {
1159
            $this->saveDebugFiles();
1160
        }
1161
1162
        return $this->lastResponseCode;
1163
    }
1164
1165
    /**
1166
     * Obtain json for application/json
1167
     * 
1168
     * @param string $contentType
1169
     * @param string $url
1170
     * 
1171
     * @return string response format
1172
     */
1173
    public function contentTypeToResponseFormat($contentType, $url = null) {
1174
        if (!empty($url)) {
1175
            $url = parse_url($url, PHP_URL_PATH);
1176
        }
1177
1178
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1179
                        strpos($contentType, ';')) : $contentType;
1180
1181
        switch ($url) {
1182
            case '/login-logout/login';
1183
                $responseFormat = 'json';
1184
                break;
1185
            default :
1186
                switch ($contentTypeClean) {
1187
                    case 'text/javascript':
1188
                        $responseFormat = 'js';
1189
                        break;
1190
1191
                    default:
1192
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1193
                        break;
1194
                }
1195
                break;
1196
        }
1197
1198
        return $responseFormat;
1199
    }
1200
1201
    /**
1202
     * Nastaví druh prováděné akce.
1203
     *
1204
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1205
     * @param string $action
1206
     * 
1207
     * @return boolean
1208
     */
1209
    public function setAction($action) {
1210
        $result = false;
1211
        $actionsAvailable = $this->getActionsInfo();
1212
        if (is_array($actionsAvailable) && array_key_exists($action,
1213
                        $actionsAvailable)) {
1214
            $this->action = $action;
1215
            $result = true;
1216
        }
1217
        return $result;
1218
    }
1219
1220
    /**
1221
     * Convert XML to array.
1222
     *
1223
     * @param string $xml
1224
     *
1225
     * @return array
1226
     */
1227
    public static function xml2array($xml) {
1228
        $arr = [];
1229
        if (!empty($xml)) {
1230
            if (is_string($xml)) {
1231
                $xml = simplexml_load_string($xml);
1232
            }
1233
            foreach ($xml->attributes() as $a) {
1234
                $arr['@' . $a->getName()] = strval($a);
1235
            }
1236
            foreach ($xml->children() as $r) {
1237
                if (count($r->children()) == 0) {
1238
                    $arr[$r->getName()] = strval($r);
1239
                } else {
1240
                    $arr[$r->getName()][] = self::xml2array($r);
1241
                }
1242
            }
1243
        }
1244
        return $arr;
1245
    }
1246
1247
    /**
1248
     * Odpojení od FlexiBee.
1249
     */
1250
    public function disconnect() {
1251
        if (is_resource($this->curl)) {
1252
            curl_close($this->curl);
1253
        }
1254
        $this->curl = null;
1255
    }
1256
1257
    /**
1258
     * Disconnect CURL befere pass away
1259
     */
1260
    public function __destruct() {
1261
        $this->disconnect();
1262
    }
1263
1264
    /**
1265
     * Načte řádek dat z FlexiBee.
1266
     *
1267
     * @param int $recordID id požadovaného záznamu
1268
     *
1269
     * @return array
1270
     */
1271
    public function getFlexiRow($recordID) {
1272
        $record = null;
1273
        $response = $this->performRequest($this->evidence . '/' . $recordID . '.json');
1274
        if (isset($response[$this->evidence])) {
1275
            $record = $response[$this->evidence][0];
1276
        }
1277
1278
        return $record;
1279
    }
1280
1281
    /**
1282
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1283
     *
1284
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1285
     * @param array $conditions pole podmínek   - rendrují se do ()
1286
     * @param array $urlParams  pole parametrů  - rendrují za ?
1287
     */
1288
    public function extractUrlParams(&$conditions, &$urlParams) {
1289
        foreach (array_keys($this->urlParams) as $urlParam) {
1290
            if (isset($conditions[$urlParam])) {
1291
                \Ease\Functions::divDataArray($conditions, $urlParams, $urlParam);
1292
            }
1293
        }
1294
    }
1295
1296
    /**
1297
     * convert unicode to entities for use with FlexiBee queries
1298
     *
1299
     * @param string $urlRaw
1300
     * 
1301
     * @return string
1302
     */
1303
    public static function urlEncode($urlRaw) {
1304
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1305
    }
1306
1307
    /**
1308
     * Načte data z FlexiBee.
1309
     *
1310
     * @param string $suffix     dotaz
1311
     * @param string|array       $conditions Custom filters or modifiers
1312
     *
1313
     * @return array Data obtained
1314
     */
1315
    public function getFlexiData($suffix = null, $conditions = null) {
1316
        $finalUrl = '';
1317
        $evidenceToRestore = null;
1318
        $urlParams = $this->defaultUrlParams;
1319
1320
        if (!empty($conditions)) {
1321
            if (is_array($conditions)) {
1322
                $this->extractUrlParams($conditions, $urlParams);
1323
                if (array_key_exists('evidence', $conditions) && is_null($this->getColumnInfo('evidence'))) {
1324
                    $evidenceToRestore = $this->getEvidence();
1325
                    $this->setEvidence($conditions['evidence']);
1326
                    unset($conditions['evidence']);
1327
                }
1328
                $conditions = $this->flexiUrl($conditions);
1329
            }
1330
1331
            if (strlen($conditions) && ($conditions[0] != '/')) {
1332
                $conditions = '(' . self::urlEncode($conditions) . ')';
1333
            }
1334
        }
1335
1336
        if (strlen($suffix) && ($suffix != '$sum')) {
1337
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1338
                $finalUrl = $suffix;
1339
            } else {
1340
                if (preg_match('/^(code|ext):(.*)/', $suffix)) {
1341
                    $finalUrl = self::urlizeId($suffix);
1342
                } else {
1343
                    $finalUrl = $suffix;
1344
                }
1345
            }
1346
        }
1347
1348
        $finalUrl .= $conditions;
1349
1350
        if ($suffix == '$sum') {
1351
            $finalUrl .= '/$sum';
1352
        }
1353
1354
        if (!empty($urlParams)) {
1355
            if (strstr($finalUrl, '?')) {
1356
                $finalUrl .= '&';
1357
            } else {
1358
                $finalUrl .= '?';
1359
            }
1360
            $finalUrl .= http_build_query(array_map(function($a) {
1361
                        return is_bool($a) ? ($a ? 'true' : 'false' ) : $a;
1362
                    }, $urlParams), null, '&', PHP_QUERY_RFC3986);
1363
        }
1364
1365
        $transactions = $this->performRequest($finalUrl, 'GET');
1366
        $responseEvidence = $this->getResponseEvidence();
1367
        if (is_array($transactions) && array_key_exists($responseEvidence,
1368
                        $transactions)) {
1369
            $result = $transactions[$responseEvidence];
1370
            if ((count($result) == 1) && empty(current($result))) {
1371
                $result = []; // Response is empty Array
1372
            }
1373
        } else {
1374
            $result = $transactions;
1375
        }
1376
        if (!is_null($evidenceToRestore)) {
1377
            $this->setEvidence($evidenceToRestore);
1378
        }
1379
        return $result;
1380
    }
1381
1382
    /**
1383
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1384
     * Read FlexiBee record and store it inside od object
1385
     *
1386
     * @param int|string $id ID or conditions
1387
     *
1388
     * @return int počet načtených položek
1389
     */
1390
    public function loadFromFlexiBee($id = null) {
1391
        $data = [];
1392
        if (is_null($id)) {
1393
            $id = $this->getMyKey();
1394
        }
1395
        $flexidata = $this->getFlexiData($this->getEvidenceUrl() . '/' . self::urlizeId($id));
1396
        if ($this->lastResponseCode == 200) {
1397
            $this->apiURL = $this->curlInfo['url'];
1398
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1399
                $data = current($flexidata);
1400
            }
1401
        }
1402
        return $this->takeData($data);
1403
    }
1404
1405
    /**
1406
     * Reload current record from FlexiBee
1407
     * 
1408
     * @return boolean 
1409
     */
1410
    public function reload() {
1411
        $id = $this->getRecordIdent();
1412
        $this->dataReset();
1413
        $this->loadFromFlexiBee($id);
1414
        return $this->lastResponseCode == 200;
1415
    }
1416
1417
    /**
1418
     * Set Filter code for requests
1419
     *
1420
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1421
     *
1422
     * @param array|string $filter filter formula or ['key'=>'value']
1423
     *
1424
     * @return string Filter code
1425
     */
1426
    public function setFilter($filter) {
1427
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1428
    }
1429
1430
    /**
1431
     * Převede data do Json formátu pro FlexiBee.
1432
     * Convert data to FlexiBee like Json format
1433
     *
1434
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1435
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1436
     *
1437
     * @param array $data    object data
1438
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1439
     *
1440
     * @return string
1441
     */
1442
    public function getJsonizedData($data = null, $options = 0) {
1443
        if (is_null($data)) {
1444
            $data = $this->getData();
1445
        }
1446
1447
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1448
                $this->getDataForJSON($data));
1449
        $jsonRaw = json_encode([$this->nameSpace => $dataToJsonize],
1450
                $options);
1451
1452
        return $jsonRaw;
1453
    }
1454
1455
    /**
1456
     * Get Data Fragment specific for current object
1457
     *
1458
     * @param array $data
1459
     *
1460
     * @return array
1461
     */
1462
    public function getDataForJSON($data = null) {
1463
        if (is_null($data)) {
1464
            $data = $this->getData();
1465
        }
1466
1467
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null; however, FlexiPeeHP\FlexiBeeRO::objectToID() does only seem to accept object|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
1468
1469
        if (!is_null($this->action)) {
1470
            $dataForJson[$this->evidence . '@action'] = $this->action;
1471
            $this->action = null;
1472
        }
1473
1474
        if (!is_null($this->filter)) {
1475
            $dataForJson[$this->evidence . '@filter'] = $this->filter;
1476
        }
1477
1478
1479
        foreach ($this->chained as $chained) {
1480
            $chainedData = $chained->getDataForJSON();
1481
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1482
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1483
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1484
                        $dataBackup = $dataForJson[$chainedItemEvidence];
1485
                        $dataForJson[$chainedItemEvidence] = [];
1486
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1487
                    }
1488
                    if (array_key_exists(0, $chainedItemData)) {
1489
                        foreach ($chainedItemData as $chainedItem) {
1490
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1491
                        }
1492
                    } else {
1493
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1494
                    }
1495
                } else {
1496
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1497
                }
1498
            }
1499
        }
1500
1501
1502
        return $dataForJson;
1503
    }
1504
1505
    /**
1506
     * Join another FlexiPeeHP Object
1507
     *
1508
     * @param FlexiBeeRO $object
1509
     *
1510
     * @return boolean adding to stack success
1511
     */
1512
    public function join(&$object) {
1513
        $result = true;
1514
        if (method_exists($object, 'getDataForJSON')) {
1515
            $this->chained[] = $object;
1516
        } else {
1517
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1518
        }
1519
1520
        return $result;
1521
    }
1522
1523
    /**
1524
     * Prepare record ID to use in URL
1525
     * 
1526
     * @param mixed $id
1527
     * 
1528
     * @return string id ready for use in URL
1529
     */
1530
    public static function urlizeId($id) {
1531
        if (is_array($id)) {
1532
            $id = rawurlencode('(' . self::flexiUrl($id) . ')');
1533
        } else if (preg_match('/^ext:/', $id)) {
1534
            $id = self::urlEncode($id);
1535
        } else if (preg_match('/^code:/', $id)) {
1536
            $id = self::code(self::urlEncode(self::uncode($id)));
1537
        }
1538
        return $id;
1539
    }
1540
1541
    /**
1542
     * Test if given record ID exists in FlexiBee.
1543
     *
1544
     * @param mixed $identifer presence state
1545
     *
1546
     * @return boolean
1547
     */
1548
    public function idExists($identifer = null) {
1549
        if (is_null($identifer)) {
1550
            $identifer = $this->getMyKey();
1551
        }
1552
        $ignorestate = $this->ignore404();
1553
        $this->ignore404(true);
1554
        $cands = $this->getFlexiData(null,
1555
                [
1556
                    'detail' => 'custom:' . $this->getKeyColumn(),
1557
                    $this->getKeyColumn() => $identifer
1558
        ]);
1559
        $this->ignore404($ignorestate);
1560
        return ($this->lastResponseCode == 200) && !empty($cands);
1561
    }
1562
1563
    /**
1564
     * Test if given record exists in FlexiBee.
1565
     *
1566
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1567
     * 
1568
     * @return boolean Record presence status
1569
     */
1570
    public function recordExists($data = []) {
1571
1572
        if (empty($data)) {
1573
            $data = $this->getData();
1574
        }
1575
        $ignorestate = $this->ignore404();
1576
        $this->ignore404(true);
1577
        $keyColumn = $this->getKeyColumn();
1578
        $res = $this->getColumnsFromFlexibee([$keyColumn],
1579
                is_array($data) ? $data : [$keyColumn => $data]);
1580
1581
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false')) || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1582
            $found = false;
1583
        } else {
1584
            $found = true;
1585
        }
1586
        $this->ignore404($ignorestate);
1587
        return $found;
1588
    }
1589
1590
    /**
1591
     * Vrací z FlexiBee sloupečky podle podmínek.
1592
     *
1593
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1594
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1595
     *                                     sloupečku
1596
     * @return array
1597
     */
1598
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1599
        if (is_int($conditions)) {
1600
            $conditions = [$this->getmyKeyColumn() => $conditions];
0 ignored issues
show
Bug introduced by
The method getmyKeyColumn() does not exist on FlexiPeeHP\FlexiBeeRO. Did you maybe mean getMyKey()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1601
        }
1602
1603
        $flexiData = $this->getFlexiData('', $conditions);
1604
1605
        if (!is_null($indexBy)) {
1606
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData);
1607
        }
1608
1609
        return $flexiData;
1610
    }
1611
1612
    /**
1613
     * Vrací z FlexiBee sloupečky podle podmínek.
1614
     *
1615
     * @param string|string[] $columnsList seznam položek nebo úrověň detailu: id|summary|full
1616
     * @param array           $conditions  pole podmínek nebo ID záznamu
1617
     * @param string          $indexBy     Sloupeček podle kterého indexovat záznamy
1618
     *
1619
     * @return array
1620
     */
1621
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1622
            $indexBy = null) {
1623
        $detail = 'full';
1624
        switch (gettype($columnsList)) {
1625
            case 'integer': //Record ID
1626
                $conditions = [$this->getmyKeyColumn() => $conditions];
0 ignored issues
show
Bug introduced by
The method getmyKeyColumn() does not exist on FlexiPeeHP\FlexiBeeRO. Did you maybe mean getMyKey()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1627
            case 'array': //Few Conditions
1628
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1629
                                $columnsList)) {
1630
                    $columnsList[] = $indexBy;
1631
                }
1632
                $columns = implode(',', array_unique($columnsList));
1633
                $detail = 'custom:' . $columns;
1634
            default:
1635
                switch ($columnsList) {
1636
                    case 'id':
1637
                        $detail = 'id';
1638
                        break;
1639
                    case 'summary':
1640
                        $detail = 'summary';
1641
                        break;
1642
                    default:
1643
                        break;
1644
                }
1645
                break;
1646
        }
1647
1648
        $conditions['detail'] = $detail;
1649
1650
        $flexiData = $this->getFlexiData(null, $conditions);
1651
1652
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1653
                        $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1654
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData, $indexBy);
1655
        }
1656
1657
        return $flexiData;
1658
    }
1659
1660
    /**
1661
     * Vrací kód záznamu.
1662
     * Obtain record CODE
1663
     *
1664
     * @param mixed $data
1665
     *
1666
     * @return string
1667
     */
1668
    public function getKod($data = null, $unique = true) {
1669
        $kod = null;
1670
1671
        if (is_null($data)) {
1672
            $data = $this->getData();
1673
        }
1674
1675
        if (is_string($data)) {
1676
            $data = [$this->nameColumn => $data];
1677
        }
1678
1679
        if (isset($data['kod'])) {
1680
            $kod = $data['kod'];
1681
        } else {
1682
            if (isset($data[$this->nameColumn])) {
1683
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1684
                        \Ease\Functions::rip($data[$this->nameColumn]));
1685
            } else {
1686
                if (isset($data[$this->keyColumn])) {
1687
                    $kod = \Ease\Functions::rip($data[$this->keyColumn]);
1688
                }
1689
            }
1690
            $kod = substr($kod, 0, 20);
1691
        }
1692
1693
        if (!strlen($kod)) {
1694
            $kod = 'NOTSET';
1695
        }
1696
1697
        if (strlen($kod) > 18) {
1698
            $kodfinal = strtoupper(substr($kod, 0, 18));
1699
        } else {
1700
            $kodfinal = strtoupper($kod);
1701
        }
1702
1703
        if ($unique) {
1704
            $counter = 0;
1705
            if (!empty($this->codes) && count($this->codes)) {
1706
                foreach ($this->codes as $codesearch => $keystring) {
1707
                    if (strstr($codesearch, $kodfinal)) {
1708
                        ++$counter;
1709
                    }
1710
                }
1711
            }
1712
            if ($counter) {
1713
                $kodfinal = $kodfinal . $counter;
1714
            }
1715
1716
            $this->codes[$kodfinal] = $kod;
1717
        }
1718
1719
        return self::code($kodfinal);
1720
    }
1721
1722
    /**
1723
     * Write Operation Result.
1724
     *
1725
     * @param array  $resultData
1726
     * @param string $url        URL
1727
     * 
1728
     * @return boolean Log save success
1729
     */
1730
    public function logResult($resultData = null, $url = null) {
1731
        $logResult = false;
1732
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1733
            $this->addStatusMessage('Error ' . $this->lastResponseCode . ': ' . urldecode($url) . (array_key_exists('message',
1734
                            $resultData) ? ' ' . $resultData['message'] : ''), 'warning');
1735
            unset($url);
1736
        }
1737
        if (is_null($resultData)) {
1738
            $resultData = $this->lastResult;
1739
        }
1740
        if (isset($url)) {
1741
            \Ease\Shared::logger()->addToLog($this,$this->lastResponseCode . ':' . urldecode($url));
1742
        }
1743
1744
        if (isset($resultData['results'])) {
1745
            if ($resultData['success'] == 'false') {
1746
                $status = 'error';
1747
            } else {
1748
                $status = 'success';
1749
            }
1750
            foreach ($resultData['results'] as $result) {
1751
                if (isset($result['request-id'])) {
1752
                    $rid = $result['request-id'];
1753
                } else {
1754
                    $rid = '';
1755
                }
1756
                if (isset($result['errors'])) {
1757
                    foreach ($result['errors'] as $error) {
1758
                        $message = $error['message'];
1759
                        if (isset($error['for'])) {
1760
                            $message .= ' for: ' . $error['for'];
1761
                        }
1762
                        if (isset($error['value'])) {
1763
                            $message .= ' value:' . $error['value'];
1764
                        }
1765
                        if (isset($error['code'])) {
1766
                            $message .= ' code:' . $error['code'];
1767
                        }
1768
                        $this->addStatusMessage($rid . ': ' . $message, $status);
1769
                    }
1770
                }
1771
            }
1772
        }
1773
        return $logResult;
1774
    }
1775
1776
    /**
1777
     * Save RAW Curl Request & Response to files in Temp directory
1778
     */
1779
    public function saveDebugFiles() {
1780
        $tmpdir = sys_get_temp_dir();
1781
        $fname = $this->evidence . '-' . $this->curlInfo['when'] . '.' . $this->format;
1782
        $reqname = $tmpdir . '/request-' . $fname;
1783
        $respname = $tmpdir . '/response-' . $fname;
1784
        $header = '# ' . (new \DateTime())->format('Y-m-d\TH:i:s.u') . ' ' . $this->curlInfo['url'] . ' (' . urldecode($this->curlInfo['url']) . ')';
1785
        if (file_put_contents($reqname, $header . "\n" . $this->postFields)) {
1786
            $this->addStatusMessage($reqname, 'debug');
1787
        }
1788
        if (file_put_contents($respname, $header . "\n" . $this->lastCurlResponse)) {
1789
            $this->addStatusMessage($respname, 'debug');
1790
        }
1791
    }
1792
1793
    /**
1794
     * Připraví data pro odeslání do FlexiBee
1795
     *
1796
     * @param string $data
1797
     */
1798
    public function setPostFields($data) {
1799
        $this->postFields = $data;
1800
    }
1801
1802
    /**
1803
     * Get Content ready to be send as POST body
1804
     * @return string
1805
     */
1806
    public function getPostFields() {
1807
        return $this->postFields;
1808
    }
1809
1810
    /**
1811
     * Generuje fragment url pro filtrování.
1812
     *
1813
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1814
     *
1815
     * @param array  $data   key=>values; value can bee class DatePeriod, DateTime or Array
1816
     * @param string $joiner default and/or
1817
     * @param string $defop  default operator
1818
     *
1819
     * @return string
1820
     */
1821
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq') {
1822
        $parts = [];
1823
1824
        foreach ($data as $column => $value) {
1825
            if (!is_numeric($column)) {
1826
                if (is_integer($data[$column]) || is_float($data[$column])) {
1827
                    $parts[$column] = $column . ' eq \'' . $data[$column] . '\'';
1828
                } elseif (is_bool($data[$column])) {
1829
                    $parts[$column] = $data[$column] ? $column . ' eq true' : $column . ' eq false';
1830
                } elseif (is_null($data[$column])) {
1831
                    $parts[$column] = $column . " is null";
1832
                } elseif (is_array($data[$column])) {
1833
                    $parts[$column] = $column . " in (" . implode(',',
1834
                                    array_map(function($a, $column) {
1835
                                        return $column == 'stitky' ? "'" . self::code($a) . "'" : "'$a'";
1836
                                    }, $data[$column],
1837
                                            array_fill(0, count($data[$column]), $column))) . ")";
1838
                } elseif (is_object($data[$column])) {
1839
                    switch (get_class($data[$column])) {
1840
                        case 'DatePeriod':
1841
                            $parts[$column] = $column . " between '" . $data[$column]->getStartDate()->format(self::$DateFormat) . "' '" . $data[$column]->getEndDate()->format(self::$DateFormat) . "'";
1842
                            break;
1843
                        case 'DateTime':
1844
                            $parts[$column] = $column . " eq '" . $data[$column]->format(self::$DateFormat) . "'";
1845
                            break;
1846
                        default:
1847
                            $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1848
                            break;
1849
                    }
1850
                } else {
1851
                    switch ($value) {
1852
                        case '!null':
1853
                            $parts[$column] = $column . " is not null";
1854
                            break;
1855
                        case 'is empty':
1856
                        case 'is not empty':
1857
                        case 'is true':
1858
                        case 'is false':
1859
                            $parts[$column] = $column . ' ' . $value;
1860
                            break;
1861
                        default:
1862
                            $condParts = explode(' ', trim($value));
1863
                            switch ($condParts[0]) {
1864
                                case '<>':
1865
                                case '!=':
1866
                                case 'ne':
1867
                                case 'neq':
1868
                                case '<':
1869
                                case 'lt':
1870
                                case '<=':
1871
                                case 'lte':
1872
                                case '>':
1873
                                case 'gt':
1874
                                case '>=':
1875
                                case 'gte':
1876
                                case 'like':
1877
                                case 'begins':
1878
                                case 'between':
1879
                                case 'ends':
1880
                                    if (count($condParts) == 1) {
1881
                                        $parts[$column] = $column .= ' ' . $value;
1882
                                    } else {
1883
                                        $parts[$column] = $column .= ' ' . $condParts[0] . " '" . $condParts[1] . "'";
1884
                                    }
1885
                                    break;
1886
                                default:
1887
                                    if ($column == 'stitky') {
1888
                                        $parts[$column] = $column . "='" . self::code($data[$column]) . "'";
1889
                                    } else {
1890
                                        $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1891
                                    }
1892
                                    break;
1893
                            }
1894
1895
                            break;
1896
                    }
1897
                }
1898
            } else {
1899
                $parts[] = $value;
1900
            }
1901
        }
1902
        return implode(' ' . $joiner . ' ', $parts);
1903
    }
1904
1905
    /**
1906
     * Obtain record/object numeric identificator id:
1907
     * Vrací číselný identifikátor objektu id:
1908
     *
1909
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1910
     *
1911
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1912
     */
1913
    public function getRecordID() {
1914
        $id = $this->getDataValue('id');
1915
        return is_null($id) ? null : (is_numeric($id) ? intval($id) : $id);
1916
    }
1917
1918
    /**
1919
     * Obtain record/object identificator code:
1920
     * Vrací identifikátor objektu code:
1921
     *
1922
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1923
     *
1924
     * @return string record code identifier
1925
     */
1926
    public function getRecordCode() {
1927
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1928
    }
1929
1930
    /**
1931
     * Obtain record/object identificator extId: code: or id:
1932
     * Vrací identifikátor objektu extId: code: nebo id:
1933
     *
1934
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1935
     *
1936
     * @return string|int|null record code identifier
1937
     */
1938
    public function getRecordIdent() {
1939
        $ident = $this->getExternalID();
1940
        if (empty($ident)) {
1941
            $ident = $this->getRecordCode();
1942
        }
1943
        if (empty($ident)) {
1944
            $ident = $this->getRecordID();
1945
        }
1946
        return $ident;
1947
    }
1948
1949
    /**
1950
     * Obtain record/object identificator code: or id:
1951
     * Vrací identifikátor objektu code: nebo id:
1952
     *
1953
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1954
     * 
1955
     * @return string indentifikátor záznamu reprezentovaného objektem
1956
     */
1957
    public function __toString() {
1958
        return strval($this->getRecordIdent());
1959
    }
1960
1961
    /**
1962
     * Gives you FlexiPeeHP class name for Given Evidence
1963
     *
1964
     * @param string $evidence
1965
     * 
1966
     * @return string Class name
1967
     */
1968
    public static function evidenceToClassName($evidence) {
1969
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1970
    }
1971
1972
    /**
1973
     * Obtain ID of first record in evidence
1974
     *
1975
     * @return string|null id or null if no records
1976
     */
1977
    public function getFirstRecordID() {
1978
        $firstID = null;
1979
        $keyColumn = $this->getKeyColumn();
1980
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1981
                ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1982
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1983
            $firstID = current($firstIdRaw)[$keyColumn];
1984
        }
1985
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1986
    }
1987
1988
    /**
1989
     * Get previous record ID
1990
     * 
1991
     * @param array $conditions optional
1992
     * 
1993
     * @return int|null
1994
     */
1995
    public function getNextRecordID($conditions = []) {
1996
        $conditions['order'] = 'id@D';
1997
        $conditions['limit'] = 1;
1998
        $conditions[] = 'id gt ' . $this->getRecordID();
1999
        $next = $this->getColumnsFromFlexibee(['id'], $conditions);
2000
        return (is_array($next) && array_key_exists(0, $next) && array_key_exists('id',
2001
                        $next[0])) ? intval($next[0]['id']) : null;
2002
    }
2003
2004
    /**
2005
     * Get next record ID
2006
     * 
2007
     * @param array $conditions optional
2008
     * 
2009
     * @return int|null
2010
     */
2011
    public function getPrevRecordID($conditions = []) {
2012
        $conditions['order'] = 'id@A';
2013
        $conditions['limit'] = 1;
2014
        $conditions[] = 'id lt ' . $this->getRecordID();
2015
        $prev = $this->getColumnsFromFlexibee(['id'], $conditions);
2016
        return (is_array($prev) && array_key_exists(0, $prev) && array_key_exists('id',
2017
                        $prev[0])) ? intval($prev[0]['id']) : null;
2018
    }
2019
2020
    /**
2021
     * Vrací hodnotu daného externího ID
2022
     *
2023
     * @param string $want Namespace Selector. If empty,you obtain the first one.
2024
     * 
2025
     * @return string|array one id or array if multiplete
2026
     */
2027
    public function getExternalID($want = null) {
2028
        $extid = null;
2029
        $ids = $this->getExternalIDs();
2030
        if (is_null($want)) {
2031
            if (!empty($ids)) {
2032
                $extid = current($ids);
2033
            }
2034
        } else {
2035
            if (!is_null($ids) && is_array($ids)) {
2036
                foreach ($ids as $id) {
2037
                    if (strstr($id, 'ext:' . $want)) {
2038
                        if (is_null($extid)) {
2039
                            $extid = str_replace('ext:' . $want . ':', '', $id);
2040
                        } else {
2041
                            if (is_array($extid)) {
2042
                                $extid[] = str_replace('ext:' . $want . ':', '', $id);
2043
                            } else {
2044
                                $extid = [$extid, str_replace('ext:' . $want . ':',
2045
                                            '', $id)];
2046
                            }
2047
                        }
2048
                    }
2049
                }
2050
            }
2051
        }
2052
        return $extid;
2053
    }
2054
2055
    /**
2056
     * gives you currently loaded extermal IDs
2057
     * 
2058
     * @return array
2059
     */
2060
    public function getExternalIDs() {
2061
        return $this->getDataValue('external-ids');
2062
    }
2063
2064
    /**
2065
     * Obtain actual GlobalVersion
2066
     * Vrací aktuální globální verzi změn
2067
     *
2068
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
2069
     * 
2070
     * @return int
2071
     */
2072
    public function getGlobalVersion() {
2073
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
2074
2075
        return $this->globalVersion;
2076
    }
2077
2078
    /**
2079
     * Gives you current ApiURL with given format suffix
2080
     * 
2081
     * @param string $format json|html|xml|...
2082
     * 
2083
     * @return string API URL for current record or object/evidence
2084
     */
2085
    public function getApiURL($format = null) {
2086
        $apiUrl = str_replace(['.' . $this->format, '?limit=0'], '', $this->apiURL);
2087
        return $apiUrl . (empty($format) ? '' : '.' . $format );
2088
    }
2089
2090
    /**
2091
     * Obtain content type of last response
2092
     *
2093
     * @return string
2094
     */
2095
    public function getResponseFormat() {
2096
        return $this->responseFormat;
2097
    }
2098
2099
    /**
2100
     * Return the same response format for one and multiplete results
2101
     *
2102
     * @param array $responseBody
2103
     * 
2104
     * @return array
2105
     */
2106
    public function unifyResponseFormat($responseBody) {
2107
        if (!is_array($responseBody) || array_key_exists('message',
2108
                        $responseBody)) { //Unifi response format
2109
            $response = $responseBody;
2110
        } else {
2111
            $evidence = $this->getResponseEvidence();
2112
            if (array_key_exists($evidence, $responseBody)) {
2113
                $response = [];
2114
                $evidenceContent = $responseBody[$evidence];
2115
                if (array_key_exists(0, $evidenceContent)) {
2116
                    $response[$evidence] = $evidenceContent; //Multiplete Results
2117
                } else {
2118
                    $response[$evidence][0] = $evidenceContent; //One result
2119
                }
2120
            } else {
2121
                if (isset($responseBody['priloha'])) {
2122
                    $response = $responseBody['priloha'];
2123
                } else {
2124
                    if (array_key_exists('results', $responseBody)) {
2125
                        $response = $responseBody['results'];
2126
                    } else {
2127
                        $response = $responseBody;
2128
                    }
2129
                }
2130
            }
2131
        }
2132
        return $response;
2133
    }
2134
2135
    /**
2136
     * Obtain structure for current (or given) evidence
2137
     *
2138
     * @param string $evidence
2139
     * 
2140
     * @return array Evidence structure
2141
     */
2142
    public function getOfflineColumnsInfo($evidence = null) {
2143
        $columnsInfo = null;
2144
        $infoSource = self::$infoDir . '/Properties.' . (empty($evidence) ? $this->getEvidence() : $evidence) . '.json';
2145
        if (file_exists($infoSource)) {
2146
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2147
        }
2148
        return $columnsInfo;
2149
    }
2150
2151
    /**
2152
     * Obtain Current evidence Live structure
2153
     * 
2154
     * @param string $evidence
2155
     * 
2156
     * @return array structure
2157
     */
2158
    public function getOnlineColumnsInfo($evidence = null) {
2159
        $properties = [];
2160
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2161
        $flexinfo = $this->performRequest('/c/' . $this->company . '/' . $evidence . '/properties.json');
2162
        if (!empty($flexinfo) && array_key_exists('properties', $flexinfo)) {
2163
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2164
                $key = $evidenceProperty['propertyName'];
2165
                $properties[$key] = $evidenceProperty;
2166
                if (array_key_exists('name', $evidenceProperty)) {
2167
                    $proerties[$key]['name'] = $evidenceProperty['name'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$proerties was never initialized. Although not strictly required by PHP, it is generally a good practice to add $proerties = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2168
                }
2169
                $properties[$key]['type'] = $evidenceProperty['type'];
2170
                if (array_key_exists('url', $evidenceProperty)) {
2171
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2172
                            $evidenceProperty['url']);
2173
                }
2174
            }
2175
        }
2176
        return $properties;
2177
    }
2178
2179
    /**
2180
     * Update evidence info from array or online from properties.json or offline
2181
     * 
2182
     * @param array  $columnsInfo
2183
     * @param string $evidence
2184
     */
2185
    public function updateColumnsInfo($columnsInfo = null, $evidence = null) {
2186
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2187
        if (is_null($columnsInfo)) {
2188
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence) : $this->getOnlineColumnsInfo($evidence);
2189
        } else {
2190
            $this->columnsInfo[$evidence] = $columnsInfo;
2191
        }
2192
    }
2193
2194
    /**
2195
     * Gives you evidence structure. You can obtain current online by pre-calling:
2196
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2197
     * 
2198
     * @param string $evidence
2199
     * 
2200
     * @return array
2201
     */
2202
    public function getColumnsInfo($evidence = null) {
2203
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2204
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2205
            $this->updateColumnsInfo($this->getOfflineColumnsInfo($evidence),
2206
                    $evidence);
2207
        }
2208
        return $this->columnsInfo[$evidence];
2209
    }
2210
2211
    /**
2212
     * Gives you properties for (current) evidence column
2213
     *
2214
     * @param string $column    name of column
2215
     * @param string $evidence  evidence name if different
2216
     *
2217
     * @return array column properties or null if column not exits
2218
     */
2219
    public function getColumnInfo($column, $evidence = null) {
2220
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence() : $evidence);
2221
        return (empty($column) || empty($columnsInfo) || !is_array($columnsInfo)) ? null : (array_key_exists($column, $columnsInfo) ? $columnsInfo[$column] : null);
2222
    }
2223
2224
    /**
2225
     * Obtain actions for current (or given) evidence
2226
     *
2227
     * @param string $evidence
2228
     * 
2229
     * @return array Evidence structure
2230
     */
2231
    public function getActionsInfo($evidence = null) {
2232
        $actionsInfo = null;
2233
        if (is_null($evidence)) {
2234
            $evidence = $this->getEvidence();
2235
        }
2236
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2237
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2238
            $actionsInfo = Actions::$$propsName;
2239
        }
2240
        return $actionsInfo;
2241
    }
2242
2243
    /**
2244
     * Obtain relations for current (or given) evidence
2245
     *
2246
     * @param string $evidence
2247
     * 
2248
     * @return array Evidence structure
2249
     */
2250
    public function getRelationsInfo($evidence = null) {
2251
        $relationsInfo = null;
2252
        if (is_null($evidence)) {
2253
            $evidence = $this->getEvidence();
2254
        }
2255
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2256
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2257
            $relationsInfo = Relations::$$propsName;
2258
        }
2259
        return $relationsInfo;
2260
    }
2261
2262
    /**
2263
     * Obtain info for current (or given) evidence
2264
     *
2265
     * @param string $evidence
2266
     * 
2267
     * @return array Evidence info
2268
     */
2269
    public function getEvidenceInfo($evidence = null) {
2270
        $evidencesInfo = null;
2271
        if (is_null($evidence)) {
2272
            $evidence = $this->getEvidence();
2273
        }
2274
        if (isset(EvidenceList::$evidences[$evidence])) {
2275
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2276
            $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2277
            if (isset(Formats::$$propsName)) {
2278
                $evidencesInfo['formats'] = Formats::$$propsName;
2279
            }
2280
        }
2281
        return $evidencesInfo;
2282
    }
2283
2284
    /**
2285
     * Obtain name for current (or given) evidence path
2286
     *
2287
     * @param string $evidence Evidence Path
2288
     * 
2289
     * @return array Evidence info
2290
     */
2291
    public function getEvidenceName($evidence = null) {
2292
        $evidenceName = null;
2293
        if (is_null($evidence)) {
2294
            $evidence = $this->getEvidence();
2295
        }
2296
        if (isset(EvidenceList::$name[$evidence])) {
2297
            $evidenceName = EvidenceList::$name[$evidence];
2298
        }
2299
        return $evidenceName;
2300
    }
2301
2302
    /**
2303
     * Save current object to file
2304
     *
2305
     * @param string $destfile path to file
2306
     */
2307
    public function saveResponseToFile($destfile) {
2308
        if (strlen($this->lastCurlResponse)) {
2309
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2310
        }
2311
        file_put_contents($destfile, $this->lastCurlResponse);
2312
    }
2313
2314
    /**
2315
     * Obtain established relations listing
2316
     *
2317
     * @return array Null or Relations
2318
     */
2319
    public function getVazby($id = null) {
2320
        if (is_null($id)) {
2321
            $id = $this->getRecordID();
2322
        }
2323
        if (!empty($id)) {
2324
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2325
                    ['relations' => 'vazby', 'id' => $id]);
2326
            $vazby = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby'] : null;
2327
        } else {
2328
            throw new \Exception(_('ID requied to get record relations '));
2329
        }
2330
        return $vazby;
2331
    }
2332
2333
    /**
2334
     * Gives You URL for Current Record in FlexiBee web interface
2335
     *
2336
     * @return string url
2337
     */
2338
    public function getFlexiBeeURL() {
2339
        $parsed_url = parse_url(str_replace('.' . $this->format, '', $this->apiURL));
2340
        $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
2341
        $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2342
        $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
2343
        $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2344
        $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
2345
        $pass = ($user || $pass) ? "$pass@" : '';
2346
        $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2347
        return $scheme . $user . $pass . $host . $port . $path;
2348
    }
2349
2350
    /**
2351
     * Set Record Key
2352
     *
2353
     * @param int|string $myKeyValue
2354
     * 
2355
     * @return boolean
2356
     */
2357
    public function setMyKey($myKeyValue) {
2358
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2359
            if ($this->evidenceInfo['extIdSupported'] == 'false') {
2360
                $this->addStatusMessage(sprintf(_('Evidence %s does not support extIDs'),
2361
                                $this->getEvidence()), 'warning');
2362
                $res = false;
2363
            } else {
2364
                $extIds = $this->getDataValue('external-ids');
2365
                if (!empty($extIds) && count($extIds)) {
2366
                    $extIds = array_combine($extIds, $extIds);
2367
                }
2368
2369
                $extIds[$myKeyValue] = $myKeyValue;
2370
                $res = $this->setDataValue('external-ids',
2371
                        $extIds);
2372
            }
2373
        } else {
2374
            $res = $this->setDataValue($this->getKeyColumn(), $myKeyValue);
2375
        }
2376
        $this->updateApiURL();
2377
        return $res;
2378
    }
2379
2380
    /**
2381
     * Set or get ignore not found pages flag
2382
     *
2383
     * @param boolean $ignore set flag to
2384
     *
2385
     * @return boolean get flag state
2386
     */
2387
    public function ignore404($ignore = null) {
2388
        if (!is_null($ignore)) {
2389
            $this->ignoreNotFound = $ignore;
2390
        }
2391
        return $this->ignoreNotFound;
2392
    }
2393
2394
    /**
2395
     * Send Document by mail
2396
     *
2397
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2398
     *
2399
     * @param string $to         Email ecipient
2400
     * @param string $subject    Email Subject
2401
     * @param string $body       Email Text
2402
     *
2403
     * @return boolean mail sent status
2404
     */
2405
    public function sendByMail($to, $subject, $body, $cc = null) {
2406
        $this->setPostFields($body);
2407
2408
        $this->performRequest(rawurlencode($this->getRecordID()) . '/odeslani-dokladu?to=' . $to . '&subject=' . urlencode($subject) . '&cc=' . $cc
2409
                , 'PUT', 'xml');
2410
2411
        return $this->lastResponseCode == 200;
2412
    }
2413
2414
    /**
2415
     * Send all unsent Documents by eMail
2416
     *
2417
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2418
     * 
2419
     * @return int http response code
2420
     */
2421
    public function sendUnsent() {
2422
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
2423
                        'xml');
2424
    }
2425
2426
    /**
2427
     * FlexiBee date to PHP DateTime conversion
2428
     *
2429
     * @param string $flexidate 2017-05-26 or 2017-05-26+02:00
2430
     *
2431
     * @return \DateTime | false
2432
     */
2433
    public static function flexiDateToDateTime($flexidate) {
2434
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat . 'O' : self::$DateFormat, $flexidate)->setTime(0, 0);
2435
    }
2436
2437
    /**
2438
     * FlexiBee dateTime to PHP DateTime conversion
2439
     *
2440
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2441
     *
2442
     * @return \DateTime | false
2443
     */
2444
    public static function flexiDateTimeToDateTime($flexidatetime) {
2445
        if (strchr($flexidatetime, '.')) { //NewFormat
2446
            $format = self::$DateTimeFormat;
2447
        } else { // Old format
2448
            $format = 'Y-m-d\TH:i:s+P';
2449
        }
2450
        return \DateTime::createFromFormat($format, $flexidatetime);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression \DateTime::createFromFor...ormat, $flexidatetime); of type DateTime|false adds false to the return on line 2450 which is incompatible with the return type documented by FlexiPeeHP\FlexiBeeRO::flexiDateTimeToDateTime of type DateTime. It seems like you forgot to handle an error condition.
Loading history...
2451
    }
2452
2453
    /**
2454
     * Získá dokument v daném formátu
2455
     * Obtain document in given format
2456
     *
2457
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2458
     *
2459
     * @param string  $format     pdf/csv/xml/json/ ...
2460
     * @param string  $reportName Template used to generate PDF
2461
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2462
     * @param boolean $sign       sign resulting PDF by certificate ?
2463
     *
2464
     * @return string|null filename downloaded or none
2465
     */
2466
    public function getInFormat($format, $reportName = null, $lang = null,
2467
            $sign = false) {
2468
        $response = null;
2469
        if ($this->setFormat($format)) {
2470
            $urlParams = [];
2471
            switch ($format) {
2472
                case 'pdf':
2473
                    switch ($lang) {
2474
                        case 'cs':
2475
                        case 'sk':
2476
                        case 'en':
2477
                        case 'de':
2478
                            $urlParams['report-lang'] = $lang;
2479
                            break;
2480
                        case null:
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $lang of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2481
                        case '':
2482
                            break;
2483
                        default:
2484
                            throw new \Ease\Exception('Unknown language ' . $lang . ' for PDF export');
2485
                            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...
2486
                    }
2487
                    if (boolval($sign) === true) {
2488
                        $urlParams['report-sign'] = 'true';
2489
                    }
2490
                    break;
2491
                case 'html':
2492
                    $urlParams['inDesktopApp'] = 'true';
2493
                    break;
2494
            }
2495
            if (!empty($reportName)) {
2496
                $urlParams['report-name'] = $reportName;
2497
            }
2498
            if (($this->doCurlRequest(\Ease\Functions::addUrlParams($this->apiURL,
2499
                                    $urlParams), 'GET') == 200)) {
2500
                $response = $this->lastCurlResponse;
2501
            }
2502
        }
2503
        return $response;
2504
    }
2505
2506
    /**
2507
     * Uloží dokument v daném formátu do složky v systému souborů
2508
     * Save document in given format to directory in filesystem
2509
     *
2510
     * @param string $format  pdf/csv/xml/json/ ...
2511
     * @param string $destDir where to put file (prefix)
2512
     * @param string $reportName Template used to generate PDF
2513
     *
2514
     * @return string|null filename downloaded or none
2515
     */
2516
    public function downloadInFormat($format, $destDir = './',
2517
            $reportName = null) {
2518
        $fileOnDisk = null;
2519
        $formatBackup = $this->format;
2520
        if ($this->setFormat($format)) {
2521
            $downloadTo = $destDir . $this->getEvidence() . '_' . $this->getMyKey() . '.' . $format;
2522
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Functions::addUrlParams($this->apiURL,
2523
                                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2524
                            $this->lastCurlResponse) !== false)) {
2525
                $fileOnDisk = $downloadTo;
2526
            }
2527
            $this->setFormat($formatBackup);
2528
        }
2529
        return $fileOnDisk;
2530
    }
2531
2532
    /**
2533
     * Take data for object. separate external IDs
2534
     *
2535
     * @param array $data Data to keep
2536
     * 
2537
     * @return int number of records taken
2538
     */
2539
    public function takeData($data) {
2540
        $keyColumn = $this->getKeyColumn();
2541
        if (array_key_exists($keyColumn, $data) && is_array($data[$keyColumn])) {
2542
            foreach ($data[$keyColumn] as $recPos => $recordKey) {
2543
                if (substr($recordKey, 0, 4) == 'ext:') {
2544
                    $data['external-ids'][] = $recordKey;
2545
                    unset($data[$keyColumn][$recPos]);
2546
                }
2547
            }
2548
            if (count($data[$keyColumn]) == 1) {
2549
                $data[$keyColumn] = current($data[$keyColumn]);
2550
            }
2551
        }
2552
        $result = parent::takeData($data);
2553
2554
        if (array_key_exists($keyColumn, $data) || array_key_exists('kod', $data)) {
2555
            $this->updateApiURL();
2556
        }
2557
2558
        return $result;
2559
    }
2560
2561
    /**
2562
     * Get Current Evidence reports listing
2563
     * 
2564
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2565
     * 
2566
     * @return array
2567
     */
2568
    public function getReportsInfo() {
2569
        $reports = [];
2570
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL() . '/reports');
2571
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports']) && array_key_exists('report', $reportsRaw['reports']) &&
2572
                !empty($reportsRaw['reports']['report'])) {
2573
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
2574
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2575
            } else {
2576
                $reports = \Ease\Functions::reindexArrayBy($reportsRaw['reports']['report'],
2577
                                'reportId');
2578
            }
2579
        }
2580
        return $reports;
2581
    }
2582
2583
    /**
2584
     * Request authSessionId from current server
2585
     * 
2586
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2587
     * 
2588
     * @param string $username
2589
     * @param string $password
2590
     * @param string $otp       optional onetime password
2591
     * 
2592
     * @return string authUserId or null in case of problems
2593
     */
2594
    public function requestAuthSessionID($username, $password, $otp = null) {
2595
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2596
            'password' => $password] : ['username' => $username, 'password' => $password,
2597
            'otp' => $otp]);
2598
        $response = $this->performRequest('/login-logout/login', 'POST',
2599
                'json');
2600
        if (array_key_exists('refreshToken', $response)) {
2601
            $this->refreshToken = $response['refreshToken'];
2602
        } else {
2603
            $this->refreshToken = null;
2604
        }
2605
        return array_key_exists('authSessionId', $response) ? $response['authSessionId'] : null;
2606
    }
2607
2608
    /**
2609
     * Try to Sign in current user to FlexiBee and keep authSessionId
2610
     * 
2611
     * @return boolean sign in success
2612
     */
2613
    public function login() {
2614
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2615
                $this->password);
2616
        return $this->lastResponseCode == 200;
2617
    }
2618
2619
    /**
2620
     * End (current's user) session
2621
     * 
2622
     * 
2623
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2624
     * 
2625
     * @param string $username force username to sign off
2626
     * 
2627
     * @return array server response
2628
     */
2629
    public function logout($username = null) {
2630
        return $this->performRequest('/status/user/' . (is_null($username) ? $this->user : $username) . '/logout', 'POST');
2631
    }
2632
2633
    /**
2634
     * Compile and send Report about Error500 to FlexiBee developers
2635
     * If FlexiBee is running on localost try also include java backtrace
2636
     *
2637
     * @param array $errorResponse result of parseError();
2638
     */
2639
    public function error500Reporter($errorResponse) {
2640
        $ur = str_replace('/c/' . $this->company, '',
2641
                str_replace($this->url, '', $this->curlInfo['url']));
2642
        if (!array_key_exists($ur, $this->reports)) {
2643
            $tmpdir = sys_get_temp_dir();
2644
            $myTime = $this->curlInfo['when'];
2645
            $curlname = $tmpdir . '/curl-' . $this->evidence . '-' . $myTime . '.json';
2646
            file_put_contents($curlname,
2647
                    json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2648
2649
            $report = new \Ease\Mailer($this->reportRecipient,
2650
                    'Error report 500 - ' . $ur);
2651
2652
            $d = dir($tmpdir);
2653
            while (false !== ($entry = $d->read())) {
2654
                if (strstr($entry, $myTime)) {
2655
                    $ext = pathinfo($tmpdir . '/' . $entry, PATHINFO_EXTENSION);
2656
                    $mime = Formats::suffixToContentType($ext);
2657
                    $report->addFile($tmpdir . '/' . $entry,
2658
                            empty($mime) ? 'text/plain' : $mime);
2659
                }
2660
            }
2661
            $d->close();
2662
2663
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2664
                            '://127.')) && file_exists('/var/log/flexibee.log')) {
2665
2666
                $fl = fopen('/var/log/' . 'flexibee.log', 'r');
2667
                if ($fl) {
2668
                    $tracelog = [];
2669
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2670
                                    $x_pos, SEEK_END) !== -1; $x_pos--) {
2671
                        $char = fgetc($fl);
2672
                        if ($char === "\n") {
2673
                            $tracelog[] = $output[$ln];
2674
                            if (strstr($output[$ln], $errorResponse['message'])) {
2675
                                break;
2676
                            }
2677
                            $ln++;
2678
                            continue;
2679
                        }
2680
                        $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : '');
2681
                    }
2682
2683
                    $trace = implode("\n", array_reverse($tracelog));
2684
                    $tracefile = $tmpdir . '/trace-' . $this->evidence . '-' . $myTime . '.log';
2685
                    file_put_contents($tracefile, $trace);
2686
                    $report->addItem("\n\n" . $trace);
0 ignored issues
show
Bug introduced by
The method addItem() does not seem to exist on object<Ease\Mailer>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
2687
                    fclose($fl);
2688
                }
2689
            } else {
2690
                $report->addItem($errorResponse['message']);
0 ignored issues
show
Bug introduced by
The method addItem() does not seem to exist on object<Ease\Mailer>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
2691
            }
2692
2693
            $licenseInfo = $this->performRequest($this->url . '/default-license.json');
2694
2695
            $report->addItem("\n\n" . json_encode($licenseInfo['license'],
0 ignored issues
show
Bug introduced by
The method addItem() does not seem to exist on object<Ease\Mailer>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
2696
                            JSON_PRETTY_PRINT));
2697
2698
            if ($report->send()) {
2699
                $this->reports[$ur] = $myTime;
2700
            }
2701
        }
2702
    }
2703
2704
    /**
2705
     * Returns code:CODE
2706
     *
2707
     * @param string $code
2708
     *
2709
     * @return string
2710
     */
2711
    public static function code($code) {
2712
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:' . strtoupper(self::uncode($code)));
2713
    }
2714
2715
    /**
2716
     * Returns CODE without code: prefix
2717
     *
2718
     * @param string $code
2719
     *
2720
     * @return string
2721
     */
2722
    public static function uncode($code) {
2723
        return str_replace(['code:', 'code%3A'], '', $code);
2724
    }
2725
2726
    /**
2727
     * Remove all @ items from array
2728
     *
2729
     * @param array $data original data
2730
     *
2731
     * @return array data without @ columns
2732
     */
2733
    public static function arrayCleanUP($data) {
2734
        return array_filter(
2735
                $data,
2736
                function ($key) {
2737
            return !strchr($key, '@');
2738
        }, ARRAY_FILTER_USE_KEY);
2739
    }
2740
2741
    /**
2742
     * Add Info about used user, server and libraries
2743
     *
2744
     * @param string $prefix banner prefix text
2745
     * @param string $suffix banner suffix text
2746
     */
2747
    public function logBanner($prefix = null, $suffix = null) {
2748
        parent::logBanner($prefix,
2749
                ' FlexiBee ' . str_replace('://', '://' . $this->user . '@',
2750
                        $this->getApiUrl()) . ' FlexiBeeHP v' . self::$libVersion . ' (FlexiBee ' . EvidenceList::$version . ') EasePHP Framework v' . \Ease\Atom::$frameworkVersion . ' ' .
2751
                $suffix
2752
        );
2753
    }
2754
2755
    /**
2756
     * Get Last operation type
2757
     * 
2758
     * @return string create|read|update|delete or update,insert for some inserted and updated in one transaction
2759
     */
2760
    public function getLastOperationType() {
2761
        return implode(',', array_keys(array_filter($this->responseStats)));
2762
    }
2763
2764
    /**
2765
     * Last operation errors 
2766
     * 
2767
     * @return array FlexiBee error meassages
2768
     */
2769
    public function getErrors() {
2770
        return $this->errors;
2771
    }
2772
2773
    /**
2774
     * Reconnect After unserialization
2775
     */
2776
    public function __wakeup() {
2777
        $this->curlInit();
2778
    }
2779
2780
}
2781