00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 $__d = dirname(__FILE__);
00024 require_once _phptal_os_path_join($__d, 'XML_Parser.php');
00025 require_once _phptal_os_path_join($__d, 'Attribute.php');
00026 require_once _phptal_os_path_join($__d, 'Expression.php');
00027 require_once _phptal_os_path_join($__d, 'ExpressionFunctions.php');
00028 require_once _phptal_os_path_join($__d, 'Generator.php');
00029 require_once _phptal_os_path_join($__d, 'Tag.php');
00030
00031
$_t = _phptal_os_path_join($__d, 'Attribute', 'TAL');
00032 require_once _phptal_os_path_join($_t, 'Attributes.php');
00033 require_once _phptal_os_path_join($_t, 'Comment.php');
00034 require_once _phptal_os_path_join($_t, 'Content.php');
00035 require_once _phptal_os_path_join($_t, 'Condition.php');
00036 require_once _phptal_os_path_join($_t, 'Define.php');
00037 require_once _phptal_os_path_join($_t, 'Omit_tag.php');
00038 require_once _phptal_os_path_join($_t, 'Replace.php');
00039 require_once _phptal_os_path_join($_t, 'On_error.php');
00040 require_once _phptal_os_path_join($_t, 'Repeat.php');
00041
00042
$_t = _phptal_os_path_join($__d, 'Attribute', '
PHPTAL');
00043 require_once _phptal_os_path_join($_t, 'Include.php');
00044 require_once _phptal_os_path_join($_t, 'Src_include.php');
00045
00046
$_t = _phptal_os_path_join($__d, 'Attribute', 'METAL');
00047 require_once _phptal_os_path_join($_t, 'Define_macro.php');
00048 require_once _phptal_os_path_join($_t, 'Use_macro.php');
00049 require_once _phptal_os_path_join($_t, 'Define_slot.php');
00050 require_once _phptal_os_path_join($_t, 'Fill_slot.php');
00051
00052 $_t = _phptal_os_path_join($__d, 'Attribute', 'I18N');
00053 require_once _phptal_os_path_join($_t, 'Translate.php');
00054 require_once _phptal_os_path_join($_t, 'Name.php');
00055 require_once _phptal_os_path_join($_t, 'Attributes.php');
00056
00057
00086 class PHPTAL_Parser extends PHPTAL_XML_Parser
00087 {
00088
00089 var
$_root;
00090
00091 var
$_headers =
false;
00092 var
$_started =
false;
00093
00094 var
$_docType;
00095 var
$_inDocType;
00096
00097
00098 var
$_current;
00099
00100
00101 var
$_file;
00102
00103
00104 var
$_outputFormat = PHPTAL_XHTML;
00105
00106
00107 var
$_keepXMLNS =
false;
00108
00119 function
parse($file, $src)
00120 {
00121 $this->_file = $file;
00122 $this->
_initRoot();
00123
return $this->parseString($src,
true);
00124 }
00125
00138 function
generateCode($func_name)
00139 {
00140 $gen =
new PHPTAL_Generator($this->_file, $func_name);
00141 $gen->setHeaders($this->_headers);
00142 $err = $this->_root->generateCode($gen);
00143
if (PEAR::isError($err)) {
00144
return $err;
00145 }
00146
return $gen->getCode();
00147 }
00148
00157 function
toString()
00158 {
00159 $buf =
new StringBuffer();
00160 $buf->appendln('Template tree [\'', $this->_file,
'\']');
00161 $buf->append($this->_root->toString());
00162
return $buf->toString();
00163 }
00164
00165
00166
00167
00168
00169
00175 function
_initRoot()
00176 {
00177 $this->_headers =
"";
00178 $this->_started =
false;
00179 $this->_root =
new PHPTAL_Tag($
this,
"#root", array());
00180 $this->_current =& $this->_root;
00181 }
00182
00189 function
_push(&$tag)
00190 {
00191 $this->_current->addChild($tag);
00192 unset($this->_current);
00193 $this->_current =& $tag;
00194 }
00195
00202 function
_pushChild(&$tag)
00203 {
00204 $this->_current->addChild($tag);
00205 }
00206
00212 function
_pop()
00213 {
00214 $temp =& $this->_current;
00215 unset($this->_current);
00216
if ($temp != $this->_root) {
00217 $this->_current =& $temp->getParent();
00218 }
else {
00219 $this->_current =& $this->_root;
00220 }
00221 }
00222
00223
00224
00225
00226
00227
00228
00229 function
_outputMode($mode=
false)
00230 {
00231
if ($mode !==
false) {
00232 $this->_outputFormat = $mode;
00233 }
00234
return $this->_outputFormat;
00235 }
00236
00237
00238
00239
00240
00246 function
onElementStart($name, $attributes)
00247 {
00248 global
$_phptal_namespaces;
00249
00250 $this->_started =
true;
00251
00252
if (strpos($
name,
':') !==
false) {
00253 list($domain, $extend) = split(
':', strtoupper($
name));
00254
if (($extend == 'BLOCK') && (in_array($domain, $_phptal_namespaces))) {
00255 $attributes =
PHPTAL_Parser::extendZptBlockAttributes($domain, $attributes);
00256 $attributes['tal:omit-tag'] = '';
00257 }
00258 }
00259
00260
00261
00262 $split =
PHPTAL_Parser::TemplateAttributes($attributes);
00263
if (PEAR::isError($split)) {
00264
return $split;
00265 }
00266
00267
00268 list($phptal, $attributes) = $split;
00269
00270
00271 $phptal =
PHPTAL_Parser::OrderTemplateAttributes($phptal);
00272
if (PEAR::isError($phptal)) {
00273
return $phptal;
00274 }
00275
00276
00277 $tag =
new PHPTAL_Tag($
this, $
name, $attributes);
00278 foreach ($phptal as $t) {
00279 $tag->appendTemplateAttribute($t);
00280 unset($t);
00281 }
00282
00283 $tag->line = $this->
getLineNumber();
00284 $this->_push($tag);
00285 }
00286
00293 function
extendZptBlockAttributes($domain, $attributes)
00294 {
00295 global
$_phptal_dictionary;
00296 $result = array();
00297 foreach ($attributes as $key => $value) {
00298 $expected = strtoupper(
"$domain:$key");
00299
if (array_key_exists($expected, $_phptal_dictionary)) {
00300 $result[$expected] = $value;
00301 }
00302 }
00303
return $result;
00304 }
00305
00311 function
onElementData($data)
00312 {
00313
00314
00315
00316 $tag =
new PHPTAL_Tag($
this,
"#cdata", array());
00317 $tag->setContent($
data);
00318 $this->_pushChild($tag);
00319 }
00320
00326 function
onSpecific($data)
00327 {
00328
00329 $data = str_replace('&',
'&', $
data);
00330
00331
if ($this->_current->name() ==
"#root" && !$this->_started) {
00332 $this->_headers .= $data;
00333
return;
00334 }
00335 $tag =
new PHPTAL_Tag($
this,
"#cdata", array());
00336 $tag->setContent($
data);
00337 $this->_pushChild($tag);
00338 }
00339
00345 function
onElementClose($name)
00346 {
00347
if ($this->_current == null) {
00348
return $this->
_raiseNoTagExpected($
name);
00349 }
00350
if ($this->_current->name() != $name) {
00351
return $this->
_raiseUnexpectedTagClosure($
name);
00352 }
00353 $this->
_pop();
00354 }
00355
00356
00357
00358
00359
00375 function
TemplateAttributes($attrs)
00376 {
00377 global
$_phptal_dictionary,
$_phptal_aliases,
$_phptal_namespaces;
00378 $phptal = array();
00379 $att = array();
00380
00381 foreach ($attrs as $key=>$exp) {
00382
00383 $test_key = strtoupper($key);
00384 $ns = preg_replace('/(:.*?)$/', '', $test_key);
00385 $sns = preg_replace('/^(.*?:)/', '', $test_key);
00386
00387
if (array_key_exists($test_key, $_phptal_dictionary)) {
00388 $phptal[$test_key] = $exp;
00389 }
00390
00391 elseif (array_key_exists($test_key, $_phptal_aliases)) {
00392 $phptal[
$_phptal_aliases[$test_key] ] = $exp;
00393 }
00394
00395 elseif (in_array($ns, $_phptal_namespaces)) {
00396
return $this->
_raiseUnknownAttribute($test_key);
00397 }
00398
00399 elseif ($ns !== 'XMLNS' || $this->_keepXMLNS
00400 || !in_array($
sns, $_phptal_namespaces)) {
00401 $att[$key] = $exp;
00402 }
00403 }
00404
return array($phptal, $att);
00405 }
00406
00416 function
OrderTemplateAttributes(&$phptal)
00417 {
00418 global
$_phptal_rules_order,
$_phptal_dictionary;
00419
00420
00421 $result = array();
00422 foreach ($phptal as $akey=>$exp) {
00423
00424
00425 $class =
"PHPTAL_ATTRIBUTE_" . str_replace(
":",
"_", $akey);
00426 $class = str_replace(
"-",
"_", $
class);
00427
if (!class_exists($
class)) {
00428
return $this->
_raiseAttributeNotFound($akey, $
class);
00429 }
00430
00431 $hdl =
new $class($exp);
00432 $hdl->name = $akey;
00433 $hdl->_phptal_type =
$_phptal_dictionary[$akey];
00434
00435
00436 $pos =
$_phptal_rules_order[$akey];
00437
if (array_key_exists($pos, $result)) {
00438
return $this->
_raiseAttConflict($akey, $result[$pos]->
name);
00439 }
00440
00441
00442 $result[
$_phptal_rules_order[$akey]] = $hdl;
00443 unset($hdl);
00444 }
00445
return $result;
00446 }
00447
00448
00449
00450
00451
00452 function
_raiseAttributeNotFound($att, $
class)
00453 {
00454 $str = sprintf(
"Attribute '%s' exists in dictionary but class '%s' ".
00455
"was not found",
00456 $att, $
class);
00457 $err =
new PHPTAL_ParseError($str);
00458
return PEAR::raiseError($err);
00459 }
00460
00461 function
_raiseUnknownAttribute($att)
00462 {
00463 $str = sprintf(
"Unknown PHPTAL attribute '%s' in %s at line %d",
00464 $att, $this->_file, $this->getLineNumber());
00465 $err =
new PHPTAL_UnknownAttribute($str);
00466
return PEAR::raiseError($err);
00467 }
00468
00469 function
_raiseUnexpectedTagClosure($name)
00470 {
00471 $str = sprintf(
"Non matching tag '%s' error in xml file '%s' at line %d"
00472 . endl .
"waiting for end of tag '%s' declared at line %d.",
00473 $
name, $this->_file, $this->getLineNumber(),
00474 $this->_current->name(), $this->_current->line);
00475 $err =
new PHPTAL_ParseError($str);
00476
return PEAR::raiseError($err);
00477 }
00478
00479 function
_raiseNoTagExpected($name)
00480 {
00481 $str = sprintf(
"Bad xml error in xml file '%s' at line %d". endl
00482 .
"Found closing tag '%s' while no current tag is waited.",
00483 $this->_file, $this->getLineNumber(), $name);
00484 $err =
new PHPTAL_ParseError($str);
00485
return PEAR::raiseError($err);
00486 }
00487
00488 function
_raiseAttConflict($a2, $a1)
00489 {
00490 $str = sprintf('Template Attribute conflict in \'%s\' at line %d'. endl
00491 . ' %s must not be used in the same tag as %s',
00492 $this->_file, $this->getLineNumber(), $a1, $a2);
00493 $err =
new PHPTAL_AttributeConflict($str);
00494
return PEAR::raiseError($err);
00495 }
00496 };
00497
00502 class PHPTAL_ParseError extends PEAR_Error {}
00503
00507 class PHPTAL_UnknownAttribute extends PHPTAL_ParseError {}
00508
00512 class PHPTAL_AttributeConflict extends PHPTAL_ParseError {}
00513
00514
00515 ?>