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