00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 define('_PHPTAL_ES_RECEIVER_IS_CONTEXT', 1);
00024 define('_PHPTAL_ES_RECEIVER_IS_NONE', 2);
00025 define('_PHPTAL_ES_RECEIVER_IS_TEMP', 4);
00026 define('_PHPTAL_ES_RECEIVER_IS_OUTPUT', 8);
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 class PHPTAL_Expression
00037 {
00038 var
$_tag;
00039 var
$_gen;
00040 var
$_src;
00041 var
$_subs = array();
00042 var
$_policy;
00043 var
$_receiver =
false;
00044 var
$_prepared =
false;
00045 var
$_structure =
false;
00046
00047 function
PHPTAL_Expression(&$generator, &$tag, $str)
00048 {
00049 $this->_tag =& $tag;
00050 $this->_gen =& $generator;
00051 $this->_src = $str;
00052 }
00053
00054 function
setPolicy($policy)
00055 {
00056 $this->_policy = $policy;
00057 }
00058
00068 function
prepare()
00069 {
00070
if ($this->_prepared) {
return; }
00071 $test = $this->_src;
00072
00073
00074
while (preg_match('/^(.*?)(?<!;);(?!;)/sm', $test, $m)) {
00075 list($src, $exp) = $m;
00076
00077 $x =
new PHPTAL_Expression($this->_gen, $this->_tag, $exp);
00078 $x->setPolicy($this->_policy);
00079 $x->setReceiver($this->getReceiver());
00080 $err = $x->prepare();
00081
if (PEAR::isError($err)) {
00082
return $err;
00083 }
00084 $this->_subs[] = $x;
00085
00086 $test = substr($test, strlen($src));
00087 }
00088
00089
if ($this->
countSubs() > 0 && strlen(trim($test)) > 0) {
00090 $exp = $test;
00091 $x =
new PHPTAL_Expression($this->_gen, $this->_tag, $exp);
00092 $x->setPolicy($this->_policy);
00093 $x->setReceiver($this->getReceiver());
00094 $err = $x->prepare();
00095
if (PEAR::isError($err)) {
00096
return $err;
00097 }
00098 $this->_subs[] = $x;
00099 }
else {
00100
00101
00102 $exp = $test;
00103 $exp = str_replace(';;',
';', $exp);
00104 $this->_src = $exp;
00105
if (strlen($exp) == 0)
return;
00106
00107 $err = $this->
_extractReceiver();
00108
if (PEAR::isError($err)){
00109
return $err;
00110 }
00111
00112
if (!$this->_receiver
00113 && ($this->_policy &
_PHPTAL_ES_RECEIVER_IS_CONTEXT
00114 || $this->_policy &
_PHPTAL_ES_RECEIVER_IS_TEMP)) {
00115 $str = sprintf('Receiver required in expression \'%s\' from %s:%d',
00116 $this->_src,
00117 $this->_tag->_parser->_file,
00118 $this->_tag->line);
00119 $err =
new PHPTAL_ExpressionError($str);
00120
return PEAR::raiseError($err);
00121 }
00122
00123
if ($this->_policy &
_PHPTAL_ES_RECEIVER_IS_NONE && $this->_receiver) {
00124 $str = sprintf('Unexpected receiver \'%s\' in expression \'%s\' from %s:%d',
00125 $this->_receiver,
00126 $this->_src,
00127 $this->_tag->_parser->_file,
00128 $this->_tag->line);
00129 $err =
new PHPTAL_ExpressionError($str);
00130
return PEAR::raiseError($err);
00131 }
00132 }
00133
00134 $this->_prepared =
true;
00135 }
00136
00137 function
_extractReceiver()
00138 {
00139 global
$_phptal_es_namespaces;
00140
00141 $this->_src = preg_replace('/^\s+/sm', '', $this->_src);
00142
if (preg_match('/^([a-z:A-Z_0-9]+)\s+([^\|].*?)$/sm', $this->_src, $m)) {
00143
00144
00145
00146
if (preg_match('/^([a-zA-Z_0-9]+):/', $m[1], $sub)) {
00147 $ns = $sub[1];
00148
00149
if (function_exists('phptal_es_'.$ns)) {
00150
00151
return;
00152 }
00153 }
00154
00155
if ($this->_receiver) {
00156 $str = sprintf('Receiver already set to \'%s\' in \'%s\'',
00157 $this->_receiver,
00158 $this->_src);
00159 $err =
new PHPTAL_ExpressionError($str);
00160
return PEAR::raiseError($err);
00161 }
00162
00163 $this->_receiver = $m[1];
00164
00165
00166
00167
00168 $this->_receiver = str_replace(
':', '__phptales_dd__', $this->_receiver);
00169 $this->_src = $m[2];
00170
if ($this->_receiver ==
"structure") {
00171 $this->_structure =
true;
00172 $this->_receiver =
false;
00173 $this->
_extractReceiver();
00174 }
00175 }
00176 }
00177
00181 function
countSubs()
00182 {
00183
return count($this->_subs);
00184 }
00185
00186 function &
subs()
00187 {
00188
return $this->_subs;
00189 }
00190
00194 function
hasReceiver()
00195 {
00196
return $this->_receiver !=
false;
00197 }
00198
00202 function
getReceiver()
00203 {
00204
return $this->_receiver;
00205 }
00206
00210 function
setReceiver($name)
00211 {
00212 $this->_receiver = $name;
00213 }
00214
00218 function
generate()
00219 {
00220 $err = $this->
prepare();
00221
if (PEAR::isError($err)) {
00222
return $err;
00223 }
00224
00225
if ($this->
countSubs() > 0) {
00226 foreach ($this->_subs as $sub) {
00227 $err = $sub->generate();
00228
if (PEAR::isError($err)) {
00229
return $err;
00230 }
00231 }
00232 }
else {
00233 $exp = $this->_src;
00234
if (strlen($exp) == 0)
return;
00235
00236
00237
00238
00239
00240
00241
if (preg_match('/\s*?\|\s*?string:/sm', $exp, $m)) {
00242 $search = $m[0];
00243 $str = strpos($exp, $search);
00244
00245
00246 $seq = preg_split('/(\s*?\|\s*?)/sm', substr($exp, 0, $str));
00247 $seq[]= substr($exp, $str + 2);
00248 }
else {
00249 $seq = preg_split('/(\s*?\|\s*?)/sm', $exp);
00250 }
00251
00252
00253
if (count($seq) == 1) {
00254 $code =
PHPTAL_Expression::_GetCode($
this, $exp);
00255
if (PEAR::isError($code)) {
return $code; }
00256
00257 $temp = $this->_gen->newTemporaryVar();
00258 $this->_gen->doAffectResult($temp, $code);
00259
return $this->
_useResult($temp);
00260 }
else {
00261
return $this->
_evaluateSequence($seq);
00262 }
00263 }
00264 }
00265
00266
00267 function
_evaluateSequence($seq)
00268 {
00269 $temp = $this->_gen->newTemporaryVar();
00270
00271 $this->_gen->doDo();
00272 foreach ($seq as $s) {
00273
00274
if (strlen(trim($s)) > 0) {
00275 $code =
PHPTAL_Expression::_GetCode($
this, $s);
00276
if (PEAR::isError($code)) {
return $code; }
00277
00278 $this->_gen->doUnset($temp);
00279 $this->_gen->doAffectResult($temp, $code);
00280 $this->_gen->doIf('!PEAR::isError(' . $temp . ') && ' .
00281
00282 $temp . ' !== null');
00283 $this->_gen->execute('$__ctx__->_errorRaised =
false');
00284 $this->_gen->execute('
break');
00285 $this->_gen->endBlock();
00286 }
00287 }
00288 $this->_gen->doEndDoWhile(
'0');
00289
00290
00291
00292
00293
00294
00295
00296 $err = $this->
_useResult($temp);
00297
00298
00299
return $err;
00300 }
00301
00302 function
_useResult($temp)
00303 {
00304
if ($this->_policy &
_PHPTAL_ES_RECEIVER_IS_TEMP) {
00305 $this->_gen->doReference($this->_receiver, $temp);
00306 }
else if ($this->_policy &
_PHPTAL_ES_RECEIVER_IS_OUTPUT) {
00307 $this->_gen->doPrintVar($temp, $this->_structure);
00308 }
else if ($this->_policy &
_PHPTAL_ES_RECEIVER_IS_CONTEXT) {
00309 $this->_gen->doContextSet($this->_receiver, $temp);
00310 }
else {
00311 $err =
new PHPTAL_ExpressionError(
"Expression '$this->_src' Don't know what to do with result.");
00312
return PEAR::raiseError($err);
00313 }
00314 }
00315
00334 function
_FindFunctionNamespace($str)
00335 {
00336 $str = preg_replace('/^\s/sm', '', $str);
00337
if (preg_match('/^([a-z0-9\-]+):(?!>:)(.*?)$/ism', $str, $m)) {
00338 list($ns, $
path) = array_slice($m, 1);
00339 $ns = str_replace(
'-',
'_', $ns);
00340
return array($ns, $
path);
00341 }
00342
return array('
path', $str);
00343 }
00344
00348 function
_GetCode(&$exp, $str)
00349 {
00350 list($ns, $args) =
PHPTAL_Expression::_FindFunctionNamespace($str);
00351 $func =
"PHPTAL_ES_$ns";
00352
if (!function_exists($func)) {
00353 $err =
new PHPTAL_ExpressionError(
"Unknown function $func in '$str'");
00354
return PEAR::raiseError($err);
00355 }
00356
return $func($exp, $args);
00357 }
00358 }
00359
00363 class PHPTAL_ExpressionError extends PEAR_Error
00364 {
00365 }
00366
00367 ?>