Advertisement
Guest User

Untitled

a guest
Sep 8th, 2017
543
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 17.52 KB | None | 0 0
  1. <?php
  2. /*####
  3. #
  4. #   Name: PHx (Placeholders Xtended)
  5. #   Version: 2.1.3
  6. #   Modified by Nick to include external files
  7. #   Author: Armand "bS" Pondman (apondman@zerobarrier.nl)
  8. #   Date: July 13, 2007
  9. #
  10. ####*/
  11.  
  12. class PHxParser {
  13.     var $placeholders = array();
  14.  
  15.     function PHxParser($debug=0,$maxpass=50) {
  16.         global $modx;
  17.         $this->name = "PHx";
  18.         $this->version = "2.1.3";
  19.         $this->user["mgrid"] = intval($_SESSION['mgrInternalKey']);
  20.         $this->user["usrid"] = intval($_SESSION['webInternalKey']);
  21.         $this->user["id"] = ($this->user["usrid"] > 0 ) ? (-$this->user["usrid"]) : $this->user["mgrid"];
  22.         $this->cache["cm"] = array();
  23.         $this->cache["ui"] = array();
  24.         $this->cache["mo"] = array();
  25.         $this->safetags[0][0] = '~(?<![\[]|^\^)\[(?=[^\+\*\(\[]|$)~s';
  26.         $this->safetags[0][1] = '~(?<=[^\+\*\)\]]|^)\](?=[^\]]|$)~s';
  27.         $this->safetags[1][0] = '&_PHX_INTERNAL_091_&';
  28.         $this->safetags[1][1] = '&_PHX_INTERNAL_093_&';
  29.         $this->safetags[2][0] = '[';
  30.         $this->safetags[2][1] = ']';
  31.         $this->console = array();
  32.         $this->debug = ($debug!='') ? $debug : 0;
  33.         $this->debugLog = false;
  34.         $this->curPass = 0;
  35.         $this->maxPasses = ($maxpass!='') ? $maxpass : 50;
  36.         $this->swapSnippetCache = array();
  37.         $modx->setPlaceholder("phx", "&_PHX_INTERNAL_&");
  38.     }
  39.  
  40.     // Plugin event hook for MODx
  41.     function OnParseDocument() {
  42.         global $modx;
  43.         // Get document output from MODx
  44.         $template = $modx->documentOutput;
  45.         // To the parse cave .. let's go! *insert batman tune here*
  46.         $template = $this->Parse($template);
  47.         // Set processed document output in MODx
  48.         $modx->documentOutput = $template;
  49.     }
  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.         $withModifiers = 0;
  64.         preg_match_all('~\[(\+|\*|\()  ([^:\+\[\]]+)  ([^\[\]]*?)  (\1|\))\]~s', $template, $matches);
  65.         if ($matches[0]) {
  66.             if(is_array($matches[0])) {
  67.                 foreach($matches[0] as $k->$m) {
  68.                     if(empty($matches[3][$k])) {
  69.                         unset($matches[0][$k],$matches[1][$k],$matches[2][$k],$matches[3][$k]);
  70.                     } else {
  71.                         ++$withModifiers;
  72.                     }
  73.                 }
  74.             } else {
  75.                 if(empty($matches[3])) {
  76.                     unset($matches[0]);
  77.                 } else {
  78.                     ++$withModifiers;
  79.                 }
  80.             }
  81.         }
  82.         if ($withModifiers > 0) {
  83.             $template = str_replace($matches[0], '', $template);
  84.             $this->Log("Cleaning unsolved tags: \n" . implode("\n",$matches[2]) );
  85.         }
  86.         // Restore non-call characters in the template: [, ]
  87.         $template = str_replace($this->safetags[1],$this->safetags[2],$template);
  88.         // Set template post-process hash
  89.         $et = md5($template);
  90.         // If template has changed, parse it once more...
  91.         if ($st!=$et) $template = $this->Parse($template);
  92.         // Write an event log if debugging is enabled and there is something to log
  93.         if ($this->debug && $this->debugLog) {
  94.             $modx->logEvent($this->curPass,1,$this->createEventLog(), $this->name.' '.$this->version);
  95.             $this->debugLog = false;
  96.         }
  97.         // Return the processed template
  98.         return $template;
  99.     }
  100.  
  101.     // Parser: Tag detection and replacements
  102.     function ParseValues($template='') {
  103.         global $modx;
  104.  
  105.         $this->curPass = $this->curPass + 1;
  106.         $st = md5($template);
  107.  
  108.         //$this->LogSource($template);
  109.         $this->LogPass();
  110.  
  111.         // MODx Chunks
  112.         $this->Log("MODx Chunks -> Merging all chunk tags");
  113.         $template = $modx->mergeChunkContent($template);
  114.  
  115.         // MODx Snippets
  116.         //if ( preg_match_all('~\[(\[|!)([^\[]*?)(!|\])\]~s',$template, $matches)) {
  117.         if ( preg_match_all('~\[(\[)([^\[]*?)(\])\]~s',$template, $matches)) {
  118.                 $count = count($matches[0]);
  119.                 $var_search = array();
  120.                 $var_replace = array();
  121.  
  122.                 // for each detected snippet
  123.                 for($i=0; $i<$count; $i++) {
  124.                     $snippet = $matches[2][$i]; // snippet call
  125.                     $this->Log("MODx Snippet -> ".$snippet);
  126.  
  127.                     // Let MODx evaluate snippet
  128.                     $replace = $modx->evalSnippets("[[".$snippet."]]");
  129.                     $this->LogSnippet($replace);
  130.  
  131.                     // Replace values
  132.                     $var_search[] = $matches[0][$i];
  133.                     $var_replace[] = $replace;
  134.  
  135.                 }
  136.                 $template = str_replace($var_search, $var_replace, $template);
  137.         }
  138.  
  139.         // PHx / MODx Tags
  140.         if ( preg_match_all('~\[(\+|\*|\()([^:\+\[\]]+)([^\[\]]*?)(\1|\))\]~s',$template, $matches)) {
  141.  
  142.             //$matches[0] // Complete string that's need to be replaced
  143.             //$matches[1] // Type
  144.             //$matches[2] // The placeholder(s)
  145.             //$matches[3] // The modifiers
  146.             //$matches[4] // Type (end character)
  147.  
  148.             $count = count($matches[0]);
  149.             $var_search = array();
  150.             $var_replace = array();
  151.             for($i=0; $i<$count; $i++) {
  152.                 $replace = NULL;
  153.                 $match = $matches[0][$i];
  154.                 $type = $matches[1][$i];
  155.                 $type_end = $matches[4][$i];
  156.                 $input = $matches[2][$i];
  157.                 $modifiers = $matches[3][$i];
  158.                 $var_search[] = $match;
  159.                     switch($type) {
  160.                         // Document / Template Variable eXtended
  161.                         case "*":
  162.                             $this->Log("MODx TV/DV: " . $input);
  163.                             $input = $modx->mergeDocumentContent("[*".$input."*]");
  164.                             $replace = $this->Filter($input,$modifiers);
  165.                             break;
  166.                         // MODx Setting eXtended
  167.                         case "(":
  168.                             $this->Log("MODx Setting variable: " . $input);
  169.                             $input = $modx->mergeSettingsContent("[(".$input.")]");
  170.                             $replace = $this->Filter($input,$modifiers);
  171.                             break;
  172.                         // MODx Placeholder eXtended
  173.                         default:
  174.                             $this->Log("MODx / PHx placeholder variable: " . $input);
  175.                             // Check if placeholder is set
  176.                             if ( !array_key_exists($input, $this->placeholders) && !array_key_exists($input, $modx->placeholders) ) {
  177.                                 // not set so try again later.
  178.                                 $replace = $match;
  179.                                 $this->Log("  |--- Skipping - hasn't been set yet.");
  180.                             }
  181.                             else {
  182.                                 // is set, get value and run filter
  183.                                 $input = $this->getPHxVariable($input);
  184.                                 $replace = $this->Filter($input,$modifiers);
  185.                             }
  186.                         break;
  187.                     }
  188.                     $var_replace[] = $replace;
  189.              }
  190.              $template = str_replace($var_search, $var_replace, $template);
  191.         }
  192.         $et = md5($template); // Post-process template hash
  193.  
  194.         // Log an event if this was the maximum pass
  195.         if ($this->curPass == $this->maxPasses) $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.");
  196.         // If this pass is not at maximum passes and the template hash is not the same, get at it again.
  197.         if (($this->curPass < $this->maxPasses) && ($st!=$et))  $template = $this->ParseValues($template);
  198.  
  199.         return $template;
  200.     }
  201.  
  202.     // Parser: modifier detection and eXtended processing if needed
  203.     function Filter($input, $modifiers) {
  204.         global $modx;
  205.         $output = $input;
  206.         $this->Log("  |--- Input = '". $output ."'");
  207.         if (preg_match_all('~:([^:=]+)(?:=`(.*?)`(?=:[^:=]+|$))?~s',$modifiers, $matches)) {
  208.             $modifier_cmd = $matches[1]; // modifier command
  209.             $modifier_value = $matches[2]; // modifier value
  210.             $count = count($modifier_cmd);
  211.             $condition = array();
  212.             for($i=0; $i<$count; $i++) {
  213.                 $output = trim($output);
  214.                 $this->Log("  |--- Modifier = '". $modifier_cmd[$i] ."'");
  215.                 if ($modifier_value[$i] != '') $this->Log("  |--- Options = '". $modifier_value[$i] ."'");
  216.                 switch ($modifier_cmd[$i]) {
  217.                     #####  Conditional Modifiers
  218.                     case "input":   case "if": $output = $modifier_value[$i]; break;
  219.                     case "equals": case "is": case "eq": $condition[] = intval(($output==$modifier_value[$i])); break;
  220.                     case "notequals": case "isnot": case "isnt": case "ne":$condition[] = intval(($output!=$modifier_value[$i]));break;
  221.                     case "isgreaterthan":   case "isgt": case "eg": $condition[] = intval(($output>=$modifier_value[$i]));break;
  222.                     case "islowerthan": case "islt": case "el": $condition[] = intval(($output<=$modifier_value[$i]));break;
  223.                     case "greaterthan": case "gt": $condition[] = intval(($output>$modifier_value[$i]));break;
  224.                     case "lowerthan":   case "lt":$condition[] = intval(($output<$modifier_value[$i]));break;
  225.                     case "isinrole": case "ir": case "memberof": case "mo": // Is Member Of  (same as inrole but this one can be stringed as a conditional)
  226.                         if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  227.                         $grps = (strlen($modifier_value) > 0 ) ? explode(",",$modifier_value[$i]) :array();
  228.                         $condition[] = intval($this->isMemberOfWebGroupByUserId($output,$grps));
  229.                         break;
  230.                     case "or":$condition[] = "||";break;
  231.                     case "and": $condition[] = "&&";break;
  232.                     case "show":
  233.                         $conditional = implode(' ',$condition);
  234.                         $isvalid = intval(eval("return (". $conditional. ");"));
  235.                         if (!$isvalid) { $output = NULL;}
  236.                     case "then":
  237.                         $conditional = implode(' ',$condition);
  238.                         $isvalid = intval(eval("return (". $conditional. ");"));
  239.                         if ($isvalid) { $output = $modifier_value[$i]; }
  240.                         else { $output = NULL; }
  241.                         break;
  242.                     case "else":
  243.                         $conditional = implode(' ',$condition);
  244.                         $isvalid = intval(eval("return (". $conditional. ");"));
  245.                         if (!$isvalid) { $output = $modifier_value[$i]; }
  246.                         break;
  247.                     case "select":
  248.                         $raw = explode("&",$modifier_value[$i]);
  249.                         $map = array();
  250.                         for($m=0; $m<(count($raw)); $m++) {
  251.                             $mi = explode("=",$raw[$m]);
  252.                             $map[$mi[0]] = $mi[1];
  253.                         }
  254.                         $output = $map[$output];
  255.                         break;
  256.                     ##### End of Conditional Modifiers
  257.  
  258.                     #####  String Modifiers
  259.                     case "lcase": $output = strtolower($output); break;
  260.                     case "ucase": $output = strtoupper($output); break;
  261.                     case "ucfirst": $output = ucfirst($output); break;
  262.                     case "htmlent": $output = htmlentities($output,ENT_QUOTES,$modx->config['etomite_charset']); break;
  263.                     case "esc":
  264.                         $output = preg_replace("/&(#[0-9]+|[a-z]+);/i", "&$1;", htmlspecialchars($output));
  265.                         $output = str_replace(array("[","]","`"),array("&#91;","&#93;","&#96;"),$output);
  266.                         break;
  267.                     case "strip": $output = preg_replace("~([\n\r\t\s]+)~"," ",$output); break;
  268.                     case "notags": $output = strip_tags($output); break;
  269.                     case "length": case "len": $output = strlen($output); break;
  270.                     case "reverse": $output = strrev($output); break;
  271.                     case "wordwrap": // default: 70
  272.                         $wrapat = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 70;
  273.                         $output = preg_replace("~(\b\w+\b)~e","wordwrap('\\1',\$wrapat,' ',1)",$output);
  274.                         break;
  275.                     case "limit": // default: 100
  276.                       $limit = intval($modifier_value[$i]) ? intval($modifier_value[$i]) : 100;
  277.                         $output = substr($output,0,$limit);
  278.                         break;
  279.  
  280.                     #####  Special functions
  281.                     case "math":
  282.                         $filter = preg_replace("~([a-zA-Z\n\r\t\s])~","",$modifier_value[$i]);
  283.                         $filter = str_replace("?",$output,$filter);
  284.                         $output = eval("return ".$filter.";");
  285.                         break;
  286.                     case "ifempty": if (empty($output)) $output = $modifier_value[$i]; break;
  287.                     case "nl2br": $output = nl2br($output); break;
  288.                     case "date": $output = strftime($modifier_value[$i],0+$output); break;
  289.                     case "set":
  290.                         $c = $i+1;
  291.                         if ($count>$c&&$modifier_cmd[$c]=="value") $output = preg_replace("~([^a-zA-Z0-9])~","",$modifier_value[$i]);
  292.                         break;
  293.                     case "value":
  294.                         if ($i>0&&$modifier_cmd[$i-1]=="set") { $modx->SetPlaceholder("phx.".$output,$modifier_value[$i]); }
  295.                         $output = NULL;
  296.                         break;
  297.                     case "md5": $output = md5($output); break;
  298.                     case "userinfo":
  299.                         if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  300.                         $output = $this->ModUser($output,$modifier_value[$i]);
  301.                         break;
  302.                     case "inrole": // deprecated
  303.                         if ($output == "&_PHX_INTERNAL_&") $output = $this->user["id"];
  304.                         $grps = (strlen($modifier_value) > 0 ) ? explode(",",$modifier_value[$i]) :array();
  305.                         $output = intval($this->isMemberOfWebGroupByUserId($output,$grps));
  306.                         break;
  307.                     default:
  308.                         if (!array_key_exists($modifier_cmd[$i], $this->cache["cm"])) {
  309.                             $sql = "SELECT snippet FROM " . $modx->getFullTableName("site_snippets") . " WHERE " . $modx->getFullTableName("site_snippets") . ".name='phx:" . $modifier_cmd[$i] . "';";
  310.                             $result = $modx->dbQuery($sql);
  311.                             if ($modx->recordCount($result) == 1) {
  312.                                 $row = $modx->fetchRow($result);
  313.                                 $cm = $this->cache["cm"][$modifier_cmd[$i]] = $row["snippet"];
  314.                                 $this->Log("  |--- DB -> Custom Modifier");
  315.                             } else if ($modx->recordCount($result) == 0){ // If snippet not found, look in the modifiers folder
  316.                                 $filename = $modx->config['rb_base_dir'] . 'plugins/phx/modifiers/'.$modifier_cmd[$i].'.phx.php';
  317.                                 if (@file_exists($filename)) {
  318.                                     $file_contents = @file_get_contents($filename);
  319.                                     $file_contents = str_replace('<?php', '', $file_contents);
  320.                                     $file_contents = str_replace('?>', '', $file_contents);
  321.                                     $file_contents = str_replace('<?', '', $file_contents);
  322.                                     $cm = $this->cache["cm"][$modifier_cmd[$i]] = $file_contents;
  323.                                     $this->Log("  |--- File ($filename) -> Custom Modifier");
  324.                                 }
  325.                             }
  326.                          } else {
  327.                             $cm = $this->cache["cm"][$modifier_cmd[$i]];
  328.                             $this->Log("  |--- Cache -> Custom Modifier");
  329.                          }
  330.                          ob_start();
  331.                          $options = $modifier_value[$i];
  332.                          $custom = eval($cm);
  333.                          $msg = ob_get_contents();
  334.                          $output = $msg.$custom;
  335.                          ob_end_clean();
  336.                          break;
  337.                 }
  338.                 if (count($condition)) $this->Log("  |--- Condition = '". $condition[count($condition)-1] ."'");
  339.                 $this->Log("  |--- Output = '". $output ."'");
  340.             }
  341.         }
  342.         return $output;
  343.     }
  344.  
  345.     // Event logging (debug)
  346.     function createEventLog() {
  347.         if($this->console) {
  348.             $console = implode("\n",$this->console);
  349.             $this->console = array();
  350.             return '<pre style="overflow: auto;">' . $console . '</pre>';
  351.         }
  352.     }
  353.  
  354.     // Returns a cleaned string escaping the HTML and special MODx characters
  355.     function LogClean($string) {
  356.         $string = preg_replace("/&(#[0-9]+|[a-z]+);/i", "&$1;", htmlspecialchars($string));
  357.         $string = str_replace(array("[","]","`"),array("&#91;","&#93;","&#96;"),$string);
  358.         return $string;
  359.     }
  360.  
  361.     // Simple log entry
  362.     function Log($string) {
  363.         if ($this->debug) {$this->debugLog = true; $this->console[] = (count($this->console)+1-$this->curPass). " [". strftime("%H:%M:%S",time()). "] " . $this->LogClean($string);}
  364.     }
  365.  
  366.     // Log snippet output
  367.     function LogSnippet($string) {
  368.         if ($this->debug) {$this->debugLog = true; $this->console[] = (count($this->console)+1-$this->curPass). " [". strftime("%H:%M:%S",time()). "] " . "  |--- Returns: <div style='margin: 10px;'>".$this->LogClean($string)."</div>";}
  369.     }
  370.  
  371.     // Log pass
  372.     function LogPass() {
  373.         $this->console[] = "<div style='margin: 2px;margin-top: 5px;border-bottom: 1px solid black;'>Pass " . $this->curPass . "</div>";
  374.     }
  375.  
  376.     // Log pass
  377.     function LogSource($string) {
  378.         $this->console[] = "<div style='margin: 2px;margin-top: 5px;border-bottom: 1px solid black;'>Source:</div>" . $this->LogClean($string);
  379.     }
  380.  
  381.  
  382.     // Returns the specified field from the user record
  383.     // positive userid = manager, negative integer = webuser
  384.     function ModUser($userid,$field) {
  385.         global $modx;
  386.         if (!array_key_exists($userid, $this->cache["ui"])) {
  387.             if (intval($userid) < 0) {
  388.                 $user = $modx->getWebUserInfo(-($userid));
  389.             } else {
  390.                 $user = $modx->getUserInfo($userid);
  391.             }
  392.             $this->cache["ui"][$userid] = $user;
  393.         } else {
  394.             $user = $this->cache["ui"][$userid];
  395.         }
  396.         return $user[$field];
  397.     }
  398.  
  399.      // Returns true if the user id is in one the specified webgroups
  400.      function isMemberOfWebGroupByUserId($userid=0,$groupNames=array()) {
  401.         global $modx;
  402.  
  403.         // if $groupNames is not an array return false
  404.         if(!is_array($groupNames)) return false;
  405.  
  406.         // if the user id is a negative number make it positive
  407.         if (intval($userid) < 0) { $userid = -($userid); }
  408.  
  409.         // Creates an array with all webgroups the user id is in
  410.         if (!array_key_exists($userid, $this->cache["mo"])) {
  411.             $tbl = $modx->getFullTableName("webgroup_names");
  412.             $tbl2 = $modx->getFullTableName("web_groups");
  413.             $sql = "SELECT wgn.name FROM $tbl wgn INNER JOIN $tbl2 wg ON wg.webgroup=wgn.id AND wg.webuser='".$userid."'";
  414.             $this->cache["mo"][$userid] = $grpNames = $modx->db->getColumn("name",$sql);
  415.         } else {
  416.             $grpNames = $this->cache["mo"][$userid];
  417.         }
  418.         // Check if a supplied group matches a webgroup from the array we just created
  419.         foreach($groupNames as $k=>$v)
  420.             if(in_array(trim($v),$grpNames)) return true;
  421.  
  422.         // If we get here the above logic did not find a match, so return false
  423.         return false;
  424.      }
  425.  
  426.     // Returns the value of a PHx/MODx placeholder.
  427.     function getPHxVariable($name) {
  428.         global $modx;
  429.         // Check if this variable is created by PHx
  430.         if (array_key_exists($name, $this->placeholders)) {
  431.             // Return the value from PHx
  432.             return $this->placeholders[$name];
  433.         } else {
  434.             // Return the value from MODx
  435.             return $modx->getPlaceholder($name);
  436.         }
  437.     }
  438.  
  439.     // Sets a placeholder variable which can only be access by PHx
  440.     function setPHxVariable($name, $value) {
  441.         if ($name != "phx") $this->placeholders[$name] = $value;
  442.     }
  443.  
  444. }
  445. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement