[cgiapp] proposal for new cgiapp hook: loaded_html_tmpl
Michael Graham
magog at the-wire.com
Tue Oct 27 10:28:21 EDT 2009
Hi Mark!
> How would your propose to deal with the "HTML::Template-like" modules
> that do not pass the "isa HTML::Template" test but are generally
> compatible?
>
> Could we test for the features we need instead of the classes they
> come from?
Right, of course - that makes much more sense. Maybe we could use
'$class->can("query")' instead of '$class->isa("HTML::Template")'.
I'm thinking that each plugin that wanted to pass template parameters
would do something like this:
## hooked via load_tmpl
sub my_load_tmpl_callback {
my ($c, $ht_params, $tmpl_params, $tmpl_file) = @_;
my $template_class = $c->html_tmpl_class;
eval "require $template_class;";
# for HTML::Template and compatible templating
# systems, don't add params here, add them in
# the loaded_html_template callback instead
# detect HTML::Template - compatibility by presence
# of a 'query' method
return if eval { $template_class->can('query') };
$tmpl_params->{'my_param'} = 'some_value';
}
## hooked via loaded_html_tmpl
sub my_html_template_loaded_callback {
my ($c, $ht_params, $tmpl_params, $tmpl_file, $tmpl_obj) = @_;
my $template_class = $c->html_tmpl_class;
eval "require $template_class;";
# skip if not HTML::Template or compatible,
# because we should have already added params under
# the load_tmpl callback
# detect HTML::Template - compatibility by presence
# of a 'query' method
return unless eval { $template_class->can('query') };
if (!exists $ht_params->{'die_on_bad_params'}
or $ht_params->{'die_on_bad_params'}) {
return unless $tmpl_obj->query(
name => 'my_param',
);
}
$tmpl_obj->param('my_param' => 'some_value');
}
Problems I see with this approach:
1) html_tmpl_class being used contrary to its original purpose.
Returning 'Petal' or 'Template' or 'Template::Toolkit' from this
attribute seems weird, since it's named 'html_tmpl...' and none
of these other templating systems are related to HTML::Template
at all. Maybe this isn't a big deal.
At the very least, to support a mix of templating systems,
plugins like CAP::TT and CAP::AnyTemplate should probably only
set this attribute for the duration of the 'load_tmpl' hook, e.g.
my $saved_class = $c->html_tmpl_class;
$c->html_tmpl_class('Template');
$self->call_hook('load_tmpl', ... );
$c->html_tmpl_class($saved_class);
2) What happens if another templating system provides a 'query'
method that does something completely different from what
HTML::Template's 'query' does?
3) Plugin code complexity. While this approach does reduce the code
that plugins have to include, it's still a lot of code to write
(and test) just to add a template parameter. It's also pretty
tricky and fragile for a standard API. Maybe it could be wrapped
up into its own "CAP::AddTemplateParams" plugin with a simpler
API?
A plugin that wanted to add template parameters would do
something like this:
use CGI::Application::Plugin::AddTemplateParams;
sub import {
my $caller = scalar(caller);
if ($caller->can('add_callback')) {
$caller->add_callback(
'add_template_params' => \&_add_tmpl_parms
);
}
}
## hooked via add_template_params
sub _add_tmpl_parms {
my ($c, $tmpl_params) = @_;
$tmpl_params->{'my_param'} = 'some_value';
}
Michael
--
Michael Graham <magog at the-wire.com>
More information about the cgiapp
mailing list