DLphx::LogSource()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 1
c 3
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
0 ignored issues
show
Coding Style introduced by
End of line character is invalid; expected "\n" but found "\r\n"
Loading history...
2
/*####
3
#
4
#   Name: PHx (Placeholders Xtended)
5
#   Version: 2.2.0
6
#   Modified by Nick to include external files
7
#   Modified by Anton Kuzmin for using of modx snippets cache
8
#   Modified by Temus ([email protected])
9
#   Author: Armand "bS" Pondman ([email protected])
10
#   Date: March 22, 2013
11
#
12
####*/
13
include_once(MODX_BASE_PATH . 'assets/lib/APIHelpers.class.php');
14
15
/**
16
 * Class DLphx
17
 */
18
class DLphx
19
{
20
    public $placeholders = array();
21
    public $name = 'PHx';
22
    public $version = '2.2.0';
23
    public $user = array();
24
    public $cache = array(
25
        'cm' => array(),
26
        'ui' => array(),
27
        'mo' => array()
28
    );
29
    public $safetags = array(
30
        array('~(?<![\[]|^\^)\[(?=[^\+\*\(\[]|$)~s', '~(?<=[^\+\*\)\]]|^)\](?=[^\]]|$)~s'),
31
        array('&_PHX_INTERNAL_091_&', '&_PHX_INTERNAL_093_&'),
32
        array('[', ']')
33
    );
34
    public $console = array();
35
    public $debug = false;
36
    public $debugLog = false;
37
    public $curPass = 0;
38
    public $maxPasses = 50;
39
    public $swapSnippetCache = array();
40
    protected $modx = null;
41
42
    /**
43
     * DLphx constructor.
44
     * @param DocumentParser $modx
45
     * @param int|bool|string $debug
46
     * @param int $maxpass
47
     */
48
    public function __construct(DocumentParser $modx, $debug = false, $maxpass = 50)
49
    {
50
        $this->modx = $modx;
51
        $this->user["mgrid"] = isset($_SESSION['mgrInternalKey']) ? intval($_SESSION['mgrInternalKey']) : 0;
52
        $this->user["usrid"] = isset($_SESSION['webInternalKey']) ? intval($_SESSION['webInternalKey']) : 0;
53
        $this->user["id"] = ($this->user["usrid"] > 0) ? (-$this->user["usrid"]) : $this->user["mgrid"];
54
55
        $this->debug = (bool)$debug;
56
57
        $this->maxPasses = ($maxpass != '') ? $maxpass : 50;
58
59
        $this->modx->setPlaceholder("phx", "&_PHX_INTERNAL_&");
0 ignored issues
show
Bug introduced by
The method setPlaceholder() does not exist on DocumentParser. ( Ignorable by Annotation )

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

59
        $this->modx->/** @scrutinizer ignore-call */ 
60
                     setPlaceholder("phx", "&_PHX_INTERNAL_&");

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...
60
        if (function_exists('mb_internal_encoding')) {
61
            mb_internal_encoding($this->modx->config['modx_charset']);
62
        }
63
    }
64
65
    // Plugin event hook for MODx
66
    public function OnParseDocument()
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::OnParseDocument" 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...
67
    {
68
        // Get document output from MODx
69
        $template = $this->modx->documentOutput;
0 ignored issues
show
Bug introduced by
The property documentOutput does not seem to exist on DocumentParser.
Loading history...
70
        // To the parse cave .. let's go! *insert batman tune here*
71
        $template = $this->Parse($template);
72
        // Set processed document output in MODx
73
        $this->modx->documentOutput = $template;
74
    }
75
76
    // Parser: Preparation, cleaning and checkup
77
78
    /**
79
     * @param string $template
80
     * @return mixed|string
81
     */
82
    public function Parse($template = '')
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::Parse" 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...
83
    {
84
        // If we already reached max passes don't get at it again.
85
        if ($this->curPass == $this->maxPasses) {
86
            return $template;
87
        }
88
        // Set template pre-process hash
89
        $st = md5($template);
90
        // Replace non-call characters in the template: [, ]
91
        $template = preg_replace($this->safetags[0], $this->safetags[1], $template);
92
        // To the parse mobile.. let's go! *insert batman tune here*
93
        $template = $this->ParseValues($template);
94
        // clean up unused placeholders that have modifiers attached (MODx can't clean them)
95
        preg_match_all('~(?:=`[^`@]*?)(\[\+([^:\+\[\]]+)([^\[\]]*?)\+\])~s', $template, $matches);
96
        if ($matches[0]) {
97
            $template = str_replace($matches[1], '', $template);
98
            $this->Log("Cleaning unsolved tags: \n" . implode("\n", $matches[2]));
99
        }
100
        // Restore non-call characters in the template: [, ]
101
        $template = str_replace($this->safetags[1], $this->safetags[2], $template);
102
        // Set template post-process hash
103
        $et = md5($template);
104
        // If template has changed, parse it once more...
105
        if ($st != $et) {
106
            $template = $this->Parse($template);
107
        }
108
        // Write an event log if debugging is enabled and there is something to log
109
        if ($this->debug && $this->debugLog) {
110
            $this->modx->logEvent($this->curPass, 1, $this->createEventLog(), $this->name . ' ' . $this->version);
0 ignored issues
show
Bug introduced by
The method logEvent() does not exist on DocumentParser. ( Ignorable by Annotation )

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

110
            $this->modx->/** @scrutinizer ignore-call */ logEvent($this->curPass, 1, $this->createEventLog(), $this->name . ' ' . $this->version);

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...
111
            $this->debugLog = false;
112
        }
113
114
        // Return the processed template
115
        return $template;
116
    }
117
118
    // Parser: Tag detection and replacements
119
120
    /**
121
     * @param string $template
122
     * @return mixed|string
123
     */
124
    public function ParseValues($template = '')
0 ignored issues
show
Coding Style introduced by
Function's nesting level (5) exceeds 3; consider refactoring the function
Loading history...
Coding Style introduced by
Method name "DLphx::ParseValues" 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...
125
    {
126
        $this->curPass = $this->curPass + 1;
127
        $st = md5($template);
128
129
        $this->LogPass();
130
        // MODX Chunks
131
        if (preg_match_all('~(?<!(?:then|else)=`){{([^:\+{}]+)([^{}]*?)}}~s', $template, $matches)) {
132
            $this->Log('MODX Chunks -> Merging all chunk tags');
133
            $count = count($matches[0]);
134
            $var_search = array();
135
            $var_replace = array();
136
            for ($i = 0; $i < $count; $i++) {
137
                $var_search[] = $matches[0][$i];
138
                $input = $matches[1][$i];
139
                $this->Log('MODX Chunk: ' . $input);
140
                $input = $this->modx->mergeChunkContent('{{' . $input . '}}');
0 ignored issues
show
Bug introduced by
The method mergeChunkContent() does not exist on DocumentParser. ( Ignorable by Annotation )

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

140
                /** @scrutinizer ignore-call */ $input = $this->modx->mergeChunkContent('{{' . $input . '}}');

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...
141
                $var_replace[] = $this->Filter($input, $matches[2][$i]);
142
            }
143
            $template = str_replace($var_search, $var_replace, $template);
144
        }
145
146
        // MODx Snippets
147
        //if ( preg_match_all('~\[(\[|!)([^\[]*?)(!|\])\]~s',$template, $matches)) {
148
        if (preg_match_all('~(?<!(?:then|else)=`)\[(\[)([^\[]*?)(\])\]~s', $template, $matches)) {
149
            $count = count($matches[0]);
150
            $var_search = array();
151
            $var_replace = array();
152
153
            // for each detected snippet
154
            for ($i = 0; $i < $count; $i++) {
155
                $snippet = $matches[2][$i]; // snippet call
156
                $this->Log("MODx Snippet -> " . $snippet);
157
158
                // Let MODx evaluate snippet
159
                $replace = $this->modx->evalSnippets("[[" . $snippet . "]]");
0 ignored issues
show
Bug introduced by
The method evalSnippets() does not exist on DocumentParser. ( Ignorable by Annotation )

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

159
                /** @scrutinizer ignore-call */ $replace = $this->modx->evalSnippets("[[" . $snippet . "]]");

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...
160
                $this->LogSnippet($replace);
161
162
                // Replace values
163
                $var_search[] = $matches[0][$i];
164
                $var_replace[] = $replace;
165
            }
166
            $template = str_replace($var_search, $var_replace, $template);
167
        }
168
169
        // PHx / MODx Tags
170
        if (preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s', $template, $matches)) {
171
            //$matches[0] // Complete string that's need to be replaced
172
            //$matches[1] // Type
173
            //$matches[2] // The placeholder(s)
174
            //$matches[3] // The modifiers
175
            //$matches[4] // Type (end character)
176
177
            $count = count($matches[0]);
178
            $var_search = array();
179
            $var_replace = array();
180
            for ($i = 0; $i < $count; $i++) {
181
                $input = $matches[2][$i];
182
                $modifiers = $matches[3][$i];
183
                if(empty($modifiers)) continue;
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
Coding Style introduced by
Expected 1 space after IF keyword; 0 found
Loading history...
184
                $var_search[] = $matches[0][$i];
185
                switch ($matches[1][$i]) {
186
                    // Document / Template Variable eXtended
187
                    case "*":
188
                        $this->Log("MODx TV/DV: " . $input);
189
                        $input = $this->modx->mergeDocumentContent("[*" . $input . "*]");
0 ignored issues
show
Bug introduced by
The method mergeDocumentContent() does not exist on DocumentParser. ( Ignorable by Annotation )

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

189
                        /** @scrutinizer ignore-call */ $input = $this->modx->mergeDocumentContent("[*" . $input . "*]");

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...
190
                        $replace = $this->Filter($input, $modifiers);
191
                        break;
192
                    // MODx Setting eXtended
193
                    case "(":
194
                        $this->Log("MODx Setting variable: " . $input);
195
                        $input = $this->modx->mergeSettingsContent("[(" . $input . ")]");
0 ignored issues
show
Bug introduced by
The method mergeSettingsContent() does not exist on DocumentParser. ( Ignorable by Annotation )

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

195
                        /** @scrutinizer ignore-call */ $input = $this->modx->mergeSettingsContent("[(" . $input . ")]");

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...
196
                        $replace = $this->Filter($input, $modifiers);
197
                        break;
198
                    // MODx Placeholder eXtended
199
                    default:
200
                        $this->Log("MODx / PHx placeholder variable: " . $input);
201
                        // Check if placeholder is set
202
                        if (!array_key_exists($input, $this->placeholders) && !array_key_exists(
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
203
                            $input,
204
                            $this->modx->placeholders
0 ignored issues
show
Bug introduced by
The property placeholders does not seem to exist on DocumentParser.
Loading history...
205
                        )
206
                        ) {
207
                            // not set so try again later.
208
                            $input = '';
209
                        } else {
210
                            // is set, get value and run filter
211
                            $input = $this->getPHxVariable($input);
212
                        }
213
                        $replace = $this->Filter($input, $modifiers);
214
                        break;
215
                }
216
                $var_replace[] = $replace;
217
            }
218
            $template = str_replace($var_search, $var_replace, $template);
219
        }
220
        $et = md5($template); // Post-process template hash
221
222
        // Log an event if this was the maximum pass
223
        if ($this->curPass == $this->maxPasses) {
224
            $this->Log("Max passes reached. infinite loop protection so exiting.\n If you need the extra passes set the max passes to the highest count of nested tags in your template.");
225
        }
226
        // If this pass is not at maximum passes and the template hash is not the same, get at it again.
227
        if (($this->curPass < $this->maxPasses) && ($st != $et)) {
228
            $template = $this->ParseValues($template);
229
        }
230
231
        return $template;
232
    }
233
234
    // Parser: modifier detection and eXtended processing if needed
235
236
    /**
237
     * @param $input
238
     * @param $modifiers
239
     * @return mixed|null|string
240
     */
241
    public function Filter($input, $modifiers)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::Filter" is not in camel caps format
Loading history...
Coding Style introduced by
Function's nesting level (8) exceeds allowed maximum of 6
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...
242
    {
243
        $output = $input;
244
        $this->Log("  |--- Input = '" . $output . "'");
245
        if (preg_match_all('~:([^:=]+)(?:=`(.*?)`(?=:[^:=]+|$))?~s', $modifiers, $matches)) {
246
            $modifier_cmd = $matches[1]; // modifier command
247
            $modifier_value = $matches[2]; // modifier value
248
            $count = count($modifier_cmd);
249
            $condition = array();
250
            for ($i = 0; $i < $count; $i++) {
251
                $output = trim($output);
252
                $this->Log("  |--- Modifier = '" . $modifier_cmd[$i] . "'");
253
                if ($modifier_value[$i] != '') {
254
                    $this->Log("  |--- Options = '" . $modifier_value[$i] . "'");
255
                }
256
                switch ($modifier_cmd[$i]) {
257
                    #####  Conditional Modifiers
258
                    case "input":
259
                    case "if":
260
                        $output = $modifier_value[$i];
261
                        break;
262
                    case "equals":
263
                    case "is":
264
                    case "eq":
265
                        $condition[] = intval(($output == $modifier_value[$i]));
266
                        break;
267
                    case "empty":
268
                        $condition[] = intval(empty($output));
269
                        break;
270
                    case "notequals":
271
                    case "isnot":
272
                    case "isnt":
273
                    case "ne":
274
                        $condition[] = intval(($output != $modifier_value[$i]));
275
                        break;
276
                    case "isgreaterthan":
277
                    case "isgt":
278
                    case "eg":
279
                        $condition[] = intval(($output >= $modifier_value[$i]));
280
                        break;
281
                    case "islowerthan":
282
                    case "islt":
283
                    case "el":
284
                        $condition[] = intval(($output <= $modifier_value[$i]));
285
                        break;
286
                    case "greaterthan":
287
                    case "gt":
288
                        $condition[] = intval(($output > $modifier_value[$i]));
289
                        break;
290
                    case "lowerthan":
291
                    case "lt":
292
                        $condition[] = intval(($output < $modifier_value[$i]));
293
                        break;
294
                    case "isinrole":
295
                    case "ir":
296
                    case "memberof":
297
                    case "mo": // Is Member Of  (same as inrole but this one can be stringed as a conditional)
298
                        if ($output == "&_PHX_INTERNAL_&") {
299
                            $output = $this->user["id"];
300
                        }
301
                        $grps = ($this->strlen($modifier_value[$i]) > 0) ? explode(",", $modifier_value[$i]) : array();
302
                        $condition[] = intval($this->isMemberOfWebGroupByUserId($output, $grps));
303
                        break;
304
                    case "or":
305
                        $condition[] = "||";
306
                        break;
307
                    case "and":
308
                        $condition[] = "&&";
309
                        break;
310
                    case "show":
311
                        $conditional = implode(' ', $condition);
312
                        $isvalid = intval($this->runCode($conditional));
313
                        if (!$isvalid) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
314
                            $output = null;
315
                        }
316
                        break;
317
                    case "then":
318
                        $conditional = implode(' ', $condition);
319
                        $isvalid = intval($this->runCode($conditional));
320
                        if ($isvalid) {
321
                            $output = $modifier_value[$i];
322
                        } else {
323
                            $output = null;
324
                        }
325
                        break;
326
                    case "else":
327
                        $conditional = implode(' ', $condition);
328
                        $isvalid = intval($this->runCode($conditional));
329
                        if (!$isvalid) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
330
                            $output = $modifier_value[$i];
331
                        }
332
                        break;
333
                    case "select":
334
                        $raw = explode("&", $modifier_value[$i]);
335
                        $map = array();
336
                        $count = count($raw);
337
                        for ($m = 0; $m < $count; $m++) {
338
                            $mi = explode("=", $raw[$m]);
339
                            $map[$mi[0]] = $mi[1];
340
                        }
341
                        $output = $map[$output];
342
                        break;
343
                    ##### End of Conditional Modifiers
344
345
                    #####  String Modifiers
346
                    case "default":
347
                        $output = ($output === '') ? $modifier_value[0] : $output;
348
                        break;
349
                    case "lcase":
350
                    case "strtolower":
351
                        $output = $this->strtolower($output);
352
                        break;
353
                    case "ucase":
354
                    case "strtoupper":
355
                        $output = $this->strtoupper($output);
356
                        break;
357
                    case "ucfirst":
358
                        $output = $this->ucfirst($output);
359
                        break;
360
                    case "lcfirst":
361
                        $output = $this->lcfirst($output);
362
                        break;
363
                    case "ucwords":
364
                        $output = $this->ucwords($output);
365
                        break;
366
                    case "htmlent":
367
                    case "htmlentities":
368
                        $output = htmlentities($output, ENT_QUOTES, $this->modx->config['modx_charset']);
369
                        break;
370
                    case "html_entity_decode":
371
                        $output = html_entity_decode($output, ENT_QUOTES, $this->modx->config['modx_charset']);
372
                        break;
373
                    case "esc":
374
                        $output = preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", APIHelpers::e($output));
375
                        $output = str_replace(array("[", "]", "`"), array("&#91;", "&#93;", "&#96;"), $output);
376
                        break;
377
                    case "strip":
378
                        $output = preg_replace("~([\n\r\t\s]+)~", " ", $output);
379
                        break;
380
                    case "notags":
381
                    case "strip_tags":
382
                        $output = strip_tags($output);
383
                        break;
384
                    case "length":
385
                    case "len":
386
                    case "strlen":
387
                        $output = $this->strlen($output);
388
                        break;
389
                    case "reverse":
390
                    case "strrev":
391
                        $output = $this->strrev($output);
392
                        break;
393
                    case "wordwrap": // default: 70
394
                        $wrapat = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 70;
395
                        $output = preg_replace_callback("@(\b\w+\b)@", function ($m) use ($wrapat) {
396
                            return wordwrap($m[1], $wrapat, ' ', 1);
397
                        }, $output);
398
                        break;
399
                    case "limit": // default: 100
400
                        $limit = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 100;
401
                        $output = $this->substr($output, 0, $limit);
402
                        break;
403
                    case "str_shuffle":
404
                    case "shuffle":
405
                        $output = $this->str_shuffle($output);
406
                        break;
407
                    case "str_word_count":
408
                    case "word_count":
409
                    case "wordcount":
410
                        $output = $this->str_word_count($output);
411
                        break;
412
413
                    #####  Special functions
414
                    case "math":
415
                        $filter = preg_replace("~([a-zA-Z\n\r\t\s])~", "", $modifier_value[$i]);
416
                        $filter = str_replace("?", $output, $filter);
417
                        $output = eval("return " . $filter . ";");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
Coding Style introduced by
The use of function eval() is forbidden
Loading history...
418
                        break;
419
                    case "isnotempty":
420
                        if (!empty($output)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
421
                            $output = $modifier_value[$i];
422
                        }
423
                        break;
424
                    case "isempty":
425
                    case "ifempty":
426
                        if (empty($output)) {
427
                            $output = $modifier_value[$i];
428
                        }
429
                        break;
430
                    case "nl2br":
431
                        $output = nl2br($output);
432
                        break;
433
                    case "date":
434
                        $output = date($modifier_value[$i], (int)$output);
435
                        break;
436
                    case "set":
437
                        $c = $i + 1;
438
                        if ($count > $c && $modifier_cmd[$c] == "value") {
439
                            $output = preg_replace("~([^a-zA-Z0-9])~", "", $modifier_value[$i]);
440
                        }
441
                        break;
442
                    case "value":
443
                        if ($i > 0 && $modifier_cmd[$i - 1] == "set") {
444
                            $this->modx->SetPlaceholder("phx." . $output, $modifier_value[$i]);
0 ignored issues
show
Bug introduced by
The method SetPlaceholder() does not exist on DocumentParser. ( Ignorable by Annotation )

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

444
                            $this->modx->/** @scrutinizer ignore-call */ SetPlaceholder("phx." . $output, $modifier_value[$i]);

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...
445
                        }
446
                        $output = null;
447
                        break;
448
                    case "md5":
449
                        $output = md5($output);
450
                        break;
451
                    case 'inarray':
452
                    case 'in_array':
453
                    case 'in':
454
                        $modifier_value[$i] = explode(',', $modifier_value[$i]);
455
                        $condition[] = (int)(in_array($output, $modifier_value[$i]) !== false);
456
                        break;
457
                    case "userinfo":
458
                        if ($output == "&_PHX_INTERNAL_&") {
459
                            $output = $this->user["id"];
460
                        }
461
                        $output = $this->ModUser($output, $modifier_value[$i]);
462
                        break;
463
                    case "inrole": // deprecated
464
                        if ($output == "&_PHX_INTERNAL_&") {
465
                            $output = $this->user["id"];
466
                        }
467
                        $grps = ($this->strlen($modifier_value[$i]) > 0) ? explode(",", $modifier_value[$i]) : array();
468
                        $output = intval($this->isMemberOfWebGroupByUserId($output, $grps));
469
                        break;
470
471
                    // If we haven't yet found the modifier, let's look elsewhere
472
                    default:
473
                        $snippet = '';
474
                        // modified by Anton Kuzmin (23.06.2010) //
475
                        $snippetName = 'phx:' . $modifier_cmd[$i];
476
                        if (isset($this->modx->snippetCache[$snippetName])) {
0 ignored issues
show
Bug introduced by
The property snippetCache does not seem to exist on DocumentParser.
Loading history...
477
                            $snippet = $this->modx->snippetCache[$snippetName];
478
                        } else {
479
// not in cache so let's check the db
480
                            $sql = "SELECT snippet FROM " . $this->modx->getFullTableName("site_snippets") . " WHERE " . $this->modx->getFullTableName("site_snippets") . ".name='" . $this->modx->db->escape($snippetName) . "';";
481
                            $result = $this->modx->db->query($sql);
482
                            if ($this->modx->db->getRecordCount($result) == 1) {
483
                                $row = $this->modx->db->getRow($result);
484
                                $snippet = $this->modx->snippetCache[$row['name']] = $row['snippet'];
485
                                $this->Log("  |--- DB -> Custom Modifier");
486
                            } else {
487
                                if ($this->modx->db->getRecordCount($result) == 0) {
488
// If snippet not found, look in the modifiers folder
489
                                    $filename = $this->modx->config['rb_base_dir'] . 'plugins/phx/modifiers/' . $modifier_cmd[$i] . '.phx.php';
490
                                    if (@file_exists($filename)) {
491
                                        $file_contents = @file_get_contents($filename);
492
                                        $file_contents = str_replace('<' . '?php', '', $file_contents);
493
                                        $file_contents = str_replace('?' . '>', '', $file_contents);
494
                                        $file_contents = str_replace('<?', '', $file_contents);
495
                                        $snippet = $this->modx->snippetCache[$snippetName] = $file_contents;
496
                                        $this->modx->snippetCache[$snippetName . 'Props'] = '';
497
                                        $this->Log("  |--- File ($filename) -> Custom Modifier");
498
                                    } else {
499
                                        $this->Log("  |--- PHX Error:  {$modifier_cmd[$i]} could not be found");
500
                                    }
501
                                }
502
                            }
503
                        }
504
                        if (!empty($snippet)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
505
                            $output = $this->modx->runSnippet($snippetName, array(
0 ignored issues
show
Bug introduced by
The method runSnippet() does not exist on DocumentParser. ( Ignorable by Annotation )

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

505
                            /** @scrutinizer ignore-call */ $output = $this->modx->runSnippet($snippetName, array(

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...
506
                                'input'   => $output,
507
                                'output'  => $output,
508
                                'options' => $modifier_value[$i]
509
                            ));
510
                        } else {
511
                            $output = '';
512
                        }
513
                        break;
514
                }
515
                if (count($condition)) {
516
                    $this->Log("  |--- Condition = '" . $condition[count($condition) - 1] . "'");
517
                }
518
                $this->Log("  |--- Output = '" . $output . "'");
519
            }
520
        }
521
522
        return $output;
523
    }
524
525
    /**
526
     * @param string $code
527
     * @return mixed
528
     */
529
    private function runCode($code)
530
    {
531
        return eval("return (" . $code . ");");
0 ignored issues
show
Coding Style introduced by
The use of function eval() is forbidden
Loading history...
introduced by
The use of eval() is discouraged.
Loading history...
532
    }
533
534
    // Event logging (debug)
535
536
    /**
537
     * @return string
538
     */
539
    public function createEventLog()
540
    {
541
        $out = '';
542
        if (!empty($this->console)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
543
            $console = implode("\n", $this->console);
544
            $this->console = array();
545
546
            $out = '<pre style="overflow: auto;">' . $console . '</pre>';
547
        }
548
549
        return $out;
550
    }
551
552
    // Returns a cleaned string escaping the HTML and special MODx characters
553
554
    /**
555
     * @param $string
556
     * @return array|mixed|string
557
     */
558
    public function LogClean($string)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::LogClean" 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...
559
    {
560
        $string = preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", $string);
561
        $string = APIHelpers::sanitarTag($string);
562
563
        return $string;
564
    }
565
566
    // Simple log entry
567
568
    /**
569
     * @param $string
570
     */
571
    public function Log($string)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::Log" 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...
572
    {
573
        if ($this->debug) {
574
            $this->debugLog = true;
575
            $this->console[] = (count($this->console) + 1 - $this->curPass) . " [" . date(
576
                "H:i:S",
577
                time()
578
            ) . "] " . $this->LogClean($string);
0 ignored issues
show
Bug introduced by
Are you sure $this->LogClean($string) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

578
            ) . "] " . /** @scrutinizer ignore-type */ $this->LogClean($string);
Loading history...
579
        }
580
    }
581
582
    // Log snippet output
583
584
    /**
585
     * @param $string
586
     */
587
    public function LogSnippet($string)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::LogSnippet" 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...
588
    {
589
        if ($this->debug) {
590
            $this->debugLog = true;
591
            $this->console[] = (count($this->console) + 1 - $this->curPass) . " [" . date(
592
                "H:i:S",
593
                time()
594
            ) . "] " . "  |--- Returns: <div style='margin: 10px;'>" . $this->LogClean($string) . "</div>";
0 ignored issues
show
Bug introduced by
Are you sure $this->LogClean($string) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

594
            ) . "] " . "  |--- Returns: <div style='margin: 10px;'>" . /** @scrutinizer ignore-type */ $this->LogClean($string) . "</div>";
Loading history...
595
        }
596
    }
597
598
    // Log pass
599
    public function LogPass()
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::LogPass" 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...
600
    {
601
        $this->console[] = "<div style='margin: 5px 2px 2px;border-bottom: 1px solid black;'>Pass " . $this->curPass . "</div>";
602
    }
603
604
    // Log pass
605
606
    /**
607
     * @param $string
608
     */
609
    public function LogSource($string)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::LogSource" 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...
610
    {
611
        $this->console[] = "<div style='margin: 5px 2px 2px;border-bottom: 1px solid black;'>Source:</div>" . $this->LogClean($string);
0 ignored issues
show
Bug introduced by
Are you sure $this->LogClean($string) of type array|string can be used in concatenation? ( Ignorable by Annotation )

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

611
        $this->console[] = "<div style='margin: 5px 2px 2px;border-bottom: 1px solid black;'>Source:</div>" . /** @scrutinizer ignore-type */ $this->LogClean($string);
Loading history...
612
    }
613
614
    // Returns the specified field from the user record
615
    // positive userid = manager, negative integer = webuser
616
    
617
/**
618
     * @param $userid
619
     * @param $field
620
     * @return mixed
621
     */
622
    public function ModUser($userid, $field)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::ModUser" 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...
623
    {
624
        if (!array_key_exists($userid, $this->cache["ui"])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
625
            if (intval($userid) < 0) {
626
                $user = $this->modx->getWebUserInfo(-($userid));
0 ignored issues
show
Bug introduced by
The method getWebUserInfo() does not exist on DocumentParser. ( Ignorable by Annotation )

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

626
                /** @scrutinizer ignore-call */ $user = $this->modx->getWebUserInfo(-($userid));

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...
627
            } else {
628
                $user = $this->modx->getUserInfo($userid);
0 ignored issues
show
Bug introduced by
The method getUserInfo() does not exist on DocumentParser. ( Ignorable by Annotation )

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

628
                /** @scrutinizer ignore-call */ $user = $this->modx->getUserInfo($userid);

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...
629
            }
630
            $this->cache["ui"][$userid] = $user;
631
        } else {
632
            $user = $this->cache["ui"][$userid];
633
        }
634
635
        return $user[$field];
636
    }
637
638
    // Returns true if the user id is in one the specified webgroups
639
640
    /**
641
     * @param int $userid
642
     * @param array $groupNames
643
     * @return bool
644
     */
645
    public function isMemberOfWebGroupByUserId($userid = 0, $groupNames = array())
646
    {
647
        $userid = (int)$userid;
648
        // if $groupNames is not an array return false
649
        if (!is_array($groupNames)) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
introduced by
The condition is_array($groupNames) is always true.
Loading history...
650
            return false;
651
        }
652
653
        // if the user id is a negative number make it positive
654
        if (intval($userid) < 0) {
655
            $userid = -($userid);
656
        }
657
658
        // Creates an array with all webgroups the user id is in
659
        if (!array_key_exists($userid, $this->cache["mo"])) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after NOT operator; 0 found
Loading history...
660
            $tbl = $this->modx->getFullTableName("webgroup_names");
661
            $tbl2 = $this->modx->getFullTableName("web_groups");
662
            $sql = "SELECT `wgn`.`name` FROM {$tbl} `wgn` INNER JOIN {$tbl2} `wg` ON `wg`.`webgroup`=`wgn`.`id` AND `wg`.`webuser`={$userid}";
663
            $this->cache["mo"][$userid] = $grpNames = $this->modx->db->getColumn("name", $sql);
664
        } else {
665
            $grpNames = $this->cache["mo"][$userid];
666
        }
667
        // Check if a supplied group matches a webgroup from the array we just created
668
        foreach ($groupNames as $k => $v) {
669
            if (in_array(trim($v), $grpNames)) {
670
                return true;
671
            }
672
        }
673
674
        // If we get here the above logic did not find a match, so return false
675
        return false;
676
    }
677
678
    // Returns the value of a PHx/MODx placeholder.
679
680
    /**
681
     * @param $name
682
     * @return mixed|string
683
     */
684
    public function getPHxVariable($name)
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...
685
    {
686
        // Check if this variable is created by PHx
687
        if (array_key_exists($name, $this->placeholders)) {
688
            // Return the value from PHx
689
            return $this->placeholders[$name];
690
        } else {
691
            // Return the value from MODx
692
            return $this->modx->getPlaceholder($name);
0 ignored issues
show
Bug introduced by
The method getPlaceholder() does not exist on DocumentParser. ( Ignorable by Annotation )

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

692
            return $this->modx->/** @scrutinizer ignore-call */ getPlaceholder($name);

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...
693
        }
694
    }
695
696
    // Sets a placeholder variable which can only be access by PHx
697
698
    /**
699
     * @param $name
700
     * @param $value
701
     */
702
    public function setPHxVariable($name, $value)
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...
703
    {
704
        if ($name != "phx") {
705
            $this->placeholders[$name] = $value;
706
        }
707
    }
708
709
    //mbstring
710
711
    /**
712
     * @param $str
713
     * @param $s
714
     * @param null $l
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $l is correct as it would always require null to be passed?
Loading history...
715
     * @return string
716
     */
717
    public function substr($str, $s, $l = null)
718
    {
719
        if (function_exists('mb_substr')) {
720
            return mb_substr($str, $s, $l);
721
        }
722
723
        return substr($str, $s, $l);
724
    }
725
726
    /**
727
     * @param $str
728
     * @return int
729
     */
730
    public function strlen($str)
731
    {
732
        if (function_exists('mb_strlen')) {
733
            return mb_strlen($str);
734
        }
735
736
        return strlen($str);
737
    }
738
739
    /**
740
     * @param $str
741
     * @return string
742
     */
743
    public function strtolower($str)
744
    {
745
        if (function_exists('mb_strtolower')) {
746
            return mb_strtolower($str);
747
        }
748
749
        return strtolower($str);
750
    }
751
752
    /**
753
     * @param $str
754
     * @return string
755
     */
756
    public function strtoupper($str)
757
    {
758
        if (function_exists('mb_strtoupper')) {
759
            return mb_strtoupper($str);
760
        }
761
762
        return strtoupper($str);
763
    }
764
765
    /**
766
     * @param $str
767
     * @return string
768
     */
769
    public function ucfirst($str)
770
    {
771
        if (function_exists('mb_strtoupper') && function_exists('mb_substr') && function_exists('mb_strlen')) {
772
            return mb_strtoupper(mb_substr($str, 0, 1)) . mb_substr($str, 1, mb_strlen($str));
773
        }
774
775
        return ucfirst($str);
776
    }
777
778
    /**
779
     * @param $str
780
     * @return string
781
     */
782
    public function lcfirst($str)
783
    {
784
        if (function_exists('mb_strtolower') && function_exists('mb_substr') && function_exists('mb_strlen')) {
785
            return mb_strtolower(mb_substr($str, 0, 1)) . mb_substr($str, 1, mb_strlen($str));
786
        }
787
788
        return lcfirst($str);
789
    }
790
791
    /**
792
     * @param $str
793
     * @return string
794
     */
795
    public function ucwords($str)
796
    {
797
        if (function_exists('mb_convert_case')) {
798
            return mb_convert_case($str, MB_CASE_TITLE);
799
        }
800
801
        return ucwords($str);
802
    }
803
804
    /**
805
     * @param $str
806
     * @return string
807
     */
808
    public function strrev($str)
809
    {
810
        preg_match_all('/./us', $str, $ar);
811
812
        return implode(array_reverse($ar[0]));
813
    }
814
815
    /**
816
     * @param $str
817
     * @return string
818
     */
819
    public function str_shuffle($str)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::str_shuffle" 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...
820
    {
821
        preg_match_all('/./us', $str, $ar);
822
        shuffle($ar[0]);
823
824
        return implode($ar[0]);
825
    }
826
827
    /**
828
     * @param $str
829
     * @return int
830
     */
831
    public function str_word_count($str)
0 ignored issues
show
Coding Style introduced by
Method name "DLphx::str_word_count" 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...
832
    {
833
        return count(preg_split('~[^\p{L}\p{N}\']+~u', $str));
834
    }
835
}
836