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. --- HISTORY | 2 + UPGRADE | 18 ++- .../protected/pages/Configurations/Templates2.page | 30 ++-- .../protected/pages/Controls/Expression.page | 13 +- .../pages/Controls/Samples/TDataGrid/Sample2.page | 2 +- .../pages/Controls/Samples/TDataGrid/Sample2.php | 2 + .../pages/Controls/Samples/TDataGrid/Sample6.page | 1 + .../pages/Controls/Samples/TDataList/Sample1.page | 10 +- .../pages/Controls/Samples/TDataList/Sample2.page | 12 +- .../pages/Controls/Samples/TExpression/Home.page | 6 - .../pages/Controls/Samples/TRepeater/Sample1.page | 20 +-- .../pages/Controls/Samples/TRepeater/Sample2.page | 8 +- .../pages/Controls/Samples/TRepeater/Sample3.page | 12 +- .../pages/Controls/Samples/TStatements/Home.page | 9 -- .../protected/pages/Controls/Statements.page | 19 +-- framework/Web/UI/TControl.php | 18 ++- framework/Web/UI/TTemplateManager.php | 166 +++++++++++++++++++-- framework/interfaces.php | 38 +++++ .../quickstart/Controls/DataGrid3TestCase.php | 8 +- .../quickstart/Controls/DataList2TestCase.php | 8 +- 20 files changed, 292 insertions(+), 110 deletions(-) diff --git a/HISTORY b/HISTORY index 3115e35f..b418a495 100644 --- a/HISTORY +++ b/HISTORY @@ -5,6 +5,8 @@ ENH: Format string in TDataGrid columns can now evaluate an expression (Qiang) Version 3.0RC2 April 16, 2006 ============================= BUG: Ticket#118 - Variables that may not have been initialized (Qiang) +CHG: Moved localize() into PradoBase (Qiang) +ENH: Optimized the representation and evaluation of template expressions (Qiang) Version 3.0RC1 April 5, 2006 ============================ diff --git a/UPGRADE b/UPGRADE index a811738d..391c55ff 100644 --- a/UPGRADE +++ b/UPGRADE @@ -1,6 +1,6 @@ - Upgrading Instructions for PRADO Framework v3.0RC1 - ================================================== + Upgrading Instructions for PRADO Framework v3.0.0 RC2 + ===================================================== !!!IMPORTANT!!! @@ -14,8 +14,14 @@ version B between A and C, you need to following the instructions for both A and B. -Upgrading from v3.0b --------------------- +Upgrading from v3.0.0 RC1 +------------------------- +- !!! The context of template expression/statements/databinding tags + is changed to the control owning the template. Previously, it was + the control representing the tag. + +Upgrading from v3.0.0 beta +-------------------------- - THttpSession.UseCustomStorage replaces the previous Storage. - Pagers in TDataGrid are now enclosed within panels. The event indicating their creation is changed to OnPagerCreated instead of OnItemCreated. @@ -27,8 +33,8 @@ Upgrading from v3.0b TLogger, TLogRouter, TDataFieldAccessor, TSimpleDateFormatter are moved to System.Util -Upgrading from v3.0a --------------------- +Upgrading from v3.0.0 alpha +--------------------------- All event names must start with 'On'. diff --git a/demos/quickstart/protected/pages/Configurations/Templates2.page b/demos/quickstart/protected/pages/Configurations/Templates2.page index f4f68b69..0971c828 100644 --- a/demos/quickstart/protected/pages/Configurations/Templates2.page +++ b/demos/quickstart/protected/pages/Configurations/Templates2.page @@ -10,52 +10,59 @@ Dynamic content tags are introduced as shortcuts to some commonly used

Expression Tags

-An expression tag represents a PHP expression that is evaluated when the template control is being rendered. The expression evaluation result is inserted at the place where the tag resides in the template. Its format is as follows, +An expression tag represents a PHP expression that is evaluated when the template control is being rendered. The expression evaluation result is inserted at the place where the tag resides in the template. The context (namely $this) of the expression is the control owning the template. +

+

+The format of an expression tag is as follows, +

<%= PhpExpression %> -Inernally, an expression tag is represented by a TExpression control. Therefore, in the expression $this refers to the TExpression control. For example, the following expression tag will display the current page title at the place, +

+For example, the following expression tag will display the current page title at the place, +

-<%= $this->Page->Title %> +<%= $this->Title %> -

Statement Tags

-Statement tags are similar to expression tags, except that statement tags contain PHP statements rather than expressions. The output of the PHP statements (using for example echo or print in PHP) are displayed at the place where the statement tag resides in the template. Inernally, a statement tag is represented by a TStatements control. Therefore, in the statements $this refers to the TStatements control. The format of statement tags is as follows, +Statement tags are similar to expression tags, except that statement tags contain PHP statements rather than expressions. The output of the PHP statements (using for example echo or print in PHP) are displayed at the place where the statement tag resides in the template. The context (namely $this) of the statements is the control owning the template. The format of statement tags is as follows, +

<%% PHP Statements %> -

The following example displays the current time in Dutch at the place, +

<%% setlocale(LC_ALL, 'nl_NL'); echo strftime("%A %e %B %Y",time()); %> -

Databind Tags

-Databind tags are similar to expression tags, except that the expressions are evaluated only when a dataBind() call is invoked on the controls representing the databind tags. Internally, a TLiteral control is used to represent a databind tag and $this in the expression would refer to the control. The format of databind tags is as follows, +Databind tags are similar to expression tags, except that the expressions are evaluated only when a dataBind() call is invoked on the controls representing the databind tags. The context (namely $this) of a databind expression is the control owning the template. The format of databind tags is as follows, +

<%# PhpExpression %> -

Parameter Tags

Parameter tags are used to insert application parameters at the place where they appear in the template. The format of parameter tags is as follows, +

<%$ ParameterName %> +

Note, application parameters are usually defined in application configurations or page directory configurations. The parameters are evaluated when the template is instantiated.

@@ -66,9 +73,11 @@ Asset tags are used to publish private files and display the corresponding the U

The format of asset tags is as follows, +

<%~ LocalFileName %> +

where LocalFileName refers to a file path that is relative to the directory containing the current template file. The file path can be a single file or a directory. If the latter, the content in the whole directory will be made accessible by end-users.

@@ -79,9 +88,12 @@ BE VERY CAUTIOUS when you are using asset tags as it may expose to end-users fil

Localization Tags

Localization tags represent localized texts. They are in the following format, +

<%[string]%> +

where string will be translated to different languages according to the end-user's language preference. +

\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Controls/Expression.page b/demos/quickstart/protected/pages/Controls/Expression.page index c87f0ba4..80a45a3a 100644 --- a/demos/quickstart/protected/pages/Controls/Expression.page +++ b/demos/quickstart/protected/pages/Controls/Expression.page @@ -4,23 +4,14 @@

-TExpression evaluates a PHP expression and displays the evaluation result. To specify the expression to be evaluated, set the Expression property. In a control template, expression tags are often used instead of the complete component tags when the main purpose is to display the evaluation result of some PHP expression. For example, the following two tags are equivalent, -

- -<com:TExpression Expression="date()" /> -<%= date() %> - - -

-TExpression evaluates the expression during the rendering control lifecycle. +TExpression evaluates a PHP expression and displays the evaluation result. To specify the expression to be evaluated, set the Expression property. Note, TExpression evaluates the expression during the rendering control lifecycle.

-The context of the expression in a TExpression control is the control itself. That is, $this represents the control object if it is present in the expression. For example, both of the following template tags will display the title of the page containing the TExpression control. +The context of the expression in a TExpression control is the control itself. That is, $this represents the control object if it is present in the expression. For example, the following template tag will display the title of the page containing the TExpression control.

<com:TExpression Expression="$this->Page->Title" /> -<%= $this->Page->Title %>

diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.page b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.page index 6de3063a..79c1890c 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.page @@ -42,7 +42,7 @@ Rating - + diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.php b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.php index d40e3be3..a49077b5 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.php +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample2.php @@ -78,6 +78,8 @@ class Sample2 extends TPage { foreach($this->DataGrid->Columns as $index=>$column) $column->Visible=$sender->Items[$index]->Selected; + $this->DataGrid->DataSource=$this->Data; + $this->DataGrid->dataBind(); } } diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample6.page b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample6.page index d2277bc5..3d1a33a8 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample6.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample6.page @@ -6,6 +6,7 @@

-Total <%# $this->Parent->Parent->ItemCount %> products. +Total <%# $this->Parent->ItemCount %> products.
@@ -36,10 +36,10 @@ Total <%# $this->Parent->Parent->ItemCount %> products. IDNameQuantityPrice - <%#$this->Parent->DataItem['id'] %> - <%#$this->Parent->DataItem['name'] %> - <%#$this->Parent->DataItem['quantity'] %> - $<%#$this->Parent->DataItem['price'] %> + <%#$this->DataItem['id'] %> + <%#$this->DataItem['name'] %> + <%#$this->DataItem['quantity'] %> + $<%#$this->DataItem['price'] %> diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.page b/demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.page index 07980c49..4b484b21 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.page @@ -29,7 +29,7 @@ Text=<%#$this->Parent->DataItem['id']%> CommandName="select" /> - <%#$this->Parent->DataItem['name']%> + <%#$this->DataItem['name']%> IDNameQuantityPrice - <%#$this->Parent->DataItem['id'] %> - <%#$this->Parent->DataItem['name'] %> - <%#$this->Parent->DataItem['quantity'] %> - $<%#$this->Parent->DataItem['price'] %> + <%#$this->DataItem['id'] %> + <%#$this->DataItem['name'] %> + <%#$this->DataItem['quantity'] %> + $<%#$this->DataItem['price'] %> @@ -77,7 +77,7 @@ - + diff --git a/demos/quickstart/protected/pages/Controls/Samples/TExpression/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TExpression/Home.page index 2273f3c1..8c736ca9 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TExpression/Home.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TExpression/Home.page @@ -10,12 +10,6 @@ Using expression component tag: - -
ID<%#$this->Parent->DataItem['id']%><%#$this->DataItem['id']%>
Name
-Using shortcut expression tag: - -<%= $this->Page->PagePath %> -
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample1.page b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample1.page index e28ef6fb..f519342d 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample1.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample1.page @@ -17,21 +17,21 @@ -<%#$this->Parent->DataItem['id']%> -<%#$this->Parent->DataItem['name']%> -<%#$this->Parent->DataItem['quantity']%> -<%#$this->Parent->DataItem['price']%> -<%#$this->Parent->DataItem['imported']?'Yes':'No'%> +<%#$this->DataItem['id']%> +<%#$this->DataItem['name']%> +<%#$this->DataItem['quantity']%> +<%#$this->DataItem['price']%> +<%#$this->DataItem['imported']?'Yes':'No'%> -<%#$this->Parent->DataItem['id']%> -<%#$this->Parent->DataItem['name']%> -<%#$this->Parent->DataItem['quantity']%> -<%#$this->Parent->DataItem['price']%> -<%#$this->Parent->DataItem['imported']?'Yes':'No'%> +<%#$this->DataItem['id']%> +<%#$this->DataItem['name']%> +<%#$this->DataItem['quantity']%> +<%#$this->DataItem['price']%> +<%#$this->DataItem['imported']?'Yes':'No'%> diff --git a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample2.page b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample2.page index b939c586..ce0942c3 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample2.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample2.page @@ -14,7 +14,7 @@ - <%#$this->NamingContainer->DataItem %> + <%#$this->DataItem %> - <%#$this->NamingContainer->DataItem['name'] %> + <%#$this->DataItem['name'] %> - <%#$this->NamingContainer->DataItem['age'] %> + <%#$this->DataItem['age'] %> - <%#$this->NamingContainer->DataItem['position'] %> + <%#$this->DataItem['position'] %> diff --git a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample3.page b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample3.page index fde06a36..38636962 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample3.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TRepeater/Sample3.page @@ -69,12 +69,12 @@ The following example allows users to modify the existing tabular data using a < - -<%#$this->Parent->DataItem['id']%> -<%#$this->Parent->DataItem['name']%> -<%#$this->Parent->DataItem['category']%> -<%#$this->Parent->DataItem['price']%> -<%#$this->Parent->DataItem['imported']?'Yes':'No'%> + +<%#$this->DataItem['id']%> +<%#$this->DataItem['name']%> +<%#$this->DataItem['category']%> +<%#$this->DataItem['price']%> +<%#$this->DataItem['imported']?'Yes':'No'%> diff --git a/demos/quickstart/protected/pages/Controls/Samples/TStatements/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TStatements/Home.page index 66734ce0..d07bf159 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TStatements/Home.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TStatements/Home.page @@ -15,15 +15,6 @@ Using TStatements component tag: - -Using shortcut statements tag: - -<%% - $uid=$this->UniqueID; - echo "UniqueID is '$uid'."; -%> - - \ No newline at end of file diff --git a/demos/quickstart/protected/pages/Controls/Statements.page b/demos/quickstart/protected/pages/Controls/Statements.page index c6807738..dd26ec1b 100644 --- a/demos/quickstart/protected/pages/Controls/Statements.page +++ b/demos/quickstart/protected/pages/Controls/Statements.page @@ -4,34 +4,31 @@

-TStatements evaluates a sequence of PHP statements and displays the content rendered by the statements. To specify the PHP statements to be evaluated, set the Statements property. In a control template, statement tags are often used instead of the complete component tags when the main purpose is to display the result rendered by some PHP statements. For example, the following two tags are equivalent, +TStatements evaluates a sequence of PHP statements and displays the content rendered by the statements. To specify the PHP statements to be evaluated, set the Statements property. For example, the following component tag displays the current time on the Web page,

<com:TStatements> - <prop:Expression> + <prop:Statements> setlocale(LC_ALL, 'nl_NL'); echo strftime("%A %e %B %Y",time()); - </prop:Expression> + </prop:Statements> </com:TStatements> - -<%% - setlocale(LC_ALL, 'nl_NL'); - echo strftime("%A %e %B %Y",time()); -%>

-TStatements evaluates the PHP statements during the rendering control lifecycle. Unlike TExpression, TStatements only displays the content 'echoed' within the statements. +Note, TStatements evaluates the PHP statements during the rendering control lifecycle. Unlike TExpression, TStatements only displays the content 'echoed' within the statements.

The context of the statements in a TStatements control is the control itself. That is, $this represents the control object if it is present in the statements. For example, the following statement tag will display the title of the page containing the TStatements control.

-<%% +<com:TStatements> + <prop:Statements> $page=$this->Page; echo $page->Title; -%> + </prop:Statements> +</com:TStatements>

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 diff --git a/framework/interfaces.php b/framework/interfaces.php index ca5c77bb..2a407696 100644 --- a/framework/interfaces.php +++ b/framework/interfaces.php @@ -242,4 +242,42 @@ interface ICacheDependency public function getHasChanged(); } +/** + * IRenderable interface. + * + * This interface must be implemented by classes that can be rendered + * to end-users. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System + * @since 3.0 + */ +interface IRenderable +{ + /** + * Renders the component to end-users. + * @param ITextWriter writer for the rendering purpose + */ + public function render($writer); +} + +/** + * IBindable interface. + * + * This interface must be implemented by classes that are capable of performing databinding. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System + * @since 3.0 + */ +interface IBindable +{ + /** + * Performs databinding. + */ + public function dataBind(); +} + ?> \ No newline at end of file diff --git a/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php b/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php index 095d455a..b92cc9f5 100644 --- a/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php +++ b/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php @@ -15,7 +15,7 @@ class DataGrid3TestCase extends SeleniumTestCase //$this->verifyElementPresent("//img[@src='images/star5.gif']",''); // edit the 2nd row - $this->clickAndWait("id=ctl0_body_DataGrid_ctl2_ctl9", ""); + $this->clickAndWait("id=ctl0_body_DataGrid_ctl2_ctl8", ""); $this->type("ctl0\$body\$DataGrid\$ctl2\$ctl7", "Design Pattern: Elements of Reusable Object-Oriented Software"); $this->type("ctl0\$body\$DataGrid\$ctl2\$ctl8", "Addison Wesley Professional"); $this->type("ctl0\$body\$DataGrid\$ctl2\$ctl9", "\$57.04"); @@ -32,18 +32,18 @@ class DataGrid3TestCase extends SeleniumTestCase //$this->verifyElementPresent("//img[@src='images/star1.gif']",''); // verify cancel editting the 3rd row - $this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl9", ""); + $this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl8", ""); $this->clickAndWait("link=Cancel", ""); $this->verifyTextPresent("Design Patterns Explained : A New Perspective on Object-Oriented Design", ""); // verify deleting - $this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl10", ""); + $this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl9", ""); $this->verifyConfirmation("Are you sure?"); $this->verifyTextNotPresent("Design Patterns Explained : A New Perspective on Object-Oriented Design", ""); $this->verifyTextPresent("Extreme Programming Explained : Embrace Change",''); $this->chooseCancelOnNextConfirmation(); - $this->click("id=ctl0_body_DataGrid_ctl5_ctl10", ""); + $this->click("id=ctl0_body_DataGrid_ctl6_ctl9", ""); $this->verifyConfirmation("Are you sure?"); $this->verifyTextPresent("Extreme Programming Explained : Embrace Change",''); } diff --git a/tests/FunctionalTests/quickstart/Controls/DataList2TestCase.php b/tests/FunctionalTests/quickstart/Controls/DataList2TestCase.php index e29aabc8..9b6e98d2 100644 --- a/tests/FunctionalTests/quickstart/Controls/DataList2TestCase.php +++ b/tests/FunctionalTests/quickstart/Controls/DataList2TestCase.php @@ -19,7 +19,7 @@ class DataList2TestCase extends SeleniumTestCase $this->verifyTextPresent("\$150", ""); // verify editting an item - $this->clickAndWait("id=ctl0_body_DataList_ctl5_ctl4", ""); + $this->clickAndWait("id=ctl0_body_DataList_ctl5_ctl0", ""); $this->type("ctl0\$body\$DataList\$ctl5\$ProductQuantity", "11"); $this->type("ctl0\$body\$DataList\$ctl5\$ProductPrice", "140.99"); $this->click("//input[@name='ctl0\$body\$DataList\$ctl5\$ProductImported' and @value='ctl0\$body\$DataList\$ctl5\$ProductImported']", ""); @@ -31,7 +31,7 @@ class DataList2TestCase extends SeleniumTestCase $this->verifyTextPresent("11", ""); // verify editting another item - $this->clickAndWait("id=ctl0_body_DataList_ctl3_ctl2", ""); + $this->clickAndWait("id=ctl0_body_DataList_ctl3_ctl1", ""); $this->type("ctl0\$body\$DataList\$ctl3\$ProductName", "Hard Drive"); $this->type("ctl0\$body\$DataList\$ctl3\$ProductQuantity", "23"); $this->click("//input[@name='ctl0\$body\$DataList\$ctl3\$ProductImported' and @value='ctl0\$body\$DataList\$ctl3\$ProductImported']", ""); @@ -43,10 +43,10 @@ class DataList2TestCase extends SeleniumTestCase $this->verifyTextPresent("Harddrive ", ""); // verify item deletion - $this->clickAndWait("id=ctl0_body_DataList_ctl3_ctl5", ""); + $this->clickAndWait("id=ctl0_body_DataList_ctl3_ctl1", ""); $this->verifyConfirmation("Are you sure?"); $this->chooseCancelOnNextConfirmation(); - $this->click("id=ctl0_body_DataList_ctl5_ctl3", ""); + $this->click("id=ctl0_body_DataList_ctl5_ctl2", ""); $this->verifyConfirmation("Are you sure?"); $this->verifyTextPresent("Motherboard ", ""); $this->verifyTextPresent("CPU ", ""); -- cgit v1.2.3