PageRenderTime 59ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/assets/snippets/ajaxSearch/classes/asPhxParser.class.inc.php

https://github.com/good-web-master/modx.evo.custom
PHP | 436 lines | 330 code | 36 blank | 70 comment | 64 complexity | 9e74f08d1f50853877c21ee8c58963a4 MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0, MIT, BSD-3-Clause
  1. <?php
  2. /* -----------------------------------------------------------------------------
  3. *
  4. * Name: PHx (Placeholders Xtended)
  5. * Version: 2.1.3
  6. *
  7. * Author: Armand "bS" Pondman (apondman@zerobarrier.nl)
  8. * Date: July 13, 2007
  9. *
  10. * Adapted by Coroico for AjaxSearch => AsPHxParser
  11. * Merge of the chunkie and PHxParser classes
  12. * cleanVars and unsetPHxVariable functions added
  13. *
  14. */
  15. class asPHxParser {
  16. var $placeholders = array();
  17. function asPHxParser($template='',$maxpass=500) {
  18. global $modx;
  19. $this->name = "PHx";
  20. $this->version = "2.1.3";
  21. $this->template = $this->getTemplate($template);
  22. $this->user["mgrid"] = intval($_SESSION['mgrInternalKey']);
  23. $this->user["usrid"] = intval($_SESSION['webInternalKey']);
  24. $this->user["id"] = ($this->user["usrid"] > 0 ) ? (-$this->user["usrid"]) : $this->user["mgrid"];
  25. $this->cache["cm"] = array();
  26. $this->cache["ui"] = array();
  27. $this->cache["mo"] = array();
  28. $this->safetags[0][0] = '~(?<![\[]|^\^)\[(?=[^\+\*\(\[]|$)~s';
  29. $this->safetags[0][1] = '~(?<=[^\+\*\)\]]|^)\](?=[^\]]|$)~s';
  30. $this->safetags[1][0] = '&_PHX_INTERNAL_091_&';
  31. $this->safetags[1][1] = '&_PHX_INTERNAL_093_&';
  32. $this->safetags[2][0] = '[';
  33. $this->safetags[2][1] = ']';
  34. $this->console = array();
  35. $this->curPass = 0;
  36. $this->maxPasses = ($maxpass!='') ? $maxpass : 500;
  37. $this->swapSnippetCache = array();
  38. $modx->setPlaceholder("phx", "&_PHX_INTERNAL_&");
  39. }
  40. // ====================================================================== parser part
  41. // Plugin event hook for MODx
  42. function OnParseDocument() {
  43. global $modx;
  44. // Get document output from MODx
  45. $template = $modx->documentOutput;
  46. // To the parse cave .. let's go! *insert batman tune here*
  47. $template = $this->Parse($template);
  48. // Set processed document output in MODx
  49. $modx->documentOutput = $template;
  50. }
  51. // Parser: Preparation, cleaning and checkup
  52. function Parse($template='') {
  53. global $modx;
  54. // If we already reached max passes don't get at it again.
  55. if ($this->curPass == $this->maxPasses) return $template;
  56. // Set template pre-process hash
  57. $st = md5($template);
  58. // Replace non-call characters in the template: [, ]
  59. $template = preg_replace($this->safetags[0],$this->safetags[1],$template);
  60. // To the parse mobile.. let's go! *insert batman tune here*
  61. $template = $this->ParseValues($template);
  62. // clean up unused placeholders that have modifiers attached (MODx can't clean them)
  63. preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s', $template, $matches);
  64. if ($matches[0]) $template = str_replace($matches[0], '', $template);
  65. // Restore non-call characters in the template: [, ]
  66. $template = str_replace($this->safetags[1],$this->safetags[2],$template);
  67. // Set template post-process hash
  68. $et = md5($template);
  69. // If template has changed, parse it once more...
  70. if ($st!=$et) $template = $this->Parse($template);
  71. // Return the processed template
  72. return $template;
  73. }
  74. // Parser: Tag detection and replacements
  75. function ParseValues($template='') {
  76. global $modx;
  77. $this->curPass = $this->curPass + 1;
  78. $st = md5($template);
  79. // MODx Chunks
  80. $template = $modx->mergeChunkContent($template);
  81. // MODx Snippets
  82. if ( preg_match_all('~\[(\[)([^\[]*?)(\])\]~s',$template, $matches)) {
  83. $count = count($matches[0]);
  84. $var_search = array();
  85. $var_replace = array();
  86. // for each detected snippet
  87. for($i=0; $i<$count; $i++) {
  88. $snippet = $matches[2][$i]; // snippet call
  89. // Let MODx evaluate snippet
  90. $replace = $modx->evalSnippets("[[".$snippet."]]");
  91. // Replace values
  92. $var_search[] = $matches[0][$i];
  93. $var_replace[] = $replace;
  94. }
  95. $template = str_replace($var_search, $var_replace, $template);
  96. }
  97. // PHx / MODx Tags
  98. if ( preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s',$template, $matches)) {
  99. //$matches[0] // Complete string that's need to be replaced
  100. //$matches[1] // Type
  101. //$matches[2] // The placeholder(s)
  102. //$matches[3] // The modifiers
  103. //$matches[4] // Type (end character)
  104. $count = count($matches[0]);
  105. $var_search = array();
  106. $var_replace = array();
  107. for($i=0; $i<$count; $i++) {
  108. $replace = NULL;
  109. $match = $matches[0][$i];
  110. $type = $matches[1][$i];
  111. $type_end = $matches[4][$i];
  112. $input = $matches[2][$i];
  113. $modifiers = $matches[3][$i];
  114. $var_search[] = $match;
  115. switch($type) {
  116. // Document / Template Variable eXtended
  117. case "*":
  118. $input = $modx->mergeDocumentContent("[*".$input."*]");
  119. $replace = $this->Filter($input,$modifiers);
  120. break;
  121. // MODx Setting eXtended
  122. case "(":
  123. $input = $modx->mergeSettingsContent("[(".$input.")]");
  124. $replace = $this->Filter($input,$modifiers);
  125. break;
  126. // MODx Placeholder eXtended
  127. default:
  128. // Check if placeholder is set
  129. if ( !array_key_exists($input, $this->placeholders) && !array_key_exists($input, $modx->placeholders) ) {
  130. // not set so try again later.
  131. $replace = $match;
  132. }
  133. else {
  134. // is set, get value and run filter
  135. $input = $this->getPHxVariable($input);
  136. $replace = $this->Filter($input,$modifiers);
  137. }
  138. break;
  139. }
  140. $var_replace[] = $replace;
  141. }
  142. $template = str_replace($var_search, $var_replace, $template);
  143. }
  144. $et = md5($template); // Post-process template hash
  145. // If this pass is not at maximum passes and the template hash is not the same, get at it again.
  146. if (($this->curPass < $this->maxPasses) && ($st!=$et)) $template = $this->ParseValues($template);
  147. return $template;
  148. }
  149. // Parser: modifier detection and eXtended processing if needed
  150. function Filter($input, $modifiers) {
  151. global $modx;
  152. $output = $input;
  153. if (preg_match_all('~:([^:=]+)(?:=`(.*?)`(?=:[^:=]+|$))?~s',$modifiers, $matches)) {
  154. $modifier_cmd = $matches[1]; // modifier command
  155. $modifier_value = $matches[2]; // modifier value
  156. $count = count($modifier_cmd);
  157. $condition = array();
  158. for($i=0; $i<$count; $i++) {
  159. $output = trim($output);
  160. switch ($modifier_cmd[$i]) {
  161. ##### Conditional Modifiers
  162. case "input": case "if": $output = $modifier_value[$i]; break;
  163. case "equals": case "is": case "eq": $condition[] = intval(($output==$modifier_value[$i])); break;
  164. case "notequals": case "isnot": case "isnt": case "ne":$condition[] = intval(($output!=$modifier_value[$i]));break;
  165. case "isgreaterthan": case "isgt": case "eg": $condition[] = intval(($output>=$modifier_value[$i]));break;
  166. case "islowerthan": case "islt": case "el": $condition[] = intval(($output<=$modifier_value[$i]));break;
  167. case "greaterthan": case "gt": $condition[] = intval(($output>$modifier_value[$i]));break;
  168. case "lowerthan": case "lt":$condition[] = intval(($output<$modifier_value[$i]));break;
  169. case "isinrole": case "ir": case "memberof": case "mo": // Is Member Of (same as inrole but this one can be stringed as a conditional)
  170. if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  171. $grps = (strlen($modifier_value[$i]) > 0 ) ? explode(",",$modifier_value[$i]) :array();
  172. $condition[] = intval($this->isMemberOfWebGroupByUserId($output,$grps));
  173. break;
  174. case "or":$condition[] = "||";break;
  175. case "and": $condition[] = "&&";break;
  176. case "show":
  177. $conditional = implode(' ',$condition);
  178. $isvalid = intval(eval("return (". $conditional. ");"));
  179. if (!$isvalid) { $output = NULL;}
  180. case "then":
  181. $conditional = implode(' ',$condition);
  182. $isvalid = intval(eval("return (". $conditional. ");"));
  183. if ($isvalid) { $output = $modifier_value[$i]; }
  184. else { $output = NULL; }
  185. break;
  186. case "else":
  187. $conditional = implode(' ',$condition);
  188. $isvalid = intval(eval("return (". $conditional. ");"));
  189. if (!$isvalid) { $output = $modifier_value[$i]; }
  190. break;
  191. case "select":
  192. $raw = explode("&",$modifier_value[$i]);
  193. $map = array();
  194. for($m=0; $m<(count($raw)); $m++) {
  195. $mi = explode("=",$raw[$m]);
  196. $map[$mi[0]] = $mi[1];
  197. }
  198. $output = $map[$output];
  199. break;
  200. ##### End of Conditional Modifiers
  201. ##### String Modifiers
  202. case "lcase": $output = strtolower($output); break;
  203. case "ucase": $output = strtoupper($output); break;
  204. case "ucfirst": $output = ucfirst($output); break;
  205. case "htmlent": $output = htmlentities($output,ENT_QUOTES,$modx->config['etomite_charset']); break;
  206. case "esc":
  207. $output = preg_replace("/&amp;(#[0-9]+|[a-z]+);/i", "&$1;", htmlspecialchars($output));
  208. $output = str_replace(array("[","]","`"),array("&#91;","&#93;","&#96;"),$output);
  209. break;
  210. case "strip": $output = preg_replace("~([\n\r\t\s]+)~"," ",$output); break;
  211. case "notags": $output = strip_tags($output); break;
  212. case "length": case "len": $output = strlen($output); break;
  213. case "reverse": $output = strrev($output); break;
  214. case "wordwrap": // default: 70
  215. $wrapat = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 70;
  216. $output = preg_replace("~(\b\w+\b)~e","wordwrap('\\1',\$wrapat,' ',1)",$output);
  217. break;
  218. case "limit": // default: 100
  219. $limit = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 100;
  220. $output = substr($output,0,$limit);
  221. break;
  222. ##### Special functions
  223. // img modifiers added by coroico
  224. case "imgwidth": list($width, $height, $type, $attr) = getimagesize($output); $output = $width; break;
  225. case "imgheight": list($width, $height, $type, $attr) = getimagesize($output); $output = $height; break;
  226. case "imgattr": list($width, $height, $type, $attr) = getimagesize($output); $output = $attr; break;
  227. case "imgmaxwidth":
  228. list($width, $height, $type, $attr) = getimagesize($output);
  229. $output = ($width < intval($modifier_value[$i])) ? $width : intval($modifier_value[$i]);
  230. break;
  231. case "imgmaxheight":
  232. list($width, $height, $type, $attr) = getimagesize($output);
  233. $output = ($height < intval($modifier_value[$i])) ? $height : intval($modifier_value[$i]);
  234. break;
  235. case "math":
  236. $filter = preg_replace("~([a-zA-Z\n\r\t\s])~","",$modifier_value[$i]);
  237. $filter = str_replace("?",$output,$filter);
  238. $output = eval("return ".$filter.";");
  239. break;
  240. case "ifempty": if (empty($output)) $output = $modifier_value[$i]; break;
  241. case "nl2br": $output = nl2br($output); break;
  242. case "date": $output = strftime($modifier_value[$i],0+$output); break;
  243. case "set":
  244. $c = $i+1;
  245. if ($count>$c&&$modifier_cmd[$c]=="value") $output = preg_replace("~([^a-zA-Z0-9])~","",$modifier_value[$i]);
  246. break;
  247. case "value":
  248. if ($i>0&&$modifier_cmd[$i-1]=="set") { $modx->SetPlaceholder("phx.".$output,$modifier_value[$i]); }
  249. $output = NULL;
  250. break;
  251. case "md5": $output = md5($output); break;
  252. case "userinfo":
  253. if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  254. $output = $this->ModUser($output,$modifier_value[$i]);
  255. break;
  256. case "inrole": // deprecated
  257. if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  258. $grps = (strlen($modifier_value[$i]) > 0 ) ? explode(",",$modifier_value[$i]) :array();
  259. $output = intval($this->isMemberOfWebGroupByUserId($output,$grps));
  260. break;
  261. default:
  262. if (!array_key_exists($modifier_cmd[$i], $this->cache["cm"])) {
  263. $phx_snippet_name = 'phx:' . $modx->db->escape($modifier_cmd[$i]);
  264. $sql = "SELECT snippet FROM " . $modx->getFullTableName("site_snippets") . " WHERE " . $modx->getFullTableName("site_snippets") . ".name='" . $phx_snippet_name . "';";
  265. $result = $modx->dbQuery($sql);
  266. if ($modx->recordCount($result) == 1) {
  267. $row = $modx->fetchRow($result);
  268. $cm = $this->cache["cm"][$modifier_cmd[$i]] = $row["snippet"];
  269. } else if ($modx->recordCount($result) == 0){ // If snippet not found, look in the modifiers folder
  270. $filename = $modx->config['rb_base_dir'] . 'plugins/phx/modifiers/'.$modifier_cmd[$i].'.phx.php';
  271. if (@file_exists($filename)) {
  272. $file_contents = @file_get_contents($filename);
  273. $file_contents = str_replace('<?php', '', $file_contents);
  274. $file_contents = str_replace('?>', '', $file_contents);
  275. $file_contents = str_replace('<?', '', $file_contents);
  276. $cm = $this->cache["cm"][$modifier_cmd[$i]] = $file_contents;
  277. }
  278. }
  279. } else {
  280. $cm = $this->cache["cm"][$modifier_cmd[$i]];
  281. }
  282. ob_start();
  283. $options = $modifier_value[$i];
  284. $custom = eval($cm);
  285. $msg = ob_get_contents();
  286. $output = $msg.$custom;
  287. ob_end_clean();
  288. break;
  289. }
  290. }
  291. }
  292. return $output;
  293. }
  294. // Returns the specified field from the user record
  295. // positive userid = manager, negative integer = webuser
  296. function ModUser($userid,$field) {
  297. global $modx;
  298. if (!array_key_exists($userid, $this->cache["ui"])) {
  299. if (intval($userid) < 0) {
  300. $user = $modx->getWebUserInfo(-($userid));
  301. } else {
  302. $user = $modx->getUserInfo($userid);
  303. }
  304. $this->cache["ui"][$userid] = $user;
  305. } else {
  306. $user = $this->cache["ui"][$userid];
  307. }
  308. return $user[$field];
  309. }
  310. // Returns true if the user id is in one the specified webgroups
  311. function isMemberOfWebGroupByUserId($userid=0,$groupNames=array()) {
  312. global $modx;
  313. // if $groupNames is not an array return false
  314. if(!is_array($groupNames)) return false;
  315. // if the user id is a negative number make it positive
  316. if (intval($userid) < 0) { $userid = -($userid); }
  317. // Creates an array with all webgroups the user id is in
  318. if (!array_key_exists($userid, $this->cache["mo"])) {
  319. $tbl = $modx->getFullTableName("webgroup_names");
  320. $tbl2 = $modx->getFullTableName("web_groups");
  321. $sql = "SELECT wgn.name FROM $tbl wgn INNER JOIN $tbl2 wg ON wg.webgroup=wgn.id AND wg.webuser='".$userid."'";
  322. $this->cache["mo"][$userid] = $grpNames = $modx->db->getColumn("name",$sql);
  323. } else {
  324. $grpNames = $this->cache["mo"][$userid];
  325. }
  326. // Check if a supplied group matches a webgroup from the array we just created
  327. foreach($groupNames as $k=>$v)
  328. if(in_array(trim($v),$grpNames)) return true;
  329. // If we get here the above logic did not find a match, so return false
  330. return false;
  331. }
  332. // Returns the value of a PHx/MODx placeholder.
  333. function getPHxVariable($name) {
  334. global $modx;
  335. // Check if this variable is created by PHx
  336. if (array_key_exists($name, $this->placeholders)) {
  337. // Return the value from PHx
  338. return $this->placeholders[$name];
  339. } else {
  340. // Return the value from MODx
  341. return $modx->getPlaceholder($name);
  342. }
  343. }
  344. // Sets a placeholder variable which can only be access by PHx
  345. function setPHxVariable($name, $value) {
  346. if ($name != "phx") $this->placeholders[$name] = $value;
  347. }
  348. // unset all the placeholders - Added by coroico
  349. function unsetPHxVariable() {
  350. unset($this->placeholders);
  351. }
  352. // ====================================================================== chunkie part
  353. function CreateVars($value = '', $key = '', $path = '') {
  354. $keypath = !empty($path) ? $path . "." . $key : $key;
  355. if (is_array($value)) {
  356. foreach ($value as $subkey => $subval) {
  357. $this->CreateVars($subval, $subkey, $keypath);
  358. }
  359. } else {
  360. $this->setPHxVariable($keypath, $value);
  361. }
  362. }
  363. function AddVar($name, $value) {
  364. $this->CreateVars($value, $name);
  365. }
  366. // Added by coroico
  367. function CleanVars() {
  368. $this->unsetPHxVariable();
  369. }
  370. function Render() {
  371. $template = $this->Parse($this->template);
  372. return $template;
  373. }
  374. function getTemplate($tpl) {
  375. global $modx;
  376. $template = "";
  377. if ($modx->getChunk($tpl) != "") {
  378. $template = $modx->getChunk($tpl);
  379. } else if (substr($tpl, 0, 6) == "@FILE:") {
  380. $template = $this->get_file_contents($modx->config['base_path'] . substr($tpl, 6));
  381. } else if (substr($tpl, 0, 6) == "@CODE:") {
  382. $template = substr($tpl, 6);
  383. } else {
  384. $template = FALSE;
  385. }
  386. return $template;
  387. }
  388. function get_file_contents($filename) {
  389. // Returns the contents of file name passed
  390. if (!function_exists('file_get_contents')) {
  391. $fhandle = fopen($filename, "r");
  392. $fcontents = fread($fhandle, filesize($filename));
  393. fclose($fhandle);
  394. } else {
  395. $fcontents = file_get_contents($filename);
  396. }
  397. return $fcontents;
  398. }
  399. }
  400. ?>