File Coverage

blib/lib/Template/Plugin/ArrayRef.pm
Criterion Covered Total %
statement 45 47 95.7
branch 5 10 50.0
condition n/a
subroutine 11 11 100.0
pod 2 3 66.6
total 63 71 88.7


line stmt bran cond sub pod time code
1             package Template::Plugin::ArrayRef;
2 2     2   145423 use base 'Template::Plugin';
  2         6  
  2         2025  
3 2     2   8045 use strict;
  2         4  
  2         59  
4 2     2   13 use warnings;
  2         9  
  2         50  
5 2     2   1020 use Template::Exception;
  2         4316  
  2         54  
6 2     2   15 use Scalar::Util qw();
  2         4  
  2         1316  
7              
8             our $VERSION = 0.11;
9             our $MONAD = 'Template::Monad::ArrayRef';
10             our $EXCEPTION = 'Template::Exception';
11             our $AUTOLOAD;
12              
13             sub load {
14 12     12 1 139986 my $class = shift;
15 12         34 my $context = shift;
16              
17             # define .arrayref vmethods for hash and list objects
18 12         71 $context->define_vmethod( hash => arrayref => \&arrayref_monad );
19 12         347 $context->define_vmethod( list => arrayref => \&arrayref_monad );
20              
21 12         235 return $class;
22             }
23              
24             sub arrayref_monad {
25             # create a .arrayref monad which wraps the hash- or list-based object
26             # and delegates any method calls back to it, calling them in scalar
27             # context, e.g. foo.arrayref.bar becomes $MONAD->new($foo)->bar and
28             # the monad calls $foo->bar in array context
29 3     3 0 443 $MONAD->new(shift);
30             }
31              
32             sub new {
33 12     12 1 241 my ($class, $context, @args) = @_;
34             # create a scalar plugin object which will lookup a variable subroutine
35             # and call it. e.g. arrayref.foo results in a call to foo() in array context
36 12         73 my $self = bless {
37             _CONTEXT => $context,
38             }, $class;
39 12         42 return $self;
40             }
41              
42             sub AUTOLOAD {
43 3     3   467 my $self = shift;
44 3         7 my $item = $AUTOLOAD;
45 3         20 $item =~ s/.*:://;
46 3 50       15 return if $item eq 'DESTROY';
47            
48             # lookup the named values
49 3         21 my $stash = $self->{ _CONTEXT }->stash;
50 3         15 my $value = $stash->{ $item };
51              
52 3 50       21 if (! defined $value) {
    50          
53 0         0 die $EXCEPTION->new( arrayref => "undefined value for arrayref call: $item" );
54             }
55             elsif (ref $value eq 'CODE') {
56 3         15 $value = [ $value->(@_) ];
57             }
58 3         42 return $value;
59             }
60              
61              
62             package Template::Monad::ArrayRef;
63              
64             our $EXCEPTION = 'Template::Exception';
65             our $AUTOLOAD;
66              
67             sub new {
68 3     3   8 my ($class, $this) = @_;
69 3         61 bless \$this, $class;
70             }
71              
72             sub AUTOLOAD {
73 3     3   8 my $self = shift;
74 3         10 my $this = $$self;
75 3         7 my $item = $AUTOLOAD;
76 3         15 $item =~ s/.*:://;
77 3 50       19 return if $item eq 'DESTROY';
78              
79 3         6 my $method;
80 3 50       15 if (Scalar::Util::blessed($this)) {
81             # lookup the method...
82 3         18 $method = $this->can($item);
83             }
84             else {
85 0         0 die $EXCEPTION->new( arrayref => "invalid object method: $item" );
86             }
87              
88             # ...and call it in array context
89 3         15 my @results = $method->($this, @_);
90 3         39 return \@results;
91             }
92              
93             1;
94              
95             __END__