HTML-Template-JIT

 view release on metacpan or  search on metacpan

JIT.pm  view on Meta::CPAN


our $VERSION = '0.05';

use Carp qw(croak);
use File::Spec;
use File::Path qw(rmtree mkpath);
use Digest::MD5 qw(md5_hex);

sub new {
  my $pkg = shift;
  
  croak(__PACKAGE__ . "::new() called with odd number of arguments")
    if @_ % 2;
  my %args = @_;

  croak(__PACKAGE__ . "::new() : called without required filename parameter")
    unless exists $args{filename};

  croak(__PACKAGE__ . "::new() : called without required jit_path parameter")
    unless exists $args{jit_path};
 
  croak(__PACKAGE__ . "::new() : jit_path \"$args{jit_path}\" does not exist!")
    unless -e $args{jit_path};

  croak(__PACKAGE__ . "::new() : jit_path \"$args{jit_path}\" is not a writable directory!")
    unless -d _ and -w _;

  # try to find the template file
  my $path = _find_file($args{filename}, $args{path} || []);
  croak(__PACKAGE__ . "::new() : unable to find template file \"$args{filename}\"")
    unless $path;

  # setup options we care about
  $args{global_vars}       ||= 0;
  $args{print_to_stdout}   ||= 0;
  $args{case_sensitive}    ||= 0;
  $args{loop_context_vars} ||= 0;

  # get a hash of the path and mtime.  hashing them together means
  # that everytime the template file is changed we'll get a new md5
  # and that'll force a recompile.
  my $path_md5     = md5_hex($path . (stat($path))[9] . $VERSION .
                             join(' ', $args{global_vars},
                                       $args{print_to_stdout},
                                       $args{loop_context_vars},
                                       $args{case_sensitive}));
  
  # compute package and filesystem details
  my $package      = "tmpl_$path_md5";      # package name
  my $package_dir  = File::Spec->catdir($args{jit_path}, $path_md5);
  my $package_path = File::Spec->catfile($package_dir, "$package.pm");

  print STDERR __PACKAGE__ . "::new() : found file : $path : $path_md5\n"
    if $args{jit_debug};

  print STDERR __PACKAGE__ . "::new() : attempting to load...\n"
    if $args{jit_debug};

  # try to load the module and return package handle if successful
  my $result;
  eval { $result = require $package_path; };
  if ($result) {
    $package->clear_params(); # need to clear out params from prior run
    return $package;
  }

  # die now if we can't compile
  croak(__PACKAGE__ . "::new() : no_compile is on but no compile form for $path is available!")
    if $args{no_compile};

  print STDERR __PACKAGE__ . "::new() : compiling...\n"
    if $args{jit_debug};

  # load the compiler
  require 'HTML/Template/JIT/Compiler.pm';

  # compile the template
  $result = HTML::Template::JIT::Compiler::compile(%args, 
						   package => $package, 
						   package_dir => $package_dir,
						   package_path => $package_path);
  croak(__PACKAGE__ . "::new() : Unable to compile $path.")
    unless $result;

  return $package;
}

# _find_file stolen from HTML::Template - needs to stay in sync but it
# would be a shame to have to load HTML::Template just to get it.
sub _find_file {
  my ($filename, $path) = @_;
  my $filepath;

  # first check for a full path
  return File::Spec->canonpath($filename)
    if (File::Spec->file_name_is_absolute($filename) and (-e $filename));

  # try pre-prending HTML_Template_Root
  if (exists($ENV{HTML_TEMPLATE_ROOT})) {
    $filepath =  File::Spec->catfile($ENV{HTML_TEMPLATE_ROOT}, $filename);
    return File::Spec->canonpath($filepath) if -e $filepath;
  }

  # try "path" option list..
  foreach my $path (@$path) {
    $filepath = File::Spec->canonpath(File::Spec->catfile($path, $filename));
    return File::Spec->canonpath($filepath) if -e $filepath;
  }

  # try even a relative path from the current directory...
  return File::Spec->canonpath($filename) if -e $filename;
  
  return undef;
}



1;
__END__

=pod



( run in 0.498 second using v1.01-cache-2.11-cpan-39bf76dae61 )