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');
|
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_&");
|
|
|
|
|
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()
|
|
|
|
|
67
|
|
|
{
|
68
|
|
|
// Get document output from MODx
|
69
|
|
|
$template = $this->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
|
|
|
$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 = '')
|
|
|
|
|
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);
|
|
|
|
|
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 = '')
|
|
|
|
|
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 . '}}');
|
|
|
|
|
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 . "]]");
|
|
|
|
|
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;
|
|
|
|
|
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 . "*]");
|
|
|
|
|
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 . ")]");
|
|
|
|
|
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(
|
|
|
|
|
203
|
|
|
$input,
|
204
|
|
|
$this->modx->placeholders
|
|
|
|
|
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)
|
|
|
|
|
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) {
|
|
|
|
|
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) {
|
|
|
|
|
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("/&(#[0-9]+|[a-z]+);/i", "&$1;", APIHelpers::e($output));
|
375
|
|
|
$output = str_replace(array("[", "]", "`"), array("[", "]", "`"), $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 . ";");
|
|
|
|
|
418
|
|
|
break;
|
419
|
|
|
case "isnotempty":
|
420
|
|
|
if (!empty($output)) {
|
|
|
|
|
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]);
|
|
|
|
|
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])) {
|
|
|
|
|
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)) {
|
|
|
|
|
505
|
|
|
$output = $this->modx->runSnippet($snippetName, array(
|
|
|
|
|
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 . ");");
|
|
|
|
|
532
|
|
|
}
|
533
|
|
|
|
534
|
|
|
// Event logging (debug)
|
535
|
|
|
|
536
|
|
|
/**
|
537
|
|
|
* @return string
|
538
|
|
|
*/
|
539
|
|
|
public function createEventLog()
|
540
|
|
|
{
|
541
|
|
|
$out = '';
|
542
|
|
|
if (!empty($this->console)) {
|
|
|
|
|
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)
|
|
|
|
|
559
|
|
|
{
|
560
|
|
|
$string = preg_replace("/&(#[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)
|
|
|
|
|
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);
|
|
|
|
|
579
|
|
|
}
|
580
|
|
|
}
|
581
|
|
|
|
582
|
|
|
// Log snippet output
|
583
|
|
|
|
584
|
|
|
/**
|
585
|
|
|
* @param $string
|
586
|
|
|
*/
|
587
|
|
|
public function LogSnippet($string)
|
|
|
|
|
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>";
|
|
|
|
|
595
|
|
|
}
|
596
|
|
|
}
|
597
|
|
|
|
598
|
|
|
// Log pass
|
599
|
|
|
public function LogPass()
|
|
|
|
|
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)
|
|
|
|
|
610
|
|
|
{
|
611
|
|
|
$this->console[] = "<div style='margin: 5px 2px 2px;border-bottom: 1px solid black;'>Source:</div>" . $this->LogClean($string);
|
|
|
|
|
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)
|
|
|
|
|
623
|
|
|
{
|
624
|
|
|
if (!array_key_exists($userid, $this->cache["ui"])) {
|
|
|
|
|
625
|
|
|
if (intval($userid) < 0) {
|
626
|
|
|
$user = $this->modx->getWebUserInfo(-($userid));
|
|
|
|
|
627
|
|
|
} else {
|
628
|
|
|
$user = $this->modx->getUserInfo($userid);
|
|
|
|
|
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)) {
|
|
|
|
|
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"])) {
|
|
|
|
|
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)
|
|
|
|
|
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);
|
|
|
|
|
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)
|
|
|
|
|
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
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
832
|
|
|
{
|
833
|
|
|
return count(preg_split('~[^\p{L}\p{N}\']+~u', $str));
|
834
|
|
|
}
|
835
|
|
|
}
|
836
|
|
|
|