Test Failed
Push — master ( 5aadec...a965f9 )
by Agel_Nash
03:19
created

modResource::get()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
c 0
b 0
f 0
rs 9.2
cc 4
eloc 8
nc 3
nop 1
1
<?php
2
require_once('MODx.php');
3
4
/**
5
 * Class modResource
6
 */
7
class modResource extends MODxAPI
8
{
9
    /**
10
     * @var string
11
     */
12
    protected $mode = 'new';
13
    /**
14
     * @var array
15
     */
16
    protected $default_field = array(
17
        'type'            => 'document',
18
        'contentType'     => 'text/html',
19
        'pagetitle'       => 'New document',
20
        'longtitle'       => '',
21
        'description'     => '',
22
        'alias'           => '',
23
        'link_attributes' => '',
24
        'published'       => 1,
25
        'pub_date'        => 0,
26
        'unpub_date'      => 0,
27
        'parent'          => 0,
28
        'isfolder'        => 0,
29
        'introtext'       => '',
30
        'content'         => '',
31
        'richtext'        => 1,
32
        'template'        => 0,
33
        'menuindex'       => 0,
34
        'searchable'      => 1,
35
        'cacheable'       => 1,
36
        'createdon'       => 0,
37
        'createdby'       => 0,
38
        'editedon'        => 0,
39
        'editedby'        => 0,
40
        'deleted'         => 0,
41
        'deletedon'       => 0,
42
        'deletedby'       => 0,
43
        'publishedon'     => 0,
44
        'publishedby'     => 0,
45
        'menutitle'       => '',
46
        'donthit'         => 0,
47
        'privateweb'      => 0,
48
        'privatemgr'      => 0,
49
        'content_dispo'   => 0,
50
        'hidemenu'        => 0,
51
        'alias_visible'   => 1
52
    );
53
    /**
54
     * @var array
55
     */
56
    private $table = array(
57
        '"' => '_',
58
        "'" => '_',
59
        ' ' => '_',
60
        '.' => '_',
61
        ',' => '_',
62
        'а' => 'a',
63
        'б' => 'b',
64
        'в' => 'v',
65
        'г' => 'g',
66
        'д' => 'd',
67
        'е' => 'e',
68
        'ё' => 'e',
69
        'ж' => 'zh',
70
        'з' => 'z',
71
        'и' => 'i',
72
        'й' => 'y',
73
        'к' => 'k',
74
        'л' => 'l',
75
        'м' => 'm',
76
        'н' => 'n',
77
        'о' => 'o',
78
        'п' => 'p',
79
        'р' => 'r',
80
        'с' => 's',
81
        'т' => 't',
82
        'у' => 'u',
83
        'ф' => 'f',
84
        'х' => 'h',
85
        'ц' => 'c',
86
        'ч' => 'ch',
87
        'ш' => 'sh',
88
        'щ' => 'sch',
89
        'ь' => '',
90
        'ы' => 'y',
91
        'ъ' => '',
92
        'э' => 'e',
93
        'ю' => 'yu',
94
        'я' => 'ya',
95
        'А' => 'A',
96
        'Б' => 'B',
97
        'В' => 'V',
98
        'Г' => 'G',
99
        'Д' => 'D',
100
        'Е' => 'E',
101
        'Ё' => 'E',
102
        'Ж' => 'Zh',
103
        'З' => 'Z',
104
        'И' => 'I',
105
        'Й' => 'Y',
106
        'К' => 'K',
107
        'Л' => 'L',
108
        'М' => 'M',
109
        'Н' => 'N',
110
        'О' => 'O',
111
        'П' => 'P',
112
        'Р' => 'R',
113
        'С' => 'S',
114
        'Т' => 'T',
115
        'У' => 'U',
116
        'Ф' => 'F',
117
        'Х' => 'H',
118
        'Ц' => 'C',
119
        'Ч' => 'Ch',
120
        'Ш' => 'Sh',
121
        'Щ' => 'Sch',
122
        'Ь' => '',
123
        'Ы' => 'Y',
124
        'Ъ' => '',
125
        'Э' => 'E',
126
        'Ю' => 'Yu',
127
        'Я' => 'Ya',
128
    );
129
    /**
130
     * @var array массив ТВшек где name это ключ массива, а ID это значение
131
     */
132
    private $tv = array();
133
    /**
134
     * @var array массив ТВшек где ID это ключ массива, а name это значение
135
     */
136
    private $tvid = array();
137
    /**
138
     * @var array значения по умолчанию для ТВ параметров
139
     */
140
    private $tvd = array();
141
142
    /** @var array связи ТВ и шаблонов */
143
    private $tvTpl = array();
144
145
    /** @var array параметры ТВ с массивами */
146
    protected $tvaFields = array();
147
148
    /**
149
     * Массив администраторов
150
     * @var DLCollection
151
     */
152
    private $managerUsers = null;
153
    /** @var array группы документов */
154
    protected $groupIds = array();
155
    /**
156
     * modResource constructor.
157
     * @param DocumentParser $modx
1 ignored issue
show
Bug introduced by
The type DocumentParser 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...
158
     * @param bool $debug
159
     */
160
    public function __construct($modx, $debug = false)
161
    {
162
        parent::__construct($modx, $debug);
163
        $this->get_TV();
164
        $uTable = $this->makeTable("manager_users");
165
        $aTable = $this->makeTable("user_attributes");
166
        $query = "SELECT `u`.`id`, `a`.`email`, `u`.`username`  FROM " . $aTable . " as `a` LEFT JOIN " . $uTable . " as `u` ON `u`.`id`=`a`.`internalKey`";
167
        $query = $this->query($query);
168
        $this->managerUsers = new DLCollection($modx, empty($query) ? array() : $query);
169
    }
170
171
    /**
172
     * @return array
173
     */
174
    public function toArrayMain()
175
    {
176
        $out = array_intersect_key(parent::toArray(), $this->default_field);
177
178
        return $out;
179
    }
180
181
    /**
182
     * @param bool $render
183
     * @return array
184
     */
185
    public function toArrayTV($render = false)
186
    {
187
        $out = array_diff_key(parent::toArray(), $this->default_field);
188
        $tpl = $this->get('template');
189
        $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
190
        foreach ($tvTPL as $item) {
191
            if (isset($this->tvid[$item]) && !array_key_exists($this->tvid[$item], $out)) {
192
                $out[$this->tvid[$item]] = $this->get($this->tvid[$item]);
193
            }
194
        }
195
        if ($render) {
196
            foreach ($out as $key => $val) {
197
                $out[$key] = $this->renderTV($key);
198
            }
199
        }
200
201
        return $out;
202
    }
203
204
    /**
205
     * @param string $prefix
206
     * @param string $suffix
207
     * @param string $sep
208
     * @param bool $render
209
     * @return array
210
     */
211
    public function toArray($prefix = '', $suffix = '', $sep = '_', $render = true)
212
    {
213
        $out = array_merge(
214
            $this->toArrayMain(),
215
            $this->toArrayTV($render),
216
            array($this->fieldPKName() => $this->getID())
217
        );
218
219
        return \APIhelpers::renameKeyArr($out, $prefix, $suffix, $sep);
220
    }
221
222
    /**
223
     * @return null|string
224
     */
225
    public function getUrl()
226
    {
227
        $out = null;
228
        $id = (int)$this->getID();
229
        if (!empty($id)) {
230
            $out = $this->modx->makeUrl($id);
231
        }
232
233
        return $out;
234
    }
235
236
    /**
237
     * @param string $main
238
     * @param string $second
239
     * @return mixed
240
     */
241
    public function getTitle($main = 'menutitle', $second = 'pagetitle')
242
    {
243
        $title = $this->get($main);
244
        if (empty($title) && $title !== '0') {
245
            $title = $this->get($second);
246
        }
247
248
        return $title;
249
    }
250
251
    /**
252
     * @return bool
253
     */
254
    public function isWebShow()
255
    {
256
        $pub = ($this->get('publishedon') < time() && $this->get('published'));
257
        $unpub = ($this->get('unpub_date') == 0 || $this->get('unpub_date') > time());
258
        $del = ($this->get('deleted') == 0 && ($this->get('deletedon') == 0 || $this->get('deletedon') > time()));
259
260
        return ($pub && $unpub && $del);
261
    }
262
263
    /**
264
     * @return $this
265
     */
266
    public function touch()
267
    {
268
        $this->set('editedon', time());
269
270
        return $this;
271
    }
272
273
    /**
274
     * @param $tvname
275
     * @return null|string
276
     */
277
    public function renderTV($tvname)
278
    {
279
        $out = null;
280
        if ($this->getID() > 0) {
281
            include_once MODX_MANAGER_PATH . "includes/tmplvars.format.inc.php";
282
            include_once MODX_MANAGER_PATH . "includes/tmplvars.commands.inc.php";
283
            $tvval = $this->get($tvname);
284
            if ($this->isTVarrayField($tvname) && is_array($tvval)) {
285
                $tvval = implode('||', $tvval);
286
            }
287
            $param = APIHelpers::getkey($this->tvd, $tvname, array());
288
            $display = APIHelpers::getkey($param, 'display', '');
289
            $display_params = APIHelpers::getkey($param, 'display_params', '');
290
            $type = APIHelpers::getkey($param, 'type', '');
291
            $out = getTVDisplayFormat($tvname, $tvval, $display, $display_params, $type, $this->getID(), '');
0 ignored issues
show
Bug introduced by
The function getTVDisplayFormat was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

291
            $out = /** @scrutinizer ignore-call */ getTVDisplayFormat($tvname, $tvval, $display, $display_params, $type, $this->getID(), '');
Loading history...
292
        }
293
294
        return $out;
295
    }
296
297
    /**
298
     * @param $key
299
     * @return mixed
300
     */
301
    public function get($key)
302
    {
303
        $out = parent::get($key);
304
        if (isset($this->tv[$key])) {
305
            $tpl = $this->get('template');
306
            $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
307
            $tvID = APIHelpers::getkey($this->tv, $key, 0);
308
            if (in_array($tvID, $tvTPL) && is_null($out)) {
309
                $out = APIHelpers::getkey($this->tvd[$key], 'value', null);
310
            }
311
        }
312
313
        return $out;
314
    }
315
316
    /**
317
     * @param $key
318
     * @param $value
319
     * @return $this
320
     */
321
    public function set($key, $value)
322
    {
323
        if ((is_scalar($value) || $this->isTVarrayField($key) || $this->isJsonField($key)) && is_scalar($key) && !empty($key)) {
324
            switch ($key) {
325
                case 'parent':
326
                    $value = (int)$value;
327
                    break;
328
                case 'template':
329
                    $value = trim($value);
330
                    $value = $this->setTemplate($value);
331
                    break;
332
                case 'published':
333
                    $value = (int)((bool)$value);
334
                    if ($value) {
335
                        $this->field['publishedon'] = time() + $this->modxConfig('server_offset_time');
336
                    }
337
                    break;
338
                case 'pub_date':
339
                    $value = $this->getTime($value);
340
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
341
                        $this->field['published'] = 1;
342
                        $this->field['publishedon'] = $value;
343
                    }
344
                    break;
345
                case 'unpub_date':
346
                    $value = $this->getTime($value);
347
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
348
                        $this->field['published'] = 0;
349
                        $this->field['publishedon'] = 0;
350
                    }
351
                    break;
352
                case 'deleted':
353
                    $value = (int)((bool)$value);
354
                    if ($value) {
355
                        $this->field['deletedon'] = time() + $this->modxConfig('server_offset_time');
356
                    } else {
357
                        $this->field['deletedon'] = 0;
358
                    }
359
                    break;
360
                case 'deletedon':
361
                    $value = $this->getTime($value);
362
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') < $value) {
363
                        $value = 0;
364
                    }
365
                    if ($value) {
366
                        $this->field['deleted'] = 1;
367
                    }
368
                    break;
369
                case 'editedon':
370
                case 'createdon':
371
                case 'publishedon':
372
                    $value = $this->getTime($value);
373
                    break;
374
                case 'publishedby':
375
                case 'editedby':
376
                case 'createdby':
377
                case 'deletedby':
378
                    $value = $this->getUser($value, $this->default_field[$key]);
379
                    break;
380
            }
381
            $this->field[$key] = $value;
382
        }
383
384
        return $this;
385
    }
386
387
    /**
388
     * @param $value
389
     * @param int $default
390
     * @return int|mixed
391
     */
392
    protected function getUser($value, $default = 0)
393
    {
394
        $currentAdmin = APIHelpers::getkey($_SESSION, 'mgrInternalKey', 0);
395
        $value = (int)$value;
396
        if (!empty($value)) {
397
            $by = $this->findUserBy($value);
398
            $exists = $this->managerUsers->exists(function ($key, Helpers\Collection $val) use ($by, $value) {
399
                return ($val->containsKey($by) && $val->get($by) === (string)$value);
400
            });
401
            if (!$exists) {
402
                $value = 0;
403
            }
404
        }
405
        if (empty($value)) {
406
            $value = empty($currentAdmin) ? $default : $currentAdmin;
407
        }
408
409
        return $value;
410
    }
411
412
    /**
413
     * @param $data
414
     * @return bool|string
415
     */
416
    protected function findUserBy($data)
417
    {
418
        switch (true) {
419
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
420
                $find = 'id';
421
                break;
422
            case filter_var($data, FILTER_VALIDATE_EMAIL):
423
                $find = 'email';
424
                break;
425
            case is_scalar($data):
426
                $find = 'username';
427
                break;
428
            default:
429
                $find = false;
430
        }
431
432
        return $find;
433
    }
434
435
    /**
436
     * @param array $data
437
     * @return $this
438
     */
439
    public function create($data = array())
440
    {
441
        $this->close();
442
        $fld = array();
443
        foreach ($this->tvd as $name => $tv) {
444
            $fld[$name] = $tv['value'];
445
        };
446
        $this->store($fld);
447
448
        $this->fromArray(array_merge($fld, $data));
449
        $this->set('createdby', null)
450
            ->set('editedby', null)
451
            ->set('createdon', time())
452
            ->touch();
453
454
        return $this;
455
    }
456
457
    /**
458
     * @param $id
459
     * @return $this
460
     */
461
    public function edit($id)
462
    {
463
        $id = is_scalar($id) ? trim($id) : '';
464
        if ($this->getID() != $id) {
465
            $this->close();
466
            $this->markAllEncode();
467
            $this->newDoc = false;
468
469
            $result = $this->query("SELECT * from {$this->makeTable('site_content')} where `id`=" . (int)$id);
470
            $this->fromArray($this->modx->db->getRow($result));
471
            $result = $this->query("SELECT * from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid`=" . (int)$id);
472
            while ($row = $this->modx->db->getRow($result)) {
473
                $this->field[$this->tvid[$row['tmplvarid']]] = $row['value'];
474
            }
475
            if (empty($this->field['id'])) {
476
                $this->id = null;
477
            } else {
478
                $this->id = $this->field['id'];
479
                $this->set('editedby', null)->touch();
480
                $this->decodeFields();
481
            }
482
            $this->store($this->toArray(null, null, null, false));
483
            unset($this->field['id']);
484
        }
485
486
        return $this;
487
    }
488
489
    /**
490
     * @param bool $fire_events
491
     * @param bool $clearCache
492
     * @return bool|null
493
     */
494
    public function save($fire_events = false, $clearCache = false)
495
    {
496
        $parent = null;
497
        if ($this->field['pagetitle'] == '') {
498
            $this->log['emptyPagetitle'] = 'Pagetitle is empty in <pre>' . print_r($this->field, true) . '</pre>';
499
500
            return false;
501
        }
502
503
        $uid = $this->modx->getLoginUserID('mgr');
504
505
        if (
506
            $this->field['parent'] == 0 &&
507
            !$this->modxConfig('udperms_allowroot') &&
508
            !($uid && isset($_SESSION['mgrRole']) && $_SESSION['mgrRole'] == 1)
509
        ) {
510
            $this->log['rootForbidden'] = 'Only Administrators can create documents in the root folder because udperms_allowroot setting is off';
511
512
            return false;
513
        }
514
515
        $this->set('alias', $this->getAlias());
516
517
        $this->invokeEvent('OnBeforeDocFormSave', array(
518
            'mode'   => $this->newDoc ? "new" : "upd",
519
            'id'     => isset($this->id) ? $this->id : '',
520
            'doc'    => $this->toArray(),
521
            'docObj' => $this
522
        ), $fire_events);
523
524
        $fld = $this->encodeFields()->toArray(null, null, null, false);
525
        foreach ($this->default_field as $key => $value) {
526
            $tmp = $this->get($key);
527
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
528
                if ($tmp == $value) {
529
                    switch ($key) {
530
                        case 'cacheable':
531
                            $value = $this->modxConfig('cache_default');
532
                            break;
533
                        case 'template':
534
                            $value = $value = $this->modxConfig('default_template');
0 ignored issues
show
Unused Code introduced by
The assignment to $value is dead and can be removed.
Loading history...
535
                            break;
536
                        case 'published':
537
                            $value = $this->modxConfig('publish_default');
538
                            break;
539
                        case 'searchable':
540
                            $value = $this->modxConfig('search_default');
541
                            break;
542
                        case 'donthit':
543
                            $value = $this->modxConfig('track_visitors');
544
                            break;
545
                    }
546
                }
547
                $this->field[$key] = $value;
548
            }
549
            switch (true) {
550
                case $key == 'parent':
551
                    $parent = (int)$this->get($key);
552
                    $q = $this->query("SELECT count(`id`) FROM {$this->makeTable('site_content')} WHERE `id`='{$parent}'");
553
                    if ($this->modx->db->getValue($q) != 1) {
554
                        $parent = 0;
555
                    }
556
                    $this->field[$key] = $parent;
557
                    $this->Uset($key);
558
                    break;
559
                case ($key == 'alias_visible' && !$this->checkVersion('1.0.10', true)):
560
                    $this->eraseField('alias_visible');
561
                    break;
562
                default:
563
                    $this->Uset($key);
564
            }
565
            unset($fld[$key]);
566
        }
567
568
        if (!empty($this->set)) {
569
            if ($this->newDoc) {
570
                $SQL = "INSERT into {$this->makeTable('site_content')} SET " . implode(', ', $this->set);
571
            } else {
572
                $SQL = "UPDATE {$this->makeTable('site_content')} SET " . implode(', ',
573
                        $this->set) . " WHERE `id` = " . $this->id;
574
            }
575
            $this->query($SQL);
576
577
            if ($this->newDoc) {
578
                $this->id = $this->modx->db->getInsertId();
579
            }
580
581
            if ($parent > 0) {
582
                $this->query("UPDATE {$this->makeTable('site_content')} SET `isfolder`='1' WHERE `id`='{$parent}'");
583
            }
584
        }
585
586
        $_deleteTVs = $_insertTVs = array();
587
        foreach ($fld as $key => $value) {
588
            if (empty($this->tv[$key]) || !$this->isChanged($key) || !$this->belongsToTemplate($this->tv[$key])) {
589
                continue;
590
            } elseif ($value === '') {
591
                $_deleteTVs[] = $this->tv[$key];
592
            } else {
593
                $_insertTVs[$this->tv[$key]] = $this->escape($value);
594
            }
595
        }
596
597
        if (!empty($_insertTVs)) {
598
            $values = array();
599
            foreach ($_insertTVs as $id => $value) {
600
                $values[] = "({$this->id}, {$id}, '{$value}')";
601
            }
602
            $values = implode(',', $values);
603
            $this->query("INSERT INTO {$this->makeTable('site_tmplvar_contentvalues')} (`contentid`,`tmplvarid`,`value`) VALUES {$values} ON DUPLICATE KEY UPDATE
604
    `value` = VALUES(`value`)");
605
        }
606
607
        if (!empty($_deleteTVs)) {
608
            $ids = implode(',', $_deleteTVs);
609
            $this->query("DELETE FROM {$this->makeTable('site_tmplvar_contentvalues')} WHERE `contentid` = '{$this->id}' AND `tmplvarid` IN ({$ids})");
610
        }
611
612
        if (!isset($this->mode)) {
613
            $this->mode = $this->newDoc ? "new" : "upd";
614
            $this->newDoc = false;
615
        }
616
617
        if (!empty($this->groupIds)) {
618
            $this->setDocumentGroups($this->id, $this->groupIds);
0 ignored issues
show
Bug introduced by
It seems like $this->id can also be of type string; however, parameter $docId of modResource::setDocumentGroups() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

618
            $this->setDocumentGroups(/** @scrutinizer ignore-type */ $this->id, $this->groupIds);
Loading history...
619
        }
620
        $this->invokeEvent('OnDocFormSave', array(
621
            'mode'   => $this->mode,
622
            'id'     => isset($this->id) ? $this->id : '',
623
            'doc'    => $this->toArray(),
624
            'docObj' => $this
625
        ), $fire_events);
626
627
        if ($clearCache) {
628
            $this->clearCache($fire_events);
629
        }
630
        $this->decodeFields();
631
632
        return $this->id;
633
    }
634
635
    /**
636
     * @param $tvId
637
     * @return bool
638
     */
639
    protected function belongsToTemplate($tvId)
640
    {
641
        $template = $this->get('template');
642
643
        return isset($this->tvTpl[$template]) && in_array($tvId, $this->tvTpl[$template]);
644
    }
645
646
    /**
647
     * @param $ids
648
     * @return $this
649
     * @throws Exception
650
     */
651
    public function toTrash($ids)
652
    {
653
        $ignore = $this->systemID();
654
        $_ids = $this->cleanIDs($ids, ',', $ignore);
655
        if (is_array($_ids) && $_ids != array()) {
656
            $id = $this->sanitarIn($_ids);
657
            $uid = (int)$this->modx->getLoginUserId();
658
            $deletedon = time() + $this->modxConfig('server_offset_time');
659
            $this->query("UPDATE {$this->makeTable('site_content')} SET `deleted`=1, `deletedby`={$uid}, `deletedon`={$deletedon} WHERE `id` IN ({$id})");
660
        } else {
661
            throw new Exception('Invalid IDs list for mark trash: <pre>' . print_r($ids,
662
                    1) . '</pre> please, check ignore list: <pre>' . print_r($ignore, 1) . '</pre>');
663
        }
664
665
        return $this;
666
    }
667
668
    /**
669
     * @param bool $fire_events
670
     * @return $this
671
     */
672
    public function clearTrash($fire_events = false)
673
    {
674
        $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `deleted`='1'");
675
        $_ids = $this->modx->db->getColumn('id', $q);
676
        if (is_array($_ids) && $_ids != array()) {
677
            $this->invokeEvent('OnBeforeEmptyTrash', array(
678
                "ids" => $_ids
679
            ), $fire_events);
680
681
            $id = $this->sanitarIn($_ids);
682
            $this->query("DELETE from {$this->makeTable('site_content')} where `id` IN ({$id})");
683
            $this->query("DELETE from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid` IN ({$id})");
684
685
            $this->invokeEvent('OnEmptyTrash', array(
686
                "ids" => $_ids
687
            ), $fire_events);
688
        }
689
690
        return $this;
691
    }
692
693
    /**
694
     * @param $ids
695
     * @param int|bool $depth
696
     * @return array
697
     */
698
    public function children($ids, $depth)
699
    {
700
        $_ids = $this->cleanIDs($ids, ',');
701
        if (is_array($_ids) && $_ids != array()) {
702
            $id = $this->sanitarIn($_ids);
703
            if (!empty($id)) {
704
                $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} where `parent` IN ({$id})");
705
                $id = $this->modx->db->getColumn('id', $q);
706
                if ($depth > 0 || $depth === true) {
707
                    $id = $this->children($id, is_bool($depth) ? $depth : ($depth - 1));
708
                }
709
                $_ids = array_merge($_ids, $id);
710
            }
711
        }
712
713
        return $_ids;
714
    }
715
716
    /**
717
     * @param string|array $ids
718
     * @param bool $fire_events
719
     * @return $this
720
     * @throws Exception
721
     */
722
    public function delete($ids, $fire_events = false)
723
    {
724
        $ids = $this->children($ids, true);
725
        $_ids = $this->cleanIDs($ids, ',', $this->systemID());
726
        $this->invokeEvent('OnBeforeDocFormDelete', array(
727
            'ids' => $_ids
728
        ), $fire_events);
729
        $this->toTrash($_ids);
730
        $this->invokeEvent('OnDocFormDelete', array(
731
            'ids' => $_ids
732
        ), $fire_events);
733
734
        return $this;
735
    }
736
737
    /**
738
     * @return array
739
     */
740
    private function systemID()
741
    {
742
        $ignore = array(
743
            0, //empty document
744
            (int)$this->modxConfig('site_start'),
745
            (int)$this->modxConfig('error_page'),
746
            (int)$this->modxConfig('unauthorized_page'),
747
            (int)$this->modxConfig('site_unavailable_page')
748
        );
749
        $data = $this->query("SELECT DISTINCT setting_value FROM {$this->makeTable('web_user_settings')} WHERE `setting_name`='login_home' AND `setting_value`!=''");
750
        $data = $this->modx->db->makeArray($data);
751
        foreach ($data as $item) {
752
            $ignore[] = (int)$item['setting_value'];
753
        }
754
755
        return array_unique($ignore);
756
757
    }
758
759
    /**
760
     * @param $alias
761
     * @return string
762
     */
763
    protected function checkAlias($alias)
764
    {
765
        $alias = strtolower($alias);
766
        if ($this->modxConfig('friendly_urls')) {
767
            $_alias = $this->escape($alias);
768
            if ((!$this->modxConfig('allow_duplicate_alias') && !$this->modxConfig('use_alias_path')) || ($this->modxConfig('allow_duplicate_alias') && $this->modxConfig('use_alias_path'))) {
769
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' AND `parent`={$this->get('parent')} LIMIT 1"));
770
            } else {
771
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' LIMIT 1"));
772
            }
773
            if (($flag && $this->newDoc) || (!$this->newDoc && $flag && $this->id != $flag)) {
774
                $suffix = substr($alias, -2);
775
                if (preg_match('/-(\d+)/', $suffix, $tmp) && isset($tmp[1]) && (int)$tmp[1] > 1) {
776
                    $suffix = (int)$tmp[1] + 1;
777
                    $alias = substr($alias, 0, -2) . '-' . $suffix;
778
                } else {
779
                    $alias .= '-2';
780
                }
781
                $alias = $this->checkAlias($alias);
782
            }
783
        }
784
785
        return $alias;
786
    }
787
788
    /**
789
     * @param $key
790
     * @return bool
791
     */
792
    public function issetField($key)
793
    {
794
        return (array_key_exists($key, $this->default_field) || array_key_exists($key, $this->tv));
795
    }
796
797
    /**
798
     * @param bool $reload
799
     * @return $this
800
     */
801
    protected function get_TV($reload = false)
802
    {
803
        $this->modx->_TVnames = array();
804
        if (empty($this->modx->_TVnames) || $reload) {
805
            $result = $this->query('SELECT `id`,`name`,`type` FROM ' . $this->makeTable('site_tmplvars'));
806
            while ($row = $this->modx->db->GetRow($result)) {
807
                $this->modx->_TVnames[$row['name']] = array(
808
                    "id"   => $row['id'],
809
                    "type" => $row['type']
810
                );
811
            }
812
        }
813
        $arrayTypes = array('checkbox', 'listbox-multiple');
814
        $arrayTVs = array();
815
        foreach ($this->modx->_TVnames as $name => $data) {
816
            $this->tvid[$data['id']] = $name;
817
            $this->tv[$name] = $data['id'];
818
            if (in_array($data['type'], $arrayTypes)) {
819
                $arrayTVs[] = $name;
820
            }
821
        }
822
        if (empty($this->tvaFields)) {
823
            $this->tvaFields = $arrayTVs;
824
        }
825
        $this->loadTVTemplate()->loadTVDefault(array_values($this->tv));
826
827
        return $this;
828
    }
829
830
    /**
831
     * @return $this
832
     */
833
    protected function loadTVTemplate()
834
    {
835
        $q = $this->query("SELECT `tmplvarid`, `templateid` FROM " . $this->makeTable('site_tmplvar_templates'));
836
        $q = $this->modx->db->makeArray($q);
837
        $this->tvTpl = array();
838
        foreach ($q as $item) {
839
            $this->tvTpl[$item['templateid']][] = $item['tmplvarid'];
840
        }
841
842
        return $this;
843
    }
844
845
    /**
846
     * @param array $tvId
847
     * @return $this
848
     */
849
    protected function loadTVDefault(array $tvId = array())
850
    {
851
        if (is_array($tvId) && !empty($tvId)) {
852
            $tbl_site_tmplvars = $this->makeTable('site_tmplvars');
853
            $fields = 'id,name,default_text as value,display,display_params,type';
854
            $implodeTvId = implode(',', $tvId);
855
            $rs = $this->query("SELECT {$fields} FROM {$tbl_site_tmplvars} WHERE id IN({$implodeTvId})");
856
            $rows = $this->modx->db->makeArray($rs);
857
            $this->tvd = array();
858
            foreach ($rows as $item) {
859
                $this->tvd[$item['name']] = $item;
860
            }
861
        }
862
863
        return $this;
864
    }
865
866
    /**
867
     * @param $tpl
868
     * @return int
869
     * @throws Exception
870
     */
871
    public function setTemplate($tpl)
872
    {
873
        if (!is_numeric($tpl) || $tpl != (int)$tpl) {
874
            if (is_scalar($tpl)) {
875
                $sql = "SELECT `id` FROM {$this->makeTable('site_templates')} WHERE `templatename` = '" . $this->escape($tpl) . "'";
876
                $rs = $this->query($sql);
877
                if (!$rs || $this->modx->db->getRecordCount($rs) <= 0) {
878
                    throw new Exception("Template {$tpl} is not exists");
879
                }
880
                $tpl = $this->modx->db->getValue($rs);
881
            } else {
882
                throw new Exception("Invalid template name: " . print_r($tpl, 1));
883
            }
884
        }
885
886
        return (int)$tpl;
887
    }
888
889
    /**
890
     * @return string
891
     */
892
    protected function getAlias()
893
    {
894
        if ($this->modxConfig('friendly_urls') && $this->modxConfig('automatic_alias') && $this->get('alias') == '') {
895
            $alias = strtr($this->get('pagetitle'), $this->table);
896
        } else {
897
            if ($this->get('alias') != '') {
898
                $alias = $this->get('alias');
899
            } else {
900
                $alias = '';
901
            }
902
        }
903
        $alias = $this->modx->stripAlias($alias);
904
905
        return $this->checkAlias($alias);
906
    }
907
908
    /**
909
     * @param int $parent
910
     * @param string $criteria
911
     * @param string $dir
912
     * @return $this
913
     *
914
     * Пересчет menuindex по полю таблицы site_content
915
     */
916
    public function updateMenuindex($parent, $criteria = 'id', $dir = 'asc')
917
    {
918
        $dir = strtolower($dir) == 'desc' ? 'desc' : 'asc';
919
        if (is_integer($parent) && $criteria !== '') {
920
            $this->query("SET @index := 0");
921
            $this->query("UPDATE {$this->makeTable('site_content')} SET `menuindex` = (@index := @index + 1) WHERE `parent`={$parent} ORDER BY {$criteria} {$dir}");
922
        }
923
924
        return $this;
925
    }
926
927
    /**
928
     * Устанавливает значение шаблона согласно системной настройке
929
     *
930
     * @return $this
931
     */
932
    public function setDefaultTemplate()
933
    {
934
        $parent = $this->get('parent');
935
        $template = $this->modxConfig('default_template');
936
        switch ($this->modxConfig('auto_template_logic')) {
937
            case 'sibling':
938
                if (!$parent) {
939
                    $site_start = $this->modxConfig('site_start');
940
                    $where = "sc.isfolder=0 AND sc.id!={$site_start}";
941
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', $where, 'menuindex', 'ASC', 1);
942
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
943
                        $template = $sibl[0]['template'];
944
                    }
945
                } else {
946
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', 'isfolder=0', 'menuindex',
947
                        'ASC', 1);
948
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
949
                        $template = $sibl[0]['template'];
950
                    } else {
951
                        $sibl = $this->modx->getDocumentChildren($parent, 0, 0, 'template', 'isfolder=0', 'menuindex',
952
                            'ASC', 1);
953
                        if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
954
                            $template = $sibl[0]['template'];
955
                        }
956
                    }
957
                }
958
                break;
959
            case 'parent':
960
                if ($parent) {
961
                    $_parent = $this->modx->getPageInfo($parent, 0, 'template');
962
                    if (isset($_parent['template'])) {
963
                        $template = $_parent['template'];
964
                    }
965
                }
966
                break;
967
        }
968
        $this->set('template', $template);
969
970
        return $this;
971
    }
972
973
    /**
974
     * Декодирует конкретное поле
975
     * @param  string $field Имя поля
976
     * @param  bool $store обновить распакованное поле
977
     * @return array ассоциативный массив с данными из json строки
978
     */
979
    public function decodeField($field, $store = false)
980
    {
981
        $out = array();
982
        if ($this->isDecodableField($field)) {
983
            $data = $this->get($field);
984
            if ($this->isTVarrayField($field)) {
985
                $out = explode('||', $data);
986
            } else {
987
                $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
988
            }
989
        }
990
        if ($store) {
991
            $this->field[$field] = $out;
992
            $this->markAsDecode($field);
993
        }
994
995
        return $out;
996
    }
997
998
    /**
999
     * Запаковывает конкретное поле в JSON
1000
     * @param  string $field Имя поля
1001
     * @param  bool $store обновить запакованное поле
1002
     * @return string|null json строка
1003
     */
1004
    public function encodeField($field, $store = false)
1005
    {
1006
        $out = null;
1007
        if ($this->isEncodableField($field)) {
1008
            $data = $this->get($field);
1009
            if ($this->isTVarrayField($field)) {
1010
                $out = is_array($data) ? implode('||', $data) : (string)$data;
1011
            } else {
1012
                $out = json_encode($data);
1013
            }
1014
        }
1015
        if ($store) {
1016
            $this->field[$field] = $out;
1017
            $this->markAsEncode($field);
1018
        }
1019
1020
        return $out;
1021
    }
1022
1023
    /**
1024
     * Может ли содержать данное поле json массив
1025
     * @param  string $field имя поля
1026
     * @return boolean
1027
     */
1028
    public function isTVarrayField($field)
1029
    {
1030
        return (is_scalar($field) && in_array($field, $this->tvaFields));
1031
    }
1032
1033
    /**
1034
     * Пометить все поля как запакованные
1035
     * @return $this
1036
     */
1037
    public function markAllEncode()
1038
    {
1039
        parent::markAllEncode();
1040
        foreach ($this->tvaFields as $field) {
1041
            $this->markAsEncode($field);
1042
        }
1043
1044
        return $this;
1045
    }
1046
1047
    /**
1048
     * Пометить все поля как распакованные
1049
     * @return $this
1050
     */
1051
    public function markAllDecode()
1052
    {
1053
        parent::markAllDecode();
1054
        foreach ($this->tvaFields as $field) {
1055
            $this->markAsDecode($field);
1056
        }
1057
1058
        return $this;
1059
    }
1060
1061
    /**
1062
     * @param int $docId
1063
     */
1064
    public function getDocumentGroups($docId = 0)
1065
    {
1066
        $out = array();
1067
        $doc = $this->switchObject($docId);
1068
        if (null !== $doc->getID()) {
1069
            $doc_groups = $this->makeTable('document_groups');
1070
            $docgroup_names = $this->makeTable('documentgroup_names');
1071
1072
            $rs = $this->query("SELECT `dg`.`document_group`, `dgn`.`name` FROM {$doc_groups} as `dg` INNER JOIN {$docgroup_names} as `dgn` ON `dgn`.`id`=`dg`.`document_group`
1073
                WHERE `dg`.`document` = " . $doc->getID());
1074
            while ($row = $this->modx->db->getRow($rs)) {
1075
                $out[$row['document_group']] = $row['name'];
1076
            }
1077
1078
        }
1079
        unset($doc);
1080
1081
        return $out;
1082
    }
1083
1084
    /**
1085
     * @param int $docId
1086
     * @param array $groupIds
1087
     * @return $this
1088
     */
1089
    public function setDocumentGroups($docId = 0, $groupIds = array())
1090
    {
1091
        if (!is_array($groupIds)) {
0 ignored issues
show
introduced by
The condition ! is_array($groupIds) can never be true.
Loading history...
1092
            return $this;
1093
        }
1094
        if ($this->newDoc && $docId == 0) {
1095
            $this->groupIds = $groupIds;
1096
        } else {
1097
            $doc = $this->switchObject($docId);
1098
            if ($id = $doc->getID()) {
1099
                foreach ($groupIds as $gid) {
1100
                    $this->query("REPLACE INTO {$this->makeTable('document_groups')} (`document_group`, `document`) VALUES ('{$gid}', '{$id}')");
1101
                }
1102
                if (!$this->newDoc) {
1103
                    $groupIds = empty($groupIds) ? '0' : implode(',', $groupIds);
1104
                    $this->query("DELETE FROM {$this->makeTable('document_groups')} WHERE `document`={$id} AND `document_group` NOT IN ({$groupIds})");
1105
                }
1106
            }
1107
            unset($doc);
1108
            $this->groupIds = array();
1109
        }
1110
1111
        return $this;
1112
    }
1113
1114
}
1115