From b703e05d9154845b6e5c6f1bf20b0a42df7c3613 Mon Sep 17 00:00:00 2001
From: xue <>
Date: Sun, 29 Jan 2006 00:46:56 +0000
Subject: Enhanced error report for template parser.
---
.../protected/pages/Configurations/AppConfig.page | 3 +-
framework/Exceptions/messages.txt | 27 +-
framework/Web/UI/TTemplateManager.php | 296 +++++++++------------
framework/core.php | 28 +-
4 files changed, 162 insertions(+), 192 deletions(-)
diff --git a/demos/quickstart/protected/pages/Configurations/AppConfig.page b/demos/quickstart/protected/pages/Configurations/AppConfig.page
index d40510ef..8d998f85 100644
--- a/demos/quickstart/protected/pages/Configurations/AppConfig.page
+++ b/demos/quickstart/protected/pages/Configurations/AppConfig.page
@@ -31,8 +31,9 @@ Configuration for an application is stored in an XML file named application.
The <services> element is similar to the <modules> element. It mainly specifies the services provided by the application.
The <parameters> element contains a list of application-level parameters that are accessible from anywhere in the application. You may specify component-typed parameters like specifying modules, or you may specify string-typed parameters which take a simpler format as follows,
-ParameterValue
+
+Note, if the value attribute is not specified, the whole parameter XML node (of type TXmlElement) will be returned as the parameter value.
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt
index c3826d35..55c2f112 100644
--- a/framework/Exceptions/messages.txt
+++ b/framework/Exceptions/messages.txt
@@ -1,5 +1,5 @@
prado_application_singleton_required = Prado.Application must only be set once.
-prado_component_unknown = Unable to create unknown component '%s'.
+prado_component_unknown = Unknown component type '%s'.
prado_using_invalid = '%s' is not a valid namespace to be used. Make sure '.*' is appended if you want to use a namespace referring to a directory.
prado_alias_redefined = Alias '%s' cannot be redefined.
prado_alias_invalid = Alias '%s' refers to an invalid path '%s'. Only existing directories can be aliased.
@@ -93,18 +93,19 @@ pageserviceconf_moduletype_required = must have a "class" attr
pageserviceconf_parameter_invalid = element must have an "id" attribute in page directory configuration file '%s'.
pageserviceconf_page_invalid = element must have an "id" attribute in page directory configuration file '%s'.
-template_closingtag_unexpected = %s: Unexpected closing tag '%s' is found.
-template_closingtag_expected = %s: Closing tag '%s' is expected.
-template_directive_nonunique = %s: Directive '<%@ ... %>' must appear at most once in a template.
-template_comments_forbidden = %s: Template comments are not allowed within property tags.
-template_matching_unexpected = %s: Unexpected matching.
-template_componenttag_invalid = %s: Component tag has error (%s)
-template_property_unknown = Unknown property '%s'.
-template_event_unknown = Unknown event '%s'.
-template_property_readonly = Property '%s' is read-only.
-template_event_forbidden = Event handler cannot be attached to the event '%s' of a non-control component in template.
-template_databind_forbidden = Non-control component property '%s' cannot receive a databind expression.
-template_component_required = '%s' is not a component. Only components can appear in templates.
+template_closingtag_unexpected = Unexpected closing tag '%s' is found.
+template_closingtag_expected = Closing tag '%s' is expected.
+template_directive_nonunique = Directive '<%%@ ... %%>' must appear at most once in a template.
+template_comments_forbidden = Template comments are not allowed within property tags.
+template_matching_unexpected = Unexpected matching.
+template_property_unknown = %s has no property called '%s'.
+template_event_unknown = %s has no event called '%s'.
+template_property_readonly = %s has a read-only property '%s'.
+template_event_forbidden = %s is a non-control component. No handler can be attached to its event '%s' in a template.
+template_databind_forbidden = %s is a non-control component. No databinding expression can be set to its property '%s'.
+template_component_required = '%s' is not a component. Only components can appear in a template.
+template_format_invalid = Error in %s (line %d) : %s
+template_format_invalid2 = Error at line %d of the following template: %s %s
xmldocument_file_read_failed = TXmlDocument is unable to read file '%s'.
xmldocument_file_write_failed = TXmlDocument is unable to write file '%s'.
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php
index 5bf0d4bb..3c522897 100644
--- a/framework/Web/UI/TTemplateManager.php
+++ b/framework/Web/UI/TTemplateManager.php
@@ -430,208 +430,156 @@ class TTemplate extends TComponent implements ITemplate
$textStart=0;
$stack=array();
$container=-1;
+ $matchEnd=0;
$c=0;
- for($i=0;$i<$n;++$i)
+ try
{
- $match=&$matches[$i];
- $str=$match[0][0];
- $matchStart=$match[0][1];
- $matchEnd=$matchStart+strlen($str)-1;
- if(strpos($str,'$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- $type=$match[1][0];
- $attributes=$this->parseAttributes($match[2][0]);
- try
+ $match=&$matches[$i];
+ $str=$match[0][0];
+ $matchStart=$match[0][1];
+ $matchEnd=$matchStart+strlen($str)-1;
+ if(strpos($str,'$textStart)
+ $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
+ $textStart=$matchEnd+1;
+ $type=$match[1][0];
+ $attributes=$this->parseAttributes($match[2][0]);
$this->validateAttributes($type,$attributes);
+ $tpl[$c++]=array($container,$type,$attributes);
+ if($str[strlen($str)-2]!=='/') // open tag
+ {
+ array_push($stack,$type);
+ $container=$c-1;
+ }
}
- catch(Exception $e)
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_componenttag_invalid',"Line $line",$type,$e->getMessage());
- else
- throw new TConfigurationException('template_componenttag_invalid',"{$this->_tplFile} (Line $line)",$type,$e->getMessage());
- }
- $tpl[$c++]=array($container,$type,$attributes);
- if($str[strlen($str)-2]!=='/') // open tag
+ else if(strpos($str,'$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- $type=$match[1][0];
+ if($expectPropEnd)
+ continue;
+ if($matchStart>$textStart)
+ $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
+ $textStart=$matchEnd+1;
+ $type=$match[1][0];
- if(empty($stack))
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_closingtag_unexpected',"Line $line","");
- else
- throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","");
- }
+ if(empty($stack))
+ throw new TConfigurationException('template_closingtag_unexpected',"");
- $name=array_pop($stack);
- if($name!==$type)
- {
- if($name[0]==='@')
- $tag='';
- else
- $tag='';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_closingtag_expected',"Line $line",$tag);
- else
- throw new TConfigurationException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
- }
- $container=$tpl[$container][0];
- }
- else if(strpos($str,'<%@')===0) // directive
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- if(isset($tpl[0]))
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_directive_nonunique',"Line $line");
- else
- throw new TConfigurationException('template_directive_nonunique',"{$this->_tplFile} (Line $line)");
+ $name=array_pop($stack);
+ if($name!==$type)
+ {
+ $tag=$name[0]==='@' ? '' : "";
+ throw new TConfigurationException('template_closingtag_expected',$tag);
+ }
+ $container=$tpl[$container][0];
}
- $this->_directive=$this->parseAttributes($match[4][0]);
- }
- else if(strpos($str,'<%')===0) // expression
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- if($str[2]==='=') // expression
- $tpl[$c++]=array($container,'TExpression',array('Expression'=>THttpUtility::htmlDecode($match[5][0])));
- else if($str[2]==='%') // statements
- $tpl[$c++]=array($container,'TStatements',array('Statements'=>THttpUtility::htmlDecode($match[5][0])));
- else
- $tpl[$c++]=array($container,'TLiteral',array('Text'=>$this->parseAttribute($str)));
- }
- else if(strpos($str,'$textStart)
$tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
$textStart=$matchEnd+1;
- $expectPropEnd=true;
+ if(isset($tpl[0]))
+ throw new TConfigurationException('template_directive_nonunique');
+ $this->_directive=$this->parseAttributes($match[4][0]);
}
- }
- else if(strpos($str,'_tplFile===null)
- throw new TConfigurationException('template_closingtag_unexpected',"Line $line","");
+ if($expectPropEnd)
+ continue;
+ if($matchStart>$textStart)
+ $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
+ $textStart=$matchEnd+1;
+ if($str[2]==='=') // expression
+ $tpl[$c++]=array($container,'TExpression',array('Expression'=>THttpUtility::htmlDecode($match[5][0])));
+ else if($str[2]==='%') // statements
+ $tpl[$c++]=array($container,'TStatements',array('Statements'=>THttpUtility::htmlDecode($match[5][0])));
else
- throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","");
+ $tpl[$c++]=array($container,'TLiteral',array('Text'=>$this->parseAttribute($str)));
}
- $name=array_pop($stack);
- if($name!=='@'.$prop)
+ else if(strpos($str,'';
- else
- $tag='';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_closingtag_expected',"Line $line",$tag);
- else
- throw new TConfigurationException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
+ $prop=strtolower($match[3][0]);
+ array_push($stack,'@'.$prop);
+ if(!$expectPropEnd)
+ {
+ if($matchStart>$textStart)
+ $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
+ $textStart=$matchEnd+1;
+ $expectPropEnd=true;
+ }
}
- if(($last=count($stack))<1 || $stack[$last-1][0]!=='@')
+ else if(strpos($str,'$textStart && $container>=0)
+ $prop=strtolower($match[3][0]);
+ if(empty($stack))
+ {
+ $line=count(explode("\n",substr($input,0,$matchEnd+1)));
+ if($this->_tplFile===null)
+ throw new TConfigurationException('template_closingtag_unexpected',"Line $line","");
+ else
+ throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","");
+ }
+ $name=array_pop($stack);
+ if($name!=='@'.$prop)
{
- $value=substr($input,$textStart,$matchStart-$textStart);
- $value=$this->parseAttribute($value);
- $type=$tpl[$container][1];
- try
+ $tag=$name[0]==='@' ? '' : "";
+ throw new TConfigurationException('template_closingtag_expected',$tag);
+ }
+ if(($last=count($stack))<1 || $stack[$last-1][0]!=='@')
+ {
+ if($matchStart>$textStart && $container>=0)
{
+ $value=substr($input,$textStart,$matchStart-$textStart);
+ $value=$this->parseAttribute($value);
+ $type=$tpl[$container][1];
$this->validateAttributes($type,array($prop=>$value));
+ $tpl[$container][2][$prop]=$value;
+ $textStart=$matchEnd+1;
}
- catch(Exception $e)
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_componenttag_invalid',"Line $line",$type,$e->getMessage());
- else
- throw new TConfigurationException('template_componenttag_invalid',"{$this->_tplFile} (Line $line)",$type,$e->getMessage());
- }
- $tpl[$container][2][$prop]=$value;
- $textStart=$matchEnd+1;
+ $expectPropEnd=false;
}
- $expectPropEnd=false;
}
- }
- else if(strpos($str,'