File Coverage

blib/lib/DTL/Fast/Template.pm
Criterion Covered Total %
statement 95 98 96.9
branch 17 20 85.0
condition 9 13 69.2
subroutine 14 14 100.0
pod 0 4 0.0
total 135 149 90.6


line stmt bran cond sub pod time code
1             package DTL::Fast::Template;
2 98     98   66384 use parent 'DTL::Fast::Parser';
  98         30017  
  98         570  
3 98     98   5099 use strict;
  98         208  
  98         2094  
4 98     98   513 use utf8;
  98         194  
  98         385  
5 98     98   2493 use warnings FATAL => 'all';
  98         174  
  98         3482  
6              
7 98     98   482 use DTL::Fast qw(get_template);
  98         214  
  98         4368  
8 98     98   569 use DTL::Fast::Context;
  98         192  
  98         2269  
9 98     98   53432 use DTL::Fast::Tags;
  98         270  
  98         3161  
10 98     98   52363 use DTL::Fast::Filters;
  98         262  
  98         3233  
11 98     98   571 use Scalar::Util qw/weaken/;
  98         179  
  98         114161  
12              
13             our $CURRENT_TEMPLATE; # global variable for linking modules
14             our $CURRENT_TEMPLATE_LINE; # global variable for source line number
15              
16             #@Override
17             sub new
18             {
19 962     962 0 222949 my( $proto, $template, %kwargs ) = @_;
20 962   50     2642 $template //= '';
21              
22 962         2426 $kwargs{'raw_chunks'} = _get_raw_chunks($template);
23 962   100     4882 $kwargs{'dirs'} //= []; # optional dirs to look up for includes or parents
24 962   100     4113 $kwargs{'file_path'} //= 'inline';
25 962         2185 $kwargs{'perl'} = $];
26 962         1837 $kwargs{'blocks'} = {};
27 962   50     5030 $kwargs{'modules'} //= {
28             'DTL::Fast' => $DTL::Fast::VERSION,
29             };
30            
31 962         5600 my $self = $proto->SUPER::new(%kwargs);
32            
33 946         4378 return $self;
34             }
35              
36             #@Override self-linking
37             sub remember_template
38             {
39 962     962 0 1563 my ($self) = @_;
40            
41 962         2260 $self->{'_template'} = $self;
42 962         1603 $self->{'_template_line'} = 1;
43 962         3062 weaken $self->{'_template'};
44              
45 962         2104 return $self;
46             }
47              
48             #@Override
49             sub parse_chunks
50             {
51 962     962 0 1493 my( $self ) = @_;
52            
53 962         1625 my( $current_template_backup, $current_template_line_backup ) = ($CURRENT_TEMPLATE, $CURRENT_TEMPLATE_LINE);
54 962         1534 ($CURRENT_TEMPLATE, $CURRENT_TEMPLATE_LINE) = ($self, 1);
55            
56 962         3122 $self->SUPER::parse_chunks();
57            
58 946         1607 ($CURRENT_TEMPLATE, $CURRENT_TEMPLATE_LINE) = ($current_template_backup, $current_template_line_backup);
59 946         2228 return $self;
60             }
61              
62             my $reg = qr/(
63             \{\#.+?\#\}
64             |\{\%.+?\%\}
65             |\{\{.+?\}\}
66             )/xs;
67              
68             sub _get_raw_chunks
69             {
70 962     962   1489 my( $template ) = @_;
71              
72 962         13082 my $result = [split $reg, $template];
73            
74 962         3417 return $result;
75             }
76              
77             #@Override
78             sub render
79             {
80 2336     2336 0 17674 my( $self, $context ) = @_;
81              
82 2336   100     6094 $context //= {};
83            
84 2336 100 33     14823 if( ref $context eq 'HASH' )
    50          
85             {
86 38         209 $context = DTL::Fast::Context->new($context);
87             }
88             elsif(
89             defined $context
90             and ref $context ne 'DTL::Fast::Context'
91             )
92             {
93 0         0 die "Context must be a DTL::Fast::Context object or a HASH reference";
94             }
95            
96 2336         7288 $context->push_scope();
97            
98 2336 100       6049 $context->{'ns'}->[-1]->{'_dtl_ssi_dirs'} = $self->{'ssi_dirs'} if $self->{'ssi_dirs'};
99 2336 100       5389 $context->{'ns'}->[-1]->{'_dtl_url_source'} = $self->{'url_source'} if $self->{'url_source'};
100              
101 2336         3986 my $template_path = $self->{'file_path'};
102              
103 2336 100       5913 if( not exists $context->{'ns'}->[-1]->{'_dtl_include_path'} ) # entry point
104             {
105 2313         5127 $context->{'ns'}->[-1]->{'_dtl_include_path'} = [];
106 2313         5314 $context->{'ns'}->[-1]->{'_dtl_include_files'} = {};
107             }
108             else # check for recursion, shouldn't this be in the include tag?
109             {
110 23 100       76 if( exists $context->{'ns'}->[-1]->{'_dtl_include_files'}->{$template_path} )
111             {
112             # recursive inclusion
113             die sprintf("Recursive inclusion detected:\n%s\n"
114 3         7 , join( "\n includes ", @{$context->{'ns'}->[-1]->{'_dtl_include_path'}}, $template_path)
  3         37  
115             );
116             }
117             }
118            
119 2333         6164 $context->{'ns'}->[-1]->{'_dtl_include_files'}->{$template_path} = 1;
120 2333         2991 push @{$context->{'ns'}->[-1]->{'_dtl_include_path'}}, $template_path;
  2333         6244  
121            
122 2333         3049 my $result;
123 2333 100       5150 if ( $self->{'extends'} ) # has parent template
124             {
125 11         19 my @descendants = ();
126 11         15 my $current_descendant = $self;
127 11         19 my %inheritance = ();
128            
129 11         29 while( $current_descendant->{'extends'} )
130             {
131 18         27 push @descendants, $current_descendant;
132 18         43 $inheritance{$current_descendant->{'file_path'}} = 1;
133            
134 18         63 my $parent_template_name = $current_descendant->{'extends'}->render($context);
135            
136             die sprintf(
137             "Unable to resolve parent template name for %s"
138 18 50       43 , $current_descendant->{'file_path'}
139             ) if not $parent_template_name;
140            
141             $current_descendant = get_template(
142             $parent_template_name
143 18         52 , 'dirs' => $self->{'dirs'}
144             );
145            
146 17 50       35 if ( defined $current_descendant )
147             {
148 17 100       66 if ( $inheritance{$current_descendant->{'file_path'}} )
149             {
150             die sprintf(
151             "Recursive inheritance detected:\n%s\n"
152             , join(
153             "\n inherited from ",
154 4         20 (map {$_->{'file_path'}} @descendants),
155 1         3 $current_descendant->{'file_path'}
156             )
157             );
158             }
159             }
160             else
161             {
162             die sprintf( "Couldn't found a parent template: %s in one of the following directories: %s"
163             , $parent_template_name
164 0         0 , join( ', ', @{$self->{'dirs'}})
  0         0  
165             );
166             }
167             }
168            
169 9         14 push @descendants, $current_descendant;
170 9         20 $context->{'ns'}->[-1]->{'_dtl_descendants'} = \@descendants;
171 9         18 $context->{'ns'}->[-1]->{'_dtl_rendering_template'} = $current_descendant;
172 9         26 $result = $current_descendant->SUPER::render($context);
173              
174             }
175             else
176             {
177 2322         3815 delete $context->{'ns'}->[-1]->{'_dtl_descendants'};
178 2322         4365 $context->{'ns'}->[-1]->{'_dtl_rendering_template'} = $self;
179 2322         7463 $result = $self->SUPER::render($context);
180             }
181            
182 2312         3201 pop @{$context->{'ns'}->[-1]->{'_dtl_include_path'}};
  2312         5277  
183 2312         5707 delete $context->{'ns'}->[-1]->{'_dtl_include_files'}->{$template_path};
184            
185 2312         6777 $context->pop_scope();
186            
187 2312         9150 return $result;
188             }
189              
190             1;