Test Failed
Push — master ( 2b8d6f...dc2483 )
by Agel_Nash
02:05
created

DLTemplate::setTemplateData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 3
nc 2
nop 1
1
<?php
2
3
include_once(MODX_BASE_PATH . 'assets/lib/APIHelpers.class.php');
4
5
use EvolutionCMS\Core as DocumentParser;
0 ignored issues
show
Bug introduced by
The type EvolutionCMS\Core was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
/**
7
 * Class DLTemplate
8
 */
9
class DLTemplate
10
{
11
    /**
12
     * Объект DocumentParser - основной класс MODX
13
     * @var DocumentParser $modx
14
     * @access protected
15
     */
16
    protected $modx = null;
17
18
    /**
19
     * @var DLTemplate cached reference to singleton instance
20
     */
21
    protected static $instance;
22
23
    protected $templatePath = 'assets/templates/';
24
25
    protected $templateExtension = 'html';
26
27
    /**
28
     * @var null|Twig_Environment twig object
0 ignored issues
show
Bug introduced by
The type Twig_Environment was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
     */
30
    protected $twig = null;
31
32
    /**
33
     * @var null|Jenssegers\Blade\Blade blade object
0 ignored issues
show
Bug introduced by
The type Jenssegers\Blade\Blade was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
     */
35
    protected $blade = null;
36
37
    protected $twigEnabled = false;
38
39
    protected $bladeEnabled = false;
40
41
    protected $templateData = array();
42
43
    public $phx = null;
44
45
    /**
46
     * gets the instance via lazy initialization (created on first usage)
47
     *
48
     * @return self
49
     */
50
    public static function getInstance(DocumentParser $modx)
51
    {
52
53
        if (null === self::$instance) {
54
            self::$instance = new self($modx);
55
        }
56
57
        return self::$instance;
58
    }
59
60
    /**
61
     * is not allowed to call from outside: private!
62
     *
63
     */
64
    private function __construct(DocumentParser $modx)
65
    {
66
        $this->modx = $modx;
67
    }
68
69
    /**
70
     * prevent the instance from being cloned
71
     *
72
     * @return void
73
     */
74
    private function __clone()
75
    {
76
    }
77
78
    /**
79
     * prevent from being unserialized
80
     *
81
     * @return void
82
     */
83
    private function __wakeup()
84
    {
85
    }
86
87
    /**
88
     * Задает относительный путь к папке с шаблонами
89
     *
90
     * @param $path
91
     * @param bool $supRoot
92
     * @return $this
93
     */
94
    public function setTemplatePath($path, $supRoot = false)
95
    {
96
        $path = trim($path);
97
        if ($supRoot === false) {
98
            $path = preg_replace(array(
99
                '/\.*[\/|\\\]/i',
100
                '/[\/|\\\]+/i'
101
            ), array('/', '/'), $path);
102
        }
103
104
        if (!empty($path)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
105
            $this->templatePath = $path;
106
        }
107
108
        return $this;
109
    }
110
111
    /**
112
     * Задает расширение файла с шаблоном
113
     *
114
     * @param $ext
115
     * @return $this
116
     */
117
    public function setTemplateExtension($ext)
118
    {
119
        $ext = preg_replace(array(
120
            '/\.*[\/|\\\]/i',
121
            '/[\/|\\\]+/i'
122
        ), array('/', '/'), trim($ext, ". \t\n\r\0\x0B"));
123
124
        if (!empty($ext)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
125
            $this->templateExtension = $ext;
126
        }
127
128
        return $this;
129
    }
130
131
    /**
132
     * Additional data for external templates
133
     *
134
     * @param array $data
135
     * @return $this
136
     */
137
    public function setTemplateData($data = array())
138
    {
139
        if (is_array($data)) {
0 ignored issues
show
introduced by
The condition is_array($data) is always true.
Loading history...
140
            $this->templateData = $data;
141
        }
142
143
        return $this;
144
    }
145
146
    /**
147
     * @param array $data
148
     * @return array
149
     */
150
    public function getTemplateData($data = array())
151
    {
152
        $plh = $this->templateData;
153
        $plh['data'] = $data;
154
        $plh['modx'] = $this->modx;
155
156
        return $plh;
157
    }
158
159
    /**
160
     * Сохранение данных в массив плейсхолдеров
161
     *
162
     * @param mixed $data данные
163
     * @param int $set устанавливать ли глобальнй плейсхолдер MODX
164
     * @param string $key ключ локального плейсхолдера
165
     * @param string $prefix префикс для ключей массива
166
     * @return string
167
     */
168
    public function toPlaceholders($data, $set = 0, $key = 'contentPlaceholder', $prefix = '')
169
    {
170
        $out = '';
171
        if ($set != 0) {
172
            $this->modx->toPlaceholder($key, $data, $prefix);
173
        } else {
174
            $out = $data;
175
        }
176
177
        return $out;
178
    }
179
180
    /**
181
     * refactor $modx->getChunk();
182
     *
183
     * @param string $name Template: chunk name || @CODE: template || @FILE: file with template
184
     * @return string html template with placeholders without data
185
     */
186
    public function getChunk($name)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
187
    {
188
        $tpl = '';
189
        $this->twigEnabled = (0 === strpos($name, '@T_'));
190
        $this->bladeEnabled = (0 === strpos($name, '@B_'));
191
        if ($name != '' && !isset($this->modx->chunkCache[$name])) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
192
            $mode = (preg_match(
193
                '/^((@[A-Z_]+)[:]{0,1})(.*)/Asu',
194
                trim($name),
195
                $tmp
196
            ) && isset($tmp[2], $tmp[3])) ? $tmp[2] : false;
197
            $subTmp = (isset($tmp[3])) ? trim($tmp[3]) : null;
198
            if ($this->twigEnabled) {
199
                $mode = '@' . substr($mode, 3);
0 ignored issues
show
Bug introduced by
It seems like $mode can also be of type false; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

199
                $mode = '@' . substr(/** @scrutinizer ignore-type */ $mode, 3);
Loading history...
200
            } elseif ($this->bladeEnabled) {
201
                $mode = '@' . substr($mode, 3);
202
            }
203
            switch ($mode) {
204
                case '@FILE':
205
                    if ($subTmp != '') {
206
                        $real = realpath(MODX_BASE_PATH . $this->templatePath);
207
                        $path = realpath(MODX_BASE_PATH . $this->templatePath . preg_replace(array(
208
                                '/\.*[\/|\\\]/i',
209
                                '/[\/|\\\]+/i'
210
                            ), array('/', '/'), $subTmp) . '.' . $this->templateExtension);
211
                        if (basename($path, '.' . $this->templateExtension) !== '' &&
212
                            0 === strpos($path, $real) &&
213
                            file_exists($path)
214
                        ) {
215
                            $tpl = file_get_contents($path);
216
                        }
217
                    }
218
                    break;
219
                case '@CHUNK':
220
                    if ($subTmp != '') {
221
                        $tpl = $this->modx->getChunk($subTmp);
222
                    }
223
                    break;
224
                case '@INLINE':
225
                case '@TPL':
226
                case '@CODE':
227
                    $tpl = $tmp[3]; //without trim
228
                    break;
229
                case '@DOCUMENT':
230
                case '@DOC':
231
                    switch (true) {
232
                        case ((int)$subTmp > 0):
233
                            $tpl = $this->modx->getPageInfo((int)$subTmp, 0, "content");
234
                            $tpl = isset($tpl['content']) ? $tpl['content'] : '';
235
                            break;
236
                        case ((int)$subTmp == 0):
237
                            $tpl = $this->modx->documentObject['content'];
238
                            break;
239
                    }
240
                    break;
241
                case '@PLH':
242
                case '@PLACEHOLDER':
243
                    if ($subTmp != '') {
244
                        $tpl = $this->modx->getPlaceholder($subTmp);
245
                    }
246
                    break;
247
                case '@CFG':
248
                case '@CONFIG':
249
                case '@OPTIONS':
250
                    if ($subTmp != '') {
251
                        $tpl = $this->modx->getConfig($subTmp);
252
                    }
253
                    break;
254
                case '@SNIPPET':
255
                    if ($subTmp != '') {
256
                        $tpl = $this->modx->runSnippet($subTmp, $this->modx->event->params);
257
                    }
258
                    break;
259
                case '@RENDERPAGE':
260
                    $tpl = $this->renderDoc($subTmp, false);
0 ignored issues
show
Bug introduced by
It seems like $subTmp can also be of type string; however, parameter $id of DLTemplate::renderDoc() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

260
                    $tpl = $this->renderDoc(/** @scrutinizer ignore-type */ $subTmp, false);
Loading history...
261
                    break;
262
                case '@LOADPAGE':
263
                    $tpl = $this->renderDoc($subTmp, true);
264
                    break;
265
                case '@TEMPLATE':
266
                    $tpl = $this->getTemplate($subTmp);
0 ignored issues
show
Bug introduced by
It seems like $subTmp can also be of type string; however, parameter $id of DLTemplate::getTemplate() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

266
                    $tpl = $this->getTemplate(/** @scrutinizer ignore-type */ $subTmp);
Loading history...
267
                    break;
268
                default:
269
                    $tpl = $this->modx->getChunk($name);
270
            }
271
            $this->modx->chunkCache[$name] = $tpl;
272
        } else {
273
            if ($name != '') {
274
                $tpl = $this->modx->getChunk($name);
275
            }
276
        }
277
278
        return $tpl;
279
    }
280
281
    /**
282
     * Рендер документа с подстановкой плейсхолдеров и выполнением сниппетов
283
     *
284
     * @param int $id ID документа
285
     * @param bool $events Во время рендера документа стоит ли вызывать события OnLoadWebDocument и OnLoadDocumentObject (внутри метода getDocumentObject).
286
     * @param mixed $tpl Шаблон с которым необходимо отрендерить документ. Возможные значения:
287
     *                       null - Использовать шаблон который назначен документу
288
     *                       int(0-n) - Получить шаблон из базы данных с указанным ID и применить его к документу
289
     *                       string - Применить шаблон указанный в строке к документу
290
     * @return string
291
     *
292
     * Событие OnLoadWebDocument дополнительно передает параметры:
293
     *       - с источиком от куда произошел вызов события
294
     *       - оригинальный экземпляр класса DocumentParser
295
     */
296
    public function renderDoc($id, $events = false, $tpl = null)
297
    {
298
        $id = (int)$id;
299
        if ($id <= 0) {
300
            return '';
301
        }
302
303
        $m = clone $this->modx; //Чтобы была возможность вызывать события
304
        $m->documentIdentifier = $id;
305
        $m->documentObject = $m->getDocumentObject('id', (int)$id, $events ? 'prepareResponse' : null);
306
        if ($m->documentObject['type'] == "reference") {
307
            if (is_numeric($m->documentObject['content']) && $m->documentObject['content'] > 0) {
308
                $m->documentObject['content'] = $this->renderDoc($m->documentObject['content'], $events);
309
            }
310
        }
311
        switch (true) {
312
            case is_integer($tpl):
313
                $tpl = $this->getTemplate($tpl);
314
                break;
315
            case is_string($tpl):
316
                break;
317
            case is_null($tpl):
318
            default:
319
                $tpl = $this->getTemplate($m->documentObject['template']);
320
        }
321
        $m->documentContent = $tpl;
322
        if ($events) {
323
            $m->invokeEvent("OnLoadWebDocument", array(
324
                'source'   => 'DLTemplate',
325
                'mainModx' => $this->modx,
326
            ));
327
        }
328
329
        return $this->parseDocumentSource($m->documentContent, $m);
330
    }
331
332
    /**
333
     * Получить содержимое шаблона с определенным номером
334
     * @param int $id Номер шаблона
335
     * @return string HTML код шаблона
336
     */
337
    public function getTemplate($id)
338
    {
339
        $tpl = null;
340
        $id = (int)$id;
341
        if ($id > 0) {
342
            $tpl = $this->modx->getDatabase()->getValue("SELECT `content` FROM {$this->modx->getDatabase()->getFullTableName("site_templates")} WHERE `id` = {$id}");
343
        }
344
        if (is_null($tpl)) {
345
            $tpl = '[*content*]';
346
        }
347
348
        return $tpl;
349
    }
350
351
    /**
352
     * refactor $modx->parseChunk();
353
     *
354
     * @param string $name Template: chunk name || @CODE: template || @FILE: file with template
355
     * @param array $data paceholder
356
     * @param bool $parseDocumentSource render html template via DocumentParser::parseDocumentSource()
357
     * @return string html template with data without placeholders
358
     */
359
    public function parseChunk($name, $data = array(), $parseDocumentSource = false, $disablePHx = false)
0 ignored issues
show
Coding Style introduced by
Function's nesting level (4) exceeds 3; consider refactoring the function
Loading history...
360
    {
361
        $out = $this->getChunk($name);
362
        switch (true) {
363
            case $this->twigEnabled && $out !== '' && ($twig = $this->getTwig($name, $out)):
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $twig is correct as $this->getTwig($name, $out) targeting DLTemplate::getTwig() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
364
                $out = $twig->render(md5($name), $this->getTemplateData($data));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $twig does not seem to be defined for all execution paths leading up to this point.
Loading history...
365
                break;
366
            case $this->bladeEnabled && $out !== '' && ($blade = $this->getBlade($name, $out)):
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $blade is correct as $this->getBlade($name, $out) targeting DLTemplate::getBlade() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
367
                $out = $blade->with($this->getTemplateData($data))->render();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $blade does not seem to be defined for all execution paths leading up to this point.
Loading history...
368
                break;
369
            case is_array($data) && ($out != ''):
370
                if (preg_match("/\[\+[A-Z0-9\.\_\-]+\+\]/is", $out)) {
371
                    $item = $this->renameKeyArr($data, '[', ']', '+');
372
                    $out = str_replace(array_keys($item), array_values($item), $out);
373
                }
374
                if (!$disablePHx && preg_match("/:([^:=]+)(?:=`(.*?)`(?=:[^:=]+|$))?/is", $out)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
375
                    if (is_null($this->phx) || !($this->phx instanceof DLphx)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
376
                        $this->phx = $this->createPHx(0, 1000);
377
                    }
378
                    $this->phx->placeholders = array();
379
                    $this->setPHxPlaceholders($data);
380
                    $out = $this->phx->Parse($out);
381
                    $out = $this->cleanPHx($out);
0 ignored issues
show
Bug introduced by
It seems like $out can also be of type mixed; however, parameter $string of DLTemplate::cleanPHx() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

381
                    $out = $this->cleanPHx(/** @scrutinizer ignore-type */ $out);
Loading history...
382
                }
383
                break;
384
        }
385
        if ($parseDocumentSource) {
386
            $out = $this->parseDocumentSource($out);
387
        }
388
389
        return $out;
390
    }
391
392
    /**
393
     *
394
     * @param string|array $value
395
     * @param string $key
396
     * @param string $path
397
     */
398
    public function setPHxPlaceholders($value = '', $key = '', $path = '')
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...
399
    {
400
        $keypath = !empty($path) ? $path . "." . $key : $key;
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
401
        $this->phx->curPass = 0;
402
        if (is_array($value)) {
403
            foreach ($value as $subkey => $subval) {
404
                $this->setPHxPlaceholders($subval, $subkey, $keypath);
405
            }
406
        } else {
407
            $this->phx->setPHxVariable($keypath, $value);
408
        }
409
    }
410
411
    /**
412
     * Return clone of twig
413
     *
414
     * @param string $name
415
     * @param string $tpl
416
     * @return null
417
     */
418
    protected function getTwig($name, $tpl)
419
    {
420
        if (is_null($this->twig) && isset($this->modx->twig)) {
421
            $twig = clone $this->modx->twig;
422
            $this->twig = $twig;
423
        } else {
424
            $twig = $this->twig;
425
        }
426
        if ($twig && class_exists('Twig_Loader_Array')) {
427
            $twig->getLoader()->addLoader(
428
                new Twig_Loader_Array(array(
0 ignored issues
show
Bug introduced by
The type Twig_Loader_Array was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
429
                    md5($name) => $tpl
430
                ))
431
            );
432
        }
433
434
        return $twig;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $twig also could return the type object|Twig_Environment which is incompatible with the documented return type null.
Loading history...
435
    }
436
437
    /**
438
     * Return clone of blade
439
     *
440
     * @param string $name
441
     * @param string $tpl
442
     * @return null
443
     */
444
    protected function getBlade($name, $tpl)
445
    {
446
        if ($this->blade === null && isset($this->modx->blade)) {
447
            $blade = clone $this->modx->blade;
448
            $this->blade = $blade;
449
        } else {
450
            $blade = $this->blade;
451
        }
452
453
        $cache = md5($name). '-'. sha1($tpl);
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
454
        $path = $blade->viewPaths . '/~cache/' . $cache . '.blade.php';
455
        if (! file_exists($path)) {
456
            file_put_contents($path, $tpl);
457
        }
458
459
        return $blade->make('~cache/' . $cache);
0 ignored issues
show
Bug introduced by
The method make() does not exist on null. ( Ignorable by Annotation )

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

459
        return $blade->/** @scrutinizer ignore-call */ make('~cache/' . $cache);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
460
    }
461
462
    /**
463
     *
464
     * @param string $string
465
     * @return string
466
     */
467
    public function cleanPHx($string)
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...
468
    {
469
        preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s', $string, $matches);
470
        if ($matches[0]) {
471
            $string = str_replace($matches[0], '', $string);
472
        }
473
474
        return $string;
475
    }
476
477
    /**
478
     * @param int $debug
479
     * @param int $maxpass
480
     * @return DLphx
481
     */
482
    public function createPHx($debug = 0, $maxpass = 50)
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...
483
    {
484
        if (!class_exists('DLphx')) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
485
            include_once(__DIR__ . '/DLphx.class.php');
486
        }
487
488
        return new DLphx($this->modx, $debug, $maxpass);
489
    }
490
491
    /**
492
     * Переменовывание элементов массива
493
     *
494
     * @param array $data массив с данными
495
     * @param string $prefix префикс ключей
496
     * @param string $suffix суффикс ключей
497
     * @param string $sep разделитель суффиксов, префиксов и ключей массива
498
     * @return array массив с переименованными ключами
499
     */
500
    public function renameKeyArr($data, $prefix = '', $suffix = '', $sep = '.')
501
    {
502
        return APIhelpers::renameKeyArr($data, $prefix, $suffix, $sep);
503
    }
504
505
    /**
506
     * @param $out
507
     * @param DocumentParser|null $modx
508
     * @return mixed|string
509
     */
510
    public function parseDocumentSource($out, $modx = null)
511
    {
512
        if (!is_object($modx)) {
0 ignored issues
show
Coding Style introduced by
There must be a single space after a NOT operator; 0 found
Loading history...
513
            $modx = $this->modx;
514
        }
515
        $minPasses = empty($modx->minParserPasses) ? 2 : $modx->minParserPasses;
516
        $maxPasses = empty($modx->maxParserPasses) ? 10 : $modx->maxParserPasses;
517
        $site_status = $modx->getConfig('site_status');
518
        $modx->config['site_status'] = 0;
519
        for ($i = 1; $i <= $maxPasses; $i++) {
520
            $html = $out;
521
            if (preg_match('/\[\!(.*)\!\]/us', $out)) {
522
                $out = str_replace(array('[!', '!]'), array('[[', ']]'), $out);
523
            }
524
            if ($i <= $minPasses || $out != $html) {
525
                $out = $modx->parseDocumentSource($out);
526
            } else {
527
                break;
528
            }
529
        }
530
        $out = $modx->rewriteUrls($out);
531
        $out = $this->cleanPHx($out);
532
        $modx->config['site_status'] = $site_status;
533
534
        return $out;
535
    }
536
}
537