Completed
Push — master ( e76b9a...add113 )
by Vítězslav
21:19
created

FlexiBeeRO::performRequest()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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