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;