Test Failed
Branch master (5aadec)
by Agel_Nash
04:00
created

DLphx::createEventLog()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
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');
1 ignored issue
show
Bug introduced by
The constant MODX_BASE_PATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
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
41
    /**
42
     * DLphx constructor.
43
     * @param int|bool|string $debug
44
     * @param int $maxpass
45
     */
46
    public function __construct($debug = false, $maxpass = 50)
47
    {
48
        global $modx;
49
50
        $this->user["mgrid"] = isset($_SESSION['mgrInternalKey']) ? intval($_SESSION['mgrInternalKey']) : 0;
51
        $this->user["usrid"] = isset($_SESSION['webInternalKey']) ? intval($_SESSION['webInternalKey']) : 0;
52
        $this->user["id"] = ($this->user["usrid"] > 0) ? (-$this->user["usrid"]) : $this->user["mgrid"];
53
54
        $this->debug = (bool)$debug;
55
56
        $this->maxPasses = ($maxpass != '') ? $maxpass : 50;
57
58
        $modx->setPlaceholder("phx", "&_PHX_INTERNAL_&");
59
        if (function_exists('mb_internal_encoding')) {
60
            mb_internal_encoding($modx->config['modx_charset']);
61
        }
62
    }
63
64
    // Plugin event hook for MODx
65
    public function OnParseDocument()
66
    {
67
        global $modx;
68
        // Get document output from MODx
69
        $template = $modx->documentOutput;
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
        $modx->documentOutput = $template;
74
    }
75
76
    // Parser: Preparation, cleaning and checkup
77
    /**
78
     * @param string $template
79
     * @return mixed|string
80
     */
81
    public function Parse($template = '')
82
    {
83
        global $modx;
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
            $modx->logEvent($this->curPass, 1, $this->createEventLog(), $this->name . ' ' . $this->version);
111
            $this->debugLog = false;
112
        }
113
114
        // Return the processed template
115
        return $template;
116
    }
117
118
    // Parser: Tag detection and replacements
119
    /**
120
     * @param string $template
121
     * @return mixed|string
122
     */
123
    public function ParseValues($template = '')
124
    {
125
        global $modx;
126
127
        $this->curPass = $this->curPass + 1;
128
        $st = md5($template);
129
130
        $this->LogPass();
131
132
        // MODX Chunks
133
        if (preg_match_all('~(?<!(?:then|else)=`){{([^:\+{}]+)([^{}]*?)}}~s', $template, $matches)) {
134
            $this->Log('MODX Chunks -> Merging all chunk tags');
135
            $count = count($matches[0]);
136
            $var_search = array();
137
            $var_replace = array();
138
            for ($i = 0; $i < $count; $i++) {
139
                $var_search[] = $matches[0][$i];
140
                $input = $matches[1][$i];
141
                $this->Log('MODX Chunk: ' . $input);
142
                $input = $modx->mergeChunkContent('{{' . $input . '}}');
143
                $var_replace[] = $this->Filter($input, $matches[2][$i]);
144
            }
145
            $template = str_replace($var_search, $var_replace, $template);
146
        }
147
148
        // MODx Snippets
149
        //if ( preg_match_all('~\[(\[|!)([^\[]*?)(!|\])\]~s',$template, $matches)) {
150
        if (preg_match_all('~(?<!(?:then|else)=`)\[(\[)([^\[]*?)(\])\]~s', $template, $matches)) {
151
            $count = count($matches[0]);
152
            $var_search = array();
153
            $var_replace = array();
154
155
            // for each detected snippet
156
            for ($i = 0; $i < $count; $i++) {
157
                $snippet = $matches[2][$i]; // snippet call
158
                $this->Log("MODx Snippet -> " . $snippet);
159
160
                // Let MODx evaluate snippet
161
                $replace = $modx->evalSnippets("[[" . $snippet . "]]");
162
                $this->LogSnippet($replace);
163
164
                // Replace values
165
                $var_search[] = $matches[0][$i];
166
                $var_replace[] = $replace;
167
            }
168
            $template = str_replace($var_search, $var_replace, $template);
169
        }
170
171
        // PHx / MODx Tags
172
        if (preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s', $template, $matches)) {
173
174
            //$matches[0] // Complete string that's need to be replaced
175
            //$matches[1] // Type
176
            //$matches[2] // The placeholder(s)
177
            //$matches[3] // The modifiers
178
            //$matches[4] // Type (end character)
179
180
            $count = count($matches[0]);
181
            $var_search = array();
182
            $var_replace = array();
183
            for ($i = 0; $i < $count; $i++) {
184
                $input = $matches[2][$i];
185
                $modifiers = $matches[3][$i];
186
                $var_search[] = $matches[0][$i];
187
                switch ($matches[1][$i]) {
188
                    // Document / Template Variable eXtended
189
                    case "*":
190
                        $this->Log("MODx TV/DV: " . $input);
191
                        $input = $modx->mergeDocumentContent("[*" . $input . "*]");
192
                        $replace = $this->Filter($input, $modifiers);
193
                        break;
194
                    // MODx Setting eXtended
195
                    case "(":
196
                        $this->Log("MODx Setting variable: " . $input);
197
                        $input = $modx->mergeSettingsContent("[(" . $input . ")]");
198
                        $replace = $this->Filter($input, $modifiers);
199
                        break;
200
                    // MODx Placeholder eXtended
201
                    default:
202
                        $this->Log("MODx / PHx placeholder variable: " . $input);
203
                        // Check if placeholder is set
204
                        if (!array_key_exists($input, $this->placeholders) && !array_key_exists($input,
205
                                $modx->placeholders)
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
     * @param $input
237
     * @param $modifiers
238
     * @return mixed|null|string
239
     */
240
    public function Filter($input, $modifiers)
241
    {
242
        global $modx;
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) {
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);
0 ignored issues
show
Unused Code introduced by
The assignment to $conditional is dead and can be removed.
Loading history...
328
                        $isvalid = intval($this->runCode($condition));
329
                        if (!$isvalid) {
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, $modx->config['modx_charset']);
369
                        break;
370
                    case "html_entity_decode":
371
                        $output = html_entity_decode($output, ENT_QUOTES, $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) {return wordwrap($m[1],$wrapat,' ',1);},$output);
396
                        break;
397
                    case "limit": // default: 100
398
                        $limit = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 100;
399
                        $output = $this->substr($output, 0, $limit);
400
                        break;
401
                    case "str_shuffle":
402
                    case "shuffle":
403
                        $output = $this->str_shuffle($output);
404
                        break;
405
                    case "str_word_count":
406
                    case "word_count":
407
                    case "wordcount":
408
                        $output = $this->str_word_count($output);
409
                        break;
410
411
                    #####  Special functions
412
                    case "math":
413
                        $filter = preg_replace("~([a-zA-Z\n\r\t\s])~", "", $modifier_value[$i]);
414
                        $filter = str_replace("?", $output, $filter);
415
                        $output = eval("return " . $filter . ";");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
416
                        break;
417
                    case "isnotempty":
418
                        if (!empty($output)) {
419
                            $output = $modifier_value[$i];
420
                        }
421
                        break;
422
                    case "isempty":
423
                    case "ifempty":
424
                        if (empty($output)) {
425
                            $output = $modifier_value[$i];
426
                        }
427
                        break;
428
                    case "nl2br":
429
                        $output = nl2br($output);
430
                        break;
431
                    case "date":
432
                        $output = strftime($modifier_value[$i], 0 + $output);
433
                        break;
434
                    case "set":
435
                        $c = $i + 1;
436
                        if ($count > $c && $modifier_cmd[$c] == "value") {
437
                            $output = preg_replace("~([^a-zA-Z0-9])~", "", $modifier_value[$i]);
438
                        }
439
                        break;
440
                    case "value":
441
                        if ($i > 0 && $modifier_cmd[$i - 1] == "set") {
442
                            $modx->SetPlaceholder("phx." . $output, $modifier_value[$i]);
443
                        }
444
                        $output = null;
445
                        break;
446
                    case "md5":
447
                        $output = md5($output);
448
                        break;
449
                    case "userinfo":
450
                        if ($output == "&_PHX_INTERNAL_&") {
451
                            $output = $this->user["id"];
452
                        }
453
                        $output = $this->ModUser($output, $modifier_value[$i]);
454
                        break;
455
                    case "inrole": // deprecated
456
                        if ($output == "&_PHX_INTERNAL_&") {
457
                            $output = $this->user["id"];
458
                        }
459
                        $grps = ($this->strlen($modifier_value[$i]) > 0) ? explode(",", $modifier_value[$i]) : array();
460
                        $output = intval($this->isMemberOfWebGroupByUserId($output, $grps));
461
                        break;
462
463
                    // If we haven't yet found the modifier, let's look elsewhere
464
                    default:
465
                        $snippet = '';
466
                        // modified by Anton Kuzmin (23.06.2010) //
467
                        $snippetName = 'phx:' . $modifier_cmd[$i];
468
                        if (isset($modx->snippetCache[$snippetName])) {
469
                            $snippet = $modx->snippetCache[$snippetName];
470
                        } else { // not in cache so let's check the db
471
                            $sql = "SELECT snippet FROM " . $modx->getFullTableName("site_snippets") . " WHERE " . $modx->getFullTableName("site_snippets") . ".name='" . $modx->db->escape($snippetName) . "';";
472
                            $result = $modx->dbQuery($sql);
473
                            if ($modx->recordCount($result) == 1) {
474
                                $row = $modx->fetchRow($result);
475
                                $snippet = $modx->snippetCache[$row['name']] = $row['snippet'];
476
                                $this->Log("  |--- DB -> Custom Modifier");
477
                            } else {
478
                                if ($modx->recordCount($result) == 0) { // If snippet not found, look in the modifiers folder
479
                                    $filename = $modx->config['rb_base_dir'] . 'plugins/phx/modifiers/' . $modifier_cmd[$i] . '.phx.php';
480
                                    if (@file_exists($filename)) {
481
                                        $file_contents = @file_get_contents($filename);
482
                                        $file_contents = str_replace('<' . '?php', '', $file_contents);
483
                                        $file_contents = str_replace('?' . '>', '', $file_contents);
484
                                        $file_contents = str_replace('<?', '', $file_contents);
485
                                        $snippet = $modx->snippetCache[$snippetName] = $file_contents;
486
                                        $modx->snippetCache[$snippetName . 'Props'] = '';
487
                                        $this->Log("  |--- File ($filename) -> Custom Modifier");
488
                                    } else {
489
                                        $this->Log("  |--- PHX Error:  {$modifier_cmd[$i]} could not be found");
490
                                    }
491
                                }
492
                            }
493
                        }
494
                        $cm = $snippet;
495
                        // end //
496
497
                        if (!empty($cm)) {
498
                            ob_start();
499
                            $options = $modifier_value[$i];
0 ignored issues
show
Unused Code introduced by
The assignment to $options is dead and can be removed.
Loading history...
500
                            $custom = eval($cm);
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
501
                            $msg = ob_get_contents();
502
                            $output = $msg . $custom;
503
                            ob_end_clean();
504
                        } else {
505
                            $output = '';
506
                        }
507
                        break;
508
                }
509
                if (count($condition)) {
510
                    $this->Log("  |--- Condition = '" . $condition[count($condition) - 1] . "'");
511
                }
512
                $this->Log("  |--- Output = '" . $output . "'");
513
            }
514
        }
515
516
        return $output;
517
    }
518
519
    private function runCode($code){
520
        return eval("return (" . $code . ");");
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
521
    }
522
    // Event logging (debug)
523
    /**
524
     * @return string
525
     */
526
    public function createEventLog()
527
    {
528
        if (!empty($this->console)) {
529
            $console = implode("\n", $this->console);
530
            $this->console = array();
531
532
            return '<pre style="overflow: auto;">' . $console . '</pre>';
533
        }
534
    }
535
536
    // Returns a cleaned string escaping the HTML and special MODx characters
537
    /**
538
     * @param $string
539
     * @return array|mixed|string
540
     */
541
    public function LogClean($string)
542
    {
543
        $string = preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", $string);
544
        $string = APIHelpers::sanitarTag($string);
545
546
        return $string;
547
    }
548
549
    // Simple log entry
550
    /**
551
     * @param $string
552
     */
553
    public function Log($string)
554
    {
555
        if ($this->debug) {
556
            $this->debugLog = true;
557
            $this->console[] = (count($this->console) + 1 - $this->curPass) . " [" . strftime("%H:%M:%S",
558
                    time()) . "] " . $this->LogClean($string);
0 ignored issues
show
Bug introduced by
Are you sure $this->LogClean($string) of type string|array 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

558
                    time()) . "] " . /** @scrutinizer ignore-type */ $this->LogClean($string);
Loading history...
559
        }
560
    }
561
562
    // Log snippet output
563
    /**
564
     * @param $string
565
     */
566
    public function LogSnippet($string)
567
    {
568
        if ($this->debug) {
569
            $this->debugLog = true;
570
            $this->console[] = (count($this->console) + 1 - $this->curPass) . " [" . strftime("%H:%M:%S",
571
                    time()) . "] " . "  |--- Returns: <div style='margin: 10px;'>" . $this->LogClean($string) . "</div>";
0 ignored issues
show
Bug introduced by
Are you sure $this->LogClean($string) of type string|array 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

571
                    time()) . "] " . "  |--- Returns: <div style='margin: 10px;'>" . /** @scrutinizer ignore-type */ $this->LogClean($string) . "</div>";
Loading history...
572
        }
573
    }
574
575
    // Log pass
576
    public function LogPass()
577
    {
578
        $this->console[] = "<div style='margin: 2px;margin-top: 5px;border-bottom: 1px solid black;'>Pass " . $this->curPass . "</div>";
579
    }
580
581
    // Log pass
582
    /**
583
     * @param $string
584
     */
585
    public function LogSource($string)
586
    {
587
        $this->console[] = "<div style='margin: 2px;margin-top: 5px;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 string|array 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

587
        $this->console[] = "<div style='margin: 2px;margin-top: 5px;border-bottom: 1px solid black;'>Source:</div>" . /** @scrutinizer ignore-type */ $this->LogClean($string);
Loading history...
588
    }
589
590
591
    // Returns the specified field from the user record
592
    // positive userid = manager, negative integer = webuser
593
    /**
594
     * @param $userid
595
     * @param $field
596
     * @return mixed
597
     */
598
    public function ModUser($userid, $field)
599
    {
600
        global $modx;
601
        if (!array_key_exists($userid, $this->cache["ui"])) {
602
            if (intval($userid) < 0) {
603
                $user = $modx->getWebUserInfo(-($userid));
604
            } else {
605
                $user = $modx->getUserInfo($userid);
606
            }
607
            $this->cache["ui"][$userid] = $user;
608
        } else {
609
            $user = $this->cache["ui"][$userid];
610
        }
611
612
        return $user[$field];
613
    }
614
615
    // Returns true if the user id is in one the specified webgroups
616
    /**
617
     * @param int $userid
618
     * @param array $groupNames
619
     * @return bool
620
     */
621
    public function isMemberOfWebGroupByUserId($userid = 0, $groupNames = array())
622
    {
623
        global $modx;
624
625
        // if $groupNames is not an array return false
626
        if (!is_array($groupNames)) {
0 ignored issues
show
introduced by
The condition ! is_array($groupNames) can never be true.
Loading history...
627
            return false;
628
        }
629
630
        // if the user id is a negative number make it positive
631
        if (intval($userid) < 0) {
632
            $userid = -($userid);
633
        }
634
635
        // Creates an array with all webgroups the user id is in
636
        if (!array_key_exists($userid, $this->cache["mo"])) {
637
            $tbl = $modx->getFullTableName("webgroup_names");
638
            $tbl2 = $modx->getFullTableName("web_groups");
639
            $sql = "SELECT wgn.name FROM $tbl wgn INNER JOIN $tbl2 wg ON wg.webgroup=wgn.id AND wg.webuser='" . $userid . "'";
640
            $this->cache["mo"][$userid] = $grpNames = $modx->db->getColumn("name", $sql);
641
        } else {
642
            $grpNames = $this->cache["mo"][$userid];
643
        }
644
        // Check if a supplied group matches a webgroup from the array we just created
645
        foreach ($groupNames as $k => $v) {
646
            if (in_array(trim($v), $grpNames)) {
647
                return true;
648
            }
649
        }
650
651
        // If we get here the above logic did not find a match, so return false
652
        return false;
653
    }
654
655
    // Returns the value of a PHx/MODx placeholder.
656
    /**
657
     * @param $name
658
     * @return mixed|string
659
     */
660
    public function getPHxVariable($name)
661
    {
662
        global $modx;
663
        // Check if this variable is created by PHx
664
        if (array_key_exists($name, $this->placeholders)) {
665
            // Return the value from PHx
666
            return $this->placeholders[$name];
667
        } else {
668
            // Return the value from MODx
669
            return $modx->getPlaceholder($name);
670
        }
671
    }
672
673
    // Sets a placeholder variable which can only be access by PHx
674
    /**
675
     * @param $name
676
     * @param $value
677
     */
678
    public function setPHxVariable($name, $value)
679
    {
680
        if ($name != "phx") {
681
            $this->placeholders[$name] = $value;
682
        }
683
    }
684
685
    //mbstring
686
    /**
687
     * @param $str
688
     * @param $s
689
     * @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...
690
     * @return string
691
     */
692
    public function substr($str, $s, $l = null)
693
    {
694
        if (function_exists('mb_substr')) {
695
            return mb_substr($str, $s, $l);
696
        }
697
698
        return substr($str, $s, $l);
699
    }
700
701
    /**
702
     * @param $str
703
     * @return int
704
     */
705
    public function strlen($str)
706
    {
707
        if (function_exists('mb_strlen')) {
708
            return mb_strlen($str);
709
        }
710
711
        return strlen($str);
712
    }
713
714
    /**
715
     * @param $str
716
     * @return string
717
     */
718
    public function strtolower($str)
719
    {
720
        if (function_exists('mb_strtolower')) {
721
            return mb_strtolower($str);
722
        }
723
724
        return strtolower($str);
725
    }
726
727
    /**
728
     * @param $str
729
     * @return string
730
     */
731
    public function strtoupper($str)
732
    {
733
        if (function_exists('mb_strtoupper')) {
734
            return mb_strtoupper($str);
735
        }
736
737
        return strtoupper($str);
738
    }
739
740
    /**
741
     * @param $str
742
     * @return string
743
     */
744
    public function ucfirst($str)
745
    {
746
        if (function_exists('mb_strtoupper') && function_exists('mb_substr') && function_exists('mb_strlen')) {
747
            return mb_strtoupper(mb_substr($str, 0, 1)) . mb_substr($str, 1, mb_strlen($str));
748
        }
749
750
        return ucfirst($str);
751
    }
752
753
    /**
754
     * @param $str
755
     * @return string
756
     */
757
    public function lcfirst($str)
758
    {
759
        if (function_exists('mb_strtolower') && function_exists('mb_substr') && function_exists('mb_strlen')) {
760
            return mb_strtolower(mb_substr($str, 0, 1)) . mb_substr($str, 1, mb_strlen($str));
761
        }
762
763
        return lcfirst($str);
764
    }
765
766
    /**
767
     * @param $str
768
     * @return string
769
     */
770
    public function ucwords($str)
771
    {
772
        if (function_exists('mb_convert_case')) {
773
            return mb_convert_case($str, MB_CASE_TITLE);
774
        }
775
776
        return ucwords($str);
777
    }
778
779
    /**
780
     * @param $str
781
     * @return string
782
     */
783
    public function strrev($str)
784
    {
785
        preg_match_all('/./us', $str, $ar);
786
787
        return implode(array_reverse($ar[0]));
788
    }
789
790
    /**
791
     * @param $str
792
     * @return string
793
     */
794
    public function str_shuffle($str)
795
    {
796
        preg_match_all('/./us', $str, $ar);
797
        shuffle($ar[0]);
798
799
        return implode($ar[0]);
800
    }
801
802
    /**
803
     * @param $str
804
     * @return int
805
     */
806
    public function str_word_count($str)
807
    {
808
        return count(preg_split('~[^\p{L}\p{N}\']+~u', $str));
0 ignored issues
show
Bug introduced by
It seems like preg_split('~[^\p{L}\p{N}']+~u', $str) can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, 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

808
        return count(/** @scrutinizer ignore-type */ preg_split('~[^\p{L}\p{N}\']+~u', $str));
Loading history...
809
    }
810
}
811