File::Find::Rule::TTMETA - Find files based on Template Toolkit META directives


File-Find-Rule-TTMETA documentation Contained in the File-Find-Rule-TTMETA distribution.

Index


Code Index:

NAME

Top

File::Find::Rule::TTMETA - Find files based on Template Toolkit META directives

SYNOPSIS

Top

    use File::Find::Rule qw(:TTMETA);

    my @files = find(ttmeta => { author => "darren chamberlain" },
                     in => "/var/www/html");

DESCRIPTION

Top

File::Find::Rule::TTMETA extends File::Find::Rule to work with Template Toolkit templates by providing access to template-specific metadata.

File::Find::Rule::TTMETA adds a ttmeta method / keyword to File::Find::Rule. ttmeta takes a series of name, value tuples, each of which is compared to the metadata for the file in question (a Template::Provider instance attempts to treat each file as a template; compile errors are silently skipped). A file matches if each element of metadata defined in ttmeta is present. If there are multiple keys defined, all must match for the file to be considered a match.

Values can be strings or regexes:

    find(ttmeta => { VERSION => qr/^2\.\d+/ } => in => $dir);

    File::Find::Rule->file
                    ->ttmeta(color => "green", sheep => 3)
                    ->in($dir);

More complex variables are not (currently) supported by this module, even though Template::Document supports them. Patches welcome.

Template Toolkit DETAILS

Top

File::Find::Rule::TTMETA uses Template::Config to instantiate its Template::Provider instance, so it is possible to use custom provider subclasses.

The Template::Provider instance that is created has only ABSOLUTE => 1 set, mainly because most of the other options don't really apply here, but also because I can't think of an elegant way to pass configuration parameters to the constructor.

SEE ALSO

Top

File::Find::Rule, Template


File-Find-Rule-TTMETA documentation Contained in the File-Find-Rule-TTMETA distribution.

package File::Find::Rule::TTMETA;

use strict;
use vars qw($VERSION);
use base qw(File::Find::Rule);

use Template::Config;

my $provider;

sub File::Find::Rule::ttmeta {
    my $self = shift->_force_object();
    my $meta = UNIVERSAL::isa($_[0], 'HASH') ? shift : { @_ };

    $self->exec(
        sub {
            my $file = shift;
            my ($doc, $match, $key);
            $match = 0;

            # Optimization
            return $match
                if scalar keys %$meta == 0;

            # warn " *** $file ***\n";

            # Skip directories
            return if -d $file;

            # Set $provider to a Template::Provider instance or workalike
            # $file contains an absolute path
            $provider = Template::Config->provider(ABSOLUTE => 1)
                unless defined $provider;

            # Attempt to turn the file into a Template::Document instance,
            # or return -- it can't match if it isn't a valid Template.
            eval { ($doc) = $provider->fetch($file); };
            return if $@;

            # Bad Things Happened.  Next!
            return unless defined $doc &&
                UNIVERSAL::isa($doc, 'Template::Document');

            # The intent is to match all of the possibilities;
            # if someone specifies:
            #
            #   find(ttmeta => { AUTHOR => 'foo', VERSION => '1.1' })
            #
            # then we only want to return success if all match.
            #
            # To support complex (TT-style foo.bar) variables, $key 
            # would need to be split on /\./, and each element treated
            # as either a hash or array entry.  This reimplementing of
            # Template::Stash::_dotop bugs me, though.
            for $key (keys %$meta) {
                my $val = $meta->{$key};

                if (ref $val eq 'Regexp') {
                    $match++ if $doc->$key() =~ $val;
                }
                else {
                    $match++ if $doc->$key() eq $val;
                }
            }

            return $match == scalar keys %$meta;
        }
    );
}

1;

__END__