Completed
Push — master ( 3e5347...9f2a0a )
by Agel_Nash
03:13
created

MODxAPI::getInvokeEventResult()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 8
nop 3
dl 0
loc 6
rs 9.2
c 0
b 0
f 0
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
7
class MODxAPIhelpers
8
{
9
    public function emailValidate($email, $dns = true)
10
    {
11
        return \APIhelpers::emailValidate($email, $dns);
12
    }
13
    public function genPass($len, $data = '')
14
    {
15
        return \APIhelpers::genPass($len, $data);
16
    }
17
    public function getUserIP($out = '127.0.0.1')
18
    {
19
        return \APIhelpers::getUserIP($out);
20
    }
21
22
    public function sanitarTag($data)
23
    {
24
        return \APIhelpers::sanitarTag($data);
25
    }
26
27
    public function checkString($value, $minLen = 1, $alph = array(), $mixArray = array())
28
    {
29
        return \APIhelpers::checkString($value, $minLen, $alph, $mixArray);
30
    }
31
}
32
33
abstract class MODxAPI extends MODxAPIhelpers
34
{
35
    protected $modx = null;
36
    protected $log = array();
37
    protected $field = array();
38
    protected $default_field = array();
39
    protected $id = null;
40
    protected $set = array();
41
    protected $newDoc = false;
42
    protected $pkName = 'id';
43
	protected $ignoreError = '';
44
    protected $_debug = false;
45
    protected $_query = array();
46
    protected $jsonFields = array();
47
	/**
48
	 * @var DLCollection
49
	 */
50
    private $_decodedFields;
51
	private $_table = array();
52
53
    public function __construct(DocumentParser $modx, $debug = false)
54
    {	
55
    	$this->modx = $modx;
56
        if(function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()){
57
        	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.');
58
		}
59
60
		$this->setDebug($debug);
61
        $this->_decodedFields = new DLCollection($this->modx);
62
    }
63
64
    public function setDebug($flag){
65
        $this->_debug = (bool)$flag;
66
        return $this;
67
    }
68
    public function getDebug(){
69
        return $this->_debug;
70
    }
71
    public function getDefaultFields(){
72
        return $this->default_field;
73
    }
74
    final public function modxConfig($name, $default = null)
75
    {
76
        return APIHelpers::getkey($this->modx->config, $name, $default);
77
    }
78
    public function addQuery($q){
79
        if(is_scalar($q) && !empty($q)){
80
            $this->_query[] = $q;
81
        }
82
        return $this;
83
    }
84
    public function getQueryList(){
85
        return $this->_query;
86
    }
87
    final public function query($SQL)
88
    {
89
        if($this->getDebug()){
90
            $this->addQuery($SQL);
91
        }
92
        return empty($SQL) ? null : $this->modx->db->query($SQL);
93
    }
94
    final public function escape($value){
95
        if(!is_scalar($value)){
96
            $value = '';
97
        }else{
98
            $value = $this->modx->db->escape($value);
99
        }
100
        return $value;
101
     }
102
    final public function invokeEvent($name, $data = array(), $flag = false)
103
    {
104
        $flag = (isset($flag) && $flag != '') ? (bool)$flag : false;
105
        if ($flag) {
106
            $this->modx->invokeEvent($name, $data);
107
        }
108
        return $this;
109
    }
110
111
    final public function getInvokeEventResult($name, $data = array(), $flag = false) {
112
        $flag = (isset($flag) && $flag != '') ? (bool)$flag : false;
113
        if ($flag) {
114
            return $this->modx->invokeEvent($name, $data);
115
        }
116
    }
117
118
    final public function clearLog()
119
    {
120
        $this->log = array();
121
        return $this;
122
    }
123
124
    final public function getLog()
125
    {
126
        return $this->log;
127
    }
128
129
    final public function list_log($flush = false)
130
    {
131
        echo '<pre>' . print_r(APIHelpers::sanitarTag($this->log), true) . '</pre>';
132
        if ($flush) $this->clearLog();
133
        return $this;
134
    }
135
136
    final public function getCachePath($full = true)
137
    {
138
        $path = $this->modx->getCachePath();
139
        if ($full) {
140
            $path = MODX_BASE_PATH . substr($path, strlen(MODX_BASE_URL));
141
        }
142
        return $path;
143
    }
144
145
    final public function clearCache($fire_events = null, $custom = false)
146
    {
147
		$IDs = array();
148
		if($custom === false) {
149
			$this->modx->clearCache();
150
			include_once(MODX_MANAGER_PATH . 'processors/cache_sync.class.processor.php');
151
			$sync = new synccache();
152
			$path = $this->getCachePath(true);
153
			$sync->setCachepath($path);
154
			$sync->setReport(false);
155
			$sync->emptyCache();
156
		}else {
157
			if(is_scalar($custom)){
158
				$custom = array($custom);
159
			}
160
			switch ($this->modx->config['cache_type']) {
161
				case 2:
162
					$cacheFile = "_*.pageCache.php";
163
					break;
164
				default:
165
					$cacheFile = ".pageCache.php";
166
			}
167
			if(is_array($custom)) {
168
				foreach($custom as $id) {
169
					$tmp = glob(MODX_BASE_PATH."assets/cache/docid_" . $id . $cacheFile);
170
					foreach($tmp as $file){
171
						if(is_readable($file)){
172
							unlink($file);
173
						}
174
						$IDs[] = $id;
175
					}
176
				}
177
			}
178
			clearstatcache();
179
		}
180
        $this->invokeEvent('OnSiteRefresh', array('IDs' => $IDs), $fire_events);
181
    }
182
	public function switchObject($id){
183
        switch(true){
184
            //Если загружен другой объект - не тот, с которым мы хотим временно поработать
185
            case ($this->getID() != $id && $id):
186
                $obj = clone $this;
187
                $obj->edit($id);
188
                break;
189
            //Если уже загружен объект, с которым мы хотим временно поработать
190
            case ($this->getID() == $id && $id):
191
            //Если $id не указан, но уже загружен какой-то объект
192
            case (!$id && $this->getID()):
193
            default:
194
                $obj = $this;
195
                break;
196
        }
197
        return $obj;
198
    }
199
	public function useIgnore($flag = true){
200
		$this->ignoreError = $flag ? 'IGNORE' : '';
201
		return $this;
202
	}
203
	public function hasIgnore(){
204
		return (bool)$this->ignoreError;
205
	}
206
207
    public function set($key, $value)
208
    {
209
        if ((is_scalar($value) || $this->isJsonField($key)) && is_scalar($key) && !empty($key)) {
210
            $this->field[$key] = $value;
211
        }
212
        return $this;
213
    }
214
215
    final public function getID()
216
    {
217
        return $this->id;
218
    }
219
220
    public function get($key)
221
    {
222
        return APIHelpers::getkey($this->field, $key, null);
223
    }
224
225
    public function fromArray($data)
226
    {
227
        if (is_array($data)) {
228
            foreach ($data as $key => $value) {
229
                $this->set($key, $value);
230
            }
231
        }
232
        return $this;
233
    }
234
235
    final protected function Uset($key, $id = '')
236
    {
237
        if (!isset($this->field[$key])) {
238
            $tmp = "`{$key}`=''";
239
            $this->log[] = "{$key} is empty";
240
        } else {
241
            if ($this->issetField($key) && is_scalar($this->field[$key])) {
242
            	$tmp = "`{$key}`='{$this->escape($this->field[$key])}'";
243
			} else throw new Exception("{$key} is invalid <pre>" . print_r($this->field[$key], true) . "</pre>");
244
        }
245
        if (!empty($tmp)) {
246
            if ($id == '') {
247
                $this->set[] = $tmp;
248
            } else {
249
                $this->set[$id][] = $tmp;
250
            }
251
        }
252
        return $this;
253
    }
254
255
256
    final public function cleanIDs($IDs, $sep = ',', $ignore = array())
257
    {
258
        $out = array();
259
        if (!is_array($IDs)) {
260
            if (is_scalar($IDs)) {
261
            	$IDs = explode($sep, $IDs);
262
			} else {
263
            	$IDs = array();
264
                throw new Exception('Invalid IDs list <pre>' . print_r($IDs, 1) . '</pre>');
265
			}
266
        }
267
        foreach ($IDs as $item) {
268
            $item = trim($item);
269
            if (is_scalar($item) && (int)$item >= 0) { //Fix 0xfffffffff
270
                if (!empty($ignore) && in_array((int)$item, $ignore, true)) {
271
                    $this->log[] = 'Ignore id ' . (int)$item;
272
                } else {
273
                    $out[] = (int)$item;
274
                }
275
            }
276
        }
277
        $out = array_unique($out);
278
        return $out;
279
    }
280
281
    final public function fromJson($data, $callback = null)
282
    {
283
        if (is_scalar($data) && !empty($data)) {
284
        	$json = json_decode($data);
285
		} else throw new Exception("json is not string with json data");
286
287
		if ($this->jsonError($json)) {
288
        	if (isset($callback) && is_callable($callback)) {
289
            	call_user_func_array($callback, array($json));
290
			} else {
291
            	if (isset($callback)) throw new Exception("Can't call callback JSON unpack <pre>" . print_r($callback, 1) . "</pre>");
292
                foreach ($json as $key => $val) {
293
                	$this->set($key, $val);
294
				}
295
			}
296
		} else throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
297
298
		return $this;
299
    }
300
301
    final public function toJson($callback = null)
302
    {
303
        $data = $this->toArray();
304
        if (isset($callback) && is_callable($callback)) {
305
        	$data = call_user_func_array($callback, array($data));
306
		} else {
307
        	if (isset($callback)) throw new Exception("Can't call callback JSON pre pack <pre>" . print_r($callback, 1) . "</pre>");
308
		}
309
        $json = json_encode($data);
310
311
		if ($this->jsonError($data)) {
312
        	throw new Exception('Error from JSON decode: <pre>' . print_r($data, 1) . '</pre>');
313
		}
314
315
		return $json;
316
    }
317
318
    final protected function jsonError($data)
319
    {
320
        $flag = false;
321
        if (json_last_error() === JSON_ERROR_NONE && is_object($data) && $data instanceof stdClass) {
322
            $flag = true;
323
        }
324
        return $flag;
325
    }
326
327
    public function toArray($prefix = '', $suffix = '', $sep = '_')
328
    {
329
        $tpl = '';
330
        $plh = '[+key+]';
331
        if ($prefix !== '') {
332
            $tpl = $prefix . $sep;
333
        }
334
        $tpl .= $plh;
335
        if ($suffix !== '') {
336
            $tpl .= $sep . $suffix;
337
        }
338
        $out = array();
339
        $fields = $this->field;
340
        $fields[$this->fieldPKName()] = $this->getID();
341
        if ($tpl != $plh) {
342
            foreach ($fields as $key => $value) {
343
                $out[str_replace($plh, $key, $tpl)] = $value;
344
            }
345
        } else {
346
            $out = $fields;
347
        }
348
        return $out;
349
    }
350
    final public function fieldPKName(){
351
        return $this->pkName;
352
    }
353
    final public function makeTable($table)
354
    {
355
        //Без использования APIHelpers::getkey(). Иначе getFullTableName будет всегда выполняться
356
        return (isset($this->_table[$table])) ? $this->_table[$table] : $this->modx->getFullTableName($table);
357
    }
358
359
    final public function sanitarIn($data, $sep = ',')
360
    {
361
        if (!is_array($data)) {
362
            $data = explode($sep, $data);
363
        }
364
        $out = array();
365
        foreach ($data as $item) {
366
            if($item !== ''){
367
                $out[] = $this->escape($item);
368
            }
369
        }
370
        $out = empty($out) ? '' : "'" . implode("','", $out) . "'";
371
        return $out;
372
    }
373
374
    public function checkUnique($table, $field, $PK = 'id')
375
    {
376
        if (is_array($field)) {
377
            $where = array();
378
            foreach ($field as $_field) {
379
                $val = $this->get($_field);
380
                if ($val != '')
381
                    $where[] = "`".$this->escape($_field)."` = '".$this->escape($val)."'";
382
            }
383
            $where = implode(' AND ',$where);
384
        } else {
385
            $where = '';
386
            $val = $this->get($field);
387
            if ($val != '')
388
                $where = "`".$this->escape($field)."` = '".$this->escape($val)."'";
389
        }
390
        
391
        if ($where != '') {
392
            $sql = $this->query("SELECT `" . $this->escape($PK) . "` FROM " . $this->makeTable($table) . " WHERE ".$where);
393
            $id = $this->modx->db->getValue($sql);
394
            if (is_null($id) || (!$this->newDoc && $id == $this->getID())) {
395
                $flag = true;
396
            } else {
397
                $flag = false;
398
            }
399
        } else {
400
            $flag = false;
401
        }
402
        return $flag;
403
    }
404
405
    public function create($data = array())
406
    {
407
        $this->close();
408
        $this->fromArray($data);
409
        return $this;
410
    }
411
412
    public function copy($id)
413
    {
414
        $this->edit($id)->id = 0;
415
        $this->newDoc = true;
416
        return $this;
417
    }
418
419
    public function close()
420
    {
421
        $this->newDoc = true;
422
        $this->id = null;
423
        $this->field = array();
424
        $this->set = array();
425
        $this->markAllDecode();
426
    }
427
428
    public function issetField($key)
429
    {
430
        return (is_scalar($key) && array_key_exists($key, $this->default_field));
431
    }
432
433
    abstract public function edit($id);
434
435
    abstract public function save($fire_events = null, $clearCache = false);
436
437
    abstract public function delete($ids, $fire_events = null);
438
439
    final public function sanitarTag($data)
440
    {
441
        return parent::sanitarTag($this->modx->stripTags($data));
442
    }
443
444
    final protected function checkVersion($version, $dmi3yy = true)
445
    {
446
        $flag = false;
447
        $currentVer = $this->modx->getVersionData('version');
448
        if (is_array($currentVer)) {
449
            $currentVer = APIHelpers::getkey($currentVer, 'version', '');
450
        }
451
        $tmp = substr($currentVer, 0, strlen($version));
452
        if (version_compare($tmp, $version, '>=')) {
453
            $flag = true;
454
            if ($dmi3yy) {
455
                $flag = (boolean)preg_match('/^' . $tmp . '(.*)\-d/', $currentVer);
456
            }
457
        }
458
        return $flag;
459
    }
460
461
    protected function eraseField($name)
462
    {
463
        $flag = false;
464
        if (array_key_exists($name, $this->field)) {
465
            $flag = $this->field[$name];
466
            unset($this->field[$name]);
467
        }
468
        return $flag;
469
    }
470
471
    /**
472
     * Может ли содержать данное поле json массив
473
     * @param  string $field имя поля
474
     * @return boolean
475
     */
476
    public function isJsonField($field){
477
        return (is_scalar($field) && in_array($field, $this->jsonFields));
478
    }
479
480
    /**
481
     * Пометить поле как распакованное
482
     * @param  string $field имя поля
483
     * @return $this
484
     */
485
    public function markAsDecode($field){
486
        if(is_scalar($field)){
487
            $this->_decodedFields->set($field, false);
488
        }
489
        return $this;
490
    }
491
492
    /**
493
     * Пометить поле как запакованное
494
     * @param  string $field имя поля
495
     * @return $this
496
     */
497
    public function markAsEncode($field){
498
        if(is_scalar($field)){
499
            $this->_decodedFields->set($field, true);
500
        }
501
        return $this;
502
    }
503
504
    /**
505
     * Пометить все поля как запакованные
506
     * @return $this
507
     */
508
    public function markAllEncode(){
509
        $this->_decodedFields->clear();
510
        foreach($this->jsonFields as $field){
511
            $this->markAsEncode($field);
512
        }
513
        return $this;
514
    }
515
516
    /**
517
     * Пометить все поля как распакованные
518
     * @return $this
519
     */
520
    public function markAllDecode(){
521
        $this->_decodedFields->clear();
522
        foreach($this->jsonFields as $field){
523
            $this->markAsDecode($field);
524
        }
525
        return $this;
526
    }
527
528
    /**
529
     * Получить список не запакованных полей
530
     * @return array
531
     */
532
    public function getNoEncodeFields(){
533
        return $this->_decodedFields->filter(function($value){
534
            return ($value === false);
535
        });
536
    }
537
538
    /**
539
     * Получить список не распакованных полей
540
     * @return array
541
     */
542
    public function getNoDecodeFields(){
543
       return $this->_decodedFields->filter(function($value){
544
            return ($value === true);
545
        });
546
    }
547
548
    /**
549
     * Можно ли данное декодировать с помощью json_decode
550
     * @param  string $field имя поля
551
     * @return boolean
552
     */
553
    public function isDecodableField($field){
554
        $data = $this->get($field);
555
        /**
556
         * Если поле скалярного типа и оно не распаковывалось раньше
557
         */
558
        return (is_scalar($data) && is_scalar($field) && $this->_decodedFields->get($field)===true);
559
    }
560
561
    /**
562
     * Можно ли закодировать данные с помощью json_encode
563
     * @param  string  $field имя поля
564
     * @return boolean
565
     */
566
    public function isEncodableField($field){
567
        /**
568
         * Если поле было распаковано ранее и еще не упаковано
569
         */
570
        return (is_scalar($field) && $this->_decodedFields->get($field)===false);
571
    }
572
573
    /**
574
     * Декодирует конкретное поле
575
     * @param  string $field Имя поля
576
     * @param  bool $store обновить распакованное поле
577
     * @return array ассоциативный массив с данными из json строки
578
     */
579
    public function decodeField($field, $store = false){
580
        $out = array();
581
        if($this->isDecodableField($field)){
582
            $data = $this->get($field);
583
            $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
584
        }
585
        if($store){
586
            $this->field[$field] = $out;
587
            $this->markAsDecode($field);
588
        }
589
        return $out;
590
    }
591
592
    /**
593
     * Декодирование всех json полей
594
     * @return $this
595
     */
596
    protected function decodeFields(){
597
        foreach($this->getNoDecodeFields() as $field => $flag){
598
            $this->decodeField($field, true);
599
        }
600
        return $this;
601
    }
602
603
    /**
604
     * Запаковывает конкретное поле в JSON
605
     * @param  string $field Имя поля
606
     * @param  bool $store обновить запакованное поле
607
     * @return array json строка
608
     */
609
    public function encodeField($field, $store = false){
610
        $out = null;
611
        if($this->isEncodableField($field)){
612
            $data = $this->get($field);
613
            $out = json_encode($data);
614
        }
615
        if($store){
616
            $this->field[$field] = $out;
617
            $this->markAsEncode($field);
618
        }
619
        return $out;
620
    }
621
622
    /**
623
     * Запаковка всех json полей
624
     * @return $this
625
     */
626
    protected function encodeFields(){
627
        foreach($this->getNoEncodeFields() as $field => $flag){
628
            $this->encodeField($field, true);
629
        }
630
        return $this;
631
    }
632
}
633