variable downgrading

This commit is contained in:
Paul Driver 2010-09-01 14:39:03 -05:00
parent 5765739a95
commit c89da43b58
5 changed files with 151 additions and 0 deletions

View file

@ -2,6 +2,9 @@
- fixed #11812: Checking www_ajaxSave's response in the cart js, urlencoding post parameters
- added: Link in the Admin Console to the Addons section on webgui.org
- added: Labels in the Shopping Cart addresses are optional.
- added: template variable downgrading so that using we can safely pass
template variables TT would understand to HTML::Template templates -- see
WebGUI::Asset::Template::Parser->downgrade for details.
7.9.13
- fixed #11783: Instances deleted during realtime run

View file

@ -54,6 +54,7 @@ sub process {
my $self = shift;
my $template = shift;
my $vars = $self->addSessionVars(shift);
$self->downgrade($vars);
my $t;
eval {
$t = HTML::Template->new(

View file

@ -81,6 +81,7 @@ sub process {
my $class = shift;
my $template = shift;
my $vars = $class->addSessionVars(shift);
$class->downgrade($vars);
my $t;
eval {
$t = HTML::Template::Expr->new(scalarref=>\$template,

View file

@ -16,6 +16,7 @@ package WebGUI::Asset::Template::Parser;
use strict;
use WebGUI::International;
use Scalar::Util qw(blessed);
#-------------------------------------------------------------------
@ -63,6 +64,49 @@ sub addSessionVars {
#-------------------------------------------------------------------
=head2 downgrade ( vars )
Removes or converts things HTML::Template-like engines can't handle. Coderefs
are removed, blessed objects are removed, and hashes are recursively flattened
by appending keys separated by dots (e.g. { foo => { bar => 'baz' } } becomes
{ 'foo.bar' => 'baz' }. Also, array elements that aren't hashes are converted
to hashes via { value => $bareValue }.
=cut
sub downgrade {
my ($self, $vars) = @_;
for my $k (keys %$vars) {
my $v = $vars->{$k};
if (blessed($v) || ref $v eq 'CODE') {
delete $vars->{$k};
}
elsif (ref $v eq 'ARRAY') {
for my $i (0..$#$v) {
if (ref $v->[$i] eq 'HASH') {
$self->downgrade($v->[$i]);
}
else {
my %hash = ( value => $v->[$i] );
$self->downgrade(\%hash);
$v->[$i] = \%hash;
}
}
}
elsif (ref $v eq 'HASH') {
delete $vars->{$k};
my %flatter;
for my $subkey (keys %$v) {
$flatter{"$k.$subkey"} = $v->{$subkey};
}
$self->downgrade(\%flatter);
@{$vars}{keys %flatter} = values %flatter;
}
}
}
#-------------------------------------------------------------------
=head2 new ( session )
Constructor.

102
t/Template/downgrade.t Normal file
View file

@ -0,0 +1,102 @@
use FindBin;
use strict;
use warnings;
use lib "$FindBin::Bin/../../lib";
use lib "$FindBin::Bin/../lib";
use Data::Dumper;
use Test::More;
use WebGUI::Test;
use WebGUI::Asset;
use WebGUI::Asset::Template::Parser;
my $funky_instance = bless {}, 'WebGUI::Asset::Template::Parser';
sub down_ok {
my ( $down, $expected, $msg ) = @_;
$funky_instance->downgrade($down);
is_deeply( $down, $expected, $msg )
or diag Dumper($down);
}
down_ok { foo => 'bar' }, { foo => 'bar' }, 'nonthreatening';
down_ok {
code => sub { }
},
{},
'code';
down_ok { obj => $funky_instance }, {}, 'object';
down_ok { hash => { foo => 'foo', bar => 'bar' } },
{ 'hash.foo' => 'foo', 'hash.bar' => 'bar' },
'simple hash flattening';
down_ok { array => [ 1, 2, 3 ] },
{ array => [ { value => 1 }, { value => 2 }, { value => 3 }, ] }, 'simple array flattening';
down_ok {
regular => 'simple',
hash => {
quite => 'deeply',
with => {
another => 'hashref',
and_even => [
'an', sub { }, { obj => $funky_instance },
'array',
[ 'nested', 'further', { son => '!!!' } ],
[ { oh => { wow => 'man' } } ]
],
blessme => $funky_instance,
}
}
}, {
regular => 'simple',
'hash.quite' => 'deeply',
'hash.with.another' => 'hashref',
'hash.with.and_even' => [
{ value => 'an' },
{}, {},
{ value => 'array' },
{ value => [ { value => 'nested' }, { value => 'further' }, { son => '!!!' }, ], },
{ value => [ { 'oh.wow' => 'man' } ] }
],
},
'twisted deep complex strucuture';
my $session = WebGUI::Test->session;
sub processed_ok {
my ( $parser, $template, $msg ) = @_;
my $temp = WebGUI::Asset->getTempspace($session);
my $tmpl = $temp->addChild( {
className => 'WebGUI::Asset::Template',
parser => $parser,
template => $template,
}
);
addToCleanup($tmpl);
is( $tmpl->process( {
his => { yes => 'yes', stop => 'stop' },
my => { yes => 'no', stop => 'go' }
}
),
<<'END_EXPECTED', $msg );
You say yes, I say no.
You say stop, and I say go.
END_EXPECTED
} ## end sub processed_ok
processed_ok( 'WebGUI::Asset::Template::HTMLTemplate', <<'END_HT', 'HTML::Template' );
You say <tmpl_var his.yes>, I say <tmpl_var my.yes>.
You say <tmpl_var his.stop>, and I say <tmpl_var my.stop>.
END_HT
processed_ok( 'WebGUI::Asset::Template::HTMLTemplateExpr', <<'END_HTE', 'HTML::Template::Expr' );
You say <tmpl_var his_yes>, I say <tmpl_var my_yes>.
You say <tmpl_var his_stop>, and I say <tmpl_var my_stop>.
END_HTE
done_testing;
#vim:ft=perl