Passed
Push — master ( b2f528...fcecd3 )
by Vítězslav
21:42
created

RO::error500Reporter()   C

Complexity

Conditions 14
Paths 25

Size

Total Lines 61
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 45
c 1
b 0
f 1
dl 0
loc 61
rs 6.2666
cc 14
nc 25
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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->loadFromFlexiBee($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->loadFromFlexiBee($init);
597
        }
598
    }
599
600
    /**
601
     * Set Data Field value
602
     *
603
     * @param string $columnName field name
604
     * @param mixed  $value      field data value
605
     *
606
     * @return bool Success
607
     */
608
    public function setDataValue($columnName, $value) {
609
        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
     * Načte záznam z FlexiBee a uloží v sobě jeho data
1364
     * Read FlexiBee record and store it inside od object
1365
     *
1366
     * @param int|string $id ID or conditions
1367
     *
1368
     * @return int počet načtených položek
1369
     */
1370
    public function loadFromFlexiBee($id = null) {
1371
        $data = [];
1372
        if (is_null($id)) {
1373
            $id = $this->getMyKey();
1374
        }
1375
        $flexidata = $this->getFlexiData($this->getEvidenceUrl() . '/' . self::urlizeId($id));
1376
        if ($this->lastResponseCode == 200) {
1377
            $this->apiURL = $this->curlInfo['url'];
1378
            if (is_array($flexidata) && (count($flexidata) == 1) && is_array(current($flexidata))) {
1379
                $data = current($flexidata);
1380
            }
1381
        }
1382
        return $this->takeData($data);
1383
    }
1384
1385
    /**
1386
     * Reload current record from FlexiBee
1387
     * 
1388
     * @return boolean 
1389
     */
1390
    public function reload() {
1391
        $id = $this->getRecordIdent();
1392
        $this->dataReset();
1393
        $this->loadFromFlexiBee($id);
1394
        return $this->lastResponseCode == 200;
1395
    }
1396
1397
    /**
1398
     * Set Filter code for requests
1399
     *
1400
     * @link https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1401
     *
1402
     * @param array|string $filter filter formula or ['key'=>'value']
1403
     *
1404
     * @return string Filter code
1405
     */
1406
    public function setFilter($filter) {
1407
        return $this->filter = is_array($filter) ? self::flexiUrl($filter) : $filter;
1408
    }
1409
1410
    /**
1411
     * Převede data do Json formátu pro FlexiBee.
1412
     * Convert data to FlexiBee like Json format
1413
     *
1414
     * @url https://www.flexibee.eu/api/dokumentace/ref/actions/
1415
     * @url https://www.flexibee.eu/api/dokumentace/ref/zamykani-odemykani/
1416
     *
1417
     * @param array $data    object data
1418
     * @param int   $options json_encode options like JSON_PRETTY_PRINT etc
1419
     *
1420
     * @return string
1421
     */
1422
    public function getJsonizedData($data = null, $options = 0) {
1423
        if (is_null($data)) {
1424
            $data = $this->getData();
1425
        }
1426
1427
        $dataToJsonize = array_merge(['@version' => $this->protoVersion],
1428
                $this->getDataForJSON($data));
1429
        $jsonRaw = json_encode([$this->nameSpace => $dataToJsonize],
1430
                $options);
1431
1432
        return $jsonRaw;
1433
    }
1434
1435
    /**
1436
     * Get Data Fragment specific for current object
1437
     *
1438
     * @param array $data
1439
     *
1440
     * @return array
1441
     */
1442
    public function getDataForJSON($data = null) {
1443
        if (is_null($data)) {
1444
            $data = $this->getData();
1445
        }
1446
1447
        $dataForJson = [$this->getEvidence() => $this->objectToID($data)];
1448
1449
        if (!is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
1450
            $dataForJson[$this->evidence . '@action'] = $this->action;
1451
            $this->action = null;
1452
        }
1453
1454
        if (!is_null($this->filter)) {
0 ignored issues
show
introduced by
The condition is_null($this->filter) is always false.
Loading history...
1455
            $dataForJson[$this->evidence . '@filter'] = $this->filter;
1456
        }
1457
1458
1459
        foreach ($this->chained as $chained) {
1460
            $chainedData = $chained->getDataForJSON();
1461
            foreach ($chainedData as $chainedItemEvidence => $chainedItemData) {
1462
                if (array_key_exists($chainedItemEvidence, $dataForJson)) {
1463
                    if (is_string(key($dataForJson[$chainedItemEvidence]))) {
1464
                        $dataBackup = $dataForJson[$chainedItemEvidence];
1465
                        $dataForJson[$chainedItemEvidence] = [];
1466
                        $dataForJson[$chainedItemEvidence][] = $dataBackup;
1467
                    }
1468
                    if (array_key_exists(0, $chainedItemData)) {
1469
                        foreach ($chainedItemData as $chainedItem) {
1470
                            $dataForJson[$chainedItemEvidence][] = $chainedItem;
1471
                        }
1472
                    } else {
1473
                        $dataForJson[$chainedItemEvidence][] = $chainedItemData;
1474
                    }
1475
                } else {
1476
                    $dataForJson[$chainedItemEvidence] = $chainedItemData;
1477
                }
1478
            }
1479
        }
1480
1481
1482
        return $dataForJson;
1483
    }
1484
1485
    /**
1486
     * Join another FlexiPeeHP Object
1487
     *
1488
     * @param RO $object
1489
     *
1490
     * @return boolean adding to stack success
1491
     */
1492
    public function join(&$object) {
1493
        $result = true;
1494
        if (method_exists($object, 'getDataForJSON')) {
1495
            $this->chained[] = $object;
1496
        } else {
1497
            throw new \Ease\Exception('$object->getDataForJSON() does not exist');
1498
        }
1499
1500
        return $result;
1501
    }
1502
1503
    /**
1504
     * Prepare record ID to use in URL
1505
     * 
1506
     * @param mixed $id
1507
     * 
1508
     * @return string id ready for use in URL
1509
     */
1510
    public static function urlizeId($id) {
1511
        if (is_array($id)) {
1512
            $id = rawurlencode('(' . self::flexiUrl($id) . ')');
1513
        } else if (preg_match('/^ext:/', $id)) {
1514
            $id = self::urlEncode($id);
1515
        } else if (preg_match('/^code:/', $id)) {
1516
            $id = self::code(self::urlEncode(self::uncode($id)));
1517
        }
1518
        return $id;
1519
    }
1520
1521
    /**
1522
     * Test if given record ID exists in FlexiBee.
1523
     *
1524
     * @param mixed $identifer presence state
1525
     *
1526
     * @return boolean
1527
     */
1528
    public function idExists($identifer = null) {
1529
        if (is_null($identifer)) {
1530
            $identifer = $this->getMyKey();
1531
        }
1532
        $ignorestate = $this->ignore404();
1533
        $this->ignore404(true);
1534
        $cands = $this->getFlexiData(null,
1535
                [
1536
                    'detail' => 'custom:' . $this->getKeyColumn(),
1537
                    $this->getKeyColumn() => $identifer
1538
        ]);
1539
        $this->ignore404($ignorestate);
1540
        return ($this->lastResponseCode == 200) && !empty($cands);
1541
    }
1542
1543
    /**
1544
     * Test if given record exists in FlexiBee.
1545
     *
1546
     * @param array|string|int $data ext:id:23|code:ITEM|['id'=>23]|23
1547
     * 
1548
     * @return boolean Record presence status
1549
     */
1550
    public function recordExists($data = []) {
1551
1552
        if (empty($data)) {
1553
            $data = $this->getData();
1554
        }
1555
        $ignorestate = $this->ignore404();
1556
        $this->ignore404(true);
1557
        $keyColumn = $this->getKeyColumn();
1558
        $res = $this->getColumnsFromFlexibee([$keyColumn],
1559
                is_array($data) ? $data : [$keyColumn => $data]);
1560
1561
        if (empty($res) || (isset($res['success']) && ($res['success'] == 'false')) || ((isset($res) && is_array($res)) && !isset($res[0]) )) {
1562
            $found = false;
1563
        } else {
1564
            $found = true;
1565
        }
1566
        $this->ignore404($ignorestate);
1567
        return $found;
1568
    }
1569
1570
    /**
1571
     * Vrací z FlexiBee sloupečky podle podmínek.
1572
     *
1573
     * @param array|int|string $conditions pole podmínek nebo ID záznamu
1574
     * @param string           $indexBy    klice vysledku naplnit hodnotou ze
1575
     *                                     sloupečku
1576
     * @return array
1577
     */
1578
    public function getAllFromFlexibee($conditions = null, $indexBy = null) {
1579
        if (is_int($conditions)) {
1580
            $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

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

2604
                $report->/** @scrutinizer ignore-call */ 
2605
                         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...
2605
            }
2606
2607
            $licenseInfo = $this->performRequest($this->url . '/default-license.json');
2608
2609
            $report->addItem("\n\n" . json_encode($licenseInfo['license'],
2610
                            JSON_PRETTY_PRINT));
2611
2612
            if ($report->send()) {
2613
                $this->reports[$ur] = $myTime;
2614
            }
2615
        }
2616
    }
2617
2618
    /**
2619
     * Returns code:CODE
2620
     *
2621
     * @param string $code
2622
     *
2623
     * @return string
2624
     */
2625
    public static function code($code) {
2626
        return ((substr($code, 0, 4) == 'ext:') ? $code : 'code:' . strtoupper(self::uncode($code)));
2627
    }
2628
2629
    /**
2630
     * Returns CODE without code: prefix
2631
     *
2632
     * @param string $code
2633
     *
2634
     * @return string
2635
     */
2636
    public static function uncode($code) {
2637
        return str_replace(['code:', 'code%3A'], '', $code);
2638
    }
2639
2640
    /**
2641
     * Remove all @ items from array
2642
     *
2643
     * @param array $data original data
2644
     *
2645
     * @return array data without @ columns
2646
     */
2647
    public static function arrayCleanUP($data) {
2648
        return array_filter(
2649
                $data,
2650
                function ($key) {
2651
            return !strchr($key, '@');
2652
        }, ARRAY_FILTER_USE_KEY);
2653
    }
2654
2655
    /**
2656
     * Add Info about used user, server and libraries
2657
     *
2658
     * @param string $prefix banner prefix text
2659
     * @param string $suffix banner suffix text
2660
     */
2661
    public function logBanner($prefix = null, $suffix = null) {
2662
        parent::logBanner($prefix,
2663
                ' FlexiBee ' . str_replace('://', '://' . $this->user . '@',
2664
                        $this->getApiUrl()) . ' FlexiBeeHP v' . self::$libVersion . ' (FlexiBee ' . EvidenceList::$version . ') EasePHP Framework v' . \Ease\Atom::$frameworkVersion . ' ' .
2665
                $suffix
2666
        );
2667
    }
2668
2669
    /**
2670
     * Get Last operation type
2671
     * 
2672
     * @return string create|read|update|delete or update,insert for some inserted and updated in one transaction
2673
     */
2674
    public function getLastOperationType() {
2675
        return implode(',', array_keys(array_filter($this->responseStats)));
2676
    }
2677
2678
    /**
2679
     * Last operation errors 
2680
     * 
2681
     * @return array FlexiBee error meassages
2682
     */
2683
    public function getErrors() {
2684
        return $this->errors;
2685
    }
2686
2687
    /**
2688
     * Reconnect After unserialization
2689
     */
2690
    public function __wakeup() {
2691
        $this->curlInit();
2692
    }
2693
2694
}
2695