Test Failed
Push — master ( e4f2f5...2b8d6f )
by Agel_Nash
02:04
created

DLTemplate::toPlaceholders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 6
nc 2
nop 4
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 $twigTemplateVars = 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 twig templates
133
     *
134
     * @param array $data
135
     * @return $this
136
     */
137
    public function setTwigTemplateVars($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->twigTemplateVars = $data;
141
        }
142
143
        return $this;
144
    }
145
146
    /**
147
     * Сохранение данных в массив плейсхолдеров
148
     *
149
     * @param mixed $data данные
150
     * @param int $set устанавливать ли глобальнй плейсхолдер MODX
151
     * @param string $key ключ локального плейсхолдера
152
     * @param string $prefix префикс для ключей массива
153
     * @return string
154
     */
155
    public function toPlaceholders($data, $set = 0, $key = 'contentPlaceholder', $prefix = '')
156
    {
157
        $out = '';
158
        if ($set != 0) {
159
            $this->modx->toPlaceholder($key, $data, $prefix);
160
        } else {
161
            $out = $data;
162
        }
163
164
        return $out;
165
    }
166
167
    /**
168
     * refactor $modx->getChunk();
169
     *
170
     * @param string $name Template: chunk name || @CODE: template || @FILE: file with template
171
     * @return string html template with placeholders without data
172
     */
173
    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...
174
    {
175
        $tpl = '';
176
        $this->twigEnabled = (0 === strpos($name, '@T_'));
177
        $this->bladeEnabled = (0 === strpos($name, '@B_'));
178
        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...
179
            $mode = (preg_match(
180
                '/^((@[A-Z_]+)[:]{0,1})(.*)/Asu',
181
                trim($name),
182
                $tmp
183
            ) && isset($tmp[2], $tmp[3])) ? $tmp[2] : false;
184
            $subTmp = (isset($tmp[3])) ? trim($tmp[3]) : null;
185
            if ($this->twigEnabled) {
186
                $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

186
                $mode = '@' . substr(/** @scrutinizer ignore-type */ $mode, 3);
Loading history...
187
            } elseif ($this->bladeEnabled) {
188
                $mode = '@' . substr($mode, 3);
189
            }
190
            switch ($mode) {
191
                case '@FILE':
192
                    if ($subTmp != '') {
193
                        $real = realpath(MODX_BASE_PATH . $this->templatePath);
194
                        $path = realpath(MODX_BASE_PATH . $this->templatePath . preg_replace(array(
195
                                '/\.*[\/|\\\]/i',
196
                                '/[\/|\\\]+/i'
197
                            ), array('/', '/'), $subTmp) . '.' . $this->templateExtension);
198
                        if (basename($path, '.' . $this->templateExtension) !== '' &&
199
                            0 === strpos($path, $real) &&
200
                            file_exists($path)
201
                        ) {
202
                            $tpl = file_get_contents($path);
203
                        }
204
                    }
205
                    break;
206
                case '@CHUNK':
207
                    if ($subTmp != '') {
208
                        $tpl = $this->modx->getChunk($subTmp);
209
                    }
210
                    break;
211
                case '@INLINE':
212
                case '@TPL':
213
                case '@CODE':
214
                    $tpl = $tmp[3]; //without trim
215
                    break;
216
                case '@DOCUMENT':
217
                case '@DOC':
218
                    switch (true) {
219
                        case ((int)$subTmp > 0):
220
                            $tpl = $this->modx->getPageInfo((int)$subTmp, 0, "content");
221
                            $tpl = isset($tpl['content']) ? $tpl['content'] : '';
222
                            break;
223
                        case ((int)$subTmp == 0):
224
                            $tpl = $this->modx->documentObject['content'];
225
                            break;
226
                    }
227
                    break;
228
                case '@PLH':
229
                case '@PLACEHOLDER':
230
                    if ($subTmp != '') {
231
                        $tpl = $this->modx->getPlaceholder($subTmp);
232
                    }
233
                    break;
234
                case '@CFG':
235
                case '@CONFIG':
236
                case '@OPTIONS':
237
                    if ($subTmp != '') {
238
                        $tpl = $this->modx->getConfig($subTmp);
239
                    }
240
                    break;
241
                case '@SNIPPET':
242
                    if ($subTmp != '') {
243
                        $tpl = $this->modx->runSnippet($subTmp, $this->modx->event->params);
244
                    }
245
                    break;
246
                case '@RENDERPAGE':
247
                    $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

247
                    $tpl = $this->renderDoc(/** @scrutinizer ignore-type */ $subTmp, false);
Loading history...
248
                    break;
249
                case '@LOADPAGE':
250
                    $tpl = $this->renderDoc($subTmp, true);
251
                    break;
252
                case '@TEMPLATE':
253
                    $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

253
                    $tpl = $this->getTemplate(/** @scrutinizer ignore-type */ $subTmp);
Loading history...
254
                    break;
255
                default:
256
                    $tpl = $this->modx->getChunk($name);
257
            }
258
            $this->modx->chunkCache[$name] = $tpl;
259
        } else {
260
            if ($name != '') {
261
                $tpl = $this->modx->getChunk($name);
262
            }
263
        }
264
265
        return $tpl;
266
    }
267
268
    /**
269
     * Рендер документа с подстановкой плейсхолдеров и выполнением сниппетов
270
     *
271
     * @param int $id ID документа
272
     * @param bool $events Во время рендера документа стоит ли вызывать события OnLoadWebDocument и OnLoadDocumentObject (внутри метода getDocumentObject).
273
     * @param mixed $tpl Шаблон с которым необходимо отрендерить документ. Возможные значения:
274
     *                       null - Использовать шаблон который назначен документу
275
     *                       int(0-n) - Получить шаблон из базы данных с указанным ID и применить его к документу
276
     *                       string - Применить шаблон указанный в строке к документу
277
     * @return string
278
     *
279
     * Событие OnLoadWebDocument дополнительно передает параметры:
280
     *       - с источиком от куда произошел вызов события
281
     *       - оригинальный экземпляр класса DocumentParser
282
     */
283
    public function renderDoc($id, $events = false, $tpl = null)
284
    {
285
        $id = (int)$id;
286
        if ($id <= 0) {
287
            return '';
288
        }
289
290
        $m = clone $this->modx; //Чтобы была возможность вызывать события
291
        $m->documentIdentifier = $id;
292
        $m->documentObject = $m->getDocumentObject('id', (int)$id, $events ? 'prepareResponse' : null);
293
        if ($m->documentObject['type'] == "reference") {
294
            if (is_numeric($m->documentObject['content']) && $m->documentObject['content'] > 0) {
295
                $m->documentObject['content'] = $this->renderDoc($m->documentObject['content'], $events);
296
            }
297
        }
298
        switch (true) {
299
            case is_integer($tpl):
300
                $tpl = $this->getTemplate($tpl);
301
                break;
302
            case is_string($tpl):
303
                break;
304
            case is_null($tpl):
305
            default:
306
                $tpl = $this->getTemplate($m->documentObject['template']);
307
        }
308
        $m->documentContent = $tpl;
309
        if ($events) {
310
            $m->invokeEvent("OnLoadWebDocument", array(
311
                'source'   => 'DLTemplate',
312
                'mainModx' => $this->modx,
313
            ));
314
        }
315
316
        return $this->parseDocumentSource($m->documentContent, $m);
317
    }
318
319
    /**
320
     * Получить содержимое шаблона с определенным номером
321
     * @param int $id Номер шаблона
322
     * @return string HTML код шаблона
323
     */
324
    public function getTemplate($id)
325
    {
326
        $tpl = null;
327
        $id = (int)$id;
328
        if ($id > 0) {
329
            $tpl = $this->modx->getDatabase()->getValue("SELECT `content` FROM {$this->modx->getDatabase()->getFullTableName("site_templates")} WHERE `id` = {$id}");
330
        }
331
        if (is_null($tpl)) {
332
            $tpl = '[*content*]';
333
        }
334
335
        return $tpl;
336
    }
337
338
    /**
339
     * refactor $modx->parseChunk();
340
     *
341
     * @param string $name Template: chunk name || @CODE: template || @FILE: file with template
342
     * @param array $data paceholder
343
     * @param bool $parseDocumentSource render html template via DocumentParser::parseDocumentSource()
344
     * @return string html template with data without placeholders
345
     */
346
    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...
347
    {
348
        $out = $this->getChunk($name);
349
        switch (true) {
350
            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...
351
                $plh = $this->twigTemplateVars;
352
                $plh['data'] = $data;
353
                $plh['modx'] = $this->modx;
354
                $out = $twig->render(md5($name), $plh);
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...
355
                break;
356
            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...
357
                $out = $blade->with($data);
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...
358
                break;
359
            case is_array($data) && ($out != ''):
360
                if (preg_match("/\[\+[A-Z0-9\.\_\-]+\+\]/is", $out)) {
361
                    $item = $this->renameKeyArr($data, '[', ']', '+');
362
                    $out = str_replace(array_keys($item), array_values($item), $out);
363
                }
364
                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...
365
                    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...
366
                        $this->phx = $this->createPHx(0, 1000);
367
                    }
368
                    $this->phx->placeholders = array();
369
                    $this->setPHxPlaceholders($data);
370
                    $out = $this->phx->Parse($out);
371
                    $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

371
                    $out = $this->cleanPHx(/** @scrutinizer ignore-type */ $out);
Loading history...
372
                }
373
                break;
374
        }
375
        if ($parseDocumentSource) {
376
            $out = $this->parseDocumentSource($out);
377
        }
378
379
        return $out;
380
    }
381
382
    /**
383
     *
384
     * @param string|array $value
385
     * @param string $key
386
     * @param string $path
387
     */
388
    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...
389
    {
390
        $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...
391
        $this->phx->curPass = 0;
392
        if (is_array($value)) {
393
            foreach ($value as $subkey => $subval) {
394
                $this->setPHxPlaceholders($subval, $subkey, $keypath);
395
            }
396
        } else {
397
            $this->phx->setPHxVariable($keypath, $value);
398
        }
399
    }
400
401
    /**
402
     * Return clone of twig
403
     *
404
     * @param string $name
405
     * @param string $tpl
406
     * @return null
407
     */
408
    protected function getTwig($name, $tpl)
409
    {
410
        if (is_null($this->twig) && isset($this->modx->twig)) {
411
            $twig = clone $this->modx->twig;
412
            $this->twig = $twig;
413
        } else {
414
            $twig = $this->twig;
415
        }
416
        if ($twig && class_exists('Twig_Loader_Array')) {
417
            $twig->getLoader()->addLoader(
418
                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...
419
                    md5($name) => $tpl
420
                ))
421
            );
422
        }
423
424
        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...
425
    }
426
427
    /**
428
     * Return clone of blade
429
     *
430
     * @param string $name
431
     * @param string $tpl
432
     * @return null
433
     */
434
    protected function getBlade($name, $tpl)
435
    {
436
        if ($this->blade === null && isset($this->modx->blade)) {
437
            $blade = clone $this->modx->blade;
438
            $this->blade = $blade;
439
        } else {
440
            $blade = $this->blade;
441
        }
442
443
        $cache = md5($name). '-'. sha1($tpl);
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
444
        $path = $blade->viewPaths . '/~cache/' . $cache . '.blade.php';
445
        if (! file_exists($path)) {
446
            file_put_contents($path, $tpl);
447
        }
448
449
        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

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