File Coverage

blib/lib/DTL/Fast/Tag/Ifchanged.pm
Criterion Covered Total %
statement 78 79 98.7
branch 19 20 95.0
condition 5 5 100.0
subroutine 13 13 100.0
pod 0 8 0.0
total 115 125 92.0


line stmt bran cond sub pod time code
1             package DTL::Fast::Tag::Ifchanged;
2 2     2   1067 use strict; use utf8; use warnings FATAL => 'all';
  2     2   2  
  2     2   55  
  2         10  
  2         2  
  2         9  
  2         51  
  2         3  
  2         72  
3 2     2   8 use parent 'DTL::Fast::Tag';
  2         3  
  2         9  
4              
5             $DTL::Fast::TAG_HANDLERS{'ifchanged'} = __PACKAGE__;
6              
7 2     2   525 use DTL::Fast::Expression::Operator::Binary::Eq;
  2         3  
  2         1535  
8              
9             #@Override
10 8     8 0 15 sub get_close_tag{ return 'endifchanged'; }
11              
12             #@Override
13             sub parse_parameters
14             {
15 8     8 0 8 my $self = shift;
16              
17 8         13 $self->add_branch();
18              
19 8 100       11 if ( $self->{'parameter'})
20             {
21 5         18 $self->{'watches'} = $self->parse_sources($self->{'parameter'});
22             }
23             else
24             {
25 3         5 $self->{'watch_content'} = 1;
26             }
27              
28 8         9 return $self;
29             }
30              
31              
32             #@Override
33             sub add_chunk
34             {
35 34     34 0 20 my $self = shift;
36 34         24 my $chunk = shift;
37              
38 34         53 $self->{'branches'}->[-1]->add_chunk($chunk);
39              
40 34         45 return $self;
41             }
42              
43             #@Override
44             sub parse_tag_chunk
45             {
46 12     12 0 18 my( $self, $tag_name, $tag_param, $chunk_lines ) = @_;
47              
48 12         12 my $result = undef;
49              
50 12 100       15 if( $tag_name eq 'else' )
51             {
52 4         7 $self->add_branch();
53 4         5 $DTL::Fast::Template::CURRENT_TEMPLATE_LINE += $chunk_lines;
54             }
55             else
56             {
57 8         17 $result = $self->SUPER::parse_tag_chunk($tag_name, $tag_param, $chunk_lines);
58             }
59              
60 12         15 return $result;
61             }
62              
63             #@Override
64             sub render
65             {
66 71     71 0 43 my $self = shift;
67 71         51 my $context = shift;
68 71         51 my $result = '';
69              
70 71         64 my $forloop = $context->{'ns'}->[-1]->{'forloop'};
71              
72 71 50       90 if( defined $forloop )
73             {
74 71 100       78 if( $self->{'watch_content'} ) # slow behavior
75             {
76 27         45 $result = $self->{'branches'}->[0]->render($context);
77 27 100 100     83 if(
    100          
78             $forloop->{'first'} # first pass
79             or $result ne $self->{'last_iteration_content'} # content changed
80             )
81             {
82 9         9 $self->{'last_iteration_content'} = $result;
83             }
84 18         24 elsif( scalar @{$self->{'branches'}} > 1 )
85             {
86 9         15 $result = $self->{'branches'}->[1]->render($context);
87             }
88             else
89             {
90 9         9 $result = '';
91             }
92             }
93             else
94             {
95 44 100       49 if( $forloop->{'first'} ) # first pass
96             {
97 5         10 $self->update_preserved($context);
98 5         17 $result = $self->{'branches'}->[0]->render($context);
99             }
100             else
101             {
102 39 100       42 if( $self->watches_changed($context) )
    100          
103             {
104 14         29 $result = $self->{'branches'}->[0]->render($context);
105 14         21 $self->update_preserved($context);
106             }
107 25         42 elsif( scalar @{$self->{'branches'}} > 1 )
108             {
109 9         20 $result = $self->{'branches'}->[1]->render($context);
110             }
111             }
112             }
113             }
114             else
115             {
116 0         0 warn "ifchanged tag can be rendered only inside for loop";
117             }
118              
119 71         176 return $result;
120             }
121              
122             sub watches_changed
123             {
124 39     39 0 27 my $self = shift;
125 39         28 my $context = shift;
126 39         25 my $result = 0;
127              
128 39         33 for( my $i = 0; $i < scalar @{$self->{'watches'}}; $i++ )
  64         93  
129             {
130 39         64 my $watch = $self->{'watches'}->[$i]->render($context);
131 39         35 my $preserve = $self->{'preserved'}->[$i];
132              
133 39 100       55 if( not DTL::Fast::Expression::Operator::Binary::Eq::dispatch($self, $watch, $preserve))
134             {
135 14         14 $result = 1;
136 14         14 last;
137             }
138             }
139 39         58 return $result;
140             }
141              
142              
143             sub update_preserved
144             {
145 19     19 0 12 my $self = shift;
146 19         15 my $context = shift;
147              
148 19         21 $self->{'preserved'} = [];
149            
150 19         18 foreach my $watch ( @{$self->{'watches'}} )
  19         24  
151             {
152 19         15 push @{$self->{'preserved'}}, $watch->render($context);
  19         38  
153             }
154              
155 19         21 return $self;
156             }
157              
158             sub add_branch
159             {
160 12     12 0 11 my $self = shift;
161              
162 12   100     38 $self->{'branches'} //= [];
163 12         7 push @{$self->{'branches'}}, DTL::Fast::Renderer->new();
  12         31  
164 12         10 return $self;
165             }
166              
167             1;