Completed
Push — master ( 59734f...449770 )
by Vítězslav
21:32
created

FlexiBeeRO::parseError()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 8
rs 10
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-2020 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
     * Basic namespace for communication with FlexiBee
36
     *
37
     * @var string Jmený prostor datového bloku odpovědi
38
     */
39
    public $nameSpace = 'winstrom';
40
41
    /**
42
     * URL of object data in FlexiBee
43
     * @var string url
44
     */
45
    public $apiURL = null;
46
47
    /**
48
     * Data block in response field.
49
     *
50
     * @var string
51
     */
52
    public $resultField = 'results';
53
54
    /**
55
     * Communication protocol version used.
56
     *
57
     * @var string Verze použitého API
58
     */
59
    public $protoVersion = '1.0';
60
61
    /**
62
     * Evidence used by object
63
     *
64
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
65
     * 
66
     * @var string
67
     */
68
    public $evidence = null;
69
70
    /**
71
     * Detaily evidence užité objektem
72
     * 
73
     * @var array 
74
     */
75
    public $evidenceInfo = [];
76
77
    /**
78
     * Default communication format.
79
     *
80
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
81
     *
82
     * @var string json|xml|...
83
     */
84
    public $format = 'json';
85
86
    /**
87
     * requested response format
88
     *
89
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
90
     *
91
     * @var string json|xml|...
92
     */
93
    public $responseFormat = 'json';
94
95
    /**
96
     * Curl Handle.
97
     *
98
     * @var resource
99
     */
100
    public $curl = null;
101
102
    /**
103
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
104
     * @var string
105
     */
106
    public $company = null;
107
108
    /**
109
     * [protocol://]Server[:port]
110
     * @var string
111
     */
112
    public $url = null;
113
114
    /**
115
     * REST API Username
116
     * @var string
117
     */
118
    public $user = null;
119
120
    /**
121
     * REST API Password
122
     * @var string
123
     */
124
    public $password = null;
125
126
    /**
127
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
128
     */
129
    public $defaultHttpHeaders = [];
130
131
    /**
132
     * Default additional request url parameters after question mark
133
     *
134
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
135
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
136
     * @var array
137
     */
138
    public $defaultUrlParams = [];
139
140
    /**
141
     * Identifikační řetězec.
142
     *
143
     * @var string
144
     */
145
    public $init = null;
146
147
    /**
148
     * Sloupeček s názvem.
149
     *
150
     * @var string
151
     */
152
    public $nameColumn = 'nazev';
153
154
    /**
155
     * Sloupeček obsahující datum vložení záznamu do shopu.
156
     *
157
     * @var string
158
     */
159
    public $myCreateColumn = 'false';
160
161
    /**
162
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
163
     *
164
     * @var string
165
     */
166
    public $myLastModifiedColumn = 'lastUpdate';
167
168
    /**
169
     * Klíčový idendifikátor záznamu.
170
     *
171
     * @var string
172
     */
173
    public $fbKeyColumn = 'id';
174
175
    /**
176
     * Informace o posledním HTTP requestu.
177
     *
178
     * @var *
179
     */
180
    public $curlInfo;
181
182
    /**
183
     * Informace o poslední HTTP chybě.
184
     *
185
     * @var string
186
     */
187
    public $lastCurlError = null;
188
189
    /**
190
     * Used codes storage.
191
     *
192
     * @var array
193
     */
194
    public $codes = null;
195
196
    /**
197
     * Last Inserted ID.
198
     *
199
     * @var int
200
     */
201
    public $lastInsertedID = null;
202
203
    /**
204
     * Default Line Prefix.
205
     *
206
     * @var string
207
     */
208
    public $prefix = '/c/';
209
210
    /**
211
     * Raw Content of last curl response
212
     *
213
     * @var string
214
     */
215
    public $lastCurlResponse;
216
217
    /**
218
     * HTTP Response code of last request
219
     *
220
     * @var int
221
     */
222
    public $lastResponseCode = null;
223
224
    /**
225
     * Body data  for next curl POST operation
226
     *
227
     * @var string
228
     */
229
    public $postFields = null;
230
231
    /**
232
     * Last operation result data or message(s)
233
     *
234
     * @var array
235
     */
236
    public $lastResult = null;
237
238
    /**
239
     * Number from  @rowCount in response
240
     * @var int
241
     */
242
    public $rowCount = null;
243
244
    /**
245
     * Number from  @globalVersion
246
     * @var int
247
     */
248
    public $globalVersion = null;
249
250
    /**
251
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
252
     * @var string filter query
253
     */
254
    public $filter;
255
256
    /**
257
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
258
     * @var string
259
     */
260
    protected $action;
261
262
    /**
263
     * Pole akcí které podporuje ta která evidence
264
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
265
     * @var array
266
     */
267
    public $actionsAvailable = null;
268
269
    /**
270
     * Parmetry pro URL
271
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
272
     * @var array
273
     */
274
    public $urlParams = [
275
        'add-global-version' => ['type' => 'boolean', 'description' => 'The response will contain the global version number of the current export'],
276
        'add-row-count' => ['type' => 'boolean', 'description' => 'Adding Total Records to Output (Pagination)'],
277
        'as-gui' => ['type' => 'boolean', 'description' => 'Turns on functions that complement the GUI processing outputs'],
278
        '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.'],
279
        'authSessionId' => ['type' => 'string', 'description' => 'Authentification Session ID'],
280
        '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>'],
281
        'code-in-response' => ['type' => 'boolean', 'description' => 'The response will contain not only ID and URL for each object, but also code.'],
282
        'delimeter' => ['type' => 'string', 'description' => 'Specifies the input / output file separator in CSV format.',
283
            'example' => ';'],
284
        'detail' => ['type' => 'string', 'description' => 'Definition of the level of detail'], //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
285
        'dir' => ['type' => 'string', 'description' => 'Sorting direction.', 'example' => 'desc'],
286
        'dry-run' => ['type' => 'boolean', 'description' => 'Test run (dry-run)'], // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
287
        'encoding' => ['type' => 'string', 'description' => 'Specifies the encoding of the input / output file in CSV format.'],
288
        'export-settings' => ['type' => 'boolean', 'description' => 'Export one extra entry with current settings at the beginning'],
289
        'fail-on-warning' => ['type' => 'boolean', 'description' => 'If a warning occurs, do not save a record (Data Validation)'],
290
        'filter' => ['type' => 'string', 'description' => 'filter results by this param'],
291
        'format' => ['type' => 'string', 'description' => 'One of the compiled XSL transforms will be applied to the output XML.'],
292
        'idUcetniObdobi' => ['type' => 'string', 'description' => ''], //See: https://www.flexibee.eu/api/dokumentace/ref/stavy-uctu/
293
        'includes' => ['type' => 'string', 'description' => 'Include related detail level object ',
294
            'example' => 'faktura-vydana/stredisko'],
295
        'inDesktopApp' => ['type' => 'boolean', 'description' => 'Hide menu and navigation in html format'], // Note: Undocumented function (html only)
296
        'limit' => ['type' => 'integer', 'description' => 'number of requested results'],
297
        'mode' => ['type' => 'string', 'description' => 'Support for RubyOnRails',
298
            'example' => 'ruby'],
299
        'no-ext-ids' => ['type' => 'boolean', 'description' => 'The answer will not contain external identifiers (performance optimization)'],
300
        'no-http-errors' => ['type' => 'boolean', 'description' => 'If a 4xx error occurs while processing a request, the server sends 200 OK anyway'],
301
        'no-ids' => ['type' => 'boolean', 'description' => 'The response will not contain any primary identifiers (performance optimization). It only affects the main records.'],
302
        '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.'],
303
        'order' => ['type' => 'string', 'description' => 'Sorting records', 'example' => 'nazev@A'],
304
        'relations' => ['type' => 'string', 'description' => 'Adding session data (see detail levels) A session overview can be obtained for each record (/ relations).'],
305
        'report-lang' => ['type' => 'string', 'description' => 'The language in which to print the output when exporting to PDF',
306
            'example' => 'en'],
307
        'report-name' => ['type' => 'string', 'description' => 'The name of the printout when exporting to PDF',
308
            'example' => 'invoice'],
309
        'report-sign' => ['type' => 'string', 'description' => 'Whether the PDF should be exported electronically signed'],
310
        'skupina-stitku' => ['type' => 'string', 'description' => 'Enables grouping of labels when exporting by group (multiple labels)'],
311
        'sort' => ['type' => 'string', 'description' => 'Sorting records for ExtJS'],
312
        'start' => ['type' => 'integer', 'description' => 'Pagination'],
313
        'stitky-as-ids' => ['type' => 'boolean', 'description' => 'Labels will be exported and imported not as a code list but as a list of numeric IDs'],
314
        'use-ext-id' => ['type' => 'boolean', 'description' => 'If the object contains an external ESHOP or MY ID, use it as a bind.'],
315
        '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'],
316
        'xpath' => ['type' => 'string', 'description' => 'Apply XPATH to result',
317
            'example' => '//winstrom/adresar/email/text()'] // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
318
    ];
319
320
    /**
321
     * Session ID
322
     * @var string
323
     */
324
    public $authSessionId = null;
325
326
    /**
327
     * Token obtained during login procedure
328
     * @var string 
329
     */
330
    public $refreshToken = null;
331
332
    /**
333
     * Save 404 results to log ?
334
     * @var boolean
335
     */
336
    protected $ignoreNotFound = false;
337
338
    /**
339
     * Array of errors caused by last request
340
     * @var array
341
     */
342
    protected $errors = [];
343
344
    /**
345
     * List of Error500 reports sent
346
     * @var array
347
     */
348
    private $reports = [];
349
350
    /**
351
     * Send Error500 Report to
352
     * @var string email address
353
     */
354
    public $reportRecipient = '[email protected]';
355
356
    /**
357
     * Formating string for \DateTime::format() for datetime columns
358
     * @var string
359
     */
360
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
361
362
    /**
363
     * Formating string for \DateTime::format() for date columns
364
     * @var string
365
     */
366
    static public $DateFormat = 'Y-m-d';
367
368
    /**
369
     * Last Request response stats
370
     * @var array 
371
     */
372
    protected $responseStats = null;
373
374
    /**
375
     * Chained Objects
376
     * @var array
377
     */
378
    public $chained = [];
379
380
    /**
381
     * We Connect to server by default
382
     * @var boolean
383
     */
384
    public $offline = false;
385
386
    /**
387
     * Override cURL timeout
388
     * @var int seconds
389
     */
390
    public $timeout = null;
391
392
    /**
393
     * Columns Info for serveral evidencies
394
     * @var array 
395
     */
396
    private $columnsInfo = [];
397
398
    /**
399
     * Throw Exception in case of FlexiBee error
400
     * @var boolean 
401
     */
402
    public $throwException = false;
403
404
    /**
405
     * Class for read only interaction with FlexiBee.
406
     *
407
     * @param mixed $init default record id or initial data. See processInit()
408
     * @param array $options Connection settings and other options override
409
     */
410
    public function __construct($init = null, $options = []) {
411
        $this->init = $init;
412
413
        $this->setUp($options);
414
        $this->curlInit();
415
        if (!empty($init)) {
416
            $this->processInit($init);
417
        }
418
    }
419
420
    /**
421
     * Set internal Object name
422
     *
423
     * @param string $objectName
424
     *
425
     * @return string Jméno objektu
426
     */
427
    public function setObjectName($objectName = null) {
428
        return parent::setObjectName(is_null($objectName) ? ( empty($this->getRecordIdent()) ? $this->getObjectName() : $this->getRecordIdent() . '@' . $this->getObjectName() ) : $objectName);
429
    }
430
431
    /**
432
     * SetUp Object to be ready for work
433
     *
434
     * @param array $options Object Options ( user,password,authSessionId
435
     *                                        company,url,evidence,
436
     *                                        prefix,defaultUrlParams,debug,
437
     *                                        detail,offline,filter,ignore404
438
     *                                        timeout,companyUrl,ver,throwException
439
     */
440
    public function setUp($options = []) {
441
        if (array_key_exists('ver', $options)) {
442
            $this->protoVersion = $options['ver'];
443
            $this->prefix = 'v' . round($this->protoVersion) . '/c/';
444
        }
445
        if (array_key_exists('companyUrl', $options)) {
446
            $options = array_merge(self::companyUrlToOptions($options['companyUrl']),
447
                    $options);
448
        }
449
450
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
451
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
452
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
453
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
454
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
455
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
456
        if (!empty($this->authSessionId)) {
457
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
458
        }
459
        if (isset($options['evidence'])) {
460
            $this->setEvidence($options['evidence']);
461
        }
462
        $this->setupProperty($options, 'defaultUrlParams');
463
        if (isset($options['prefix'])) {
464
            $this->setPrefix($options['prefix']);
465
        }
466
        if (array_key_exists('detail', $options)) {
467
            $this->defaultUrlParams['detail'] = $options['detail'];
468
        }
469
        $this->setupProperty($options, 'filter');
470
        if (array_key_exists('offline', $options)) {
471
            $this->offline = (boolean) $options['offline'];
472
        }
473
474
        if (array_key_exists('ignore404', $options)) {
475
            $this->ignore404($options['ignore404']);
476
        }
477
478
        $this->setupProperty($options, 'throwException', 'FLEXIBEE_EXCEPTIONS');
479
        $this->setupProperty($options, 'debug');
480
        $this->updateApiURL();
481
    }
482
483
    /**
484
     * Convert companyUrl provided by CustomButton to options array
485
     * 
486
     * @param string $companyUrl
487
     * 
488
     * @return array Options
489
     */
490
    public static function companyUrlToOptions($companyUrl) {
491
        $urlParts = parse_url($companyUrl);
492
        $scheme = isset($urlParts['scheme']) ? $urlParts['scheme'] . '://' : '';
493
        $host = isset($urlParts['host']) ? $urlParts['host'] : '';
494
        $port = isset($urlParts['port']) ? ':' . $urlParts['port'] : '';
495
        $path = isset($urlParts['path']) ? $urlParts['path'] : '';
496
497
        $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...
498
        $options['url'] = $scheme . $host . $port;
499
        return $options;
500
    }
501
502
    /**
503
     * Get Current connection options for use in another object
504
     *
505
     * @return array usable as second constructor parameter
506
     */
507
    public function getConnectionOptions() {
508
        $conOpts = ['url' => $this->url];
509
        if (empty($this->authSessionId)) {
510
            $conOpts ['user'] = $this->user;
511
            $conOpts['password'] = $this->password;
512
        } else {
513
            $conOpts['authSessionId'] = $this->authSessionId;
514
        }
515
        $company = $this->getCompany();
516
        if (!empty($company)) {
517
            $conOpts['company'] = $company;
518
        }
519
        if (!is_null($this->timeout)) {
520
            $conOpts['timeout'] = $this->timeout;
521
        }
522
        return $conOpts;
523
    }
524
525
    /**
526
     * Export current/given configutation into Environment  
527
     * @param array $opts
528
     */
529
    public function configToEnv($opts = null) {
530
        $options = is_null($opts) ? $this->getConnectionOptions() : $opts;
531
        if (array_key_exists('url', $options)) {
532
            putenv('FLEXIBEE_URL=' . $options['URL']);
533
        }
534
        if (array_key_exists('user', $options)) {
535
            putenv('FLEXIBEE_LOGIN=' . $options['user']);
536
        }
537
        if (array_key_exists('password', $options)) {
538
            putenv('FLEXIBEE_PASSWORD=' . $options['password']);
539
        }
540
        if (array_key_exists('company', $options)) {
541
            putenv('FLEXIBEE_COMPANY=' . $options['company']);
542
        }
543
        if (array_key_exists('authSessionId', $options)) {
544
            putenv('FLEXIBEE_AUTHSESSID=' . $options['authSessionId']);
545
        }
546
    }
547
548
    /**
549
     * Inicializace CURL
550
     *
551
     * @return boolean Online Status
552
     */
553
    public function curlInit() {
554
        if ($this->offline === false) {
555
            $this->curl = \curl_init(); // create curl resource
556
            \curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
557
            \curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
558
            \curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
559
            \curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
560
            \curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
561
            \curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
562
            if (empty($this->authSessionId)) {
563
                \curl_setopt($this->curl, CURLOPT_USERPWD,
564
                        $this->user . ':' . $this->password); // set username and password
565
            }
566
            if (!is_null($this->timeout)) {
567
                \curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
568
            }
569
570
            \curl_setopt($this->curl, CURLOPT_USERAGENT, 'phpFlexiBee  v' . self::$libVersion . ' https://github.com/Spoje-NET/php-flexibee');
571
        }
572
        return !$this->offline;
573
    }
574
575
    /**
576
     * Initialise object with given data. Availble value types:
577
     *
578
     *  * 234                              - interní číslo záznamu k načtení
579
     *  * code:LOPATA                      - kód záznamu
580
     *  * BAGR                             - kód záznamu k načtení
581
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
582
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
583
     *
584
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
585
     */
586
    public function processInit($init) {
587
        if (is_integer($init)) {
588
            $this->loadFromFlexiBee($init);
589
        } elseif (is_array($init)) {
590
            $this->takeData($init);
591
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
592
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init) : $init)));
593
        } else {
594
            $this->loadFromFlexiBee($init);
595
        }
596
    }
597
598
    /**
599
     * Set Data Field value
600
     *
601
     * @param string $columnName field name
602
     * @param mixed  $value      field data value
603
     *
604
     * @return bool Success
605
     */
606
    public function setDataValue($columnName, $value) {
607
        switch ($columnName) {
608
            case 'kod':
609
                $value = self::uncode($value); //Alwyas uncode "kod" column
610
611
            default:
612
                if (is_object($value)) {
613
                    switch (get_class($value)) {
614
                        case 'DateTime':
615
                            $columnInfo = $this->getColumnInfo($columnName);
616
                            switch ($columnInfo['type']) {
617
                                case 'date':
618
                                    $value = self::dateToFlexiDate($value);
619
                                    break;
620
                                case 'datetime':
621
                                    $value = self::dateToFlexiDateTime($value);
622
                                    break;
623
                            }
624
                            break;
625
                    }
626
                }
627
                $result = parent::setDataValue($columnName, $value);
628
                break;
629
        }
630
        return $result;
631
    }
632
633
    /**
634
     * PHP Date object to FlexiBee date format
635
     * 
636
     * @param \DateTime $date
637
     */
638
    public static function dateToFlexiDate($date) {
639
        return $date->format(self::$DateFormat);
640
    }
641
642
    /**
643
     * PHP Date object to FlexiBee date format
644
     * 
645
     * @param \DateTime $dateTime
646
     */
647
    public static function dateToFlexiDateTime($dateTime) {
648
        return $dateTime->format(self::$DateTimeFormat);
649
    }
650
651
    /**
652
     * Set URL prefix
653
     *
654
     * @param string $prefix
655
     */
656
    public function setPrefix($prefix) {
657
        switch ($prefix) {
658
            case 'a': //Access
659
            case 'c': //Company
660
            case 'u': //User
661
            case 'g': //License Groups
662
            case 'admin':
663
            case 'status':
664
            case 'login-logout':
665
                $this->prefix = '/' . $prefix . '/';
666
                break;
667
            case null:
668
            case '':
669
            case '/':
670
                $this->prefix = '';
671
                break;
672
            default:
673
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
674
        }
675
    }
676
677
    /**
678
     * Set communication format.
679
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
680
     *
681
     * @param string $format
682
     * 
683
     * @return boolean format is availble
684
     */
685
    public function setFormat($format) {
686
        $result = true;
687
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
688
            if (array_key_exists($format, array_flip(Formats::$$this->evidence)) === false) {
689
                $result = false;
690
            }
691
        }
692
        if ($result === true) {
693
            $this->format = $format;
694
            $this->updateApiURL();
695
        }
696
        return $result;
697
    }
698
699
    /**
700
     * Nastaví Evidenci pro Komunikaci.
701
     * Set evidence for communication
702
     *
703
     * @param string $evidence evidence pathName to use
704
     * 
705
     * @return boolean evidence switching status
706
     */
707
    public function setEvidence($evidence) {
708
        switch ($this->prefix) {
709
            case '/c/':
710
                if ($this->debug === true) {
711
                    if (array_key_exists($evidence, EvidenceList::$name)) {
712
                        $this->evidence = $evidence;
713
                        $result = true;
714
                    } else {
715
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
716
                                        $evidence));
717
                    }
718
                } else {
719
                    $this->evidence = $evidence;
720
                    $result = true;
721
                }
722
                break;
723
            default:
724
                $this->evidence = $evidence;
725
                $result = true;
726
                break;
727
        }
728
        $this->updateApiURL();
729
        $this->evidenceInfo = $this->getEvidenceInfo();
730
        return $result;
731
    }
732
733
    /**
734
     * Vrací právě používanou evidenci pro komunikaci
735
     * Obtain current used evidence
736
     *
737
     * @return string
738
     */
739
    public function getEvidence() {
740
        return $this->evidence;
741
    }
742
743
    /**
744
     * Set used company.
745
     * Nastaví Firmu.
746
     *
747
     * @param string $company
748
     */
749
    public function setCompany($company) {
750
        $this->company = $company;
751
    }
752
753
    /**
754
     * Obtain company now used
755
     * Vrací právě používanou firmu
756
     *
757
     * @return string
758
     */
759
    public function getCompany() {
760
        return $this->company;
761
    }
762
763
    /**
764
     * Vrací název evidence použité v odpovědích z FlexiBee
765
     *
766
     * @return string
767
     */
768
    public function getResponseEvidence() {
769
        switch ($this->evidence) {
770
            case 'c':
771
                $evidence = 'company';
772
                break;
773
            case 'evidence-list':
774
                $evidence = 'evidence';
775
                break;
776
            default:
777
                $evidence = $this->getEvidence();
778
                break;
779
        }
780
        return $evidence;
781
    }
782
783
    /**
784
     * Převede rekurzivně Objekt na pole.
785
     *
786
     * @param object|array $object
787
     *
788
     * @return array
789
     */
790
    public static function object2array($object) {
791
        $result = null;
792
        if (is_object($object)) {
793
            $objectData = get_object_vars($object);
794
            if (is_array($objectData) && count($objectData)) {
795
                $result = array_map('self::object2array', $objectData);
796
            }
797
        } else {
798
            if (is_array($object)) {
799
                foreach ($object as $item => $value) {
800
                    $result[$item] = self::object2array($value);
801
                }
802
            } else {
803
                $result = $object;
804
            }
805
        }
806
807
        return $result;
808
    }
809
810
    /**
811
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
812
     *
813
     * @param object|array $object
814
     *
815
     * @return array
816
     */
817
    public static function objectToID($object) {
818
        $resultID = null;
819
        if (is_object($object) && method_exists($object, '__toString')
820
        ) {
821
            $resultID = $object->__toString();
822
        } else {
823
            if (is_array($object)) {
824
                foreach ($object as $item => $value) {
825
                    $resultID[$item] = self::objectToID($value);
826
                }
827
            } else { //String
828
                $resultID = $object;
829
            }
830
        }
831
832
        return $resultID;
833
    }
834
835
    /**
836
     * Return basic URL for used Evidence
837
     *
838
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
839
     *
840
     * @return string Evidence URL
841
     */
842
    public function getEvidenceURL() {
843
        $evidenceUrl = $this->url . $this->prefix . $this->company;
844
        $evidence = $this->getEvidence();
845
        if (!empty($evidence)) {
846
            $evidenceUrl .= '/' . $evidence;
847
        }
848
        return $evidenceUrl;
849
    }
850
851
    /**
852
     * Add suffix to Evidence URL
853
     *
854
     * @param string $urlSuffix
855
     *
856
     * @return string
857
     */
858
    public function evidenceUrlWithSuffix($urlSuffix) {
859
        $evidenceUrl = $this->getEvidenceUrl();
860
        if (!empty($urlSuffix)) {
861
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0] != '?')) {
862
                $evidenceUrl .= '/';
863
            }
864
            $evidenceUrl .= $urlSuffix;
865
        }
866
        return $evidenceUrl;
867
    }
868
869
    /**
870
     * Update $this->apiURL
871
     */
872
    public function updateApiURL() {
873
        $this->apiURL = $this->getEvidenceURL();
874
        $rowIdentifier = $this->getRecordIdent();
875
        if (empty($rowIdentifier)) {
876
            $rowIdentifier = $this->getRecordCode();
877
            if (empty($rowIdentifier)) {
878
                $rowIdentifier = $this->getExternalID();
879
            }
880
        }
881
        if (!empty($rowIdentifier)) {
882
            $this->apiURL .= '/' . self::urlEncode($rowIdentifier);
883
        }
884
        $this->apiURL .= '.' . $this->format;
885
    }
886
887
    /*
888
     * Add Default Url params to given url if not overrided
889
     *
890
     * @param string $urlRaw
891
     *
892
     * @return string url with default params added
893
     */
894
895
    public function addDefaultUrlParams($urlRaw) {
896
        return \Ease\Functions::addUrlParams($urlRaw, $this->defaultUrlParams,
897
                        false);
898
    }
899
900
    /**
901
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
902
     *
903
     * @param string $urlSuffix část URL za identifikátorem firmy.
904
     * @param string $method    HTTP/REST metoda
905
     * @param string $format    Requested format
906
     * 
907
     * @return array|boolean Výsledek operace
908
     */
909
    public function performRequest($urlSuffix = null, $method = 'GET',
910
            $format = null) {
911
        $this->rowCount = null;
912
        $this->responseStats = [];
913
        $this->errors = [];
914
915
        if (preg_match('/^http/', $urlSuffix)) {
916
            $url = $urlSuffix;
917
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
918
            $url = $this->url . $urlSuffix;
919
        } else {
920
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
921
        }
922
923
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
924
                $method, $format);
925
926
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
927
                                $this->responseFormat), $responseCode);
928
    }
929
930
    /**
931
     * Parse Raw FlexiBee response in several formats
932
     *
933
     * @param string $responseRaw raw response body
934
     * @param string $format      Raw Response format json|xml|etc
935
     *
936
     * @return array
937
     */
938
    public function rawResponseToArray($responseRaw, $format) {
939
        $responseDecoded = [];
940
        if (!empty(trim($responseRaw))) {
941
            switch ($format) {
942
                case 'json':
943
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
944
                    break;
945
                case 'xml':
946
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
947
                    break;
948
                case 'txt':
949
                default:
950
                    $responseDecoded = [$this->lastCurlResponse];
951
                    break;
952
            }
953
        }
954
        return $responseDecoded;
955
    }
956
957
    /**
958
     * Convert FlexiBee Response JSON to Array
959
     *
960
     * @param string $rawJson
961
     *
962
     * @return array
963
     */
964
    public function rawJsonToArray($rawJson) {
965
        $responseDecoded = json_decode($rawJson, true, 10);
966
        $decodeError = json_last_error_msg();
967
        if ($decodeError == 'No error') {
968
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
969
                $responseDecoded = $responseDecoded[$this->nameSpace];
970
            }
971
        } else {
972
            if ($this->debug) {
973
                $this->addStatusMessage('JSON Decoder: ' . $decodeError, 'error');
974
                $this->addStatusMessage($rawJson, 'debug');
975
            }
976
        }
977
        return $responseDecoded;
978
    }
979
980
    /**
981
     * Convert FlexiBee Response XML to Array
982
     *
983
     * @param string $rawXML
984
     *
985
     * @return array
986
     */
987
    public function rawXmlToArray($rawXML) {
988
        return self::xml2array($rawXML);
989
    }
990
991
    /**
992
     * Parse Response array
993
     *
994
     * @param array $responseDecoded
995
     * @param int $responseCode Request Response Code
996
     *
997
     * @return array main data part of response
998
     */
999
    public function parseResponse($responseDecoded, $responseCode) {
1000
        $mainResult = null;
1001
        switch ($responseCode) {
1002
            case 201: //We do not care about Success Write here
1003
                break;
1004
            case 200: //Success Read
1005
1006
                if (is_array($responseDecoded)) {
1007
                    if (isset($responseDecoded['@rowCount'])) {
1008
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
1009
                    }
1010
                    if (isset($responseDecoded['@globalVersion'])) {
1011
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
1012
                    }
1013
1014
                    $mainResult = $this->unifyResponseFormat($responseDecoded);
1015
1016
                    if (array_key_exists('stats', $responseDecoded)) {
1017
                        $this->responseStats = $responseDecoded['stats'];
1018
                    } elseif (!empty($mainResult)) {
1019
                        if (array_key_exists('success', $mainResult) && ($mainResult['success'] == 'false')) {
1020
                            $this->responseStats = ['read' => 0];
1021
                        } elseif (array_key_exists('properties', $mainResult)) {
1022
                            $this->responseStats = ['read' => 1];
1023
                        } else {
1024
                            $responseEvidence = $this->getResponseEvidence();
1025
                            if (!empty($this->rowCount)) {
1026
                                $this->responseStats = ['read' => $this->rowCount];
1027
                            } elseif (array_key_exists($responseEvidence,
1028
                                            $mainResult)) {
1029
                                $this->responseStats = ['read' => count($mainResult[$responseEvidence])];
1030
                            } else {
1031
                                $this->responseStats = ['read' => count($mainResult)];
1032
                            }
1033
                        }
1034
                    }
1035
                } else {
1036
                    $mainResult = $responseDecoded;
1037
                }
1038
1039
                $this->lastResult = $mainResult;
1040
                break;
1041
1042
            case 500: // Internal Server Error
1043
                if ($this->debug === true) {
1044
                    $this->error500Reporter($responseDecoded);
1045
                }
1046
            case 404: // Page not found
1047
                if ($this->ignoreNotFound === true) {
1048
                    break;
1049
                }
1050
            case 400: //Bad Request parameters
1051
            default: //Something goes wrong
1052
                if (is_array($responseDecoded)) {
1053
                    $this->parseError($responseDecoded);
1054
                }
1055
1056
                if ($this->throwException === true) {
1057
                    throw new \Ease\Exception(json_encode($this->getErrors()), $this->lastResponseCode);
1058
                } else {
1059
                    $this->addStatusMessage($this->lastResponseCode . ': ' . $this->curlInfo['url'],
1060
                            'warning');
1061
                    $this->logResult($responseDecoded, $this->curlInfo['url']);
1062
                }
1063
                break;
1064
        }
1065
        return $mainResult;
1066
    }
1067
1068
    /**
1069
     * Parse error message response
1070
     *
1071
     * @param array $responseDecoded
1072
     * 
1073
     * @return int number of errors processed
1074
     */
1075
    public function parseError(array $responseDecoded) {
1076
        if (array_key_exists('success', $responseDecoded)) {
1077
            $this->errors = [['message' => array_key_exists('message', $responseDecoded) ? $responseDecoded['message'] : '']];
1078
        } else {
1079
            throw new \Ease\Exception('Unparsed error: ' . $this->lastCurlResponse);
1080
        }
1081
        return count($this->errors);
1082
    }
1083
1084
    /**
1085
     * Vykonej HTTP požadavek
1086
     *
1087
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1088
     * @param string $url    URL požadavku
1089
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1090
     * @param string $format požadovaný formát komunikace
1091
     * 
1092
     * @return int HTTP Response CODE
1093
     */
1094
    public function doCurlRequest($url, $method, $format = null) {
1095
        if (is_null($format)) {
1096
            $format = $this->format;
1097
        }
1098
        curl_setopt($this->curl, CURLOPT_URL, $url);
1099
// Nastavení samotné operace
1100
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1101
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1102
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1103
1104
        $httpHeaders = $this->defaultHttpHeaders;
1105
1106
        $formats = Formats::bySuffix();
1107
1108
        if (!isset($httpHeaders['Accept'])) {
1109
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1110
        }
1111
        if (!isset($httpHeaders['Content-Type'])) {
1112
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1113
        }
1114
1115
        array_walk($httpHeaders, function (&$value,$header) { $value = $header .': '.$value; } );
1116
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeaders);
1117
1118
// Proveď samotnou operaci
1119
        $this->lastCurlResponse = curl_exec($this->curl);
1120
        $this->curlInfo = curl_getinfo($this->curl);
1121
        $this->curlInfo['when'] = microtime();
1122
        $this->curlInfo['request_headers'] = $httpHeaders;
1123
        $this->responseFormat = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1124
                $url);
1125
        $this->lastResponseCode = $this->curlInfo['http_code'];
1126
        $this->lastCurlError = curl_error($this->curl);
1127
        if (strlen($this->lastCurlError)) {
1128
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1129
                            $this->lastResponseCode, $this->lastCurlError), 'error');
1130
        }
1131
1132
        if ($this->debug === true) {
1133
            $this->saveDebugFiles();
1134
        }
1135
        return $this->lastResponseCode;
1136
    }
1137
1138
    /**
1139
     * Obtain json for application/json
1140
     * 
1141
     * @param string $contentType
1142
     * @param string $url
1143
     * 
1144
     * @return string response format
1145
     */
1146
    public function contentTypeToResponseFormat($contentType, $url = null) {
1147
        if (!empty($url)) {
1148
            $url = parse_url($url, PHP_URL_PATH);
1149
        }
1150
1151
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1152
                        strpos($contentType, ';')) : $contentType;
1153
1154
        switch ($url) {
1155
            case '/login-logout/login';
1156
                $responseFormat = 'json';
1157
                break;
1158
            default :
1159
                switch ($contentTypeClean) {
1160
                    case 'text/javascript':
1161
                        $responseFormat = 'js';
1162
                        break;
1163
1164
                    default:
1165
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1166
                        break;
1167
                }
1168
                break;
1169
        }
1170
1171
        return $responseFormat;
1172
    }
1173
1174
    /**
1175
     * Nastaví druh prováděné akce.
1176
     *
1177
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1178
     * @param string $action
1179
     * 
1180
     * @return boolean
1181
     */
1182
    public function setAction($action) {
1183
        $result = false;
1184
        $actionsAvailable = $this->getActionsInfo();
1185
        if (is_array($actionsAvailable) && array_key_exists($action,
1186
                        $actionsAvailable)) {
1187
            $this->action = $action;
1188
            $result = true;
1189
        }
1190
        return $result;
1191
    }
1192
1193
    /**
1194
     * Convert XML to array.
1195
     *
1196
     * @param string $xml
1197
     *
1198
     * @return array
1199
     */
1200
    public static function xml2array($xml) {
1201
        $arr = [];
1202
        if (!empty($xml)) {
1203
            if (is_string($xml)) {
1204
                $xml = simplexml_load_string($xml);
1205
            }
1206
            foreach ($xml->attributes() as $a) {
1207
                $arr['@' . $a->getName()] = strval($a);
1208
            }
1209
            foreach ($xml->children() as $r) {
1210
                if (count($r->children()) == 0) {
1211
                    $arr[$r->getName()] = strval($r);
1212
                } else {
1213
                    $arr[$r->getName()][] = self::xml2array($r);
1214
                }
1215
            }
1216
        }
1217
        return $arr;
1218
    }
1219
1220
    /**
1221
     * Odpojení od FlexiBee.
1222
     */
1223
    public function disconnect() {
1224
        if (is_resource($this->curl)) {
1225
            curl_close($this->curl);
1226
        }
1227
        $this->curl = null;
1228
    }
1229
1230
    /**
1231
     * Disconnect CURL befere pass away
1232
     */
1233
    public function __destruct() {
1234
        $this->disconnect();
1235
    }
1236
1237
    /**
1238
     * Načte řádek dat z FlexiBee.
1239
     *
1240
     * @param int $recordID id požadovaného záznamu
1241
     *
1242
     * @return array
1243
     */
1244
    public function getFlexiRow($recordID) {
1245
        $record = null;
1246
        $response = $this->performRequest($this->evidence . '/' . $recordID . '.json');
1247
        if (isset($response[$this->evidence])) {
1248
            $record = $response[$this->evidence][0];
1249
        }
1250
1251
        return $record;
1252
    }
1253
1254
    /**
1255
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1256
     *
1257
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1258
     * @param array $conditions pole podmínek   - rendrují se do ()
1259
     * @param array $urlParams  pole parametrů  - rendrují za ?
1260
     */
1261
    public function extractUrlParams(&$conditions, &$urlParams) {
1262
        foreach (array_keys($this->urlParams) as $urlParam) {
1263
            if (isset($conditions[$urlParam])) {
1264
                \Ease\Functions::divDataArray($conditions, $urlParams, $urlParam);
1265
            }
1266
        }
1267
    }
1268
1269
    /**
1270
     * convert unicode to entities for use with FlexiBee queries
1271
     *
1272
     * @param string $urlRaw
1273
     * 
1274
     * @return string
1275
     */
1276
    public static function urlEncode($urlRaw) {
1277
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1278
    }
1279
1280
    /**
1281
     * Načte data z FlexiBee.
1282
     *
1283
     * @param string $suffix     dotaz
1284
     * @param string|array       $conditions Custom filters or modifiers
1285
     *
1286
     * @return array Data obtained
1287
     */
1288
    public function getFlexiData($suffix = null, $conditions = null) {
1289
        $finalUrl = '';
1290
        $evidenceToRestore = null;
1291
        $urlParams = $this->defaultUrlParams;
1292
1293
        if (!empty($conditions)) {
1294
            if (is_array($conditions)) {
1295
                $this->extractUrlParams($conditions, $urlParams);
1296
                if (array_key_exists('evidence', $conditions) && is_null($this->getColumnInfo('evidence'))) {
1297
                    $evidenceToRestore = $this->getEvidence();
1298
                    $this->setEvidence($conditions['evidence']);
1299
                    unset($conditions['evidence']);
1300
                }
1301
                $conditions = $this->flexiUrl($conditions);
1302
            }
1303
1304
            if (strlen($conditions) && ($conditions[0] != '/')) {
1305
                $conditions = '(' . self::urlEncode($conditions) . ')';
1306
            }
1307
        }
1308
1309
        if (strlen($suffix) && ($suffix != '$sum')) {
1310
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1311
                $finalUrl = $suffix;
1312
            } else {
1313
                if (preg_match('/^(code|ext):(.*)/', $suffix)) {
1314
                    $finalUrl = self::urlizeId($suffix);
1315
                } else {
1316
                    $finalUrl = $suffix;
1317
                }
1318
            }
1319
        }
1320
1321
        $finalUrl .= $conditions;
1322
1323
        if ($suffix == '$sum') {
1324
            $finalUrl .= '/$sum';
1325
        }
1326
1327
        if (!empty($urlParams)) {
1328
            if (strstr($finalUrl, '?')) {
1329
                $finalUrl .= '&';
1330
            } else {
1331
                $finalUrl .= '?';
1332
            }
1333
            $finalUrl .= http_build_query(array_map(function($a) {
1334
                        return is_bool($a) ? ($a ? 'true' : 'false' ) : $a;
1335
                    }, $urlParams), null, '&', PHP_QUERY_RFC3986);
1336
        }
1337
1338
        $transactions = $this->performRequest($finalUrl, 'GET');
1339
        $responseEvidence = $this->getResponseEvidence();
1340
        if (is_array($transactions) && array_key_exists($responseEvidence,
1341
                        $transactions)) {
1342
            $result = $transactions[$responseEvidence];
1343
            if ((count($result) == 1) && empty(current($result))) {
1344
                $result = []; // Response is empty Array
1345
            }
1346
        } else {
1347
            $result = $transactions;
1348
        }
1349
        if (!is_null($evidenceToRestore)) {
1350
            $this->setEvidence($evidenceToRestore);
1351
        }
1352
        return $result;
1353
    }
1354
1355
    /**
1356
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1357
     * Read FlexiBee record and store it inside od object
1358
     *
1359
     * @param int|string $id ID or conditions
1360
     *
1361
     * @return int počet načtených položek
1362
     */
1363
    public function loadFromFlexiBee($id = null) {
1364
        $data = [];
1365
        if (is_null($id)) {
1366
            $id = $this->getMyKey();
1367
        }
1368
        $flexidata = $this->getFlexiData($this->getEvidenceUrl() . '/' . self::urlizeId($id));
1369
        if ($this->lastResponseCode == 200) {
1370
            $this->apiURL = $this->curlInfo['url'];
1371
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1372
                $data = current($flexidata);
1373
            }
1374
        }
1375
        return $this->takeData($data);
1376
    }
1377
1378
    /**
1379
     * Reload current record from FlexiBee
1380
     * 
1381
     * @return boolean 
1382
     */
1383
    public function reload() {
1384
        $id = $this->getRecordIdent();
1385
        $this->dataReset();
1386
        $this->loadFromFlexiBee($id);
1387
        return $this->lastResponseCode == 200;
1388
    }
1389
1390
    /**
1391
     * Set Filter code for requests
1392
     *
1393
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1394
     *
1395
     * @param array|string $filter filter formula or ['key'=>'value']
1396
     *
1397
     * @return string Filter code
1398
     */
1399
    public function setFilter($filter) {
1400
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1401
    }
1402
1403
    /**
1404
     * Převede data do Json formátu pro FlexiBee.
1405
     * Convert data to FlexiBee like Json format
1406
     *
1407
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1408
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1409
     *
1410
     * @param array $data    object data
1411
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1412
     *
1413
     * @return string
1414
     */
1415
    public function getJsonizedData($data = null, $options = 0) {
1416
        if (is_null($data)) {
1417
            $data = $this->getData();
1418
        }
1419
1420
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1421
                $this->getDataForJSON($data));
1422
        $jsonRaw = json_encode([$this->nameSpace => $dataToJsonize],
1423
                $options);
1424
1425
        return $jsonRaw;
1426
    }
1427
1428
    /**
1429
     * Get Data Fragment specific for current object
1430
     *
1431
     * @param array $data
1432
     *
1433
     * @return array
1434
     */
1435
    public function getDataForJSON($data = null) {
1436
        if (is_null($data)) {
1437
            $data = $this->getData();
1438
        }
1439
1440
        $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...
1441
1442
        if (!is_null($this->action)) {
1443
            $dataForJson[$this->evidence . '@action'] = $this->action;
1444
            $this->action = null;
1445
        }
1446
1447
        if (!is_null($this->filter)) {
1448
            $dataForJson[$this->evidence . '@filter'] = $this->filter;
1449
        }
1450
1451
1452
        foreach ($this->chained as $chained) {
1453
            $chainedData = $chained->getDataForJSON();
1454
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1455
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1456
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1457
                        $dataBackup = $dataForJson[$chainedItemEvidence];
1458
                        $dataForJson[$chainedItemEvidence] = [];
1459
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1460
                    }
1461
                    if (array_key_exists(0, $chainedItemData)) {
1462
                        foreach ($chainedItemData as $chainedItem) {
1463
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1464
                        }
1465
                    } else {
1466
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1467
                    }
1468
                } else {
1469
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1470
                }
1471
            }
1472
        }
1473
1474
1475
        return $dataForJson;
1476
    }
1477
1478
    /**
1479
     * Join another FlexiPeeHP Object
1480
     *
1481
     * @param FlexiBeeRO $object
1482
     *
1483
     * @return boolean adding to stack success
1484
     */
1485
    public function join(&$object) {
1486
        $result = true;
1487
        if (method_exists($object, 'getDataForJSON')) {
1488
            $this->chained[] = $object;
1489
        } else {
1490
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1491
        }
1492
1493
        return $result;
1494
    }
1495
1496
    /**
1497
     * Prepare record ID to use in URL
1498
     * 
1499
     * @param mixed $id
1500
     * 
1501
     * @return string id ready for use in URL
1502
     */
1503
    public static function urlizeId($id) {
1504
        if (is_array($id)) {
1505
            $id = rawurlencode('(' . self::flexiUrl($id) . ')');
1506
        } else if (preg_match('/^ext:/', $id)) {
1507
            $id = self::urlEncode($id);
1508
        } else if (preg_match('/^code:/', $id)) {
1509
            $id = self::code(self::urlEncode(self::uncode($id)));
1510
        }
1511
        return $id;
1512
    }
1513
1514
    /**
1515
     * Test if given record ID exists in FlexiBee.
1516
     *
1517
     * @param mixed $identifer presence state
1518
     *
1519
     * @return boolean
1520
     */
1521
    public function idExists($identifer = null) {
1522
        if (is_null($identifer)) {
1523
            $identifer = $this->getMyKey();
1524
        }
1525
        $ignorestate = $this->ignore404();
1526
        $this->ignore404(true);
1527
        $cands = $this->getFlexiData(null,
1528
                [
1529
                    'detail' => 'custom:' . $this->getKeyColumn(),
1530
                    $this->getKeyColumn() => $identifer
1531
        ]);
1532
        $this->ignore404($ignorestate);
1533
        return ($this->lastResponseCode == 200) && !empty($cands);
1534
    }
1535
1536
    /**
1537
     * Test if given record exists in FlexiBee.
1538
     *
1539
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1540
     * 
1541
     * @return boolean Record presence status
1542
     */
1543
    public function recordExists($data = []) {
1544
1545
        if (empty($data)) {
1546
            $data = $this->getData();
1547
        }
1548
        $ignorestate = $this->ignore404();
1549
        $this->ignore404(true);
1550
        $keyColumn = $this->getKeyColumn();
1551
        $res = $this->getColumnsFromFlexibee([$keyColumn],
1552
                is_array($data) ? $data : [$keyColumn => $data]);
1553
1554
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false')) || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1555
            $found = false;
1556
        } else {
1557
            $found = true;
1558
        }
1559
        $this->ignore404($ignorestate);
1560
        return $found;
1561
    }
1562
1563
    /**
1564
     * Vrací z FlexiBee sloupečky podle podmínek.
1565
     *
1566
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1567
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1568
     *                                     sloupečku
1569
     * @return array
1570
     */
1571
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1572
        if (is_int($conditions)) {
1573
            $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...
1574
        }
1575
1576
        $flexiData = $this->getFlexiData('', $conditions);
1577
1578
        if (!is_null($indexBy)) {
1579
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData);
1580
        }
1581
1582
        return $flexiData;
1583
    }
1584
1585
    /**
1586
     * Vrací z FlexiBee sloupečky podle podmínek.
1587
     *
1588
     * @param string|string[] $columnsList seznam položek nebo úrověň detailu: id|summary|full
1589
     * @param array           $conditions  pole podmínek nebo ID záznamu
1590
     * @param string          $indexBy     Sloupeček podle kterého indexovat záznamy
1591
     *
1592
     * @return array
1593
     */
1594
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1595
            $indexBy = null) {
1596
        $detail = 'full';
1597
        switch (gettype($columnsList)) {
1598
            case 'integer': //Record ID
1599
                $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...
1600
            case 'array': //Few Conditions
1601
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1602
                                $columnsList)) {
1603
                    $columnsList[] = $indexBy;
1604
                }
1605
                $columns = implode(',', array_unique($columnsList));
1606
                $detail = 'custom:' . $columns;
1607
            default:
1608
                switch ($columnsList) {
1609
                    case 'id':
1610
                        $detail = 'id';
1611
                        break;
1612
                    case 'summary':
1613
                        $detail = 'summary';
1614
                        break;
1615
                    default:
1616
                        break;
1617
                }
1618
                break;
1619
        }
1620
1621
        $conditions['detail'] = $detail;
1622
1623
        $flexiData = $this->getFlexiData(null, $conditions);
1624
1625
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1626
                        $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1627
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData, $indexBy);
1628
        }
1629
1630
        return $flexiData;
1631
    }
1632
1633
    /**
1634
     * Vrací kód záznamu.
1635
     * Obtain record CODE
1636
     *
1637
     * @param mixed $data
1638
     *
1639
     * @return string
1640
     */
1641
    public function getKod($data = null, $unique = true) {
1642
        $kod = null;
1643
1644
        if (is_null($data)) {
1645
            $data = $this->getData();
1646
        }
1647
1648
        if (is_string($data)) {
1649
            $data = [$this->nameColumn => $data];
1650
        }
1651
1652
        if (isset($data['kod'])) {
1653
            $kod = $data['kod'];
1654
        } else {
1655
            if (isset($data[$this->nameColumn])) {
1656
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1657
                        \Ease\Functions::rip($data[$this->nameColumn]));
1658
            } else {
1659
                if (isset($data[$this->keyColumn])) {
1660
                    $kod = \Ease\Functions::rip($data[$this->keyColumn]);
1661
                }
1662
            }
1663
            $kod = substr($kod, 0, 20);
1664
        }
1665
1666
        if (!strlen($kod)) {
1667
            $kod = 'NOTSET';
1668
        }
1669
1670
        if (strlen($kod) > 18) {
1671
            $kodfinal = strtoupper(substr($kod, 0, 18));
1672
        } else {
1673
            $kodfinal = strtoupper($kod);
1674
        }
1675
1676
        if ($unique) {
1677
            $counter = 0;
1678
            if (!empty($this->codes) && count($this->codes)) {
1679
                foreach ($this->codes as $codesearch => $keystring) {
1680
                    if (strstr($codesearch, $kodfinal)) {
1681
                        ++$counter;
1682
                    }
1683
                }
1684
            }
1685
            if ($counter) {
1686
                $kodfinal = $kodfinal . $counter;
1687
            }
1688
1689
            $this->codes[$kodfinal] = $kod;
1690
        }
1691
1692
        return self::code($kodfinal);
1693
    }
1694
1695
    /**
1696
     * Write Operation Result.
1697
     *
1698
     * @param array  $resultData
1699
     * @param string $url        URL
1700
     * 
1701
     * @return boolean Log save success
1702
     */
1703
    public function logResult($resultData = null, $url = null) {
1704
        $logResult = false;
1705
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1706
            $this->addStatusMessage('Error ' . $this->lastResponseCode . ': ' . urldecode($url) . (array_key_exists('message',
1707
                            $resultData) ? ' ' . $resultData['message'] : ''), 'warning');
1708
            unset($url);
1709
        }
1710
        if (is_null($resultData)) {
1711
            $resultData = $this->lastResult;
1712
        }
1713
        if (isset($url)) {
1714
            \Ease\Shared::logger()->addToLog($this, $this->lastResponseCode . ':' . urldecode($url));
1715
        }
1716
1717
        if (isset($resultData['results'])) {
1718
            if ($resultData['success'] == 'false') {
1719
                $status = 'error';
1720
            } else {
1721
                $status = 'success';
1722
            }
1723
            foreach ($resultData['results'] as $result) {
1724
                if (isset($result['request-id'])) {
1725
                    $rid = $result['request-id'];
1726
                } else {
1727
                    $rid = '';
1728
                }
1729
                if (isset($result['errors'])) {
1730
                    foreach ($result['errors'] as $error) {
1731
                        $message = $error['message'];
1732
                        if (isset($error['for'])) {
1733
                            $message .= ' for: ' . $error['for'];
1734
                        }
1735
                        if (isset($error['value'])) {
1736
                            $message .= ' value:' . $error['value'];
1737
                        }
1738
                        if (isset($error['code'])) {
1739
                            $message .= ' code:' . $error['code'];
1740
                        }
1741
                        $this->addStatusMessage($rid . ': ' . $message, $status);
1742
                    }
1743
                }
1744
            }
1745
        }
1746
        return $logResult;
1747
    }
1748
1749
    /**
1750
     * Save RAW Curl Request & Response to files in Temp directory
1751
     */
1752
    public function saveDebugFiles() {
1753
        $tmpdir = sys_get_temp_dir();
1754
        $fname = $this->evidence . '-' . $this->curlInfo['when'] . '.' . $this->format;
1755
        $reqname = $tmpdir . '/request-' . $fname;
1756
        $respname = $tmpdir . '/response-' . $fname;
1757
        $header = '# ' . (new \DateTime())->format('Y-m-d\TH:i:s.u') . ' ' . $this->curlInfo['url'] . ' (' . urldecode($this->curlInfo['url']) . ')';
1758
        if (file_put_contents($reqname, $header . "\n" . $this->postFields)) {
1759
            $this->addStatusMessage($reqname, 'debug');
1760
        }
1761
        if (file_put_contents($respname, $header . "\n" . $this->lastCurlResponse)) {
1762
            $this->addStatusMessage($respname, 'debug');
1763
        }
1764
    }
1765
1766
    /**
1767
     * Připraví data pro odeslání do FlexiBee
1768
     *
1769
     * @param string $data
1770
     */
1771
    public function setPostFields($data) {
1772
        $this->postFields = $data;
1773
    }
1774
1775
    /**
1776
     * Get Content ready to be send as POST body
1777
     * @return string
1778
     */
1779
    public function getPostFields() {
1780
        return $this->postFields;
1781
    }
1782
1783
    /**
1784
     * Generuje fragment url pro filtrování.
1785
     *
1786
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1787
     *
1788
     * @param array  $data   key=>values; value can bee class DatePeriod, DateTime or Array
1789
     * @param string $joiner default and/or
1790
     * @param string $defop  default operator
1791
     *
1792
     * @return string
1793
     */
1794
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq') {
1795
        $parts = [];
1796
1797
        foreach ($data as $column => $value) {
1798
            if (!is_numeric($column)) {
1799
                if (is_integer($data[$column]) || is_float($data[$column])) {
1800
                    $parts[$column] = $column . ' eq \'' . $data[$column] . '\'';
1801
                } elseif (is_bool($data[$column])) {
1802
                    $parts[$column] = $data[$column] ? $column . ' eq true' : $column . ' eq false';
1803
                } elseif (is_null($data[$column])) {
1804
                    $parts[$column] = $column . " is null";
1805
                } elseif (is_array($data[$column])) {
1806
                    $parts[$column] = $column . " in (" . implode(',',
1807
                                    array_map(function($a, $column) {
1808
                                        return $column == 'stitky' ? "'" . self::code($a) . "'" : "'$a'";
1809
                                    }, $data[$column],
1810
                                            array_fill(0, count($data[$column]), $column))) . ")";
1811
                } elseif (is_object($data[$column])) {
1812
                    switch (get_class($data[$column])) {
1813
                        case 'DatePeriod':
1814
                            $parts[$column] = $column . " between '" . $data[$column]->getStartDate()->format(self::$DateFormat) . "' '" . $data[$column]->getEndDate()->format(self::$DateFormat) . "'";
1815
                            break;
1816
                        case 'DateTime':
1817
                            $parts[$column] = $column . " eq '" . $data[$column]->format(self::$DateFormat) . "'";
1818
                            break;
1819
                        default:
1820
                            $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1821
                            break;
1822
                    }
1823
                } else {
1824
                    switch ($value) {
1825
                        case '!null':
1826
                            $parts[$column] = $column . " is not null";
1827
                            break;
1828
                        case 'is empty':
1829
                        case 'is not empty':
1830
                        case 'is true':
1831
                        case 'is false':
1832
                            $parts[$column] = $column . ' ' . $value;
1833
                            break;
1834
                        default:
1835
                            $condParts = explode(' ', trim($value));
1836
                            switch ($condParts[0]) {
1837
                                case '<>':
1838
                                case '!=':
1839
                                case 'ne':
1840
                                case 'neq':
1841
                                case '<':
1842
                                case 'lt':
1843
                                case '<=':
1844
                                case 'lte':
1845
                                case '>':
1846
                                case 'gt':
1847
                                case '>=':
1848
                                case 'gte':
1849
                                case 'like':
1850
                                case 'begins':
1851
                                case 'between':
1852
                                case 'ends':
1853
                                    if (count($condParts) == 1) {
1854
                                        $parts[$column] = $column .= ' ' . $value;
1855
                                    } else {
1856
                                        $parts[$column] = $column .= ' ' . $condParts[0] . " '" . $condParts[1] . "'";
1857
                                    }
1858
                                    break;
1859
                                default:
1860
                                    if ($column == 'stitky') {
1861
                                        $parts[$column] = $column . "='" . self::code($data[$column]) . "'";
1862
                                    } else {
1863
                                        $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1864
                                    }
1865
                                    break;
1866
                            }
1867
1868
                            break;
1869
                    }
1870
                }
1871
            } else {
1872
                $parts[] = $value;
1873
            }
1874
        }
1875
        return implode(' ' . $joiner . ' ', $parts);
1876
    }
1877
1878
    /**
1879
     * Obtain record/object numeric identificator id:
1880
     * Vrací číselný identifikátor objektu id:
1881
     *
1882
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1883
     *
1884
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1885
     */
1886
    public function getRecordID() {
1887
        $id = $this->getDataValue('id');
1888
        return is_null($id) ? null : (is_numeric($id) ? intval($id) : $id);
1889
    }
1890
1891
    /**
1892
     * Obtain record/object identificator code:
1893
     * Vrací identifikátor objektu code:
1894
     *
1895
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1896
     *
1897
     * @return string record code identifier
1898
     */
1899
    public function getRecordCode() {
1900
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1901
    }
1902
1903
    /**
1904
     * Obtain record/object identificator extId: code: or id:
1905
     * Vrací identifikátor objektu extId: code: nebo id:
1906
     *
1907
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1908
     *
1909
     * @return string|int|null record code identifier
1910
     */
1911
    public function getRecordIdent() {
1912
        $ident = $this->getExternalID();
1913
        if (empty($ident)) {
1914
            $ident = $this->getRecordCode();
1915
        }
1916
        if (empty($ident)) {
1917
            $ident = $this->getRecordID();
1918
        }
1919
        return $ident;
1920
    }
1921
1922
    /**
1923
     * Obtain record/object identificator code: or id:
1924
     * Vrací identifikátor objektu code: nebo id:
1925
     *
1926
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1927
     * 
1928
     * @return string indentifikátor záznamu reprezentovaného objektem
1929
     */
1930
    public function __toString() {
1931
        return strval($this->getRecordIdent());
1932
    }
1933
1934
    /**
1935
     * Gives you FlexiPeeHP class name for Given Evidence
1936
     *
1937
     * @param string $evidence
1938
     * 
1939
     * @return string Class name
1940
     */
1941
    public static function evidenceToClassName($evidence) {
1942
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1943
    }
1944
1945
    /**
1946
     * Obtain ID of first record in evidence
1947
     *
1948
     * @return string|null id or null if no records
1949
     */
1950
    public function getFirstRecordID() {
1951
        $firstID = null;
1952
        $keyColumn = $this->getKeyColumn();
1953
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1954
                ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1955
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1956
            $firstID = current($firstIdRaw)[$keyColumn];
1957
        }
1958
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1959
    }
1960
1961
    /**
1962
     * Get previous record ID
1963
     * 
1964
     * @param array $conditions optional
1965
     * 
1966
     * @return int|null
1967
     */
1968
    public function getNextRecordID($conditions = []) {
1969
        $conditions['order'] = 'id@D';
1970
        $conditions['limit'] = 1;
1971
        $conditions[] = 'id gt ' . $this->getRecordID();
1972
        $next = $this->getColumnsFromFlexibee(['id'], $conditions);
1973
        return (is_array($next) && array_key_exists(0, $next) && array_key_exists('id',
1974
                        $next[0])) ? intval($next[0]['id']) : null;
1975
    }
1976
1977
    /**
1978
     * Get next record ID
1979
     * 
1980
     * @param array $conditions optional
1981
     * 
1982
     * @return int|null
1983
     */
1984
    public function getPrevRecordID($conditions = []) {
1985
        $conditions['order'] = 'id@A';
1986
        $conditions['limit'] = 1;
1987
        $conditions[] = 'id lt ' . $this->getRecordID();
1988
        $prev = $this->getColumnsFromFlexibee(['id'], $conditions);
1989
        return (is_array($prev) && array_key_exists(0, $prev) && array_key_exists('id',
1990
                        $prev[0])) ? intval($prev[0]['id']) : null;
1991
    }
1992
1993
    /**
1994
     * Vrací hodnotu daného externího ID
1995
     *
1996
     * @param string $want Namespace Selector. If empty,you obtain the first one.
1997
     * 
1998
     * @return string|array one id or array if multiplete
1999
     */
2000
    public function getExternalID($want = null) {
2001
        $extid = null;
2002
        $ids = $this->getExternalIDs();
2003
        if (is_null($want)) {
2004
            if (!empty($ids)) {
2005
                $extid = current($ids);
2006
            }
2007
        } else {
2008
            if (!is_null($ids) && is_array($ids)) {
2009
                foreach ($ids as $id) {
2010
                    if (strstr($id, 'ext:' . $want)) {
2011
                        if (is_null($extid)) {
2012
                            $extid = str_replace('ext:' . $want . ':', '', $id);
2013
                        } else {
2014
                            if (is_array($extid)) {
2015
                                $extid[] = str_replace('ext:' . $want . ':', '', $id);
2016
                            } else {
2017
                                $extid = [$extid, str_replace('ext:' . $want . ':',
2018
                                            '', $id)];
2019
                            }
2020
                        }
2021
                    }
2022
                }
2023
            }
2024
        }
2025
        return $extid;
2026
    }
2027
2028
    /**
2029
     * gives you currently loaded extermal IDs
2030
     * 
2031
     * @return array
2032
     */
2033
    public function getExternalIDs() {
2034
        return $this->getDataValue('external-ids');
2035
    }
2036
2037
    /**
2038
     * Obtain actual GlobalVersion
2039
     * Vrací aktuální globální verzi změn
2040
     *
2041
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
2042
     * 
2043
     * @return int
2044
     */
2045
    public function getGlobalVersion() {
2046
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
2047
2048
        return $this->globalVersion;
2049
    }
2050
2051
    /**
2052
     * Gives you current ApiURL with given format suffix
2053
     * 
2054
     * @param string $format json|html|xml|...
2055
     * 
2056
     * @return string API URL for current record or object/evidence
2057
     */
2058
    public function getApiURL($format = null) {
2059
        $apiUrl = str_replace(['.' . $this->format, '?limit=0'], '', $this->apiURL);
2060
        return $apiUrl . (empty($format) ? '' : '.' . $format );
2061
    }
2062
2063
    /**
2064
     * Obtain content type of last response
2065
     *
2066
     * @return string
2067
     */
2068
    public function getResponseFormat() {
2069
        return $this->responseFormat;
2070
    }
2071
2072
    /**
2073
     * Return the same response format for one and multiplete results
2074
     *
2075
     * @param array $responseBody
2076
     * 
2077
     * @return array
2078
     */
2079
    public function unifyResponseFormat($responseBody) {
2080
        if (!is_array($responseBody) || array_key_exists('message',
2081
                        $responseBody)) { //Unifi response format
2082
            $response = $responseBody;
2083
        } else {
2084
            $evidence = $this->getResponseEvidence();
2085
            if (array_key_exists($evidence, $responseBody)) {
2086
                $response = [];
2087
                $evidenceContent = $responseBody[$evidence];
2088
                if (array_key_exists(0, $evidenceContent)) {
2089
                    $response[$evidence] = $evidenceContent; //Multiplete Results
2090
                } else {
2091
                    $response[$evidence][0] = $evidenceContent; //One result
2092
                }
2093
            } else {
2094
                if (isset($responseBody['priloha'])) {
2095
                    $response = $responseBody['priloha'];
2096
                } else {
2097
                    if (array_key_exists('results', $responseBody)) {
2098
                        $response = $responseBody['results'];
2099
                    } else {
2100
                        $response = $responseBody;
2101
                    }
2102
                }
2103
            }
2104
        }
2105
        return $response;
2106
    }
2107
2108
    /**
2109
     * Obtain structure for current (or given) evidence
2110
     *
2111
     * @param string $evidence
2112
     * 
2113
     * @return array Evidence structure
2114
     */
2115
    public function getOfflineColumnsInfo($evidence = null) {
2116
        $columnsInfo = null;
2117
        $infoSource = self::$infoDir . '/Properties.' . (empty($evidence) ? $this->getEvidence() : $evidence) . '.json';
2118
        if (file_exists($infoSource)) {
2119
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2120
        }
2121
        return $columnsInfo;
2122
    }
2123
2124
    /**
2125
     * Obtain Current evidence Live structure
2126
     * 
2127
     * @param string $evidence
2128
     * 
2129
     * @return array structure
2130
     */
2131
    public function getOnlineColumnsInfo($evidence = null) {
2132
        $properties = [];
2133
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2134
        $flexinfo = $this->performRequest('/c/' . $this->company . '/' . $evidence . '/properties.json');
2135
        if (!empty($flexinfo) && array_key_exists('properties', $flexinfo)) {
2136
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2137
                $key = $evidenceProperty['propertyName'];
2138
                $properties[$key] = $evidenceProperty;
2139
                if (array_key_exists('name', $evidenceProperty)) {
2140
                    $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...
2141
                }
2142
                $properties[$key]['type'] = $evidenceProperty['type'];
2143
                if (array_key_exists('url', $evidenceProperty)) {
2144
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2145
                            $evidenceProperty['url']);
2146
                }
2147
            }
2148
        }
2149
        return $properties;
2150
    }
2151
2152
    /**
2153
     * Update evidence info from array or online from properties.json or offline
2154
     * 
2155
     * @param array  $columnsInfo
2156
     * @param string $evidence
2157
     */
2158
    public function updateColumnsInfo($columnsInfo = null, $evidence = null) {
2159
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2160
        if (is_null($columnsInfo)) {
2161
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence) : $this->getOnlineColumnsInfo($evidence);
2162
        } else {
2163
            $this->columnsInfo[$evidence] = $columnsInfo;
2164
        }
2165
    }
2166
2167
    /**
2168
     * Gives you evidence structure. You can obtain current online by pre-calling:
2169
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2170
     * 
2171
     * @param string $evidence
2172
     * 
2173
     * @return array
2174
     */
2175
    public function getColumnsInfo($evidence = null) {
2176
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2177
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2178
            $this->updateColumnsInfo($this->getOfflineColumnsInfo($evidence),
2179
                    $evidence);
2180
        }
2181
        return $this->columnsInfo[$evidence];
2182
    }
2183
2184
    /**
2185
     * Gives you properties for (current) evidence column
2186
     *
2187
     * @param string $column    name of column
2188
     * @param string $evidence  evidence name if different
2189
     *
2190
     * @return array column properties or null if column not exits
2191
     */
2192
    public function getColumnInfo($column, $evidence = null) {
2193
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence() : $evidence);
2194
        return (empty($column) || empty($columnsInfo) || !is_array($columnsInfo)) ? null : (array_key_exists($column, $columnsInfo) ? $columnsInfo[$column] : null);
2195
    }
2196
2197
    /**
2198
     * Obtain actions for current (or given) evidence
2199
     *
2200
     * @param string $evidence
2201
     * 
2202
     * @return array Evidence structure
2203
     */
2204
    public function getActionsInfo($evidence = null) {
2205
        $actionsInfo = null;
2206
        if (is_null($evidence)) {
2207
            $evidence = $this->getEvidence();
2208
        }
2209
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2210
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2211
            $actionsInfo = Actions::$$propsName;
2212
        }
2213
        return $actionsInfo;
2214
    }
2215
2216
    /**
2217
     * Obtain relations for current (or given) evidence
2218
     *
2219
     * @param string $evidence
2220
     * 
2221
     * @return array Evidence structure
2222
     */
2223
    public function getRelationsInfo($evidence = null) {
2224
        $relationsInfo = null;
2225
        if (is_null($evidence)) {
2226
            $evidence = $this->getEvidence();
2227
        }
2228
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2229
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2230
            $relationsInfo = Relations::$$propsName;
2231
        }
2232
        return $relationsInfo;
2233
    }
2234
2235
    /**
2236
     * Obtain info for current (or given) evidence
2237
     *
2238
     * @param string $evidence
2239
     * 
2240
     * @return array Evidence info
2241
     */
2242
    public function getEvidenceInfo($evidence = null) {
2243
        $evidencesInfo = null;
2244
        if (is_null($evidence)) {
2245
            $evidence = $this->getEvidence();
2246
        }
2247
        if (isset(EvidenceList::$evidences[$evidence])) {
2248
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2249
            $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2250
            if (isset(Formats::$$propsName)) {
2251
                $evidencesInfo['formats'] = Formats::$$propsName;
2252
            }
2253
        }
2254
        return $evidencesInfo;
2255
    }
2256
2257
    /**
2258
     * Obtain name for current (or given) evidence path
2259
     *
2260
     * @param string $evidence Evidence Path
2261
     * 
2262
     * @return array Evidence info
2263
     */
2264
    public function getEvidenceName($evidence = null) {
2265
        $evidenceName = null;
2266
        if (is_null($evidence)) {
2267
            $evidence = $this->getEvidence();
2268
        }
2269
        if (isset(EvidenceList::$name[$evidence])) {
2270
            $evidenceName = EvidenceList::$name[$evidence];
2271
        }
2272
        return $evidenceName;
2273
    }
2274
2275
    /**
2276
     * Save current object to file
2277
     *
2278
     * @param string $destfile path to file
2279
     */
2280
    public function saveResponseToFile($destfile) {
2281
        if (strlen($this->lastCurlResponse)) {
2282
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2283
        }
2284
        file_put_contents($destfile, $this->lastCurlResponse);
2285
    }
2286
2287
    /**
2288
     * Obtain established relations listing
2289
     *
2290
     * @return array Null or Relations
2291
     */
2292
    public function getVazby($id = null) {
2293
        if (is_null($id)) {
2294
            $id = $this->getRecordID();
2295
        }
2296
        if (!empty($id)) {
2297
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2298
                    ['relations' => 'vazby', 'id' => $id]);
2299
            $vazby = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby'] : null;
2300
        } else {
2301
            throw new \Exception(_('ID requied to get record relations '));
2302
        }
2303
        return $vazby;
2304
    }
2305
2306
    /**
2307
     * Gives You URL for Current Record in FlexiBee web interface
2308
     *
2309
     * @return string url
2310
     */
2311
    public function getFlexiBeeURL() {
2312
        $parsed_url = parse_url(str_replace('.' . $this->format, '', $this->apiURL));
2313
        $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
2314
        $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2315
        $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
2316
        $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2317
        $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
2318
        $pass = ($user || $pass) ? "$pass@" : '';
2319
        $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2320
        return $scheme . $user . $pass . $host . $port . $path;
2321
    }
2322
2323
    /**
2324
     * Set Record Key
2325
     *
2326
     * @param int|string $myKeyValue
2327
     * 
2328
     * @return boolean
2329
     */
2330
    public function setMyKey($myKeyValue) {
2331
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2332
            if (empty($this->evidenceInfo) || ($this->evidenceInfo['extIdSupported'] == 'false')) {
2333
                $this->addStatusMessage(sprintf(_('Evidence %s does not support extIDs'),
2334
                                $this->getEvidence()), 'warning');
2335
                $res = false;
2336
            } else {
2337
                $extIds = $this->getDataValue('external-ids');
2338
                if (!empty($extIds) && count($extIds)) {
2339
                    $extIds = array_combine($extIds, $extIds);
2340
                }
2341
2342
                $extIds[$myKeyValue] = $myKeyValue;
2343
                $res = $this->setDataValue('external-ids',
2344
                        $extIds);
2345
            }
2346
        } else {
2347
            $res = $this->setDataValue($this->getKeyColumn(), $myKeyValue);
2348
        }
2349
        $this->updateApiURL();
2350
        return $res;
2351
    }
2352
2353
    /**
2354
     * Set or get ignore not found pages flag
2355
     *
2356
     * @param boolean $ignore set flag to
2357
     *
2358
     * @return boolean get flag state
2359
     */
2360
    public function ignore404($ignore = null) {
2361
        if (!is_null($ignore)) {
2362
            $this->ignoreNotFound = $ignore;
2363
        }
2364
        return $this->ignoreNotFound;
2365
    }
2366
2367
    /**
2368
     * Send Document by mail
2369
     *
2370
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2371
     *
2372
     * @param string $to         Email ecipient
2373
     * @param string $subject    Email Subject
2374
     * @param string $body       Email Text
2375
     *
2376
     * @return boolean mail sent status
2377
     */
2378
    public function sendByMail($to, $subject, $body, $cc = null) {
2379
        $this->setPostFields($body);
2380
2381
        $this->performRequest(rawurlencode($this->getRecordID()) . '/odeslani-dokladu?to=' . $to . '&subject=' . urlencode($subject) . '&cc=' . $cc
2382
                , 'PUT', 'xml');
2383
2384
        return $this->lastResponseCode == 200;
2385
    }
2386
2387
    /**
2388
     * FlexiBee date to PHP DateTime conversion
2389
     *
2390
     * @param string $flexidate 2017-05-26 or 2017-05-26+02:00
2391
     *
2392
     * @return \DateTime | false
2393
     */
2394
    public static function flexiDateToDateTime($flexidate) {
2395
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat . 'O' : self::$DateFormat, $flexidate)->setTime(0, 0);
2396
    }
2397
2398
    /**
2399
     * FlexiBee dateTime to PHP DateTime conversion
2400
     *
2401
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2402
     *
2403
     * @return \DateTime | false
2404
     */
2405
    public static function flexiDateTimeToDateTime($flexidatetime) {
2406
        if (strchr($flexidatetime, '.')) { //NewFormat
2407
            $format = self::$DateTimeFormat;
2408
        } else { // Old format
2409
            $format = 'Y-m-d\TH:i:s+P';
2410
        }
2411
        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 2411 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...
2412
    }
2413
2414
    /**
2415
     * Získá dokument v daném formátu
2416
     * Obtain document in given format
2417
     *
2418
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2419
     *
2420
     * @param string  $format     pdf/csv/xml/json/ ...
2421
     * @param string  $reportName Template used to generate PDF
2422
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2423
     * @param boolean $sign       sign resulting PDF by certificate ?
2424
     *
2425
     * @return string|null filename downloaded or none
2426
     */
2427
    public function getInFormat($format, $reportName = null, $lang = null,
2428
            $sign = false) {
2429
        $response = null;
2430
        if ($this->setFormat($format)) {
2431
            $urlParams = [];
2432
            switch ($format) {
2433
                case 'pdf':
2434
                    switch ($lang) {
2435
                        case 'cs':
2436
                        case 'sk':
2437
                        case 'en':
2438
                        case 'de':
2439
                            $urlParams['report-lang'] = $lang;
2440
                            break;
2441
                        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...
2442
                        case '':
2443
                            break;
2444
                        default:
2445
                            throw new \Ease\Exception('Unknown language ' . $lang . ' for PDF export');
2446
                            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...
2447
                    }
2448
                    if (boolval($sign) === true) {
2449
                        $urlParams['report-sign'] = 'true';
2450
                    }
2451
                    break;
2452
                case 'html':
2453
                    $urlParams['inDesktopApp'] = 'true';
2454
                    break;
2455
            }
2456
            if (!empty($reportName)) {
2457
                $urlParams['report-name'] = $reportName;
2458
            }
2459
            if (($this->doCurlRequest(\Ease\Functions::addUrlParams($this->apiURL,
2460
                                    $urlParams), 'GET') == 200)) {
2461
                $response = $this->lastCurlResponse;
2462
            }
2463
        }
2464
        return $response;
2465
    }
2466
2467
    /**
2468
     * Uloží dokument v daném formátu do složky v systému souborů
2469
     * Save document in given format to directory in filesystem
2470
     *
2471
     * @param string $format  pdf/csv/xml/json/ ...
2472
     * @param string $destDir where to put file (prefix)
2473
     * @param string $reportName Template used to generate PDF
2474
     *
2475
     * @return string|null filename downloaded or none
2476
     */
2477
    public function downloadInFormat($format, $destDir = './',
2478
            $reportName = null) {
2479
        $fileOnDisk = null;
2480
        $formatBackup = $this->format;
2481
        if ($this->setFormat($format)) {
2482
            $downloadTo = $destDir . $this->getEvidence() . '_' . $this->getMyKey() . '.' . $format;
2483
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Functions::addUrlParams($this->apiURL,
2484
                                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2485
                            $this->lastCurlResponse) !== false)) {
2486
                $fileOnDisk = $downloadTo;
2487
            }
2488
            $this->setFormat($formatBackup);
2489
        }
2490
        return $fileOnDisk;
2491
    }
2492
2493
    /**
2494
     * Take data for object. separate external IDs
2495
     *
2496
     * @param array $data Data to keep
2497
     * 
2498
     * @return int number of records taken
2499
     */
2500
    public function takeData($data) {
2501
        $keyColumn = $this->getKeyColumn();
2502
        if (array_key_exists($keyColumn, $data) && is_array($data[$keyColumn])) {
2503
            foreach ($data[$keyColumn] as $recPos => $recordKey) {
2504
                if (substr($recordKey, 0, 4) == 'ext:') {
2505
                    $data['external-ids'][] = $recordKey;
2506
                    unset($data[$keyColumn][$recPos]);
2507
                }
2508
            }
2509
            if (count($data[$keyColumn]) == 1) {
2510
                $data[$keyColumn] = current($data[$keyColumn]);
2511
            }
2512
        }
2513
        $result = parent::takeData($data);
2514
2515
        if (array_key_exists($keyColumn, $data) || array_key_exists('kod', $data)) {
2516
            $this->updateApiURL();
2517
        }
2518
2519
        return $result;
2520
    }
2521
2522
    /**
2523
     * Get Current Evidence reports listing
2524
     * 
2525
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2526
     * 
2527
     * @return array
2528
     */
2529
    public function getReportsInfo() {
2530
        $reports = [];
2531
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL() . '/reports');
2532
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports']) && array_key_exists('report', $reportsRaw['reports']) &&
2533
                !empty($reportsRaw['reports']['report'])) {
2534
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
2535
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2536
            } else {
2537
                $reports = \Ease\Functions::reindexArrayBy($reportsRaw['reports']['report'],
2538
                                'reportId');
2539
            }
2540
        }
2541
        return $reports;
2542
    }
2543
2544
    /**
2545
     * Request authSessionId from current server
2546
     * 
2547
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2548
     * 
2549
     * @param string $username
2550
     * @param string $password
2551
     * @param string $otp       optional onetime password
2552
     * 
2553
     * @return string authUserId or null in case of problems
2554
     */
2555
    public function requestAuthSessionID($username, $password, $otp = null) {
2556
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2557
            'password' => $password] : ['username' => $username, 'password' => $password,
2558
            'otp' => $otp]);
2559
        $response = $this->performRequest('/login-logout/login', 'POST',
2560
                'json');
2561
        if (array_key_exists('refreshToken', $response)) {
2562
            $this->refreshToken = $response['refreshToken'];
2563
        } else {
2564
            $this->refreshToken = null;
2565
        }
2566
        return array_key_exists('authSessionId', $response) ? $response['authSessionId'] : null;
2567
    }
2568
2569
    /**
2570
     * Try to Sign in current user to FlexiBee and keep authSessionId
2571
     * 
2572
     * @return boolean sign in success
2573
     */
2574
    public function login() {
2575
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2576
                $this->password);
2577
        return $this->lastResponseCode == 200;
2578
    }
2579
2580
    /**
2581
     * End (current's user) session
2582
     * 
2583
     * 
2584
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2585
     * 
2586
     * @param string $username force username to sign off
2587
     * 
2588
     * @return array server response
2589
     */
2590
    public function logout($username = null) {
2591
        return $this->performRequest('/status/user/' . (is_null($username) ? $this->user : $username) . '/logout', 'POST');
2592
    }
2593
2594
    /**
2595
     * Compile and send Report about Error500 to FlexiBee developers
2596
     * If FlexiBee is running on localost try also include java backtrace
2597
     *
2598
     * @param array $errorResponse result of parseError();
2599
     */
2600
    public function error500Reporter($errorResponse) {
2601
        $ur = str_replace('/c/' . $this->company, '',
2602
                str_replace($this->url, '', $this->curlInfo['url']));
2603
        if (!array_key_exists($ur, $this->reports)) {
2604
            $tmpdir = sys_get_temp_dir();
2605
            $myTime = $this->curlInfo['when'];
2606
            $curlname = $tmpdir . '/curl-' . $this->evidence . '-' . $myTime . '.json';
2607
            file_put_contents($curlname,
2608
                    json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2609
2610
            $report = new \Ease\Mailer($this->reportRecipient,
2611
                    'Error report 500 - ' . $ur);
2612
2613
            $d = dir($tmpdir);
2614
            while (false !== ($entry = $d->read())) {
2615
                if (strstr($entry, $myTime)) {
2616
                    $ext = pathinfo($tmpdir . '/' . $entry, PATHINFO_EXTENSION);
2617
                    $mime = Formats::suffixToContentType($ext);
2618
                    $report->addFile($tmpdir . '/' . $entry,
2619
                            empty($mime) ? 'text/plain' : $mime);
2620
                }
2621
            }
2622
            $d->close();
2623
2624
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2625
                            '://127.')) && file_exists('/var/log/flexibee.log')) {
2626
2627
                $fl = fopen('/var/log/' . 'flexibee.log', 'r');
2628
                if ($fl) {
2629
                    $tracelog = [];
2630
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2631
                                    $x_pos, SEEK_END) !== -1; $x_pos--) {
2632
                        $char = fgetc($fl);
2633
                        if ($char === "\n") {
2634
                            $tracelog[] = $output[$ln];
2635
                            if (strstr($output[$ln], $errorResponse['message'])) {
2636
                                break;
2637
                            }
2638
                            $ln++;
2639
                            continue;
2640
                        }
2641
                        $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : '');
2642
                    }
2643
2644
                    $trace = implode("\n", array_reverse($tracelog));
2645
                    $tracefile = $tmpdir . '/trace-' . $this->evidence . '-' . $myTime . '.log';
2646
                    file_put_contents($tracefile, $trace);
2647
                    $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...
2648
                    fclose($fl);
2649
                }
2650
            } else {
2651
                $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...
2652
            }
2653
2654
            $licenseInfo = $this->performRequest($this->url . '/default-license.json');
2655
2656
            $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...
2657
                            JSON_PRETTY_PRINT));
2658
2659
            if ($report->send()) {
2660
                $this->reports[$ur] = $myTime;
2661
            }
2662
        }
2663
    }
2664
2665
    /**
2666
     * Returns code:CODE
2667
     *
2668
     * @param string $code
2669
     *
2670
     * @return string
2671
     */
2672
    public static function code($code) {
2673
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:' . strtoupper(self::uncode($code)));
2674
    }
2675
2676
    /**
2677
     * Returns CODE without code: prefix
2678
     *
2679
     * @param string $code
2680
     *
2681
     * @return string
2682
     */
2683
    public static function uncode($code) {
2684
        return str_replace(['code:', 'code%3A'], '', $code);
2685
    }
2686
2687
    /**
2688
     * Remove all @ items from array
2689
     *
2690
     * @param array $data original data
2691
     *
2692
     * @return array data without @ columns
2693
     */
2694
    public static function arrayCleanUP($data) {
2695
        return array_filter(
2696
                $data,
2697
                function ($key) {
2698
            return !strchr($key, '@');
2699
        }, ARRAY_FILTER_USE_KEY);
2700
    }
2701
2702
    /**
2703
     * Add Info about used user, server and libraries
2704
     *
2705
     * @param string $prefix banner prefix text
2706
     * @param string $suffix banner suffix text
2707
     */
2708
    public function logBanner($prefix = null, $suffix = null) {
2709
        parent::logBanner($prefix,
2710
                ' FlexiBee ' . str_replace('://', '://' . $this->user . '@',
2711
                        $this->getApiUrl()) . ' FlexiBeeHP v' . self::$libVersion . ' (FlexiBee ' . EvidenceList::$version . ') EasePHP Framework v' . \Ease\Atom::$frameworkVersion . ' ' .
2712
                $suffix
2713
        );
2714
    }
2715
2716
    /**
2717
     * Get Last operation type
2718
     * 
2719
     * @return string create|read|update|delete or update,insert for some inserted and updated in one transaction
2720
     */
2721
    public function getLastOperationType() {
2722
        return implode(',', array_keys(array_filter($this->responseStats)));
2723
    }
2724
2725
    /**
2726
     * Last operation errors 
2727
     * 
2728
     * @return array FlexiBee error meassages
2729
     */
2730
    public function getErrors() {
2731
        return $this->errors;
2732
    }
2733
2734
    /**
2735
     * Reconnect After unserialization
2736
     */
2737
    public function __wakeup() {
2738
        $this->curlInit();
2739
    }
2740
2741
}
2742