summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--demos/quickstart/protected/pages/Configurations/AppConfig.page3
-rw-r--r--framework/Exceptions/messages.txt27
-rw-r--r--framework/Web/UI/TTemplateManager.php296
-rw-r--r--framework/core.php28
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 <tt>application.
<li>The <tt>&lt;services&gt;</tt> element is similar to the <tt>&lt;modules&gt;</tt> element. It mainly specifies the services provided by the application.</li>
<li>The <tt>&lt;parameters&gt;</tt> 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,
<com:TTextHighlighter Language="xml" CssClass="source">
-<parameter id="ParameterID">ParameterValue</parameter>
+<parameter id="ParameterID" value="ParameterValue" />
</com:TTextHighlighter>
+Note, if the <tt>value</tt> attribute is not specified, the whole parameter XML node (of type <tt>TXmlElement</tt>) will be returned as the parameter value.
</li>
</ul>
<p>
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 = <module id="%s"> must have a "class" attr
pageserviceconf_parameter_invalid = <parameter> element must have an "id" attribute in page directory configuration file '%s'.
pageserviceconf_page_invalid = <page> 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 <com:%s> 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,'<com:')===0) // opening component tag
+ for($i=0;$i<$n;++$i)
{
- if($expectPropEnd)
- continue;
- if($matchStart>$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,'<com:')===0) // opening component tag
{
+ if($expectPropEnd)
+ continue;
+ if($matchStart>$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,'</com:')===0) // closing component tag
{
- array_push($stack,$type);
- $container=$c-1;
- }
- }
- else if(strpos($str,'</com:')===0) // closing component tag
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$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","</com:$type>");
- else
- throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","</com:$type>");
- }
+ if(empty($stack))
+ throw new TConfigurationException('template_closingtag_unexpected',"</com:$type>");
- $name=array_pop($stack);
- if($name!==$type)
- {
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
- else
- $tag='</com:'.$name.'>';
- $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]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";
+ 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,'<prop:')===0) // opening property
- {
- $prop=strtolower($match[3][0]);
- array_push($stack,'@'.$prop);
- if(!$expectPropEnd)
+ else if(strpos($str,'<%@')===0) // directive
{
+ if($expectPropEnd)
+ continue;
if($matchStart>$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,'</prop:')===0) // closing property
- {
- $prop=strtolower($match[3][0]);
- if(empty($stack))
+ else if(strpos($str,'<%')===0) // expression
{
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_closingtag_unexpected',"Line $line","</prop:$prop>");
+ 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)","</prop:$prop>");
+ $tpl[$c++]=array($container,'TLiteral',array('Text'=>$this->parseAttribute($str)));
}
- $name=array_pop($stack);
- if($name!=='@'.$prop)
+ else if(strpos($str,'<prop:')===0) // opening property
{
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
- else
- $tag='</com:'.$name.'>';
- $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,'</prop:')===0) // closing property
{
- if($matchStart>$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","</prop:$prop>");
+ else
+ throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","</prop:$prop>");
+ }
+ $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]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";
+ 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,'<!--')===0) // HTML comments
- {
- $state=0;
- }
- else if(strpos($str,'<!')===0) // template comments
- {
- if($expectPropEnd)
+ else if(strpos($str,'<!--')===0) // HTML comments
{
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_comments_forbidden',"Line $line");
- else
- throw new TConfigurationException('template_comments_forbidden',"{$this->_tplFile} (Line $line)");
+ $state=0;
}
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
+ else if(strpos($str,'<!')===0) // template comments
+ {
+ if($expectPropEnd)
+ throw new TConfigurationException('template_comments_forbidden');
+ if($matchStart>$textStart)
+ $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
+ $textStart=$matchEnd+1;
+ }
+ else
+ throw new TConfigurationException('template_matching_unexpected',$match);
}
- else
+ if(!empty($stack))
{
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_matching_unexpected',"Line $line",$match);
- else
- throw new TConfigurationException('template_matching_unexpected',"{$this->_tplFile} (Line $line)",$match);
+ $name=array_pop($stack);
+ $tag=$name[0]==='@' ? '</prop:'.substr($name,1).'>' : "</com:$name>";
+ throw new TConfigurationException('template_closingtag_expected',$tag);
}
+ if($textStart<strlen($input))
+ $tpl[$c++]=array($container,substr($input,$textStart));
}
- if(!empty($stack))
+ catch(Exception $e)
{
- $name=array_pop($stack);
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
+ if($matchEnd===0)
+ $line=1;
else
- $tag='</com:'.$name.'>';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TConfigurationException('template_closingtag_expected',"Line $line",$tag);
+ $line=count(explode("\n",substr($input,0,$matchEnd+1)));
+ if(empty($this->_tplFile))
+ throw new TConfigurationException('template_format_invalid2',$line,$e->getMessage(),$input);
else
- throw new TConfigurationException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
+ throw new TConfigurationException('template_format_invalid',$this->_tplFile,$line,$e->getMessage());
}
- if($textStart<strlen($input))
- $tpl[$c++]=array($container,substr($input,$textStart));
return $tpl;
}
@@ -697,13 +645,13 @@ class TTemplate extends TComponent implements ITemplate
// a subproperty, so the first segment must be readable
$subname=substr($name,0,$pos);
if(!is_callable(array($className,'get'.$subname)))
- throw new TConfigurationException('template_property_unknown',$subname);
+ throw new TConfigurationException('template_property_unknown',$type,$subname);
}
else if(strncasecmp($name,'on',2)===0)
{
// an event
if(!is_callable(array($className,$name)))
- throw new TConfigurationException('template_event_unknown',$name);
+ throw new TConfigurationException('template_event_unknown',$type,$name);
}
else
{
@@ -711,9 +659,9 @@ class TTemplate extends TComponent implements ITemplate
if(!is_callable(array($className,'set'.$name)))
{
if(is_callable(array($className,'get'.$name)))
- throw new TConfigurationException('template_property_readonly',$name);
+ throw new TConfigurationException('template_property_readonly',$type,$name);
else
- throw new TConfigurationException('template_property_unknown',$name);
+ throw new TConfigurationException('template_property_unknown',$type,$name);
}
}
}
@@ -723,25 +671,25 @@ class TTemplate extends TComponent implements ITemplate
foreach($attributes as $name=>$att)
{
if($att[0]===self::CONFIG_DATABIND)
- throw new TConfigurationException('template_databind_forbidden',$name);
+ throw new TConfigurationException('template_databind_forbidden',$type,$name);
if(($pos=strpos($name,'.'))!==false)
{
// a subproperty, so the first segment must be readable
$subname=substr($name,0,$pos);
if(!is_callable(array($className,'get'.$subname)))
- throw new TConfigurationException('template_property_unknown',$subname);
+ throw new TConfigurationException('template_property_unknown',$type,$subname);
}
else if(strncasecmp($name,'on',2)===0)
- throw new TConfigurationException('template_event_forbidden',$name);
+ throw new TConfigurationException('template_event_forbidden',$type,$name);
else
{
// id is still alowed for TComponent, even if id property doesn't exist
if(strcasecmp($name,'id')!==0 && !is_callable(array($className,'set'.$name)))
{
if(is_callable(array($className,'get'.$name)))
- throw new TConfigurationException('template_property_readonly',$name);
+ throw new TConfigurationException('template_property_readonly',$type,$name);
else
- throw new TConfigurationException('template_property_unknown',$name);
+ throw new TConfigurationException('template_property_unknown',$type,$name);
}
}
}
diff --git a/framework/core.php b/framework/core.php
index 293209d0..6c31bc55 100644
--- a/framework/core.php
+++ b/framework/core.php
@@ -538,9 +538,17 @@ class PradoBase
return;
if(($pos=strrpos($namespace,'.'))===false) // a class name
{
- include_once($namespace.self::CLASS_FILE_EXT);
- if(!class_exists($namespace,false))
- throw new TInvalidOperationException('prado_component_unknown',$namespace);
+ try
+ {
+ include_once($namespace.self::CLASS_FILE_EXT);
+ }
+ catch(Exception $e)
+ {
+ if(!class_exists($namespace,false))
+ throw new TInvalidOperationException('prado_component_unknown',$namespace);
+ else
+ throw $e;
+ }
}
else if(($path=self::getPathOfNamespace($namespace,self::CLASS_FILE_EXT))!==null)
{
@@ -561,7 +569,19 @@ class PradoBase
{
self::$_usings[$namespace]=$path;
if(!class_exists($className,false))
- include_once($path);
+ {
+ try
+ {
+ include_once($path);
+ }
+ catch(Exception $e)
+ {
+ if(!class_exists($className,false))
+ throw new TInvalidOperationException('prado_component_unknown',$className);
+ else
+ throw $e;
+ }
+ }
}
else
throw new TInvalidDataValueException('prado_using_invalid',$namespace);