Apache-SimpleTemplate
view release on metacpan or search on metacpan
SimpleTemplate.pm view on Meta::CPAN
our $DEFAULT_RELOAD_FLAG = 1;
our $DEFAULT_CASCADE_STATUS = 1;
our $DEFAULT_DEBUG_LEVEL = 0;
#
# handler
#
# the Apache/mod_perl handler
#
sub handler {
my $r = shift;
my $s = shift || new Apache::SimpleTemplate($r);
#unless ($r) { return &cgi_handler($s); }
$s->{_header_sent} = 0;
print STDERR "-------- Apache::SimpleTemplate::handler REQUEST FOR $s->{file}\n" if ($s->{debug} > 1);
if ($s->{status} == 200) { $s->render($ENV{DOCUMENT_ROOT}.$s->{file}); }
$s->flush(1);
# return ($s->{debug} && $s->{_error}) ? undef : $s->{status};
# return ($s->{_error}) ? $s->{status} : undef;
return ( $s->{status} && ($s->{status} != 200) ) ? $s->{status} : undef;
}
#########################################################
# OBJECT CREATOR/METHODS
#
#
# new
#
# make a new instance of SimpleTemplate,
# given the current Apache request object ($r) or
# a hash with the CGI variables already parsed.
#
# new Apache::SimpleTemplate($r);
# new Apache::SimpleTemplate($inref);
#
sub new {
my $class = shift;
my $r = shift;
my $self = {};
bless($self, $class);
if (ref($r) =~ m/Apache/) {
$self->{file} = $r->dir_config('SimpleTemplateFile');
$self->{block_begin} = $r->dir_config('SimpleTemplateBlockBegin');
$self->{block_end} = $r->dir_config('SimpleTemplateBlockEnd');
$self->{content_type} = $r->dir_config('SimpleTemplateContentType');
$self->{cascade_status} = $r->dir_config('SimpleTemplateCascadeStatus');
$self->{cache} = $r->dir_config('SimpleTemplateCache');
$self->{reload} = $r->dir_config('SimpleTemplateReload');
$self->{debug} = $r->dir_config('SimpleTemplateDebug');
}
if (!defined $self->{cache}) { $self->{cache} = $DEFAULT_CACHE_FLAG; }
if (!defined $self->{reload}) { $self->{reload} = $DEFAULT_RELOAD_FLAG; }
if (!defined $self->{block_begin}) { $self->{block_begin} = $DEFAULT_BLOCK_BEGIN; }
if (!defined $self->{block_end}) { $self->{block_end} = $DEFAULT_BLOCK_END; }
if (!defined $self->{file}) { $self->{file} = ($ENV{SCRIPT_NAME} . ($ENV{PATH_INFO}||'') ); }
if (!defined $self->{content_type}) { $self->{content_type} = $DEFAULT_CONTENT_TYPE; }
if (!defined $self->{cascade_status}) { $self->{cascade_status} = $DEFAULT_CASCADE_STATUS; }
if (!defined $self->{debug}) { $self->{debug} = $DEFAULT_DEBUG_LEVEL; }
print STDERR "---- NEW SimpleTemplate OBJECT FOR $self->{file}\n" if ($self->{debug} > 1);
$self->{r} = $r;
$self->{inref} = (ref($r) eq 'HASH') ? $r : $self->parse_form($r);
$self->{headerref} = {};
$self->{status} = 200;
return $self;
}
# getters/setters
sub block_begin { my $s = shift; return $_[0] ? $s->{block_begin} = $_[0] : $s->{block_begin}; }
sub block_end { my $s = shift; return $_[0] ? $s->{block_end} = $_[0] : $s->{block_end}; }
sub file { my $s = shift; return $_[0] ? $s->{file} = $_[0] : $s->{file}; }
sub debug { my $s = shift; return $_[0] ? $s->{debug} = $_[0] : $s->{debug}; }
sub reload { my $s = shift; return $_[0] ? $s->{reload} = $_[0] : $s->{reload}; }
sub cache { my $s = shift; return $_[0] ? $s->{cache} = $_[0] : $s->{cache}; }
sub status { my $s = shift; return $_[0] ? $s->{status} = $_[0] : $s->{status}; }
sub content_type { my $s = shift; return $_[0] ? $s->{content_type} = $_[0] : $s->{content_type}; }
sub cascade_status { my $s = shift; return $_[0] ? $s->{cascade_status} = $_[0] : $s->{cascade_status}; }
#
# header
#
# safely add a header (without squashing an existing entry.)
#
sub header {
my ($s, $name, $value) = @_;
my $cur = $s->{headerref}->{$name};
if ($cur) { $s->{headerref}->{$name} = $cur . "\n" . $name . ': ' . $value; }
else { $s->{headerref}->{$name} = $value; }
}
#
# print
#
# print out something
#
sub print {
my ($s) = shift;
${ $s->{out} } .= join('', @_);
}
#
# flush
#
# flush the current output buffer.
# (changing status or content_type no longer an option.)
# an arg of one won't change buffering (for internal calls.)
#
sub flush {
my ($s) = shift;
my $r = $s->{r};
local $| = $_[0] ? undef : 1;
if (!$s->{_header_sent} && ($s->{status} < 400)) {
# send any header stuff from headerref
foreach my $h (keys %{ $s->{headerref} }) {
if ($r) {
my $cur = $r->header_out($h);
if ($cur) { $r->header_out($h, ($cur . "\n" . $h . ': ' . $s->{headerref}->{$h})); }
else { $r->header_out($h, $s->{headerref}->{$h}); }
}
else {
print $h . ': ' . $s->{headerref}->{$h} . "\n";
}
}
if ($r) {
# set my status and content_type...
$r->status($s->{status});
$r->content_type($s->{content_type});
$r->send_http_header;
}
SimpleTemplate.pm view on Meta::CPAN
$eval .= &blank_lines($block);
}
}
else {
print STDERR "** Apache::SimpleTemplate $_[0]: Invalid Block in:\n";
print STDERR $pieces[$i].$s->{block_end}."\n";
$s->{_error} .= "Invalid Block: ".$pieces[$i].$s->{block_end}."\n";
return 500;
}
}
if ($s->{debug} > 3) {
print STDERR "==================================TEXT $i:\n";
print STDERR "$pieces[$i]\n";
print STDERR "==================================\n";
}
$eval .= '$$____st_out_.=\''."e_escape($pieces[$i]).'\'; ';
$eval .= "return (\$____st_out_);\n}";
#if ($usepackage) { $eval .= "1;\n"; }
if ($s->{debug} > 2) {
print STDERR "===================================================EVAL\n";
print STDERR "$eval\n";
print STDERR "===================================================/EVAL\n";
}
my $fun = eval($eval);
if ($@) { print STDERR "** Apache::SimpleTemplate $_[0]: $@\n"; $s->{_error} .= $@; return 500; }
if ($usepackage) { return 200; }
return $fun;
}
sub blank_lines {
my ($string) = @_;
$string =~ s/[^\n]//g;
return $string;
}
#
# include
#
# for use in templates, so they can include other templates/files.
# takes a path relative to the document root.
# $s->include('/path/relative/to/docroot.stml');
#
sub include {
my $s = shift;
print STDERR "---- Apache::SimpleTemplate::include FROM $s->{file} FOR $_[0]\n" if ($s->{debug} > 1);
my $tmp = $s->{status};
$s->render($ENV{DOCUMENT_ROOT}.$_[0]);
$s->status($tmp) if ($s->{cascade_status} == 0);
}
#
# preload a template into memory
# takes a full path
#
sub preload {
my $s = shift;
$_cache{$_[0]} = $s->compile($_[0]);
}
#########################################################
# OTHER FUNCTIONS (callable as methods, too.)
#
# url-encode a string
sub encode {
my $s = shift;
if (ref $s) { $s = shift; }
return undef unless defined($s);
$s =~ s/([^a-zA-Z0-9_\.\-\ ])/uc sprintf("%%%02x",ord($1))/eg;
$s =~ s/\ /\+/g;
return $s;
}
# url-decode a string
sub decode {
my $s = shift;
if (ref $s) { $s = shift; }
return undef unless defined($s);
$s =~ s/\+/ /g;
$s =~ s/\%([0-9a-fA-F]{2})/chr(hex($1))/eg;
return $s;
}
# html-escape a string ('<tag> & " ' becomes '<tag> & "')
sub escape {
my $s = shift;
if (ref $s) { $s = shift; }
return undef unless defined($s);
SimpleTemplate.pm view on Meta::CPAN
#
# example using SimpleTemplate in other code
#
# (could use your subclass here instead.)
use Apache::SimpleTemplate;
my $s = new Apache::SimpleTemplate();
#### options: (caching won't do anything usefule in CGI mode.)
#$s->block_begin('<%');
#$s->block_end('%>');
#$s->debug(0);
$s->cache(0);
$s->reload(0);
#### call as a CGI (will get headers and status set):
#$s->content_type('text/html');
$s->file('/dir/file.stml');
exit &Apache::SimpleTemplate::handler();
#### or non-CGI use, just get the rendered page:
# $s->render('/full/path/to/file.stml');
# print ${ $s->{out} };
=head1 VARIABLES & FUNCTIONS
=head2 variables in templates:
$r - this instance of 'Apache', i.e. the request object.
$s - this instance of 'Apache::SimpleTemplate' (or your subclass)
$inref - a reference to a hash containing the CGI/form input args
$____st_* - these names are reserved for use inside the parsing function.
=head2 constructor and getters/setters:
$s = new Apache::SimpleTemplate($r) -- pass the Apache request object, $r.
parses CGI params.
$s = new Apache::SimpleTemplate($in) -- pass me a hash of CGI params.
$s = new Apache::SimpleTemplate() -- parses params from $ENV{QUERY_STRING}
$s->block_begin() -- get or set the beginning delimiter
$s->block_begin('<%')
$s->block_end() -- get or set the ending delimiter
$s->block_end('%>')
$s->file() -- get or set a file for rendering
$s->file('/foo.stml')
$s->debug() -- get or set the debug level (0=quiet - 3=verbose)
$s->debug(1)
$s->reload() -- get or set the reload flag (0 or 1)
$s->reload(1)
$s->cache() -- get or set the caching flag (0 or 1)
$s->cache(1)
$s->cascade_status() -- get or set flag for cascading status codes
$s->cascade_status(0) from included templates
=head2 other methods/functions (mostly useful in templates):
$s->content_type('text/xml') -- set our content-type to something
(must be done before any call to flush().)
$s->status(302) -- set our status to something other than 200
(must be done before any call to flush().)
$s->header($name,$value) -- add an outgoing header. (can add multiple
of the same name.)
(must be done before any call to flush().)
return -- stop running this template (within <% %>)
$s->encode($string) -- url-encode the $string.
&Apache::SimpleTemplate::encode($string)
$s->decode($string) -- url-decode the $string.
&Apache::SimpleTemplate::decode($string)
$s->escape($string) -- html-escape the $string.
&Apache::SimpleTemplate::escape($string)
$s->quote_escape($string) -- single-quote-escape the $string.
&Apache::SimpleTemplate::quote_escape($string)
$s->js_escape($string) -- single-quote and newline escape (for javascript)
&Apache::SimpleTemplate::quote_escape($string)
$s->preload($file) -- preload the template in $file, a full
path which must match the DOCUMENT_ROOT.
(for use in a startup.pl file.)
$s->include('/dir/file') -- include another document/template.
the path is relative to the DOCUMENT_ROOT
$s->print(...) -- print out something from within <% %>.
$s->flush() -- flush the print buffer (within <% %>).
(sends HTTP headers on the first call.)
=head2 deprecated and removed vars and functions.
$out - deprecated template variable.
a <%: %> block of code could use this for the output,
instead of the last value returned by the block.
use <% %> or <%= %> blocks as needed instead.
$headerref - removed, use $s->header() instead.
$status - removed, use $s->status() instead.
$content_type - removed, use $s->content_type() instead.
Apache::SimpleTemplate::include() -- static calls no longer work.
instantiate if necessary, and use $s->include() instead.
(shouldn't have been included in the first place, as they
would not follow any settings other than defaults.)
=head2 PerlSetVar options
SimpleTemplateBlockBegin -- the delim for a code block's end ['<%']
SimpleTemplateBlockEnd -- the delim for a code block's start ['%>']
SimpleTemplateCache -- keep templates in memory? [1]
SimpleTemplateReload -- check templates for changes? [1]
SimpleTemplateDebug -- level of debug msgs in error_log (0-3) [0]
(if >= 1, compile errors go to the browser.)
SimpleTemplateContentType -- the default content_type ['text/html']
SimpleTemplateCascadeStatus -- set to 0 if you do not want included
templates to affect the response status.
SimpleTemplateFile -- template file location (w/in doc_root)
probably useful only within a <Location>.
[the incoming request path]
=head1 OTHER TIDBITS
=head2 template processing
Any errors in evaluating a code block should get logged to the error_log.
The compilation process tries to keep the line numbers consistent with
the template, but <%! %> declarations/definitions that are not at the
top of the template may throw line numbers off.
Any additional variables you wish to use must be declared (with 'my').
If you declare them in <%! %> or <% %> blocks, they will be accessible
in later blocks.
Included sub-templates receive the same instance of $s, so they have the
same $inref, etc. Thus, they can also set headers, change status, etc.
(Turn off "cascade_status" to prevent the latter.)
=head2 template debugging
SimpleTemplateDebug / $s->debug() values have the following meanings
0 quiet, errors logged to error_log
1 quiet, errors also sent to browser
2 info on requests, includes, status codes, etc.
3 info on template compilation. (noisy)
4 verbose info on template compilation. (extremely noisy)
You can also always log your own messages to the error_log from
within your templates, eg: <% print STDERR "some message" %>.
=head2 performance notes
Templates are compiled into perl packages (or anonymous subroutines if
there is no <%! %> block.) Caching of templates, which is on by default,
will help speed performance greatly. The only reason you might want to
turn it off is if you have many, many templates and don't want them
always kept around in memory.
Preloading via preload() in a startup.pl file is a way to save more
memory (the template will get loaded before the webserver forks its
children, thus keeping the template in memory shared by all the procs.)
This also will improve speed a bit, as each newly spawned webserver
proc will not need to load the template anew.
preload() may be used even with caching off (0), if you have a handful of
templates you want to cache but many others you do not.
Turning SimpleTemplateReload to off (0) will speed things a little bit,
as SimpleTemplate will not check the file for updates with every request.
However, if you are using caching/preloading and SimpleTemplateCache is
off (0), Apache must be restarted to see template changes.
Finally, the regular CGI mode will probably be very slow, so you may
want only to use it when testing something (a cached template or another
module/subclass), or when using a host without mod_perl installed.
=head2 New in 0.04
$s->print and $s->flush methods. Option to have errors in included
templates not bubble up and cause whole page to fail.
Defaults delims are now the more conventional '<%' and '%>'.
Users still wanting '{{' and '}}' can set the
SimpleTemplateBlockBegin and SimpleTemplateBlockEnd variables.
$status, $headerref, $content_type not supported in templates.
=head2 Note for users of previous versions 0.01 or 0.02
Anyone switching from a version previous to 0.03 should note that the
default <% _perl_block_ %> behavior has changed. The behavior of the
new <%: %> tag should be functionally equivalent, so switching all
your tags to this should be an easy fix. (try
"perl -pi~ -e 's/\{\{/\<\%\:/g' __your_files__", and
"perl -pi~ -e 's/\}\}/\%\>/g' __your_files__".)
( run in 0.536 second using v1.01-cache-2.11-cpan-2398b32b56e )