summaryrefslogtreecommitdiff
path: root/lib/Template/Service.pm
diff options
context:
space:
mode:
authorAndreas Mair <amair.sob@googlemail.com>2005-03-06 08:11:12 +0100
committerAndreas Mair <amair.sob@googlemail.com>2005-03-06 08:11:12 +0100
commit7525bed2d315a25ac2caf95ff0bf44c905d58a7e (patch)
tree64f68331dd109cf5c92182d10bb53c614db4a73b /lib/Template/Service.pm
downloadvdradmin-am-0.97-am1.tar.gz
vdradmin-am-0.97-am1.tar.bz2
2005-03-06: 0.97-am1 "initial release"v0.97-am1
This is mainly the lastest vdradmin (v0.97) with different patches applied: - vdradmin-0.97 has been taken from linvdr-0.7. - xpix's BigPatch_0.9pre5 (ported from vdradmin-0.95 to vdradmin-0.97 (see HISTORY.bigpatch). - included changes from vdradmin-0.95-ct-10 (see HISTORY.ct). - included vdradmin-0.95_0.9_pre5_fb1.diff (see HISTORY.macfly). - included vdradmin-0.96-rename.diff which also needs an applied "vdr-aio21_svdrprename.patch" patch (don't know the author right now). My own changes: - included missing "Was läuft heute?" template (found at www.vdr-portal.de). - fixed some rendering problems with "New Timer" and "New Autotimer" on KDE's Konqueror. - Beautified recordings listing (at least in my eyes ;-) - Added "Size" selectbox to TV template.
Diffstat (limited to 'lib/Template/Service.pm')
-rw-r--r--lib/Template/Service.pm765
1 files changed, 765 insertions, 0 deletions
diff --git a/lib/Template/Service.pm b/lib/Template/Service.pm
new file mode 100644
index 0000000..e2ac533
--- /dev/null
+++ b/lib/Template/Service.pm
@@ -0,0 +1,765 @@
+#============================================================= -*-Perl-*-
+#
+# Template::Service
+#
+# DESCRIPTION
+# Module implementing a template processing service which wraps a
+# template within PRE_PROCESS and POST_PROCESS templates and offers
+# ERROR recovery.
+#
+# AUTHOR
+# Andy Wardley <abw@kfs.org>
+#
+# COPYRIGHT
+# Copyright (C) 1996-2000 Andy Wardley. All Rights Reserved.
+# Copyright (C) 1998-2000 Canon Research Centre Europe Ltd.
+#
+# This module is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+#
+#----------------------------------------------------------------------------
+#
+# $Id: Service.pm,v 2.70 2003/04/29 12:39:37 abw Exp $
+#
+#============================================================================
+
+package Template::Service;
+
+require 5.004;
+
+use strict;
+use vars qw( $VERSION $DEBUG $ERROR );
+use base qw( Template::Base );
+use Template::Base;
+use Template::Config;
+use Template::Exception;
+use Template::Constants;
+
+$VERSION = sprintf("%d.%02d", q$Revision: 2.70 $ =~ /(\d+)\.(\d+)/);
+$DEBUG = 0 unless defined $DEBUG;
+
+
+#========================================================================
+# ----- PUBLIC METHODS -----
+#========================================================================
+
+#------------------------------------------------------------------------
+# process($template, \%params)
+#
+# Process a template within a service framework. A service may encompass
+# PRE_PROCESS and POST_PROCESS templates and an ERROR hash which names
+# templates to be substituted for the main template document in case of
+# error. Each service invocation begins by resetting the state of the
+# context object via a call to reset(). The AUTO_RESET option may be set
+# to 0 (default: 1) to bypass this step.
+#------------------------------------------------------------------------
+
+sub process {
+ my ($self, $template, $params) = @_;
+ my $context = $self->{ CONTEXT };
+ my ($name, $output, $procout, $error);
+ $output = '';
+
+ $self->debug("process($template, ",
+ defined $params ? $params : '<no params>',
+ ')') if $self->{ DEBUG };
+
+ $context->reset()
+ if $self->{ AUTO_RESET };
+
+ # pre-request compiled template from context so that we can alias it
+ # in the stash for pre-processed templates to reference
+ eval { $template = $context->template($template) };
+ return $self->error($@)
+ if $@;
+
+ # localise the variable stash with any parameters passed
+ # and set the 'template' variable
+ $params ||= { };
+ $params->{ template } = $template
+ unless ref $template eq 'CODE';
+ $context->localise($params);
+
+ SERVICE: {
+ # PRE_PROCESS
+ eval {
+ foreach $name (@{ $self->{ PRE_PROCESS } }) {
+ $self->debug("PRE_PROCESS: $name") if $self->{ DEBUG };
+ $output .= $context->process($name);
+ }
+ };
+ last SERVICE if ($error = $@);
+
+ # PROCESS
+ eval {
+ foreach $name (@{ $self->{ PROCESS } || [ $template ] }) {
+ $self->debug("PROCESS: $name") if $self->{ DEBUG };
+ $procout .= $context->process($name);
+ }
+ };
+ if ($error = $@) {
+ last SERVICE
+ unless defined ($procout = $self->_recover(\$error));
+ }
+
+ if (defined $procout) {
+ # WRAPPER
+ eval {
+ foreach $name (reverse @{ $self->{ WRAPPER } }) {
+ $self->debug("WRAPPER: $name") if $self->{ DEBUG };
+ $procout = $context->process($name, { content => $procout });
+ }
+ };
+ last SERVICE if ($error = $@);
+ $output .= $procout;
+ }
+
+ # POST_PROCESS
+ eval {
+ foreach $name (@{ $self->{ POST_PROCESS } }) {
+ $self->debug("POST_PROCESS: $name") if $self->{ DEBUG };
+ $output .= $context->process($name);
+ }
+ };
+ last SERVICE if ($error = $@);
+ }
+
+ $context->delocalise();
+ delete $params->{ template };
+
+ if ($error) {
+# $error = $error->as_string if ref $error;
+ return $self->error($error);
+ }
+
+ return $output;
+}
+
+
+#------------------------------------------------------------------------
+# context()
+#
+# Returns the internal CONTEXT reference.
+#------------------------------------------------------------------------
+
+sub context {
+ return $_[0]->{ CONTEXT };
+}
+
+
+#========================================================================
+# -- PRIVATE METHODS --
+#========================================================================
+
+sub _init {
+ my ($self, $config) = @_;
+ my ($item, $data, $context, $block, $blocks);
+ my $delim = $config->{ DELIMITER };
+ $delim = ':' unless defined $delim;
+
+ # coerce PRE_PROCESS, PROCESS and POST_PROCESS to arrays if necessary,
+ # by splitting on non-word characters
+ foreach $item (qw( PRE_PROCESS PROCESS POST_PROCESS WRAPPER )) {
+ $data = $config->{ $item };
+ $self->{ $item } = [ ], next unless (defined $data);
+ $data = [ split($delim, $data || '') ]
+ unless ref $data eq 'ARRAY';
+ $self->{ $item } = $data;
+ }
+ # unset PROCESS option unless explicitly specified in config
+ $self->{ PROCESS } = undef
+ unless defined $config->{ PROCESS };
+
+ $self->{ ERROR } = $config->{ ERROR } || $config->{ ERRORS };
+ $self->{ AUTO_RESET } = defined $config->{ AUTO_RESET }
+ ? $config->{ AUTO_RESET } : 1;
+ $self->{ DEBUG } = ( $config->{ DEBUG } || 0 )
+ & Template::Constants::DEBUG_SERVICE;
+
+ $context = $self->{ CONTEXT } = $config->{ CONTEXT }
+ || Template::Config->context($config)
+ || return $self->error(Template::Config->error);
+
+ return $self;
+}
+
+
+#------------------------------------------------------------------------
+# _recover(\$exception)
+#
+# Examines the internal ERROR hash array to find a handler suitable
+# for the exception object passed by reference. Selecting the handler
+# is done by delegation to the exception's select_handler() method,
+# passing the set of handler keys as arguments. A 'default' handler
+# may also be provided. The handler value represents the name of a
+# template which should be processed.
+#------------------------------------------------------------------------
+
+sub _recover {
+ my ($self, $error) = @_;
+ my $context = $self->{ CONTEXT };
+ my ($hkey, $handler, $output);
+
+ # there shouldn't ever be a non-exception object received at this
+ # point... unless a module like CGI::Carp messes around with the
+ # DIE handler.
+ return undef
+ unless (ref $$error);
+
+ # a 'stop' exception is thrown by [% STOP %] - we return the output
+ # buffer stored in the exception object
+ return $$error->text()
+ if $$error->type() eq 'stop';
+
+ my $handlers = $self->{ ERROR }
+ || return undef; ## RETURN
+
+ if (ref $handlers eq 'HASH') {
+ if ($hkey = $$error->select_handler(keys %$handlers)) {
+ $handler = $handlers->{ $hkey };
+ $self->debug("using error handler for $hkey") if $self->{ DEBUG };
+ }
+ elsif ($handler = $handlers->{ default }) {
+ # use default handler
+ $self->debug("using default error handler") if $self->{ DEBUG };
+ }
+ else {
+ return undef; ## RETURN
+ }
+ }
+ else {
+ $handler = $handlers;
+ $self->debug("using default error handler") if $self->{ DEBUG };
+ }
+
+ eval { $handler = $context->template($handler) };
+ if ($@) {
+ $$error = $@;
+ return undef; ## RETURN
+ };
+
+ $context->stash->set('error', $$error);
+ eval {
+ $output .= $context->process($handler);
+ };
+ if ($@) {
+ $$error = $@;
+ return undef; ## RETURN
+ }
+
+ return $output;
+}
+
+
+
+#------------------------------------------------------------------------
+# _dump()
+#
+# Debug method which return a string representing the internal object
+# state.
+#------------------------------------------------------------------------
+
+sub _dump {
+ my $self = shift;
+ my $context = $self->{ CONTEXT }->_dump();
+ $context =~ s/\n/\n /gm;
+
+ my $error = $self->{ ERROR };
+ $error = join('',
+ "{\n",
+ (map { " $_ => $error->{ $_ }\n" }
+ keys %$error),
+ "}\n")
+ if ref $error;
+
+ local $" = ', ';
+ return <<EOF;
+$self
+PRE_PROCESS => [ @{ $self->{ PRE_PROCESS } } ]
+POST_PROCESS => [ @{ $self->{ POST_PROCESS } } ]
+ERROR => $error
+CONTEXT => $context
+EOF
+}
+
+
+1;
+
+__END__
+
+
+#------------------------------------------------------------------------
+# IMPORTANT NOTE
+# This documentation is generated automatically from source
+# templates. Any changes you make here may be lost.
+#
+# The 'docsrc' documentation source bundle is available for download
+# from http://www.template-toolkit.org/docs.html and contains all
+# the source templates, XML files, scripts, etc., from which the
+# documentation for the Template Toolkit is built.
+#------------------------------------------------------------------------
+
+=head1 NAME
+
+Template::Service - General purpose template processing service
+
+=head1 SYNOPSIS
+
+ use Template::Service;
+
+ my $service = Template::Service->new({
+ PRE_PROCESS => [ 'config', 'header' ],
+ POST_PROCESS => 'footer',
+ ERROR => {
+ user => 'user/index.html',
+ dbi => 'error/database',
+ default => 'error/default',
+ },
+ });
+
+ my $output = $service->process($template_name, \%replace)
+ || die $service->error(), "\n";
+
+=head1 DESCRIPTION
+
+The Template::Service module implements an object class for providing
+a consistent template processing service.
+
+Standard header (PRE_PROCESS) and footer (POST_PROCESS) templates may
+be specified which are prepended and appended to all templates
+processed by the service (but not any other templates or blocks
+INCLUDEd or PROCESSed from within). An ERROR hash may be specified
+which redirects the service to an alternate template file in the case
+of uncaught exceptions being thrown. This allows errors to be
+automatically handled by the service and a guaranteed valid response
+to be generated regardless of any processing problems encountered.
+
+A default Template::Service object is created by the Template module.
+Any Template::Service options may be passed to the Template new()
+constructor method and will be forwarded to the Template::Service
+constructor.
+
+ use Template;
+
+ my $template = Template->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ });
+
+Similarly, the Template::Service constructor will forward all configuration
+parameters onto other default objects (e.g. Template::Context) that it may
+need to instantiate.
+
+A Template::Service object (or subclass/derivative) can be explicitly
+instantiated and passed to the Template new() constructor method as
+the SERVICE item.
+
+ use Template;
+ use Template::Service;
+
+ my $service = Template::Service->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ });
+
+ my $template = Template->new({
+ SERVICE => $service,
+ });
+
+The Template::Service module can be sub-classed to create custom service
+handlers.
+
+ use Template;
+ use MyOrg::Template::Service;
+
+ my $service = MyOrg::Template::Service->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ COOL_OPTION => 'enabled in spades',
+ });
+
+ my $template = Template->new({
+ SERVICE => $service,
+ });
+
+The Template module uses the Template::Config service() factory method
+to create a default service object when required. The
+$Template::Config::SERVICE package variable may be set to specify an
+alternate service module. This will be loaded automatically and its
+new() constructor method called by the service() factory method when
+a default service object is required. Thus the previous example could
+be written as:
+
+ use Template;
+
+ $Template::Config::SERVICE = 'MyOrg::Template::Service';
+
+ my $template = Template->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ COOL_OPTION => 'enabled in spades',
+ });
+
+=head1 METHODS
+
+=head2 new(\%config)
+
+The new() constructor method is called to instantiate a Template::Service
+object. Configuration parameters may be specified as a HASH reference or
+as a list of (name =E<gt> value) pairs.
+
+ my $service1 = Template::Service->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ });
+
+ my $service2 = Template::Service->new( ERROR => 'error.html' );
+
+The new() method returns a Template::Service object (or sub-class) or
+undef on error. In the latter case, a relevant error message can be
+retrieved by the error() class method or directly from the
+$Template::Service::ERROR package variable.
+
+ my $service = Template::Service->new(\%config)
+ || die Template::Service->error();
+
+ my $service = Template::Service->new(\%config)
+ || die $Template::Service::ERROR;
+
+The following configuration items may be specified:
+
+=over 4
+
+
+
+
+=item PRE_PROCESS, POST_PROCESS
+
+These values may be set to contain the name(s) of template files
+(relative to INCLUDE_PATH) which should be processed immediately
+before and/or after each template. These do not get added to
+templates processed into a document via directives such as INCLUDE,
+PROCESS, WRAPPER etc.
+
+ my $service = Template::Service->new({
+ PRE_PROCESS => 'header',
+ POST_PROCESS => 'footer',
+ };
+
+Multiple templates may be specified as a reference to a list. Each is
+processed in the order defined.
+
+ my $service = Template::Service->new({
+ PRE_PROCESS => [ 'config', 'header' ],
+ POST_PROCESS => 'footer',
+ };
+
+Alternately, multiple template may be specified as a single string,
+delimited by ':'. This delimiter string can be changed via the
+DELIMITER option.
+
+ my $service = Template::Service->new({
+ PRE_PROCESS => 'config:header',
+ POST_PROCESS => 'footer',
+ };
+
+The PRE_PROCESS and POST_PROCESS templates are evaluated in the same
+variable context as the main document and may define or update
+variables for subsequent use.
+
+config:
+
+ [% # set some site-wide variables
+ bgcolor = '#ffffff'
+ version = 2.718
+ %]
+
+header:
+
+ [% DEFAULT title = 'My Funky Web Site' %]
+ <html>
+ <head>
+ <title>[% title %]</title>
+ </head>
+ <body bgcolor="[% bgcolor %]">
+
+footer:
+
+ <hr>
+ Version [% version %]
+ </body>
+ </html>
+
+The Template::Document object representing the main template being processed
+is available within PRE_PROCESS and POST_PROCESS templates as the 'template'
+variable. Metadata items defined via the META directive may be accessed
+accordingly.
+
+ $service->process('mydoc.html', $vars);
+
+mydoc.html:
+
+ [% META title = 'My Document Title' %]
+ blah blah blah
+ ...
+
+header:
+
+ <html>
+ <head>
+ <title>[% template.title %]</title></head>
+ <body bgcolor="[% bgcolor %]">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+=item PROCESS
+
+The PROCESS option may be set to contain the name(s) of template files
+(relative to INCLUDE_PATH) which should be processed instead of the
+main template passed to the Template::Service process() method. This can
+be used to apply consistent wrappers around all templates, similar to
+the use of PRE_PROCESS and POST_PROCESS templates.
+
+ my $service = Template::Service->new({
+ PROCESS => 'content',
+ };
+
+ # processes 'content' instead of 'foo.html'
+ $service->process('foo.html');
+
+A reference to the original template is available in the 'template'
+variable. Metadata items can be inspected and the template can be
+processed by specifying it as a variable reference (i.e. prefixed by
+'$') to an INCLUDE, PROCESS or WRAPPER directive.
+
+content:
+
+ <html>
+ <head>
+ <title>[% template.title %]</title>
+ </head>
+
+ <body>
+ [% PROCESS $template %]
+ <hr>
+ &copy; Copyright [% template.copyright %]
+ </body>
+ </html>
+
+foo.html:
+
+ [% META
+ title = 'The Foo Page'
+ author = 'Fred Foo'
+ copyright = '2000 Fred Foo'
+ %]
+ <h1>[% template.title %]</h1>
+ Welcome to the Foo Page, blah blah blah
+
+output:
+
+ <html>
+ <head>
+ <title>The Foo Page</title>
+ </head>
+
+ <body>
+ <h1>The Foo Page</h1>
+ Welcome to the Foo Page, blah blah blah
+ <hr>
+ &copy; Copyright 2000 Fred Foo
+ </body>
+ </html>
+
+
+
+
+
+
+
+=item ERROR
+
+The ERROR (or ERRORS if you prefer) configuration item can be used to
+name a single template or specify a hash array mapping exception types
+to templates which should be used for error handling. If an uncaught
+exception is raised from within a template then the appropriate error
+template will instead be processed.
+
+If specified as a single value then that template will be processed
+for all uncaught exceptions.
+
+ my $service = Template::Service->new({
+ ERROR => 'error.html'
+ });
+
+If the ERROR item is a hash reference the keys are assumed to be
+exception types and the relevant template for a given exception will
+be selected. A 'default' template may be provided for the general
+case. Note that 'ERROR' can be pluralised to 'ERRORS' if you find
+it more appropriate in this case.
+
+ my $service = Template::Service->new({
+ ERRORS => {
+ user => 'user/index.html',
+ dbi => 'error/database',
+ default => 'error/default',
+ },
+ });
+
+In this example, any 'user' exceptions thrown will cause the
+'user/index.html' template to be processed, 'dbi' errors are handled
+by 'error/database' and all others by the 'error/default' template.
+Any PRE_PROCESS and/or POST_PROCESS templates will also be applied
+to these error templates.
+
+Note that exception types are hierarchical and a 'foo' handler will
+catch all 'foo.*' errors (e.g. foo.bar, foo.bar.baz) if a more
+specific handler isn't defined. Be sure to quote any exception types
+that contain periods to prevent Perl concatenating them into a single
+string (i.e. C<user.passwd> is parsed as 'user'.'passwd').
+
+ my $service = Template::Service->new({
+ ERROR => {
+ 'user.login' => 'user/login.html',
+ 'user.passwd' => 'user/badpasswd.html',
+ 'user' => 'user/index.html',
+ 'default' => 'error/default',
+ },
+ });
+
+In this example, any template processed by the $service object, or
+other templates or code called from within, can raise a 'user.login'
+exception and have the service redirect to the 'user/login.html'
+template. Similarly, a 'user.passwd' exception has a specific
+handling template, 'user/badpasswd.html', while all other 'user' or
+'user.*' exceptions cause a redirection to the 'user/index.html' page.
+All other exception types are handled by 'error/default'.
+
+
+Exceptions can be raised in a template using the THROW directive,
+
+ [% THROW user.login 'no user id: please login' %]
+
+or by calling the throw() method on the current Template::Context object,
+
+ $context->throw('user.passwd', 'Incorrect Password');
+ $context->throw('Incorrect Password'); # type 'undef'
+
+or from Perl code by calling die() with a Template::Exception object,
+
+ die (Template::Exception->new('user.denied', 'Invalid User ID'));
+
+or by simply calling die() with an error string. This is
+automagically caught and converted to an exception of 'undef'
+type which can then be handled in the usual way.
+
+ die "I'm sorry Dave, I can't do that";
+
+
+
+
+
+
+
+=item AUTO_RESET
+
+The AUTO_RESET option is set by default and causes the local BLOCKS
+cache for the Template::Context object to be reset on each call to the
+Template process() method. This ensures that any BLOCKs defined
+within a template will only persist until that template is finished
+processing. This prevents BLOCKs defined in one processing request
+from interfering with other independent requests subsequently
+processed by the same context object.
+
+The BLOCKS item may be used to specify a default set of block definitions
+for the Template::Context object. Subsequent BLOCK definitions in templates
+will over-ride these but they will be reinstated on each reset if AUTO_RESET
+is enabled (default), or if the Template::Context reset() method is called.
+
+
+
+
+
+
+
+=item DEBUG
+
+The DEBUG option can be used to enable debugging messages from the
+Template::Service module by setting it to include the DEBUG_SERVICE
+value.
+
+ use Template::Constants qw( :debug );
+
+ my $template = Template->new({
+ DEBUG => DEBUG_SERVICE,
+ });
+
+
+
+
+=back
+
+=head2 process($input, \%replace)
+
+The process() method is called to process a template specified as the first
+parameter, $input. This may be a file name, file handle (e.g. GLOB or IO::Handle)
+or a reference to a text string containing the template text. An additional
+hash reference may be passed containing template variable definitions.
+
+The method processes the template, adding any PRE_PROCESS or POST_PROCESS
+templates defined, and returns the output text. An uncaught exception thrown
+by the template will be handled by a relevant ERROR handler if defined.
+Errors that occur in the PRE_PROCESS or POST_PROCESS templates, or those that
+occur in the main input template and aren't handled, cause the method to
+return undef to indicate failure. The appropriate error message can be
+retrieved via the error() method.
+
+ $service->process('myfile.html', { title => 'My Test File' })
+ || die $service->error();
+
+
+=head2 context()
+
+Returns a reference to the internal context object which is, by default, an
+instance of the Template::Context class.
+
+=head2 error()
+
+Returns the most recent error message.
+
+=head1 AUTHOR
+
+Andy Wardley E<lt>abw@andywardley.comE<gt>
+
+L<http://www.andywardley.com/|http://www.andywardley.com/>
+
+
+
+
+=head1 VERSION
+
+2.70, distributed as part of the
+Template Toolkit version 2.10, released on 24 July 2003.
+
+=head1 COPYRIGHT
+
+ Copyright (C) 1996-2003 Andy Wardley. All Rights Reserved.
+ Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<Template|Template>, L<Template::Context|Template::Context>