Hi, I added the solutions mentioned in the previous mails to the proposal. Here are the new solutions and a new evaluation. Please, check if it is correct.
The "context" proposal is not included. Frederik or Kore can you give me an example? Please, keep in mind that the word "context" may be confusing because we use that to set the target output to: HTML or text. Attached is the proposal. ===== Solution 6: Struct like variable passed on ------------------------------------------ The variables send to the first template can be packed in one structure. For example the user application sends: $t = new ezcTemplate(); $t->send->structure = new ezcTemplateVariableCollection(); $t->send->structure->a = 1; $t->send->structure->b = 2; $t->process("p"); Template p and q are: Template p: {use $structure} {include "q" send $structure} Template q: {use $structure} {$structure->a} {$structure->b} Solution 7: Provide a variable with all send variables ------------------------------------------------------ Almost the same as solution 6, but a struct like variable with all 'send' variables is provided by default. User application: $t = new ezcTemplate(); $t->send->a = 1; $t->send->b = 2; $t->process("p"); Template p: {use $send, $a} {$a} {include "q" send $send} Template q: {use $send} {$send->a} {$send->b} It can also be that the $send variable is always available for all templates. The templates would be: Template p: {use $a} {$a} {include "q"} Template q: {use $send} {$send->a} {$send->b} Solution 8: Add a function that can retrieve send variables ----------------------------------------------------------- A function, possibly a custom function, can retrieve all 'send' variables: User application: $t = new ezcTemplate(); $t->send->a = 1; $t->send->b = 2; $t->process("p"); Template p: {use $a} {$a} {include "q"} Template q: {var $send = getSendVariables()} {$send->a} {$send->b} Or: {var $b = getSendVariable("b")} {$b} Evaluation ---------- Many solutions share the same concept. Therefor we categorized the solutions in three groups: - Group 1: Solution 1, 2 and 3. - Group 2: Solution 4 and 5. - Group 3: Solution 6, 7 and 8. Group 1 changes the behavior of the {include} statement. The changed behavior results that the original send variables are passed along without specifying those variables explicitly. Group 2 adds a keyword to the included template so that more variables are available. Group 3 packs all the original send variables in a group (object). Advantages and disadvantages for group 1: + Easy to write a (single) template. No knowledge is needed where variables are made available. {use} specifies only which variables are used inside the template. + Easy to change in the template code. + Easy to see which variables are used in the template (and are declared externally). - Once a template is written, it may be difficult to 'backtrack' a variable to it's declaration. Keep in mind that when 'template overrides' are used, this task is difficult without extra runtime information. Advantages and disadvantages for group 2: + Easy to see if a variable comes from the user application or from the calling template. + Easy to see which variables are used in the template (and are declared externally). - Makes templates less generic. Multi-purpose templates may be called from anywhere. - May be harder to write the template when it's unknown where previous templates declare their variables. - It is not possible to specify a variable that comes from the user application unless it's (modified and) sent by the previous template. (Making this work would undo the 'easy backtracking' advantage.) Advantages and disadvantages for group 3: + Some variants are possible to implement without changing the template engine or are already available. Send-use structure is the same. + Easy to see if a variable comes from the user application or from the calling template. - Hard to see which variables are actually used. (The group is only available in the {use} block.) Also checking if a variable is set, has to be done manually. - Extra code in the templates itself is needed to retrieve a variable from the top scope. - Makes templates less generic. Multi-purpose templates may be called from anywhere.
Problem ------- In a system with lots of nested templates or template overrides the amount of variables that need to be forwarded to each template may grow out of proportion. The following example uses three templates: p, q, and r that forward all variables via includes to the underlying template: Template p: {use $a, $b, $c, $d, $e, $f} {include "q" send $a, $b, $c, $d, $e, $f} Template q: {use $a, $b, $c, $d, $e, $f} Show a: {$a} {include "r" send $b, $c, $d, $e, $f} Template r: {use $b, $c, $d, $e, $f} Show all variables: {$b}, {$c}, {$d}, {$e}, {$f} The user application sends all external variables: $t = new ezcTemplate(); $t->send->a = 1, $t->send->b = 2, ... $t->send->f = 6, $t->process("p"); In this example, we nested the templates three deep. In real applications (eZ publish scale) this nesting will be deeper. Another technique some applications use are template overrides. Basically, a template override decides dynamically what template to include and execute. An {if} block will be used in this document to simulate a in general much complexer override system: {use $load_p, $a, $b, $c, $d, $e, $f} {if $load_p} {include "p" send $a, $b, $c} {else} {include "q" send $d, $e, $f} {/if} The use-variables: a, b, c, d, e, and f are never used inside the template, but only forwarded. Solution 1: ezcTemplateConfiguration option ------------------------------------------- An option in the ezcTemplateConfiguration changes the behavior of the {include} statements. The {include} statement will then forward all the variables that it got from the user application by default. The modified example will be: Template p: {include "q"} Template q: {use $a} Show a: {$a} {include "r"} Template r: {use $b, $c, $d, $e, $f} Show all variables: {$b}, {$c}, {$d}, {$e}, {$f} The user application remains the same: $t = new ezcTemplate(); $t->send->a = 1, $t->send->b = 2, ... $t->send->f = 6, $t->process("p"); The {use} block specifies which variables are used directly in that template. Where the variables come from is not important. Solution 2: Add a keyword to include ------------------------------------ Same as solution 1, but instead of adding a configuration a special keyword is added to the include. This triggers the new behavior. For example: {include "q" with_externals} or: {var $local_var = 2} {include "q" with_externals send $local_var} Solution 3: Add a block simular to include ------------------------------------------ Same as solution 1, but then add a new block to ezcTemplate that works simular to include. For example: {extern "q"} Solution 4: Globals ------------------- Variables used in the template, coming directly the user application are specified via the {global} keyword. For example: Template p: {var $local_var = 2} {include "q" send $local_var} Template q: {global $a} {use $local_var} Show a: {$a} {include "r" send $local_var} Template r: {global $b, $c, $d, $e, $f} {use $local_var} Show all variables: {$b}, {$c}, {$d}, {$e}, {$f} The user application remains the same: $t = new ezcTemplate(); $t->send->a = 1, $t->send->b = 2, ... $t->send->f = 6, $t->process("p"); It is more verbose where a variable comes from. It may be more difficult to write the template, because the origin of the variable may not always be known. Solution 5: Add external keyword to {use} ----------------------------------------- This solution adds an external keyword to the {use}, so that it could be used like: Template p: {var $local_var = 2} {include "q" send $local_var} Template q: {use $local_var, external $a} Show a: {$a} {include "r" send $local_var} Template r: {use $local_var, external $b, external $c, external $d, external $e, external $f} Show all variables: {$b}, {$c}, {$d}, {$e}, {$f} The user application remains the same: $t = new ezcTemplate(); $t->send->a = 1, $t->send->b = 2, ... $t->send->f = 6, $t->process("p"); Solution 6: Struct like variable passed on ------------------------------------------ The variables send to the first template can be packed in one structure. For example the user application sends: $t = new ezcTemplate(); $t->send->structure = new ezcTemplateVariableCollection(); $t->send->structure->a = 1; $t->send->structure->b = 2; $t->process("p"); Template p and q are: Template p: {use $structure} {include "q" send $structure} Template q: {use $structure} {$structure->a} {$structure->b} Solution 7: Provide a variable with all send variables ------------------------------------------------------ Almost the same as solution 6, but a struct like variable with all 'send' variables is provided by default. User application: $t = new ezcTemplate(); $t->send->a = 1; $t->send->b = 2; $t->process("p"); Template p: {use $send, $a} {$a} {include "q" send $send} Template q: {use $send} {$send->a} {$send->b} It can also be that the $send variable is always available for all templates. The templates would be: Template p: {use $a} {$a} {include "q"} Template q: {use $send} {$send->a} {$send->b} Solution 8: Add a function that can retrieve send variables ----------------------------------------------------------- A function, possibly a custom function, can retrieve all 'send' variables: User application: $t = new ezcTemplate(); $t->send->a = 1; $t->send->b = 2; $t->process("p"); Template p: {use $a} {$a} {include "q"} Template q: {var $send = getSendVariables()} {$send->a} {$send->b} Or: {var $b = getSendVariable("b")} {$b} Evaluation ---------- Many solutions share the same concept. Therefor we categorized the solutions in three groups: - Group 1: Solution 1, 2 and 3. - Group 2: Solution 4 and 5. - Group 3: Solution 6, 7 and 8. Group 1 changes the behavior of the {include} statement. The changed behavior results that the original send variables are passed along without specifying those variables explicitly. Group 2 adds a keyword to the included template so that more variables are available. Group 3 packs all the original send variables in a group (object). Advantages and disadvantages for group 1: + Easy to write a (single) template. No knowledge is needed where variables are made available. {use} specifies only which variables are used inside the template. + Easy to change in the template code. + Easy to see which variables are used in the template (and are declared externally). - Once a template is written, it may be difficult to 'backtrack' a variable to it's declaration. Keep in mind that when 'template overrides' are used, this task is difficult without extra runtime information. Advantages and disadvantages for group 2: + Easy to see if a variable comes from the user application or from the calling template. + Easy to see which variables are used in the template (and are declared externally). - Makes templates less generic. Multi-purpose templates may be called from anywhere. - May be harder to write the template when it's unknown where previous templates declare their variables. - It is not possible to specify a variable that comes from the user application unless it's (modified and) sent by the previous template. (Making this work would undo the 'easy backtracking' advantage.) Advantages and disadvantages for group 3: + Some variants are possible to implement without changing the template engine or are already available. Send-use structure is the same. + Easy to see if a variable comes from the user application or from the calling template. - Hard to see which variables are actually used. (The group is only available in the {use} block.) Also checking if a variable is set, has to be done manually. - Extra code in the templates itself is needed to retrieve a variable from the top scope. - Makes templates less generic. Multi-purpose templates may be called from anywhere.
-- Components mailing list Components@lists.ez.no http://lists.ez.no/mailman/listinfo/components