Completed
Push — master ( 922354...8b82c3 )
by Vítězslav
25:02 queued 12s
created

FlexiBeeRO::setupProperty()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 5
nop 3
dl 0
loc 13
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * FlexiPeeHP - Read Only Access to FlexiBee class.
5
 *
6
 * @author     Vítězslav Dvořák <[email protected]>
7
 * @copyright  (C) 2015-2019 Spoje.Net
8
 */
9
10
namespace FlexiPeeHP;
11
12
/**
13
 * Základní třída pro čtení z FlexiBee
14
 *
15
 * @url https://demo.flexibee.eu/devdoc/
16
 */
17
class FlexiBeeRO extends \Ease\Sand {
18
19
    use \Ease\RecordKey;
20
21
    /**
22
     * Where to get JSON files with evidence stricture etc.
23
     * @var string
24
     */
25
    public static $infoDir = __DIR__ . '/../../static';
26
27
    /**
28
     * Version of FlexiPeeHP library
29
     *
30
     * @var string
31
     */
32
    public static $libVersion = '1.34';
33
34
    /**
35
     * Základní namespace pro komunikaci s FlexiBee.
36
     * Basic namespace for communication with FlexiBee
37
     *
38
     * @var string Jmený prostor datového bloku odpovědi
39
     */
40
    public $nameSpace = 'winstrom';
41
42
    /**
43
     * URL of object data in FlexiBee
44
     * @var string url
45
     */
46
    public $apiURL = null;
47
48
    /**
49
     * Datový blok v poli odpovědi.
50
     * Data block in response field.
51
     *
52
     * @var string
53
     */
54
    public $resultField = 'results';
55
56
    /**
57
     * Verze protokolu použitého pro komunikaci.
58
     * Communication protocol version used.
59
     *
60
     * @var string Verze použitého API
61
     */
62
    public $protoVersion = '1.0';
63
64
    /**
65
     * Evidence užitá objektem.
66
     * Evidence used by object
67
     *
68
     * @link https://demo.flexibee.eu/c/demo/evidence-list Přehled evidencí
69
     * @var string
70
     */
71
    public $evidence = null;
72
73
    /**
74
     * Detaily evidence užité objektem
75
     * 
76
     * @var array 
77
     */
78
    public $evidenceInfo = [];
79
80
    /**
81
     * Výchozí formát pro komunikaci.
82
     * Default communication format.
83
     *
84
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
85
     *
86
     * @var string json|xml|...
87
     */
88
    public $format = 'json';
89
90
    /**
91
     * formát příchozí odpovědi
92
     * response format
93
     *
94
     * @link https://www.flexibee.eu/api/dokumentace/ref/format-types Přehled možných formátů
95
     *
96
     * @var string json|xml|...
97
     */
98
    public $responseFormat = 'json';
99
100
    /**
101
     * Curl Handle.
102
     *
103
     * @var resource
104
     */
105
    public $curl = null;
106
107
    /**
108
     * @link https://demo.flexibee.eu/devdoc/company-identifier Identifikátor firmy
109
     * @var string
110
     */
111
    public $company = null;
112
113
    /**
114
     * [protocol://]Server[:port]
115
     * @var string
116
     */
117
    public $url = null;
118
119
    /**
120
     * REST API Username
121
     * @var string
122
     */
123
    public $user = null;
124
125
    /**
126
     * REST API Password
127
     * @var string
128
     */
129
    public $password = null;
130
131
    /**
132
     * @var array Pole HTTP hlaviček odesílaných s každým požadavkem
133
     */
134
    public $defaultHttpHeaders = ['User-Agent' => 'FlexiPeeHP'];
135
136
    /**
137
     * Default additional request url parameters after question mark
138
     *
139
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls   Common params
140
     * @link https://www.flexibee.eu/api/dokumentace/ref/paging Paging params
141
     * @var array
142
     */
143
    public $defaultUrlParams = [];
144
145
    /**
146
     * Identifikační řetězec.
147
     *
148
     * @var string
149
     */
150
    public $init = null;
151
152
    /**
153
     * Sloupeček s názvem.
154
     *
155
     * @var string
156
     */
157
    public $nameColumn = 'nazev';
158
159
    /**
160
     * Sloupeček obsahující datum vložení záznamu do shopu.
161
     *
162
     * @var string
163
     */
164
    public $myCreateColumn = 'false';
165
166
    /**
167
     * Slopecek obsahujici datum poslení modifikace záznamu do shopu.
168
     *
169
     * @var string
170
     */
171
    public $myLastModifiedColumn = 'lastUpdate';
172
173
    /**
174
     * Klíčový idendifikátor záznamu.
175
     *
176
     * @var string
177
     */
178
    public $fbKeyColumn = 'id';
179
180
    /**
181
     * Informace o posledním HTTP requestu.
182
     *
183
     * @var *
184
     */
185
    public $curlInfo;
186
187
    /**
188
     * Informace o poslední HTTP chybě.
189
     *
190
     * @var string
191
     */
192
    public $lastCurlError = null;
193
194
    /**
195
     * Used codes storage.
196
     *
197
     * @var array
198
     */
199
    public $codes = null;
200
201
    /**
202
     * Last Inserted ID.
203
     *
204
     * @var int
205
     */
206
    public $lastInsertedID = null;
207
208
    /**
209
     * Default Line Prefix.
210
     *
211
     * @var string
212
     */
213
    public $prefix = '/c/';
214
215
    /**
216
     * Raw Content of last curl response
217
     *
218
     * @var string
219
     */
220
    public $lastCurlResponse;
221
222
    /**
223
     * HTTP Response code of last request
224
     *
225
     * @var int
226
     */
227
    public $lastResponseCode = null;
228
229
    /**
230
     * Body data  for next curl POST operation
231
     *
232
     * @var string
233
     */
234
    protected $postFields = null;
235
236
    /**
237
     * Last operation result data or message(s)
238
     *
239
     * @var array
240
     */
241
    public $lastResult = null;
242
243
    /**
244
     * Number from  @rowCount in response
245
     * @var int
246
     */
247
    public $rowCount = null;
248
249
    /**
250
     * Number from  @globalVersion
251
     * @var int
252
     */
253
    public $globalVersion = null;
254
255
    /**
256
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
257
     * @var string filter query
258
     */
259
    public $filter;
260
261
    /**
262
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
263
     * @var string
264
     */
265
    protected $action;
266
267
    /**
268
     * Pole akcí které podporuje ta která evidence
269
     * @link https://demo.flexibee.eu/c/demo/faktura-vydana/actions.json Např. Akce faktury
270
     * @var array
271
     */
272
    public $actionsAvailable = null;
273
274
    /**
275
     * Parmetry pro URL
276
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Všechny podporované parametry
277
     * @var array
278
     */
279
    public $urlParams = [
280
        'add-global-version' => ['type' => 'boolean', 'description' => 'The response will contain the global version number of the current export'],
281
        'add-row-count' => ['type' => 'boolean', 'description' => 'Adding Total Records to Output (Pagination)'],
282
        'as-gui' => ['type' => 'boolean', 'description' => 'Turns on functions that complement the GUI processing outputs'],
283
        'auth' => ['type' => 'string', 'description' => 'http: Forces login using HTTP authentication, for example, to change the default WUI login method. html: Force HTML form authentication. This can be useful to suppress automatic SSO authentication.'],
284
        'authSessionId' => ['type' => 'string', 'description' => 'Authentification Session ID'],
285
        'code-as-id' => ['type' => 'boolean', 'description' => 'If an object has unique code, it is also exported (except for the <code> element) as <id> code: ... </id>'],
286
        'code-in-response' => ['type' => 'boolean', 'description' => 'The response will contain not only ID and URL for each object, but also code.'],
287
        'delimeter' => ['type' => 'string', 'description' => 'Specifies the input / output file separator in CSV format.',
288
            'example' => ';'],
289
        'detail' => ['type' => 'string', 'description' => 'Definition of the level of detail'], //See: https://www.flexibee.eu/api/dokumentace/ref/detail-levels
290
        'dir' => ['type' => 'string', 'description' => 'Sorting direction.', 'example' => 'desc'],
291
        'dry-run' => ['type' => 'boolean', 'description' => 'Test run (dry-run)'], // See: https://www.flexibee.eu/api/dokumentace/ref/dry-run/
292
        'encoding' => ['type' => 'string', 'description' => 'Specifies the encoding of the input / output file in CSV format.'],
293
        'export-settings' => ['type' => 'boolean', 'description' => 'Export one extra entry with current settings at the beginning'],
294
        'fail-on-warning' => ['type' => 'boolean', 'description' => 'If a warning occurs, do not save a record (Data Validation)'],
295
        'filter' => ['type' => 'string', 'description' => 'filter results by this param'],
296
        'format' => ['type' => 'string', 'description' => 'One of the compiled XSL transforms will be applied to the output XML.'],
297
        'idUcetniObdobi' => ['type' => 'string', 'description' => ''], //See: https://www.flexibee.eu/api/dokumentace/ref/stavy-uctu/
298
        'includes' => ['type' => 'string', 'description' => 'Include related detail level object ',
299
            'example' => 'faktura-vydana/stredisko'],
300
        'inDesktopApp' => ['type' => 'boolean', 'description' => 'Hide menu and navigation in html format'], // Note: Undocumented function (html only)
301
        'limit' => ['type' => 'integer', 'description' => 'number of requested results'],
302
        'mode' => ['type' => 'string', 'description' => 'Support for RubyOnRails',
303
            'example' => 'ruby'],
304
        'no-ext-ids' => ['type' => 'boolean', 'description' => 'The answer will not contain external identifiers (performance optimization)'],
305
        'no-http-errors' => ['type' => 'boolean', 'description' => 'If a 4xx error occurs while processing a request, the server sends 200 OK anyway'],
306
        'no-ids' => ['type' => 'boolean', 'description' => 'The response will not contain any primary identifiers (performance optimization). It only affects the main records.'],
307
        'only-ext-ids' => ['type' => 'boolean', 'description' => 'The primary key will not be exported, the <id> elements will only contain the external ID. Similar no-ids, but also affects subevidencies.'],
308
        'order' => ['type' => 'string', 'description' => 'Sorting records', 'example' => 'nazev@A'],
309
        'relations' => ['type' => 'string', 'description' => 'Adding session data (see detail levels) A session overview can be obtained for each record (/ relations).'],
310
        'report-lang' => ['type' => 'string', 'description' => 'The language in which to print the output when exporting to PDF',
311
            'example' => 'en'],
312
        'report-name' => ['type' => 'string', 'description' => 'The name of the printout when exporting to PDF',
313
            'example' => 'invoice'],
314
        'report-sign' => ['type' => 'string', 'description' => 'Whether the PDF should be exported electronically signed'],
315
        'skupina-stitku' => ['type' => 'string', 'description' => 'Enables grouping of labels when exporting by group (multiple labels)'],
316
        'sort' => ['type' => 'string', 'description' => 'Sorting records for ExtJS'],
317
        'start' => ['type' => 'integer', 'description' => 'Pagination'],
318
        'stitky-as-ids' => ['type' => 'boolean', 'description' => 'Labels will be exported and imported not as a code list but as a list of numeric IDs'],
319
        'use-ext-id' => ['type' => 'boolean', 'description' => 'If the object contains an external ESHOP or MY ID, use it as a bind.'],
320
        'use-internal-id' => ['type' => 'boolean', 'description' => 'In addition to the ref and showAs for objects, it also supplies an internalId attribute that contains the internal record ID'],
321
        'xpath' => ['type' => 'string', 'description' => 'Apply XPATH to result',
322
            'example' => '//winstrom/adresar/email/text()'] // See: https://www.flexibee.eu/api/dokumentace/ref/xpath/
323
    ];
324
325
    /**
326
     * Session ID
327
     * @var string
328
     */
329
    public $authSessionId = null;
330
331
    /**
332
     * Token obtained during login procedure
333
     * @var string 
334
     */
335
    public $refreshToken = null;
336
337
    /**
338
     * Save 404 results to log ?
339
     * @var boolean
340
     */
341
    protected $ignoreNotFound = false;
342
343
    /**
344
     * Array of errors caused by last request
345
     * @var array
346
     */
347
    private $errors = [];
348
349
    /**
350
     * List of Error500 reports sent
351
     * @var array
352
     */
353
    private $reports = [];
354
355
    /**
356
     * Send Error500 Report to
357
     * @var string email address
358
     */
359
    public $reportRecipient = '[email protected]';
360
361
    /**
362
     * Formating string for \DateTime::format() for datetime columns
363
     * @var string
364
     */
365
    static public $DateTimeFormat = 'Y-m-d\TH:i:s.u+P';
366
367
    /**
368
     * Formating string for \DateTime::format() for date columns
369
     * @var string
370
     */
371
    static public $DateFormat = 'Y-m-d';
372
373
    /**
374
     * Last Request response stats
375
     * @var array 
376
     */
377
    protected $responseStats = null;
378
379
    /**
380
     * Chained Objects
381
     * @var array
382
     */
383
    public $chained = [];
384
385
    /**
386
     * We Connect to server by default
387
     * @var boolean
388
     */
389
    public $offline = false;
390
391
    /**
392
     * Override cURL timeout
393
     * @var int seconds
394
     */
395
    public $timeout = null;
396
397
    /**
398
     * Columns Info for serveral evidencies
399
     * @var array 
400
     */
401
    private $columnsInfo = [];
402
403
    /**
404
     * Throw Exception in case of FlexiBee error
405
     * @var boolean 
406
     */
407
    public $throwException = false;
408
409
    /**
410
     * Class for read only interaction with FlexiBee.
411
     *
412
     * @param mixed $init default record id or initial data. See processInit()
413
     * @param array $options Connection settings and other options override
414
     */
415
    public function __construct($init = null, $options = []) {
416
        $this->init = $init;
417
418
        $this->setUp($options);
419
        $this->curlInit();
420
        if (!empty($init)) {
421
            $this->processInit($init);
422
        }
423
    }
424
425
    /**
426
     * Set internal Object name
427
     *
428
     * @param string $objectName
429
     *
430
     * @return string Jméno objektu
431
     */
432
    public function setObjectName($objectName = null) {
433
        return parent::setObjectName(is_null($objectName) ? ( empty($this->getRecordIdent()) ? $this->getObjectName() : $this->getRecordIdent() . '@' . $this->getObjectName() ) : $objectName);
434
    }
435
436
    /**
437
     * SetUp Object to be ready for work
438
     *
439
     * @param array $options Object Options ( user,password,authSessionId
440
     *                                        company,url,evidence,
441
     *                                        prefix,defaultUrlParams,debug,
442
     *                                        detail,offline,filter,ignore404
443
     *                                        timeout,companyUrl,ver,throwException
444
     */
445
    public function setUp($options = []) {
446
        if (array_key_exists('ver', $options)) {
447
            $this->protoVersion = $options['ver'];
448
            $this->prefix = 'v' . round($this->protoVersion) . '/c/';
449
        }
450
        if (array_key_exists('companyUrl', $options)) {
451
            $options = array_merge(self::companyUrlToOptions($options['companyUrl']),
452
                    $options);
453
        }
454
455
        $this->setupProperty($options, 'company', 'FLEXIBEE_COMPANY');
456
        $this->setupProperty($options, 'url', 'FLEXIBEE_URL');
457
        $this->setupProperty($options, 'user', 'FLEXIBEE_LOGIN');
458
        $this->setupProperty($options, 'password', 'FLEXIBEE_PASSWORD');
459
        $this->setupProperty($options, 'authSessionId', 'FLEXIBEE_AUTHSESSID');
460
        $this->setupProperty($options, 'timeout', 'FLEXIBEE_TIMEOUT');
461
        if (!empty($this->authSessionId)) {
462
            $this->defaultHttpHeaders['X-authSessionId'] = $this->authSessionId;
463
        }
464
        if (isset($options['evidence'])) {
465
            $this->setEvidence($options['evidence']);
466
        }
467
        $this->setupProperty($options, 'defaultUrlParams');
468
        if (isset($options['prefix'])) {
469
            $this->setPrefix($options['prefix']);
470
        }
471
        if (array_key_exists('detail', $options)) {
472
            $this->defaultUrlParams['detail'] = $options['detail'];
473
        }
474
        $this->setupProperty($options, 'filter');
475
        if (array_key_exists('offline', $options)) {
476
            $this->offline = (boolean) $options['offline'];
477
        }
478
479
        if (array_key_exists('ignore404', $options)) {
480
            $this->ignore404($options['ignore404']);
481
        }
482
483
        $this->setupProperty($options, 'throwException', 'FLEXIBEE_EXCEPTIONS');
484
        $this->setupProperty($options, 'debug');
485
        $this->updateApiURL();
486
    }
487
488
    /**
489
     * Set up one of properties
490
     *
491
     * @param array  $options  array of given properties
492
     * @param string $name     name of property to process
493
     * @param string $constant load default property value from constant
494
     */
495
    public function setupProperty($options, $name, $constant = null) {
496
        if (array_key_exists($name, $options)) {
497
            $this->$name = $options[$name];
498
        } elseif (array_key_exists($constant, $options)) {
499
            $this->$name = $options[$constant];
500
        } elseif (property_exists($this, $name) && ($env = getenv($constant)) && !empty($env)) {
501
            $this->$name = getenv($constant);
502
        } else {
503
            if (property_exists($this, $name) && !empty($constant) && defined($constant)) {
504
                $this->$name = constant($constant);
505
            }
506
        }
507
    }
508
509
    /**
510
     * Convert companyUrl provided by CustomButton to options array
511
     * 
512
     * @param string $companyUrl
513
     * 
514
     * @return array Options
515
     */
516
    public static function companyUrlToOptions($companyUrl) {
517
        $urlParts = parse_url($companyUrl);
518
        $scheme = isset($urlParts['scheme']) ? $urlParts['scheme'] . '://' : '';
519
        $host = isset($urlParts['host']) ? $urlParts['host'] : '';
520
        $port = isset($urlParts['port']) ? ':' . $urlParts['port'] : '';
521
        $path = isset($urlParts['path']) ? $urlParts['path'] : '';
522
523
        $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...
524
        $options['url'] = $scheme . $host . $port;
525
        return $options;
526
    }
527
528
    /**
529
     * Get Current connection options for use in another object
530
     *
531
     * @return array usable as second constructor parameter
532
     */
533
    public function getConnectionOptions() {
534
        $conOpts = ['url' => $this->url];
535
        if (empty($this->authSessionId)) {
536
            $conOpts ['user'] = $this->user;
537
            $conOpts['password'] = $this->password;
538
        } else {
539
            $conOpts['authSessionId'] = $this->authSessionId;
540
        }
541
        $company = $this->getCompany();
542
        if (!empty($company)) {
543
            $conOpts['company'] = $company;
544
        }
545
        if (!is_null($this->timeout)) {
546
            $conOpts['timeout'] = $this->timeout;
547
        }
548
        return $conOpts;
549
    }
550
551
    /**
552
     * Inicializace CURL
553
     *
554
     * @return boolean Online Status
555
     */
556
    public function curlInit() {
557
        if ($this->offline === false) {
558
            $this->curl = \curl_init(); // create curl resource
559
            curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
560
            curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true); // follow redirects (compatibility for future changes in FlexiBee)
561
            curl_setopt($this->curl, CURLOPT_HTTPAUTH, true);       // HTTP authentication
562
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); // FlexiBee by default uses Self-Signed certificates
563
            curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false);
564
            curl_setopt($this->curl, CURLOPT_VERBOSE, ($this->debug === true)); // For debugging
565
            if (empty($this->authSessionId)) {
566
                curl_setopt($this->curl, CURLOPT_USERPWD,
567
                        $this->user . ':' . $this->password); // set username and password
568
            }
569
            if (!is_null($this->timeout)) {
570
                curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
571
            }
572
        }
573
        return !$this->offline;
574
    }
575
576
    /**
577
     * Zinicializuje objekt dle daných dat. Možné hodnoty:
578
     *
579
     *  * 234                              - interní číslo záznamu k načtení
580
     *  * code:LOPATA                      - kód záznamu
581
     *  * BAGR                             - kód záznamu k načtení
582
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
583
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
584
     *
585
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
586
     */
587
    public function processInit($init) {
588
        if (is_integer($init)) {
589
            $this->loadFromFlexiBee($init);
590
        } elseif (is_array($init)) {
591
            $this->takeData($init);
592
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
593
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init) : $init)));
594
        } else {
595
            $this->loadFromFlexiBee($init);
596
        }
597
    }
598
599
    /**
600
     * Set Data Field value
601
     *
602
     * @param string $columnName field name
603
     * @param mixed  $value      field data value
604
     *
605
     * @return bool Success
606
     */
607
    public function setDataValue($columnName, $value) {
608
        switch ($columnName) {
609
            case 'kod':
610
                $value = self::uncode($value); //Alwyas uncode "kod" column
611
612
            default:
613
                if (is_object($value)) {
614
                    switch (get_class($value)) {
615
                        case 'DateTime':
616
                            $columnInfo = $this->getColumnInfo($columnName);
617
                            switch ($columnInfo['type']) {
618
                                case 'date':
619
                                    $value = self::dateToFlexiDate($value);
620
                                    break;
621
                                case 'datetime':
622
                                    $value = self::dateToFlexiDateTime($value);
623
                                    break;
624
                            }
625
                            break;
626
                    }
627
                }
628
                $result = parent::setDataValue($columnName, $value);
629
                break;
630
        }
631
        return $result;
632
    }
633
634
    /**
635
     * PHP Date object to FlexiBee date format
636
     * 
637
     * @param \DateTime $date
638
     */
639
    public static function dateToFlexiDate($date) {
640
        return $date->format(self::$DateFormat);
641
    }
642
643
    /**
644
     * PHP Date object to FlexiBee date format
645
     * 
646
     * @param \DateTime $dateTime
647
     */
648
    public static function dateToFlexiDateTime($dateTime) {
649
        return $dateTime->format(self::$DateTimeFormat);
650
    }
651
652
    /**
653
     * Set URL prefix
654
     *
655
     * @param string $prefix
656
     */
657
    public function setPrefix($prefix) {
658
        switch ($prefix) {
659
            case 'a': //Access
660
            case 'c': //Company
661
            case 'u': //User
662
            case 'g': //License Groups
663
            case 'admin':
664
            case 'status':
665
            case 'login-logout':
666
                $this->prefix = '/' . $prefix . '/';
667
                break;
668
            case null:
669
            case '':
670
            case '/':
671
                $this->prefix = '';
672
                break;
673
            default:
674
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
675
        }
676
    }
677
678
    /**
679
     * Set communication format.
680
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
681
     *
682
     * @param string $format
683
     * 
684
     * @return boolean format is availble
685
     */
686
    public function setFormat($format) {
687
        $result = true;
688
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
689
            if (array_key_exists($format, array_flip(Formats::$$this->evidence)) === false) {
690
                $result = false;
691
            }
692
        }
693
        if ($result === true) {
694
            $this->format = $format;
695
            $this->updateApiURL();
696
        }
697
        return $result;
698
    }
699
700
    /**
701
     * Nastaví Evidenci pro Komunikaci.
702
     * Set evidence for communication
703
     *
704
     * @param string $evidence evidence pathName to use
705
     * 
706
     * @return boolean evidence switching status
707
     */
708
    public function setEvidence($evidence) {
709
        switch ($this->prefix) {
710
            case '/c/':
711
                if ($this->debug === true) {
712
                    if (array_key_exists($evidence, EvidenceList::$name)) {
713
                        $this->evidence = $evidence;
714
                        $result = true;
715
                    } else {
716
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
717
                                        $evidence));
718
                    }
719
                } else {
720
                    $this->evidence = $evidence;
721
                    $result = true;
722
                }
723
                break;
724
            default:
725
                $this->evidence = $evidence;
726
                $result = true;
727
                break;
728
        }
729
        $this->updateApiURL();
730
        $this->evidenceInfo = $this->getEvidenceInfo();
731
        return $result;
732
    }
733
734
    /**
735
     * Vrací právě používanou evidenci pro komunikaci
736
     * Obtain current used evidence
737
     *
738
     * @return string
739
     */
740
    public function getEvidence() {
741
        return $this->evidence;
742
    }
743
744
    /**
745
     * Set used company.
746
     * Nastaví Firmu.
747
     *
748
     * @param string $company
749
     */
750
    public function setCompany($company) {
751
        $this->company = $company;
752
    }
753
754
    /**
755
     * Obtain company now used
756
     * Vrací právě používanou firmu
757
     *
758
     * @return string
759
     */
760
    public function getCompany() {
761
        return $this->company;
762
    }
763
764
    /**
765
     * Vrací název evidence použité v odpovědích z FlexiBee
766
     *
767
     * @return string
768
     */
769
    public function getResponseEvidence() {
770
        switch ($this->evidence) {
771
            case 'c':
772
                $evidence = 'company';
773
                break;
774
            case 'evidence-list':
775
                $evidence = 'evidence';
776
                break;
777
            default:
778
                $evidence = $this->getEvidence();
779
                break;
780
        }
781
        return $evidence;
782
    }
783
784
    /**
785
     * Převede rekurzivně Objekt na pole.
786
     *
787
     * @param object|array $object
788
     *
789
     * @return array
790
     */
791
    public static function object2array($object) {
792
        $result = null;
793
        if (is_object($object)) {
794
            $objectData = get_object_vars($object);
795
            if (is_array($objectData) && count($objectData)) {
796
                $result = array_map('self::object2array', $objectData);
797
            }
798
        } else {
799
            if (is_array($object)) {
800
                foreach ($object as $item => $value) {
801
                    $result[$item] = self::object2array($value);
802
                }
803
            } else {
804
                $result = $object;
805
            }
806
        }
807
808
        return $result;
809
    }
810
811
    /**
812
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
813
     *
814
     * @param object|array $object
815
     *
816
     * @return array
817
     */
818
    public static function objectToID($object) {
819
        $resultID = null;
820
        if (is_object($object) && method_exists($object, '__toString')
821
        ) {
822
            $resultID = $object->__toString();
823
        } else {
824
            if (is_array($object)) {
825
                foreach ($object as $item => $value) {
826
                    $resultID[$item] = self::objectToID($value);
827
                }
828
            } else { //String
829
                $resultID = $object;
830
            }
831
        }
832
833
        return $resultID;
834
    }
835
836
    /**
837
     * Return basic URL for used Evidence
838
     *
839
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
840
     *
841
     * @return string Evidence URL
842
     */
843
    public function getEvidenceURL() {
844
        $evidenceUrl = $this->url . $this->prefix . $this->company;
845
        $evidence = $this->getEvidence();
846
        if (!empty($evidence)) {
847
            $evidenceUrl .= '/' . $evidence;
848
        }
849
        return $evidenceUrl;
850
    }
851
852
    /**
853
     * Add suffix to Evidence URL
854
     *
855
     * @param string $urlSuffix
856
     *
857
     * @return string
858
     */
859
    public function evidenceUrlWithSuffix($urlSuffix) {
860
        $evidenceUrl = $this->getEvidenceUrl();
861
        if (!empty($urlSuffix)) {
862
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0] != '?')) {
863
                $evidenceUrl .= '/';
864
            }
865
            $evidenceUrl .= $urlSuffix;
866
        }
867
        return $evidenceUrl;
868
    }
869
870
    /**
871
     * Update $this->apiURL
872
     */
873
    public function updateApiURL() {
874
        $this->apiURL = $this->getEvidenceURL();
875
        $rowIdentifier = $this->getRecordIdent();
876
        if (empty($rowIdentifier)) {
877
            $rowIdentifier = $this->getRecordCode();
878
            if (empty($rowIdentifier)) {
879
                $rowIdentifier = $this->getExternalID();
880
            }
881
        }
882
        if (!empty($rowIdentifier)) {
883
            $this->apiURL .= '/' . self::urlEncode($rowIdentifier);
884
        }
885
        $this->apiURL .= '.' . $this->format;
886
    }
887
888
    /*
889
     * Add Default Url params to given url if not overrided
890
     *
891
     * @param string $urlRaw
892
     *
893
     * @return string url with default params added
894
     */
895
896
    public function addDefaultUrlParams($urlRaw) {
897
        return \Ease\Functions::addUrlParams($urlRaw, $this->defaultUrlParams,
898
                        false);
899
    }
900
901
    /**
902
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
903
     *
904
     * @param string $urlSuffix část URL za identifikátorem firmy.
905
     * @param string $method    HTTP/REST metoda
906
     * @param string $format    Requested format
907
     * 
908
     * @return array|boolean Výsledek operace
909
     */
910
    public function performRequest($urlSuffix = null, $method = 'GET',
911
            $format = null) {
912
        $this->rowCount = null;
913
        $this->responseStats = [];
914
        $this->errors = [];
915
916
        if (preg_match('/^http/', $urlSuffix)) {
917
            $url = $urlSuffix;
918
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
919
            $url = $this->url . $urlSuffix;
920
        } else {
921
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
922
        }
923
924
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
925
                $method, $format);
926
927
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
928
                                $this->responseFormat), $responseCode);
929
    }
930
931
    /**
932
     * Parse Raw FlexiBee response in several formats
933
     *
934
     * @param string $responseRaw raw response body
935
     * @param string $format      Raw Response format json|xml|etc
936
     *
937
     * @return array
938
     */
939
    public function rawResponseToArray($responseRaw, $format) {
940
        $responseDecoded = [];
941
        if (!empty(trim($responseRaw))) {
942
            switch ($format) {
943
                case 'json':
944
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
945
                    break;
946
                case 'xml':
947
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
948
                    break;
949
                case 'txt':
950
                default:
951
                    $responseDecoded = [$this->lastCurlResponse];
952
                    break;
953
            }
954
        }
955
        return $responseDecoded;
956
    }
957
958
    /**
959
     * Convert FlexiBee Response JSON to Array
960
     *
961
     * @param string $rawJson
962
     *
963
     * @return array
964
     */
965
    public function rawJsonToArray($rawJson) {
966
        $responseDecoded = json_decode($rawJson, true, 10);
967
        $decodeError = json_last_error_msg();
968
        if ($decodeError == 'No error') {
969
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
970
                $responseDecoded = $responseDecoded[$this->nameSpace];
971
            }
972
        } else {
973
            if ($this->debug) {
974
                $this->addStatusMessage('JSON Decoder: ' . $decodeError, 'error');
975
                $this->addStatusMessage($rawJson, 'debug');
976
            }
977
        }
978
        return $responseDecoded;
979
    }
980
981
    /**
982
     * Convert FlexiBee Response XML to Array
983
     *
984
     * @param string $rawXML
985
     *
986
     * @return array
987
     */
988
    public function rawXmlToArray($rawXML) {
989
        return self::xml2array($rawXML);
990
    }
991
992
    /**
993
     * Parse Response array
994
     *
995
     * @param array $responseDecoded
996
     * @param int $responseCode Request Response Code
997
     *
998
     * @return array main data part of response
999
     */
1000
    public function parseResponse($responseDecoded, $responseCode) {
1001
        $mainResult = null;
1002
        switch ($responseCode) {
1003
            case 201: //We do not care about Success Write here
1004
                break;
1005
            case 200: //Success Read
1006
1007
                if (is_array($responseDecoded)) {
1008
                    if (isset($responseDecoded['@rowCount'])) {
1009
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
1010
                    }
1011
                    if (isset($responseDecoded['@globalVersion'])) {
1012
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
1013
                    }
1014
1015
                    $mainResult = $this->unifyResponseFormat($responseDecoded);
1016
1017
                    if (array_key_exists('stats', $responseDecoded)) {
1018
                        $this->responseStats = $responseDecoded['stats'];
1019
                    } elseif (!empty($mainResult)) {
1020
                        if (array_key_exists('success', $mainResult) && ($mainResult['success'] == 'false')) {
1021
                            $this->responseStats = ['read' => 0];
1022
                        } elseif (array_key_exists('properties', $mainResult)) {
1023
                            $this->responseStats = ['read' => 1];
1024
                        } else {
1025
                            $responseEvidence = $this->getResponseEvidence();
1026
                            if (!empty($this->rowCount)) {
1027
                                $this->responseStats = ['read' => $this->rowCount];
1028
                            } elseif (array_key_exists($responseEvidence,
1029
                                            $mainResult)) {
1030
                                $this->responseStats = ['read' => count($mainResult[$responseEvidence])];
1031
                            } else {
1032
                                $this->responseStats = ['read' => count($mainResult)];
1033
                            }
1034
                        }
1035
                    }
1036
                } else {
1037
                    $mainResult = $responseDecoded;
1038
                }
1039
1040
                $this->lastResult = $mainResult;
1041
                break;
1042
1043
            case 500: // Internal Server Error
1044
                if ($this->debug === true) {
1045
                    $this->error500Reporter($responseDecoded);
1046
                }
1047
            case 404: // Page not found
1048
                if ($this->ignoreNotFound === true) {
1049
                    break;
1050
                }
1051
            case 400: //Bad Request parameters
1052
            default: //Something goes wrong
1053
                if (is_array($responseDecoded)) {
1054
                    $this->parseError($responseDecoded);
1055
                }
1056
1057
                if ($this->throwException === true) {
1058
                    throw new \Ease\Exception(json_encode($this->getErrors()), $this->lastResponseCode);
1059
                } else {
1060
                    $this->addStatusMessage($this->lastResponseCode . ': ' . $this->curlInfo['url'],
1061
                            'warning');
1062
                    $this->logResult($responseDecoded, $this->curlInfo['url']);
1063
                }
1064
                break;
1065
        }
1066
        return $mainResult;
1067
    }
1068
1069
    /**
1070
     * Parse error message response
1071
     *
1072
     * @param array $responseDecoded
1073
     * 
1074
     * @return int number of errors processed
1075
     */
1076
    public function parseError(array $responseDecoded) {
1077
        if (array_key_exists('results', $responseDecoded)) {
1078
            $this->errors = $responseDecoded['results'][0]['errors'];
1079
            foreach ($this->errors as $errorInfo) {
1080
                $this->addStatusMessage($errorInfo['message'], 'error');
1081
                if (array_key_exists('for', $errorInfo)) {
1082
                    unset($errorInfo['message']);
1083
                    $this->addStatusMessage(json_encode($errorInfo), 'debug');
1084
                }
1085
            }
1086
        } else {
1087
            if (array_key_exists('message', $responseDecoded)) {
1088
                $this->errors = [['message' => $responseDecoded['message']]];
1089
            }
1090
        }
1091
        return count($this->errors);
1092
    }
1093
1094
    /**
1095
     * Vykonej HTTP požadavek
1096
     *
1097
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1098
     * @param string $url    URL požadavku
1099
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1100
     * @param string $format požadovaný formát komunikace
1101
     * 
1102
     * @return int HTTP Response CODE
1103
     */
1104
    public function doCurlRequest($url, $method, $format = null) {
1105
        if (is_null($format)) {
1106
            $format = $this->format;
1107
        }
1108
        curl_setopt($this->curl, CURLOPT_URL, $url);
1109
// Nastavení samotné operace
1110
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1111
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1112
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1113
1114
        $httpHeaders = $this->defaultHttpHeaders;
1115
1116
        $formats = Formats::bySuffix();
1117
1118
        if (!isset($httpHeaders['Accept'])) {
1119
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1120
        }
1121
        if (!isset($httpHeaders['Content-Type'])) {
1122
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1123
        }
1124
        $httpHeadersFinal = [];
1125
        foreach ($httpHeaders as $key => $value) {
1126
            if (($key == 'User-Agent') && ($value == 'FlexiPeeHP')) {
1127
                $value .= ' v' . self::$libVersion;
1128
            }
1129
            $httpHeadersFinal[] = $key . ': ' . $value;
1130
        }
1131
1132
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeadersFinal);
1133
1134
// Proveď samotnou operaci
1135
        $this->lastCurlResponse = curl_exec($this->curl);
1136
        $this->curlInfo = curl_getinfo($this->curl);
1137
        $this->curlInfo['when'] = microtime();
1138
        $this->curlInfo['request_headers'] = $httpHeadersFinal;
1139
        $this->responseFormat = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1140
                $url);
1141
        $this->lastResponseCode = $this->curlInfo['http_code'];
1142
        $this->lastCurlError = curl_error($this->curl);
1143
        if (strlen($this->lastCurlError)) {
1144
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1145
                            $this->lastResponseCode, $this->lastCurlError), 'error');
1146
        }
1147
1148
        if ($this->debug === true) {
1149
            $this->saveDebugFiles();
1150
        }
1151
1152
        return $this->lastResponseCode;
1153
    }
1154
1155
    /**
1156
     * Obtain json for application/json
1157
     * 
1158
     * @param string $contentType
1159
     * @param string $url
1160
     * 
1161
     * @return string response format
1162
     */
1163
    public function contentTypeToResponseFormat($contentType, $url = null) {
1164
        if (!empty($url)) {
1165
            $url = parse_url($url, PHP_URL_PATH);
1166
        }
1167
1168
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1169
                        strpos($contentType, ';')) : $contentType;
1170
1171
        switch ($url) {
1172
            case '/login-logout/login';
1173
                $responseFormat = 'json';
1174
                break;
1175
            default :
1176
                switch ($contentTypeClean) {
1177
                    case 'text/javascript':
1178
                        $responseFormat = 'js';
1179
                        break;
1180
1181
                    default:
1182
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1183
                        break;
1184
                }
1185
                break;
1186
        }
1187
1188
        return $responseFormat;
1189
    }
1190
1191
    /**
1192
     * Nastaví druh prováděné akce.
1193
     *
1194
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1195
     * @param string $action
1196
     * 
1197
     * @return boolean
1198
     */
1199
    public function setAction($action) {
1200
        $result = false;
1201
        $actionsAvailable = $this->getActionsInfo();
1202
        if (is_array($actionsAvailable) && array_key_exists($action,
1203
                        $actionsAvailable)) {
1204
            $this->action = $action;
1205
            $result = true;
1206
        }
1207
        return $result;
1208
    }
1209
1210
    /**
1211
     * Convert XML to array.
1212
     *
1213
     * @param string $xml
1214
     *
1215
     * @return array
1216
     */
1217
    public static function xml2array($xml) {
1218
        $arr = [];
1219
        if (!empty($xml)) {
1220
            if (is_string($xml)) {
1221
                $xml = simplexml_load_string($xml);
1222
            }
1223
            foreach ($xml->attributes() as $a) {
1224
                $arr['@' . $a->getName()] = strval($a);
1225
            }
1226
            foreach ($xml->children() as $r) {
1227
                if (count($r->children()) == 0) {
1228
                    $arr[$r->getName()] = strval($r);
1229
                } else {
1230
                    $arr[$r->getName()][] = self::xml2array($r);
1231
                }
1232
            }
1233
        }
1234
        return $arr;
1235
    }
1236
1237
    /**
1238
     * Odpojení od FlexiBee.
1239
     */
1240
    public function disconnect() {
1241
        if (is_resource($this->curl)) {
1242
            curl_close($this->curl);
1243
        }
1244
        $this->curl = null;
1245
    }
1246
1247
    /**
1248
     * Disconnect CURL befere pass away
1249
     */
1250
    public function __destruct() {
1251
        $this->disconnect();
1252
    }
1253
1254
    /**
1255
     * Načte řádek dat z FlexiBee.
1256
     *
1257
     * @param int $recordID id požadovaného záznamu
1258
     *
1259
     * @return array
1260
     */
1261
    public function getFlexiRow($recordID) {
1262
        $record = null;
1263
        $response = $this->performRequest($this->evidence . '/' . $recordID . '.json');
1264
        if (isset($response[$this->evidence])) {
1265
            $record = $response[$this->evidence][0];
1266
        }
1267
1268
        return $record;
1269
    }
1270
1271
    /**
1272
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1273
     *
1274
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1275
     * @param array $conditions pole podmínek   - rendrují se do ()
1276
     * @param array $urlParams  pole parametrů  - rendrují za ?
1277
     */
1278
    public function extractUrlParams(&$conditions, &$urlParams) {
1279
        foreach (array_keys($this->urlParams) as $urlParam) {
1280
            if (isset($conditions[$urlParam])) {
1281
                \Ease\Functions::divDataArray($conditions, $urlParams, $urlParam);
1282
            }
1283
        }
1284
    }
1285
1286
    /**
1287
     * convert unicode to entities for use with FlexiBee queries
1288
     *
1289
     * @param string $urlRaw
1290
     * 
1291
     * @return string
1292
     */
1293
    public static function urlEncode($urlRaw) {
1294
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1295
    }
1296
1297
    /**
1298
     * Načte data z FlexiBee.
1299
     *
1300
     * @param string $suffix     dotaz
1301
     * @param string|array       $conditions Custom filters or modifiers
1302
     *
1303
     * @return array Data obtained
1304
     */
1305
    public function getFlexiData($suffix = null, $conditions = null) {
1306
        $finalUrl = '';
1307
        $evidenceToRestore = null;
1308
        $urlParams = $this->defaultUrlParams;
1309
1310
        if (!empty($conditions)) {
1311
            if (is_array($conditions)) {
1312
                $this->extractUrlParams($conditions, $urlParams);
1313
                if (array_key_exists('evidence', $conditions) && is_null($this->getColumnInfo('evidence'))) {
1314
                    $evidenceToRestore = $this->getEvidence();
1315
                    $this->setEvidence($conditions['evidence']);
1316
                    unset($conditions['evidence']);
1317
                }
1318
                $conditions = $this->flexiUrl($conditions);
1319
            }
1320
1321
            if (strlen($conditions) && ($conditions[0] != '/')) {
1322
                $conditions = '(' . self::urlEncode($conditions) . ')';
1323
            }
1324
        }
1325
1326
        if (strlen($suffix) && ($suffix != '$sum')) {
1327
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1328
                $finalUrl = $suffix;
1329
            } else {
1330
                if (preg_match('/^(code|ext):(.*)/', $suffix)) {
1331
                    $finalUrl = self::urlizeId($suffix);
1332
                } else {
1333
                    $finalUrl = $suffix;
1334
                }
1335
            }
1336
        }
1337
1338
        $finalUrl .= $conditions;
1339
1340
        if ($suffix == '$sum') {
1341
            $finalUrl .= '/$sum';
1342
        }
1343
1344
        if (!empty($urlParams)) {
1345
            if (strstr($finalUrl, '?')) {
1346
                $finalUrl .= '&';
1347
            } else {
1348
                $finalUrl .= '?';
1349
            }
1350
            $finalUrl .= http_build_query(array_map(function($a) {
1351
                        return is_bool($a) ? ($a ? 'true' : 'false' ) : $a;
1352
                    }, $urlParams), null, '&', PHP_QUERY_RFC3986);
1353
        }
1354
1355
        $transactions = $this->performRequest($finalUrl, 'GET');
1356
        $responseEvidence = $this->getResponseEvidence();
1357
        if (is_array($transactions) && array_key_exists($responseEvidence,
1358
                        $transactions)) {
1359
            $result = $transactions[$responseEvidence];
1360
            if ((count($result) == 1) && empty(current($result))) {
1361
                $result = []; // Response is empty Array
1362
            }
1363
        } else {
1364
            $result = $transactions;
1365
        }
1366
        if (!is_null($evidenceToRestore)) {
1367
            $this->setEvidence($evidenceToRestore);
1368
        }
1369
        return $result;
1370
    }
1371
1372
    /**
1373
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1374
     * Read FlexiBee record and store it inside od object
1375
     *
1376
     * @param int|string $id ID or conditions
1377
     *
1378
     * @return int počet načtených položek
1379
     */
1380
    public function loadFromFlexiBee($id = null) {
1381
        $data = [];
1382
        if (is_null($id)) {
1383
            $id = $this->getMyKey();
1384
        }
1385
        $flexidata = $this->getFlexiData($this->getEvidenceUrl() . '/' . self::urlizeId($id));
1386
        if ($this->lastResponseCode == 200) {
1387
            $this->apiURL = $this->curlInfo['url'];
1388
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1389
                $data = current($flexidata);
1390
            }
1391
        }
1392
        return $this->takeData($data);
1393
    }
1394
1395
    /**
1396
     * Reload current record from FlexiBee
1397
     * 
1398
     * @return boolean 
1399
     */
1400
    public function reload() {
1401
        $id = $this->getRecordIdent();
1402
        $this->dataReset();
1403
        $this->loadFromFlexiBee($id);
1404
        return $this->lastResponseCode == 200;
1405
    }
1406
1407
    /**
1408
     * Set Filter code for requests
1409
     *
1410
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1411
     *
1412
     * @param array|string $filter filter formula or ['key'=>'value']
1413
     *
1414
     * @return string Filter code
1415
     */
1416
    public function setFilter($filter) {
1417
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1418
    }
1419
1420
    /**
1421
     * Převede data do Json formátu pro FlexiBee.
1422
     * Convert data to FlexiBee like Json format
1423
     *
1424
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1425
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1426
     *
1427
     * @param array $data    object data
1428
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1429
     *
1430
     * @return string
1431
     */
1432
    public function getJsonizedData($data = null, $options = 0) {
1433
        if (is_null($data)) {
1434
            $data = $this->getData();
1435
        }
1436
1437
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1438
                $this->getDataForJSON($data));
1439
        $jsonRaw = json_encode([$this->nameSpace => $dataToJsonize],
1440
                $options);
1441
1442
        return $jsonRaw;
1443
    }
1444
1445
    /**
1446
     * Get Data Fragment specific for current object
1447
     *
1448
     * @param array $data
1449
     *
1450
     * @return array
1451
     */
1452
    public function getDataForJSON($data = null) {
1453
        if (is_null($data)) {
1454
            $data = $this->getData();
1455
        }
1456
1457
        $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...
1458
1459
        if (!is_null($this->action)) {
1460
            $dataForJson[$this->evidence . '@action'] = $this->action;
1461
            $this->action = null;
1462
        }
1463
1464
        if (!is_null($this->filter)) {
1465
            $dataForJson[$this->evidence . '@filter'] = $this->filter;
1466
        }
1467
1468
1469
        foreach ($this->chained as $chained) {
1470
            $chainedData = $chained->getDataForJSON();
1471
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1472
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1473
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1474
                        $dataBackup = $dataForJson[$chainedItemEvidence];
1475
                        $dataForJson[$chainedItemEvidence] = [];
1476
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1477
                    }
1478
                    if (array_key_exists(0, $chainedItemData)) {
1479
                        foreach ($chainedItemData as $chainedItem) {
1480
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1481
                        }
1482
                    } else {
1483
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1484
                    }
1485
                } else {
1486
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1487
                }
1488
            }
1489
        }
1490
1491
1492
        return $dataForJson;
1493
    }
1494
1495
    /**
1496
     * Join another FlexiPeeHP Object
1497
     *
1498
     * @param FlexiBeeRO $object
1499
     *
1500
     * @return boolean adding to stack success
1501
     */
1502
    public function join(&$object) {
1503
        $result = true;
1504
        if (method_exists($object, 'getDataForJSON')) {
1505
            $this->chained[] = $object;
1506
        } else {
1507
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1508
        }
1509
1510
        return $result;
1511
    }
1512
1513
    /**
1514
     * Prepare record ID to use in URL
1515
     * 
1516
     * @param mixed $id
1517
     * 
1518
     * @return string id ready for use in URL
1519
     */
1520
    public static function urlizeId($id) {
1521
        if (is_array($id)) {
1522
            $id = rawurlencode('(' . self::flexiUrl($id) . ')');
1523
        } else if (preg_match('/^ext:/', $id)) {
1524
            $id = self::urlEncode($id);
1525
        } else if (preg_match('/^code:/', $id)) {
1526
            $id = self::code(self::urlEncode(self::uncode($id)));
1527
        }
1528
        return $id;
1529
    }
1530
1531
    /**
1532
     * Test if given record ID exists in FlexiBee.
1533
     *
1534
     * @param mixed $identifer presence state
1535
     *
1536
     * @return boolean
1537
     */
1538
    public function idExists($identifer = null) {
1539
        if (is_null($identifer)) {
1540
            $identifer = $this->getMyKey();
1541
        }
1542
        $ignorestate = $this->ignore404();
1543
        $this->ignore404(true);
1544
        $cands = $this->getFlexiData(null,
1545
                [
1546
                    'detail' => 'custom:' . $this->getKeyColumn(),
1547
                    $this->getKeyColumn() => $identifer
1548
        ]);
1549
        $this->ignore404($ignorestate);
1550
        return ($this->lastResponseCode == 200) && !empty($cands);
1551
    }
1552
1553
    /**
1554
     * Test if given record exists in FlexiBee.
1555
     *
1556
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1557
     * 
1558
     * @return boolean Record presence status
1559
     */
1560
    public function recordExists($data = []) {
1561
1562
        if (empty($data)) {
1563
            $data = $this->getData();
1564
        }
1565
        $ignorestate = $this->ignore404();
1566
        $this->ignore404(true);
1567
        $keyColumn = $this->getKeyColumn();
1568
        $res = $this->getColumnsFromFlexibee([$keyColumn],
1569
                is_array($data) ? $data : [$keyColumn => $data]);
1570
1571
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false')) || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1572
            $found = false;
1573
        } else {
1574
            $found = true;
1575
        }
1576
        $this->ignore404($ignorestate);
1577
        return $found;
1578
    }
1579
1580
    /**
1581
     * Subitems - ex. items of invoice
1582
     * 
1583
     * @return array of document items or null
1584
     */
1585
    public function getSubItems() {
1586
        return array_key_exists('polozkyFaktury', $this->getData()) ? $this->getDataValue('polozkyFaktury') : (array_key_exists('polozkyDokladu', $this->getData()) ? $this->getDataValue('polozkyDokladu') : null);
1587
    }
1588
1589
    /**
1590
     * Vrací z FlexiBee sloupečky podle podmínek.
1591
     *
1592
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1593
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1594
     *                                     sloupečku
1595
     * @return array
1596
     */
1597
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1598
        if (is_int($conditions)) {
1599
            $conditions = [$this->getmyKeyColumn() => $conditions];
0 ignored issues
show
Bug introduced by
The method getmyKeyColumn() does not exist on FlexiPeeHP\FlexiBeeRO. Did you maybe mean getMyKey()?

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

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

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