From 976e3aa06ebe82fe6d1c7317c827425111be5df6 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sun, 29 Jan 2006 09:14:14 +0000 Subject: Added support to template tag. --- framework/Exceptions/messages.txt | 1 + framework/Web/Services/TPageService.php | 11 +++-- framework/Web/UI/TPage.php | 15 ------- framework/Web/UI/TTemplateManager.php | 79 ++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 44 deletions(-) (limited to 'framework') diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 55c2f112..602efcdd 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -106,6 +106,7 @@ template_databind_forbidden = %s is a non-control component. No databinding e 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 +template_eventhandler_invalid = An invalid event handler is attached to %s's event '%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/Services/TPageService.php b/framework/Web/Services/TPageService.php index 0d8f28b9..239cf870 100644 --- a/framework/Web/Services/TPageService.php +++ b/framework/Web/Services/TPageService.php @@ -442,10 +442,15 @@ class TPageService extends TService } else $className='TPage'; - //allow the page constructor to change application settings before template is loaded + $this->_page=new $className(); - $this->_properties['Template']=$this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT); - $this->_page->initializeProperties($this->_properties); + + // initialize page properties with those set in configurations + foreach($this->_properties as $name=>$value) + $this->_page->setSubProperty($name,$value); + + // set page template + $this->_page->setTemplate($this->getTemplateManager()->getTemplateByFileName($path.self::PAGE_FILE_EXT)); } else throw new THttpException(404,'pageservice_page_unknown',$this->_pagePath); diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index a5e4fa52..b7c1bae6 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -120,21 +120,6 @@ class TPage extends TTemplateControl $this->setPage($this); } - /** - * If initial property values are given, they will be set to the page. - * @param array initial property values for the page. - */ - public function initializeProperties($initProperties=null) - { - Prado::trace('Constructing page','System.Web.UI.TPage'); - if(is_array($initProperties)) - { - Prado::trace('Initializing page properties specified in configurations','System.Web.UI.TPage'); - foreach($initProperties as $name=>$value) - $this->setSubProperty($name,$value); - } - } - /** * Runs through the page lifecycles. * This method runs through the page lifecycles. diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php index 312b821d..8ca95b33 100644 --- a/framework/Web/UI/TTemplateManager.php +++ b/framework/Web/UI/TTemplateManager.php @@ -70,7 +70,7 @@ class TTemplateManager extends TModule */ public function getTemplateByFileName($fileName) { - if(!is_null($fileName=$this->getLocalizedTemplate($fileName))) + if(($fileName=$this->getLocalizedTemplate($fileName))!==null) { Prado::trace("Loading template $fileName",'System.Web.UI.TTemplateManager'); if(($cache=$this->getApplication()->getCache())===null) @@ -107,7 +107,7 @@ class TTemplateManager extends TModule if(($file=realpath($file))!==false && is_file($file)) return $file; } - + return null; } } @@ -164,6 +164,7 @@ class TTemplate extends TComponent implements ITemplate const CONFIG_ASSET=2; const CONFIG_PARAMETER=3; const CONFIG_LOCALIZATION=4; + const CONFIG_TEMPLATE=5; /** * @var array list of component tags and strings @@ -185,6 +186,14 @@ class TTemplate extends TComponent implements ITemplate * @var TAssetManager asset manager */ private $_assetManager; + /** + * @var integer the line number that parsing starts from (internal use) + */ + private $_startingLine=0; + /** + * @var string template content to be parsed + */ + private $_content; /** @@ -193,12 +202,16 @@ class TTemplate extends TComponent implements ITemplate * @param string the template string * @param string the template context directory * @param string the template file, null if no file + * @param integer the line number that parsing starts from (internal use) */ - public function __construct($template,$contextPath,$tplFile=null) + public function __construct($template,$contextPath,$tplFile=null,$startingLine=0) { $this->_contextPath=$contextPath; $this->_tplFile=$tplFile; + $this->_startingLine=$startingLine; + $this->_content=$template; $this->parse($template); + $this->_content=null; // reset to save memory } /** @@ -292,7 +305,7 @@ class TTemplate extends TComponent implements ITemplate */ protected function configureControl($control,$name,$value) { - if(is_string($value) && strncasecmp($name,'on',2)===0) // is an event + if(strncasecmp($name,'on',2)===0) // is an event $this->configureEvent($control,$name,$value); else if(strpos($name,'.')===false) // is a simple property or custom attribute $this->configureProperty($control,$name,$value); @@ -347,6 +360,9 @@ class TTemplate extends TComponent implements ITemplate case self::CONFIG_EXPRESSION: $component->$setter($component->evaluateExpression($value[1])); break; + case self::CONFIG_TEMPLATE: + $component->$setter($value[1]); + break; case self::CONFIG_ASSET: // asset URL $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$value[1]); $component->$setter($url); @@ -384,6 +400,9 @@ class TTemplate extends TComponent implements ITemplate case self::CONFIG_EXPRESSION: // expression $component->setSubProperty($name,$component->evaluateExpression($value[1])); break; + case self::CONFIG_TEMPLATE: + $component->setSubProperty($name,$value[1]); + break; case self::CONFIG_ASSET: // asset URL $url=$this->_assetManager->publishFilePath($this->_contextPath.'/'.$value[1]); $component->setSubProperty($name,$url); @@ -449,7 +468,7 @@ class TTemplate extends TComponent implements ITemplate $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); $textStart=$matchEnd+1; $type=$match[1][0]; - $attributes=$this->parseAttributes($match[2][0]); + $attributes=$this->parseAttributes($match[2][0],$match[2][1]); $this->validateAttributes($type,$attributes); $tpl[$c++]=array($container,$type,$attributes); if($str[strlen($str)-2]!=='/') // open tag @@ -487,7 +506,7 @@ class TTemplate extends TComponent implements ITemplate $textStart=$matchEnd+1; if(isset($tpl[0])) throw new TConfigurationException('template_directive_nonunique'); - $this->_directive=$this->parseAttributes($match[4][0]); + $this->_directive=$this->parseAttributes($match[4][0],$match[4][1]); } else if(strpos($str,'<%')===0) // expression { @@ -501,7 +520,7 @@ class TTemplate extends TComponent implements ITemplate 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))); + $tpl[$c++]=array($container,'TLiteral',array('Text'=>$this->parseAttribute($str,$matchStart))); } else if(strpos($str,'_tplFile===null) - throw new TConfigurationException('template_closingtag_unexpected',"Line $line",""); - else - throw new TConfigurationException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)",""); - } + throw new TConfigurationException('template_closingtag_unexpected',""); $name=array_pop($stack); if($name!=='@'.$prop) { @@ -537,7 +550,7 @@ class TTemplate extends TComponent implements ITemplate if($matchStart>$textStart && $container>=0) { $value=substr($input,$textStart,$matchStart-$textStart); - $value=$this->parseAttribute($value); + $value=$this->parseAttribute($value,$textStart); $type=$tpl[$container][1]; $this->validateAttributes($type,array($prop=>$value)); $tpl[$container][2][$prop]=$value; @@ -572,10 +585,12 @@ class TTemplate extends TComponent implements ITemplate } catch(Exception $e) { + if($e->getErrorCode()==='template_format_invalid' || $e->getErrorCode()==='template_format_invalid2') + throw $e; if($matchEnd===0) - $line=1; + $line=$this->_startingLine+1; else - $line=count(explode("\n",substr($input,0,$matchEnd+1))); + $line=$this->_startingLine+count(explode("\n",substr($input,0,$matchEnd+1))); if(empty($this->_tplFile)) throw new TConfigurationException('template_format_invalid2',$line,$e->getMessage(),$input); else @@ -589,20 +604,22 @@ class TTemplate extends TComponent implements ITemplate * @param string the string to be parsed. * @return array attribute values indexed by names. */ - protected function parseAttributes($str) + protected function parseAttributes($str,$offset) { if($str==='') return array(); $pattern='/([\w\.]+)=(\'.*?\'|".*?"|<%.*?%>)/msS'; $attributes=array(); - $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER); + $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); for($i=0;$i<$n;++$i) { - $name=strtolower($matches[$i][1]); - $value=$matches[$i][2]; + $match=&$matches[$i]; + $name=strtolower($match[1][0]); + $value=$match[2][0]; if($value[0]==='\'' || $value[0]==='"') - $value=substr($value,1,strlen($value)-2); - $attributes[$name]=$this->parseAttribute($value); + $attributes[$name]=$this->parseAttribute(substr($value,1,strlen($value)-2),$match[2][1]+1); + else + $attributes[$name]=$this->parseAttribute($value,$match[2][1]); } return $attributes; } @@ -612,12 +629,20 @@ class TTemplate extends TComponent implements ITemplate * @param string the string to be parsed. * @return array attribute initialization */ - protected function parseAttribute($value) + protected function parseAttribute($value,$offset) { $matches=array(); - if(!preg_match('/^(<%#.*?%>|<%=.*?%>|<%~.*?%>|<%\\$.*?%>|<%\\[.*?\\]%>)$/msS',$value,$matches)) + if(!preg_match('/\\s*(<%!.*?%>|<%#.*?%>|<%=.*?%>|<%~.*?%>|<%\\$.*?%>|<%\\[.*?\\]%>)\\s*/msS',$value,$matches) || $matches[0]!==$value) return THttpUtility::htmlDecode($value); - $value=THttpUtility::htmlDecode($matches[1]); + $match=$matches[1]; + if($match[2]==='!') + { + $offset+=strpos($value,$match); + $line=$this->_startingLine+count(explode("\n",substr($this->_content,0,$offset)))-1; + $content=substr($match,3,strlen($match)-5); + return array(self::CONFIG_TEMPLATE,new TTemplate($content,$this->_contextPath,$this->_tplFile,$line)); + } + $value=THttpUtility::htmlDecode($match); if($value[2]==='#') // databind return array(self::CONFIG_DATABIND,substr($value,3,strlen($value)-5)); else if($value[2]==='=') // a dynamic initialization @@ -653,6 +678,8 @@ class TTemplate extends TComponent implements ITemplate // an event if(!is_callable(array($className,$name))) throw new TConfigurationException('template_event_unknown',$type,$name); + else if(!is_string($att)) + throw new TConfigurationException('template_eventhandler_invalid',$type,$name); } else { -- cgit v1.2.3