From 93d3916faec05987e549f0df58474312a591aa76 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sat, 9 Sep 2006 21:56:58 +0000 Subject: Fixed #366. --- framework/Exceptions/messages.txt | 1 + framework/Web/UI/TTemplateManager.php | 109 +++++++++++++++++++++++++++++++--- 2 files changed, 103 insertions(+), 7 deletions(-) (limited to 'framework') diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index d0aff516..38aab10f 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -123,6 +123,7 @@ template_eventhandler_invalid = {0}.{1} can only accept a static string. template_controlid_invalid = {0}.ID can only accept a static text string. template_controlskinid_invalid = {0}.SkinID can only accept a static text string. template_content_unexpected = Unexpected content is encountered when instantiating template: {0}. +template_include_invalid = Invalid template inclusion. Make sure {0} is a valid namespace pointing to an existing template file whose extension is .tpl. xmldocument_file_read_failed = TXmlDocument is unable to read file '{0}'. xmldocument_file_write_failed = TXmlDocument is unable to write file '{0}'. diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php index 264112fc..4e71e4c1 100644 --- a/framework/Web/UI/TTemplateManager.php +++ b/framework/Web/UI/TTemplateManager.php @@ -80,12 +80,28 @@ class TTemplateManager extends TModule $array=$cache->get(self::TEMPLATE_CACHE_PREFIX.$fileName); if(is_array($array)) { - list($template,$timestamp)=$array; - if(filemtime($fileName)<$timestamp) + list($template,$timestamps)=$array; + if($this->getApplication()->getMode()===TApplicationMode::Performance) + return $template; + $cacheValid=true; + foreach($timestamps as $tplFile=>$timestamp) + { + if(!is_file($tplFile) || filemtime($tplFile)>$timestamp) + { + $cacheValid=false; + break; + } + } + if($cacheValid) return $template; } $template=new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName); - $cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,time())); + $includedFiles=$template->getIncludedFiles(); + $timestamps=array(); + $timestamps[$fileName]=filemtime($fileName); + foreach($includedFiles as $includedFile) + $timestamps[$includedFile]=filemtime($includedFile); + $cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,$timestamps)); return $template; } } @@ -194,6 +210,9 @@ class TTemplate extends TApplicationComponent implements ITemplate */ private $_sourceTemplate=true; private $_tplControl=null; + private $_includedFiles=array(); + private $_includeAtLine=array(); + private $_includeLines=array(); /** @@ -513,6 +532,7 @@ class TTemplate extends TApplicationComponent implements ITemplate */ protected function parse($input) { + $input=$this->preprocess($input); $tpl=&$this->_tpl; $n=preg_match_all(self::REGEX_RULES,$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE); $expectPropEnd=false; @@ -681,10 +701,7 @@ class TTemplate extends TApplicationComponent implements ITemplate $line=$this->_startingLine+1; else $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 - throw new TConfigurationException('template_format_invalid',$this->_tplFile,$line,$e->getMessage()); + $this->handleException($e,$line,$input); } if($this->_directive===null) @@ -898,6 +915,84 @@ class TTemplate extends TApplicationComponent implements ITemplate else throw new TConfigurationException('template_component_required',$type); } + + /** + * @return array list of included external template files + */ + public function getIncludedFiles() + { + return $this->_includedFiles; + } + + /** + * Handles template parsing exception. + * This method rethrows the exception caught during template parsing. + * It adjusts the error location by giving out correct error line number and source file. + * @param Exception template exception + * @param int line number + * @param string template string if no source file is used + */ + protected function handleException($e,$line,$input=null) + { + $srcFile=$this->_tplFile; + if(($n=count($this->_includedFiles))>0) // need to adjust error row number and file name + { + for($i=$n-1;$i>=0;--$i) + { + if($this->_includeAtLine[$i]<=$line) + { + if($line<$this->_includeAtLine[$i]+$this->_includeLines[$i]) + { + $line=$line-$this->_includeAtLine[$i]+1; + $srcFile=$this->_includedFiles[$i]; + break; + } + else + $line=$line-$this->_includeLines[$i]+1; + } + } + } + if(empty($srcFile)) + throw new TConfigurationException('template_format_invalid2',$line,$e->getMessage(),$input); + else + throw new TConfigurationException('template_format_invalid',$srcFile,$line,$e->getMessage()); + } + + /** + * Preprocesses the template string by including external templates + * @param string template string + * @return string expanded template string + */ + protected function preprocess($input) + { + if($n=preg_match_all('/<%include(.*?)%>/',$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) + { + for($i=0;$i<$n;++$i) + { + $filePath=Prado::getPathOfNamespace(trim($matches[$i][1][0]),TTemplateManager::TEMPLATE_FILE_EXT); + if($filePath!==null && is_file($filePath)) + $this->_includedFiles[]=$filePath; + else + { + $errorLine=count(explode("\n",substr($input,0,$matches[$i][0][1]+1))); + $this->handleException(new TConfigurationException('template_include_invalid',trim($matches[$i][1][0])),$errorLine,$input); + } + } + $base=0; + for($i=0;$i<$n;++$i) + { + $ext=file_get_contents($this->_includedFiles[$i]); + $length=strlen($matches[$i][0][0]); + $offset=$base+$matches[$i][0][1]; + $this->_includeAtLine[$i]=count(explode("\n",substr($input,0,$offset))); + $this->_includeLines[$i]=count(explode("\n",$ext)); + $input=substr_replace($input,$ext,$offset,$length); + $base+=strlen($ext)-$length; + } + } + + return $input; + } } ?> \ No newline at end of file -- cgit v1.2.3