[Templates-cvs] cvs commit: TT3/lib/Template Store.pm

cvs@template-toolkit.org cvs@template-toolkit.org
Wed, 24 Mar 2004 14:08:38 +0000


cvs         04/03/24 14:08:38

  Added:       lib/Template Store.pm
  Log:
  * added Template::Store module
  
  Revision  Changes    Path
  1.1                  TT3/lib/Template/Store.pm
  
  Index: Store.pm
  ===================================================================
  #========================================================================
  #
  # Template::Store
  #
  # DESCRIPTION
  #   This module implements a default store object which stored compiled
  #   template Perl code in files and reloads them back into in-memory 
  #   objects on demand.
  # 
  # AUTHOR
  #   Andy Wardley <abw@wardley.org>
  #
  # COPYRIGHT
  #   Copyright (C) 1996-2004 Andy Wardley.  All Rights Reserved.
  #   Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
  #   Copyright (C) 2004 Fotango Ltd.
  #
  #   This module is free software; you can redistribute it and/or
  #   modify it under the same terms as Perl itself.
  #
  # REVISION
  #   $Id: Store.pm,v 1.1 2004/03/24 14:08:37 abw Exp $
  #
  #========================================================================
  
  package Template::Store;
  
  use strict;
  use warnings;
  use Template::Utils;
  use Template::Base;
  use base qw( Template::Base );
  use vars qw( $VERSION $ERROR $DEBUG $UTILS $THROW );
  
  $VERSION  = sprintf("%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/);
  $ERROR    = '';
  $DEBUG    = 0 unless defined $DEBUG;
  $UTILS    = 'Template::Utils';
  $THROW    = 'store';
  
  
  sub init {
      my ($self, $config) = @_;
      $self->{ extension } = $config->{ extension } || $config->{ ext };
      $self->{ directory } = $config->{ directory } || $config->{ dir }
          || return $self->error('no directory defined');
      return $self;
  }
  
  
  sub get {
      my ($self, $id) = @_;
      my $file = $self->filename($id) || return;
      my $object;
  
      $self->debug("fetching $id from file $file\n") if $self->{ DEBUG };
  
      # check the file exists
      return $self->decline("$id not found")
          unless -f $file;
  
      # load the file using require(), first deleteing any
      # %INC entry to ensure it is reloaded - we don't want 
      # require() to return 1 to say it's already in memory
      delete $INC{ $file };
      eval { $object = require $file; };
  
      return $@
          ? $self->error("error loading compiled template $file: $@")
          : $object;
  }
  
  
  sub set {
      my ($self, $id, $code) = @_;
      my $file = $self->filename($id) || return;
  
      $self->debug("storing $id in file $file\n") if $self->{ DEBUG };
  
      return $UTILS->save_file($file, $code)
          || $self->error($UTILS->error());
  }
  
  
  sub filename {
      my ($self, $id) = @_;
      my $ext;
  
      # split id by ':' provider:path separator and also take care
      # of any paths with dos-like driver specifiers like C:/blah/blah
  
      my $path = $UTILS->file_path($self->{ directory }, split(':', $id));
  
      # add any file extension
      if (defined ($ext = $self->{ extension })) {
          if ($ext =~ /^\w/) {
              # extension starting with word character (e.g. 'ttc') is 
              # appended to end of path, with '.' as separator
              $path .= ".$ext";
          }
          else {
              # otherwise we assume it's got it's own separator, e.g. '-ttc'
              $path .= $ext;
          }
      }
  
      return $path;
  }
  
  
  
  1;
  
  __END__
  
  =head1 NAME
  
  Template::Store - secondary storage of compiled templates
  
  =head1 SYNOPSIS
  
      use Template::Store;
  
      my $store = Template::Store->new( 
          directory => '/tmp/tt3/store',
          extension => '.ttc',
      );
  
      # set() method to store Perl code in a file
      $store->set( foo => $foo_perl_code );
  
      # get() method to require() it back in again
      $foo_object = $store->get('foo')
          || die "foo is not in store\n";
  
  =head1 DESCRIPTION
  
  The Template::Store module implements a simple filesystem-based 
  store, providing persistant storage of compiled templates.  It also
  acts as a base class for other storage modules that store templates
  using different media or mechanisms.
  
  The Template::Store is a little like the Template::Cache module.  Both
  are designed to save us from having to compile a template from source
  code into Perl code whenever possible, given that this is the most
  time consuming part of processing a template.  The key difference
  between them is that the Template::Cache module stores live Perl
  objects in memory, whereas Template::Store saves the compiled Perl
  code on disk (or some other storage system).  However, both return
  live Perl objects, from their get() method. In the case of
  Template::Store, the file in which the component Perl code is stored
  is loaded using Perl's require() function, causing the Perl code to be
  loaded and evaluated into a Template::Component object.
  
  =head2 METHODS
  
  =head3 new()
  
  Constructor method used to create a new store module.  The
  C<directory> argument (or C<dir> for short) must be provided to define
  the root directory under which compiled template files should be
  stored.
  
      use Template::Store;
  
      my $store = Template::Store->new( 
          directory => '/tmp/tt3/store' 
      );
  
  The optional C<extension> (or C<ext> for short) parameter can be
  used to define an extension that will be automatically added to the
  end of the name of each file used to store compiled templates.
  
      my $store = Template::Store->new( 
          directory => '/tmp/tt3/store' 
          extension => 'ttc' 
      );
  
  If the extension begins with a word character, as shown in the
  previous example, then it will be added to the end of the filename
  with a C<.> character used to delimit them (e.g. ".ttc").  If the
  extension already begins with a non-word character (e.g. ".ttc",
  "-ttc", etc) then it is appended as it is with no further delimiter
  added.
  
  =head3 set($id, $perl_code)
  
  Public method to store the Perl code generated for a compiled template
  based on a unique identifier.  The C<$perl_code> argument should be 
  provided as a scalar or reference to a scalar.
  
      my $perl_code = $compiler->compile($source_code);
  
      $store->set( foo => $perl_code );
  
  =head3 get($id)
  
  Public method to fetch an item from the store if it exists.  The unique
  identifier is passed as the first argument.  The method loads the relevant
  file associated with the identifier using Perl's require(), thereby evaluating
  the Perl code and generating a Template::Component object (or whatever other
  result the Perl code returned).
  
      my $foo = $store->get('foo')
          || die "foo not in store";
  
  =head1 ERROR HANDLING
  
  Any errors raised by the Template::Store module will be thrown as 
  Template::Exception objects with a C<store> type.  This includes 
  errors in the C<new()> constructor (e.g. no C<directory> defined), 
  C<get()> and C<set()> methods (e.g. failed to read or write a file).
  
  =head1 AUTHOR
  
  Andy Wardley  E<lt>abw@wardley.orgE<gt>
  
  =head1 VERSION
  
  $Revision: 1.1 $
  
  =head1 COPYRIGHT
  
    Copyright (C) 1996-2004 Andy Wardley.  All Rights Reserved.
    Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
    Copyright (C) 2004 Fotango Ltd.
  
  This module is free software; you can redistribute it and/or
  modify it under the same terms as Perl itself.
  
  =cut
  
  # Local Variables:
  # mode: perl
  # perl-indent-level: 4
  # indent-tabs-mode: nil
  # End:
  #
  # vim: expandtab shiftwidth=4: