From 4226093cc034dfbd25a5b9e9aee2778e795ee42a Mon Sep 17 00:00:00 2001 From: xue <> Date: Fri, 7 Apr 2006 03:46:10 +0000 Subject: Merge from 3.0 till 868. --- framework/Web/UI/TControl.php | 18 ++-- framework/Web/UI/TTemplateManager.php | 166 ++++++++++++++++++++++++++++++++-- 2 files changed, 166 insertions(+), 18 deletions(-) (limited to 'framework/Web') diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php index 52ec9bb1..15965a74 100644 --- a/framework/Web/UI/TControl.php +++ b/framework/Web/UI/TControl.php @@ -68,7 +68,7 @@ Prado::using('System.Web.UI.TControlAdapter'); * @package System.Web.UI * @since 3.0 */ -class TControl extends TApplicationComponent +class TControl extends TApplicationComponent implements IRenderable, IBindable { /** * format of control ID @@ -772,7 +772,7 @@ class TControl extends TApplicationComponent if(isset($this->_rf[self::RF_CONTROLS])) { foreach($this->_rf[self::RF_CONTROLS] as $control) - if($control instanceof TControl) + if($control instanceof IBindable) $control->dataBind(); } } @@ -1416,10 +1416,12 @@ class TControl extends TApplicationComponent { foreach($this->_rf[self::RF_CONTROLS] as $control) { - if($control instanceof TControl) - $control->renderControl($writer); - else if(is_string($control)) + if(is_string($control)) $writer->write($control); + else if($control instanceof TControl) + $control->renderControl($writer); + else if($control instanceof IRenderable) + $control->render($writer); } } } @@ -1660,13 +1662,13 @@ class TControlCollection extends TList */ public function insertAt($index,$item) { - if(is_string($item)) - parent::insertAt($index,$item); - else if($item instanceof TControl) + if($item instanceof TControl) { parent::insertAt($index,$item); $this->_o->addedControl($item); } + else if(is_string($item) || ($item instanceof IRenderable)) + parent::insertAt($index,$item); else throw new TInvalidDataTypeException('controlcollection_control_required'); } diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php index 26cc9c3a..fa4cbcbf 100644 --- a/framework/Web/UI/TTemplateManager.php +++ b/framework/Web/UI/TTemplateManager.php @@ -126,8 +126,7 @@ class TTemplateManager extends TModule * can be a property name, an event name or a regular tag attribute name. * - directive: directive specifies the property values for the template owner. * It is in the format of <% property name-value pairs %> - * - expressions: expressions are shorthand of {@link TExpression} and {@link TStatements} - * controls. They are in the formate of <= PHP expression > and < PHP statements > + * - expressions: They are in the formate of <= PHP expression > and <% PHP statements > * - comments: There are two kinds of comments, regular HTML comments and special template comments. * The former is in the format of <!-- comments -->, which will be treated as text strings. * The latter is in the format of <%* comments %>, which will be stripped out. @@ -310,7 +309,16 @@ class TTemplate extends TApplicationComponent implements ITemplate } } else // string - $parent->addParsedObject($object[1]); + { + if($object[1] instanceof TCompositeLiteral) + { + $o=clone $object[1]; + $o->setContainer($tplControl); + $parent->addParsedObject($o); + } + else + $parent->addParsedObject($object[1]); + } } } @@ -388,8 +396,7 @@ class TTemplate extends TApplicationComponent implements ITemplate $component->$setter($this->getApplication()->getParameters()->itemAt($value[1])); break; case self::CONFIG_LOCALIZATION: - Prado::using('System.I18N.Translation'); - $component->$setter(localize(trim($value[1]))); + $component->$setter(Prado::localize($value[1])); break; default: // an error if reaching here break; @@ -532,12 +539,22 @@ class TTemplate extends TApplicationComponent implements ITemplate if($matchStart>$textStart) $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart)); $textStart=$matchEnd+1; + $literal=trim(THttpUtility::htmlDecode($match[5][0])); if($str[2]==='=') // expression - $tpl[$c++]=array($container,'TExpression',array('Expression'=>THttpUtility::htmlDecode($match[5][0]))); + $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,$literal)); 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,array(TCompositeLiteral::TYPE_STATEMENTS,$literal)); + else if($str[2]==='#') + $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_DATABINDING,$literal)); + else if($str[2]==='$') + $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->getApplication()->getParameters()->itemAt('$literal')")); + else if($str[2]==='~') + $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"\$this->publishFilePath('$this->_contextPath/$literal')")); + else if($str[2]==='[') + { + $literal=trim(substr($literal,0,strlen($literal)-1)); + $tpl[$c++]=array($container,array(TCompositeLiteral::TYPE_EXPRESSION,"Prado::localize('$literal')")); + } } else if(strpos($str,'_tplFile,$line,$e->getMessage()); } - return $tpl; + + // optimization by merging consecutive strings, expressions, statements and bindings + $objects=array(); + $parent=null; + $merged=array(); + foreach($tpl as $id=>$object) + { + if(isset($object[2]) || $object[0]!==$parent) + { + if($parent!==null) + { + if(count($merged[1])===1 && is_string($merged[1][0])) + $objects[$id-1]=array($merged[0],$merged[1][0]); + else + $objects[$id-1]=array($merged[0],new TCompositeLiteral($merged[1])); + } + if(isset($object[2])) + { + $parent=null; + $objects[$id]=$object; + } + else + { + $parent=$object[0]; + $merged=array($parent,array($object[1])); + } + } + else + $merged[1][]=$object[1]; + } + if($parent!==null) + { + if(count($merged[1])===1 && is_string($merged[1][0])) + $objects[$id]=array($merged[0],$merged[1][0]); + else + $objects[$id]=array($merged[0],new TCompositeLiteral($merged[1])); + } + $tpl=$objects; + return $objects; } /** @@ -768,4 +823,95 @@ class TTemplate extends TApplicationComponent implements ITemplate } } +/** + * TCompositeLiteral class + * + * TCompositeLiteral is used internally by {@link TTemplate} for representing + * consecutive static strings, expressions and statements. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI + * @since 3.0 + */ +class TCompositeLiteral extends TComponent implements IRenderable, IBindable +{ + const TYPE_EXPRESSION=0; + const TYPE_STATEMENTS=1; + const TYPE_DATABINDING=2; + private $_container=null; + private $_items=array(); + private $_expressions=array(); + private $_statements=array(); + private $_bindings=array(); + + /** + * Constructor. + * @param array list of items to be represented by TCompositeLiteral + */ + public function __construct($items) + { + $this->_items=array(); + $this->_expressions=array(); + $this->_statements=array(); + foreach($items as $id=>$item) + { + if(is_array($item)) + { + if($item[0]===self::TYPE_EXPRESSION) + $this->_expressions[$id]=$item[1]; + else if($item[0]===self::TYPE_STATEMENTS) + $this->_statements[$id]=$item[1]; + else if($item[0]===self::TYPE_DATABINDING) + $this->_bindings[$id]=$item[1]; + $this->_items[$id]=''; + } + else + $this->_items[$id]=$item; + } + } + + /** + * @return TComponent container of this component. It serves as the evaluation context of expressions and statements. + */ + public function getContainer() + { + return $this->_container; + } + + /** + * @param TComponent container of this component. It serves as the evaluation context of expressions and statements. + */ + public function setContainer(TComponent $value) + { + $this->_container=$value; + } + + /** + * Renders the content stored in this component. + * This method is required by {@link IRenderable} + * @param ITextWriter + */ + public function render($writer) + { + $context=$this->_container===null?$this:$this->_container; + foreach($this->_expressions as $id=>$expression) + $this->_items[$id]=$context->evaluateExpression($expression); + foreach($this->_statements as $id=>$statement) + $this->_items[$id]=$context->evaluateStatements($statement); + $writer->write(implode('',$this->_items)); + } + + /** + * Performs databindings. + * This method is required by {@link IBindable} + */ + public function dataBind() + { + $context=$this->_container===null?$this:$this->_container; + foreach($this->_bindings as $id=>$binding) + $this->_items[$id]=$context->evaluateExpression($binding); + } +} + ?> \ No newline at end of file -- cgit v1.2.3