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