package Text::Xslate::Bridge;
use strict;
use warnings;
use Carp ();
use Text::Xslate::Util qw(p);
my %storage;
sub bridge {
my $class = shift;
while(my($type, $table) = splice @_, 0, 2) {
$storage{$class}{$type} = $table;
}
return;
}
sub export_into_xslate {
my($class, $funcs_ref, @args) = @_;
push @{$funcs_ref}, $class->methods(@args);
return;
}
sub methods {
my($class, %args) = @_;
if(!exists $storage{$class}) {
Carp::croak("$class has no methods (possibly not a bridge class)");
}
if(exists $args{-exclude}) {
my $exclude = $args{-exclude};
my $methods = $class->_functions;
my @export;
if(ref($exclude) eq 'ARRAY') {
$exclude = { map { $_ => 1 } @{$exclude} };
}
if(ref($exclude) eq 'HASH') {
@export = grep { !$exclude->{$_} } keys %{$methods};
}
elsif(ref($exclude) eq 'Regexp'){
@export = grep { $_ !~ $exclude } keys %{$methods};
}
else {
@export = grep { $_ ne $exclude } keys %{$methods};
}
return map { $_ => $methods->{$_} } @export;
}
else {
return %{ $class->_functions };
}
}
sub _functions {
my($class) = @_;
my $st = $storage{$class} ||= {};
my $funcs = $st->{_funcs} ||= {};
# for methods
foreach my $type (qw(scalar hash array)) {
my $table = $st->{$type} || next;
foreach my $name(keys %{$table}) {
$funcs->{$type . '::' . $name} = $table->{$name};
}
}
# for functions
my $table = $st->{function};
foreach my $name(keys %{$table}) {
$funcs->{$name} = $table->{$name};
}
return $funcs;
}
sub dump {
p(\%storage);
}
1;
__END__
=head1 NAME
Text::Xslate::Bridge - The interface base class to import methods
=for test_synopsis my(%nil_methods, %scalar_methods, %array_methods, %hash_methods, %functions);
=head1 SYNOPSIS
package SomeTemplate::Bridge::Xslate;
use parent qw(Text::Xslate::Bridge);
__PACKAGE__->bridge(
nil => \%nil_methods,
scalar => \%scalar_methods,
array => \%array_methods,
hash => \%hash_methods,
function => \%functions,
);
# in your script
use Text::Xslate;
my $tx = Text::Xslate->new(
module => [
'SomeTemplate::Bridge::Xslate'
=> [-exclude => [qw(hash::keys hash::values)]],
],
);
=head1 DESCRIPTION
This module is the base class for adaptor classes.
=head1 INTERFACE
=head2 C<< __PACKAGE__->bridge(@mapping) :Void >>
Install a bridge module that has method I<@mapping>. See C<example/bridge.pl>
for more an example.
=head1 SEE ALSO
L<Text::Xslate>
L<Text::Xslate::Bridge::TT2>
L<Text::Xslate::Bridge::TT2Like>
L<Text::Xslate::Bridge::Alloy>
=cut