First pass at adding key files
This commit is contained in:
@ -0,0 +1,250 @@
|
||||
# ==================================================================
|
||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
|
||||
#
|
||||
# GT::Template::Inheritance
|
||||
# Author: Scott Beck
|
||||
# CVS Info : 087,071,086,086,085
|
||||
# $Id: Inheritance.pm,v 1.7 2005/02/09 20:51:27 jagerman Exp $
|
||||
#
|
||||
# Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
# ==================================================================
|
||||
#
|
||||
# Description: Provides class methods to deal with template
|
||||
# inheritance.
|
||||
#
|
||||
|
||||
package GT::Template::Inheritance;
|
||||
# ==================================================================
|
||||
|
||||
use strict;
|
||||
use vars qw($ERRORS);
|
||||
use bases 'GT::Base' => '';
|
||||
use GT::Template;
|
||||
|
||||
$ERRORS = { RECURSION => q _Recursive inheritance detected and interrupted: '%s'_ };
|
||||
|
||||
sub get_all_paths {
|
||||
# ----------------------------------------------------------------------------
|
||||
my ($class, %opts) = @_;
|
||||
|
||||
my $file = delete $opts{file};
|
||||
my $single = delete $opts{_single};
|
||||
$class->fatal(BADARGS => "No file specified to $class->" . ($single ? 'get_path' : 'get_all_paths')) unless defined $file;
|
||||
|
||||
my $root = delete $opts{path};
|
||||
$class->fatal(BADARGS => "No path specified to $class->" . ($single ? 'get_path' : 'get_all_paths')) unless defined $root;
|
||||
$class->fatal(BADARGS => "Path $root does not exist or is not a directory") unless -d $root;
|
||||
|
||||
my $local = exists $opts{local} ? delete $opts{local} : 1;
|
||||
my $inheritance = exists $opts{inheritance} ? delete $opts{inheritance} : 1;
|
||||
|
||||
# Old no-longer-supported option:
|
||||
delete @opts{qw/use_inheritance use_local local_inheritance/};
|
||||
|
||||
$class->fatal(BADARGS => "Unknown arguments: " . join ", ", keys %opts) if keys %opts;
|
||||
|
||||
my @paths = $class->tree(path => $root, local => $local, inheritance => $inheritance);
|
||||
my @files;
|
||||
for (@paths) {
|
||||
if (-f "$_/$file" and -r _) {
|
||||
return "$_/$file" if $single;
|
||||
push @files, "$_/$file";
|
||||
}
|
||||
}
|
||||
return if $single;
|
||||
return @files;
|
||||
}
|
||||
|
||||
sub get_path {
|
||||
# ----------------------------------------------------------------------------
|
||||
shift->get_all_paths(@_, _single => 1);
|
||||
}
|
||||
|
||||
sub tree {
|
||||
# -----------------------------------------------------------------------------
|
||||
my $class = shift;
|
||||
my %opts = @_ > 1 ? @_ : (path => shift);
|
||||
|
||||
my $root = delete $opts{path};
|
||||
$class->fatal(BADARGS => "No path specified for $class->tree") unless defined $root;
|
||||
$class->fatal(BADARGS => "Path '$root' does not exist or is not a directory") unless -d $root;
|
||||
|
||||
my $local = exists $opts{local} ? delete $opts{local} : 1;
|
||||
my $inheritance = exists $opts{inheritance} ? delete $opts{inheritance} : 1;
|
||||
|
||||
$class->fatal(BADARGS => "Unknown arguments: " . join ", ", keys %opts) if keys %opts;
|
||||
|
||||
my @paths;
|
||||
push @paths, $root;
|
||||
my %encountered = ($root => 1);
|
||||
if ($inheritance) {
|
||||
for my $path (@paths) {
|
||||
my $tplinfo = GT::Template->load_tplinfo($path);
|
||||
next if not defined $tplinfo->{inheritance};
|
||||
my @inherit = ref $tplinfo->{inheritance} eq 'ARRAY' ? @{$tplinfo->{inheritance}} : $tplinfo->{inheritance};
|
||||
|
||||
for (@inherit) {
|
||||
my $inh = m!^(?:[a-zA-Z]:)?[\\/]! ? $_ : "$path/$_";
|
||||
if (length $inh > 500 or $encountered{$inh}++) {
|
||||
return $class->fatal(RECURSION => $inh);
|
||||
}
|
||||
|
||||
push @paths, $inh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($local) {
|
||||
for (my $i = 0; $i < @paths; $i++) {
|
||||
if (-d "$paths[$i]/local") {
|
||||
splice @paths, $i, 0, "$paths[$i]/local";
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @paths;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
GT::Template::Inheritance - Provides GT::Template inheritance/local file
|
||||
determination.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use GT::Template::Inheritance;
|
||||
|
||||
my $file = GT::Template::Inheritance->get_path(
|
||||
file => "foo.htm",
|
||||
path => "/path/to/my/template/set"
|
||||
);
|
||||
|
||||
my @files = GT::Template::Inheritance->get_all_paths(
|
||||
file => "foo.htm",
|
||||
path => "/path/to/my/template/set"
|
||||
);
|
||||
|
||||
my @paths = GT::Template::Inheritance->tree(
|
||||
path => "/path/to/my/template/set"
|
||||
);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
GT::Template::Inheritance provides an interface to accessing files for
|
||||
GT::Template template parsing and include handling. It supports following
|
||||
inheritance directories and respects "local" template directories.
|
||||
|
||||
|
||||
=head2 Inheritance
|
||||
|
||||
GT::Template inheritance works by looking for a .tplinfo file in the template
|
||||
directory (or local/.tplinfo, if it exists). In order for the template
|
||||
directory to inherit from another template directory, this file must exist and
|
||||
must evaluate to a hash reference containing an C<inheritance> key. The
|
||||
following is a possible .tplinfo file contents:
|
||||
|
||||
{
|
||||
inheritance => '../other'
|
||||
}
|
||||
|
||||
The above example would indicate that files in this template set can be
|
||||
inherited from the ../other path, relative to the current template set
|
||||
directory. The inheritance directory may also contain a full path.
|
||||
|
||||
=head2 Inheriting from multiple locations
|
||||
|
||||
You may also inherit from multiple locations by using an array reference for
|
||||
the inheritance value:
|
||||
|
||||
{
|
||||
inheritance => ['../other', '/full/path/to/a/third']
|
||||
}
|
||||
|
||||
With the above .tplinfo file, files would be checked for in the current path,
|
||||
then C<../other>, then any of C<../other>'s inherited directories, then in
|
||||
C<third>, then in any of C<third>'s inherited directories.
|
||||
|
||||
Also keep in mind that "local" directories, if they exist, will be checked for
|
||||
the file before each of their respective directories.
|
||||
|
||||
Assuming that the initial template path was C</full/path/one>, and assuming
|
||||
that C<../other> inherited from C<../other2>, the directories checked would be
|
||||
as follows:
|
||||
|
||||
/full/path/one/local
|
||||
/full/path/one
|
||||
/full/path/one/../other/local # i.e. /full/path/other/local
|
||||
/full/path/one/../other # i.e. /full/path/other
|
||||
/full/path/one/../other/../other2/local # i.e. /full/path/other2/local
|
||||
/full/path/one/../other/../other2 # i.e. /full/path/other2
|
||||
/full/path/to/a/third/local
|
||||
/full/path/to/a/third
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
All methods in GT::Template::Inheritance are class methods. Each method takes
|
||||
a hash of options as an argument.
|
||||
|
||||
=head2 get_path
|
||||
|
||||
=head2 get_all_paths
|
||||
|
||||
These methods are used to obtain the location of the file GT::Template will
|
||||
use, taking into account all inherited and "local" template directories. The
|
||||
get_path option will return the path to the file that will be included, while
|
||||
the get_all_paths option returns the path to B<all> copies of the file found in
|
||||
the local/inheritance tree. Both methods take a hash containing the following:
|
||||
|
||||
=over 4
|
||||
|
||||
=item file
|
||||
|
||||
The name of the file desired.
|
||||
|
||||
=item path
|
||||
|
||||
The template directory at which to start looking for the above file. Depending
|
||||
on the existance of "local" directories and template inheritance, more than
|
||||
just this directory will be checked for the file.
|
||||
|
||||
=item local
|
||||
|
||||
Optional. Can be passed with a false value to override the checking of "local"
|
||||
directories for files.
|
||||
|
||||
=item inheritance
|
||||
|
||||
Optional. Can be passed with a false value to override the checking of
|
||||
inheritance directories for files.
|
||||
|
||||
=back
|
||||
|
||||
=head2 tree
|
||||
|
||||
This method returns a list of directories that would be searched for a given
|
||||
file, in the order they would be searched. It takes the C<path>, C<local>, and
|
||||
C<inheritance> options above, but not the C<file> option.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<GT::Template>
|
||||
|
||||
=head1 MAINTAINER
|
||||
|
||||
Jason Rhinelander
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2005 Gossamer Threads Inc. All Rights Reserved.
|
||||
http://www.gossamer-threads.com/
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Revision: $Id: Inheritance.pm,v 1.7 2005/02/09 20:51:27 jagerman Exp $
|
||||
|
||||
=cut
|
Reference in New Issue
Block a user