Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

ExpressionFunctions.php

Go to the documentation of this file.
00001 <?php 00002 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 00003 // 00004 // Copyright (c) 2003 Laurent Bedubourg 00005 // 00006 // This library is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public 00017 // License along with this library; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 // 00020 // Authors: Laurent Bedubourg <laurent.bedubourg@free.fr> 00021 // 00022 00030 global $_phptal_es_namespaces; 00031 $_phptal_es_namespaces = array('not', 'php', 'string', 'exists', 'path', 'not-exists'); 00032 00039 global $_phptal_es_keywords; 00040 $_phptal_es_keywords = array('nothing', 'default', 'structure'); 00041 00042 global $_phptal_es_php_types; 00043 $_phptal_es_php_types = array('true', 'false', 'null'); 00044 00048 function PHPTAL_ES_string(&$exp, $value) 00049 { 00050 $value = PHPTAL_ES_path_in_string($value); 00051 // $value = str_replace('$$', '\$\$', $value); 00052 $value = '"' . $value . '"'; 00053 $value = preg_replace('/^\" ?\"\. /', '', $value); 00054 $value = preg_replace('/\.\"\"$/', '', $value); 00055 return $value; 00056 } 00057 00061 function PHPTAL_ES_not(&$exp, $value) 00062 { 00063 return "! " . PHPTAL_ES_path($exp, $value); 00064 } 00065 00069 function PHPTAL_ES_not_exists(&$exp, $value) 00070 { 00071 return "! " . PHPTAL_ES_exists($exp, $value); 00072 } 00073 00084 function PHPTAL_ES_path(&$exp, $value) 00085 { 00086 $value = trim($value); 00087 // special case : 'string' authorized 00088 if ($value[0] == "'") { return PHPTAL_ES_path_in_string($value,"'"); } 00089 // number case 00090 if (preg_match('/^[0-9\.]*$/', $value)) { return $value; } 00091 // php constants are accessed though @ keyword 00092 if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); } 00093 if ($value == "nothing") { return 'null'; } 00094 if ($value == "default") { return '$__default__'; } 00095 $value = PHPTAL_ES_path_in_string($value); 00096 return '$__ctx__->get("'. $value .'")'; 00097 } 00098 00099 00100 function PHPTAL_ES_path_toString(&$exp, $value) 00101 { 00102 $value = trim($value); 00103 if ($value == "nothing") { return 'null'; } 00104 if ($value == "default") { return '$__default__'; } 00105 if (preg_match('/^@[_a-z][0-9a-z_]*$/i', $value)) { return substr($value, 1); } 00106 return '$__ctx__->getToString("'. $value .'")'; 00107 } 00108 00109 00113 function PHPTAL_ES_exists(&$exp, $value) 00114 { 00115 return '$__ctx__->has("'. trim($value). '")'; 00116 } 00117 00121 function PHPTAL_ES_php(&$exp, $str) 00122 { 00123 $parser = new PHPTAL_ES_PHP_Parser($exp, $str); 00124 return $parser->evaluate(); 00125 } 00126 00127 00128 // 00129 // utility functions (internal) 00130 // 00131 00132 function PHPTAL_ES_path_in_string($arg, $c='"') 00133 { 00134 list($match,$repl) = _PHPTAL_context_accessed($arg); 00135 for ($i=0; $i<count($match); $i++) { 00136 $null = ""; 00137 $repl[$i] = $c . ". " . PHPTAL_ES_path_toString($null, $repl[$i]) . " ." . $c; 00138 $pos = strpos($arg, $match[$i]); 00139 $arg = substr($arg, 0, $pos) 00140 . $repl[$i] 00141 . substr($arg, $pos + strlen($match[$i])); 00142 } 00143 if ($c == '"') { 00144 $arg = str_replace('$$','\$', $arg); 00145 } else { 00146 $arg = str_replace('$$', '$', $arg); 00147 } 00148 return $arg; 00149 } 00150 00151 function _PHPTAL_context_accessed($str) 00152 { 00153 if (preg_match_all('/((?<!\$)\$\{?([@_a-zA-z0-9.\/\-]+)\}?)/', $str, $match)) { 00154 return array_slice($match, 1); 00155 } 00156 return array(array(),array()); 00157 } 00158 00159 // 00160 // php: expression parser 00161 // 00162 00163 class PHPTAL_ES_PHP_Parser 00164 { 00165 var $_exp; 00166 var $_gen; 00167 var $_str; 00168 var $_aliases = array(); 00169 var $_code = ""; 00170 var $_last_was_array = false; 00171 00172 function PHPTAL_ES_PHP_Parser(&$expression, $str) 00173 { 00174 $this->_exp =& $expression; 00175 $this->_gen =& $expression->_gen; 00176 $this->_str = $str; 00177 } 00178 00179 function evaluate() 00180 { 00181 $value = $this->_str; 00182 $strings = array(); 00183 00184 // extract strings and replace context calls 00185 if (preg_match_all('/(\'.*?(?<!\\\)\')/sm', $value, $m)) { 00186 list(,$m) = $m; 00187 foreach ($m as $str) { 00188 $s_rplc = PHPTAL_ES_path_in_string($str, "'"); 00189 $s_rplc = preg_replace('/^\' ?\'\. /', '', $s_rplc); 00190 $s_rplc = preg_replace('/\.\'\'$/', '', $s_rplc); 00191 $value = str_replace($str, '#_STRING_'. count($strings) . '_#', $value); 00192 $strings[] = $s_rplc; 00193 } 00194 } 00195 00196 list($match, $replc) = _PHPTAL_context_accessed($value); 00197 $contexts = array(); 00198 foreach ($match as $m) { 00199 $i = count($contexts); 00200 $contexts[] = $replc[$i]; 00201 $value = str_replace($m, '#_CONTEXT_'. $i . '_#', $value); 00202 } 00203 00204 // replace or, and, lt, gt, etc... 00205 $value = $this->_php_test_modifiers($value); 00206 $value = $this->_php_vars($value); 00207 00208 // restore strings 00209 $i = 0; 00210 foreach ($strings as $str) { 00211 $value = str_replace('#_STRING_'. $i . '_#', $str, $value); 00212 $i++; 00213 } 00214 00215 $i = 0; 00216 foreach ($contexts as $c) { 00217 $value = str_replace('#_CONTEXT_' . $i . '_#', PHPTAL_ES_path($this->_exp, $c), $value); 00218 $i++; 00219 } 00220 00221 // experimental, compile php: content 00222 00223 require_once PT_IP . "/Types/Code.php"; 00224 00225 $code = new Code(); 00226 $code->setCode($value .";"); 00227 $err = $code->compile(); 00228 if (PEAR::isError($err)) { 00229 return $this->_raiseCompileError($value, $err); 00230 } 00231 00232 return $value; 00233 } 00234 00235 function _php_test_modifiers($exp) 00236 { 00237 $exp = preg_replace('/\bnot\b/i', ' !', $exp); 00238 $exp = preg_replace('/\bne\b/i', ' != ', $exp); 00239 $exp = preg_replace('/\band\b/i', ' && ', $exp); 00240 $exp = preg_replace('/\bor\b/i', ' || ', $exp); 00241 $exp = preg_replace('/\blt\b/i', ' < ', $exp); 00242 $exp = preg_replace('/\bgt\b/i', ' > ', $exp); 00243 $exp = preg_replace('/\bge\b/i', ' >= ', $exp); 00244 $exp = preg_replace('/\ble\b/i', ' <= ', $exp); 00245 $exp = preg_replace('/\beq\b/i', ' == ', $exp); 00246 return $exp; 00247 } 00248 00249 function _php_vars($arg) 00250 { 00251 $arg = preg_replace('/\s*\/\s*/',' / ', $arg); 00252 $arg = preg_replace("/\s*\(\s*/","(", $arg ); 00253 $arg = preg_replace('/\s*\)\s*/',') ', $arg ); 00254 $arg = preg_replace('/\s*\[\s*/','[', $arg ); 00255 $arg = preg_replace('/\s*\]\s*/',']', $arg ); 00256 $arg = preg_replace('/\s*,\s*/',' , ', $arg ); 00257 00258 $result = ""; 00259 $path = false; 00260 $last_path = false; 00261 $last_was_array = false; 00262 00263 $i = 0; 00264 while ($i < strlen($arg)) { 00265 $c = $arg[$i]; 00266 if (preg_match('/[a-z_]/i', $c)) { 00267 $path .= $c; 00268 } else if (preg_match('/[0-9]/', $c) && $path) { 00269 $path .= $c; 00270 } else if (preg_match('/[\/\.]/', $c) && $path) { 00271 $last_path = $path; 00272 $path .= $c; 00273 } else if (preg_match('/[\/\.]/', $c) && $this->_last_was_array) { 00274 $result .= '->'; 00275 } else if ($c == '(') { 00276 if ($last_path) { 00277 $result .= $this->pathRequest($last_path); 00278 $result .= '->'; 00279 $path = substr($path, strlen($last_path) +1); 00280 $last_path = false; 00281 } 00282 $result .= $path . '('; 00283 $this->_last_was_array = false; 00284 $path = false; 00285 } else if ($c == '#') { 00286 if ($path) { 00287 $result .= $this->pathRequest($path); 00288 $path = false; 00289 $last_path = false; 00290 } 00291 $next = strpos($arg, '#', $i+1); 00292 $result .= substr($arg, $i, $next - $i +1); 00293 $i = $next; 00294 } else if ($c == ':') { 00295 if ($arg[$i+1] != ':') { // error 00296 } 00297 $i++; 00298 $result .= $path; 00299 $result .= '::'; 00300 $path = false; 00301 $last_path = false; 00302 00303 } else if ($c == '@') { 00304 // access to defined variable, append to result 00305 // up to non word character 00306 $i++; // skip @ character 00307 do { 00308 $c = $arg[$i]; 00309 $result .= $c; 00310 $i++; 00311 } while ($i < strlen($arg) && preg_match('/[a-z_0-9]/i', $arg[$i])); 00312 $i--; // reset last character 00313 00314 } else { 00315 if ($path) { 00316 $result .= $this->pathRequest($path); 00317 $path = false; 00318 } 00319 $result .= $c; 00320 if ($c == ']') { 00321 $last_path = false; 00322 $path = false; 00323 $this->_last_was_array = true; 00324 } else { 00325 $this->_last_was_array = false; 00326 } 00327 } 00328 $i++; 00329 } 00330 00331 // don't forget the last bit 00332 if (isset($path) && $path) { 00333 $result .= $this->pathRequest($path); 00334 } 00335 00336 return $result; 00337 } 00338 00339 function pathRequest($path) 00340 { 00341 global $_phptal_es_php_types; 00342 00343 if (!preg_match('/[a-z]/i', $path)){ 00344 return $path; 00345 } 00346 if ($this->_last_was_array) { 00347 return str_replace('.', '->', $path); 00348 } 00349 if (in_array($path, $_phptal_es_php_types)) { 00350 return $path; 00351 } 00352 00353 $concatenate = false; 00354 $path = str_replace('.','/', $path); 00355 if (substr($path,-1) == '/') { 00356 $path = substr($path, 0, -1); 00357 $concatenate = true; 00358 } 00359 00360 if (array_key_exists($path, $this->_aliases)) { 00361 $res = $this->_aliases[$path]; 00362 } else { 00363 $res = $this->_gen->newTemporaryVar(); 00364 $this->_aliases[$path] = $res; 00365 $this->_gen->doContextGet($res, $path); 00366 } 00367 00368 if ($concatenate) { 00369 $res .= ' .'; 00370 } 00371 return $res; 00372 } 00373 00374 function _raiseCompileError($code, $err) 00375 { 00376 $str = sprintf("Expression 'php:' compilation error in %s:%d".endl, 00377 $this->_exp->_tag->_parser->_file, 00378 $this->_exp->_tag->line); 00379 return PEAR::raiseError($str); 00380 } 00381 } 00382 00383 00384 ?>

Generated on Tue Jun 29 23:40:03 2004 for Mediawiki by doxygen 1.3.7