MODxAPI::store()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2 1
include_once(MODX_BASE_PATH . 'assets/lib/APIHelpers.class.php');
3 1
include_once(MODX_BASE_PATH . 'assets/snippets/DocLister/lib/jsonHelper.class.php');
4 1
include_once(MODX_BASE_PATH . 'assets/snippets/DocLister/lib/DLCollection.class.php');
5
6
use \Doctrine\Common\Cache\Cache;
0 ignored issues
show
Bug introduced by
The type \Doctrine\Common\Cache\Cache 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...
7
8
/**
9
 * Class MODxAPIhelpers
10
 */
11
class MODxAPIhelpers
12
{
13
14
    /**
15
     * @param $email
16
     * @param bool $dns
17
     * @return false|string
18
     */
19
    public function emailValidate($email, $dns = true)
20
    {
21
        return \APIhelpers::emailValidate($email, $dns);
22
    }
23
24
    /**
25
     * @param $len
26
     * @param string $data
27
     * @return string
28
     */
29
    public function genPass($len, $data = '')
30
    {
31
        return \APIhelpers::genPass($len, $data);
32
    }
33
34
    /**
35
     * @param string $out
36
     * @return string
37
     */
38
    public function getUserIP($out = '127.0.0.1')
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
39
    {
40
        return \APIhelpers::getUserIP($out);
41
    }
42
43
    /**
44
     * @param $data
45
     * @return array|mixed|string
46
     */
47
    public function sanitarTag($data)
48
    {
49
        return \APIhelpers::sanitarTag($data);
50
    }
51
52
    /**
53
     * @param $value
54
     * @param int $minLen
55
     * @param array $alph
56
     * @param array $mixArray
57
     * @return bool
58
     */
59
    public function checkString($value, $minLen = 1, $alph = array(), $mixArray = array())
60
    {
61
        return \APIhelpers::checkString($value, $minLen, $alph, $mixArray);
62
    }
63
}
64
65
/**
66
 * Class MODxAPI
67
 */
68
abstract class MODxAPI extends MODxAPIhelpers
69
{
70
    /**
71
     * Объект DocumentParser - основной класс MODX
72
     * @var \DocumentParser
73
     * @access protected
74
     */
75
    protected $modx = null;
76
77
    /**
78
     * @var array
79
     */
80
    protected $log = array();
81
82
    /**
83
     * @var array
84
     */
85
    protected $field = array();
86
87
    /**
88
     * @var array
89
     */
90
    protected $default_field = array();
91
92
    /**
93
     * @var mixed
94
     */
95
    protected $id;
96
97
    /**
98
     * @var array
99
     */
100
    protected $set = array();
101
102
    /**
103
     * @var bool
104
     */
105
    protected $newDoc = false;
106
107
    /**
108
     * @var string
109
     */
110
    protected $pkName = 'id';
111
112
    /**
113
     * @var string
114
     */
115
    protected $ignoreError = '';
116
117
    /**
118
     * @var bool
119
     */
120
    protected $_debug = false;
121
122
    /**
123
     * @var array
124
     */
125
    protected $_query = array();
126
127
    /**
128
     * @var array
129
     */
130
    protected $jsonFields = array();
131
132
    /**
133
     * @var array
134
     */
135
    protected $store = array();
136
137
    /**
138
     * @var DLCollection
139
     */
140
    protected $_decodedFields;
141
142
    /**
143
     * @var array
144
     */
145
    private $_table = array();
146
147
    private $cache = false;
148
149
    /**
150
     * MODxAPI constructor.
151
     * @param DocumentParser $modx
152
     * @param bool $debug
153
     * @throws Exception
154
     */
155 12
    public function __construct(DocumentParser $modx, $debug = false)
156
    {
157 12
        $this->modx = $modx;
158 12
        $this->setDebug($debug);
159
        $this->_decodedFields = new DLCollection($this->modx);
160
        $this->cache = isset($this->modx->cache) && $this->modx->cache instanceof Cache;
0 ignored issues
show
Bug introduced by
The property cache does not seem to exist on DocumentParser.
Loading history...
161
    }
162 12
163 12
    /**
164 12
     * @param boolean $flag
165 12
     * @return $this
166
     */
167
    public function setDebug($flag)
168
    {
169
        $this->_debug = (bool)$flag;
170
171 12
        return $this;
172
    }
173 12
174
    /**
175 12
     * @return bool
176
     */
177
    public function getDebug()
178
    {
179
        return $this->_debug;
180
    }
181 2
182
    /**
183 2
     * @return array
184
     */
185
    public function getDefaultFields()
186
    {
187
        return $this->default_field;
188
    }
189
190
    /**
191
     * @param $value
192
     * @return int|mixed|string
193
     */
194
    protected function getTime($value)
195
    {
196
        $value = trim($value);
197
        if (! empty($value)) {
198 1
            if (! is_numeric($value)) {
199
                $value = (int)strtotime($value);
200 1
            }
201 1
            if (! empty($value)) {
202 1
                $value += $this->modxConfig('server_offset_time');
203
            }
204
        }
205 1
206 1
        return $value;
207 1
    }
208 1
209
    /**
210 1
     * @param string $name
211
     * @param null $default
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $default is correct as it would always require null to be passed?
Loading history...
212
     * @return mixed
213
     */
214
    final public function modxConfig($name, $default = null)
215
    {
216
        return APIHelpers::getkey($this->modx->config, $name, $default);
217
    }
218 1
219
    /**
220 1
     * @param $q
221
     * @return $this
222
     */
223
    public function addQuery($q)
224
    {
225
        if (is_scalar($q) && ! empty($q)) {
226
            $this->_query[] = $q;
227
        }
228
229
        return $this;
230
    }
231
232
    /**
233
     * @return array
234
     */
235
    public function getQueryList()
236
    {
237
        return $this->_query;
238
    }
239
240
    /**
241
     * @param $SQL
242
     * @return mixed
243
     */
244
    final public function query($SQL)
245
    {
246
        if ($this->getDebug()) {
247
            $this->addQuery($SQL);
248 2
        }
249
250 2
        return empty($SQL) ? null : $this->modx->db->query($SQL);
251
    }
252
253
    /**
254 2
     * @param $value
255
     * @return string|void
256
     */
257
    final public function escape($value)
258
    {
259
        if (! is_scalar($value)) {
260
            $value = '';
261 1
        } else {
262
            $value = $this->modx->db->escape($value);
263 1
        }
264
265
        return $value;
266 1
    }
267
268
    /**
269 1
     * @param string $name
270
     * @param array $data
271
     * @param bool $flag
272
     * @return $this
273
     */
274
    final public function invokeEvent($name, $data = array(), $flag = false)
275
    {
276
        if ((bool)$flag === true) {
277
            $this->modx->invokeEvent($name, $data);
0 ignored issues
show
Bug introduced by
The method invokeEvent() does not exist on DocumentParser. ( Ignorable by Annotation )

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

277
            $this->modx->/** @scrutinizer ignore-call */ 
278
                         invokeEvent($name, $data);

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...
278 1
        }
279
280 1
        return $this;
281
    }
282
283
    /**
284 1
     * @param string $name
285
     * @param array $data
286
     * @param boolean $flag
287
     * @return array|bool
288
     */
289
    final public function getInvokeEventResult($name, $data = array(), $flag = null)
290
    {
291
        $flag = (isset($flag) && $flag !== '') ? (bool)$flag : false;
292
293
        return $flag ? $this->modx->invokeEvent($name, $data) : false;
294
    }
295
296
    /**
297
     * @return $this
298
     */
299
    final public function clearLog()
300
    {
301
        $this->log = array();
302
303
        return $this;
304
    }
305
306
    /**
307
     * @return array
308
     */
309
    final public function getLog()
310
    {
311
        return $this->log;
312
    }
313 1
314
    /**
315 1
     * @param bool $flush
316
     * @return $this
317
     */
318
    final public function list_log($flush = false)
0 ignored issues
show
Coding Style introduced by
Method name "MODxAPI::list_log" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
319
    {
320
        echo '<pre>' . print_r(APIHelpers::sanitarTag($this->log), true) . '</pre>';
0 ignored issues
show
Bug introduced by
Are you sure print_r(APIHelpers::sanitarTag($this->log), true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

320
        echo '<pre>' . /** @scrutinizer ignore-type */ print_r(APIHelpers::sanitarTag($this->log), true) . '</pre>';
Loading history...
321
        if ($flush) {
322
            $this->clearLog();
323
        }
324
325
        return $this;
326
    }
327
328
    /**
329
     * @param bool $full
330
     * @return string
331
     */
332
    final public function getCachePath($full = true)
333
    {
334
        $path = $this->modx->getCachePath();
0 ignored issues
show
Bug introduced by
The method getCachePath() does not exist on DocumentParser. ( Ignorable by Annotation )

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

334
        /** @scrutinizer ignore-call */ 
335
        $path = $this->modx->getCachePath();

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...
335
        if ($full) {
336
            $path = MODX_BASE_PATH . substr($path, strlen(MODX_BASE_URL));
337
        }
338
339
        return $path;
340
    }
341
342
    /**
343
     * @param boolean $fire_events
344
     * @param bool $custom
345
     */
346
    final public function clearCache($fire_events = false, $custom = false)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
347
    {
348
        $IDs = array();
349
        if ($custom === false) {
350
            $this->modx->clearCache();
0 ignored issues
show
Bug introduced by
The method clearCache() does not exist on DocumentParser. ( Ignorable by Annotation )

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

350
            $this->modx->/** @scrutinizer ignore-call */ 
351
                         clearCache();

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...
351
            include_once(MODX_MANAGER_PATH . 'processors/cache_sync.class.processor.php');
352
            $sync = new synccache();
0 ignored issues
show
Bug introduced by
The type synccache 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...
353
            $path = $this->getCachePath(true);
354
            $sync->setCachepath($path);
355
            $sync->setReport(false);
356
            $sync->emptyCache();
357
        } else {
358
            if (is_scalar($custom)) {
0 ignored issues
show
introduced by
The condition is_scalar($custom) is always true.
Loading history...
359
                $custom = array($custom);
360
            }
361
            switch ($this->modx->config['cache_type']) {
362
                case 2:
363
                    $cacheFile = "_*.pageCache.php";
364
                    break;
365
                default:
366
                    $cacheFile = ".pageCache.php";
367
            }
368
            if (is_array($custom)) {
0 ignored issues
show
introduced by
The condition is_array($custom) is always true.
Loading history...
369
                foreach ($custom as $id) {
370
                    $tmp = glob(MODX_BASE_PATH . "assets/cache/docid_" . $id . $cacheFile);
0 ignored issues
show
Bug introduced by
Are you sure $id of type true can be used in concatenation? ( Ignorable by Annotation )

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

370
                    $tmp = glob(MODX_BASE_PATH . "assets/cache/docid_" . /** @scrutinizer ignore-type */ $id . $cacheFile);
Loading history...
371
                    foreach ($tmp as $file) {
372
                        if (is_readable($file)) {
373
                            unlink($file);
374
                        }
375
                        $IDs[] = $id;
376
                    }
377
                }
378
            }
379
            clearstatcache();
380
        }
381
        $this->invokeEvent('OnSiteRefresh', array('IDs' => $IDs), $fire_events);
382
    }
383
384
    /**
385
     * @param integer $id
386
     * @return MODxAPI
387
     */
388
    public function switchObject($id)
389
    {
390
        switch (true) {
391
            //Если загружен другой объект - не тот, с которым мы хотим временно поработать
392
            case ($this->getID() != $id && $id):
393
                $obj = clone $this;
394
                $obj->edit($id);
395
                break;
396
            //Если уже загружен объект, с которым мы хотим временно поработать
397
            case ($this->getID() == $id && $id):
398
                //Если $id не указан, но уже загружен какой-то объект
399
            case (! $id && null !== $this->getID()):
400
            default:
401
                $obj = $this;
402
                break;
403
        }
404
405
        return $obj;
406
    }
407
408
    /**
409
     * @param bool $flag
410
     * @return $this
411
     */
412
    public function useIgnore($flag = true)
413
    {
414
        $this->ignoreError = $flag ? 'IGNORE' : '';
415
416
        return $this;
417
    }
418
419
    /**
420
     * @return bool
421
     */
422
    public function hasIgnore()
423
    {
424
        return (bool)$this->ignoreError;
425
    }
426
427
    /**
428
     * @param $key
429
     * @param $value
430
     * @return $this
431
     */
432
    public function set($key, $value)
433
    {
434
        if ((is_scalar($value) || $this->isJsonField($key)) && is_scalar($key) && ! empty($key)) {
435
            $this->field[$key] = $value;
436
        }
437
438
        return $this;
439
    }
440
441
    /**
442
     * @return null|int
443
     */
444
    final public function getID()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
445
    {
446
        return $this->id;
447
    }
448 12
449
    /**
450 12
     * @param $key
451
     * @return mixed
452
     */
453
    public function get($key)
454
    {
455
        return APIHelpers::getkey($this->field, $key, null);
456
    }
457 11
458
    /**
459 11
     * @param $data
460
     * @return $this
461
     */
462
    public function fromArray($data)
463
    {
464
        if (is_array($data)) {
465
            foreach ($data as $key => $value) {
466 1
                $this->set($key, $value);
467
            }
468 1
        }
469 1
470 1
        return $this;
471 1
    }
472 1
473
    /**
474 1
     * Формирует массив значений для подстановки в SQL запрос на обновление
475
     *
476
     * @param $key
477
     * @param string $id
478
     * @return $this
479
     * @throws Exception
480
     */
481
    final protected function Uset($key, $id = '')
0 ignored issues
show
Coding Style introduced by
Method name "MODxAPI::Uset" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
482
    {
483
        if (! isset($this->field[$key])) {
484
            $tmp = "`{$key}`=''";
485 1
            $this->log[] = "{$key} is empty";
486
        } else {
487 1
            if ($this->issetField($key) && is_scalar($this->field[$key])) {
488
                $tmp = "`{$key}`='{$this->escape($this->field[$key])}'";
489
            } else {
490
                throw new Exception("{$key} is invalid <pre>" . print_r($this->field[$key], true) . "</pre>");
0 ignored issues
show
Bug introduced by
Are you sure print_r($this->field[$key], true) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

490
                throw new Exception("{$key} is invalid <pre>" . /** @scrutinizer ignore-type */ print_r($this->field[$key], true) . "</pre>");
Loading history...
491 1
            }
492 1
        }
493 1
        if (! empty($tmp) && $this->isChanged($key)) {
494
            if ($id == '') {
495
                $this->set[] = $tmp;
496
            } else {
497 1
                $this->set[$id][] = $tmp;
498 1
            }
499 1
        }
500 1
501
        return $this;
502
    }
503 1
504
    /**
505 1
     * Сохраняет начальные значения полей
506
     *
507
     * @param array $data
508
     * @return $this
509
     */
510
    public function store($data = array())
511
    {
512
        if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
513
            $this->store = $data;
514 1
        }
515
516 1
        return $this;
517 1
    }
518 1
519
    /**
520 1
     * Откатывает изменения отдельного поля или всех полей сразу
521
     *
522
     * @param string $key
523
     * @return MODxAPI
524
     */
525
    public function rollback($key = '')
526
    {
527
        if (! empty($key) && isset($this->store[$key])) {
528
            $this->set($key, $this->store[$key]);
529
        } else {
530
            $this->fromArray($this->store);
531
        }
532
533
        return $this;
534
    }
535
536
    /**
537
     * Проверяет изменилось ли поле
538
     *
539
     * @param $key
540
     * @return bool
541
     */
542
    public function isChanged($key)
543
    {
544
        $flag = ! isset($this->store[$key]) || (isset($this->store[$key], $this->field[$key]) && $this->store[$key] != (string)$this->field[$key]);
545
546 1
        return $flag;
547
    }
548 1
549
    /**
550 1
     * @param $IDs
551
     * @param string $sep
552
     * @param integer[] $ignore
553
     * @return array
554
     * @throws Exception
555
     */
556
    final public function cleanIDs($IDs, $sep = ',', $ignore = array())
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
557
    {
558
        $out = APIhelpers::cleanIDs($IDs, $sep, $ignore);
559
560
        return $out;
561
    }
562
563
    /**
564
     * @param $data
565
     * @param null $callback
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $callback is correct as it would always require null to be passed?
Loading history...
566
     * @return $this
567
     * @throws Exception
568
     */
569
    final public function fromJson($data, $callback = null)
570
    {
571
        if (is_scalar($data) && ! empty($data)) {
572
            $json = json_decode($data);
573
        } else {
574
            throw new Exception("json is not string with json data");
575
        }
576
577
        if ($this->jsonError($json)) {
578
            if (isset($callback) && is_callable($callback)) {
579
                call_user_func_array($callback, array($json));
580
            } else {
581
                if (isset($callback)) {
582
                    throw new Exception("Can't call callback JSON unpack <pre>" . print_r($callback, 1) . "</pre>");
0 ignored issues
show
Bug introduced by
Are you sure print_r($callback, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

582
                    throw new Exception("Can't call callback JSON unpack <pre>" . /** @scrutinizer ignore-type */ print_r($callback, 1) . "</pre>");
Loading history...
583
                }
584
                foreach ($json as $key => $val) {
585
                    $this->set($key, $val);
586
                }
587
            }
588
        } else {
589
            throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
0 ignored issues
show
Bug introduced by
Are you sure print_r($data, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

589
            throw new Exception('Error from JSON decode: <pre>' . /** @scrutinizer ignore-type */ print_r($data, 1) . '</pre>');
Loading history...
590
        }
591
592
        return $this;
593
    }
594
595
    /**
596
     * @param null $callback
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $callback is correct as it would always require null to be passed?
Loading history...
597
     * @return string
598
     * @throws Exception
599
     */
600
    final public function toJson($callback = null)
601
    {
602
        $data = $this->toArray();
603
        if (isset($callback) && is_callable($callback)) {
604
            $data = call_user_func_array($callback, array($data));
605
        } else {
606
            if (isset($callback)) {
607
                throw new Exception("Can't call callback JSON pre pack <pre>" . print_r($callback, 1) . "</pre>");
0 ignored issues
show
Bug introduced by
Are you sure print_r($callback, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

607
                throw new Exception("Can't call callback JSON pre pack <pre>" . /** @scrutinizer ignore-type */ print_r($callback, 1) . "</pre>");
Loading history...
608
            }
609
        }
610
        $json = json_encode($data);
611
612
        if ($this->jsonError($data)) {
613
            throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
0 ignored issues
show
Bug introduced by
Are you sure print_r($data, 1) of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

613
            throw new Exception('Error from JSON decode: <pre>' . /** @scrutinizer ignore-type */ print_r($data, 1) . '</pre>');
Loading history...
614
        }
615
616
        return $json;
617
    }
618
619
    /**
620
     * @param $data
621
     * @return bool
622
     */
623
    final protected function jsonError($data)
624
    {
625
        $flag = false;
626
        if (json_last_error() === JSON_ERROR_NONE && is_object($data) && $data instanceof stdClass) {
627
            $flag = true;
628
        }
629
630
        return $flag;
631
    }
632
633
    /**
634
     * @param string $prefix
635
     * @param string $suffix
636
     * @param string $sep
637
     * @return array
638
     */
639
    public function toArray($prefix = '', $suffix = '', $sep = '_')
640
    {
641
        $tpl = '';
642
        $plh = '[+key+]';
643 1
        if ($prefix !== '') {
644
            $tpl = $prefix . $sep;
645 1
        }
646 1
        $tpl .= $plh;
647 1
        if ($suffix !== '') {
648
            $tpl .= $sep . $suffix;
649
        }
650 1
        $out = array();
651 1
        $fields = $this->field;
652
        $fields[$this->fieldPKName()] = $this->getID();
653
        if ($tpl !== $plh) {
654 1
            foreach ($fields as $key => $value) {
655 1
                $out[str_replace($plh, $key, $tpl)] = $value;
656 1
            }
657 1
        } else {
658
            $out = $fields;
659
        }
660
661
        return $out;
662 1
    }
663
664
    /**
665 1
     * @return string
666
     */
667
    final public function fieldPKName()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

This check looks for method names that are not written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection seeker becomes databaseConnectionSeeker.

Loading history...
668
    {
669
        return $this->pkName;
670
    }
671 1
672
    /**
673 1
     * @param $table
674
     * @return mixed|string
675
     */
676
    final public function makeTable($table)
677
    {
678
        //Без использования APIHelpers::getkey(). Иначе getFullTableName будет всегда выполняться
679
        return (isset($this->_table[$table])) ? $this->_table[$table] : $this->modx->getFullTableName($table);
680 2
    }
681
682
    /**
683 2
     * @param $data
684
     * @param string $sep
685
     * @return array|string
686
     */
687
    final public function sanitarIn($data, $sep = ',')
688
    {
689
        if (! is_array($data)) {
690
            $data = explode($sep, $data);
691
        }
692
        $out = array();
693
        foreach ($data as $item) {
694
            if ($item !== '') {
695
                $out[] = $this->escape($item);
696
            }
697
        }
698
        $out = empty($out) ? '' : "'" . implode("','", $out) . "'";
699
700
        return $out;
701
    }
702
703
    /**
704
     * @param string $table
705
     * @param string $field
706
     * @param string $PK
707
     * @return bool
708
     */
709
    public function checkUnique($table, $field, $PK = 'id')
710
    {
711
        if (is_array($field)) {
0 ignored issues
show
introduced by
The condition is_array($field) is always false.
Loading history...
712
            $where = array();
713
            foreach ($field as $_field) {
714
                $val = $this->get($_field);
715
                if ($val != '') {
716
                    $where[] = "`" . $this->escape($_field) . "` = '" . $this->escape($val) . "'";
717
                }
718
            }
719
            $where = implode(' AND ', $where);
720
        } else {
721
            $where = '';
722
            $val = $this->get($field);
723
            if ($val != '') {
724
                $where = "`" . $this->escape($field) . "` = '" . $this->escape($val) . "'";
725
            }
726
        }
727
728
        if ($where != '') {
729
            $sql = $this->query("SELECT `" . $this->escape($PK) . "` FROM " . $this->makeTable($table) . " WHERE " . $where);
730
            $id = $this->modx->db->getValue($sql);
731
            $flag = (! $id || (! $this->newDoc && $id == $this->getID()));
732
        } else {
733
            $flag = false;
734
        }
735
736
        return $flag;
737
    }
738
739
    /**
740
     * @param array $data
741
     * @return $this
742
     */
743
    public function create($data = array())
744
    {
745
        $this->close();
746
        $this->fromArray($data);
747
748
        return $this;
749
    }
750
751
    /**
752
     * @param $id
753
     * @return $this
754
     */
755
    public function copy($id)
756
    {
757
        $this->edit($id)->id = 0;
758
        $this->newDoc = true;
759
        $this->store = array();
760
761
        return $this;
762
    }
763
764
    /**
765
     *
766
     */
767
    public function close()
768
    {
769
        $this->newDoc = true;
770
        $this->id = null;
771 1
        $this->field = array();
772
        $this->set = array();
773 1
        $this->store = array();
774 1
        $this->markAllDecode();
775 1
    }
776 1
777 1
    /**
778 1
     * @param $key
779 1
     * @return bool
780
     */
781
    public function issetField($key)
782
    {
783
        return (is_scalar($key) && array_key_exists($key, $this->default_field));
784
    }
785
786
    /**
787
     * @param $id
788
     * @return mixed
789
     */
790
    abstract public function edit($id);
791
792
    /**
793
     * @param bool $fire_events
794
     * @param bool $clearCache
795
     * @return mixed
796
     */
797
    abstract public function save($fire_events = false, $clearCache = false);
798
799
    /**
800
     * @param $ids
801
     * @param null $fire_events
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $fire_events is correct as it would always require null to be passed?
Loading history...
802
     * @return mixed
803
     */
804
    abstract public function delete($ids, $fire_events = null);
805
806
    /**
807
     * @param $data
808
     * @return array|mixed|string
809
     */
810
    final public function sanitarTag($data)
811
    {
812
        return parent::sanitarTag($this->modx->stripTags($data));
0 ignored issues
show
Bug introduced by
The method stripTags() does not exist on DocumentParser. Did you maybe mean stripAlias()? ( Ignorable by Annotation )

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

812
        return parent::sanitarTag($this->modx->/** @scrutinizer ignore-call */ stripTags($data));

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...
813
    }
814
815
    /**
816
     * @param string $version
817
     * @param bool $dmi3yy
818
     * @return bool
819
     */
820
    final protected function checkVersion($version, $dmi3yy = true)
821
    {
822
        $flag = false;
823
        $currentVer = $this->modx->getVersionData('version');
824 1
        if (is_array($currentVer)) {
0 ignored issues
show
introduced by
The condition is_array($currentVer) is always false.
Loading history...
825
            $currentVer = APIHelpers::getkey($currentVer, 'version', '');
826 1
        }
827 1
        $tmp = substr($currentVer, 0, strlen($version));
828 1
        if (version_compare($tmp, $version, '>=')) {
829
            $flag = true;
830
            if ($dmi3yy) {
831 1
                $flag = $flag || (boolean)preg_match('/^' . $tmp . '(.*)\-d/', $currentVer);
0 ignored issues
show
introduced by
The condition $flag is always true.
Loading history...
832 1
            }
833 1
        }
834 1
835 1
        return $flag;
836 1
    }
837 1
838
    /**
839 1
     * @param string $name
840
     * @return bool|string|int
841
     */
842
    protected function eraseField($name)
843
    {
844
        $flag = false;
845
        if (array_key_exists($name, $this->field)) {
846
            $flag = $this->field[$name];
847
            unset($this->field[$name]);
848
        }
849
850
        return $flag;
851
    }
852
853
    /**
854
     * Может ли содержать данное поле json массив
855
     * @param  string $field имя поля
856
     * @return boolean
857
     */
858
    public function isJsonField($field)
859
    {
860
        return (is_scalar($field) && in_array($field, $this->jsonFields));
861
    }
862 1
863
    /**
864 1
     * Пометить поле как распакованное
865
     * @param  string $field имя поля
866
     * @return $this
867
     */
868
    public function markAsDecode($field)
869
    {
870
        if (is_scalar($field)) {
0 ignored issues
show
introduced by
The condition is_scalar($field) is always true.
Loading history...
871
            $this->_decodedFields->set($field, false);
872
        }
873
874
        return $this;
875
    }
876
877
    /**
878
     * Пометить поле как запакованное
879
     * @param  string $field имя поля
880
     * @return $this
881
     */
882
    public function markAsEncode($field)
883
    {
884
        if (is_scalar($field)) {
0 ignored issues
show
introduced by
The condition is_scalar($field) is always true.
Loading history...
885
            $this->_decodedFields->set($field, true);
886
        }
887
888
        return $this;
889
    }
890
891
    /**
892
     * Пометить все поля как запакованные
893
     * @return $this
894
     */
895
    public function markAllEncode()
896
    {
897
        $this->_decodedFields->clear();
898
        foreach ($this->jsonFields as $field) {
899
            $this->markAsEncode($field);
900
        }
901
902
        return $this;
903
    }
904
905
    /**
906
     * Пометить все поля как распакованные
907
     * @return $this
908
     */
909
    public function markAllDecode()
910
    {
911
        $this->_decodedFields->clear();
912
        foreach ($this->jsonFields as $field) {
913 1
            $this->markAsDecode($field);
914
        }
915 1
916 1
        return $this;
917
    }
918 1
919
    /**
920 1
     * Получить список не запакованных полей
921
     * @return DLCollection
922
     */
923
    public function getNoEncodeFields()
924
    {
925
        return $this->_decodedFields->filter(function ($value) {
926
            return ($value === false);
927 1
        });
928
    }
929
930
    /**
931 1
     * Получить список не распакованных полей
932
     * @return DLCollection
933
     */
934
    public function getNoDecodeFields()
935
    {
936
        return $this->_decodedFields->filter(function ($value) {
937
            return ($value === true);
938
        });
939
    }
940 1
941
    /**
942 1
     * Можно ли данное декодировать с помощью json_decode
943
     * @param  string $field имя поля
944
     * @return boolean
945
     */
946
    public function isDecodableField($field)
947
    {
948
        $data = $this->get($field);
949
950
        /**
951
         * Если поле скалярного типа и оно не распаковывалось раньше
952
         */
953
954
        return (is_scalar($data) && is_scalar($field) && $this->_decodedFields->get($field) === true);
955
    }
956
957
    /**
958
     * Можно ли закодировать данные с помощью json_encode
959
     * @param  string $field имя поля
960
     * @return boolean
961
     */
962
    public function isEncodableField($field)
963
    {
964
        /**
965
         * Если поле было распаковано ранее и еще не упаковано
966
         */
967
        return (is_scalar($field) && $this->_decodedFields->get($field) === false);
968
    }
969
970
    /**
971
     * Декодирует конкретное поле
972
     * @param  string $field Имя поля
973
     * @param  bool $store обновить распакованное поле
974
     * @return array ассоциативный массив с данными из json строки
975
     */
976
    public function decodeField($field, $store = false)
977
    {
978
        $out = array();
979
        if ($this->isDecodableField($field)) {
980
            $data = $this->get($field);
981
            $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
982
        }
983
        if ($store) {
984
            $this->field[$field] = $out;
985
            $this->markAsDecode($field);
986
        }
987
988
        return $out;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $out also could return the type xNop which is incompatible with the documented return type array.
Loading history...
989
    }
990
991
    /**
992
     * Декодирование всех json полей
993
     * @return $this
994
     */
995
    protected function decodeFields()
996
    {
997
        foreach ($this->getNoDecodeFields() as $field => $flag) {
998
            $this->decodeField($field, true);
999 1
        }
1000
1001 1
        return $this;
1002
    }
1003 1
1004
    /**
1005 1
     * Запаковывает конкретное поле в JSON
1006
     * @param  string $field Имя поля
1007
     * @param  bool $store обновить запакованное поле
1008
     * @return string|null json строка
1009
     */
1010
    public function encodeField($field, $store = false)
1011
    {
1012
        $out = null;
1013
        if ($this->isEncodableField($field)) {
1014
            $data = $this->get($field);
1015
            $out = json_encode($data);
1016
        }
1017
        if ($store) {
1018
            $this->field[$field] = $out;
1019
            $this->markAsEncode($field);
1020
        }
1021
1022
        return $out;
1023
    }
1024
1025
    /**
1026
     * Запаковка всех json полей
1027
     * @return $this
1028
     */
1029
    protected function encodeFields()
1030
    {
1031
        foreach ($this->getNoEncodeFields() as $field => $flag) {
1032
            $this->encodeField($field, true);
1033 1
        }
1034
1035 1
        return $this;
1036
    }
1037 1
1038
    /**
1039 1
     * @param mixed $data
1040
     * @param string $key
1041
     * @return bool
1042
     */
1043
    protected function saveToCache($data, $key)
1044
    {
1045
        $out = false;
1046
        if ($this->cache) {
1047 2
            $out = $this->modx->cache->save($key, $data, 0);
0 ignored issues
show
Bug introduced by
The property cache does not seem to exist on DocumentParser.
Loading history...
1048
        }
1049 2
1050 2
        return $out;
1051
    }
1052
1053
    /**
1054 2
     * @param string $key
1055
     * @return mixed
1056
     */
1057
    protected function loadFromCache($key)
1058
    {
1059
        $out = false;
1060
        if ($this->cache) {
1061 2
            $out = $this->modx->cache->fetch($key);
0 ignored issues
show
Bug introduced by
The property cache does not seem to exist on DocumentParser.
Loading history...
1062
        }
1063 2
1064 2
        return $out;
1065
    }
1066
1067
}
1068