package Uttu::Handler::template; # # comments in this file assume you have read the documentation (Uttu.pod) # use Apache::Constants qw: SERVER_ERROR OK :; use AppConfig qw- :argcount -; use Data::Dumper; use IO::File; use Template; use Template::Service::Apache; use Uttu::Tools (); use strict; use warnings; use vars qw{ $REVISION $SERVICE_MODULE}; $REVISION = sprintf("%d.%d", q$Id: template.pm,v 1.6 2003/03/12 06:31:52 jgsmith Exp $ =~ m{(\d+).(\d+)}); $SERVICE_MODULE = 'Template::Service::Apache' unless defined $SERVICE_MODULE; ### ### [template] config variables ### { my $doing_config = 0; sub _setting_path { my($self, $variable, $value) = @_; return 1 if $doing_config; $doing_config = 1; $self -> set($variable, Apache -> server_root_relative($value)); $doing_config = 0; return 1; } sub _expand_string { my($self, $variable, $value) = @_; return 1 if $doing_config; $doing_config = 1; $value =~ s{\|}{\\\|}g; $self -> set($variable, eval qq:qq|$value|:); $doing_config = 0; return 1; } } sub init { my $self = shift; my $class = ref $self || $self; Uttu -> define( template_include_path => { ARGCOUNT => ARGCOUNT_LIST, }, template_pre_process => { ARGCOUNT => ARGCOUNT_LIST, }, template_interpolate => { ARGCOUNT => ARGCOUNT_NONE, }, template_post_chomp => { ARGCOUNT => ARGCOUNT_NONE, }, template_eval_perl => { ARGCOUNT => ARGCOUNT_NONE, }, template_start_tag => { ARGCOUNT => ARGCOUNT_ONE, }, template_end_tag => { ARGCOUNT => ARGCOUNT_ONE, }, template_tag_style => { ARGCOUNT => ARGCOUNT_ONE, }, template_pre_chomp => { ARGCOUNT => ARGCOUNT_NONE, }, template_process => { }, template_trim => { ARGCOUNT => ARGCOUNT_NONE, }, template_anycase => { ARGCOUNT => ARGCOUNT_NONE, }, template_delimiter => { ARGCOUNT => ARGCOUNT_ONE, }, template_absolute => { ARGCOUNT => ARGCOUNT_NONE, }, template_relative => { ARGCOUNT => ARGCOUNT_NONE, }, template_default => { ARGCOUNT => ARGCOUNT_ONE, }, template_block => { ARGCOUNT => ARGCOUNT_HASH, }, template_auto_reset => { ARGCOUNT => ARGCOUNT_NONE, }, template_recursion => { ARGCOUNT => ARGCOUNT_NONE, }, template_pre_define => { ARGCOUNT => ARGCOUNT_HASH, }, template_post_process => { ARGCOUNT => ARGCOUNT_LIST, }, template_error => { ARGCOUNT => ARGCOUNT_LIST, }, template_debug => { ARGCOUNT => ARGCOUNT_NONE, }, template_cache_size => { ARGCOUNT => ARGCOUNT_ONE, VALIDATE => q"^\d+$", }, template_compile_ext => { ARGCOUNT => ARGCOUNT_ONE, }, template_compile_dir => { ARGCOUNT => ARGCOUNT_ONE, ACTION => \&_include_file, }, template_plugin => { ARGCOUNT => ARGCOUNT_HASH, }, template_plugin_base => { ARGCOUNT => ARGCOUNT_LIST, }, template_load_perl => { ARGCOUNT => ARGCOUNT_NONE, }, template_filter => { ARGCOUNT => ARGCOUNT_HASH, }, template_v1dollar => { ARGCOUNT => ARGCOUNT_NONE, }, template_load_template => { ARGCOUNT => ARGCOUNT_LIST, }, template_load_plugin => { ARGCOUNT => ARGCOUNT_LIST, }, template_load_filter => { ARGCOUNT => ARGCOUNT_LIST, }, template_tolerant => { ARGCOUNT => ARGCOUNT_NONE, }, ); 1; } sub file_to_path { my($self, $prefix, $path) = @_; return $self ->{_lookup_cache} -> {$path} if $self ->{_lookup_cache} -> {$path}; my $roots = $self->{_template_include_path}; if(UNIVERSAL::isa($roots, "ARRAY")) { foreach my $r (@{$roots}) { my $f = $r ."/". $prefix ."/". $path; return $self ->{_lookup_cache} -> {$path} = $f if -f $f or -d _; } } else { my $f = $roots ."/". $prefix . "/" . $path; return $self ->{_lookup_cache} -> {$path} = $f if -f $f or -d _; } } sub handle_request { my($self, $u, $r) = @_; my $ttconfig = $self -> ttconfig; return SERVER_ERROR unless $ttconfig; # following copied from/based on Template::Service::Apache revision 1.2 my $SERVICE ||= do { $ttconfig = { %$ttconfig }; # instantiate new service module my $module = $ttconfig->{ SERVICE_MODULE } || $SERVICE_MODULE; (eval "require $module" && $module->new($ttconfig)) || do { $r->log_reason($module->error(), $r->filename()); return SERVER_ERROR; }; }; my $template = $SERVICE->template($r); return $template unless ref $template; my $params = $SERVICE->params($r); return $params unless ref $params; @{$params}{qw(u r)} = ($u, $r); $params -> {lh} = $u -> lh if $u -> config -> global_internationalization; my $content = $SERVICE->process($template, $params); unless (defined $content) { $r->log_reason($SERVICE->error(), $r->filename()); return SERVER_ERROR; } $SERVICE->headers($r, $template, \$content); $r->print($content); return OK; } sub shandle_request { my($self, $u, $r) = @_; my $ttconfig = $self -> ttconfig; return SERVER_ERROR unless $ttconfig; # following copied from/based on Template::Service::Apache revision 1.2 my $SERVICE ||= do { $ttconfig = { %$ttconfig }; # instantiate new service module my $module = $ttconfig->{ SERVICE_MODULE } || $SERVICE_MODULE; (eval "require $module" && $module->new($ttconfig)) || do { $r->log_reason($module->error(), $r->filename()); die SERVER_ERROR; }; }; my $template = $SERVICE->template($r); die $template unless ref $template; my $params = $SERVICE->params($r); die $params unless ref $params; @{$params}{qw(u r)} = ($u, $r); $params -> {lh} = $u -> lh if $u -> config -> global_internationalization; my $content = $SERVICE->process($template, $params); unless (defined $content) { $r->log_reason($SERVICE->error(), $r->filename()); die SERVER_ERROR; } $SERVICE->headers($r, $template, \$content); return \$content; } sub fail { my($self, $r, $status, $message) = @_; $r -> log_reason($message, $r -> filename); return $status; } ### ### Configuration support routines ### sub set_ttconfig { $_[0] ->{ttconfig} = $_[1] } sub ttconfig { $_[0] -> {ttconfig} } sub config { my($class, $c, $param) = @_; $class = ref $class || $class; my $self = bless { } => $class; my %items = qw( template_start_tag START_TAG template_end_tag END_TAG template_tag_style TAG_STYLE template_pre_chomp PRE_CHOMP template_post_chomp POST_CHOMP template_trim TRIM template_interpolate INTERPOLATE template_anycase ANYCASE template_delimiter DELIMITER template_absolute ABSOLUTE template_relative RELATIVE template_default DEFAULT template_block BLOCKS template_auto_reset AUTO_RESET template_recursion RECURSION template_pre_define PRE_DEFINE template_eval_perl EVAL_PERL template_pre_process PRE_PROCESS template_post_process POST_PROCESS template_process PROCESS template_error ERROR template_debug DEBUG template_cache_size CACHE_SIZE template_compile_ext COMPILE_EXT template_compile_dir COMPILE_DIR template_plugin PLUGINS template_plugin_base PLUGIN_BASE template_load_perl LOAD_PERL template_filter FILTERS template_v1dollar V1DOLLAR template_load_template LOAD_TEMPLATES template_load_plugin LOAD_PLUGINS template_load_filter LOAD_FILTERS template_tolerant TOLERANT ); my $s = $param -> server(); my $hostname = ($c -> global_hostname || [$s -> server_hostname]) -> [0]; my $config = { }; my @roots = map { Uttu::Tools::server_root_relative($_) } @{$c -> template_include_path || [ Apache -> server_root_relative("local") ]}; if(defined $c -> global_framework) { push @roots, $Uttu::Config::PREFIX . "/functionsets/" . $c -> global_framework . "/"; my $p = $INC{'Uttu/Framework/' . $c -> global_framework . ".pm"}; $p =~ s{lib/Uttu/Framework/.*$}{}; $p ||= $Uttu::Config::PREFIX . "/framework/" . $c -> global_framework; push @roots, $p; } $config -> {INCLUDE_PATH} = join($c -> template_delimiter || ":", @roots); $self -> {_template_include_path} = [ @roots ]; foreach my $i (keys %items) { $config -> {$items{$i}} = $c -> get($i) if $c -> get($i); } $self -> set_ttconfig($config); return $self; } 1; __END__ =head1 NAME Uttu::Handler::template =head1 SYNOPSIS [global] content_handler = template [template] =head1 DESCRIPTION By setting the global content_handler configuration variable to template, L will be called to parse the web pages and create the content. This module depends on L to provide the Template service handler. =head1 GLOBALS The Template content handler makes the following global variables available. =over 4 =item u This is the C object responsible for the current request. =item lh If C is enabled, then this is defined and is the L object providing translation services into the preferred language of the client. =item r The Apache::Request object. =back =head1 CONFIGURATION These variables are used to configure the L object. The variable names should be preceeded with C or placed in a [template] section. =over 4 =item absolute A flag indicating whether or not to allow absolute file names. The default is false. =item anycase Whether or not to allow directives in lower case. The default is false, requiring directives to be in all UPPER case. =item auto_reset A flag enabling BLOCK definitions to persist across templates. Note that we current construct a new Template object for each request. The default is false. =item block block NAME = CODE Pre-define a template block with the name C. =item cache_size Maximum number of compiled templates to cache in memory. The default is C -- cache all templates. =item compile_dir Root of directory in which compiled template files should be written. This may be a relative path which will be taken as relative to the server root. The default is C -- do not compile. =item compile_ext The filename extension for compiled template files. Default is C -- do not compile. =item debug A flag indicating whether or not to raise an error when an undefined variable is accessed. The default is false. =item default The default template to use when another is not found. =item delimiter The delimiter separating paths in C. This does not affect how C is used in the Uttu configuration file. The default is `:'. =item end_tag This is the token that indicates the end of directives. The default is C<%]>. =item error Mapping of error types to templates. =item eval_perl A flag indicating whether or not PERL/RAWPERL blocks should be processed. The default is false. =item filter Map a filter name to a filter subroutine or factory. =item include_path A list of directories in which to search for templates. If this is not defined, then C<$server_root/local> is added. If a framework is defined, then the installation directories of the framework and function sets are added. =item interpolate Whether or not to interpolate variables embedded as C<$this> or C<${this}>. The default is false. =item load_filter Load the specified filter provider. =item load_perl A flag to indicate whether regular Perl modules should be loaded if a named plugin can't be found. The default is false. =item load_plugin Load the specifide plugin provider. =item load_template Load the specifide template provider. =item plugin plugin PLUGIN My::Package Map plugin names to Perl packages. =item plugin_base One or more base classes under which plugins may be found. =item post_chomp A flag indicating whether or not to remove whitespace after directives. The default is false. =item post_process Name of templates to process after the main template. =item pre_chomp A flag indicating whether or not to remove whitespace before directives. The default is false. =item pre_define pre_define key = value A mapping of variables to values to pre-define in the stash. =item pre_process Name of templates to process before the main template. =item recursion A flag indicating whether or not to allow recursion into templates. The default is false. =item relative A flag indicating whether or not to allow relative filenames. The default is false. =item start_tag This is the token that indicates the beginning of directives. The default is C<[%>. =item tag_style Sets C amd C according to a pre-defined style. The default is `template' giving the default values for C and C. =item tolerant A flag indicating whether or not providers should tolerate errors as declinations. The default is false. =item trim Whether or not to remove leading and trailing whitespace from template output. The default is false. =item v1dollar A flag indicating whether or not to enable version 1.* handling of leading `$' on variables. The default is false -- `$' indicates interpolation. =back 4 =head1 SEE ALSO L