Skip Menu |

This queue is for tickets about the HTML-Template CPAN distribution.

Report information
The Basics
Id: 46285
Status: resolved
Priority: 0/
Queue: HTML-Template

People
Owner: Nobody in particular
Requestors: justin [...] devuyst.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 2.9
Fixed in: (no value)



Subject: Lazy loop variables and loop variables as boolean
This ticket covers two issues because the patch covers both. This patch has been in production for a few months now with no known issues. 1. HTML::Template currently handles lazy evaluating of scalar variables. We had a need to do this for loop variables. Because we have many many conditionals this helped reduce our computational load by about half. 2. Because of the way variable typing is currently done its impossible to use a loop variable in a boolean context only. I fixed this is the least amount of code I could come up with. Again, since we (ab)use conditionals so extensively this is a bug we ran into a fair amount of the time. This is similar to RT #32683. I have tests if You would like them. I am also willing to rework the patch if desired. Let me know. Thanks, jdv
Subject: template_jdv.patch
--- Template.pm.2.9 2009-05-21 13:10:38.000000000 -0400 +++ Template.pm.new 2009-05-21 13:15:13.000000000 -0400 @@ -980,6 +980,7 @@ no_includes => 0, case_sensitive => 0, filter => [], + type_guess_prefix => '_%c^s#z&_:_', ); # load in options supplied to new() @@ -1636,6 +1637,7 @@ $template->{options}{die_on_bad_params} = $options->{die_on_bad_params}; $template->{options}{case_sensitive} = $options->{case_sensitive}; $template->{options}{parent_global_vars} = $options->{parent_global_vars}; + $template->{options}{type_guess_prefix} = $options->{type_guess_prefix}; push(@pstacks, $template->{parse_stack}); } @@ -2120,6 +2122,12 @@ $top_pmap{$var} = HTML::Template::VAR->new() if $options->{global_vars} and not exists $top_pmap{$var}; $uc->[HTML::Template::COND::VARIABLE] = $pmap{$var}; + if ( $options->{type_guess_prefix} && $var !~ /^__expr/ ) { + $pmap{ $options->{type_guess_prefix} . $var } + = HTML::Template::VAR->new(); + $top_pmap{ $options->{type_guess_prefix} . $var } + = HTML::Template::VAR->new(); + } } if (ref($pmap{$var}) eq 'HTML::Template::VAR') { $uc->[HTML::Template::COND::VARIABLE_TYPE] = HTML::Template::COND::VARIABLE_TYPE_VAR; @@ -2154,7 +2162,8 @@ loop_context_vars => $options->{loop_context_vars}, case_sensitive => $options->{case_sensitive}, force_untaint => $options->{force_untaint}, - parent_global_vars => ($options->{global_vars} || $options->{parent_global_vars} || 0) + parent_global_vars => ($options->{global_vars} || $options->{parent_global_vars} || 0), + type_guess_prefix => $options->{type_guess_prefix}, ); } elsif ($which eq 'TMPL_IF' or $which eq 'TMPL_UNLESS' ) { @@ -2361,6 +2370,12 @@ $top_pmap{$var} = HTML::Template::VAR->new() if $options->{global_vars} and not exists $top_pmap{$var}; $uc->[HTML::Template::COND::VARIABLE] = $pmap{$var}; + if ( $options->{type_guess_prefix} && $var !~ /^__expr/ ) { + $pmap{ $options->{type_guess_prefix} . $var } + = HTML::Template::VAR->new(); + $top_pmap{ $options->{type_guess_prefix} . $var } + = HTML::Template::VAR->new(); + } } if (ref($pmap{$var}) eq 'HTML::Template::VAR') { $uc->[HTML::Template::COND::VARIABLE_TYPE] = HTML::Template::COND::VARIABLE_TYPE_VAR; @@ -2517,6 +2532,12 @@ return ${$param_map->{$param}} if (ref($param_map->{$param}) eq 'HTML::Template::VAR'); + + my $param_set = $param_map->{$param}[HTML::Template::LOOP::PARAM_SET]; + if ( ref $param_set->[ 0 ] eq 'CODE' ) { + @{ $param_set } = @{ $param_set->[ 0 ]->( $self, ) }; + } + return $param_map->{$param}[HTML::Template::LOOP::PARAM_SET]; } @@ -2561,6 +2582,13 @@ # objects that are compatible underneath. my $value_type = ref($value); if (defined($value_type) and length($value_type) and ($value_type eq 'ARRAY' or ((ref($value) !~ /^(CODE)|(HASH)|(SCALAR)$/) and $value->isa('ARRAY')))) { + + if ( $options->{type_guess_prefix} ) { + if ( delete $param_map->{ $options->{type_guess_prefix} . $param } ) { + $param_map->{$param} = HTML::Template::LOOP->new; + } + } + (ref($param_map->{$param}) eq 'HTML::Template::LOOP') or croak("HTML::Template::param() : attempt to set parameter '$param' with an array ref - parameter is not a TMPL_LOOP!"); $param_map->{$param}[HTML::Template::LOOP::PARAM_SET] = [@{$value}]; @@ -2741,9 +2769,15 @@ } } } else { - $x = $line->[HTML::Template::COND::JUMP_ADDRESS] if - (defined $line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET] and - scalar @{$line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET]}); + my $param_set + = $line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET]; + if ( defined $param_set ) { + if ( ref $param_set->[ 0 ] eq 'CODE' ) { + @{ $param_set } = @{ $param_set->[ 0 ]->( $self, ) }; + } + $x = $line->[HTML::Template::COND::JUMP_ADDRESS] + if scalar @{ $param_set }; + } } } else { if ($line->[HTML::Template::COND::VARIABLE_TYPE] == HTML::Template::COND::VARIABLE_TYPE_VAR) { @@ -2757,9 +2791,18 @@ $x = $line->[HTML::Template::COND::JUMP_ADDRESS]; } } else { - $x = $line->[HTML::Template::COND::JUMP_ADDRESS] if - (not defined $line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET] or - not scalar @{$line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET]}); + my $param_set + = $line->[HTML::Template::COND::VARIABLE][HTML::Template::LOOP::PARAM_SET]; + if ( defined $param_set ) { + if ( ref $param_set->[ 0 ] eq 'CODE' ) { + @{ $param_set } = @{ $param_set->[ 0 ]->( $self, ) }; + } + $x = $line->[HTML::Template::COND::JUMP_ADDRESS] + unless scalar @{ $param_set }; + } + else { + $x = $line->[HTML::Template::COND::JUMP_ADDRESS]; + } } } } @@ -3049,7 +3092,11 @@ my $template = $self->[TEMPLATE_HASH]{$index}; my $value_sets_array = $self->[PARAM_SET]; return unless defined($value_sets_array); - + + if ( ref $value_sets_array->[ 0 ] eq 'CODE' ) { + @{ $value_sets_array } = @{ $value_sets_array->[ 0 ]->( $template, ) }; + } + my $result = ''; my $count = 0; my $odd = 0;
On Thu May 21 13:29:10 2009, justin@devuyst.com wrote: Show quoted text
> 1. HTML::Template currently handles lazy evaluating of > scalar variables. We had a need to do this for loop variables. > Because we have many many conditionals this helped reduce > our computational load by about half.
Great idea. Show quoted text
> 2. Because of the way variable typing is currently done its > impossible to use a loop variable in a boolean context only. > I fixed this is the least amount of code I could come up with. > Again, since we (ab)use conditionals so extensively this is a > bug we ran into a fair amount of the time. This is similar to > RT #32683.
As I mentioned for ticket #32683, I don't think this is a feature we'll be adding anytime soon. And you're patch makes behavior dependent on variable naming (even if that naming pattern is configurable) which is quite a departure from any other HTML::Template feature. If you want something to be a loop in the code but not a loop in the template, I'm not sure there's a good way to do that. And like I mentioned in #32683 you don't actually need anything in your TMPL_LOOP to let HTML::Template know it's actually a loop: <tmpl_loop foo></tmpl_loop> <tmpl_if foo> ... </tmpl_if>
I've added support for lazy tmpl_loops (coderefs that return array references) and this will appear in the upcoming 2.10 version.