Completed
Push — master ( 3eeae9...e76b9a )
by Vítězslav
24:57
created

FlexiBeeRO::extractUrlParams()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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