File Coverage

blib/lib/Template/Extract/Run.pm
Criterion Covered Total %
statement 70 70 100.0
branch 27 34 79.4
condition 19 27 70.3
subroutine 12 12 100.0
pod 2 2 100.0
total 130 145 89.6


line stmt bran cond sub pod time code
1             package Template::Extract::Run;
2             $Template::Extract::Run::VERSION = '0.41';
3              
4 1     1   15 use 5.006;
  1         3  
  1         28  
5 1     1   4 use strict;
  1         2  
  1         22  
6 1     1   5 use warnings;
  1         1  
  1         100  
7              
8             our ($DEBUG);
9             my ( %loop, $cur_loop, $data );
10              
11             sub new {
12 13     13 1 26 my $class = shift;
13 13         22 my $self = {};
14 13         93 return bless( $self, $class );
15             }
16              
17             sub run {
18 12     12 1 29 my ( $self, $regex, $document, $ext_data ) = @_;
19              
20 12         37 $self->_init($ext_data);
21              
22 12 50       38 defined($document) or return undef;
23 12 50       28 defined($regex) or return undef;
24              
25             {
26 1     1   5 use re 'eval';
  1         1  
  1         704  
  12         20  
27 12 100       4367 return $data if $document =~ /$regex/s;
28             }
29              
30 1         5 return undef;
31             }
32              
33             # initialize temporary variables
34             sub _init {
35 12     12   49 %loop = ();
36 12         19 $cur_loop = undef;
37 12   100     99 $data = $_[1] || {};
38             }
39              
40             sub _enter_loop {
41 16   100 16   136 $cur_loop = $loop{ $_[1] } ||= {
42             name => $_[0],
43             id => $_[1],
44             count => -1,
45             };
46 16         26 $cur_loop->{count}++;
47 16         31 $cur_loop->{var} = {};
48 16         434 $cur_loop->{pos} = {};
49             }
50              
51             sub _leave_loop {
52 225     225   277 my ( $obj, $key, $vars ) = @_;
53              
54 225 50       452 ref($obj) eq 'HASH' or return;
55 225 100       461 my $old = $obj->{$key} if exists $obj->{$key};
56 225 100       3748 ref($old) eq 'ARRAY' or return;
57              
58 105 50       193 print "Validate: [$old $key @$vars]\n" if $DEBUG;
59              
60 105         119 my @new;
61              
62             OUTER:
63 105         183 foreach my $entry (@$old) {
64 264 100       437 next unless %$entry;
65 145         184 foreach my $var (@$vars) {
66              
67             # If it's a foreach, it needs to not match or match something.
68 542 100       788 if ( ref($var) ) {
69 7 50 66     25 next if !exists( $entry->{$$var} ) or @{ $entry->{$$var} };
  6         28  
70             }
71             else {
72 535 100       1374 next if exists( $entry->{$var} );
73             }
74 2         5 next OUTER; # failed!
75             }
76 143         299 push @new, $entry;
77             }
78              
79 105 100       3400 delete $_[0]{$key} unless @$old = @new;
80             }
81              
82             sub _adjust {
83 323     323   465 my ( $obj, $val ) = ( shift, pop );
84              
85 323         566 foreach my $var (@_) {
86 11   50     95 $obj = $obj->{$var} ||= {};
87             }
88 323         938 return ( $obj, $val );
89             }
90              
91             sub _traverse {
92 175     175   235 my ( $obj, $val ) = ( shift, shift );
93              
94 175         169 my $depth = -1;
95 175         383 while ( my $id = pop(@_) ) {
96 29         49 my $var = $loop{$id}{name};
97 29   33     112 my $index = $loop{ $_[-1] || $val }{count};
98 29   100     135 $obj = $obj->{$var}[$index] ||= {};
99             }
100 175         836 return $obj;
101             }
102              
103             sub _ext {
104 323     323   669 my ( $var, $val, $num ) = splice( @_, 0, 3 );
105 323         499 my $obj = $data;
106              
107 323 100       818 if (@_) {
108 175 50 66     489 print "Ext: [ $$val with $num on $-[$num]]\n" if ref($val) and $DEBUG;
109              
110             # fetch current loop structure
111 175         238 my $cur = $loop{ $_[0] };
112              
113             # if pos() changed, increment the iteration counter
114 175 50 100     1003 $cur->{var}{$num}++
      33        
      66        
115             if ( ( $cur->{pos}{$num} ||= -1 ) != $-[$num] )
116             or ref $val and $$val eq 'leave_loop';
117              
118             # remember pos()
119 175         483 $cur->{pos}{$num} = $-[$num];
120              
121 175         299 my $iteration = $cur->{var}{$num} - 1;
122 175   100     310 $obj = _traverse( $data, @_ )->{ $cur->{name} }[$iteration] ||= {};
123             }
124              
125 323         644 ( $obj, $var ) = _adjust( $obj, @$var );
126              
127 323 100       916 if ( !ref($val) ) {
    100          
128 93         3176 $obj->{$var} = $val;
129             }
130             elsif ( $$val eq 'leave_loop' ) {
131 225         442 _leave_loop( $obj, @$var );
132             }
133             else {
134 5         132 $obj->{$var} = $$$val;
135             }
136             }
137              
138             1;
139              
140             __END__