Test Failed
Push — master ( d393b1...363436 )
by Maxim
02:17
created

modResource::save()   F

Complexity

Conditions 40
Paths > 20000

Size

Total Lines 139
Code Lines 98

Duplication

Lines 0
Ratio 0 %

Importance

Changes 14
Bugs 9 Features 0
Metric Value
dl 0
loc 139
rs 2
c 14
b 9
f 0
cc 40
eloc 98
nc 57026
nop 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<<<<<<< HEAD
0 ignored issues
show
Coding Style introduced by
File has mixed line endings; this may cause incorrect results
Loading history...
2
<?php
3
require_once('MODx.php');
4
5
/**
6
 * Class modResource
7
 */
8
class modResource extends MODxAPI
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
9
{
0 ignored issues
show
Coding Style introduced by
The opening class brace should be on a newline by itself.
Loading history...
10
    /**
11
     * @var string
12
     */
13
    protected $mode = 'new';
14
    /**
15
     * @var array
16
     */
17
    protected $default_field = array(
18
        'type'            => 'document',
19
        'contentType'     => 'text/html',
20
        'pagetitle'       => 'New document',
21
        'longtitle'       => '',
22
        'description'     => '',
23
        'alias'           => '',
24
        'link_attributes' => '',
25
        'published'       => 1,
26
        'pub_date'        => 0,
27
        'unpub_date'      => 0,
28
        'parent'          => 0,
29
        'isfolder'        => 0,
30
        'introtext'       => '',
31
        'content'         => '',
32
        'richtext'        => 1,
33
        'template'        => 0,
34
        'menuindex'       => 0,
35
        'searchable'      => 1,
36
        'cacheable'       => 1,
37
        'createdon'       => 0,
38
        'createdby'       => 0,
39
        'editedon'        => 0,
40
        'editedby'        => 0,
41
        'deleted'         => 0,
42
        'deletedon'       => 0,
43
        'deletedby'       => 0,
44
        'publishedon'     => 0,
45
        'publishedby'     => 0,
46
        'menutitle'       => '',
47
        'donthit'         => 0,
48
        'privateweb'      => 0,
49
        'privatemgr'      => 0,
50
        'content_dispo'   => 0,
51
        'hidemenu'        => 0,
52
        'alias_visible'   => 1
53
    );
54
    /**
55
     * @var array
56
     */
57
    private $table = array(
58
        '"' => '_',
59
        "'" => '_',
60
        ' ' => '_',
61
        '.' => '_',
62
        ',' => '_',
63
        'а' => 'a',
64
        'б' => 'b',
65
        'в' => 'v',
66
        'г' => 'g',
67
        'д' => 'd',
68
        'е' => 'e',
69
        'ё' => 'e',
70
        'ж' => 'zh',
71
        'з' => 'z',
72
        'и' => 'i',
73
        'й' => 'y',
74
        'к' => 'k',
75
        'л' => 'l',
76
        'м' => 'm',
77
        'н' => 'n',
78
        'о' => 'o',
79
        'п' => 'p',
80
        'р' => 'r',
81
        'с' => 's',
82
        'т' => 't',
83
        'у' => 'u',
84
        'ф' => 'f',
85
        'х' => 'h',
86
        'ц' => 'c',
87
        'ч' => 'ch',
88
        'ш' => 'sh',
89
        'щ' => 'sch',
90
        'ь' => '',
91
        'ы' => 'y',
92
        'ъ' => '',
93
        'э' => 'e',
94
        'ю' => 'yu',
95
        'я' => 'ya',
96
        'А' => 'A',
97
        'Б' => 'B',
98
        'В' => 'V',
99
        'Г' => 'G',
100
        'Д' => 'D',
101
        'Е' => 'E',
102
        'Ё' => 'E',
103
        'Ж' => 'Zh',
104
        'З' => 'Z',
105
        'И' => 'I',
106
        'Й' => 'Y',
107
        'К' => 'K',
108
        'Л' => 'L',
109
        'М' => 'M',
110
        'Н' => 'N',
111
        'О' => 'O',
112
        'П' => 'P',
113
        'Р' => 'R',
114
        'С' => 'S',
115
        'Т' => 'T',
116
        'У' => 'U',
117
        'Ф' => 'F',
118
        'Х' => 'H',
119
        'Ц' => 'C',
120
        'Ч' => 'Ch',
121
        'Ш' => 'Sh',
122
        'Щ' => 'Sch',
123
        'Ь' => '',
124
        'Ы' => 'Y',
125
        'Ъ' => '',
126
        'Э' => 'E',
127
        'Ю' => 'Yu',
128
        'Я' => 'Ya',
129
    );
130
    /**
131
     * @var array массив ТВшек где name это ключ массива, а ID это значение
132
     */
133
    private $tv = array();
134
    /**
135
     * @var array массив ТВшек где ID это ключ массива, а name это значение
136
     */
137
    private $tvid = array();
138
    /**
139
     * @var array значения по умолчанию для ТВ параметров
140
     */
141
    private $tvd = array();
142
143
    /** @var array связи ТВ и шаблонов */
144
    private $tvTpl = array();
145
146
    /** @var array параметры ТВ с массивами */
147
    protected $tvaFields = array();
148
149
    /**
150
     * Массив администраторов
151
     * @var DLCollection
152
     */
153
    private $managerUsers = null;
154
    /** @var array группы документов */
155
    protected $groupIds = array();
156
157
    /**
158
     * modResource constructor.
159
     * @param DocumentParser $modx
160
     * @param bool $debug
161
     */
162
    public function __construct($modx, $debug = false)
163
    {
164
        parent::__construct($modx, $debug);
165
        $this->get_TV();
166
        $uTable = $this->makeTable("manager_users");
167
        $aTable = $this->makeTable("user_attributes");
168
        $query = "SELECT `u`.`id`, `a`.`email`, `u`.`username`  FROM " . $aTable . " as `a` LEFT JOIN " . $uTable . " as `u` ON `u`.`id`=`a`.`internalKey`";
169
        $query = $this->query($query);
170
        $this->managerUsers = new DLCollection($modx, empty($query) ? array() : $query);
171
    }
172
173
    /**
174
     * @return array
175
     */
176
    public function toArrayMain()
177
    {
178
        $out = array_intersect_key(parent::toArray(), $this->default_field);
179
180
        return $out;
181
    }
182
183
    /**
184
     * @param bool $render
185
     * @return array
186
     */
187
    public function toArrayTV($render = false)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
188
    {
189
        $out = array_diff_key(parent::toArray(), $this->default_field);
190
        $tpl = $this->get('template');
191
        $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
192
        foreach ($tvTPL as $item) {
193
            if (isset($this->tvid[$item]) && !array_key_exists($this->tvid[$item], $out)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
194
                $value = $this->get($this->tvid[$item]);
195
                $out[$this->tvid[$item]] = empty($value) ? $this->tvd[$this->tvid[$item]] : $value;
196
            }
197
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
198
        }
199
        if ($render) {
200
            foreach ($out as $key => $val) {
201
                $out[$key] = $this->renderTV($key);
202
            }
203
        }
204
205
        return $out;
206
    }
207
208
    /**
209
     * @param string $prefix
210
     * @param string $suffix
211
     * @param string $sep
212
     * @param bool $render
213
     * @return array
214
     */
215
    public function toArray($prefix = '', $suffix = '', $sep = '_', $render = true)
216
    {
217
        $out = array_merge(
218
            $this->toArrayMain(),
219
            $this->toArrayTV($render),
220
            array($this->fieldPKName() => $this->getID())
221
        );
222
223
        return \APIhelpers::renameKeyArr($out, $prefix, $suffix, $sep);
224
    }
225
226
    /**
227
     * @return null|string
228
     */
229
    public function getUrl()
230
    {
231
        $out = null;
232
        $id = (int)$this->getID();
233
        if (!empty($id)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
234
            $out = $this->modx->makeUrl($id);
235
        }
236
237
        return $out;
238
    }
239
240
    /**
241
     * @param string $main
242
     * @param string $second
243
     * @return mixed
244
     */
245
    public function getTitle($main = 'menutitle', $second = 'pagetitle')
246
    {
247
        $title = $this->get($main);
248
        if (empty($title) && $title !== '0') {
249
            $title = $this->get($second);
250
        }
251
252
        return $title;
253
    }
254
255
    /**
256
     * @return bool
257
     */
258
    public function isWebShow()
259
    {
260
        $pub = ($this->get('publishedon') < time() && $this->get('published'));
261
        $unpub = ($this->get('unpub_date') == 0 || $this->get('unpub_date') > time());
262
        $del = ($this->get('deleted') == 0 && ($this->get('deletedon') == 0 || $this->get('deletedon') > time()));
263
264
        return ($pub && $unpub && $del);
265
    }
266
267
    /**
268
     * @return $this
269
     */
270
    public function touch()
271
    {
272
        $this->set('editedon', time());
273
274
        return $this;
275
    }
276
277
    /**
278
     * @param $tvname
279
     * @return null|string
280
     */
281
    public function renderTV($tvname)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
282
    {
283
        $out = null;
284
        if ($this->getID() > 0) {
285
            include_once MODX_MANAGER_PATH . "includes/tmplvars.format.inc.php";
286
            include_once MODX_MANAGER_PATH . "includes/tmplvars.commands.inc.php";
287
            $tvval = $this->get($tvname);
288
            if ($this->isTVarrayField($tvname) && is_array($tvval)) {
289
                $tvval = implode('||', $tvval);
290
            }
291
            $param = APIHelpers::getkey($this->tvd, $tvname, array());
292
            $display = APIHelpers::getkey($param, 'display', '');
293
            $display_params = APIHelpers::getkey($param, 'display_params', '');
294
            $type = APIHelpers::getkey($param, 'type', '');
295
            $out = getTVDisplayFormat($tvname, $tvval, $display, $display_params, $type, $this->getID(), '');
296
        }
297
298
        return $out;
299
    }
300
301
    /**
302
     * @param $key
303
     * @return mixed
304
     */
305
    public function get($key)
306
    {
307
        $out = parent::get($key);
308
        if (isset($this->tv[$key])) {
309
            $tpl = $this->get('template');
310
            $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
311
            $tvID = APIHelpers::getkey($this->tv, $key, 0);
312
            if (in_array($tvID, $tvTPL) && is_null($out)) {
313
                $out = APIHelpers::getkey($this->tvd, $key, null);
314
            }
315
        }
316
317
        return $out;
318
    }
319
320
    /**
321
     * @param $key
322
     * @param $value
323
     * @return $this
324
     */
325
    public function set($key, $value)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (4) exceeds 3; consider refactoring the function
Loading history...
326
    {
327
        if ((is_scalar($value) || $this->isTVarrayField($key) || $this->isJsonField($key)) && is_scalar($key) && !empty($key)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
328
            switch ($key) {
329
                case 'parent':
330
                    $value = (int)$value;
331
                    break;
332
                case 'template':
333
                    $value = trim($value);
334
                    $value = $this->setTemplate($value);
335
                    break;
336
                case 'published':
337
                    $value = (int)((bool)$value);
338
                    if ($value) {
339
                        $this->field['publishedon'] = time() + $this->modxConfig('server_offset_time');
340
                    }
341
                    break;
342
                case 'pub_date':
343
                    $value = $this->getTime($value);
344
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
345
                        $this->field['published'] = 1;
346
                        $this->field['publishedon'] = $value;
347
                    }
348
                    break;
349
                case 'unpub_date':
350
                    $value = $this->getTime($value);
351
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
352
                        $this->field['published'] = 0;
353
                        $this->field['publishedon'] = 0;
354
                    }
355
                    break;
356
                case 'deleted':
357
                    $value = (int)((bool)$value);
358
                    if ($value) {
359
                        $this->field['deletedon'] = time() + $this->modxConfig('server_offset_time');
360
                    } else {
361
                        $this->field['deletedon'] = 0;
362
                    }
363
                    break;
364
                case 'deletedon':
365
                    $value = $this->getTime($value);
366
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') < $value) {
367
                        $value = 0;
368
                    }
369
                    if ($value) {
370
                        $this->field['deleted'] = 1;
371
                    }
372
                    break;
373
                case 'editedon':
374
                case 'createdon':
375
                case 'publishedon':
376
                    $value = $this->getTime($value);
377
                    break;
378
                case 'publishedby':
379
                case 'editedby':
380
                case 'createdby':
381
                case 'deletedby':
382
                    $value = $this->getUser($value, $this->default_field[$key]);
383
                    break;
384
            }
385
            $this->field[$key] = $value;
386
        }
387
388
        return $this;
389
    }
390
391
    /**
392
     * @param $value
393
     * @param int $default
394
     * @return int|mixed
395
     */
396
    protected function getUser($value, $default = 0)
397
    {
398
        $currentAdmin = APIHelpers::getkey($_SESSION, 'mgrInternalKey', 0);
399
        $value = (int)$value;
400
        if (!empty($value)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
401
            $by = $this->findUserBy($value);
402
            $exists = $this->managerUsers->exists(function ($key, Helpers\Collection $val) use ($by, $value) {
403
                return ($val->containsKey($by) && $val->get($by) === (string)$value);
404
            });
405
            if (!$exists) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
406
                $value = 0;
407
            }
408
        }
409
        if (empty($value)) {
410
            $value = empty($currentAdmin) ? $default : $currentAdmin;
411
        }
412
413
        return $value;
414
    }
415
416
    /**
417
     * @param $data
418
     * @return bool|string
419
     */
420
    protected function findUserBy($data)
421
    {
422
        switch (true) {
423
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
424
                $find = 'id';
425
                break;
426
            case filter_var($data, FILTER_VALIDATE_EMAIL):
427
                $find = 'email';
428
                break;
429
            case is_scalar($data):
430
                $find = 'username';
431
                break;
432
            default:
433
                $find = false;
434
        }
435
436
        return $find;
437
    }
438
439
    /**
440
     * @param array $data
441
     * @return $this
442
     */
443
    public function create($data = array())
444
    {
445
        $this->close();
446
        $fld = array();
447
        foreach ($this->tvd as $name => $tv) {
448
            $fld[$name] = $tv;
449
        };
450
        $this->store($fld);
451
452
        $this->fromArray(array_merge($fld, $data));
453
        $this->set('createdby', null)
454
            ->set('editedby', null)
455
            ->set('createdon', time())
456
            ->touch();
457
458
        return $this;
459
    }
460
461
    /**
462
     * @param $id
463
     * @return $this
464
     */
465
    public function edit($id)
466
    {
467
        $id = is_scalar($id) ? trim($id) : '';
468
        if ($this->getID() != $id) {
469
            $this->close();
470
            $this->markAllEncode();
471
            $this->newDoc = false;
472
473
            $result = $this->query("SELECT * from {$this->makeTable('site_content')} where `id`=" . (int)$id);
474
            $this->fromArray($this->modx->db->getRow($result));
475
            $result = $this->query("SELECT * from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid`=" . (int)$id);
476
            while ($row = $this->modx->db->getRow($result)) {
477
                $this->field[$this->tvid[$row['tmplvarid']]] = $row['value'];
478
            }
479
            if (empty($this->field['id'])) {
480
                $this->id = null;
481
            } else {
482
                $this->id = $this->field['id'];
483
                $this->set('editedby', null)->touch();
484
                $this->decodeFields();
485
            }
486
            $this->store($this->toArray(null, null, null, false));
487
            unset($this->field['id']);
488
        }
489
490
        return $this;
491
    }
492
493
    /**
494
     * @param bool $fire_events
495
     * @param bool $clearCache
496
     * @return bool|null
497
     */
498
    public function save($fire_events = false, $clearCache = false)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
499
    {
500
        $parent = null;
501
        if ($this->field['pagetitle'] == '') {
502
            $this->log['emptyPagetitle'] = 'Pagetitle is empty in <pre>' . print_r($this->field, true) . '</pre>';
503
504
            return false;
505
        }
506
507
        $uid = $this->modx->getLoginUserID('mgr');
508
509
        if (
510
            $this->field['parent'] == 0 &&
511
            !$this->modxConfig('udperms_allowroot') &&
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
512
            !($uid && isset($_SESSION['mgrRole']) && $_SESSION['mgrRole'] == 1)
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
513
        ) {
514
            $this->log['rootForbidden'] = 'Only Administrators can create documents in the root folder because udperms_allowroot setting is off';
515
516
            return false;
517
        }
518
519
        $this->set('alias', $this->getAlias());
520
521
        $this->invokeEvent('OnBeforeDocFormSave', array(
522
            'mode'   => $this->newDoc ? "new" : "upd",
523
            'id'     => isset($this->id) ? $this->id : '',
524
            'doc'    => $this->toArray(),
525
            'docObj' => $this
526
        ), $fire_events);
527
528
        $fld = $this->encodeFields()->toArray(null, null, null, false);
529
        foreach ($this->default_field as $key => $value) {
530
            $tmp = $this->get($key);
531
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
532
                if ($tmp == $value) {
533
                    switch ($key) {
534
                        case 'cacheable':
535
                            $value = $this->modxConfig('cache_default');
536
                            break;
537
                        case 'template':
538
                            $value = $value = $this->modxConfig('default_template');
539
                            break;
540
                        case 'published':
541
                            $value = $this->modxConfig('publish_default');
542
                            break;
543
                        case 'searchable':
544
                            $value = $this->modxConfig('search_default');
545
                            break;
546
                        case 'donthit':
547
                            $value = $this->modxConfig('track_visitors');
548
                            break;
549
                    }
550
                }
551
                $this->field[$key] = $value;
552
            }
553
            switch (true) {
554
                case $key == 'parent':
555
                    $parent = (int)$this->get($key);
556
                    $q = $this->query("SELECT count(`id`) FROM {$this->makeTable('site_content')} WHERE `id`='{$parent}'");
557
                    if ($this->modx->db->getValue($q) != 1) {
558
                        $parent = 0;
559
                    }
560
                    $this->field[$key] = $parent;
561
                    $this->Uset($key);
562
                    break;
563
                case ($key == 'alias_visible' && !$this->checkVersion('1.0.10', true)):
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
564
                    $this->eraseField('alias_visible');
565
                    break;
566
                default:
567
                    $this->Uset($key);
568
            }
569
            unset($fld[$key]);
570
        }
571
572
        if (!empty($this->set)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
573
            if ($this->newDoc) {
574
                $SQL = "INSERT into {$this->makeTable('site_content')} SET " . implode(', ', $this->set);
575
            } else {
576
                $SQL = "UPDATE {$this->makeTable('site_content')} SET " . implode(', ',
577
                        $this->set) . " WHERE `id` = " . $this->id;
578
            }
579
            $this->query($SQL);
580
581
            if ($this->newDoc) {
582
                $this->id = $this->modx->db->getInsertId();
583
            }
584
585
            if ($parent > 0) {
586
                $this->query("UPDATE {$this->makeTable('site_content')} SET `isfolder`='1' WHERE `id`='{$parent}'");
587
            }
588
        }
589
590
        $_deleteTVs = $_insertTVs = array();
591
        foreach ($fld as $key => $value) {
592
            if (empty($this->tv[$key]) || !$this->isChanged($key) || !$this->belongsToTemplate($this->tv[$key])) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
593
                continue;
594
            } elseif ($value === '') {
595
                $_deleteTVs[] = $this->tv[$key];
596
            } else {
597
                $_insertTVs[$this->tv[$key]] = $this->escape($value);
598
            }
599
        }
600
601
        if (!empty($_insertTVs)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
602
            $values = array();
603
            foreach ($_insertTVs as $id => $value) {
604
                $values[] = "({$this->id}, {$id}, '{$value}')";
605
            }
606
            $values = implode(',', $values);
607
            $this->query("INSERT INTO {$this->makeTable('site_tmplvar_contentvalues')} (`contentid`,`tmplvarid`,`value`) VALUES {$values} ON DUPLICATE KEY UPDATE
608
    `value` = VALUES(`value`)");
609
        }
610
611
        if (!empty($_deleteTVs)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
612
            $ids = implode(',', $_deleteTVs);
613
            $this->query("DELETE FROM {$this->makeTable('site_tmplvar_contentvalues')} WHERE `contentid` = '{$this->id}' AND `tmplvarid` IN ({$ids})");
614
        }
615
616
        if (!isset($this->mode)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
617
            $this->mode = $this->newDoc ? "new" : "upd";
618
            $this->newDoc = false;
619
        }
620
621
        if (!empty($this->groupIds)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
622
            $this->setDocumentGroups($this->id, $this->groupIds);
623
        }
624
        $this->invokeEvent('OnDocFormSave', array(
625
            'mode'   => $this->mode,
626
            'id'     => isset($this->id) ? $this->id : '',
627
            'doc'    => $this->toArray(),
628
            'docObj' => $this
629
        ), $fire_events);
630
631
        if ($clearCache) {
632
            $this->clearCache($fire_events);
633
        }
634
        $this->decodeFields();
635
636
        return $this->id;
637
    }
638
639
    /**
640
     * @param $tvId
641
     * @return bool
642
     */
643
    protected function belongsToTemplate($tvId)
644
    {
645
        $template = $this->get('template');
646
647
        return isset($this->tvTpl[$template]) && in_array($tvId, $this->tvTpl[$template]);
648
    }
649
650
    /**
651
     * @param $ids
652
     * @return $this
653
     * @throws Exception
654
     */
655
    public function toTrash($ids)
656
    {
657
        $ignore = $this->systemID();
658
        $_ids = $this->cleanIDs($ids, ',', $ignore);
659
        if (is_array($_ids) && $_ids != array()) {
660
            $id = $this->sanitarIn($_ids);
661
            $uid = (int)$this->modx->getLoginUserId();
662
            $deletedon = time() + $this->modxConfig('server_offset_time');
663
            $this->query("UPDATE {$this->makeTable('site_content')} SET `deleted`=1, `deletedby`={$uid}, `deletedon`={$deletedon} WHERE `id` IN ({$id})");
664
        } else {
665
            throw new Exception('Invalid IDs list for mark trash: <pre>' . print_r($ids,
666
                    1) . '</pre> please, check ignore list: <pre>' . print_r($ignore, 1) . '</pre>');
667
        }
668
669
        return $this;
670
    }
671
672
    /**
673
     * @param bool $fire_events
674
     * @return $this
675
     */
676
    public function clearTrash($fire_events = false)
677
    {
678
        $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `deleted`='1'");
679
        $_ids = $this->modx->db->getColumn('id', $q);
680
        if (is_array($_ids) && $_ids != array()) {
681
            $this->invokeEvent('OnBeforeEmptyTrash', array(
682
                "ids" => $_ids
683
            ), $fire_events);
684
685
            $id = $this->sanitarIn($_ids);
686
            $this->query("DELETE from {$this->makeTable('site_content')} where `id` IN ({$id})");
687
            $this->query("DELETE from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid` IN ({$id})");
688
689
            $this->invokeEvent('OnEmptyTrash', array(
690
                "ids" => $_ids
691
            ), $fire_events);
692
        }
693
694
        return $this;
695
    }
696
697
    /**
698
     * @param $ids
699
     * @param int|bool $depth
700
     * @return array
701
     */
702
    public function children($ids, $depth)
703
    {
704
        $_ids = $this->cleanIDs($ids, ',');
705
        if (is_array($_ids) && $_ids != array()) {
706
            $id = $this->sanitarIn($_ids);
707
            if (!empty($id)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
708
                $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} where `parent` IN ({$id})");
709
                $id = $this->modx->db->getColumn('id', $q);
710
                if ($depth > 0 || $depth === true) {
711
                    $id = $this->children($id, is_bool($depth) ? $depth : ($depth - 1));
712
                }
713
                $_ids = array_merge($_ids, $id);
714
            }
715
        }
716
717
        return $_ids;
718
    }
719
720
    /**
721
     * @param string|array $ids
722
     * @param bool $fire_events
723
     * @return $this
724
     * @throws Exception
725
     */
726
    public function delete($ids, $fire_events = false)
727
    {
728
        $ids = $this->children($ids, true);
729
        $_ids = $this->cleanIDs($ids, ',', $this->systemID());
730
        $this->invokeEvent('OnBeforeDocFormDelete', array(
731
            'ids' => $_ids
732
        ), $fire_events);
733
        $this->toTrash($_ids);
734
        $this->invokeEvent('OnDocFormDelete', array(
735
            'ids' => $_ids
736
        ), $fire_events);
737
738
        return $this;
739
    }
740
741
    /**
742
     * @return array
743
     */
744
    private function systemID()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
745
    {
746
        $ignore = array(
747
            0, //empty document
748
            (int)$this->modxConfig('site_start'),
749
            (int)$this->modxConfig('error_page'),
750
            (int)$this->modxConfig('unauthorized_page'),
751
            (int)$this->modxConfig('site_unavailable_page')
752
        );
753
        $data = $this->query("SELECT DISTINCT setting_value FROM {$this->makeTable('web_user_settings')} WHERE `setting_name`='login_home' AND `setting_value`!=''");
754
        $data = $this->modx->db->makeArray($data);
755
        foreach ($data as $item) {
756
            $ignore[] = (int)$item['setting_value'];
757
        }
758
759
        return array_unique($ignore);
760
761
    }
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
762
763
    /**
764
     * @param $alias
765
     * @return string
766
     */
767
    protected function checkAlias($alias)
768
    {
769
        $alias = strtolower($alias);
770
        if ($this->modxConfig('friendly_urls')) {
771
            $_alias = $this->escape($alias);
772
            if ((!$this->modxConfig('allow_duplicate_alias') && !$this->modxConfig('use_alias_path')) || ($this->modxConfig('allow_duplicate_alias') && $this->modxConfig('use_alias_path'))) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
773
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' AND `parent`={$this->get('parent')} LIMIT 1"));
774
            } else {
775
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' LIMIT 1"));
776
            }
777
            if (($flag && $this->newDoc) || (!$this->newDoc && $flag && $this->id != $flag)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
778
                $suffix = substr($alias, -2);
779
                if (preg_match('/-(\d+)/', $suffix, $tmp) && isset($tmp[1]) && (int)$tmp[1] > 1) {
780
                    $suffix = (int)$tmp[1] + 1;
781
                    $alias = substr($alias, 0, -2) . '-' . $suffix;
782
                } else {
783
                    $alias .= '-2';
784
                }
785
                $alias = $this->checkAlias($alias);
786
            }
787
        }
788
789
        return $alias;
790
    }
791
792
    /**
793
     * @param $key
794
     * @return bool
795
     */
796
    public function issetField($key)
797
    {
798
        return (array_key_exists($key, $this->default_field) || array_key_exists($key, $this->tv));
799
    }
800
801
    /**
802
     * @param bool $reload
803
     * @return $this
804
     */
805
    protected function get_TV($reload = false)
0 ignored issues
show
Coding Style introduced by
Method name "modResource::get_TV" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
806
    {
807
        $this->modx->_TVnames = $this->loadFromCache('_TVnames');
808
        if ($this->modx->_TVnames === false || empty($this->modx->_TVnames) || $reload) {
809
            $this->modx->_TVnames = array();
810
            $result = $this->query('SELECT `id`,`name`,`default_text`,`type` FROM ' . $this->makeTable('site_tmplvars'));
811
            while ($row = $this->modx->db->GetRow($result)) {
812
                $this->modx->_TVnames[$row['name']] = array(
813
                    "id"      => $row['id'],
814
                    "type"    => $row['type'],
815
                    "default" => $row['default_text']
816
                );
817
            }
818
            $this->saveToCache($this->modx->_TVnames, '_TVnames');
819
        }
820
        $arrayTypes = array('checkbox', 'listbox-multiple');
821
        $arrayTVs = array();
822
        foreach ($this->modx->_TVnames as $name => $data) {
823
            $this->tvid[$data['id']] = $name;
824
            $this->tv[$name] = $data['id'];
825
            if (in_array($data['type'], $arrayTypes)) {
826
                $arrayTVs[] = $name;
827
            }
828
        }
829
        if (empty($this->tvaFields)) {
830
            $this->tvaFields = $arrayTVs;
831
        }
832
        $this->loadTVTemplate()->loadTVDefault(array_values($this->tv));
833
834
        return $this;
835
    }
836
837
    /**
838
     * @return $this
839
     */
840
    protected function loadTVTemplate()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
841
    {
842
        $this->tvTpl = $this->loadFromCache('_tvTpl');
843
        if ($this->tvTpl === false) {
844
            $q = $this->query("SELECT `tmplvarid`, `templateid` FROM " . $this->makeTable('site_tmplvar_templates'));
845
            $this->tvTpl = array();
846
            while ($item = $this->modx->db->getRow($q)) {
847
                $this->tvTpl[$item['templateid']][] = $item['tmplvarid'];
848
            }
849
            $this->saveToCache($this->tvTpl, '_tvTpl');
850
        }
851
852
        return $this;
853
    }
854
855
    /**
856
     * @param array $tvId
857
     * @return $this
858
     */
859
    protected function loadTVDefault(array $tvId = array())
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
860
    {
861
        if (is_array($tvId) && !empty($tvId)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
862
            $this->tvd = array();
863
            foreach ($tvId as $id) {
864
                $name = $this->tvid[$id];
865
                $this->tvd[$name] = $this->modx->_TVnames[$name]['default'];
866
            }
867
        }
868
869
        return $this;
870
    }
871
872
    /**
873
     * @param $tpl
874
     * @return int
875
     * @throws Exception
876
     */
877
    public function setTemplate($tpl)
878
    {
879
        if (!is_numeric($tpl) || $tpl != (int)$tpl) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
880
            if (is_scalar($tpl)) {
881
                $sql = "SELECT `id` FROM {$this->makeTable('site_templates')} WHERE `templatename` = '" . $this->escape($tpl) . "'";
882
                $rs = $this->query($sql);
883
                if (!$rs || $this->modx->db->getRecordCount($rs) <= 0) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
884
                    throw new Exception("Template {$tpl} is not exists");
885
                }
886
                $tpl = $this->modx->db->getValue($rs);
887
            } else {
888
                throw new Exception("Invalid template name: " . print_r($tpl, 1));
889
            }
890
        }
891
892
        return (int)$tpl;
893
    }
894
895
    /**
896
     * @return string
897
     */
898
    protected function getAlias()
899
    {
900
        if ($this->modxConfig('friendly_urls') && $this->modxConfig('automatic_alias') && $this->get('alias') == '') {
901
            $alias = strtr($this->get('pagetitle'), $this->table);
902
        } else {
903
            if ($this->get('alias') != '') {
904
                $alias = $this->get('alias');
905
            } else {
906
                $alias = '';
907
            }
908
        }
909
        $alias = $this->modx->stripAlias($alias);
910
911
        return $this->checkAlias($alias);
912
    }
913
914
    /**
915
     * @param int $parent
916
     * @param string $criteria
917
     * @param string $dir
918
     * @return $this
919
     *
920
     * Пересчет menuindex по полю таблицы site_content
921
     */
922
    public function updateMenuindex($parent, $criteria = 'id', $dir = 'asc')
923
    {
924
        $dir = strtolower($dir) == 'desc' ? 'desc' : 'asc';
925
        if (is_integer($parent) && $criteria !== '') {
926
            $this->query("SET @index := 0");
927
            $this->query("UPDATE {$this->makeTable('site_content')} SET `menuindex` = (@index := @index + 1) WHERE `parent`={$parent} ORDER BY {$criteria} {$dir}");
928
        }
929
930
        return $this;
931
    }
932
933
    /**
934
     * Устанавливает значение шаблона согласно системной настройке
935
     *
936
     * @return $this
937
     */
938
    public function setDefaultTemplate()
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
939
    {
940
        $parent = $this->get('parent');
941
        $template = $this->modxConfig('default_template');
942
        switch ($this->modxConfig('auto_template_logic')) {
943
            case 'sibling':
944
                if (!$parent) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
945
                    $site_start = $this->modxConfig('site_start');
946
                    $where = "sc.isfolder=0 AND sc.id!={$site_start}";
947
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', $where, 'menuindex', 'ASC', 1);
948
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
949
                        $template = $sibl[0]['template'];
950
                    }
951
                } else {
952
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', 'isfolder=0', 'menuindex',
953
                        'ASC', 1);
954
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
955
                        $template = $sibl[0]['template'];
956
                    } else {
957
                        $sibl = $this->modx->getDocumentChildren($parent, 0, 0, 'template', 'isfolder=0', 'menuindex',
958
                            'ASC', 1);
959
                        if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
960
                            $template = $sibl[0]['template'];
961
                        }
962
                    }
963
                }
964
                break;
965
            case 'parent':
966
                if ($parent) {
967
                    $_parent = $this->modx->getPageInfo($parent, 0, 'template');
968
                    if (isset($_parent['template'])) {
969
                        $template = $_parent['template'];
970
                    }
971
                }
972
                break;
973
        }
974
        $this->set('template', $template);
975
976
        return $this;
977
    }
978
979
    /**
980
     * Декодирует конкретное поле
981
     * @param  string $field Имя поля
982
     * @param  bool $store обновить распакованное поле
983
     * @return array ассоциативный массив с данными из json строки
984
     */
985
    public function decodeField($field, $store = false)
986
    {
987
        $out = array();
988
        if ($this->isDecodableField($field)) {
989
            $data = $this->get($field);
990
            if ($this->isTVarrayField($field)) {
991
                $out = explode('||', $data);
992
            } else {
993
                $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
994
            }
995
        }
996
        if ($store) {
997
            $this->field[$field] = $out;
998
            $this->markAsDecode($field);
999
        }
1000
1001
        return $out;
1002
    }
1003
1004
    /**
1005
     * Запаковывает конкретное поле в JSON
1006
     * @param  string $field Имя поля
1007
     * @param  bool $store обновить запакованное поле
1008
     * @return string|null json строка
1009
     */
1010
    public function encodeField($field, $store = false)
1011
    {
1012
        $out = null;
1013
        if ($this->isEncodableField($field)) {
1014
            $data = $this->get($field);
1015
            if ($this->isTVarrayField($field)) {
1016
                $out = is_array($data) ? implode('||', $data) : (string)$data;
1017
            } else {
1018
                $out = json_encode($data);
1019
            }
1020
        }
1021
        if ($store) {
1022
            $this->field[$field] = $out;
1023
            $this->markAsEncode($field);
1024
        }
1025
1026
        return $out;
1027
    }
1028
1029
    /**
1030
     * Может ли содержать данное поле json массив
1031
     * @param  string $field имя поля
1032
     * @return boolean
1033
     */
1034
    public function isTVarrayField($field)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1035
    {
1036
        return (is_scalar($field) && in_array($field, $this->tvaFields));
1037
    }
1038
1039
    /**
1040
     * Пометить все поля как запакованные
1041
     * @return $this
1042
     */
1043
    public function markAllEncode()
1044
    {
1045
        parent::markAllEncode();
1046
        foreach ($this->tvaFields as $field) {
1047
            $this->markAsEncode($field);
1048
        }
1049
1050
        return $this;
1051
    }
1052
1053
    /**
1054
     * Пометить все поля как распакованные
1055
     * @return $this
1056
     */
1057
    public function markAllDecode()
1058
    {
1059
        parent::markAllDecode();
1060
        foreach ($this->tvaFields as $field) {
1061
            $this->markAsDecode($field);
1062
        }
1063
1064
        return $this;
1065
    }
1066
1067
    /**
1068
     * @param int $docId
1069
     */
1070
    public function getDocumentGroups($docId = 0)
1071
    {
1072
        $out = array();
1073
        $doc = $this->switchObject($docId);
1074
        if (null !== $doc->getID()) {
1075
            $doc_groups = $this->makeTable('document_groups');
1076
            $docgroup_names = $this->makeTable('documentgroup_names');
1077
1078
            $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`
1079
                WHERE `dg`.`document` = " . $doc->getID());
1080
            while ($row = $this->modx->db->getRow($rs)) {
1081
                $out[$row['document_group']] = $row['name'];
1082
            }
1083
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1084
        }
1085
        unset($doc);
1086
1087
        return $out;
1088
    }
1089
1090
    /**
1091
     * @param int $docId
1092
     * @param array $groupIds
1093
     * @return $this
1094
     */
1095
    public function setDocumentGroups($docId = 0, $groupIds = array())
1096
    {
1097
        if (!is_array($groupIds)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1098
            return $this;
1099
        }
1100
        if ($this->newDoc && $docId == 0) {
1101
            $this->groupIds = $groupIds;
1102
        } else {
1103
            $doc = $this->switchObject($docId);
1104
            if ($id = $doc->getID()) {
1105
                foreach ($groupIds as $gid) {
1106
                    $this->query("REPLACE INTO {$this->makeTable('document_groups')} (`document_group`, `document`) VALUES ('{$gid}', '{$id}')");
1107
                }
1108
                if (!$this->newDoc) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1109
                    $groupIds = empty($groupIds) ? '0' : implode(',', $groupIds);
1110
                    $this->query("DELETE FROM {$this->makeTable('document_groups')} WHERE `document`={$id} AND `document_group` NOT IN ({$groupIds})");
1111
                }
1112
            }
1113
            unset($doc);
1114
            $this->groupIds = array();
1115
        }
1116
1117
        return $this;
1118
    }
1119
}
1120
=======
1121
<?php
1122
require_once('MODx.php');
1123
1124
/**
1125
 * Class modResource
1126
 */
1127
class modResource extends MODxAPI
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
1128
{
1129
    /**
1130
     * @var string
1131
     */
1132
    protected $mode = 'new';
1133
    /**
1134
     * @var array
1135
     */
1136
    protected $default_field = array(
1137
        'type'            => 'document',
1138
        'contentType'     => 'text/html',
1139
        'pagetitle'       => 'New document',
1140
        'longtitle'       => '',
1141
        'description'     => '',
1142
        'alias'           => '',
1143
        'link_attributes' => '',
1144
        'published'       => 1,
1145
        'pub_date'        => 0,
1146
        'unpub_date'      => 0,
1147
        'parent'          => 0,
1148
        'isfolder'        => 0,
1149
        'introtext'       => '',
1150
        'content'         => '',
1151
        'richtext'        => 1,
1152
        'template'        => 0,
1153
        'menuindex'       => 0,
1154
        'searchable'      => 1,
1155
        'cacheable'       => 1,
1156
        'createdon'       => 0,
1157
        'createdby'       => 0,
1158
        'editedon'        => 0,
1159
        'editedby'        => 0,
1160
        'deleted'         => 0,
1161
        'deletedon'       => 0,
1162
        'deletedby'       => 0,
1163
        'publishedon'     => 0,
1164
        'publishedby'     => 0,
1165
        'menutitle'       => '',
1166
        'donthit'         => 0,
1167
        'privateweb'      => 0,
1168
        'privatemgr'      => 0,
1169
        'content_dispo'   => 0,
1170
        'hidemenu'        => 0,
1171
        'alias_visible'   => 1
1172
    );
1173
    /**
1174
     * @var array
1175
     */
1176
    private $table = array(
1177
        '"' => '_',
1178
        "'" => '_',
1179
        ' ' => '_',
1180
        '.' => '_',
1181
        ',' => '_',
1182
        'а' => 'a',
1183
        'б' => 'b',
1184
        'в' => 'v',
1185
        'г' => 'g',
1186
        'д' => 'd',
1187
        'е' => 'e',
1188
        'ё' => 'e',
1189
        'ж' => 'zh',
1190
        'з' => 'z',
1191
        'и' => 'i',
1192
        'й' => 'y',
1193
        'к' => 'k',
1194
        'л' => 'l',
1195
        'м' => 'm',
1196
        'н' => 'n',
1197
        'о' => 'o',
1198
        'п' => 'p',
1199
        'р' => 'r',
1200
        'с' => 's',
1201
        'т' => 't',
1202
        'у' => 'u',
1203
        'ф' => 'f',
1204
        'х' => 'h',
1205
        'ц' => 'c',
1206
        'ч' => 'ch',
1207
        'ш' => 'sh',
1208
        'щ' => 'sch',
1209
        'ь' => '',
1210
        'ы' => 'y',
1211
        'ъ' => '',
1212
        'э' => 'e',
1213
        'ю' => 'yu',
1214
        'я' => 'ya',
1215
        'А' => 'A',
1216
        'Б' => 'B',
1217
        'В' => 'V',
1218
        'Г' => 'G',
1219
        'Д' => 'D',
1220
        'Е' => 'E',
1221
        'Ё' => 'E',
1222
        'Ж' => 'Zh',
1223
        'З' => 'Z',
1224
        'И' => 'I',
1225
        'Й' => 'Y',
1226
        'К' => 'K',
1227
        'Л' => 'L',
1228
        'М' => 'M',
1229
        'Н' => 'N',
1230
        'О' => 'O',
1231
        'П' => 'P',
1232
        'Р' => 'R',
1233
        'С' => 'S',
1234
        'Т' => 'T',
1235
        'У' => 'U',
1236
        'Ф' => 'F',
1237
        'Х' => 'H',
1238
        'Ц' => 'C',
1239
        'Ч' => 'Ch',
1240
        'Ш' => 'Sh',
1241
        'Щ' => 'Sch',
1242
        'Ь' => '',
1243
        'Ы' => 'Y',
1244
        'Ъ' => '',
1245
        'Э' => 'E',
1246
        'Ю' => 'Yu',
1247
        'Я' => 'Ya',
1248
    );
1249
    /**
1250
     * @var array массив ТВшек где name это ключ массива, а ID это значение
1251
     */
1252
    private $tv = array();
1253
    /**
1254
     * @var array массив ТВшек где ID это ключ массива, а name это значение
1255
     */
1256
    private $tvid = array();
1257
    /**
1258
     * @var array значения по умолчанию для ТВ параметров
1259
     */
1260
    private $tvd = array();
1261
1262
    /** @var array связи ТВ и шаблонов */
1263
    private $tvTpl = array();
1264
1265
    /** @var array параметры ТВ с массивами */
1266
    protected $tvaFields = array();
1267
1268
    /**
1269
     * Массив администраторов
1270
     * @var DLCollection
1271
     */
1272
    private $managerUsers = null;
1273
    /** @var array группы документов */
1274
    protected $groupIds = array();
1275
1276
    /**
1277
     * modResource constructor.
1278
     * @param DocumentParser $modx
1279
     * @param bool $debug
1280
     */
1281
    public function __construct($modx, $debug = false)
1282
    {
1283
        parent::__construct($modx, $debug);
1284
        $this->get_TV();
1285
        $uTable = $this->makeTable("manager_users");
1286
        $aTable = $this->makeTable("user_attributes");
1287
        $query = "SELECT `u`.`id`, `a`.`email`, `u`.`username`  FROM " . $aTable . " as `a` LEFT JOIN " . $uTable . " as `u` ON `u`.`id`=`a`.`internalKey`";
1288
        $query = $this->query($query);
1289
        $this->managerUsers = new DLCollection($modx, empty($query) ? array() : $query);
1290
    }
1291
1292
    /**
1293
     * @return array
1294
     */
1295
    public function toArrayMain()
1296
    {
1297
        $out = array_intersect_key(parent::toArray(), $this->default_field);
1298
1299
        return $out;
1300
    }
1301
1302
    /**
1303
     * @param bool $render
1304
     * @return array
1305
     */
1306
    public function toArrayTV($render = false)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1307
    {
1308
        $out = array_diff_key(parent::toArray(), $this->default_field);
1309
        $tpl = $this->get('template');
1310
        $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
1311
        foreach ($tvTPL as $item) {
1312
            if (isset($this->tvid[$item]) && !array_key_exists($this->tvid[$item], $out)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1313
                $value = $this->get($this->tvid[$item]);
1314
                $out[$this->tvid[$item]] = empty($value) ? $this->tvd[$this->tvid[$item]] : $value;
1315
            }
1316
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1317
        }
1318
        if ($render) {
1319
            foreach ($out as $key => $val) {
1320
                $out[$key] = $this->renderTV($key);
1321
            }
1322
        }
1323
1324
        return $out;
1325
    }
1326
1327
    /**
1328
     * @param string $prefix
1329
     * @param string $suffix
1330
     * @param string $sep
1331
     * @param bool $render
1332
     * @return array
1333
     */
1334
    public function toArray($prefix = '', $suffix = '', $sep = '_', $render = true)
1335
    {
1336
        $out = array_merge(
1337
            $this->toArrayMain(),
1338
            $this->toArrayTV($render),
1339
            array($this->fieldPKName() => $this->getID())
1340
        );
1341
1342
        return \APIhelpers::renameKeyArr($out, $prefix, $suffix, $sep);
1343
    }
1344
1345
    /**
1346
     * @return null|string
1347
     */
1348
    public function getUrl()
1349
    {
1350
        $out = null;
1351
        $id = (int)$this->getID();
1352
        if (!empty($id)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1353
            $out = $this->modx->makeUrl($id);
1354
        }
1355
1356
        return $out;
1357
    }
1358
1359
    /**
1360
     * @param string $main
1361
     * @param string $second
1362
     * @return mixed
1363
     */
1364
    public function getTitle($main = 'menutitle', $second = 'pagetitle')
1365
    {
1366
        $title = $this->get($main);
1367
        if (empty($title) && $title !== '0') {
1368
            $title = $this->get($second);
1369
        }
1370
1371
        return $title;
1372
    }
1373
1374
    /**
1375
     * @return bool
1376
     */
1377
    public function isWebShow()
1378
    {
1379
        $pub = ($this->get('publishedon') < time() && $this->get('published'));
1380
        $unpub = ($this->get('unpub_date') == 0 || $this->get('unpub_date') > time());
1381
        $del = ($this->get('deleted') == 0 && ($this->get('deletedon') == 0 || $this->get('deletedon') > time()));
1382
1383
        return ($pub && $unpub && $del);
1384
    }
1385
1386
    /**
1387
     * @return $this
1388
     */
1389
    public function touch()
1390
    {
1391
        $this->set('editedon', time());
1392
1393
        return $this;
1394
    }
1395
1396
    /**
1397
     * @param $tvname
1398
     * @return null|string
1399
     */
1400
    public function renderTV($tvname)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1401
    {
1402
        $out = null;
1403
        if ($this->getID() > 0) {
1404
            include_once MODX_MANAGER_PATH . "includes/tmplvars.format.inc.php";
1405
            include_once MODX_MANAGER_PATH . "includes/tmplvars.commands.inc.php";
1406
            $tvval = $this->get($tvname);
1407
            if ($this->isTVarrayField($tvname) && is_array($tvval)) {
1408
                $tvval = implode('||', $tvval);
1409
            }
1410
            $param = APIHelpers::getkey($this->tvd, $tvname, array());
1411
            $display = APIHelpers::getkey($param, 'display', '');
1412
            $display_params = APIHelpers::getkey($param, 'display_params', '');
1413
            $type = APIHelpers::getkey($param, 'type', '');
1414
            $out = getTVDisplayFormat($tvname, $tvval, $display, $display_params, $type, $this->getID(), '');
1415
        }
1416
1417
        return $out;
1418
    }
1419
1420
    /**
1421
     * @param $key
1422
     * @return mixed
1423
     */
1424
    public function get($key)
1425
    {
1426
        $out = parent::get($key);
1427
        if (isset($this->tv[$key])) {
1428
            $tpl = $this->get('template');
1429
            $tvTPL = APIHelpers::getkey($this->tvTpl, $tpl, array());
1430
            $tvID = APIHelpers::getkey($this->tv, $key, 0);
1431
            if (in_array($tvID, $tvTPL) && is_null($out)) {
1432
                $out = APIHelpers::getkey($this->tvd, $key, null);
1433
            }
1434
        }
1435
1436
        return $out;
1437
    }
1438
1439
    /**
1440
     * @param $key
1441
     * @param $value
1442
     * @return $this
1443
     */
1444
    public function set($key, $value)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (4) exceeds 3; consider refactoring the function
Loading history...
1445
    {
1446
        if ((is_scalar($value) || $this->isTVarrayField($key) || $this->isJsonField($key)) && is_scalar($key) && !empty($key)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1447
            switch ($key) {
1448
                case 'parent':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
1449
                    $value = (int)$value;
1450
                    break;
1451
                case 'template':
1452
                    $value = trim($value);
1453
                    $value = $this->setTemplate($value);
1454
                    break;
1455
                case 'published':
1456
                    $value = (int)((bool)$value);
1457
                    if ($value) {
1458
                        $this->field['publishedon'] = time() + $this->modxConfig('server_offset_time');
1459
                    }
1460
                    break;
1461
                case 'pub_date':
1462
                    $value = $this->getTime($value);
1463
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
1464
                        $this->field['published'] = 1;
1465
                        $this->field['publishedon'] = $value;
1466
                    }
1467
                    break;
1468
                case 'unpub_date':
1469
                    $value = $this->getTime($value);
1470
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') > $value) {
1471
                        $this->field['published'] = 0;
1472
                        $this->field['publishedon'] = 0;
1473
                    }
1474
                    break;
1475
                case 'deleted':
1476
                    $value = (int)((bool)$value);
1477
                    if ($value) {
1478
                        $this->field['deletedon'] = time() + $this->modxConfig('server_offset_time');
1479
                    } else {
1480
                        $this->field['deletedon'] = 0;
1481
                    }
1482
                    break;
1483
                case 'deletedon':
1484
                    $value = $this->getTime($value);
1485
                    if ($value > 0 && time() + $this->modxConfig('server_offset_time') < $value) {
1486
                        $value = 0;
1487
                    }
1488
                    if ($value) {
1489
                        $this->field['deleted'] = 1;
1490
                    }
1491
                    break;
1492
                case 'editedon':
1493
                case 'createdon':
1494
                case 'publishedon':
1495
                    $value = $this->getTime($value);
1496
                    break;
1497
                case 'publishedby':
1498
                case 'editedby':
1499
                case 'createdby':
1500
                case 'deletedby':
1501
                    $value = $this->getUser($value, $this->default_field[$key]);
1502
                    break;
1503
            }
1504
            $this->field[$key] = $value;
1505
        }
1506
1507
        return $this;
1508
    }
1509
1510
    /**
1511
     * @param $value
1512
     * @param int $default
1513
     * @return int|mixed
1514
     */
1515
    protected function getUser($value, $default = 0)
1516
    {
1517
        $currentAdmin = APIHelpers::getkey($_SESSION, 'mgrInternalKey', 0);
1518
        $value = (int)$value;
1519
        if (!empty($value)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1520
            $by = $this->findUserBy($value);
1521
            $exists = $this->managerUsers->exists(function ($key, Helpers\Collection $val) use ($by, $value) {
1522
                return ($val->containsKey($by) && $val->get($by) === (string)$value);
1523
            });
1524
            if (!$exists) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1525
                $value = 0;
1526
            }
1527
        }
1528
        if (empty($value)) {
1529
            $value = empty($currentAdmin) ? $default : $currentAdmin;
1530
        }
1531
1532
        return $value;
1533
    }
1534
1535
    /**
1536
     * @param $data
1537
     * @return bool|string
1538
     */
1539
    protected function findUserBy($data)
1540
    {
1541
        switch (true) {
1542
            case (is_int($data) || ((int)$data > 0 && (string)intval($data) === $data)):
1543
                $find = 'id';
1544
                break;
1545
            case filter_var($data, FILTER_VALIDATE_EMAIL):
1546
                $find = 'email';
1547
                break;
1548
            case is_scalar($data):
1549
                $find = 'username';
1550
                break;
1551
            default:
1552
                $find = false;
1553
        }
1554
1555
        return $find;
1556
    }
1557
1558
    /**
1559
     * @param array $data
1560
     * @return $this
1561
     */
1562
    public function create($data = array())
1563
    {
1564
        $this->close();
1565
        $fld = array();
1566
        foreach ($this->tvd as $name => $tv) {
1567
            $fld[$name] = $tv['value'];
1568
        };
1569
        $this->store($fld);
1570
1571
        $this->fromArray(array_merge($fld, $data));
1572
        $this->set('createdby', null)
1573
            ->set('editedby', null)
1574
            ->set('createdon', time())
1575
            ->touch();
1576
1577
        return $this;
1578
    }
1579
1580
    /**
1581
     * @param $id
1582
     * @return $this
1583
     */
1584
    public function edit($id)
1585
    {
1586
        $id = is_scalar($id) ? trim($id) : '';
1587
        if ($this->getID() != $id) {
1588
            $this->close();
1589
            $this->markAllEncode();
1590
            $this->newDoc = false;
1591
1592
            $result = $this->query("SELECT * from {$this->makeTable('site_content')} where `id`=" . (int)$id);
1593
            $this->fromArray($this->modx->db->getRow($result));
1594
            $result = $this->query("SELECT * from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid`=" . (int)$id);
1595
            while ($row = $this->modx->db->getRow($result)) {
1596
                $this->field[$this->tvid[$row['tmplvarid']]] = $row['value'];
1597
            }
1598
            if (empty($this->field['id'])) {
1599
                $this->id = null;
1600
            } else {
1601
                $this->id = $this->field['id'];
1602
                $this->set('editedby', null)->touch();
1603
                $this->decodeFields();
1604
            }
1605
            $this->store($this->toArray(null, null, null, false));
1606
            unset($this->field['id']);
1607
        }
1608
1609
        return $this;
1610
    }
1611
1612
    /**
1613
     * @param bool $fire_events
1614
     * @param bool $clearCache
1615
     * @return bool|null
1616
     */
1617
    public function save($fire_events = false, $clearCache = false)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
1618
    {
1619
        $parent = null;
1620
        if ($this->field['pagetitle'] == '') {
1621
            $this->log['emptyPagetitle'] = 'Pagetitle is empty in <pre>' . print_r($this->field, true) . '</pre>';
1622
1623
            return false;
1624
        }
1625
1626
        $uid = $this->modx->getLoginUserID('mgr');
1627
1628
        if (
1629
            $this->field['parent'] == 0 &&
1630
            !$this->modxConfig('udperms_allowroot') &&
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1631
            !($uid && isset($_SESSION['mgrRole']) && $_SESSION['mgrRole'] == 1)
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1632
        ) {
1633
            $this->log['rootForbidden'] = 'Only Administrators can create documents in the root folder because udperms_allowroot setting is off';
1634
1635
            return false;
1636
        }
1637
1638
        $this->set('alias', $this->getAlias());
1639
1640
        $this->invokeEvent('OnBeforeDocFormSave', array(
1641
            'mode'   => $this->newDoc ? "new" : "upd",
1642
            'id'     => isset($this->id) ? $this->id : '',
1643
            'doc'    => $this->toArray(),
1644
            'docObj' => $this
1645
        ), $fire_events);
1646
1647
        $fld = $this->encodeFields()->toArray(null, null, null, false);
1648
        foreach ($this->default_field as $key => $value) {
1649
            $tmp = $this->get($key);
1650
            if ($this->newDoc && (!is_int($tmp) && $tmp == '')) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1651
                if ($tmp == $value) {
1652
                    switch ($key) {
1653
                        case 'cacheable':
1654
                            $value = $this->modxConfig('cache_default');
1655
                            break;
1656
                        case 'template':
1657
                            $value = $value = $this->modxConfig('default_template');
1658
                            break;
1659
                        case 'published':
1660
                            $value = $this->modxConfig('publish_default');
1661
                            break;
1662
                        case 'searchable':
1663
                            $value = $this->modxConfig('search_default');
1664
                            break;
1665
                        case 'donthit':
1666
                            $value = $this->modxConfig('track_visitors');
1667
                            break;
1668
                    }
1669
                }
1670
                $this->field[$key] = $value;
1671
            }
1672
            switch (true) {
1673
                case $key == 'parent':
1674
                    $parent = (int)$this->get($key);
1675
                    $q = $this->query("SELECT count(`id`) FROM {$this->makeTable('site_content')} WHERE `id`='{$parent}'");
1676
                    if ($this->modx->db->getValue($q) != 1) {
1677
                        $parent = 0;
1678
                    }
1679
                    $this->field[$key] = $parent;
1680
                    $this->Uset($key);
1681
                    break;
1682
                case ($key == 'alias_visible' && !$this->checkVersion('1.0.10', true)):
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1683
                    $this->eraseField('alias_visible');
1684
                    break;
1685
                default:
1686
                    $this->Uset($key);
1687
            }
1688
            unset($fld[$key]);
1689
        }
1690
1691
        if (!empty($this->set)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1692
            if ($this->newDoc) {
1693
                $SQL = "INSERT into {$this->makeTable('site_content')} SET " . implode(', ', $this->set);
1694
            } else {
1695
                $SQL = "UPDATE {$this->makeTable('site_content')} SET " . implode(', ',
1696
                        $this->set) . " WHERE `id` = " . $this->id;
1697
            }
1698
            $this->query($SQL);
1699
1700
            if ($this->newDoc) {
1701
                $this->id = $this->modx->db->getInsertId();
1702
            }
1703
1704
            if ($parent > 0) {
1705
                $this->query("UPDATE {$this->makeTable('site_content')} SET `isfolder`='1' WHERE `id`='{$parent}'");
1706
            }
1707
        }
1708
1709
        $_deleteTVs = $_insertTVs = array();
1710
        foreach ($fld as $key => $value) {
1711
            if (empty($this->tv[$key]) || !$this->isChanged($key) || !$this->belongsToTemplate($this->tv[$key])) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1712
                continue;
1713
            } elseif ($value === '') {
1714
                $_deleteTVs[] = $this->tv[$key];
1715
            } else {
1716
                $_insertTVs[$this->tv[$key]] = $this->escape($value);
1717
            }
1718
        }
1719
1720
        if (!empty($_insertTVs)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1721
            $values = array();
1722
            foreach ($_insertTVs as $id => $value) {
1723
                $values[] = "({$this->id}, {$id}, '{$value}')";
1724
            }
1725
            $values = implode(',', $values);
1726
            $this->query("INSERT INTO {$this->makeTable('site_tmplvar_contentvalues')} (`contentid`,`tmplvarid`,`value`) VALUES {$values} ON DUPLICATE KEY UPDATE
1727
    `value` = VALUES(`value`)");
1728
        }
1729
1730
        if (!empty($_deleteTVs)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1731
            $ids = implode(',', $_deleteTVs);
1732
            $this->query("DELETE FROM {$this->makeTable('site_tmplvar_contentvalues')} WHERE `contentid` = '{$this->id}' AND `tmplvarid` IN ({$ids})");
1733
        }
1734
1735
        if (!isset($this->mode)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1736
            $this->mode = $this->newDoc ? "new" : "upd";
1737
            $this->newDoc = false;
1738
        }
1739
1740
        if (!empty($this->groupIds)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1741
            $this->setDocumentGroups($this->id, $this->groupIds);
1742
        }
1743
        $this->invokeEvent('OnDocFormSave', array(
1744
            'mode'   => $this->mode,
1745
            'id'     => isset($this->id) ? $this->id : '',
1746
            'doc'    => $this->toArray(),
1747
            'docObj' => $this
1748
        ), $fire_events);
1749
1750
        if ($clearCache) {
1751
            $this->clearCache($fire_events);
1752
        }
1753
        $this->decodeFields();
1754
1755
        return $this->id;
1756
    }
1757
1758
    /**
1759
     * @param $tvId
1760
     * @return bool
1761
     */
1762
    protected function belongsToTemplate($tvId)
1763
    {
1764
        $template = $this->get('template');
1765
1766
        return isset($this->tvTpl[$template]) && in_array($tvId, $this->tvTpl[$template]);
1767
    }
1768
1769
    /**
1770
     * @param $ids
1771
     * @return $this
1772
     * @throws Exception
1773
     */
1774
    public function toTrash($ids)
1775
    {
1776
        $ignore = $this->systemID();
1777
        $_ids = $this->cleanIDs($ids, ',', $ignore);
1778
        if (is_array($_ids) && $_ids != array()) {
1779
            $id = $this->sanitarIn($_ids);
1780
            $uid = (int)$this->modx->getLoginUserId();
1781
            $deletedon = time() + $this->modxConfig('server_offset_time');
1782
            $this->query("UPDATE {$this->makeTable('site_content')} SET `deleted`=1, `deletedby`={$uid}, `deletedon`={$deletedon} WHERE `id` IN ({$id})");
1783
        } else {
1784
            throw new Exception('Invalid IDs list for mark trash: <pre>' . print_r($ids,
1785
                    1) . '</pre> please, check ignore list: <pre>' . print_r($ignore, 1) . '</pre>');
1786
        }
1787
1788
        return $this;
1789
    }
1790
1791
    /**
1792
     * @param bool $fire_events
1793
     * @return $this
1794
     */
1795
    public function clearTrash($fire_events = false)
1796
    {
1797
        $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `deleted`='1'");
1798
        $_ids = $this->modx->db->getColumn('id', $q);
1799
        if (is_array($_ids) && $_ids != array()) {
1800
            $this->invokeEvent('OnBeforeEmptyTrash', array(
1801
                "ids" => $_ids
1802
            ), $fire_events);
1803
1804
            $id = $this->sanitarIn($_ids);
1805
            $this->query("DELETE from {$this->makeTable('site_content')} where `id` IN ({$id})");
1806
            $this->query("DELETE from {$this->makeTable('site_tmplvar_contentvalues')} where `contentid` IN ({$id})");
1807
1808
            $this->invokeEvent('OnEmptyTrash', array(
1809
                "ids" => $_ids
1810
            ), $fire_events);
1811
        }
1812
1813
        return $this;
1814
    }
1815
1816
    /**
1817
     * @param $ids
1818
     * @param int|bool $depth
1819
     * @return array
1820
     */
1821
    public function children($ids, $depth)
1822
    {
1823
        $_ids = $this->cleanIDs($ids, ',');
1824
        if (is_array($_ids) && $_ids != array()) {
1825
            $id = $this->sanitarIn($_ids);
1826
            if (!empty($id)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1827
                $q = $this->query("SELECT `id` FROM {$this->makeTable('site_content')} where `parent` IN ({$id})");
1828
                $id = $this->modx->db->getColumn('id', $q);
1829
                if ($depth > 0 || $depth === true) {
1830
                    $id = $this->children($id, is_bool($depth) ? $depth : ($depth - 1));
1831
                }
1832
                $_ids = array_merge($_ids, $id);
1833
            }
1834
        }
1835
1836
        return $_ids;
1837
    }
1838
1839
    /**
1840
     * @param string|array $ids
1841
     * @param bool $fire_events
1842
     * @return $this
1843
     * @throws Exception
1844
     */
1845
    public function delete($ids, $fire_events = false)
1846
    {
1847
        $ids = $this->children($ids, true);
1848
        $_ids = $this->cleanIDs($ids, ',', $this->systemID());
1849
        $this->invokeEvent('OnBeforeDocFormDelete', array(
1850
            'ids' => $_ids
1851
        ), $fire_events);
1852
        $this->toTrash($_ids);
1853
        $this->invokeEvent('OnDocFormDelete', array(
1854
            'ids' => $_ids
1855
        ), $fire_events);
1856
1857
        return $this;
1858
    }
1859
1860
    /**
1861
     * @return array
1862
     */
1863
    private function systemID()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1864
    {
1865
        $ignore = array(
1866
            0, //empty document
1867
            (int)$this->modxConfig('site_start'),
1868
            (int)$this->modxConfig('error_page'),
1869
            (int)$this->modxConfig('unauthorized_page'),
1870
            (int)$this->modxConfig('site_unavailable_page')
1871
        );
1872
        $data = $this->query("SELECT DISTINCT setting_value FROM {$this->makeTable('web_user_settings')} WHERE `setting_name`='login_home' AND `setting_value`!=''");
1873
        $data = $this->modx->db->makeArray($data);
1874
        foreach ($data as $item) {
1875
            $ignore[] = (int)$item['setting_value'];
1876
        }
1877
1878
        return array_unique($ignore);
1879
1880
    }
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
1881
1882
    /**
1883
     * @param $alias
1884
     * @return string
1885
     */
1886
    protected function checkAlias($alias)
1887
    {
1888
        $alias = strtolower($alias);
1889
        if ($this->modxConfig('friendly_urls')) {
1890
            $_alias = $this->escape($alias);
1891
            if ((!$this->modxConfig('allow_duplicate_alias') && !$this->modxConfig('use_alias_path')) || ($this->modxConfig('allow_duplicate_alias') && $this->modxConfig('use_alias_path'))) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1892
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' AND `parent`={$this->get('parent')} LIMIT 1"));
1893
            } else {
1894
                $flag = $this->modx->db->getValue($this->query("SELECT `id` FROM {$this->makeTable('site_content')} WHERE `alias`='{$_alias}' LIMIT 1"));
1895
            }
1896
            if (($flag && $this->newDoc) || (!$this->newDoc && $flag && $this->id != $flag)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1897
                $suffix = substr($alias, -2);
1898
                if (preg_match('/-(\d+)/', $suffix, $tmp) && isset($tmp[1]) && (int)$tmp[1] > 1) {
1899
                    $suffix = (int)$tmp[1] + 1;
1900
                    $alias = substr($alias, 0, -2) . '-' . $suffix;
1901
                } else {
1902
                    $alias .= '-2';
1903
                }
1904
                $alias = $this->checkAlias($alias);
1905
            }
1906
        }
1907
1908
        return $alias;
1909
    }
1910
1911
    /**
1912
     * @param $key
1913
     * @return bool
1914
     */
1915
    public function issetField($key)
1916
    {
1917
        return (array_key_exists($key, $this->default_field) || array_key_exists($key, $this->tv));
1918
    }
1919
1920
    /**
1921
     * @param bool $reload
1922
     * @return $this
1923
     */
1924
    protected function get_TV($reload = false)
0 ignored issues
show
Coding Style introduced by
Method name "modResource::get_TV" is not in camel caps format
Loading history...
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1925
    {
1926
        $this->modx->_TVnames = $this->loadFromCache('_TVnames');
1927
        if ($this->modx->_TVnames === false || empty($this->modx->_TVnames) || $reload) {
1928
            $this->modx->_TVnames = array();
1929
            $result = $this->query('SELECT `id`,`name`,`default_text`,`type` FROM ' . $this->makeTable('site_tmplvars'));
1930
            while ($row = $this->modx->db->GetRow($result)) {
1931
                $this->modx->_TVnames[$row['name']] = array(
1932
                    "id"      => $row['id'],
1933
                    "type"    => $row['type'],
1934
                    "default" => $row['default_text']
1935
                );
1936
            }
1937
            $this->saveToCache($this->modx->_TVnames, '_TVnames');
1938
        }
1939
        $arrayTypes = array('checkbox', 'listbox-multiple');
1940
        $arrayTVs = array();
1941
        foreach ($this->modx->_TVnames as $name => $data) {
1942
            $this->tvid[$data['id']] = $name;
1943
            $this->tv[$name] = $data['id'];
1944
            if (in_array($data['type'], $arrayTypes)) {
1945
                $arrayTVs[] = $name;
1946
            }
1947
        }
1948
        if (empty($this->tvaFields)) {
1949
            $this->tvaFields = $arrayTVs;
1950
        }
1951
        $this->loadTVTemplate()->loadTVDefault(array_values($this->tv));
1952
1953
        return $this;
1954
    }
1955
1956
    /**
1957
     * @return $this
1958
     */
1959
    protected function loadTVTemplate()
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1960
    {
1961
        $this->tvTpl = $this->loadFromCache('_tvTpl');
1962
        if ($this->tvTpl === false) {
1963
            $q = $this->query("SELECT `tmplvarid`, `templateid` FROM " . $this->makeTable('site_tmplvar_templates'));
1964
            $this->tvTpl = array();
1965
            while ($item = $this->modx->db->getRow($q)) {
1966
                $this->tvTpl[$item['templateid']][] = $item['tmplvarid'];
1967
            }
1968
            $this->saveToCache($this->tvTpl, '_tvTpl');
1969
        }
1970
1971
        return $this;
1972
    }
1973
1974
    /**
1975
     * @param array $tvId
1976
     * @return $this
1977
     */
1978
    protected function loadTVDefault(array $tvId = array())
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
1979
    {
1980
        if (is_array($tvId) && !empty($tvId)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1981
            $this->tvd = array();
1982
            foreach ($tvId as $id) {
1983
                $name = $this->tvid[$id];
1984
                $this->tvd[$name] = $this->modx->_TVnames[$name]['default'];
1985
            }
1986
        }
1987
1988
        return $this;
1989
    }
1990
1991
    /**
1992
     * @param $tpl
1993
     * @return int
1994
     * @throws Exception
1995
     */
1996
    public function setTemplate($tpl)
1997
    {
1998
        if (!is_numeric($tpl) || $tpl != (int)$tpl) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
1999
            if (is_scalar($tpl)) {
2000
                $sql = "SELECT `id` FROM {$this->makeTable('site_templates')} WHERE `templatename` = '" . $this->escape($tpl) . "'";
2001
                $rs = $this->query($sql);
2002
                if (!$rs || $this->modx->db->getRecordCount($rs) <= 0) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
2003
                    throw new Exception("Template {$tpl} is not exists");
2004
                }
2005
                $tpl = $this->modx->db->getValue($rs);
2006
            } else {
2007
                throw new Exception("Invalid template name: " . print_r($tpl, 1));
2008
            }
2009
        }
2010
2011
        return (int)$tpl;
2012
    }
2013
2014
    /**
2015
     * @return string
2016
     */
2017
    protected function getAlias()
2018
    {
2019
        if ($this->modxConfig('friendly_urls') && $this->modxConfig('automatic_alias') && $this->get('alias') == '') {
2020
            $alias = strtr($this->get('pagetitle'), $this->table);
2021
        } else {
2022
            if ($this->get('alias') != '') {
2023
                $alias = $this->get('alias');
2024
            } else {
2025
                $alias = '';
2026
            }
2027
        }
2028
        $alias = $this->modx->stripAlias($alias);
2029
2030
        return $this->checkAlias($alias);
2031
    }
2032
2033
    /**
2034
     * @param int $parent
2035
     * @param string $criteria
2036
     * @param string $dir
2037
     * @return $this
2038
     *
2039
     * Пересчет menuindex по полю таблицы site_content
2040
     */
2041
    public function updateMenuindex($parent, $criteria = 'id', $dir = 'asc')
2042
    {
2043
        $dir = strtolower($dir) == 'desc' ? 'desc' : 'asc';
2044
        if (is_integer($parent) && $criteria !== '') {
2045
            $this->query("SET @index := 0");
2046
            $this->query("UPDATE {$this->makeTable('site_content')} SET `menuindex` = (@index := @index + 1) WHERE `parent`={$parent} ORDER BY {$criteria} {$dir}");
2047
        }
2048
2049
        return $this;
2050
    }
2051
2052
    /**
2053
     * Устанавливает значение шаблона согласно системной настройке
2054
     *
2055
     * @return $this
2056
     */
2057
    public function setDefaultTemplate()
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
2058
    {
2059
        $parent = $this->get('parent');
2060
        $template = $this->modxConfig('default_template');
2061
        switch ($this->modxConfig('auto_template_logic')) {
2062
            case 'sibling':
2063
                if (!$parent) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
2064
                    $site_start = $this->modxConfig('site_start');
2065
                    $where = "sc.isfolder=0 AND sc.id!={$site_start}";
2066
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', $where, 'menuindex', 'ASC', 1);
2067
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
2068
                        $template = $sibl[0]['template'];
2069
                    }
2070
                } else {
2071
                    $sibl = $this->modx->getDocumentChildren($parent, 1, 0, 'template', 'isfolder=0', 'menuindex',
2072
                        'ASC', 1);
2073
                    if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
2074
                        $template = $sibl[0]['template'];
2075
                    } else {
2076
                        $sibl = $this->modx->getDocumentChildren($parent, 0, 0, 'template', 'isfolder=0', 'menuindex',
2077
                            'ASC', 1);
2078
                        if (isset($sibl[0]['template']) && $sibl[0]['template'] !== '') {
2079
                            $template = $sibl[0]['template'];
2080
                        }
2081
                    }
2082
                }
2083
                break;
2084
            case 'parent':
2085
                if ($parent) {
2086
                    $_parent = $this->modx->getPageInfo($parent, 0, 'template');
2087
                    if (isset($_parent['template'])) {
2088
                        $template = $_parent['template'];
2089
                    }
2090
                }
2091
                break;
2092
        }
2093
        $this->set('template', $template);
2094
2095
        return $this;
2096
    }
2097
2098
    /**
2099
     * Декодирует конкретное поле
2100
     * @param  string $field Имя поля
2101
     * @param  bool $store обновить распакованное поле
2102
     * @return array ассоциативный массив с данными из json строки
2103
     */
2104
    public function decodeField($field, $store = false)
2105
    {
2106
        $out = array();
2107
        if ($this->isDecodableField($field)) {
2108
            $data = $this->get($field);
2109
            if ($this->isTVarrayField($field)) {
2110
                $out = explode('||', $data);
2111
            } else {
2112
                $out = jsonHelper::jsonDecode($data, array('assoc' => true), true);
2113
            }
2114
        }
2115
        if ($store) {
2116
            $this->field[$field] = $out;
2117
            $this->markAsDecode($field);
2118
        }
2119
2120
        return $out;
2121
    }
2122
2123
    /**
2124
     * Запаковывает конкретное поле в JSON
2125
     * @param  string $field Имя поля
2126
     * @param  bool $store обновить запакованное поле
2127
     * @return string|null json строка
2128
     */
2129
    public function encodeField($field, $store = false)
2130
    {
2131
        $out = null;
2132
        if ($this->isEncodableField($field)) {
2133
            $data = $this->get($field);
2134
            if ($this->isTVarrayField($field)) {
2135
                $out = is_array($data) ? implode('||', $data) : (string)$data;
2136
            } else {
2137
                $out = json_encode($data);
2138
            }
2139
        }
2140
        if ($store) {
2141
            $this->field[$field] = $out;
2142
            $this->markAsEncode($field);
2143
        }
2144
2145
        return $out;
2146
    }
2147
2148
    /**
2149
     * Может ли содержать данное поле json массив
2150
     * @param  string $field имя поля
2151
     * @return boolean
2152
     */
2153
    public function isTVarrayField($field)
0 ignored issues
show
Coding Style introduced by
This method is not in camel caps format.

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

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

Loading history...
2154
    {
2155
        return (is_scalar($field) && in_array($field, $this->tvaFields));
2156
    }
2157
2158
    /**
2159
     * Пометить все поля как запакованные
2160
     * @return $this
2161
     */
2162
    public function markAllEncode()
2163
    {
2164
        parent::markAllEncode();
2165
        foreach ($this->tvaFields as $field) {
2166
            $this->markAsEncode($field);
2167
        }
2168
2169
        return $this;
2170
    }
2171
2172
    /**
2173
     * Пометить все поля как распакованные
2174
     * @return $this
2175
     */
2176
    public function markAllDecode()
2177
    {
2178
        parent::markAllDecode();
2179
        foreach ($this->tvaFields as $field) {
2180
            $this->markAsDecode($field);
2181
        }
2182
2183
        return $this;
2184
    }
2185
2186
    /**
2187
     * @param int $docId
2188
     */
2189
    public function getDocumentGroups($docId = 0)
2190
    {
2191
        $out = array();
2192
        $doc = $this->switchObject($docId);
2193
        if (null !== $doc->getID()) {
2194
            $doc_groups = $this->makeTable('document_groups');
2195
            $docgroup_names = $this->makeTable('documentgroup_names');
2196
2197
            $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`
2198
                WHERE `dg`.`document` = " . $doc->getID());
2199
            while ($row = $this->modx->db->getRow($rs)) {
2200
                $out[$row['document_group']] = $row['name'];
2201
            }
2202
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
2203
        }
2204
        unset($doc);
2205
2206
        return $out;
2207
    }
2208
2209
    /**
2210
     * @param int $docId
2211
     * @param array $groupIds
2212
     * @return $this
2213
     */
2214
    public function setDocumentGroups($docId = 0, $groupIds = array())
2215
    {
2216
        if (!is_array($groupIds)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
2217
            return $this;
2218
        }
2219
        if ($this->newDoc && $docId == 0) {
2220
            $this->groupIds = $groupIds;
2221
        } else {
2222
            $doc = $this->switchObject($docId);
2223
            if ($id = $doc->getID()) {
2224
                foreach ($groupIds as $gid) {
2225
                    $this->query("REPLACE INTO {$this->makeTable('document_groups')} (`document_group`, `document`) VALUES ('{$gid}', '{$id}')");
2226
                }
2227
                if (!$this->newDoc) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
2228
                    $groupIds = empty($groupIds) ? '0' : implode(',', $groupIds);
2229
                    $this->query("DELETE FROM {$this->makeTable('document_groups')} WHERE `document`={$id} AND `document_group` NOT IN ({$groupIds})");
2230
                }
2231
            }
2232
            unset($doc);
2233
            $this->groupIds = array();
2234
        }
2235
2236
        return $this;
2237
    }
2238
}
2239
>>>>>>> d393b173f4bbf8bd6d838c984a72e8bfcfb72e11
2240