Passed
Push — master ( 40d774...35f4a7 )
by Vítězslav
23:37 queued 10s
created

RO::getAbraFlexiURL()   C

Complexity

Conditions 9
Paths 256

Size

Total Lines 10
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
558
            \curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
0 ignored issues
show
Bug introduced by
It seems like $this->curl can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

558
            \curl_setopt(/** @scrutinizer ignore-type */ $this->curl, CURLOPT_RETURNTRANSFER, true); // return content as a string from curl_exec
Loading history...
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)) {
0 ignored issues
show
introduced by
The condition is_null($this->timeout) is always false.
Loading history...
569
                \curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
570
            }
571
572
            \curl_setopt($this->curl, CURLOPT_USERAGENT, 'phpFlexiBee  v' . self::$libVersion . ' https://github.com/Spoje-NET/php-flexibee');
573
        }
574
        return !$this->offline;
575
    }
576
577
    /**
578
     * Initialise object with given data. Availble value types:
579
     *
580
     *  * 234                              - interní číslo záznamu k načtení
581
     *  * code:LOPATA                      - kód záznamu
582
     *  * BAGR                             - kód záznamu k načtení
583
     *  * ['id'=>24,'nazev'=>'hoblík']     - pole hodnot k předvyplnění
584
     *  * 743.json?relations=adresa,vazby  - část url s parametry k načtení
585
     *
586
     * @param mixed $init číslo/"(code:)kód"/(část)URI záznamu k načtení | pole hodnot k předvyplnění
587
     */
588
    public function processInit($init) {
589
        if (is_integer($init)) {
590
            $this->loadFromAbraFlexi($init);
591
        } elseif (is_array($init)) {
592
            $this->takeData($init);
593
        } elseif (preg_match('/\.(json|xml|csv)/', $init)) {
594
            $this->takeData($this->getFlexiData((($init[0] != '/') ? $this->evidenceUrlWithSuffix($init) : $init)));
595
        } else {
596
            $this->loadFromAbraFlexi($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
        switch ($columnName) {
610
            case 'kod':
611
                $value = self::uncode($value); //Alwyas uncode "kod" column
612
613
            default:
614
                if (is_object($value)) {
615
                    switch (get_class($value)) {
616
                        case 'DateTime':
617
                            $columnInfo = $this->getColumnInfo($columnName);
618
                            switch ($columnInfo['type']) {
619
                                case 'date':
620
                                    $value = self::dateToFlexiDate($value);
621
                                    break;
622
                                case 'datetime':
623
                                    $value = self::dateToFlexiDateTime($value);
624
                                    break;
625
                            }
626
                            break;
627
                    }
628
                }
629
                $result = parent::setDataValue($columnName, $value);
630
                break;
631
        }
632
        return $result;
633
    }
634
635
    /**
636
     * PHP Date object to FlexiBee date format
637
     * 
638
     * @param \DateTime $date
639
     */
640
    public static function dateToFlexiDate($date) {
641
        return $date->format(self::$DateFormat);
642
    }
643
644
    /**
645
     * PHP Date object to FlexiBee date format
646
     * 
647
     * @param \DateTime $dateTime
648
     */
649
    public static function dateToFlexiDateTime($dateTime) {
650
        return $dateTime->format(self::$DateTimeFormat);
651
    }
652
653
    /**
654
     * Set URL prefix
655
     *
656
     * @param string $prefix
657
     */
658
    public function setPrefix($prefix) {
659
        switch ($prefix) {
660
            case 'a': //Access
661
            case 'c': //Company
662
            case 'u': //User
663
            case 'g': //License Groups
664
            case 'admin':
665
            case 'status':
666
            case 'login-logout':
667
                $this->prefix = '/' . $prefix . '/';
668
                break;
669
            case null:
670
            case '':
671
            case '/':
672
                $this->prefix = '';
673
                break;
674
            default:
675
                throw new \Exception(sprintf('Unknown prefix %s', $prefix));
676
        }
677
    }
678
679
    /**
680
     * Set communication format.
681
     * One of html|xml|json|csv|dbf|xls|isdoc|isdocx|edi|pdf|pdf|vcf|ical
682
     *
683
     * @param string $format
684
     * 
685
     * @return boolean format is availble
686
     */
687
    public function setFormat($format) {
688
        $result = true;
689
        if (($this->debug === true) && !empty($this->evidence) && isset(Formats::$$this->evidence)) {
690
            if (array_key_exists($format, array_flip(Formats::$$this->evidence)) === false) {
691
                $result = false;
692
            }
693
        }
694
        if ($result === true) {
695
            $this->format = $format;
696
            $this->updateApiURL();
697
        }
698
        return $result;
699
    }
700
701
    /**
702
     * Nastaví Evidenci pro Komunikaci.
703
     * Set evidence for communication
704
     *
705
     * @param string $evidence evidence pathName to use
706
     * 
707
     * @return boolean evidence switching status
708
     */
709
    public function setEvidence($evidence) {
710
        switch ($this->prefix) {
711
            case '/c/':
712
                if ($this->debug === true) {
713
                    if (array_key_exists($evidence, EvidenceList::$name)) {
714
                        $this->evidence = $evidence;
715
                        $result = true;
716
                    } else {
717
                        throw new \Exception(sprintf('Try to set unsupported evidence %s',
718
                                                $evidence));
719
                    }
720
                } else {
721
                    $this->evidence = $evidence;
722
                    $result = true;
723
                }
724
                break;
725
            default:
726
                $this->evidence = $evidence;
727
                $result = true;
728
                break;
729
        }
730
        $this->updateApiURL();
731
        $this->evidenceInfo = $this->getEvidenceInfo();
732
        return $result;
733
    }
734
735
    /**
736
     * Vrací právě používanou evidenci pro komunikaci
737
     * Obtain current used evidence
738
     *
739
     * @return string
740
     */
741
    public function getEvidence() {
742
        return $this->evidence;
743
    }
744
745
    /**
746
     * Set used company.
747
     * Nastaví Firmu.
748
     *
749
     * @param string $company
750
     */
751
    public function setCompany($company) {
752
        $this->company = $company;
753
    }
754
755
    /**
756
     * Obtain company now used
757
     * Vrací právě používanou firmu
758
     *
759
     * @return string
760
     */
761
    public function getCompany() {
762
        return $this->company;
763
    }
764
765
    /**
766
     * Vrací název evidence použité v odpovědích z FlexiBee
767
     *
768
     * @return string
769
     */
770
    public function getResponseEvidence() {
771
        switch ($this->evidence) {
772
            case 'c':
773
                $evidence = 'company';
774
                break;
775
            case 'evidence-list':
776
                $evidence = 'evidence';
777
                break;
778
            default:
779
                $evidence = $this->getEvidence();
780
                break;
781
        }
782
        return $evidence;
783
    }
784
785
    /**
786
     * Převede rekurzivně Objekt na pole.
787
     *
788
     * @param object|array $object
789
     *
790
     * @return array
791
     */
792
    public static function object2array($object) {
793
        $result = null;
794
        if (is_object($object)) {
795
            $objectData = get_object_vars($object);
796
            if (is_array($objectData) && count($objectData)) {
797
                $result = array_map('self::object2array', $objectData);
798
            }
799
        } else {
800
            if (is_array($object)) {
0 ignored issues
show
introduced by
The condition is_array($object) is always true.
Loading history...
801
                foreach ($object as $item => $value) {
802
                    $result[$item] = self::object2array($value);
803
                }
804
            } else {
805
                $result = $object;
806
            }
807
        }
808
809
        return $result;
810
    }
811
812
    /**
813
     * Převede rekurzivně v poli všechny objekty na jejich identifikátory.
814
     *
815
     * @param object|array $object
816
     *
817
     * @return array
818
     */
819
    public static function objectToID($object) {
820
        $resultID = null;
821
        if (is_object($object) && method_exists($object, '__toString')
822
        ) {
823
            $resultID = $object->__toString();
824
        } else {
825
            if (is_array($object)) {
826
                foreach ($object as $item => $value) {
827
                    $resultID[$item] = self::objectToID($value);
828
                }
829
            } else { //String
830
                $resultID = $object;
831
            }
832
        }
833
834
        return $resultID;
835
    }
836
837
    /**
838
     * Return basic URL for used Evidence
839
     *
840
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
841
     *
842
     * @return string Evidence URL
843
     */
844
    public function getEvidenceURL() {
845
        $evidenceUrl = $this->url . $this->prefix . $this->company;
846
        $evidence = $this->getEvidence();
847
        if (!empty($evidence)) {
848
            $evidenceUrl .= '/' . $evidence;
849
        }
850
        return $evidenceUrl;
851
    }
852
853
    /**
854
     * Add suffix to Evidence URL
855
     *
856
     * @param string $urlSuffix
857
     *
858
     * @return string
859
     */
860
    public function evidenceUrlWithSuffix($urlSuffix) {
861
        $evidenceUrl = $this->getEvidenceUrl();
862
        if (!empty($urlSuffix)) {
863
            if (($urlSuffix[0] != '/') && ($urlSuffix[0] != ';') && ($urlSuffix[0] != '?')) {
864
                $evidenceUrl .= '/';
865
            }
866
            $evidenceUrl .= $urlSuffix;
867
        }
868
        return $evidenceUrl;
869
    }
870
871
    /**
872
     * Update $this->apiURL
873
     */
874
    public function updateApiURL() {
875
        $this->apiURL = $this->getEvidenceURL();
876
        $rowIdentifier = $this->getRecordIdent();
877
        if (empty($rowIdentifier)) {
878
            $rowIdentifier = $this->getRecordCode();
879
            if (empty($rowIdentifier)) {
880
                $rowIdentifier = $this->getExternalID();
881
            }
882
        }
883
        if (!empty($rowIdentifier)) {
884
            $this->apiURL .= '/' . self::urlEncode($rowIdentifier);
0 ignored issues
show
Bug introduced by
It seems like $rowIdentifier can also be of type array; however, parameter $urlRaw of FlexiPeeHP\RO::urlEncode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

884
            $this->apiURL .= '/' . self::urlEncode(/** @scrutinizer ignore-type */ $rowIdentifier);
Loading history...
885
        }
886
        $this->apiURL .= '.' . $this->format;
887
    }
888
889
    /*
890
     * Add Default Url params to given url if not overrided
891
     *
892
     * @param string $urlRaw
893
     *
894
     * @return string url with default params added
895
     */
896
897
    public function addDefaultUrlParams($urlRaw) {
898
        return \Ease\Functions::addUrlParams($urlRaw, $this->defaultUrlParams,
899
                        false);
900
    }
901
902
    /**
903
     * Funkce, která provede I/O operaci a vyhodnotí výsledek.
904
     *
905
     * @param string $urlSuffix část URL za identifikátorem firmy.
906
     * @param string $method    HTTP/REST metoda
907
     * @param string $format    Requested format
908
     * 
909
     * @return array|boolean Výsledek operace
910
     */
911
    public function performRequest($urlSuffix = null, $method = 'GET',
912
            $format = null) {
913
        $this->rowCount = null;
914
        $this->responseStats = [];
915
        $this->errors = [];
916
917
        if (preg_match('/^http/', $urlSuffix)) {
918
            $url = $urlSuffix;
919
        } elseif (strlen($urlSuffix) && ($urlSuffix[0] == '/')) {
920
            $url = $this->url . $urlSuffix;
921
        } else {
922
            $url = $this->evidenceUrlWithSuffix($urlSuffix);
923
        }
924
925
        $responseCode = $this->doCurlRequest($this->addDefaultUrlParams($url),
926
                $method, $format);
927
928
        return $this->parseResponse($this->rawResponseToArray($this->lastCurlResponse,
929
                                $this->responseFormat), $responseCode);
930
    }
931
932
    /**
933
     * Parse Raw FlexiBee response in several formats
934
     *
935
     * @param string $responseRaw raw response body
936
     * @param string $format      Raw Response format json|xml|etc
937
     *
938
     * @return array
939
     */
940
    public function rawResponseToArray($responseRaw, $format) {
941
        $responseDecoded = [];
942
        if (!empty(trim($responseRaw))) {
943
            switch ($format) {
944
                case 'json':
945
                    $responseDecoded = $this->rawJsonToArray($responseRaw);
946
                    break;
947
                case 'xml':
948
                    $responseDecoded = $this->rawXmlToArray($this->lastCurlResponse);
949
                    break;
950
                case 'txt':
951
                default:
952
                    $responseDecoded = [$this->lastCurlResponse];
953
                    break;
954
            }
955
        }
956
        return $responseDecoded;
957
    }
958
959
    /**
960
     * Convert FlexiBee Response JSON to Array
961
     *
962
     * @param string $rawJson
963
     *
964
     * @return array
965
     */
966
    public function rawJsonToArray($rawJson) {
967
        $responseDecoded = json_decode($rawJson, true, 10);
968
        $decodeError = json_last_error_msg();
969
        if ($decodeError == 'No error') {
970
            if (array_key_exists($this->nameSpace, $responseDecoded)) {
971
                $responseDecoded = $responseDecoded[$this->nameSpace];
972
            }
973
        } else {
974
            if ($this->debug) {
975
                $this->addStatusMessage('JSON Decoder: ' . $decodeError, 'error');
976
                $this->addStatusMessage($rawJson, 'debug');
977
            }
978
        }
979
        return $responseDecoded;
980
    }
981
982
    /**
983
     * Convert FlexiBee Response XML to Array
984
     *
985
     * @param string $rawXML
986
     *
987
     * @return array
988
     */
989
    public function rawXmlToArray($rawXML) {
990
        return self::xml2array($rawXML);
991
    }
992
993
    /**
994
     * Parse Response array
995
     *
996
     * @param array $responseDecoded
997
     * @param int $responseCode Request Response Code
998
     *
999
     * @return array main data part of response
1000
     */
1001
    public function parseResponse($responseDecoded, $responseCode) {
1002
        $mainResult = null;
1003
        switch ($responseCode) {
1004
            case 201: //We do not care about Success Write here
1005
            case 202: //Accept eg. unsent mails sent    
1006
                break;
1007
            case 200: //Success Read
1008
1009
                if (is_array($responseDecoded)) {
0 ignored issues
show
introduced by
The condition is_array($responseDecoded) is always true.
Loading history...
1010
                    if (isset($responseDecoded['@rowCount'])) {
1011
                        $this->rowCount = (int) $responseDecoded['@rowCount'];
1012
                    }
1013
                    if (isset($responseDecoded['@globalVersion'])) {
1014
                        $this->globalVersion = (int) $responseDecoded['@globalVersion'];
1015
                    }
1016
1017
                    $mainResult = $this->unifyResponseFormat($responseDecoded);
1018
1019
                    if (array_key_exists('stats', $responseDecoded)) {
1020
                        $this->responseStats = $responseDecoded['stats'];
1021
                    } elseif (!empty($mainResult)) {
1022
                        if (array_key_exists('success', $mainResult) && ($mainResult['success'] == 'false')) {
1023
                            $this->responseStats = ['read' => 0];
1024
                        } elseif (array_key_exists('properties', $mainResult)) {
1025
                            $this->responseStats = ['read' => 1];
1026
                        } else {
1027
                            $responseEvidence = $this->getResponseEvidence();
1028
                            if (!empty($this->rowCount)) {
1029
                                $this->responseStats = ['read' => $this->rowCount];
1030
                            } elseif (array_key_exists($responseEvidence,
1031
                                            $mainResult)) {
1032
                                $this->responseStats = ['read' => count($mainResult[$responseEvidence])];
1033
                            } else {
1034
                                $this->responseStats = ['read' => count($mainResult)];
1035
                            }
1036
                        }
1037
                    }
1038
                } else {
1039
                    $mainResult = $responseDecoded;
1040
                }
1041
1042
                $this->lastResult = $mainResult;
1043
                break;
1044
1045
            case 500: // Internal Server Error
1046
                if ($this->debug === true) {
1047
                    $this->error500Reporter($responseDecoded);
1048
                }
1049
            case 404: // Page not found
1050
                if ($this->ignoreNotFound === true) {
1051
                    break;
1052
                }
1053
            case 400: //Bad Request parameters
1054
            default: //Something goes wrong
1055
                if (!empty($responseDecoded) && is_array($responseDecoded) && array_key_exists(0, $responseDecoded)) {
1056
                    $this->parseError($responseDecoded);
1057
                }
1058
1059
                if ($this->throwException === true) {
1060
                    throw new \Ease\Exception(json_encode($this->getErrors()), $this->lastResponseCode);
1061
                } else {
1062
                    $this->addStatusMessage($this->lastResponseCode . ': ' . $this->curlInfo['url'] . ' (' . $this->format . ')',
1063
                            'warning');
1064
                }
1065
                break;
1066
        }
1067
        return $mainResult;
1068
    }
1069
1070
    /**
1071
     * Parse error message response
1072
     *
1073
     * @param array $responseDecoded
1074
     * 
1075
     * @return int number of errors processed
1076
     */
1077
    public function parseError(array $responseDecoded) {
1078
        if (array_key_exists('success', $responseDecoded)) {
1079
            $this->errors = [['message' => array_key_exists('message', $responseDecoded) ? $responseDecoded['message'] : '']];
1080
        } else {
1081
            if ($this->throwException === true) {
1082
                throw new \Ease\Exception('Unparsed error: ' . $this->lastCurlResponse);
1083
            } else {
1084
                $this->addStatusMessage('Unparsed error: ' . $this->lastCurlResponse, 'debug');
1085
            }
1086
        }
1087
        return count($this->errors);
1088
    }
1089
1090
    /**
1091
     * Vykonej HTTP požadavek
1092
     *
1093
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1094
     * @param string $url    URL požadavku
1095
     * @param string $method HTTP Method GET|POST|PUT|OPTIONS|DELETE
1096
     * @param string $format požadovaný formát komunikace
1097
     * 
1098
     * @return int HTTP Response CODE
1099
     */
1100
    public function doCurlRequest($url, $method, $format = null) {
1101
        if (is_null($format)) {
1102
            $format = $this->format;
1103
        }
1104
        curl_setopt($this->curl, CURLOPT_URL, $url);
1105
// Nastavení samotné operace
1106
        curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
1107
//Vždy nastavíme byť i prázná postdata jako ochranu před chybou 411
1108
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postFields);
1109
1110
        $httpHeaders = $this->defaultHttpHeaders;
1111
1112
        $formats = Formats::bySuffix();
1113
1114
        if (!isset($httpHeaders['Accept'])) {
1115
            $httpHeaders['Accept'] = $formats[$format]['content-type'];
1116
        }
1117
        if (!isset($httpHeaders['Content-Type'])) {
1118
            $httpHeaders['Content-Type'] = $formats[$format]['content-type'];
1119
        }
1120
1121
        array_walk($httpHeaders, function (&$value, $header) {
1122
            $value = $header . ': ' . $value;
1123
        });
1124
        curl_setopt($this->curl, CURLOPT_HTTPHEADER, $httpHeaders);
1125
1126
// Proveď samotnou operaci
1127
        $this->lastCurlResponse = curl_exec($this->curl);
0 ignored issues
show
Documentation Bug introduced by
It seems like curl_exec($this->curl) can also be of type boolean. However, the property $lastCurlResponse is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
1128
        $this->curlInfo = curl_getinfo($this->curl);
1129
        $this->curlInfo['when'] = microtime();
1130
        $this->responseFormat = $this->contentTypeToResponseFormat($this->curlInfo['content_type'],
1131
                $url);
1132
        $this->lastResponseCode = $this->curlInfo['http_code'];
1133
        $this->lastCurlError = curl_error($this->curl);
1134
        if (strlen($this->lastCurlError)) {
1135
            $this->addStatusMessage(sprintf('Curl Error (HTTP %d): %s',
1136
                            $this->lastResponseCode, $this->lastCurlError), 'error');
1137
        }
1138
1139
        if ($this->debug === true) {
1140
            $this->saveDebugFiles();
1141
        }
1142
        return $this->lastResponseCode;
1143
    }
1144
1145
    /**
1146
     * Obtain json for application/json
1147
     * 
1148
     * @param string $contentType
1149
     * @param string $url
1150
     * 
1151
     * @return string response format
1152
     */
1153
    public function contentTypeToResponseFormat($contentType, $url = null) {
1154
        if (!empty($url)) {
1155
            $url = parse_url($url, PHP_URL_PATH);
1156
        }
1157
1158
        $contentTypeClean = strstr($contentType, ';') ? substr($contentType, 0,
1159
                        strpos($contentType, ';')) : $contentType;
1160
1161
        switch ($url) {
1162
            case '/login-logout/login';
1163
                $responseFormat = 'json';
1164
                break;
1165
            default :
1166
                switch ($contentTypeClean) {
1167
                    case 'text/javascript':
1168
                        $responseFormat = 'js';
1169
                        break;
1170
1171
                    default:
1172
                        $responseFormat = Formats::contentTypeToSuffix($contentTypeClean);
1173
                        break;
1174
                }
1175
                break;
1176
        }
1177
1178
        return $responseFormat;
1179
    }
1180
1181
    /**
1182
     * Nastaví druh prováděné akce.
1183
     *
1184
     * @link https://demo.flexibee.eu/devdoc/actions Provádění akcí
1185
     * @param string $action
1186
     * 
1187
     * @return boolean
1188
     */
1189
    public function setAction($action) {
1190
        $result = false;
1191
        $actionsAvailable = $this->getActionsInfo();
1192
        if (is_array($actionsAvailable) && array_key_exists($action,
1193
                        $actionsAvailable)) {
1194
            $this->action = $action;
1195
            $result = true;
1196
        }
1197
        return $result;
1198
    }
1199
1200
    /**
1201
     * Convert XML to array.
1202
     *
1203
     * @param string $xml
1204
     *
1205
     * @return array
1206
     */
1207
    public static function xml2array($xml) {
1208
        $arr = [];
1209
        if (!empty($xml)) {
1210
            if (is_string($xml)) {
0 ignored issues
show
introduced by
The condition is_string($xml) is always true.
Loading history...
1211
                $xml = simplexml_load_string($xml);
1212
            }
1213
            foreach ($xml->attributes() as $a) {
1214
                $arr['@' . $a->getName()] = strval($a);
1215
            }
1216
            foreach ($xml->children() as $r) {
1217
                if (count($r->children()) == 0) {
1218
                    $arr[$r->getName()] = strval($r);
1219
                } else {
1220
                    $arr[$r->getName()][] = self::xml2array($r);
1221
                }
1222
            }
1223
        }
1224
        return $arr;
1225
    }
1226
1227
    /**
1228
     * Odpojení od FlexiBee.
1229
     */
1230
    public function disconnect() {
1231
        if (is_resource($this->curl)) {
1232
            curl_close($this->curl);
1233
        }
1234
        $this->curl = null;
1235
    }
1236
1237
    /**
1238
     * Disconnect CURL befere pass away
1239
     */
1240
    public function __destruct() {
1241
        $this->disconnect();
1242
    }
1243
1244
    /**
1245
     * Načte řádek dat z FlexiBee.
1246
     *
1247
     * @param int $recordID id požadovaného záznamu
1248
     *
1249
     * @return array
1250
     */
1251
    public function getFlexiRow($recordID) {
1252
        $record = null;
1253
        $response = $this->performRequest($this->evidence . '/' . $recordID . '.json');
1254
        if (isset($response[$this->evidence])) {
1255
            $record = $response[$this->evidence][0];
1256
        }
1257
1258
        return $record;
1259
    }
1260
1261
    /**
1262
     * Oddělí z pole podmínek ty jenž patří za ? v URL požadavku
1263
     *
1264
     * @link https://www.flexibee.eu/api/dokumentace/ref/urls/ Sestavování URL
1265
     * @param array $conditions pole podmínek   - rendrují se do ()
1266
     * @param array $urlParams  pole parametrů  - rendrují za ?
1267
     */
1268
    public function extractUrlParams(&$conditions, &$urlParams) {
1269
        foreach (array_keys($this->urlParams) as $urlParam) {
1270
            if (isset($conditions[$urlParam])) {
1271
                \Ease\Functions::divDataArray($conditions, $urlParams, $urlParam);
1272
            }
1273
        }
1274
    }
1275
1276
    /**
1277
     * convert unicode to entities for use with FlexiBee queries
1278
     *
1279
     * @param string $urlRaw
1280
     * 
1281
     * @return string
1282
     */
1283
    public static function urlEncode($urlRaw) {
1284
        return str_replace(['%27', '%3A'], ["'", ':'], rawurlencode($urlRaw));
1285
    }
1286
1287
    /**
1288
     * Načte data z FlexiBee.
1289
     *
1290
     * @param string $suffix     dotaz
1291
     * @param string|array       $conditions Custom filters or modifiers
1292
     *
1293
     * @return array Data obtained
1294
     */
1295
    public function getFlexiData($suffix = null, $conditions = null) {
1296
        $finalUrl = '';
1297
        $evidenceToRestore = null;
1298
        $urlParams = $this->defaultUrlParams;
1299
1300
        if (!empty($conditions)) {
1301
            if (is_array($conditions)) {
1302
                $this->extractUrlParams($conditions, $urlParams);
1303
                if (array_key_exists('evidence', $conditions) && is_null($this->getColumnInfo('evidence'))) {
0 ignored issues
show
introduced by
The condition is_null($this->getColumnInfo('evidence')) is always false.
Loading history...
1304
                    $evidenceToRestore = $this->getEvidence();
1305
                    $this->setEvidence($conditions['evidence']);
1306
                    unset($conditions['evidence']);
1307
                }
1308
                $conditions = $this->flexiUrl($conditions);
1309
            }
1310
1311
            if (strlen($conditions) && ($conditions[0] != '/')) {
1312
                $conditions = '(' . self::urlEncode($conditions) . ')';
1313
            }
1314
        }
1315
1316
        if (strlen($suffix) && ($suffix != '$sum')) {
1317
            if (preg_match('/^http/', $suffix) || ($suffix[0] == '/') || is_numeric($suffix)) {
1318
                $finalUrl = $suffix;
1319
            } else {
1320
                if (preg_match('/^(code|ext):(.*)/', $suffix)) {
1321
                    $finalUrl = self::urlizeId($suffix);
1322
                } else {
1323
                    $finalUrl = $suffix;
1324
                }
1325
            }
1326
        }
1327
1328
        $finalUrl .= $conditions;
1329
1330
        if ($suffix == '$sum') {
1331
            $finalUrl .= '/$sum';
1332
        }
1333
1334
        if (!empty($urlParams)) {
1335
            if (strstr($finalUrl, '?')) {
1336
                $finalUrl .= '&';
1337
            } else {
1338
                $finalUrl .= '?';
1339
            }
1340
            $finalUrl .= http_build_query(array_map(function($a) {
1341
                        return is_bool($a) ? ($a ? 'true' : 'false' ) : $a;
1342
                    }, $urlParams), null, '&', PHP_QUERY_RFC3986);
1343
        }
1344
1345
        $transactions = $this->performRequest($finalUrl, 'GET');
1346
        $responseEvidence = $this->getResponseEvidence();
1347
        if (is_array($transactions) && array_key_exists($responseEvidence,
1348
                        $transactions)) {
1349
            $result = $transactions[$responseEvidence];
1350
            if ((count($result) == 1) && empty(current($result))) {
1351
                $result = []; // Response is empty Array
1352
            }
1353
        } else {
1354
            $result = $transactions;
1355
        }
1356
        if (!is_null($evidenceToRestore)) {
0 ignored issues
show
introduced by
The condition is_null($evidenceToRestore) is always true.
Loading history...
1357
            $this->setEvidence($evidenceToRestore);
1358
        }
1359
        return $result;
1360
    }
1361
1362
    /**
1363
     * Read FlexiBee record and store it inside od object
1364
     * 
1365
     * @deprecated since version 2.0
1366
     * 
1367
     * @param int|string $id ID or conditions
1368
     *
1369
     * @return int počet načtených položek
1370
     */
1371
    public function loadFromFlexiBee($id = null) {
1372
        return $this->loadFromAbraFlexi($id);
1373
    }
1374
1375
    /**
1376
     * Read AbraFlexi record and store it inside od object
1377
     * 
1378
     * @param int|string $id ID or conditions
1379
     *
1380
     * @return int počet načtených položek
1381
     */
1382
    public function loadFromAbraFlexi($id = null) {
1383
        $data = [];
1384
        if (is_null($id)) {
1385
            $id = $this->getMyKey();
1386
        }
1387
        $flexidata = $this->getFlexiData($this->getEvidenceUrl() . '/' . self::urlizeId($id));
1388
        if ($this->lastResponseCode == 200) {
1389
            $this->apiURL = $this->curlInfo['url'];
1390
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1391
                $data = current($flexidata);
1392
            }
1393
        }
1394
        return $this->takeData($data);
1395
    }
1396
1397
    /**
1398
     * Reload current record from FlexiBee
1399
     * 
1400
     * @return boolean 
1401
     */
1402
    public function reload() {
1403
        $id = $this->getRecordIdent();
1404
        $this->dataReset();
1405
        $this->loadFromAbraFlexi($id);
1406
        return $this->lastResponseCode == 200;
1407
    }
1408
1409
    /**
1410
     * Set Filter code for requests
1411
     *
1412
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1413
     *
1414
     * @param array|string $filter filter formula or ['key'=>'value']
1415
     *
1416
     * @return string Filter code
1417
     */
1418
    public function setFilter($filter) {
1419
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1420
    }
1421
1422
    /**
1423
     * Převede data do Json formátu pro FlexiBee.
1424
     * Convert data to FlexiBee like Json format
1425
     *
1426
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1427
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1428
     *
1429
     * @param array $data    object data
1430
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1431
     *
1432
     * @return string
1433
     */
1434
    public function getJsonizedData($data = null, $options = 0) {
1435
        if (is_null($data)) {
1436
            $data = $this->getData();
1437
        }
1438
1439
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1440
                $this->getDataForJSON($data));
1441
        $jsonRaw = json_encode([$this->nameSpace => $dataToJsonize],
1442
                $options);
1443
1444
        return $jsonRaw;
1445
    }
1446
1447
    /**
1448
     * Get Data Fragment specific for current object
1449
     *
1450
     * @param array $data
1451
     *
1452
     * @return array
1453
     */
1454
    public function getDataForJSON($data = null) {
1455
        if (is_null($data)) {
1456
            $data = $this->getData();
1457
        }
1458
1459
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1460
1461
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1462
            $dataForJson[$this->evidence . '@action'] = $this->action;
1463
            $this->action = null;
1464
        }
1465
1466
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1467
            $dataForJson[$this->evidence . '@filter'] = $this->filter;
1468
        }
1469
1470
1471
        foreach ($this->chained as $chained) {
1472
            $chainedData = $chained->getDataForJSON();
1473
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1474
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1475
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1476
                        $dataBackup = $dataForJson[$chainedItemEvidence];
1477
                        $dataForJson[$chainedItemEvidence] = [];
1478
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1479
                    }
1480
                    if (array_key_exists(0, $chainedItemData)) {
1481
                        foreach ($chainedItemData as $chainedItem) {
1482
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1483
                        }
1484
                    } else {
1485
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1486
                    }
1487
                } else {
1488
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1489
                }
1490
            }
1491
        }
1492
1493
1494
        return $dataForJson;
1495
    }
1496
1497
    /**
1498
     * Join another FlexiPeeHP Object
1499
     *
1500
     * @param RO $object
1501
     *
1502
     * @return boolean adding to stack success
1503
     */
1504
    public function join(&$object) {
1505
        $result = true;
1506
        if (method_exists($object, 'getDataForJSON')) {
1507
            $this->chained[] = $object;
1508
        } else {
1509
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1510
        }
1511
1512
        return $result;
1513
    }
1514
1515
    /**
1516
     * Prepare record ID to use in URL
1517
     * 
1518
     * @param mixed $id
1519
     * 
1520
     * @return string id ready for use in URL
1521
     */
1522
    public static function urlizeId($id) {
1523
        if (is_array($id)) {
1524
            $id = rawurlencode('(' . self::flexiUrl($id) . ')');
1525
        } else if (preg_match('/^ext:/', $id)) {
1526
            $id = self::urlEncode($id);
1527
        } else if (preg_match('/^code:/', $id)) {
1528
            $id = self::code(self::urlEncode(self::uncode($id)));
1529
        }
1530
        return $id;
1531
    }
1532
1533
    /**
1534
     * Test if given record ID exists in FlexiBee.
1535
     *
1536
     * @param mixed $identifer presence state
1537
     *
1538
     * @return boolean
1539
     */
1540
    public function idExists($identifer = null) {
1541
        if (is_null($identifer)) {
1542
            $identifer = $this->getMyKey();
1543
        }
1544
        $ignorestate = $this->ignore404();
1545
        $this->ignore404(true);
1546
        $cands = $this->getFlexiData(null,
1547
                [
1548
                    'detail' => 'custom:' . $this->getKeyColumn(),
1549
                    $this->getKeyColumn() => $identifer
1550
        ]);
1551
        $this->ignore404($ignorestate);
1552
        return ($this->lastResponseCode == 200) && !empty($cands);
1553
    }
1554
1555
    /**
1556
     * Test if given record exists in FlexiBee.
1557
     *
1558
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1559
     * 
1560
     * @return boolean Record presence status
1561
     */
1562
    public function recordExists($data = []) {
1563
1564
        if (empty($data)) {
1565
            $data = $this->getData();
1566
        }
1567
        $ignorestate = $this->ignore404();
1568
        $this->ignore404(true);
1569
        $keyColumn = $this->getKeyColumn();
1570
        $res = $this->getColumnsFromAbraFlexi([$keyColumn],
1571
                is_array($data) ? $data : [$keyColumn => $data]);
1572
1573
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false')) || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1574
            $found = false;
1575
        } else {
1576
            $found = true;
1577
        }
1578
        $this->ignore404($ignorestate);
1579
        return $found;
1580
    }
1581
1582
    /**
1583
     * Vrací z FlexiBee sloupečky podle podmínek.
1584
     *
1585
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1586
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1587
     *                                     sloupečku
1588
     * @return array
1589
     */
1590
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1591
        if (is_int($conditions)) {
1592
            $conditions = [$this->getmyKeyColumn() => $conditions];
0 ignored issues
show
Bug introduced by
The method getmyKeyColumn() does not exist on FlexiPeeHP\RO. Did you maybe mean getKeyColumn()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1592
            $conditions = [$this->/** @scrutinizer ignore-call */ getmyKeyColumn() => $conditions];

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...
1593
        }
1594
1595
        $flexiData = $this->getFlexiData('', $conditions);
1596
1597
        if (!is_null($indexBy)) {
1598
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData);
1599
        }
1600
1601
        return $flexiData;
1602
    }
1603
1604
    /**
1605
     * Vrací z FlexiBee sloupečky podle podmínek.
1606
     *
1607
     * @deprecated since version 2.0
1608
     * 
1609
     * @param string|string[] $columnsList seznam položek nebo úrověň detailu: id|summary|full
1610
     * @param array           $conditions  pole podmínek nebo ID záznamu
1611
     * @param string          $indexBy     Sloupeček podle kterého indexovat záznamy
1612
     *
1613
     * @return array
1614
     */
1615
    public function getColumnsFromFlexiBee($columnsList, $conditions = [], $indexBy = null) {
1616
        return $this->getColumnsFromAbraFlexi($columnsList, $conditions, $indexBy);
1617
    }
1618
1619
    /**
1620
     * Obtain AbraFlexi columns by conditions.
1621
     *
1622
     * @param string|string[] $columnsList seznam položek nebo úrověň detailu: id|summary|full
1623
     * @param array           $conditions  pole podmínek nebo ID záznamu
1624
     * @param string          $indexBy     Sloupeček podle kterého indexovat záznamy
1625
     *
1626
     * @return array
1627
     */
1628
    public function getColumnsFromAbraFlexi($columnsList, $conditions = [],
1629
            $indexBy = null) {
1630
        $detail = 'full';
1631
        switch (gettype($columnsList)) {
1632
            case 'integer': //Record ID
1633
                $conditions = [$this->getmyKeyColumn() => $conditions];
1634
            case 'array': //Few Conditions
1635
                if (!is_null($indexBy) && !array_key_exists($indexBy,
1636
                                $columnsList)) {
1637
                    $columnsList[] = $indexBy;
1638
                }
1639
                $columns = implode(',', array_unique($columnsList));
1640
                $detail = 'custom:' . $columns;
1641
            default:
1642
                switch ($columnsList) {
1643
                    case 'id':
1644
                        $detail = 'id';
1645
                        break;
1646
                    case 'summary':
1647
                        $detail = 'summary';
1648
                        break;
1649
                    default:
1650
                        break;
1651
                }
1652
                break;
1653
        }
1654
1655
        $conditions['detail'] = $detail;
1656
1657
        $flexiData = $this->getFlexiData(null, $conditions);
1658
1659
        if (is_string($indexBy) && is_array($flexiData) && array_key_exists(0,
1660
                        $flexiData) && array_key_exists($indexBy, $flexiData[0])) {
1661
            $flexiData = \Ease\Functions::reindexArrayBy($flexiData, $indexBy);
1662
        }
1663
1664
        return $flexiData;
1665
    }
1666
1667
    /**
1668
     * Vrací kód záznamu.
1669
     * Obtain record CODE
1670
     *
1671
     * @param mixed $data
1672
     *
1673
     * @return string
1674
     */
1675
    public function getKod($data = null, $unique = true) {
1676
        $kod = null;
1677
1678
        if (is_null($data)) {
1679
            $data = $this->getData();
1680
        }
1681
1682
        if (is_string($data)) {
1683
            $data = [$this->nameColumn => $data];
1684
        }
1685
1686
        if (isset($data['kod'])) {
1687
            $kod = $data['kod'];
1688
        } else {
1689
            if (isset($data[$this->nameColumn])) {
1690
                $kod = preg_replace('/[^a-zA-Z0-9]/', '',
1691
                        \Ease\Functions::rip($data[$this->nameColumn]));
1692
            } else {
1693
                if (isset($data[$this->keyColumn])) {
1694
                    $kod = \Ease\Functions::rip($data[$this->keyColumn]);
1695
                }
1696
            }
1697
            $kod = substr($kod, 0, 20);
1698
        }
1699
1700
        if (!strlen($kod)) {
1701
            $kod = 'NOTSET';
1702
        }
1703
1704
        if (strlen($kod) > 18) {
1705
            $kodfinal = strtoupper(substr($kod, 0, 18));
1706
        } else {
1707
            $kodfinal = strtoupper($kod);
1708
        }
1709
1710
        if ($unique) {
1711
            $counter = 0;
1712
            if (!empty($this->codes) && count($this->codes)) {
1713
                foreach ($this->codes as $codesearch => $keystring) {
1714
                    if (strstr($codesearch, $kodfinal)) {
1715
                        ++$counter;
1716
                    }
1717
                }
1718
            }
1719
            if ($counter) {
1720
                $kodfinal = $kodfinal . $counter;
1721
            }
1722
1723
            $this->codes[$kodfinal] = $kod;
1724
        }
1725
1726
        return self::code($kodfinal);
1727
    }
1728
1729
    /**
1730
     * Save RAW Curl Request & Response to files in Temp directory
1731
     */
1732
    public function saveDebugFiles() {
1733
        $tmpdir = sys_get_temp_dir();
1734
        $fname = $this->evidence . '-' . $this->curlInfo['when'] . '.' . $this->format;
1735
        $reqname = $tmpdir . '/request-' . $fname;
1736
        $respname = $tmpdir . '/response-' . $fname;
1737
        $header = '# ' . (new \DateTime())->format('Y-m-d\TH:i:s.u') . ' ' . $this->curlInfo['url'] . ' (' . urldecode($this->curlInfo['url']) . ')';
1738
        if (file_put_contents($reqname, $header . "\n" . $this->postFields)) {
1739
            $this->addStatusMessage($reqname, 'debug');
1740
        }
1741
        if (file_put_contents($respname, $header . "\n" . $this->lastCurlResponse)) {
1742
            $this->addStatusMessage($respname, 'debug');
1743
        }
1744
    }
1745
1746
    /**
1747
     * Připraví data pro odeslání do FlexiBee
1748
     *
1749
     * @param string $data
1750
     */
1751
    public function setPostFields($data) {
1752
        $this->postFields = $data;
1753
    }
1754
1755
    /**
1756
     * Get Content ready to be send as POST body
1757
     * @return string
1758
     */
1759
    public function getPostFields() {
1760
        return $this->postFields;
1761
    }
1762
1763
    /**
1764
     * Generuje fragment url pro filtrování.
1765
     *
1766
     * @see https://www.flexibee.eu/api/dokumentace/ref/filters
1767
     *
1768
     * @param array  $data   key=>values; value can bee class DatePeriod, DateTime or Array
1769
     * @param string $joiner default and/or
1770
     * @param string $defop  default operator
1771
     *
1772
     * @return string
1773
     */
1774
    public static function flexiUrl(array $data, $joiner = 'and', $defop = 'eq') {
1775
        $parts = [];
1776
1777
        foreach ($data as $column => $value) {
1778
            if (!is_numeric($column)) {
1779
                if (is_integer($data[$column]) || is_float($data[$column])) {
1780
                    $parts[$column] = $column . ' eq \'' . $data[$column] . '\'';
1781
                } elseif (is_bool($data[$column])) {
1782
                    $parts[$column] = $data[$column] ? $column . ' eq true' : $column . ' eq false';
1783
                } elseif (is_null($data[$column])) {
1784
                    $parts[$column] = $column . " is null";
1785
                } elseif (is_array($data[$column])) {
1786
                    $parts[$column] = $column . " in (" . implode(',',
1787
                                    array_map(function($a, $column) {
1788
                                        return $column == 'stitky' ? "'" . self::code($a) . "'" : "'$a'";
1789
                                    }, $data[$column],
1790
                                            array_fill(0, count($data[$column]), $column))) . ")";
1791
                } elseif (is_object($data[$column])) {
1792
                    switch (get_class($data[$column])) {
1793
                        case 'DatePeriod':
1794
                            $parts[$column] = $column . " between '" . $data[$column]->getStartDate()->format(self::$DateFormat) . "' '" . $data[$column]->getEndDate()->format(self::$DateFormat) . "'";
1795
                            break;
1796
                        case 'DateTime':
1797
                            $parts[$column] = $column . " eq '" . $data[$column]->format(self::$DateFormat) . "'";
1798
                            break;
1799
                        default:
1800
                            $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1801
                            break;
1802
                    }
1803
                } else {
1804
                    switch ($value) {
1805
                        case '!null':
1806
                            $parts[$column] = $column . " is not null";
1807
                            break;
1808
                        case 'is empty':
1809
                        case 'is not empty':
1810
                        case 'is true':
1811
                        case 'is false':
1812
                            $parts[$column] = $column . ' ' . $value;
1813
                            break;
1814
                        default:
1815
                            $condParts = explode(' ', trim($value));
1816
                            switch ($condParts[0]) {
1817
                                case '<>':
1818
                                case '!=':
1819
                                case 'ne':
1820
                                case 'neq':
1821
                                case '<':
1822
                                case 'lt':
1823
                                case '<=':
1824
                                case 'lte':
1825
                                case '>':
1826
                                case 'gt':
1827
                                case '>=':
1828
                                case 'gte':
1829
                                case 'like':
1830
                                case 'begins':
1831
                                case 'between':
1832
                                case 'ends':
1833
                                    if (count($condParts) == 1) {
1834
                                        $parts[$column] = $column .= ' ' . $value;
1835
                                    } else {
1836
                                        $parts[$column] = $column .= ' ' . $condParts[0] . " '" . $condParts[1] . "'";
1837
                                    }
1838
                                    break;
1839
                                default:
1840
                                    if ($column == 'stitky') {
1841
                                        $parts[$column] = $column . "='" . self::code($data[$column]) . "'";
1842
                                    } else {
1843
                                        $parts[$column] = $column . " $defop '" . $data[$column] . "'";
1844
                                    }
1845
                                    break;
1846
                            }
1847
1848
                            break;
1849
                    }
1850
                }
1851
            } else {
1852
                $parts[] = $value;
1853
            }
1854
        }
1855
        return implode(' ' . $joiner . ' ', $parts);
1856
    }
1857
1858
    /**
1859
     * Obtain record/object numeric identificator id:
1860
     * Vrací číselný identifikátor objektu id:
1861
     *
1862
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1863
     *
1864
     * @return null|int indentifikátor záznamu reprezentovaného objektem
1865
     */
1866
    public function getRecordID() {
1867
        $id = $this->getDataValue('id');
1868
        return is_null($id) ? null : (is_numeric($id) ? intval($id) : $id);
1869
    }
1870
1871
    /**
1872
     * Obtain record/object identificator code:
1873
     * Vrací identifikátor objektu code:
1874
     *
1875
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1876
     *
1877
     * @return string record code identifier
1878
     */
1879
    public function getRecordCode() {
1880
        return empty($this->getDataValue('kod')) ? null : self::code($this->getDataValue('kod'));
1881
    }
1882
1883
    /**
1884
     * Obtain record/object identificator extId: code: or id:
1885
     * Vrací identifikátor objektu extId: code: nebo id:
1886
     *
1887
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1888
     *
1889
     * @return string|int|null record code identifier
1890
     */
1891
    public function getRecordIdent() {
1892
        $ident = $this->getExternalID();
1893
        if (empty($ident)) {
1894
            $ident = $this->getRecordCode();
1895
        }
1896
        if (empty($ident)) {
1897
            $ident = $this->getRecordID();
1898
        }
1899
        return $ident;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $ident also could return the type array which is incompatible with the documented return type integer|null|string.
Loading history...
1900
    }
1901
1902
    /**
1903
     * Obtain record/object identificator code: or id:
1904
     * Vrací identifikátor objektu code: nebo id:
1905
     *
1906
     * @link https://demo.flexibee.eu/devdoc/identifiers Identifikátory záznamů
1907
     * 
1908
     * @return string indentifikátor záznamu reprezentovaného objektem
1909
     */
1910
    public function __toString() {
1911
        return strval($this->getRecordIdent());
1912
    }
1913
1914
    /**
1915
     * Gives you FlexiPeeHP class name for Given Evidence
1916
     *
1917
     * @param string $evidence
1918
     * 
1919
     * @return string Class name
1920
     */
1921
    public static function evidenceToClassName($evidence) {
1922
        return str_replace(' ', '', ucwords(str_replace('-', ' ', $evidence)));
1923
    }
1924
1925
    /**
1926
     * Obtain ID of first record in evidence
1927
     *
1928
     * @return string|null id or null if no records
1929
     */
1930
    public function getFirstRecordID() {
1931
        $firstID = null;
1932
        $keyColumn = $this->getKeyColumn();
1933
        $firstIdRaw = $this->getColumnsFromAbraFlexi([$keyColumn],
1934
                ['limit' => 1, 'order' => $keyColumn], $keyColumn);
1935
        if (!empty($firstIdRaw) && isset(current($firstIdRaw)[$keyColumn])) {
1936
            $firstID = current($firstIdRaw)[$keyColumn];
1937
        }
1938
        return is_numeric($firstID) ? intval($firstID) : $firstID;
1939
    }
1940
1941
    /**
1942
     * Get previous record ID
1943
     * 
1944
     * @param array $conditions optional
1945
     * 
1946
     * @return int|null
1947
     */
1948
    public function getNextRecordID($conditions = []) {
1949
        $conditions['order'] = 'id@D';
1950
        $conditions['limit'] = 1;
1951
        $conditions[] = 'id gt ' . $this->getRecordID();
1952
        $next = $this->getColumnsFromAbraFlexi(['id'], $conditions);
1953
        return (is_array($next) && array_key_exists(0, $next) && array_key_exists('id',
1954
                        $next[0])) ? intval($next[0]['id']) : null;
1955
    }
1956
1957
    /**
1958
     * Get next record ID
1959
     * 
1960
     * @param array $conditions optional
1961
     * 
1962
     * @return int|null
1963
     */
1964
    public function getPrevRecordID($conditions = []) {
1965
        $conditions['order'] = 'id@A';
1966
        $conditions['limit'] = 1;
1967
        $conditions[] = 'id lt ' . $this->getRecordID();
1968
        $prev = $this->getColumnsFromAbraFlexi(['id'], $conditions);
1969
        return (is_array($prev) && array_key_exists(0, $prev) && array_key_exists('id',
1970
                        $prev[0])) ? intval($prev[0]['id']) : null;
1971
    }
1972
1973
    /**
1974
     * Vrací hodnotu daného externího ID
1975
     *
1976
     * @param string $want Namespace Selector. If empty,you obtain the first one.
1977
     * 
1978
     * @return string|array one id or array if multiplete
1979
     */
1980
    public function getExternalID($want = null) {
1981
        $extid = null;
1982
        $ids = $this->getExternalIDs();
1983
        if (is_null($want)) {
1984
            if (!empty($ids)) {
1985
                $extid = current($ids);
1986
            }
1987
        } else {
1988
            if (!is_null($ids) && is_array($ids)) {
0 ignored issues
show
introduced by
The condition is_null($ids) is always false.
Loading history...
introduced by
The condition is_array($ids) is always true.
Loading history...
1989
                foreach ($ids as $id) {
1990
                    if (strstr($id, 'ext:' . $want)) {
1991
                        if (is_null($extid)) {
1992
                            $extid = str_replace('ext:' . $want . ':', '', $id);
1993
                        } else {
1994
                            if (is_array($extid)) {
1995
                                $extid[] = str_replace('ext:' . $want . ':', '', $id);
1996
                            } else {
1997
                                $extid = [$extid, str_replace('ext:' . $want . ':',
1998
                                            '', $id)];
1999
                            }
2000
                        }
2001
                    }
2002
                }
2003
            }
2004
        }
2005
        return $extid;
2006
    }
2007
2008
    /**
2009
     * gives you currently loaded extermal IDs
2010
     * 
2011
     * @return array
2012
     */
2013
    public function getExternalIDs() {
2014
        return $this->getDataValue('external-ids');
2015
    }
2016
2017
    /**
2018
     * Obtain actual GlobalVersion
2019
     * Vrací aktuální globální verzi změn
2020
     *
2021
     * @link https://www.flexibee.eu/api/dokumentace/ref/changes-api#globalVersion Globální Verze
2022
     * 
2023
     * @return int
2024
     */
2025
    public function getGlobalVersion() {
2026
        $this->getFlexiData(null, ['add-global-version' => 'true', 'limit' => 1]);
2027
2028
        return $this->globalVersion;
2029
    }
2030
2031
    /**
2032
     * Gives you current ApiURL with given format suffix
2033
     * 
2034
     * @param string $format json|html|xml|...
2035
     * 
2036
     * @return string API URL for current record or object/evidence
2037
     */
2038
    public function getApiURL($format = null) {
2039
        $apiUrl = str_replace(['.' . $this->format, '?limit=0'], '', $this->apiURL);
2040
        return $apiUrl . (empty($format) ? '' : '.' . $format );
2041
    }
2042
2043
    /**
2044
     * Obtain content type of last response
2045
     *
2046
     * @return string
2047
     */
2048
    public function getResponseFormat() {
2049
        return $this->responseFormat;
2050
    }
2051
2052
    /**
2053
     * Return the same response format for one and multiplete results
2054
     *
2055
     * @param array $responseBody
2056
     * 
2057
     * @return array
2058
     */
2059
    public function unifyResponseFormat($responseBody) {
2060
        if (!is_array($responseBody) || array_key_exists('message',
0 ignored issues
show
introduced by
The condition is_array($responseBody) is always true.
Loading history...
2061
                        $responseBody)) { //Unifi response format
2062
            $response = $responseBody;
2063
        } else {
2064
            $evidence = $this->getResponseEvidence();
2065
            if (array_key_exists($evidence, $responseBody)) {
2066
                $response = [];
2067
                $evidenceContent = $responseBody[$evidence];
2068
                if (array_key_exists(0, $evidenceContent)) {
2069
                    $response[$evidence] = $evidenceContent; //Multiplete Results
2070
                } else {
2071
                    $response[$evidence][0] = $evidenceContent; //One result
2072
                }
2073
            } else {
2074
                if (isset($responseBody['priloha'])) {
2075
                    $response = $responseBody['priloha'];
2076
                } else {
2077
                    if (array_key_exists('results', $responseBody)) {
2078
                        $response = $responseBody['results'];
2079
                    } else {
2080
                        $response = $responseBody;
2081
                    }
2082
                }
2083
            }
2084
        }
2085
        return $response;
2086
    }
2087
2088
    /**
2089
     * Obtain structure for current (or given) evidence
2090
     *
2091
     * @param string $evidence
2092
     * 
2093
     * @return array Evidence structure
2094
     */
2095
    public function getOfflineColumnsInfo($evidence = null) {
2096
        $columnsInfo = null;
2097
        $infoSource = self::$infoDir . '/Properties.' . (empty($evidence) ? $this->getEvidence() : $evidence) . '.json';
2098
        if (file_exists($infoSource)) {
2099
            $columnsInfo = json_decode(file_get_contents($infoSource), true);
2100
        }
2101
        return $columnsInfo;
2102
    }
2103
2104
    /**
2105
     * Obtain Current evidence Live structure
2106
     * 
2107
     * @param string $evidence
2108
     * 
2109
     * @return array structure
2110
     */
2111
    public function getOnlineColumnsInfo($evidence = null) {
2112
        $properties = [];
2113
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2114
        $flexinfo = $this->performRequest('/c/' . $this->company . '/' . $evidence . '/properties.json');
2115
        if (!empty($flexinfo) && array_key_exists('properties', $flexinfo)) {
2116
            foreach ($flexinfo['properties']['property'] as $evidenceProperty) {
2117
                $key = $evidenceProperty['propertyName'];
2118
                $properties[$key] = $evidenceProperty;
2119
                if (array_key_exists('name', $evidenceProperty)) {
2120
                    $proerties[$key]['name'] = $evidenceProperty['name'];
2121
                }
2122
                $properties[$key]['type'] = $evidenceProperty['type'];
2123
                if (array_key_exists('url', $evidenceProperty)) {
2124
                    $properties[$key]['url'] = str_replace('?limit=0', '',
2125
                            $evidenceProperty['url']);
2126
                }
2127
            }
2128
        }
2129
        return $properties;
2130
    }
2131
2132
    /**
2133
     * Update evidence info from array or online from properties.json or offline
2134
     * 
2135
     * @param array  $columnsInfo
2136
     * @param string $evidence
2137
     */
2138
    public function updateColumnsInfo($columnsInfo = null, $evidence = null) {
2139
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2140
        if (is_null($columnsInfo)) {
2141
            $this->columnsInfo[$evidence] = $this->offline ? $this->getOfflineColumnsInfo($evidence) : $this->getOnlineColumnsInfo($evidence);
2142
        } else {
2143
            $this->columnsInfo[$evidence] = $columnsInfo;
2144
        }
2145
    }
2146
2147
    /**
2148
     * Gives you evidence structure. You can obtain current online by pre-calling:
2149
     * $this->updateColumnsInfo($evidence, $this->getOnlineColumnsInfo($evidence));
2150
     * 
2151
     * @param string $evidence
2152
     * 
2153
     * @return array
2154
     */
2155
    public function getColumnsInfo($evidence = null) {
2156
        $evidence = is_null($evidence) ? $this->getEvidence() : $evidence;
2157
        if (!array_key_exists($evidence, $this->columnsInfo)) {
2158
            $this->updateColumnsInfo($this->getOfflineColumnsInfo($evidence),
2159
                    $evidence);
2160
        }
2161
        return $this->columnsInfo[$evidence];
2162
    }
2163
2164
    /**
2165
     * Gives you properties for (current) evidence column
2166
     *
2167
     * @param string $column    name of column
2168
     * @param string $evidence  evidence name if different
2169
     *
2170
     * @return array column properties or null if column not exits
2171
     */
2172
    public function getColumnInfo($column, $evidence = null) {
2173
        $columnsInfo = $this->getColumnsInfo(empty($evidence) ? $this->getEvidence() : $evidence);
2174
        return (empty($column) || empty($columnsInfo) || !is_array($columnsInfo)) ? null : (array_key_exists($column, $columnsInfo) ? $columnsInfo[$column] : null);
2175
    }
2176
2177
    /**
2178
     * Obtain actions for current (or given) evidence
2179
     *
2180
     * @param string $evidence
2181
     * 
2182
     * @return array Evidence structure
2183
     */
2184
    public function getActionsInfo($evidence = null) {
2185
        $actionsInfo = null;
2186
        if (is_null($evidence)) {
2187
            $evidence = $this->getEvidence();
2188
        }
2189
        $propsName = lcfirst(RO::evidenceToClassName($evidence));
2190
        if (isset(\FlexiPeeHP\Actions::$$propsName)) {
2191
            $actionsInfo = Actions::$$propsName;
2192
        }
2193
        return $actionsInfo;
2194
    }
2195
2196
    /**
2197
     * Obtain relations for current (or given) evidence
2198
     *
2199
     * @param string $evidence
2200
     * 
2201
     * @return array Evidence structure
2202
     */
2203
    public function getRelationsInfo($evidence = null) {
2204
        $relationsInfo = null;
2205
        if (is_null($evidence)) {
2206
            $evidence = $this->getEvidence();
2207
        }
2208
        $propsName = lcfirst(RO::evidenceToClassName($evidence));
2209
        if (isset(\FlexiPeeHP\Relations::$$propsName)) {
2210
            $relationsInfo = Relations::$$propsName;
2211
        }
2212
        return $relationsInfo;
2213
    }
2214
2215
    /**
2216
     * Obtain info for current (or given) evidence
2217
     *
2218
     * @param string $evidence
2219
     * 
2220
     * @return array Evidence info
2221
     */
2222
    public function getEvidenceInfo($evidence = null) {
2223
        $evidencesInfo = null;
2224
        if (is_null($evidence)) {
2225
            $evidence = $this->getEvidence();
2226
        }
2227
        if (isset(EvidenceList::$evidences[$evidence])) {
2228
            $evidencesInfo = EvidenceList::$evidences[$evidence];
2229
            $propsName = lcfirst(RO::evidenceToClassName($evidence));
2230
            if (isset(Formats::$$propsName)) {
2231
                $evidencesInfo['formats'] = Formats::$$propsName;
2232
            }
2233
        }
2234
        return $evidencesInfo;
2235
    }
2236
2237
    /**
2238
     * Obtain name for current (or given) evidence path
2239
     *
2240
     * @param string $evidence Evidence Path
2241
     * 
2242
     * @return array Evidence info
2243
     */
2244
    public function getEvidenceName($evidence = null) {
2245
        $evidenceName = null;
2246
        if (is_null($evidence)) {
2247
            $evidence = $this->getEvidence();
2248
        }
2249
        if (isset(EvidenceList::$name[$evidence])) {
2250
            $evidenceName = EvidenceList::$name[$evidence];
2251
        }
2252
        return $evidenceName;
2253
    }
2254
2255
    /**
2256
     * Save current object to file
2257
     *
2258
     * @param string $destfile path to file
2259
     */
2260
    public function saveResponseToFile($destfile) {
2261
        if (strlen($this->lastCurlResponse)) {
2262
            $this->doCurlRequest($this->apiURL, 'GET', $this->format);
2263
        }
2264
        file_put_contents($destfile, $this->lastCurlResponse);
2265
    }
2266
2267
    /**
2268
     * Obtain established relations listing
2269
     *
2270
     * @return array Null or Relations
2271
     */
2272
    public function getVazby($id = null) {
2273
        if (is_null($id)) {
2274
            $id = $this->getRecordID();
2275
        }
2276
        if (!empty($id)) {
2277
            $vazbyRaw = $this->getColumnsFromAbraFlexi(['vazby'],
2278
                    ['relations' => 'vazby', 'id' => $id]);
2279
            $vazby = array_key_exists('vazby', $vazbyRaw[0]) ? $vazbyRaw[0]['vazby'] : null;
2280
        } else {
2281
            throw new \Exception(_('ID requied to get record relations '));
2282
        }
2283
        return $vazby;
2284
    }
2285
2286
    /**
2287
     * Gives You URL for Current Record in AbraFlexi web interface
2288
     *
2289
     * @deprecated since version 2.0
2290
     * 
2291
     * @return string url
2292
     */
2293
    public function getFlexiBeeURL() {
2294
        return $this->getAbraFlexiURL();
2295
    }
2296
2297
    /**
2298
     * Gives You URL for Current Record in FlexiBee web interface
2299
     *
2300
     * @return string url
2301
     */
2302
    public function getAbraFlexiURL() {
2303
        $parsed_url = parse_url(str_replace('.' . $this->format, '', $this->apiURL));
2304
        $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
2305
        $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
2306
        $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
2307
        $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
2308
        $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
2309
        $pass = ($user || $pass) ? "$pass@" : '';
2310
        $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
2311
        return $scheme . $user . $pass . $host . $port . $path;
2312
    }
2313
2314
    /**
2315
     * Set Record Key
2316
     *
2317
     * @param int|string $myKeyValue
2318
     * 
2319
     * @return boolean
2320
     */
2321
    public function setMyKey($myKeyValue) {
2322
        if (substr($myKeyValue, 0, 4) == 'ext:') {
2323
            if (empty($this->evidenceInfo) || ($this->evidenceInfo['extIdSupported'] == 'false')) {
2324
                $this->addStatusMessage(sprintf(_('Evidence %s does not support extIDs'),
2325
                                $this->getEvidence()), 'warning');
2326
                $res = false;
2327
            } else {
2328
                $extIds = $this->getDataValue('external-ids');
2329
                if (!empty($extIds) && count($extIds)) {
2330
                    $extIds = array_combine($extIds, $extIds);
2331
                }
2332
2333
                $extIds[$myKeyValue] = $myKeyValue;
2334
                $res = $this->setDataValue('external-ids',
2335
                        $extIds);
2336
            }
2337
        } else {
2338
            $res = $this->setDataValue($this->getKeyColumn(), $myKeyValue);
2339
        }
2340
        $this->updateApiURL();
2341
        return $res;
2342
    }
2343
2344
    /**
2345
     * Set or get ignore not found pages flag
2346
     *
2347
     * @param boolean $ignore set flag to
2348
     *
2349
     * @return boolean get flag state
2350
     */
2351
    public function ignore404($ignore = null) {
2352
        if (!is_null($ignore)) {
2353
            $this->ignoreNotFound = $ignore;
2354
        }
2355
        return $this->ignoreNotFound;
2356
    }
2357
2358
    /**
2359
     * Send Document by mail
2360
     *
2361
     * @url https://www.flexibee.eu/api/dokumentace/ref/odesilani-mailem/
2362
     *
2363
     * @param string $to         Email ecipient
2364
     * @param string $subject    Email Subject
2365
     * @param string $body       Email Text
2366
     *
2367
     * @return boolean mail sent status
2368
     */
2369
    public function sendByMail($to, $subject, $body, $cc = null) {
2370
        $this->setPostFields($body);
2371
2372
        $this->performRequest(rawurlencode($this->getRecordID()) . '/odeslani-dokladu?to=' . $to . '&subject=' . urlencode($subject) . '&cc=' . $cc
2373
                , 'PUT', 'xml');
2374
2375
        return $this->lastResponseCode == 200;
2376
    }
2377
2378
    /**
2379
     * FlexiBee date to PHP DateTime conversion
2380
     *
2381
     * @param string $flexidate 2017-05-26 or 2017-05-26+02:00
2382
     *
2383
     * @return \DateTime | false
2384
     */
2385
    public static function flexiDateToDateTime($flexidate) {
2386
        return \DateTime::createFromFormat(strstr($flexidate, '+') ? self::$DateFormat . 'O' : self::$DateFormat, $flexidate)->setTime(0, 0);
2387
    }
2388
2389
    /**
2390
     * FlexiBee dateTime to PHP DateTime conversion
2391
     *
2392
     * @param string $flexidatetime 2017-09-26T10:00:53.755+02:00 or older 2017-05-19T00:00:00+02:00
2393
     *
2394
     * @return \DateTime | false
2395
     */
2396
    public static function flexiDateTimeToDateTime($flexidatetime) {
2397
        if (strchr($flexidatetime, '.')) { //NewFormat
2398
            $format = self::$DateTimeFormat;
2399
        } else { // Old format
2400
            $format = 'Y-m-d\TH:i:s+P';
2401
        }
2402
        return \DateTime::createFromFormat($format, $flexidatetime);
2403
    }
2404
2405
    /**
2406
     * Získá dokument v daném formátu
2407
     * Obtain document in given format
2408
     *
2409
     * @link https://www.flexibee.eu/api/dokumentace/ref/pdf/ PDF Exports
2410
     *
2411
     * @param string  $format     pdf/csv/xml/json/ ...
2412
     * @param string  $reportName Template used to generate PDF
2413
     * @param string  $lang       cs|sk|en|de Template language used to generate PDF
2414
     * @param boolean $sign       sign resulting PDF by certificate ?
2415
     *
2416
     * @return string|null filename downloaded or none
2417
     */
2418
    public function getInFormat($format, $reportName = null, $lang = null,
2419
            $sign = false) {
2420
        $response = null;
2421
        if ($this->setFormat($format)) {
2422
            $urlParams = [];
2423
            switch ($format) {
2424
                case 'pdf':
2425
                    switch ($lang) {
2426
                        case 'cs':
2427
                        case 'sk':
2428
                        case 'en':
2429
                        case 'de':
2430
                            $urlParams['report-lang'] = $lang;
2431
                            break;
2432
                        case null:
2433
                        case '':
2434
                            break;
2435
                        default:
2436
                            throw new \Ease\Exception('Unknown language ' . $lang . ' for PDF export');
2437
                            break;
2438
                    }
2439
                    if (boolval($sign) === true) {
2440
                        $urlParams['report-sign'] = 'true';
2441
                    }
2442
                    break;
2443
                case 'html':
2444
                    $urlParams['inDesktopApp'] = 'true';
2445
                    break;
2446
            }
2447
            if (!empty($reportName)) {
2448
                $urlParams['report-name'] = $reportName;
2449
            }
2450
            if (($this->doCurlRequest(\Ease\Functions::addUrlParams($this->apiURL,
2451
                                    $urlParams), 'GET') == 200)) {
2452
                $response = $this->lastCurlResponse;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->lastCurlResponse can also be of type boolean. However, the property $lastCurlResponse is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
2453
            }
2454
        }
2455
        return $response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $response also could return the type boolean which is incompatible with the documented return type null|string.
Loading history...
2456
    }
2457
2458
    /**
2459
     * Uloží dokument v daném formátu do složky v systému souborů
2460
     * Save document in given format to directory in filesystem
2461
     *
2462
     * @param string $format  pdf/csv/xml/json/ ...
2463
     * @param string $destDir where to put file (prefix)
2464
     * @param string $reportName Template used to generate PDF
2465
     *
2466
     * @return string|null filename downloaded or none
2467
     */
2468
    public function downloadInFormat($format, $destDir = './',
2469
            $reportName = null) {
2470
        $fileOnDisk = null;
2471
        $formatBackup = $this->format;
2472
        if ($this->setFormat($format)) {
2473
            $downloadTo = $destDir . $this->getEvidence() . '_' . $this->getMyKey() . '.' . $format;
2474
            if (($this->doCurlRequest(empty($reportName) ? $this->apiURL : \Ease\Functions::addUrlParams($this->apiURL,
2475
                                            ['report-name' => $reportName]), 'GET') == 200) && (file_put_contents($downloadTo,
2476
                            $this->lastCurlResponse) !== false)) {
2477
                $fileOnDisk = $downloadTo;
2478
            }
2479
            $this->setFormat($formatBackup);
2480
        }
2481
        return $fileOnDisk;
2482
    }
2483
2484
    /**
2485
     * Take data for object. separate external IDs
2486
     *
2487
     * @param array $data Data to keep
2488
     * 
2489
     * @return int number of records taken
2490
     */
2491
    public function takeData($data) {
2492
        $keyColumn = $this->getKeyColumn();
2493
        if (array_key_exists($keyColumn, $data) && is_array($data[$keyColumn])) {
2494
            foreach ($data[$keyColumn] as $recPos => $recordKey) {
2495
                if (substr($recordKey, 0, 4) == 'ext:') {
2496
                    $data['external-ids'][] = $recordKey;
2497
                    unset($data[$keyColumn][$recPos]);
2498
                }
2499
            }
2500
            if (count($data[$keyColumn]) == 1) {
2501
                $data[$keyColumn] = current($data[$keyColumn]);
2502
            }
2503
        }
2504
        $result = parent::takeData($data);
2505
2506
        if (array_key_exists($keyColumn, $data) || array_key_exists('kod', $data)) {
2507
            $this->updateApiURL();
2508
        }
2509
2510
        return $result;
2511
    }
2512
2513
    /**
2514
     * Get Current Evidence reports listing
2515
     * 
2516
     * @link https://www.flexibee.eu/api/dokumentace/casto-kladene-dotazy-pro-api/vyber-reportu-do-pdf/ Výběr reportu do PDF
2517
     * 
2518
     * @return array
2519
     */
2520
    public function getReportsInfo() {
2521
        $reports = [];
2522
        $reportsRaw = $this->getFlexiData($this->getEvidenceURL() . '/reports');
2523
        if (!empty($reportsRaw) && array_key_exists('reports', $reportsRaw) && !empty($reportsRaw['reports']) && array_key_exists('report', $reportsRaw['reports']) &&
2524
                !empty($reportsRaw['reports']['report'])) {
2525
            if (\Ease\jQuery\Part::isAssoc($reportsRaw['reports']['report'])) {
0 ignored issues
show
Bug introduced by
The type Ease\jQuery\Part was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2526
                $reports = [$reportsRaw['reports']['report']['reportId'] => $reportsRaw['reports']['report']];
2527
            } else {
2528
                $reports = \Ease\Functions::reindexArrayBy($reportsRaw['reports']['report'],
2529
                                'reportId');
2530
            }
2531
        }
2532
        return $reports;
2533
    }
2534
2535
    /**
2536
     * Request authSessionId from current server
2537
     * 
2538
     * @link https://www.flexibee.eu/api/dokumentace/ref/login/ description
2539
     * 
2540
     * @param string $username
2541
     * @param string $password
2542
     * @param string $otp       optional onetime password
2543
     * 
2544
     * @return string authUserId or null in case of problems
2545
     */
2546
    public function requestAuthSessionID($username, $password, $otp = null) {
2547
        $this->postFields = http_build_query(is_null($otp) ? ['username' => $username,
2548
            'password' => $password] : ['username' => $username, 'password' => $password,
2549
            'otp' => $otp]);
2550
        $response = $this->performRequest('/login-logout/login', 'POST',
2551
                'json');
2552
        if (array_key_exists('refreshToken', $response)) {
2553
            $this->refreshToken = $response['refreshToken'];
2554
        } else {
2555
            $this->refreshToken = null;
2556
        }
2557
        return array_key_exists('authSessionId', $response) ? $response['authSessionId'] : null;
2558
    }
2559
2560
    /**
2561
     * Try to Sign in current user to FlexiBee and keep authSessionId
2562
     * 
2563
     * @return boolean sign in success
2564
     */
2565
    public function login() {
2566
        $this->authSessionId = $this->requestAuthSessionID($this->user,
2567
                $this->password);
2568
        return $this->lastResponseCode == 200;
2569
    }
2570
2571
    /**
2572
     * End (current's user) session
2573
     * 
2574
     * 
2575
     * @link https://www.flexibee.eu/api/dokumentace/ref/logout Logout Reference
2576
     * 
2577
     * @param string $username force username to sign off
2578
     * 
2579
     * @return array server response
2580
     */
2581
    public function logout($username = null) {
2582
        return $this->performRequest('/status/user/' . (is_null($username) ? $this->user : $username) . '/logout', 'POST');
2583
    }
2584
2585
    /**
2586
     * Compile and send Report about Error500 to FlexiBee developers
2587
     * If FlexiBee is running on localost try also include java backtrace
2588
     *
2589
     * @param array $errorResponse result of parseError();
2590
     */
2591
    public function error500Reporter($errorResponse) {
2592
        $ur = str_replace('/c/' . $this->company, '',
2593
                str_replace($this->url, '', $this->curlInfo['url']));
2594
        if (!array_key_exists($ur, $this->reports)) {
2595
            $tmpdir = sys_get_temp_dir();
2596
            $myTime = $this->curlInfo['when'];
2597
            $curlname = $tmpdir . '/curl-' . $this->evidence . '-' . $myTime . '.json';
2598
            file_put_contents($curlname,
2599
                    json_encode($this->curlInfo, JSON_PRETTY_PRINT));
2600
2601
            $report = new \Ease\Mailer($this->reportRecipient,
2602
                    'Error report 500 - ' . $ur);
2603
2604
            $d = dir($tmpdir);
2605
            while (false !== ($entry = $d->read())) {
2606
                if (strstr($entry, $myTime)) {
2607
                    $ext = pathinfo($tmpdir . '/' . $entry, PATHINFO_EXTENSION);
2608
                    $mime = Formats::suffixToContentType($ext);
2609
                    $report->addFile($tmpdir . '/' . $entry,
2610
                            empty($mime) ? 'text/plain' : $mime);
2611
                }
2612
            }
2613
            $d->close();
2614
2615
            if ((strstr($this->url, '://localhost') || strstr($this->url,
2616
                            '://127.')) && file_exists('/var/log/flexibee.log')) {
2617
2618
                $fl = fopen('/var/log/' . 'flexibee.log', 'r');
2619
                if ($fl) {
0 ignored issues
show
introduced by
$fl is of type false|resource, thus it always evaluated to false.
Loading history...
2620
                    $tracelog = [];
2621
                    for ($x_pos = 0, $ln = 0, $output = array(); fseek($fl,
2622
                                    $x_pos, SEEK_END) !== -1; $x_pos--) {
2623
                        $char = fgetc($fl);
2624
                        if ($char === "\n") {
2625
                            $tracelog[] = $output[$ln];
2626
                            if (strstr($output[$ln], $errorResponse['message'])) {
2627
                                break;
2628
                            }
2629
                            $ln++;
2630
                            continue;
2631
                        }
2632
                        $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : '');
2633
                    }
2634
2635
                    $trace = implode("\n", array_reverse($tracelog));
2636
                    $tracefile = $tmpdir . '/trace-' . $this->evidence . '-' . $myTime . '.log';
2637
                    file_put_contents($tracefile, $trace);
2638
                    $report->addItem("\n\n" . $trace);
2639
                    fclose($fl);
2640
                }
2641
            } else {
2642
                $report->addItem($errorResponse['message']);
0 ignored issues
show
Bug introduced by
The method addItem() does not exist on Ease\Mailer. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2642
                $report->/** @scrutinizer ignore-call */ 
2643
                         addItem($errorResponse['message']);

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...
2643
            }
2644
2645
            $licenseInfo = $this->performRequest($this->url . '/default-license.json');
2646
2647
            $report->addItem("\n\n" . json_encode($licenseInfo['license'],
2648
                            JSON_PRETTY_PRINT));
2649
2650
            if ($report->send()) {
2651
                $this->reports[$ur] = $myTime;
2652
            }
2653
        }
2654
    }
2655
2656
    /**
2657
     * Returns code:CODE
2658
     *
2659
     * @param string $code
2660
     *
2661
     * @return string
2662
     */
2663
    public static function code($code) {
2664
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:' . strtoupper(self::uncode($code)));
2665
    }
2666
2667
    /**
2668
     * Returns CODE without code: prefix
2669
     *
2670
     * @param string $code
2671
     *
2672
     * @return string
2673
     */
2674
    public static function uncode($code) {
2675
        return str_replace(['code:', 'code%3A'], '', $code);
2676
    }
2677
2678
    /**
2679
     * Remove all @ items from array
2680
     *
2681
     * @param array $data original data
2682
     *
2683
     * @return array data without @ columns
2684
     */
2685
    public static function arrayCleanUP($data) {
2686
        return array_filter(
2687
                $data,
2688
                function ($key) {
2689
            return !strchr($key, '@');
2690
        }, ARRAY_FILTER_USE_KEY);
2691
    }
2692
2693
    /**
2694
     * Add Info about used user, server and libraries
2695
     *
2696
     * @param string $prefix banner prefix text
2697
     * @param string $suffix banner suffix text
2698
     */
2699
    public function logBanner($prefix = null, $suffix = null) {
2700
        parent::logBanner($prefix,
2701
                ' ServerURI ' . str_replace('://', '://' . $this->user . '@',
2702
                        $this->getApiUrl()) . ' library v' . self::$libVersion . ' (FlexiBee ' . EvidenceList::$version . ') '.$suffix
2703
        );
2704
    }
2705
2706
    /**
2707
     * Get Last operation type
2708
     * 
2709
     * @return string create|read|update|delete or update,insert for some inserted and updated in one transaction
2710
     */
2711
    public function getLastOperationType() {
2712
        return implode(',', array_keys(array_filter($this->responseStats)));
2713
    }
2714
2715
    /**
2716
     * Last operation errors 
2717
     * 
2718
     * @return array FlexiBee error meassages
2719
     */
2720
    public function getErrors() {
2721
        return $this->errors;
2722
    }
2723
2724
    /**
2725
     * Reconnect After unserialization
2726
     */
2727
    public function __wakeup() {
2728
        $this->curlInit();
2729
    }
2730
2731
}
2732