Test Failed
Push — master ( de7c2b...75b2a8 )
by Maxim
02:54
created

MODxAPI::saveToCache()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
1
<?php
2
include_once(MODX_BASE_PATH . 'assets/lib/APIHelpers.class.php');
3
include_once(MODX_BASE_PATH . 'assets/snippets/DocLister/lib/jsonHelper.class.php');
4
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
     * @param $email
15
     * @param bool $dns
16
     * @return false|string
17
     */
18
    public function emailValidate($email, $dns = true)
19
    {
20
        return \APIhelpers::emailValidate($email, $dns);
21
    }
22
23
    /**
24
     * @param $len
25
     * @param string $data
26
     * @return string
27
     */
28
    public function genPass($len, $data = '')
29
    {
30
        return \APIhelpers::genPass($len, $data);
31
    }
32
33
    /**
34
     * @param string $out
35
     * @return string
36
     */
37
    public function getUserIP($out = '127.0.0.1')
38
    {
39
        return \APIhelpers::getUserIP($out);
40
    }
41
42
    /**
43
     * @param $data
44
     * @return array|mixed|string
45
     */
46
    public function sanitarTag($data)
47
    {
48
        return \APIhelpers::sanitarTag($data);
49
    }
50
51
    /**
52
     * @param $value
53
     * @param int $minLen
54
     * @param array $alph
55
     * @param array $mixArray
56
     * @return bool
57
     */
58
    public function checkString($value, $minLen = 1, $alph = array(), $mixArray = array())
59
    {
60
        return \APIhelpers::checkString($value, $minLen, $alph, $mixArray);
61
    }
62
}
63
64
/**
65
 * Class MODxAPI
66
 */
67
abstract class MODxAPI extends MODxAPIhelpers
68
{
69
    /**
70
     * Объект DocumentParser - основной класс MODX
71
     * @var \DocumentParser
72
     * @access protected
73
     */
74
    protected $modx = null;
75
76
    /**
77
     * @var array
78
     */
79
    protected $log = array();
80
81
    /**
82
     * @var array
83
     */
84
    protected $field = array();
85
86
    /**
87
     * @var array
88
     */
89
    protected $default_field = array();
90
91
    /**
92
     * @var null|integer|string
93
     */
94
    protected $id = null;
95
96
    /**
97
     * @var array
98
     */
99
    protected $set = array();
100
101
    /**
102
     * @var bool
103
     */
104
    protected $newDoc = false;
105
106
    /**
107
     * @var string
108
     */
109
    protected $pkName = 'id';
110
111
    /**
112
     * @var string
113
     */
114
    protected $ignoreError = '';
115
116
    /**
117
     * @var bool
118
     */
119
    protected $_debug = false;
120
121
    /**
122
     * @var array
123
     */
124
    protected $_query = array();
125
126
    /**
127
     * @var array
128
     */
129
    protected $jsonFields = array();
130
131
    /**
132
     * @var array
133
     */
134
    protected $store = array();
135
136
    /**
137
     * @var DLCollection
138
     */
139
    protected $_decodedFields;
140
141
    /**
142
     * @var array
143
     */
144
    private $_table = array();
145
146
    private $cache = false;
147
148
    /**
149
     * MODxAPI constructor.
150
     * @param DocumentParser $modx
151
     * @param bool $debug
152
     * @throws Exception
153
     */
154
    public function __construct(DocumentParser $modx, $debug = false)
155
    {
156
        $this->modx = $modx;
157
        if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) {
158
            throw new Exception('Magic Quotes is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.');
159
        }
160
161
        $this->setDebug($debug);
162
        $this->_decodedFields = new DLCollection($this->modx);
163
        $this->cache = isset($this->modx->cache) && $this->modx->cache instanceof Cache;
164
    }
165
166
    /**
167
     * @param boolean $flag
168
     * @return $this
169
     */
170
    public function setDebug($flag)
171
    {
172
        $this->_debug = (bool)$flag;
173
174
        return $this;
175
    }
176
177
    /**
178
     * @return bool
179
     */
180
    public function getDebug()
181
    {
182
        return $this->_debug;
183
    }
184
185
    /**
186
     * @return array
187
     */
188
    public function getDefaultFields()
189
    {
190
        return $this->default_field;
191
    }
192
193
    /**
194
     * @param $value
195
     * @return int|mixed|string
196
     */
197
    protected function getTime($value)
198
    {
199
        $value = trim($value);
200
        if (!empty($value)) {
201
            if (!is_numeric($value)) {
202
                $value = (int)strtotime($value);
203
            }
204
            if (!empty($value)) {
205
                $value += $this->modxConfig('server_offset_time');
206
            }
207
        }
208
209
        return $value;
210
    }
211
212
    /**
213
     * @param string $name
214
     * @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...
215
     * @return mixed
216
     */
217
    final public function modxConfig($name, $default = null)
218
    {
219
        return APIHelpers::getkey($this->modx->config, $name, $default);
220
    }
221
222
    /**
223
     * @param $q
224
     * @return $this
225
     */
226
    public function addQuery($q)
227
    {
228
        if (is_scalar($q) && !empty($q)) {
229
            $this->_query[] = $q;
230
        }
231
232
        return $this;
233
    }
234
235
    /**
236
     * @return array
237
     */
238
    public function getQueryList()
239
    {
240
        return $this->_query;
241
    }
242
243
    /**
244
     * @param $SQL
245
     * @return mixed
246
     */
247
    final public function query($SQL)
248
    {
249
        if ($this->getDebug()) {
250
            $this->addQuery($SQL);
251
        }
252
253
        return empty($SQL) ? null : $this->modx->db->query($SQL);
254
    }
255
256
    /**
257
     * @param $value
258
     * @return string|void
259
     */
260
    final public function escape($value)
261
    {
262
        if (!is_scalar($value)) {
263
            $value = '';
264
        } else {
265
            $value = $this->modx->db->escape($value);
266
        }
267
268
        return $value;
269
    }
270
271
    /**
272
     * @param string $name
273
     * @param array $data
274
     * @param bool $flag
275
     * @return $this
276
     */
277
    final public function invokeEvent($name, $data = array(), $flag = false)
278
    {
279
        if ((bool)$flag === true) {
280
            $this->modx->invokeEvent($name, $data);
281
        }
282
283
        return $this;
284
    }
285
286
    /**
287
     * @param string $name
288
     * @param array $data
289
     * @param boolean $flag
290
     * @return array|bool
291
     */
292
    final public function getInvokeEventResult($name, $data = array(), $flag = null)
293
    {
294
        $flag = (isset($flag) && $flag != '') ? (bool)$flag : false;
295
296
        return $flag ? $this->modx->invokeEvent($name, $data) : false;
297
    }
298
299
    /**
300
     * @return $this
301
     */
302
    final public function clearLog()
303
    {
304
        $this->log = array();
305
306
        return $this;
307
    }
308
309
    /**
310
     * @return array
311
     */
312
    final public function getLog()
313
    {
314
        return $this->log;
315
    }
316
317
    /**
318
     * @param bool $flush
319
     * @return $this
320
     */
321
    final public function list_log($flush = false)
322
    {
323
        echo '<pre>' . print_r(APIHelpers::sanitarTag($this->log), true) . '</pre>';
324
        if ($flush) {
325
            $this->clearLog();
326
        }
327
328
        return $this;
329
    }
330
331
    /**
332
     * @param bool $full
333
     * @return string
334
     */
335
    final public function getCachePath($full = true)
336
    {
337
        $path = $this->modx->getCachePath();
338
        if ($full) {
339
            $path = MODX_BASE_PATH . substr($path, strlen(MODX_BASE_URL));
340
        }
341
342
        return $path;
343
    }
344
345
    /**
346
     * @param boolean $fire_events
347
     * @param bool $custom
348
     */
349
    final public function clearCache($fire_events = false, $custom = false)
350
    {
351
        $IDs = array();
352
        if ($custom === false) {
353
            $this->modx->clearCache();
354
            include_once(MODX_MANAGER_PATH . 'processors/cache_sync.class.processor.php');
355
            $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...
356
            $path = $this->getCachePath(true);
357
            $sync->setCachepath($path);
358
            $sync->setReport(false);
359
            $sync->emptyCache();
360
        } else {
361
            if (is_scalar($custom)) {
0 ignored issues
show
introduced by
The condition is_scalar($custom) can never be false.
Loading history...
362
                $custom = array($custom);
363
            }
364
            switch ($this->modx->config['cache_type']) {
365
                case 2:
366
                    $cacheFile = "_*.pageCache.php";
367
                    break;
368
                default:
369
                    $cacheFile = ".pageCache.php";
370
            }
371
            if (is_array($custom)) {
0 ignored issues
show
introduced by
The condition is_array($custom) can never be false.
Loading history...
372
                foreach ($custom as $id) {
373
                    $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

373
                    $tmp = glob(MODX_BASE_PATH . "assets/cache/docid_" . /** @scrutinizer ignore-type */ $id . $cacheFile);
Loading history...
374
                    foreach ($tmp as $file) {
375
                        if (is_readable($file)) {
376
                            unlink($file);
377
                        }
378
                        $IDs[] = $id;
379
                    }
380
                }
381
            }
382
            clearstatcache();
383
        }
384
        $this->invokeEvent('OnSiteRefresh', array('IDs' => $IDs), $fire_events);
385
    }
386
387
    /**
388
     * @param integer $id
389
     * @return MODxAPI
390
     */
391
    public function switchObject($id)
392
    {
393
        switch (true) {
394
            //Если загружен другой объект - не тот, с которым мы хотим временно поработать
395
            case ($this->getID() != $id && $id):
396
                $obj = clone $this;
397
                $obj->edit($id);
398
                break;
399
            //Если уже загружен объект, с которым мы хотим временно поработать
400
            case ($this->getID() == $id && $id):
401
                //Если $id не указан, но уже загружен какой-то объект
402
            case (!$id && null !== $this->getID()):
403
            default:
404
                $obj = $this;
405
                break;
406
        }
407
408
        return $obj;
409
    }
410
411
    /**
412
     * @param bool $flag
413
     * @return $this
414
     */
415
    public function useIgnore($flag = true)
416
    {
417
        $this->ignoreError = $flag ? 'IGNORE' : '';
418
419
        return $this;
420
    }
421
422
    /**
423
     * @return bool
424
     */
425
    public function hasIgnore()
426
    {
427
        return (bool)$this->ignoreError;
428
    }
429
430
    /**
431
     * @param $key
432
     * @param $value
433
     * @return $this
434
     */
435
    public function set($key, $value)
436
    {
437
        if ((is_scalar($value) || $this->isJsonField($key)) && is_scalar($key) && !empty($key)) {
438
            $this->field[$key] = $value;
439
        }
440
441
        return $this;
442
    }
443
444
    /**
445
     * @return null|int
446
     */
447
    final public function getID()
448
    {
449
        return $this->id;
450
    }
451
452
    /**
453
     * @param $key
454
     * @return mixed
455
     */
456
    public function get($key)
457
    {
458
        return APIHelpers::getkey($this->field, $key, null);
459
    }
460
461
    /**
462
     * @param $data
463
     * @return $this
464
     */
465
    public function fromArray($data)
466
    {
467
        if (is_array($data)) {
468
            foreach ($data as $key => $value) {
469
                $this->set($key, $value);
470
            }
471
        }
472
473
        return $this;
474
    }
475
476
    /**
477
     * Формирует массив значений для подстановки в SQL запрос на обновление
478
     *
479
     * @param $key
480
     * @param string $id
481
     * @return $this
482
     * @throws Exception
483
     */
484
    final protected function Uset($key, $id = '')
485
    {
486
        if (!isset($this->field[$key])) {
487
            $tmp = "`{$key}`=''";
488
            $this->log[] = "{$key} is empty";
489
        } else {
490
            if ($this->issetField($key) && is_scalar($this->field[$key])) {
491
                $tmp = "`{$key}`='{$this->escape($this->field[$key])}'";
492
            } else {
493
                throw new Exception("{$key} is invalid <pre>" . print_r($this->field[$key], true) . "</pre>");
494
            }
495
        }
496
        if (!empty($tmp) && $this->isChanged($key)) {
497
            if ($id == '') {
498
                $this->set[] = $tmp;
499
            } else {
500
                $this->set[$id][] = $tmp;
501
            }
502
        }
503
504
        return $this;
505
    }
506
507
    /**
508
     * Сохраняет начальные значения полей
509
     *
510
     * @param array $data
511
     * @return $this
512
     */
513
    public function store($data = array())
514
    {
515
        if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) can never be false.
Loading history...
516
            $this->store = $data;
517
        }
518
519
        return $this;
520
    }
521
522
    /**
523
     * Откатывает изменения отдельного поля или всех полей сразу
524
     *
525
     * @param string $key
526
     * @return MODxAPI
527
     */
528
    public function rollback($key = '')
529
    {
530
        if (!empty($key) && isset($this->store[$key])) {
531
            $this->set($key, $this->store[$key]);
532
        } else {
533
            $this->fromArray($this->store);
534
        }
535
536
        return $this;
537
    }
538
539
    /**
540
     * Проверяет изменилось ли поле
541
     *
542
     * @param $key
543
     * @return bool
544
     */
545
    public function isChanged($key)
546
    {
547
        $flag = !isset($this->store[$key]) || (isset($this->store[$key]) && $this->store[$key] != $this->field[$key]);
548
549
        return $flag;
550
    }
551
552
    /**
553
     * @param $IDs
554
     * @param string $sep
555
     * @param integer[] $ignore
556
     * @return array
557
     * @throws Exception
558
     */
559
    final public function cleanIDs($IDs, $sep = ',', $ignore = array())
560
    {
561
        $out = array();
562
        if (!is_array($IDs)) {
563
            if (is_scalar($IDs)) {
564
                $IDs = explode($sep, $IDs);
565
            } else {
566
                $IDs = array();
567
                throw new Exception('Invalid IDs list <pre>' . print_r($IDs, 1) . '</pre>');
568
            }
569
        }
570
        foreach ($IDs as $item) {
571
            $item = trim($item);
572
            if (is_scalar($item) && (int)$item >= 0) { //Fix 0xfffffffff
573
                if (!empty($ignore) && in_array((int)$item, $ignore, true)) {
574
                    $this->log[] = 'Ignore id ' . (int)$item;
575
                } else {
576
                    $out[] = (int)$item;
577
                }
578
            }
579
        }
580
        $out = array_unique($out);
581
582
        return $out;
583
    }
584
585
    /**
586
     * @param $data
587
     * @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...
588
     * @return $this
589
     * @throws Exception
590
     */
591
    final public function fromJson($data, $callback = null)
592
    {
593
        if (is_scalar($data) && !empty($data)) {
594
            $json = json_decode($data);
595
        } else {
596
            throw new Exception("json is not string with json data");
597
        }
598
599
        if ($this->jsonError($json)) {
600
            if (isset($callback) && is_callable($callback)) {
601
                call_user_func_array($callback, array($json));
602
            } else {
603
                if (isset($callback)) {
604
                    throw new Exception("Can't call callback JSON unpack <pre>" . print_r($callback, 1) . "</pre>");
605
                }
606
                foreach ($json as $key => $val) {
607
                    $this->set($key, $val);
608
                }
609
            }
610
        } else {
611
            throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
612
        }
613
614
        return $this;
615
    }
616
617
    /**
618
     * @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...
619
     * @return string
620
     * @throws Exception
621
     */
622
    final public function toJson($callback = null)
623
    {
624
        $data = $this->toArray();
625
        if (isset($callback) && is_callable($callback)) {
626
            $data = call_user_func_array($callback, array($data));
627
        } else {
628
            if (isset($callback)) {
629
                throw new Exception("Can't call callback JSON pre pack <pre>" . print_r($callback, 1) . "</pre>");
630
            }
631
        }
632
        $json = json_encode($data);
633
634
        if ($this->jsonError($data)) {
635
            throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
636
        }
637
638
        return $json;
639
    }
640
641
    /**
642
     * @param $data
643
     * @return bool
644
     */
645
    final protected function jsonError($data)
646
    {
647
        $flag = false;
648
        if (json_last_error() === JSON_ERROR_NONE && is_object($data) && $data instanceof stdClass) {
649
            $flag = true;
650
        }
651
652
        return $flag;
653
    }
654
655
    /**
656
     * @param string $prefix
657
     * @param string $suffix
658
     * @param string $sep
659
     * @return array
660
     */
661
    public function toArray($prefix = '', $suffix = '', $sep = '_')
662
    {
663
        $tpl = '';
664
        $plh = '[+key+]';
665
        if ($prefix !== '') {
666
            $tpl = $prefix . $sep;
667
        }
668
        $tpl .= $plh;
669
        if ($suffix !== '') {
670
            $tpl .= $sep . $suffix;
671
        }
672
        $out = array();
673
        $fields = $this->field;
674
        $fields[$this->fieldPKName()] = $this->getID();
675
        if ($tpl != $plh) {
676
            foreach ($fields as $key => $value) {
677
                $out[str_replace($plh, $key, $tpl)] = $value;
678
            }
679
        } else {
680
            $out = $fields;
681
        }
682
683
        return $out;
684
    }
685
686
    /**
687
     * @return string
688
     */
689
    final public function fieldPKName()
690
    {
691
        return $this->pkName;
692
    }
693
694
    /**
695
     * @param $table
696
     * @return mixed|string
697
     */
698
    final public function makeTable($table)
699
    {
700
        //Без использования APIHelpers::getkey(). Иначе getFullTableName будет всегда выполняться
701
        return (isset($this->_table[$table])) ? $this->_table[$table] : $this->modx->getFullTableName($table);
702
    }
703
704
    /**
705
     * @param $data
706
     * @param string $sep
707
     * @return array|string
708
     */
709
    final public function sanitarIn($data, $sep = ',')
710
    {
711
        if (!is_array($data)) {
712
            $data = explode($sep, $data);
713
        }
714
        $out = array();
715
        foreach ($data as $item) {
716
            if ($item !== '') {
717
                $out[] = $this->escape($item);
718
            }
719
        }
720
        $out = empty($out) ? '' : "'" . implode("','", $out) . "'";
721
722
        return $out;
723
    }
724
725
    /**
726
     * @param string $table
727
     * @param string $field
728
     * @param string $PK
729
     * @return bool
730
     */
731
    public function checkUnique($table, $field, $PK = 'id')
732
    {
733
        if (is_array($field)) {
0 ignored issues
show
introduced by
The condition is_array($field) can never be true.
Loading history...
734
            $where = array();
735
            foreach ($field as $_field) {
736
                $val = $this->get($_field);
737
                if ($val != '') {
738
                    $where[] = "`" . $this->escape($_field) . "` = '" . $this->escape($val) . "'";
739
                }
740
            }
741
            $where = implode(' AND ', $where);
742
        } else {
743
            $where = '';
744
            $val = $this->get($field);
745
            if ($val != '') {
746
                $where = "`" . $this->escape($field) . "` = '" . $this->escape($val) . "'";
747
            }
748
        }
749
750
        if ($where != '') {
751
            $sql = $this->query("SELECT `" . $this->escape($PK) . "` FROM " . $this->makeTable($table) . " WHERE " . $where);
752
            $id = $this->modx->db->getValue($sql);
753
            if (!$id || (!$this->newDoc && $id == $this->getID())) {
754
                $flag = true;
755
            } else {
756
                $flag = false;
757
            }
758
        } else {
759
            $flag = false;
760
        }
761
762
        return $flag;
763
    }
764
765
    /**
766
     * @param array $data
767
     * @return $this
768
     */
769
    public function create($data = array())
770
    {
771
        $this->close();
772
        $this->fromArray($data);
773
774
        return $this;
775
    }
776
777
    /**
778
     * @param $id
779
     * @return $this
780
     */
781
    public function copy($id)
782
    {
783
        $this->edit($id)->id = 0;
784
        $this->newDoc = true;
785
        $this->store = array();
786
787
        return $this;
788
    }
789
790
    /**
791
     *
792
     */
793
    public function close()
794
    {
795
        $this->newDoc = true;
796
        $this->id = null;
797
        $this->field = array();
798
        $this->set = array();
799
        $this->store = array();
800
        $this->markAllDecode();
801
    }
802
803
    /**
804
     * @param $key
805
     * @return bool
806
     */
807
    public function issetField($key)
808
    {
809
        return (is_scalar($key) && array_key_exists($key, $this->default_field));
810
    }
811
812
    /**
813
     * @param $id
814
     * @return mixed
815
     */
816
    abstract public function edit($id);
817
818
    /**
819
     * @param bool $fire_events
820
     * @param bool $clearCache
821
     * @return mixed
822
     */
823
    abstract public function save($fire_events = false, $clearCache = false);
824
825
    /**
826
     * @param $ids
827
     * @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...
828
     * @return mixed
829
     */
830
    abstract public function delete($ids, $fire_events = null);
831
832
    /**
833
     * @param $data
834
     * @return array|mixed|string
835
     */
836
    final public function sanitarTag($data)
837
    {
838
        return parent::sanitarTag($this->modx->stripTags($data));
839
    }
840
841
    /**
842
     * @param string $version
843
     * @param bool $dmi3yy
844
     * @return bool
845
     */
846
    final protected function checkVersion($version, $dmi3yy = true)
847
    {
848
        $flag = false;
849
        $currentVer = $this->modx->getVersionData('version');
850
        if (is_array($currentVer)) {
851
            $currentVer = APIHelpers::getkey($currentVer, 'version', '');
852
        }
853
        $tmp = substr($currentVer, 0, strlen($version));
854
        if (version_compare($tmp, $version, '>=')) {
855
            $flag = true;
856
            if ($dmi3yy) {
857
                $flag = (boolean)preg_match('/^' . $tmp . '(.*)\-d/', $currentVer);
858
            }
859
        }
860
861
        return $flag;
862
    }
863
864
    /**
865
     * @param string $name
866
     * @return bool|mixed
867
     */
868
    protected function eraseField($name)
869
    {
870
        $flag = false;
871
        if (array_key_exists($name, $this->field)) {
872
            $flag = $this->field[$name];
873
            unset($this->field[$name]);
874
        }
875
876
        return $flag;
877
    }
878
879
    /**
880
     * Может ли содержать данное поле json массив
881
     * @param  string $field имя поля
882
     * @return boolean
883
     */
884
    public function isJsonField($field)
885
    {
886
        return (is_scalar($field) && in_array($field, $this->jsonFields));
887
    }
888
889
    /**
890
     * Пометить поле как распакованное
891
     * @param  string $field имя поля
892
     * @return $this
893
     */
894
    public function markAsDecode($field)
895
    {
896
        if (is_scalar($field)) {
0 ignored issues
show
introduced by
The condition is_scalar($field) can never be false.
Loading history...
897
            $this->_decodedFields->set($field, false);
898
        }
899
900
        return $this;
901
    }
902
903
    /**
904
     * Пометить поле как запакованное
905
     * @param  string $field имя поля
906
     * @return $this
907
     */
908
    public function markAsEncode($field)
909
    {
910
        if (is_scalar($field)) {
0 ignored issues
show
introduced by
The condition is_scalar($field) can never be false.
Loading history...
911
            $this->_decodedFields->set($field, true);
912
        }
913
914
        return $this;
915
    }
916
917
    /**
918
     * Пометить все поля как запакованные
919
     * @return $this
920
     */
921
    public function markAllEncode()
922
    {
923
        $this->_decodedFields->clear();
924
        foreach ($this->jsonFields as $field) {
925
            $this->markAsEncode($field);
926
        }
927
928
        return $this;
929
    }
930
931
    /**
932
     * Пометить все поля как распакованные
933
     * @return $this
934
     */
935
    public function markAllDecode()
936
    {
937
        $this->_decodedFields->clear();
938
        foreach ($this->jsonFields as $field) {
939
            $this->markAsDecode($field);
940
        }
941
942
        return $this;
943
    }
944
945
    /**
946
     * Получить список не запакованных полей
947
     * @return DLCollection
948
     */
949
    public function getNoEncodeFields()
950
    {
951
        return $this->_decodedFields->filter(function ($value) {
952
            return ($value === false);
953
        });
954
    }
955
956
    /**
957
     * Получить список не распакованных полей
958
     * @return DLCollection
959
     */
960
    public function getNoDecodeFields()
961
    {
962
        return $this->_decodedFields->filter(function ($value) {
963
            return ($value === true);
964
        });
965
    }
966
967
    /**
968
     * Можно ли данное декодировать с помощью json_decode
969
     * @param  string $field имя поля
970
     * @return boolean
971
     */
972
    public function isDecodableField($field)
973
    {
974
        $data = $this->get($field);
975
976
        /**
977
         * Если поле скалярного типа и оно не распаковывалось раньше
978
         */
979
980
        return (is_scalar($data) && is_scalar($field) && $this->_decodedFields->get($field) === true);
981
    }
982
983
    /**
984
     * Можно ли закодировать данные с помощью json_encode
985
     * @param  string $field имя поля
986
     * @return boolean
987
     */
988
    public function isEncodableField($field)
989
    {
990
        /**
991
         * Если поле было распаковано ранее и еще не упаковано
992
         */
993
        return (is_scalar($field) && $this->_decodedFields->get($field) === false);
994
    }
995
996
    /**
997
     * Декодирует конкретное поле
998
     * @param  string $field Имя поля
999
     * @param  bool $store обновить распакованное поле
1000
     * @return array ассоциативный массив с данными из json строки
1001
     */
1002
    public function decodeField($field, $store = false)
1003
    {
1004
        $out = array();
1005
        if ($this->isDecodableField($field)) {
1006
            $data = $this->get($field);
1007
            $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
1008
        }
1009
        if ($store) {
1010
            $this->field[$field] = $out;
1011
            $this->markAsDecode($field);
1012
        }
1013
1014
        return $out;
1015
    }
1016
1017
    /**
1018
     * Декодирование всех json полей
1019
     * @return $this
1020
     */
1021
    protected function decodeFields()
1022
    {
1023
        foreach ($this->getNoDecodeFields() as $field => $flag) {
1024
            $this->decodeField($field, true);
1025
        }
1026
1027
        return $this;
1028
    }
1029
1030
    /**
1031
     * Запаковывает конкретное поле в JSON
1032
     * @param  string $field Имя поля
1033
     * @param  bool $store обновить запакованное поле
1034
     * @return string|null json строка
1035
     */
1036
    public function encodeField($field, $store = false)
1037
    {
1038
        $out = null;
1039
        if ($this->isEncodableField($field)) {
1040
            $data = $this->get($field);
1041
            $out = json_encode($data);
1042
        }
1043
        if ($store) {
1044
            $this->field[$field] = $out;
1045
            $this->markAsEncode($field);
1046
        }
1047
1048
        return $out;
1049
    }
1050
1051
    /**
1052
     * Запаковка всех json полей
1053
     * @return $this
1054
     */
1055
    protected function encodeFields()
1056
    {
1057
        foreach ($this->getNoEncodeFields() as $field => $flag) {
1058
            $this->encodeField($field, true);
1059
        }
1060
1061
        return $this;
1062
    }
1063
1064
    /**
1065
     * @param mixed $data
1066
     * @param string $key
1067
     * @return bool
1068
     */
1069
    protected function saveToCache($data, $key)
1070
    {
1071
        $out = false;
1072
        if ($this->cache) {
1073
            $out = $this->modx->cache->save($key, $data, 0);
1074
        }
1075
1076
        return $out;
1077
    }
1078
1079
    /**
1080
     * @param string $key
1081
     * @return mixed
1082
     */
1083
    protected function loadFromCache($key)
1084
    {
1085
        $out = false;
1086
        if ($this->cache) {
1087
            $out = $this->modx->cache->fetch($key);
1088
        }
1089
1090
        return $out;
1091
    }
1092
}
1093