📄 template.pm
字号:
$self->_commit_to_file_cache(); } $self->_commit_to_cache() if (($options->{cache} and not $options->{shared_cache} and not $options->{file_cache}) or ($options->{double_cache}) or ($options->{double_file_cache}));}# Caching subroutines - they handle getting and validating cache# records from either the in-memory or shared caches.# handles the normal in memory cacheuse vars qw( %CACHE );sub _fetch_from_cache { my $self = shift; my $options = $self->{options}; # return if there's no cache entry for this filename return unless exists($options->{filename}); my $filepath = $self->_find_file($options->{filename}); return unless (defined($filepath) and exists $CACHE{$filepath}); $options->{filepath} = $filepath; # validate the cache my $mtime = $self->_mtime($filepath); if (defined $mtime) { # return if the mtime doesn't match the cache if (defined($CACHE{$filepath}{mtime}) and ($mtime != $CACHE{$filepath}{mtime})) { $options->{cache_debug} and print STDERR "CACHE MISS : $filepath : $mtime\n"; return; } # if the template has includes, check each included file's mtime # and return if different if (exists($CACHE{$filepath}{included_mtimes})) { foreach my $filename (keys %{$CACHE{$filepath}{included_mtimes}}) { next unless defined($CACHE{$filepath}{included_mtimes}{$filename}); my $included_mtime = (stat($filename))[9]; if ($included_mtime != $CACHE{$filepath}{included_mtimes}{$filename}) { $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### CACHE MISS : $filepath : INCLUDE $filename : $included_mtime\n"; return; } } } } # got a cache hit! $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### CACHE HIT : $filepath\n"; $self->{param_map} = $CACHE{$filepath}{param_map}; $self->{parse_stack} = $CACHE{$filepath}{parse_stack}; exists($CACHE{$filepath}{included_mtimes}) and $self->{included_mtimes} = $CACHE{$filepath}{included_mtimes}; # clear out values from param_map from last run $self->_normalize_options(); $self->clear_params();}sub _commit_to_cache { my $self = shift; my $options = $self->{options}; my $filepath = $options->{filepath}; if (not defined $filepath) { $filepath = $self->_find_file($options->{filename}); confess("HTML::Template->new() : Cannot open included file $options->{filename} : file not found.") unless defined($filepath); $options->{filepath} = $filepath; } $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### CACHE LOAD : $filepath\n"; $options->{blind_cache} or $CACHE{$filepath}{mtime} = $self->_mtime($filepath); $CACHE{$filepath}{param_map} = $self->{param_map}; $CACHE{$filepath}{parse_stack} = $self->{parse_stack}; exists($self->{included_mtimes}) and $CACHE{$filepath}{included_mtimes} = $self->{included_mtimes};}# generates MD5 from filepath to determine filename for cache filesub _get_cache_filename { my ($self, $filepath) = @_; # hash the filename ... my $hash = Digest::MD5->md5_hex($filepath); # ... and build a path out of it. Using the first two charcters # gives us 255 buckets. This means you can have 255,000 templates # in the cache before any one directory gets over a few thousand # files in it. That's probably pretty good for this planet. If not # then it should be configurable. if (wantarray) { return (substr($hash,0,2), substr($hash,2)) } else { return File::Spec->join($self->{options}{file_cache_dir}, substr($hash,0,2), substr($hash,2)); }}# handles the file cachesub _fetch_from_file_cache { my $self = shift; my $options = $self->{options}; return unless exists($options->{filename}); # return if there's no cache entry for this filename my $filepath = $self->_find_file($options->{filename}); return unless defined $filepath; my $cache_filename = $self->_get_cache_filename($filepath); return unless -e $cache_filename; eval { $self->{record} = Storable::lock_retrieve($cache_filename); }; croak("HTML::Template::new() - Problem reading cache file $cache_filename (file_cache => 1) : $@") if $@; croak("HTML::Template::new() - Problem reading cache file $cache_filename (file_cache => 1) : $!") unless defined $self->{record}; ($self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack}) = @{$self->{record}}; $options->{filepath} = $filepath; # validate the cache my $mtime = $self->_mtime($filepath); if (defined $mtime) { # return if the mtime doesn't match the cache if (defined($self->{mtime}) and ($mtime != $self->{mtime})) { $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### FILE CACHE MISS : $filepath : $mtime\n"; ($self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack}) = (undef, undef, undef, undef); return; } # if the template has includes, check each included file's mtime # and return if different if (exists($self->{included_mtimes})) { foreach my $filename (keys %{$self->{included_mtimes}}) { next unless defined($self->{included_mtimes}{$filename}); my $included_mtime = (stat($filename))[9]; if ($included_mtime != $self->{included_mtimes}{$filename}) { $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### FILE CACHE MISS : $filepath : INCLUDE $filename : $included_mtime\n"; ($self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack}) = (undef, undef, undef, undef); return; } } } } # got a cache hit! $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### FILE CACHE HIT : $filepath\n"; # clear out values from param_map from last run $self->_normalize_options(); $self->clear_params();}sub _commit_to_file_cache { my $self = shift; my $options = $self->{options}; my $filepath = $options->{filepath}; if (not defined $filepath) { $filepath = $self->_find_file($options->{filename}); confess("HTML::Template->new() : Cannot open included file $options->{filename} : file not found.") unless defined($filepath); $options->{filepath} = $filepath; } my ($cache_dir, $cache_file) = $self->_get_cache_filename($filepath); $cache_dir = File::Spec->join($options->{file_cache_dir}, $cache_dir); if (not -d $cache_dir) { if (not -d $options->{file_cache_dir}) { mkdir($options->{file_cache_dir},$options->{file_cache_dir_mode}) or croak("HTML::Template->new() : can't mkdir $options->{file_cache_dir} (file_cache => 1): $!"); } mkdir($cache_dir,$options->{file_cache_dir_mode}) or croak("HTML::Template->new() : can't mkdir $cache_dir (file_cache => 1): $!"); } $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### FILE CACHE LOAD : $options->{filepath}\n"; my $result; eval { $result = Storable::lock_store([ $self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack} ], scalar File::Spec->join($cache_dir, $cache_file) ); }; croak("HTML::Template::new() - Problem writing cache file $cache_dir/$cache_file (file_cache => 1) : $@") if $@; croak("HTML::Template::new() - Problem writing cache file $cache_dir/$cache_file (file_cache => 1) : $!") unless defined $result;}# Shared cache routines.sub _fetch_from_shared_cache { my $self = shift; my $options = $self->{options}; my $filepath = $self->_find_file($options->{filename}); return unless defined $filepath; # fetch from the shared cache. $self->{record} = $self->{cache}{$filepath}; ($self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack}) = @{$self->{record}} if defined($self->{record}); $options->{cache_debug} and defined($self->{record}) and print STDERR "### HTML::Template Cache Debug ### CACHE HIT : $filepath\n"; # clear out values from param_map from last run $self->_normalize_options(), $self->clear_params() if (defined($self->{record})); delete($self->{record}); return $self;}sub _validate_shared_cache { my ($self, $filename, $record) = @_; my $options = $self->{options}; $options->{shared_cache_debug} and print STDERR "### HTML::Template Cache Debug ### SHARED CACHE VALIDATE : $filename\n"; return 1 if $options->{blind_cache}; my ($c_mtime, $included_mtimes, $param_map, $parse_stack) = @$record; # if the modification time has changed return false my $mtime = $self->_mtime($filename); if (defined $mtime and defined $c_mtime and $mtime != $c_mtime) { $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### SHARED CACHE MISS : $filename : $mtime\n"; return 0; } # if the template has includes, check each included file's mtime # and return false if different if (defined $mtime and defined $included_mtimes) { foreach my $fname (keys %$included_mtimes) { next unless defined($included_mtimes->{$fname}); if ($included_mtimes->{$fname} != (stat($fname))[9]) { $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### SHARED CACHE MISS : $filename : INCLUDE $fname\n"; return 0; } } } # all done - return true return 1;}sub _load_shared_cache { my ($self, $filename) = @_; my $options = $self->{options}; my $cache = $self->{cache}; $self->_init_template(); $self->_parse(); $options->{cache_debug} and print STDERR "### HTML::Template Cache Debug ### SHARED CACHE LOAD : $options->{filepath}\n"; print STDERR "### HTML::Template Memory Debug ### END CACHE LOAD ", $self->{proc_mem}->size(), "\n" if $options->{memory_debug}; return [ $self->{mtime}, $self->{included_mtimes}, $self->{param_map}, $self->{parse_stack} ]; }# utility function - given a filename performs documented search and# returns a full path of undef if the file cannot be found.sub _find_file { my ($self, $filename, $extra_path) = @_; my $options = $self->{options}; 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 the extra_path if one was specified if (defined($extra_path)) { $extra_path->[$#{$extra_path}] = $filename; $filepath = File::Spec->canonpath(File::Spec->catfile(@$extra_path)); return File::Spec->canonpath($filepath) if -e $filepath; } # 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 (@{$options->{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;}# utility function - computes the mtime for $filenamesub _mtime { my ($self, $filepath) = @_; my $options = $self->{options}; return(undef) if ($options->{blind_cache}); # make sure it still exists in the filesystem (-r $filepath) or Carp::confess("HTML::Template : template file $filepath does not exist or is unreadable."); # get the modification time return (stat(_))[9];}# utility function - enforces new() options across LOOPs that have# come from a cache. Otherwise they would have stale options hashes.sub _normalize_options { my $self = shift; my $options = $self->{options}; my @pstacks = ($self->{parse_stack}); while(@pstacks) { my $pstack = pop(@pstacks); foreach my $item (@$pstack) { next unless (ref($item) eq 'HTML::Template::LOOP'); foreach my $template (values %{$item->[HTML::Template::LOOP::TEMPLATE_HASH]}) { # must be the same list as the call to _new_from_loop... $template->{options}{debug} = $options->{debug}; $template->{options}{stack_debug} = $options->{stack_debug}; $template->{options}{die_on_bad_params} = $options->{die_on_bad_params}; $template->{options}{case_sensitive} = $options->{case_sensitive};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -