[Templates] further headway on caching Service objects
Randal L. Schwartz
merlyn@stonehenge.com
03 Jul 2001 11:48:59 -0700
OK, I've decided that the only thing I'm gonna read from the .htaccess
is a keyword to describe a "service set", then I can do the mapping
for that in the handler. And this is working fine. I've put my
handler-in-progress now at the end of this message.
But now the next weirdness, that I spent another hour or two trying to
figure out how to fix or work around. Templates are only disk-cached
if they are found via the INCLUDE_PATH mechanism. That means that the
top-level documnet, which we find using ABSOLUTE => 1, is never
disk-cached! I would think that that's the one you definitely want
cached as well, since that's your first entry in.
Andy - was that a conscious decision, or a todo to fix? I stared at
the code for a little while trying to figure out how dangerous adding
_compile($template, $compiled) or whatever it was to the absolute
finder would mess up.
I think I'm starting to get my head around this. I'm making cool
little splash-widgets already. One of my favorite things to do
is to have a menu with links but have the "current position" be
unlinked and bolded automatically. Here's what I came up with:
[% INCLUDE splash_tabset_uri
tabs = [
{ link => '/', text => 'Home' },
{ link => '/merlyn/', text => 'Randal' },
{ link => '/pic/TT/', text => 'testing ground' }
]
%]
where splash_tabset_uri is
[%-
my_uri = r.uri;
my_uri = my_uri.replace('/index.html$', '/');
FOREACH tab = tabs;
IF tab.link == my_uri;
select = loop.count;
tab.link = '';
END;
END;
INCLUDE splash/tabset;
-%]
Note the call to r.uri to get my current place. This automatically
figures out which link points to "here" and unlinks and selects it!
The only downside is that the links have to be absolute in the map,
but I'm starting to think about how to have them relative but patched
up by the handler.
Andy, this stuff rocks.
Anyway, here's my work-in-progress PerlHandler ...
#!/usr/bin/perl -w
package Stonehenge::Template;
use strict;
use Template;
use Apache::Constants qw( :common );
use vars qw( $VERSION );
my $SERVICE_MODULE = 'Stonehenge::Template::Service';
my $PROVIDER_MODULE = 'Stonehenge::Template::Provider';
my $DIRNAME;
my %SERVICES = # key must be initial-capped
(
Normal =>
{
INCLUDE_PATH => '/home/merlyn/lib/Apache/TT/Template',
COMPILE_DIR => '/home/merlyn/lib/Apache/TT/Cache',
},
Splash =>
{
INCLUDE_PATH => [
'/home/merlyn/lib/Apache/TT/Template',
Template::Config->instdir('templates'),
],
COMPILE_DIR => '/home/merlyn/lib/Apache/TT/Cache',
PROCESS => 'splashprocess',
POST_CHOMP => 1,
},
);
my %SERVICE_CACHE;
my %ROOT_PROVIDER_CACHE;
sub handler {
use Stonehenge::Reload; goto &handler if Stonehenge::Reload->reload_me;
my $r = shift;
## safety check
$r->warn("trying ", $r->filename);
return DECLINED unless
$r->content_type
and $r->content_type eq "text/html"
and not $r->uri =~ m{^/CPAN}
and -f $r->filename;
my $service = $r->dir_config("TT_SERVICE");
return DECLINED unless defined $service and length $service;
$service = "\u\L$service";
return DECLINED unless my $cfg = $SERVICES{$service};
$r->warn("start processing with Stonehenge::Template $service");
my $SERVICE = $SERVICE_CACHE{$service} ||= do {
my $module = $cfg->{ SERVICE_MODULE } || $SERVICE_MODULE;
$module->new($cfg) || do {
$r->log_reason($module->error, $r->filename);
return SERVER_ERROR;
};
};
my $ROOT_PROVIDER = $ROOT_PROVIDER_CACHE{$service} ||= do {
my $module = $cfg->{ PROVIDER_MODULE } || $PROVIDER_MODULE;
$module->new({%$cfg, ABSOLUTE => 1}) || do {
$r->log_reason($module->error, $r->filename);
return SERVER_ERROR;
};
};
$r->warn("Stonehenge::Template: after setting SERVICE");
my $params =
{
r => $r,
};
$r->chdir_file;
my ($template) = eval {
$ROOT_PROVIDER->fetch($r->filename);
};
unless ($template) {
$r->log_reason($ROOT_PROVIDER->error, $r->filename);
return SERVER_ERROR;
}
$r->warn("Stonehenge::Template: after getting template");
my $content = $SERVICE->process($template, $params);
unless (defined $content) {
$r->log_reason($SERVICE->error, $r->filename);
return SERVER_ERROR;
}
$r->warn("Stonehenge::Template: after processing content");
$r->send_http_header;
$r->print(\$content);
$r->warn("end processing with Stonehenge::Template");
return OK;
}
BEGIN {
package Stonehenge::Template::Service;
use base qw(Template::Service);
}
BEGIN {
package Stonehenge::Template::Provider;
use base qw(Template::Provider);
}
1;
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!