00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
00205 $value = $this->
_php_test_modifiers($value);
00206 $value = $this->
_php_vars($value);
00207
00208
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
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] !=
':') {
00296 }
00297
$i++;
00298 $result .= $path;
00299 $result .= '::';
00300 $path =
false;
00301 $last_path =
false;
00302
00303 }
else if ($c ==
'@') {
00304
00305
00306
$i++;
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--;
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
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 ?>