Completed
Push — master ( 374c2c...691bd4 )
by Vítězslav
23:51
created

FlexiBeeRO::configToEnv()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 64
nop 1
dl 0
loc 18
rs 8.8333
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.35';
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
     * Subitems - ex. items of invoice
1584
     * 
1585
     * @return array of document items or null
1586
     */
1587
    public function getSubItems() {
1588
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury') : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu') : null);
1589
    }
1590
1591
    /**
1592
     * Vrací z FlexiBee sloupečky podle podmínek.
1593
     *
1594
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1595
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1596
     *                                     sloupečku
1597
     * @return array
1598
     */
1599
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1600
        if (is_int($conditions)) {
1601
            $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...
1602
        }
1603
1604
        $flexiData = $this->getFlexiData('', $conditions);
1605
1606
        if (!is_null($indexBy)) {
1607
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData);
1608
        }
1609
1610
        return $flexiData;
1611
    }
1612
1613
    /**
1614
     * Vrací z FlexiBee sloupečky podle podmínek.
1615
     *
1616
     * @param string|string[] $columnsList seznam položek nebo úrověň detailu: id|summary|full
1617
     * @param array           $conditions  pole podmínek nebo ID záznamu
1618
     * @param string          $indexBy     Sloupeček podle kterého indexovat záznamy
1619
     *
1620
     * @return array
1621
     */
1622
    public function getColumnsFromFlexibee($columnsList, $conditions = [],
1623
            $indexBy = null) {
1624
        $detail = 'full';
1625
        switch (gettype($columnsList)) {
1626
            case 'integer': //Record ID
1627
                $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...
1628
            case 'array': //Few Conditions
1629
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1630
                                $columnsList)) {
1631
                    $columnsList[] = $indexBy;
1632
                }
1633
                $columns = implode(',', array_unique($columnsList));
1634
                $detail = 'custom:' . $columns;
1635
            default:
1636
                switch ($columnsList) {
1637
                    case 'id':
1638
                        $detail = 'id';
1639
                        break;
1640
                    case 'summary':
1641
                        $detail = 'summary';
1642
                        break;
1643
                    default:
1644
                        break;
1645
                }
1646
                break;
1647
        }
1648
1649
        $conditions['detail'] = $detail;
1650
1651
        $flexiData = $this->getFlexiData(null, $conditions);
1652
1653
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1654
                        $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1655
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData, $indexBy);
1656
        }
1657
1658
        return $flexiData;
1659
    }
1660
1661
    /**
1662
     * Vrací kód záznamu.
1663
     * Obtain record CODE
1664
     *
1665
     * @param mixed $data
1666
     *
1667
     * @return string
1668
     */
1669
    public function getKod($data = null, $unique = true) {
1670
        $kod = null;
1671
1672
        if (is_null($data)) {
1673
            $data = $this->getData();
1674
        }
1675
1676
        if (is_string($data)) {
1677
            $data = [$this->nameColumn => $data];
1678
        }
1679
1680
        if (isset($data['kod'])) {
1681
            $kod = $data['kod'];
1682
        } else {
1683
            if (isset($data[$this->nameColumn])) {
1684
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1685
                        \Ease\Functions::rip($data[$this->nameColumn]));
1686
            } else {
1687
                if (isset($data[$this->keyColumn])) {
1688
                    $kod = \Ease\Functions::rip($data[$this->keyColumn]);
1689
                }
1690
            }
1691
            $kod = substr($kod, 0, 20);
1692
        }
1693
1694
        if (!strlen($kod)) {
1695
            $kod = 'NOTSET';
1696
        }
1697
1698
        if (strlen($kod) > 18) {
1699
            $kodfinal = strtoupper(substr($kod, 0, 18));
1700
        } else {
1701
            $kodfinal = strtoupper($kod);
1702
        }
1703
1704
        if ($unique) {
1705
            $counter = 0;
1706
            if (!empty($this->codes) && count($this->codes)) {
1707
                foreach ($this->codes as $codesearch => $keystring) {
1708
                    if (strstr($codesearch, $kodfinal)) {
1709
                        ++$counter;
1710
                    }
1711
                }
1712
            }
1713
            if ($counter) {
1714
                $kodfinal = $kodfinal . $counter;
1715
            }
1716
1717
            $this->codes[$kodfinal] = $kod;
1718
        }
1719
1720
        return self::code($kodfinal);
1721
    }
1722
1723
    /**
1724
     * Write Operation Result.
1725
     *
1726
     * @param array  $resultData
1727
     * @param string $url        URL
1728
     * 
1729
     * @return boolean Log save success
1730
     */
1731
    public function logResult($resultData = null, $url = null) {
1732
        $logResult = false;
1733
        if (isset($resultData['success']) && ($resultData['success'] == 'false')) {
1734
            $this->addStatusMessage('Error ' . $this->lastResponseCode . ': ' . urldecode($url) . (array_key_exists('message',
1735
                            $resultData) ? ' ' . $resultData['message'] : ''), 'warning');
1736
            unset($url);
1737
        }
1738
        if (is_null($resultData)) {
1739
            $resultData = $this->lastResult;
1740
        }
1741
        if (isset($url)) {
1742
            \Ease\Shared::logger()->addStatusMessage($this->lastResponseCode . ':' . urldecode($url));
1743
        }
1744
1745
        if (isset($resultData['results'])) {
1746
            if ($resultData['success'] == 'false') {
1747
                $status = 'error';
1748
            } else {
1749
                $status = 'success';
1750
            }
1751
            foreach ($resultData['results'] as $result) {
1752
                if (isset($result['request-id'])) {
1753
                    $rid = $result['request-id'];
1754
                } else {
1755
                    $rid = '';
1756
                }
1757
                if (isset($result['errors'])) {
1758
                    foreach ($result['errors'] as $error) {
1759
                        $message = $error['message'];
1760
                        if (isset($error['for'])) {
1761
                            $message .= ' for: ' . $error['for'];
1762
                        }
1763
                        if (isset($error['value'])) {
1764
                            $message .= ' value:' . $error['value'];
1765
                        }
1766
                        if (isset($error['code'])) {
1767
                            $message .= ' code:' . $error['code'];
1768
                        }
1769
                        $this->addStatusMessage($rid . ': ' . $message, $status);
1770
                    }
1771
                }
1772
            }
1773
        }
1774
        return $logResult;
1775
    }
1776
1777
    /**
1778
     * Save RAW Curl Request & Response to files in Temp directory
1779
     */
1780
    public function saveDebugFiles() {
1781
        $tmpdir = sys_get_temp_dir();
1782
        $fname = $this->evidence . '-' . $this->curlInfo['when'] . '.' . $this->format;
1783
        $reqname = $tmpdir . '/request-' . $fname;
1784
        $respname = $tmpdir . '/response-' . $fname;
1785
        $header = '# ' . (new \DateTime())->format('Y-m-d\TH:i:s.u') . ' ' . $this->curlInfo['url'] . ' (' . urldecode($this->curlInfo['url']) . ')';
1786
        if (file_put_contents($reqname, $header . "\n" . $this->postFields)) {
1787
            $this->addStatusMessage($reqname, 'debug');
1788
        }
1789
        if (file_put_contents($respname, $header . "\n" . $this->lastCurlResponse)) {
1790
            $this->addStatusMessage($respname, 'debug');
1791
        }
1792
    }
1793
1794
    /**
1795
     * Připraví data pro odeslání do FlexiBee
1796
     *
1797
     * @param string $data
1798
     */
1799
    public function setPostFields($data) {
1800
        $this->postFields = $data;
1801
    }
1802
1803
    /**
1804
     * Get Content ready to be send as POST body
1805
     * @return string
1806
     */
1807
    public function getPostFields() {
1808
        return $this->postFields;
1809
    }
1810
1811
    /**
1812
     * Generuje fragment url pro filtrování.
1813
     *
1814
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1815
     *
1816
     * @param array  $data   key=>values; value can bee class DatePeriod, DateTime or Array
1817
     * @param string $joiner default and/or
1818
     * @param string $defop  default operator
1819
     *
1820
     * @return string
1821
     */
1822
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq') {
1823
        $parts = [];
1824
1825
        foreach ($data as $column => $value) {
1826
            if (!is_numeric($column)) {
1827
                if (is_integer($data[$column]) || is_float($data[$column])) {
1828
                    $parts[$column] = $column . ' eq \'' . $data[$column] . '\'';
1829
                } elseif (is_bool($data[$column])) {
1830
                    $parts[$column] = $data[$column] ? $column . ' eq true' : $column . ' eq false';
1831
                } elseif (is_null($data[$column])) {
1832
                    $parts[$column] = $column . " is null";
1833
                } elseif (is_array($data[$column])) {
1834
                    $parts[$column] = $column . " in (" . implode(',',
1835
                                    array_map(function($a, $column) {
1836
                                        return $column == 'stitky' ? "'" . self::code($a) . "'" : "'$a'";
1837
                                    }, $data[$column],
1838
                                            array_fill(0, count($data[$column]), $column))) . ")";
1839
                } elseif (is_object($data[$column])) {
1840
                    switch (get_class($data[$column])) {
1841
                        case 'DatePeriod':
1842
                            $parts[$column] = $column . " between '" . $data[$column]->getStartDate()->format(self::$DateFormat) . "' '" . $data[$column]->getEndDate()->format(self::$DateFormat) . "'";
1843
                            break;
1844
                        case 'DateTime':
1845
                            $parts[$column] = $column . " eq '" . $data[$column]->format(self::$DateFormat) . "'";
1846
                            break;
1847
                        default:
1848
                            $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1849
                            break;
1850
                    }
1851
                } else {
1852
                    switch ($value) {
1853
                        case '!null':
1854
                            $parts[$column] = $column . " is not null";
1855
                            break;
1856
                        case 'is empty':
1857
                        case 'is not empty':
1858
                        case 'is true':
1859
                        case 'is false':
1860
                            $parts[$column] = $column . ' ' . $value;
1861
                            break;
1862
                        default:
1863
                            $condParts = explode(' ', trim($value));
1864
                            switch ($condParts[0]) {
1865
                                case '<>':
1866
                                case '!=':
1867
                                case 'ne':
1868
                                case 'neq':
1869
                                case '<':
1870
                                case 'lt':
1871
                                case '<=':
1872
                                case 'lte':
1873
                                case '>':
1874
                                case 'gt':
1875
                                case '>=':
1876
                                case 'gte':
1877
                                case 'like':
1878
                                case 'begins':
1879
                                case 'between':
1880
                                case 'ends':
1881
                                    if (count($condParts) == 1) {
1882
                                        $parts[$column] = $column .= ' ' . $value;
1883
                                    } else {
1884
                                        $parts[$column] = $column .= ' ' . $condParts[0] . " '" . $condParts[1] . "'";
1885
                                    }
1886
                                    break;
1887
                                default:
1888
                                    if ($column == 'stitky') {
1889
                                        $parts[$column] = $column . "='" . self::code($data[$column]) . "'";
1890
                                    } else {
1891
                                        $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1892
                                    }
1893
                                    break;
1894
                            }
1895
1896
                            break;
1897
                    }
1898
                }
1899
            } else {
1900
                $parts[] = $value;
1901
            }
1902
        }
1903
        return implode(' ' . $joiner . ' ', $parts);
1904
    }
1905
1906
    /**
1907
     * Obtain record/object numeric identificator id:
1908
     * Vrací číselný identifikátor objektu id:
1909
     *
1910
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1911
     *
1912
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1913
     */
1914
    public function getRecordID() {
1915
        $id = $this->getDataValue('id');
1916
        return is_null($id) ? null : (is_numeric($id) ? intval($id) : $id);
1917
    }
1918
1919
    /**
1920
     * Obtain record/object identificator code:
1921
     * Vrací identifikátor objektu code:
1922
     *
1923
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1924
     *
1925
     * @return string record code identifier
1926
     */
1927
    public function getRecordCode() {
1928
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1929
    }
1930
1931
    /**
1932
     * Obtain record/object identificator extId: code: or id:
1933
     * Vrací identifikátor objektu extId: code: nebo id:
1934
     *
1935
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1936
     *
1937
     * @return string|int|null record code identifier
1938
     */
1939
    public function getRecordIdent() {
1940
        $ident = $this->getExternalID();
1941
        if (empty($ident)) {
1942
            $ident = $this->getRecordCode();
1943
        }
1944
        if (empty($ident)) {
1945
            $ident = $this->getRecordID();
1946
        }
1947
        return $ident;
1948
    }
1949
1950
    /**
1951
     * Obtain record/object identificator code: or id:
1952
     * Vrací identifikátor objektu code: nebo id:
1953
     *
1954
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1955
     * 
1956
     * @return string indentifikátor záznamu reprezentovaného objektem
1957
     */
1958
    public function __toString() {
1959
        return strval($this->getRecordIdent());
1960
    }
1961
1962
    /**
1963
     * Gives you FlexiPeeHP class name for Given Evidence
1964
     *
1965
     * @param string $evidence
1966
     * 
1967
     * @return string Class name
1968
     */
1969
    public static function evidenceToClassName($evidence) {
1970
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1971
    }
1972
1973
    /**
1974
     * Obtain ID of first record in evidence
1975
     *
1976
     * @return string|null id or null if no records
1977
     */
1978
    public function getFirstRecordID() {
1979
        $firstID = null;
1980
        $keyColumn = $this->getKeyColumn();
1981
        $firstIdRaw = $this->getColumnsFromFlexibee([$keyColumn],
1982
                ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1983
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1984
            $firstID = current($firstIdRaw)[$keyColumn];
1985
        }
1986
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1987
    }
1988
1989
    /**
1990
     * Get previous record ID
1991
     * 
1992
     * @param array $conditions optional
1993
     * 
1994
     * @return int|null
1995
     */
1996
    public function getNextRecordID($conditions = []) {
1997
        $conditions['order'] = 'id@D';
1998
        $conditions['limit'] = 1;
1999
        $conditions[] = 'id gt ' . $this->getRecordID();
2000
        $next = $this->getColumnsFromFlexibee(['id'], $conditions);
2001
        return (is_array($next) && array_key_exists(0, $next) && array_key_exists('id',
2002
                        $next[0])) ? intval($next[0]['id']) : null;
2003
    }
2004
2005
    /**
2006
     * Get next record ID
2007
     * 
2008
     * @param array $conditions optional
2009
     * 
2010
     * @return int|null
2011
     */
2012
    public function getPrevRecordID($conditions = []) {
2013
        $conditions['order'] = 'id@A';
2014
        $conditions['limit'] = 1;
2015
        $conditions[] = 'id lt ' . $this->getRecordID();
2016
        $prev = $this->getColumnsFromFlexibee(['id'], $conditions);
2017
        return (is_array($prev) && array_key_exists(0, $prev) && array_key_exists('id',
2018
                        $prev[0])) ? intval($prev[0]['id']) : null;
2019
    }
2020
2021
    /**
2022
     * Vrací hodnotu daného externího ID
2023
     *
2024
     * @param string $want Namespace Selector. If empty,you obtain the first one.
2025
     * 
2026
     * @return string|array one id or array if multiplete
2027
     */
2028
    public function getExternalID($want = null) {
2029
        $extid = null;
2030
        $ids = $this->getExternalIDs();
2031
        if (is_null($want)) {
2032
            if (!empty($ids)) {
2033
                $extid = current($ids);
2034
            }
2035
        } else {
2036
            if (!is_null($ids) && is_array($ids)) {
2037
                foreach ($ids as $id) {
2038
                    if (strstr($id, 'ext:' . $want)) {
2039
                        if (is_null($extid)) {
2040
                            $extid = str_replace('ext:' . $want . ':', '', $id);
2041
                        } else {
2042
                            if (is_array($extid)) {
2043
                                $extid[] = str_replace('ext:' . $want . ':', '', $id);
2044
                            } else {
2045
                                $extid = [$extid, str_replace('ext:' . $want . ':',
2046
                                            '', $id)];
2047
                            }
2048
                        }
2049
                    }
2050
                }
2051
            }
2052
        }
2053
        return $extid;
2054
    }
2055
2056
    /**
2057
     * gives you currently loaded extermal IDs
2058
     * 
2059
     * @return array
2060
     */
2061
    public function getExternalIDs() {
2062
        return $this->getDataValue('external-ids');
2063
    }
2064
2065
    /**
2066
     * Obtain actual GlobalVersion
2067
     * Vrací aktuální globální verzi změn
2068
     *
2069
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
2070
     * 
2071
     * @return int
2072
     */
2073
    public function getGlobalVersion() {
2074
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
2075
2076
        return $this->globalVersion;
2077
    }
2078
2079
    /**
2080
     * Gives you current ApiURL with given format suffix
2081
     * 
2082
     * @param string $format json|html|xml|...
2083
     * 
2084
     * @return string API URL for current record or object/evidence
2085
     */
2086
    public function getApiURL($format = null) {
2087
        $apiUrl = str_replace(['.' . $this->format, '?limit=0'], '', $this->apiURL);
2088
        return $apiUrl . (empty($format) ? '' : '.' . $format );
2089
    }
2090
2091
    /**
2092
     * Obtain content type of last response
2093
     *
2094
     * @return string
2095
     */
2096
    public function getResponseFormat() {
2097
        return $this->responseFormat;
2098
    }
2099
2100
    /**
2101
     * Return the same response format for one and multiplete results
2102
     *
2103
     * @param array $responseBody
2104
     * 
2105
     * @return array
2106
     */
2107
    public function unifyResponseFormat($responseBody) {
2108
        if (!is_array($responseBody) || array_key_exists('message',
2109
                        $responseBody)) { //Unifi response format
2110
            $response = $responseBody;
2111
        } else {
2112
            $evidence = $this->getResponseEvidence();
2113
            if (array_key_exists($evidence, $responseBody)) {
2114
                $response = [];
2115
                $evidenceContent = $responseBody[$evidence];
2116
                if (array_key_exists(0, $evidenceContent)) {
2117
                    $response[$evidence] = $evidenceContent; //Multiplete Results
2118
                } else {
2119
                    $response[$evidence][0] = $evidenceContent; //One result
2120
                }
2121
            } else {
2122
                if (isset($responseBody['priloha'])) {
2123
                    $response = $responseBody['priloha'];
2124
                } else {
2125
                    if (array_key_exists('results', $responseBody)) {
2126
                        $response = $responseBody['results'];
2127
                    } else {
2128
                        $response = $responseBody;
2129
                    }
2130
                }
2131
            }
2132
        }
2133
        return $response;
2134
    }
2135
2136
    /**
2137
     * Obtain structure for current (or given) evidence
2138
     *
2139
     * @param string $evidence
2140
     * 
2141
     * @return array Evidence structure
2142
     */
2143
    public function getOfflineColumnsInfo($evidence = null) {
2144
        $columnsInfo = null;
2145
        $infoSource = self::$infoDir . '/Properties.' . (empty($evidence) ? $this->getEvidence() : $evidence) . '.json';
2146
        if (file_exists($infoSource)) {
2147
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2148
        }
2149
        return $columnsInfo;
2150
    }
2151
2152
    /**
2153
     * Obtain Current evidence Live structure
2154
     * 
2155
     * @param string $evidence
2156
     * 
2157
     * @return array structure
2158
     */
2159
    public function getOnlineColumnsInfo($evidence = null) {
2160
        $properties = [];
2161
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2162
        $flexinfo = $this->performRequest('/c/' . $this->company . '/' . $evidence . '/properties.json');
2163
        if (!empty($flexinfo) && array_key_exists('properties', $flexinfo)) {
2164
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2165
                $key = $evidenceProperty['propertyName'];
2166
                $properties[$key] = $evidenceProperty;
2167
                if (array_key_exists('name', $evidenceProperty)) {
2168
                    $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...
2169
                }
2170
                $properties[$key]['type'] = $evidenceProperty['type'];
2171
                if (array_key_exists('url', $evidenceProperty)) {
2172
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2173
                            $evidenceProperty['url']);
2174
                }
2175
            }
2176
        }
2177
        return $properties;
2178
    }
2179
2180
    /**
2181
     * Update evidence info from array or online from properties.json or offline
2182
     * 
2183
     * @param array  $columnsInfo
2184
     * @param string $evidence
2185
     */
2186
    public function updateColumnsInfo($columnsInfo = null, $evidence = null) {
2187
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2188
        if (is_null($columnsInfo)) {
2189
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence) : $this->getOnlineColumnsInfo($evidence);
2190
        } else {
2191
            $this->columnsInfo[$evidence] = $columnsInfo;
2192
        }
2193
    }
2194
2195
    /**
2196
     * Gives you evidence structure. You can obtain current online by pre-calling:
2197
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2198
     * 
2199
     * @param string $evidence
2200
     * 
2201
     * @return array
2202
     */
2203
    public function getColumnsInfo($evidence = null) {
2204
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2205
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2206
            $this->updateColumnsInfo($this->getOfflineColumnsInfo($evidence),
2207
                    $evidence);
2208
        }
2209
        return $this->columnsInfo[$evidence];
2210
    }
2211
2212
    /**
2213
     * Gives you properties for (current) evidence column
2214
     *
2215
     * @param string $column    name of column
2216
     * @param string $evidence  evidence name if different
2217
     *
2218
     * @return array column properties or null if column not exits
2219
     */
2220
    public function getColumnInfo($column, $evidence = null) {
2221
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence() : $evidence);
2222
        return (empty($column) || empty($columnsInfo) || !is_array($columnsInfo)) ? null : (array_key_exists($column, $columnsInfo) ? $columnsInfo[$column] : null);
2223
    }
2224
2225
    /**
2226
     * Obtain actions for current (or given) evidence
2227
     *
2228
     * @param string $evidence
2229
     * 
2230
     * @return array Evidence structure
2231
     */
2232
    public function getActionsInfo($evidence = null) {
2233
        $actionsInfo = null;
2234
        if (is_null($evidence)) {
2235
            $evidence = $this->getEvidence();
2236
        }
2237
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2238
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2239
            $actionsInfo = Actions::$$propsName;
2240
        }
2241
        return $actionsInfo;
2242
    }
2243
2244
    /**
2245
     * Obtain relations for current (or given) evidence
2246
     *
2247
     * @param string $evidence
2248
     * 
2249
     * @return array Evidence structure
2250
     */
2251
    public function getRelationsInfo($evidence = null) {
2252
        $relationsInfo = null;
2253
        if (is_null($evidence)) {
2254
            $evidence = $this->getEvidence();
2255
        }
2256
        $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2257
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2258
            $relationsInfo = Relations::$$propsName;
2259
        }
2260
        return $relationsInfo;
2261
    }
2262
2263
    /**
2264
     * Obtain info for current (or given) evidence
2265
     *
2266
     * @param string $evidence
2267
     * 
2268
     * @return array Evidence info
2269
     */
2270
    public function getEvidenceInfo($evidence = null) {
2271
        $evidencesInfo = null;
2272
        if (is_null($evidence)) {
2273
            $evidence = $this->getEvidence();
2274
        }
2275
        if (isset(EvidenceList::$evidences[$evidence])) {
2276
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2277
            $propsName = lcfirst(FlexiBeeRO::evidenceToClassName($evidence));
2278
            if (isset(Formats::$$propsName)) {
2279
                $evidencesInfo['formats'] = Formats::$$propsName;
2280
            }
2281
        }
2282
        return $evidencesInfo;
2283
    }
2284
2285
    /**
2286
     * Obtain name for current (or given) evidence path
2287
     *
2288
     * @param string $evidence Evidence Path
2289
     * 
2290
     * @return array Evidence info
2291
     */
2292
    public function getEvidenceName($evidence = null) {
2293
        $evidenceName = null;
2294
        if (is_null($evidence)) {
2295
            $evidence = $this->getEvidence();
2296
        }
2297
        if (isset(EvidenceList::$name[$evidence])) {
2298
            $evidenceName = EvidenceList::$name[$evidence];
2299
        }
2300
        return $evidenceName;
2301
    }
2302
2303
    /**
2304
     * Save current object to file
2305
     *
2306
     * @param string $destfile path to file
2307
     */
2308
    public function saveResponseToFile($destfile) {
2309
        if (strlen($this->lastCurlResponse)) {
2310
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2311
        }
2312
        file_put_contents($destfile, $this->lastCurlResponse);
2313
    }
2314
2315
    /**
2316
     * Obtain established relations listing
2317
     *
2318
     * @return array Null or Relations
2319
     */
2320
    public function getVazby($id = null) {
2321
        if (is_null($id)) {
2322
            $id = $this->getRecordID();
2323
        }
2324
        if (!empty($id)) {
2325
            $vazbyRaw = $this->getColumnsFromFlexibee(['vazby'],
2326
                    ['relations' => 'vazby', 'id' => $id]);
2327
            $vazby = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby'] : null;
2328
        } else {
2329
            throw new \Exception(_('ID requied to get record relations '));
2330
        }
2331
        return $vazby;
2332
    }
2333
2334
    /**
2335
     * Gives You URL for Current Record in FlexiBee web interface
2336
     *
2337
     * @return string url
2338
     */
2339
    public function getFlexiBeeURL() {
2340
        $parsed_url = parse_url(str_replace('.' . $this->format, '', $this->apiURL));
2341
        $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
2342
        $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2343
        $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
2344
        $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2345
        $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
2346
        $pass = ($user || $pass) ? "$pass@" : '';
2347
        $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2348
        return $scheme . $user . $pass . $host . $port . $path;
2349
    }
2350
2351
    /**
2352
     * Set Record Key
2353
     *
2354
     * @param int|string $myKeyValue
2355
     * 
2356
     * @return boolean
2357
     */
2358
    public function setMyKey($myKeyValue) {
2359
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2360
            if ($this->evidenceInfo['extIdSupported'] == 'false') {
2361
                $this->addStatusMessage(sprintf(_('Evidence %s does not support extIDs'),
2362
                                $this->getEvidence()), 'warning');
2363
                $res = false;
2364
            } else {
2365
                $extIds = $this->getDataValue('external-ids');
2366
                if (!empty($extIds) && count($extIds)) {
2367
                    $extIds = array_combine($extIds, $extIds);
2368
                }
2369
2370
                $extIds[$myKeyValue] = $myKeyValue;
2371
                $res = $this->setDataValue('external-ids',
2372
                        $extIds);
2373
            }
2374
        } else {
2375
            $res = $this->setDataValue($this->getKeyColumn(), $myKeyValue);
2376
        }
2377
        $this->updateApiURL();
2378
        return $res;
2379
    }
2380
2381
    /**
2382
     * Set or get ignore not found pages flag
2383
     *
2384
     * @param boolean $ignore set flag to
2385
     *
2386
     * @return boolean get flag state
2387
     */
2388
    public function ignore404($ignore = null) {
2389
        if (!is_null($ignore)) {
2390
            $this->ignoreNotFound = $ignore;
2391
        }
2392
        return $this->ignoreNotFound;
2393
    }
2394
2395
    /**
2396
     * Send Document by mail
2397
     *
2398
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2399
     *
2400
     * @param string $to         Email ecipient
2401
     * @param string $subject    Email Subject
2402
     * @param string $body       Email Text
2403
     *
2404
     * @return boolean mail sent status
2405
     */
2406
    public function sendByMail($to, $subject, $body, $cc = null) {
2407
        $this->setPostFields($body);
2408
2409
        $this->performRequest(rawurlencode($this->getRecordID()) . '/odeslani-dokladu?to=' . $to . '&subject=' . urlencode($subject) . '&cc=' . $cc
2410
                , 'PUT', 'xml');
2411
2412
        return $this->lastResponseCode == 200;
2413
    }
2414
2415
    /**
2416
     * Send all unsent Documents by eMail
2417
     *
2418
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2419
     * 
2420
     * @return int http response code
2421
     */
2422
    public function sendUnsent() {
2423
        return $this->doCurlRequest('automaticky-odeslat-neodeslane', 'PUT',
2424
                        'xml');
2425
    }
2426
2427
    /**
2428
     * FlexiBee date to PHP DateTime conversion
2429
     *
2430
     * @param string $flexidate 2017-05-26 or 2017-05-26+02:00
2431
     *
2432
     * @return \DateTime | false
2433
     */
2434
    public static function flexiDateToDateTime($flexidate) {
2435
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat . 'O' : self::$DateFormat, $flexidate)->setTime(0, 0);
2436
    }
2437
2438
    /**
2439
     * FlexiBee dateTime to PHP DateTime conversion
2440
     *
2441
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2442
     *
2443
     * @return \DateTime | false
2444
     */
2445
    public static function flexiDateTimeToDateTime($flexidatetime) {
2446
        if (strchr($flexidatetime, '.')) { //NewFormat
2447
            $format = self::$DateTimeFormat;
2448
        } else { // Old format
2449
            $format = 'Y-m-d\TH:i:s+P';
2450
        }
2451
        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 2451 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...
2452
    }
2453
2454
    /**
2455
     * Získá dokument v daném formátu
2456
     * Obtain document in given format
2457
     *
2458
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2459
     *
2460
     * @param string  $format     pdf/csv/xml/json/ ...
2461
     * @param string  $reportName Template used to generate PDF
2462
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2463
     * @param boolean $sign       sign resulting PDF by certificate ?
2464
     *
2465
     * @return string|null filename downloaded or none
2466
     */
2467
    public function getInFormat($format, $reportName = null, $lang = null,
2468
            $sign = false) {
2469
        $response = null;
2470
        if ($this->setFormat($format)) {
2471
            $urlParams = [];
2472
            switch ($format) {
2473
                case 'pdf':
2474
                    switch ($lang) {
2475
                        case 'cs':
2476
                        case 'sk':
2477
                        case 'en':
2478
                        case 'de':
2479
                            $urlParams['report-lang'] = $lang;
2480
                            break;
2481
                        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...
2482
                        case '':
2483
                            break;
2484
                        default:
2485
                            throw new \Ease\Exception('Unknown language ' . $lang . ' for PDF export');
2486
                            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...
2487
                    }
2488
                    if (boolval($sign) === true) {
2489
                        $urlParams['report-sign'] = 'true';
2490
                    }
2491
                    break;
2492
                case 'html':
2493
                    $urlParams['inDesktopApp'] = 'true';
2494
                    break;
2495
            }
2496
            if (!empty($reportName)) {
2497
                $urlParams['report-name'] = $reportName;
2498
            }
2499
            if (($this->doCurlRequest(\Ease\Functions::addUrlParams($this->apiURL,
2500
                                    $urlParams), 'GET') == 200)) {
2501
                $response = $this->lastCurlResponse;
2502
            }
2503
        }
2504
        return $response;
2505
    }
2506
2507
    /**
2508
     * Uloží dokument v daném formátu do složky v systému souborů
2509
     * Save document in given format to directory in filesystem
2510
     *
2511
     * @param string $format  pdf/csv/xml/json/ ...
2512
     * @param string $destDir where to put file (prefix)
2513
     * @param string $reportName Template used to generate PDF
2514
     *
2515
     * @return string|null filename downloaded or none
2516
     */
2517
    public function downloadInFormat($format, $destDir = './',
2518
            $reportName = null) {
2519
        $fileOnDisk = null;
2520
        $formatBackup = $this->format;
2521
        if ($this->setFormat($format)) {
2522
            $downloadTo = $destDir . $this->getEvidence() . '_' . $this->getMyKey() . '.' . $format;
2523
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Functions::addUrlParams($this->apiURL,
2524
                                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2525
                            $this->lastCurlResponse) !== false)) {
2526
                $fileOnDisk = $downloadTo;
2527
            }
2528
            $this->setFormat($formatBackup);
2529
        }
2530
        return $fileOnDisk;
2531
    }
2532
2533
    /**
2534
     * Take data for object. separate external IDs
2535
     *
2536
     * @param array $data Data to keep
2537
     * 
2538
     * @return int number of records taken
2539
     */
2540
    public function takeData($data) {
2541
        $keyColumn = $this->getKeyColumn();
2542
        if (array_key_exists($keyColumn, $data) && is_array($data[$keyColumn])) {
2543
            foreach ($data[$keyColumn] as $recPos => $recordKey) {
2544
                if (substr($recordKey, 0, 4) == 'ext:') {
2545
                    $data['external-ids'][] = $recordKey;
2546
                    unset($data[$keyColumn][$recPos]);
2547
                }
2548
            }
2549
            if (count($data[$keyColumn]) == 1) {
2550
                $data[$keyColumn] = current($data[$keyColumn]);
2551
            }
2552
        }
2553
        $result = parent::takeData($data);
2554
2555
        if (array_key_exists($keyColumn, $data) || array_key_exists('kod', $data)) {
2556
            $this->updateApiURL();
2557
        }
2558
2559
        return $result;
2560
    }
2561
2562
    /**
2563
     * Get Current Evidence reports listing
2564
     * 
2565
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2566
     * 
2567
     * @return array
2568
     */
2569
    public function getReportsInfo() {
2570
        $reports = [];
2571
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL() . '/reports');
2572
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports']) && array_key_exists('report', $reportsRaw['reports']) &&
2573
                !empty($reportsRaw['reports']['report'])) {
2574
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
2575
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2576
            } else {
2577
                $reports = \Ease\Functions::reindexArrayBy($reportsRaw['reports']['report'],
2578
                                'reportId');
2579
            }
2580
        }
2581
        return $reports;
2582
    }
2583
2584
    /**
2585
     * Request authSessionId from current server
2586
     * 
2587
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2588
     * 
2589
     * @param string $username
2590
     * @param string $password
2591
     * @param string $otp       optional onetime password
2592
     * 
2593
     * @return string authUserId or null in case of problems
2594
     */
2595
    public function requestAuthSessionID($username, $password, $otp = null) {
2596
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2597
            'password' => $password] : ['username' => $username, 'password' => $password,
2598
            'otp' => $otp]);
2599
        $response = $this->performRequest('/login-logout/login', 'POST',
2600
                'json');
2601
        if (array_key_exists('refreshToken', $response)) {
2602
            $this->refreshToken = $response['refreshToken'];
2603
        } else {
2604
            $this->refreshToken = null;
2605
        }
2606
        return array_key_exists('authSessionId', $response) ? $response['authSessionId'] : null;
2607
    }
2608
2609
    /**
2610
     * Try to Sign in current user to FlexiBee and keep authSessionId
2611
     * 
2612
     * @return boolean sign in success
2613
     */
2614
    public function login() {
2615
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2616
                $this->password);
2617
        return $this->lastResponseCode == 200;
2618
    }
2619
2620
    /**
2621
     * End (current's user) session
2622
     * 
2623
     * 
2624
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2625
     * 
2626
     * @param string $username force username to sign off
2627
     * 
2628
     * @return array server response
2629
     */
2630
    public function logout($username = null) {
2631
        return $this->performRequest('/status/user/' . (is_null($username) ? $this->user : $username) . '/logout', 'POST');
2632
    }
2633
2634
    /**
2635
     * Compile and send Report about Error500 to FlexiBee developers
2636
     * If FlexiBee is running on localost try also include java backtrace
2637
     *
2638
     * @param array $errorResponse result of parseError();
2639
     */
2640
    public function error500Reporter($errorResponse) {
2641
        $ur = str_replace('/c/' . $this->company, '',
2642
                str_replace($this->url, '', $this->curlInfo['url']));
2643
        if (!array_key_exists($ur, $this->reports)) {
2644
            $tmpdir = sys_get_temp_dir();
2645
            $myTime = $this->curlInfo['when'];
2646
            $curlname = $tmpdir . '/curl-' . $this->evidence . '-' . $myTime . '.json';
2647
            file_put_contents($curlname,
2648
                    json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2649
2650
            $report = new \Ease\Mailer($this->reportRecipient,
2651
                    'Error report 500 - ' . $ur);
2652
2653
            $d = dir($tmpdir);
2654
            while (false !== ($entry = $d->read())) {
2655
                if (strstr($entry, $myTime)) {
2656
                    $ext = pathinfo($tmpdir . '/' . $entry, PATHINFO_EXTENSION);
2657
                    $mime = Formats::suffixToContentType($ext);
2658
                    $report->addFile($tmpdir . '/' . $entry,
2659
                            empty($mime) ? 'text/plain' : $mime);
2660
                }
2661
            }
2662
            $d->close();
2663
2664
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2665
                            '://127.')) && file_exists('/var/log/flexibee.log')) {
2666
2667
                $fl = fopen('/var/log/' . 'flexibee.log', 'r');
2668
                if ($fl) {
2669
                    $tracelog = [];
2670
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2671
                                    $x_pos, SEEK_END) !== -1; $x_pos--) {
2672
                        $char = fgetc($fl);
2673
                        if ($char === "\n") {
2674
                            $tracelog[] = $output[$ln];
2675
                            if (strstr($output[$ln], $errorResponse['message'])) {
2676
                                break;
2677
                            }
2678
                            $ln++;
2679
                            continue;
2680
                        }
2681
                        $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : '');
2682
                    }
2683
2684
                    $trace = implode("\n", array_reverse($tracelog));
2685
                    $tracefile = $tmpdir . '/trace-' . $this->evidence . '-' . $myTime . '.log';
2686
                    file_put_contents($tracefile, $trace);
2687
                    $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...
2688
                    fclose($fl);
2689
                }
2690
            } else {
2691
                $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...
2692
            }
2693
2694
            $licenseInfo = $this->performRequest($this->url . '/default-license.json');
2695
2696
            $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...
2697
                            JSON_PRETTY_PRINT));
2698
2699
            if ($report->send()) {
2700
                $this->reports[$ur] = $myTime;
2701
            }
2702
        }
2703
    }
2704
2705
    /**
2706
     * Returns code:CODE
2707
     *
2708
     * @param string $code
2709
     *
2710
     * @return string
2711
     */
2712
    public static function code($code) {
2713
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:' . strtoupper(self::uncode($code)));
2714
    }
2715
2716
    /**
2717
     * Returns CODE without code: prefix
2718
     *
2719
     * @param string $code
2720
     *
2721
     * @return string
2722
     */
2723
    public static function uncode($code) {
2724
        return str_replace(['code:', 'code%3A'], '', $code);
2725
    }
2726
2727
    /**
2728
     * Remove all @ items from array
2729
     *
2730
     * @param array $data original data
2731
     *
2732
     * @return array data without @ columns
2733
     */
2734
    public static function arrayCleanUP($data) {
2735
        return array_filter(
2736
                $data,
2737
                function ($key) {
2738
            return !strchr($key, '@');
2739
        }, ARRAY_FILTER_USE_KEY);
2740
    }
2741
2742
    /**
2743
     * Add Info about used user, server and libraries
2744
     *
2745
     * @param string $prefix banner prefix text
2746
     * @param string $suffix banner suffix text
2747
     */
2748
    public function logBanner($prefix = null, $suffix = null) {
2749
        parent::logBanner($prefix,
2750
                ' FlexiBee ' . str_replace('://', '://' . $this->user . '@',
2751
                        $this->getApiUrl()) . ' FlexiBeeHP v' . self::$libVersion . ' (FlexiBee ' . EvidenceList::$version . ') EasePHP Framework v' . \Ease\Atom::$frameworkVersion . ' ' .
2752
                $suffix
2753
        );
2754
    }
2755
2756
    /**
2757
     * Get Last operation type
2758
     * 
2759
     * @return string create|read|update|delete or update,insert for some inserted and updated in one transaction
2760
     */
2761
    public function getLastOperationType() {
2762
        return implode(',', array_keys(array_filter($this->responseStats)));
2763
    }
2764
2765
    /**
2766
     * Last operation errors 
2767
     * 
2768
     * @return array FlexiBee error meassages
2769
     */
2770
    public function getErrors() {
2771
        return $this->errors;
2772
    }
2773
2774
    /**
2775
     * Reconnect After unserialization
2776
     */
2777
    public function __wakeup() {
2778
        $this->curlInit();
2779
    }
2780
2781
}
2782