File Coverage

blib/lib/Template/Extract/Run.pm
Criterion Covered Total %
statement 71 71 100.0
branch 27 34 79.4
condition 19 27 70.3
subroutine 12 12 100.0
pod 2 2 100.0
total 131 146 89.7


line stmt bran cond sub pod time code
1             package Template::Extract::Run;
2             $Template::Extract::Run::VERSION = '0.50';
3 2     2   197791 use strict;
  2         4  
  2         109  
4 2     2   11 use warnings;
  2         3  
  2         150  
5 2     2   37 use 5.006;
  2         6  
6              
7             our ($DEBUG);
8             my ( %loop, $cur_loop, $data );
9              
10             sub new {
11 14     14 1 33 my $class = shift;
12 14         30 my $self = {};
13 14         77 return bless( $self, $class );
14             }
15              
16             sub run {
17 13     13 1 40 my ( $self, $regex, $document, $ext_data ) = @_;
18              
19 13         47 $self->_init($ext_data);
20             ## no critic
21              
22 13 50       53 defined($document) or return undef;
23 13 50       30 defined($regex) or return undef;
24              
25             {
26 2     2   55 use re 'eval';
  2         6  
  2         1912  
  13         24  
27 13 100       3632 return $data if $document =~ /$regex/s;
28             }
29              
30 1         38 return undef;
31             }
32              
33             # initialize temporary variables
34             sub _init {
35 13     13   44 %loop = ();
36 13         44 $cur_loop = undef;
37 13   100     72 $data = $_[1] || {};
38             }
39              
40             sub _enter_loop {
41 16   100 16   137 $cur_loop = $loop{ $_[1] } ||= {
42             name => $_[0],
43             id => $_[1],
44             count => -1,
45             };
46 16         36 $cur_loop->{count}++;
47 16         41 $cur_loop->{var} = {};
48 16         601 $cur_loop->{pos} = {};
49             }
50              
51             sub _leave_loop {
52 225     225   418 my ( $obj, $key, $vars ) = @_;
53              
54 225 50       595 ref($obj) eq 'HASH' or return;
55 225         357 my $old;
56 225 100       531 if (exists $obj->{$key}) {
57 105         175 $old = $obj->{$key};
58             }
59 225 100       4513 ref($old) eq 'ARRAY' or return;
60              
61 105 50       212 print "Validate: [$old $key @$vars]\n" if $DEBUG;
62              
63 105         187 my @new;
64              
65             OUTER:
66 105         189 foreach my $entry (@$old) {
67 264 100       606 next unless %$entry;
68 145         259 foreach my $var (@$vars) {
69              
70             # If it's a foreach, it needs to not match or match something.
71 542 100       929 if ( ref($var) ) {
72 7 50 66     24 next if !exists( $entry->{$$var} ) or @{ $entry->{$$var} };
  6         30  
73             }
74             else {
75 535 100       1321 next if exists( $entry->{$var} );
76             }
77 2         8 next OUTER; # failed!
78             }
79 143         271 push @new, $entry;
80             }
81              
82 105 100       3872 delete $_[0]{$key} unless @$old = @new;
83             }
84              
85             sub _adjust {
86 330     330   688 my ( $obj, $val ) = ( shift, pop );
87              
88 330         667 foreach my $var (@_) {
89 12   50     66 $obj = $obj->{$var} ||= {};
90             }
91 330         760 return ( $obj, $val );
92             }
93              
94             sub _traverse {
95 175     175   385 my ( $obj, $val ) = ( shift, shift );
96              
97 175         267 my $depth = -1;
98 175         443 while ( my $id = pop(@_) ) {
99 29         88 my $var = $loop{$id}{name};
100 29   33     116 my $index = $loop{ $_[-1] || $val }{count};
101 29   100     124 $obj = $obj->{$var}[$index] ||= {};
102             }
103 175         827 return $obj;
104             }
105              
106             sub _ext {
107 330     330   967 my ( $var, $val, $num ) = splice( @_, 0, 3 );
108 330         518 my $obj = $data;
109              
110 330 100       777 if (@_) {
111 175 50 66     620 print "Ext: [ $$val with $num on $-[$num]]\n" if ref($val) and $DEBUG;
112              
113             # fetch current loop structure
114 175         362 my $cur = $loop{ $_[0] };
115              
116             # if pos() changed, increment the iteration counter
117             $cur->{var}{$num}++
118 175 50 100     1142 if ( ( $cur->{pos}{$num} ||= -1 ) != $-[$num] )
      33        
      66        
119             or ref $val and $$val eq 'leave_loop';
120              
121             # remember pos()
122 175         509 $cur->{pos}{$num} = $-[$num];
123              
124 175         375 my $iteration = $cur->{var}{$num} - 1;
125 175   100     422 $obj = _traverse( $data, @_ )->{ $cur->{name} }[$iteration] ||= {};
126             }
127              
128 330         871 ( $obj, $var ) = _adjust( $obj, @$var );
129              
130 330 100       881 if ( !ref($val) ) {
    100          
131 100         3249 $obj->{$var} = $val;
132             }
133             elsif ( $$val eq 'leave_loop' ) {
134 225         473 _leave_loop( $obj, @$var );
135             }
136             else {
137 5         194 $obj->{$var} = $$$val;
138             }
139             }
140              
141             1;
142              
143             __END__