Completed
Push — master ( 230897...bb977a )
by Vítězslav
23:32
created

FlexiBeeRO::getExternalID()   B

Complexity

Conditions 9
Paths 4

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

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

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

Let’s take a look at an example:

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

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

    // do something with $myArray
}

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

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

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