[Templates-cvs] cvs commit: TT3/lib/Template Provider.pm
cvs@template-toolkit.org
cvs@template-toolkit.org
Tue, 23 Mar 2004 14:20:35 +0000
cvs 04/03/23 14:20:35
Modified: lib/Template Provider.pm
Log:
* merged in file system provision as default mechanism
Revision Changes Path
1.3 +97 -93 TT3/lib/Template/Provider.pm
Index: Provider.pm
===================================================================
RCS file: /template-toolkit/TT3/lib/Template/Provider.pm,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Provider.pm 2004/03/23 13:34:37 1.2
+++ Provider.pm 2004/03/23 14:20:35 1.3
@@ -3,7 +3,8 @@
# Template::Provider
#
# DESCRIPTION
-# Base class object for providing templates and other resources.
+# Default provider for locating and loading templates from a file
+# system and a base class for other providers.
#
# AUTHOR
# Andy Wardley <abw@wardley.org>
@@ -17,7 +18,7 @@
# modify it under the same terms as Perl itself.
#
# REVISION
-# $Id: Provider.pm,v 1.2 2004/03/23 13:34:37 abw Exp $
+# $Id: Provider.pm,v 1.3 2004/03/23 14:20:35 abw Exp $
#
#========================================================================
@@ -26,14 +27,16 @@
use strict;
use warnings;
use Template::Source;
+use Template::Utils;
use Template::Base;
use base qw( Template::Base );
-use vars qw( $VERSION $ERROR $DEBUG $SOURCE
+use vars qw( $VERSION $ERROR $DEBUG $UTILS $SOURCE
$MAX_PATHS $STATIC $ID @CONFIG );
-$VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
+$VERSION = sprintf("%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/);
$ERROR = '';
$DEBUG = 0 unless defined $DEBUG;
+$UTILS = 'Template::Utils';
$SOURCE = 'Template::Source';
$MAX_PATHS = 32;
$STATIC = 0;
@@ -62,8 +65,8 @@
$self->{ path } = [ ];
}
- # allow base class to provide templates from a hash
- $self->{ templates } = $config->{ templates };
+ # copy across any load_source flag
+ $self->{ load_source } = $config->{ load_source };
return $self;
}
@@ -81,13 +84,17 @@
sub id {
my $self = shift;
- return $self->{ id } ||= shift || do {
- my ($sec, $min, $hour, $day, $mon, $year) = localtime(CORE::time);
- sprintf( "%04d%02d%02d%02d%02d%02d%03d",
- $year + 1900, $mon + 1, $day,
- $hour, $min, $sec,
- $ID++ );
- };
+ return $self->{ id } ||= shift || sprintf('template%02d', $ID++);
+
+# old way added timestamp which will invalidate compiled templates
+# (which may be a good thing?)
+# return $self->{ id } ||= shift || do {
+# my ($sec, $min, $hour, $day, $mon, $year) = localtime(CORE::time);
+# sprintf( "%04d%02d%02d%02d%02d%02d%03d",
+# $year + 1900, $mon + 1, $day,
+# $hour, $min, $sec,
+# $ID++ );
+# };
}
@@ -141,45 +148,31 @@
#------------------------------------------------------------------------
sub fetch_path {
- my ($self, $path, $name, $opts) = @_;
-
- $path = $self->join_path($path, $name);
-
- my $templates = $self->{ templates }
- || return $self->decline('no templates defined');
-
- my $template = $templates->{ $path }
- || return $self->decline('template not found: $path');
-
- my $source = {
- path => $name,
- load => $path,
- time => CORE::time(),
- text => $template,
- fresh => 1,
- };
-
- return $self->source($source);
-}
-
-
-#------------------------------------------------------------------------
-# join_path($path1, $path2, ...)
-#
-# Join all the arguments path to form a composite path.
-#------------------------------------------------------------------------
-
-sub join_path {
- my ($self, @paths) = @_;
- my $path = '';
- my $next;
- while (@paths) {
- $next = shift @paths;
- $next =~ s[^/][];
- $path .= '/' unless $path =~ m[/$];
- $path .= $next;
+ my ($self, $path, $name) = (shift, shift, shift);
+ my $opts = @_ && UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ };
+ my $file = $UTILS->file_path($path, $name);
+
+ $self->debug("looking to fetch file: $file\n") if $self->{ DEBUG };
+
+ if (-r $file) {
+ # define document parameters
+ my $source = {
+ name => $name,
+ time => (stat(_))[9],
+ load => $file,
+ provider => $self,
+ options => $opts,
+ %$opts,
+ };
+ # go load the text if the 'load' option is set
+ if ($opts->{ load }) {
+ $source->{ text } = $UTILS->load_file($file)
+ || return $self->error($UTILS->error());
+ }
+ return $self->source($source);
}
- return $path;
+
+ return $self->decline("file not found: $name");
}
@@ -339,7 +332,6 @@
}
-
#------------------------------------------------------------------------
# load($file)
#
@@ -351,8 +343,13 @@
#------------------------------------------------------------------------
sub load {
- my $self = shift;
- return $self->error('load() not implemented in the provider base class');
+ my ($self, $file) = @_;
+
+ # perform any validation required to check we're OK to load this file
+ $file = $self->validate($file) || return;
+
+ return $UTILS->load_file($file)
+ || return $self->error($UTILS->error());
}
@@ -364,8 +361,12 @@
#------------------------------------------------------------------------
sub time {
- my $self = shift;
- return $self->error('time() not implemented in the provider base class');
+ my ($self, $file) = @_;
+
+ # perform any validation required to check we're OK to stat this file
+ $file = $self->validate($file) || return;
+
+ return (stat($file))[9];
}
@@ -373,17 +374,12 @@
# validate($file)
#
# Validation method used to check that it's OK to go ahead and load a
-# template. Argument is as per load().
+# template file. Checks that the file exists and is readable.
#------------------------------------------------------------------------
sub validate {
- my $self = shift;
-
- # Looks alright to me, but then what do I know? I'm just a humble
- # base class provider and they haven't seen fit to provide me with
- # a validation method of my own.
-
- return 1;
+ my ($self, $file) = @_;
+ return -r $file ? $file : $self->error("$file: $!");
}
@@ -409,11 +405,13 @@
=head1 DESCRIPTION
-This module implements a base class provider for the Template Toolkit.
-A provider is responsible for locating templates on disk, in a database,
-or using some other kind of storage/retrieval system, and returning
-Template::Source objects to represent the pertinent information relating
-to them.
+This module implements a default provider for the Template Toolkit
+which is responsible locating templates in a file system and returning
+Template::Source objects to represent the pertinent information
+relating to them. The Template::Provider module also acts as a base
+class from which other providers can be derived for fetching templates
+from other secondary storage systems or retrieveal mechanisms (e.g.
+database, http, etc.)
=head1 METHODS
@@ -426,19 +424,23 @@
=head3 id
A unique identifier for the provider, used to generate unique
-identifiers for the source documents created. A default id will be
-generated if not otherwise provided. Note however that this id contains
-the current timestamp and as such, will change each time you invoke the
-provider. This may defeat the storage of compiled template documents.
-
-TODO: this isn't a very good idea and possibly needs a slight re-think.
+identifiers for the source documents created. A default id of
+the form 'template01', 'template02', etc., will be generated if
+not provided.
+
+NOTE: I previously generated an id that included a timestamp. However this
+would invalidate any previousy compiled templates if you don't explicitly
+define an id, because the provider id will change every time you run it,
+and hence the source id will also change. This all needs a little rethink.
=head3 path
-A path or reference to a list of paths that define the possible locations of
-template provided by this object. These are analagous to directories in
-a file system (and indeed are exactly that for Template::Provider::File), but
-may of course be employed by a provider that is not based on a file system.
+A path or reference to a list of paths that define the possible
+locations of template provided by this object. In the case of the
+base class Template::Provider modules, these represent the directories
+on the file system in which templates can be located. However, in
+subclasses providers, they may be used to represent other kinds of
+location.
# single path
my $provider = Template::Provider->new({
@@ -500,15 +502,9 @@
Fetch a named template from a specific path, given by the first argument.
- my $source = $provider->fetch_path('/home/abw/templates/wibble')
+ my $source = $provider->fetch_path('/home/abw/templates', 'wibble')
|| die $provider->error();
-=head2 join_path(@parts)
-
-Joins all arguments into a single path using C</> as a delimiter.
-This may be re-defined in subclassed providers to implement
-different path styles.
-
=head2 path()
Accessor method which returns a reference to the current path list.
@@ -526,18 +522,26 @@
=head2 load($path)
-Load the contents of the template defined by $path. This does nothing
-in the base class and returns an error to that effect.
+Load the contents of the template file defined by $path.
=head2 time($path)
-Return the modification of the template defined by $path. This does
-nothing in the base class and returns an error to that effect.
+Return the modification of the template file defined by $path.
=head2 validate($path)
+
+Validates that the file defined by $path passed exists and can be read.
+
+=head1 TODO
+
+Should we pass the current context reference to the fetch() method?
+
+ Pros: allows the provider to be more "smart", e.g. to implement
+ authorisation/authentication based on keys/identities defined
+ in context.
-Validates that the path passed as an argument is valid and that the
-template defined by that path can be accessed.
+ Cons: make the provider dependant on the whole architecture, rather
+ than a simple "leaf node".
=head1 AUTHOR
@@ -545,7 +549,7 @@
=head1 VERSION
-$Revision: 1.2 $
+$Revision: 1.3 $
=head1 COPYRIGHT