[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