File Coverage

blib/lib/Template/Liquid/Tag/Cycle.pm
Criterion Covered Total %
statement 34 35 97.1
branch 13 18 72.2
condition 5 9 55.5
subroutine 6 6 100.0
pod 0 2 0.0
total 58 70 82.8


line stmt bran cond sub pod time code
1             our $VERSION = '1.0.21';
2             use strict;
3 24     24   125 use warnings;
  24         41  
  24         564  
4 24     24   97 require Template::Liquid::Error;
  24         40  
  24         692  
5             require Template::Liquid::Utility;
6             use base 'Template::Liquid::Tag';
7 24     24   115  
  24         39  
  24         13835  
8 24     24   85 my ($class, $args) = @_;
9             raise Template::Liquid::Error {type => 'Context',
10             template => $args->{template},
11 17     17 0 30 message => 'Missing template argument',
12             fatal => 1
13             }
14             if !defined $args->{'template'};
15             raise Template::Liquid::Error {type => 'Context',
16             template => $args->{template},
17 17 50       29 message => 'Missing parent argument',
18             fatal => 1
19             }
20             if !defined $args->{'parent'};
21             raise Template::Liquid::Error {
22             type => 'Syntax',
23 17 50       33 template => $args->{template},
24             message => 'Missing argument list in ' . $args->{'markup'},
25             fatal => 1
26             }
27             if !defined $args->{'attrs'} || $args->{'attrs'} !~ m[\S$]o;
28             my ($name, $s);
29             if ($args->{'attrs'} =~ m[^\s*(.+?)\s*\:\s*(.*)$]o) { # Named syntax
30 17 50 33     67 ($name, $args->{'attrs'}) = ($1, $2);
31 17         21 $name = $2 if $name =~ m[^(['"])(.+)\1$];
32 17 100       133 }
    50          
33 11         30 elsif ($args->{'attrs'} =~ m[^(.+)$]o) { # Simple syntax
34 11 100       40 $name = $args->{'attrs'};
35             }
36             else {
37 6         15 raise Template::Liquid::Error {
38             template => $s->{template},
39             type => 'Syntax',
40             message =>
41             sprintf(
42             q[Syntax Error in '%s %s' - Valid syntax: cycle [name :] var [, var2, var3 ...]],
43             $args->{'tag_name'}, $args->{'attrs'}
44             ),
45             fatal => 1
46 0         0 };
47             }
48              
49             #$name = $args->{'tag_name'} . '-' . $name;
50             # XXX - Cycle objects are stored in Template::Liquid::Document objects
51             if (defined $args->{'template'}{document}->{'_CYCLES'}{$name}) {
52             $s = $args->{'template'}{document}->{'_CYCLES'}{$name};
53             }
54 17 100       39 else {
55 7         10 my @list
56             = grep { defined $_ }
57             $args->{'attrs'}
58             =~ m[$Template::Liquid::Utility::VariableFilterArgumentParser]g;
59 90         134 $s = bless {name => $name,
60 10         77 blocks => [],
61             tag_name => $args->{'tag_name'},
62             list => \@list,
63             template => $args->{'template'},
64             parent => $args->{'parent'},
65             markup => $args->{'markup'},
66             position => 0
67             }, $class;
68 10         53 $args->{'template'}{document}->{'_CYCLES'}{$name} = $s;
69             }
70             return $s;
71 10         67 }
72              
73 17         35 my ($s) = @_;
74             my $name = $s->{template}{context}->get($s->{'name'}) || $s->{'name'};
75             $s = $s->{template}{document}->{'_CYCLES'}{$name} || $s;
76             my $node = $s->{'list'}[$s->{'position'}++];
77 28     28 0 43 my $return
78 28   66     61 = ref $node ? $node->render() : $s->{template}{context}->get($node);
79 28   66     78 $s->{'position'} = 0 if $s->{'position'} >= scalar @{$s->{'list'}};
80 28         47 return $return;
81             }
82 28 50       62 1;
83 28 100       43  
  28         55  
84 28         55 =pod
85              
86             =encoding UTF-8
87              
88             =begin stopwords
89              
90             Lütke jadedPixel
91              
92             =end stopwords
93              
94             =head1 NAME
95              
96             Template::Liquid::Tag::Cycle - Document-level Persistant Lists
97              
98             =head1 Description
99              
100             Often you have to alternate between different colors or similar tasks.
101             L<Template::Liquid|Template::Liquid> has built-in support for such operations,
102             using the C<cycle> tag.
103              
104             =head1 Synopsis
105              
106             {% cycle 'one', 'two', 'three' %}
107             {% cycle 'one', 'two', 'three' %}
108             {% cycle 'one', 'two', 'three' %}
109             {% cycle 'one', 'two', 'three' %}
110              
111             ...will result in...
112              
113             one
114             two
115             three
116             one
117              
118             If no name is supplied for the cycle group, then it’s assumed that multiple
119             calls with the same parameters are one group.
120              
121             If you want to have total control over cycle groups, you can optionally specify
122             the name of the group. This can even be a variable.
123              
124             {% cycle 'group 1': 'one', 'two', 'three' %}
125             {% cycle 'group 1': 'one', 'two', 'three' %}
126             {% cycle 'group 2': 'one', 'two', 'three' %}
127             {% cycle 'group 2': 'one', 'two', 'three' %}
128              
129             ...will result in...
130              
131             one
132             two
133             one
134             two
135              
136             =head1 Notes
137              
138             The cycle tag is the only one which retains state between calls to render For a
139             particular document. So...
140              
141             use Template::Liquid;
142             my $solution = Template::Liquid->parse(<<'TEMPLATE');
143             {% cycle 'group 1': 'one', 'two', 'three' %}
144             {% cycle 'group 2': 'one', 'two', 'three' %}
145             {% cycle 'group 1': 'one', 'two', 'three' %}
146             TEMPLATE
147             print $solution->render() for 1..3;
148              
149             ...would print...
150              
151             one
152             one
153             two
154             three
155             two
156             one
157             two
158             three
159             three
160              
161             ...rather than...
162              
163             one
164             one
165             two
166             one
167             one
168             two
169             one
170             one
171             two
172              
173             ...which is what would happen if the state was reset after every render.
174              
175             Remember than state is held for each document so...
176              
177             use Template::Liquid;
178             my $solution_a = Template::Liquid->parse(<<'TEMPLATE');
179             {% cycle 'group 1': 'one', 'two', 'three' %}
180             {% cycle 'group 2': 'one', 'two', 'three' %}
181             {% cycle 'group 1': 'one', 'two', 'three' %}
182             TEMPLATE
183             my $solution_b = Template::Liquid->parse(<<'TEMPLATE');
184             {% cycle 'group 1': 'one', 'two', 'three' %}
185             {% cycle 'group 2': 'one', 'two', 'three' %}
186             {% cycle 'group 1': 'one', 'two', 'three' %}
187             TEMPLATE
188             my $solution_c = Template::Liquid->parse(<<'TEMPLATE');
189             {% cycle 'group 1': 'one', 'two', 'three' %}
190             {% cycle 'group 2': 'one', 'two', 'three' %}
191             {% cycle 'group 1': 'one', 'two', 'three' %}
192             TEMPLATE
193              
194             print $solution_a->render();
195             print $solution_b->render();
196             print $solution_c->render();
197              
198             ...would print...
199              
200             one
201             one
202             two
203             one
204             one
205             two
206             one
207             one
208             two
209              
210             =head1 See Also
211              
212             Liquid for Designers: http://wiki.github.com/tobi/liquid/liquid-for-designers
213              
214             =head1 Author
215              
216             Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
217              
218             The original Liquid template system was developed by jadedPixel
219             (http://jadedpixel.com/) and Tobias Lütke (http://blog.leetsoft.com/).
220              
221             =head1 License and Legal
222              
223             Copyright (C) 2009-2022 by Sanko Robinson E<lt>sanko@cpan.orgE<gt>
224              
225             This program is free software; you can redistribute it and/or modify it under
226             the terms of The Artistic License 2.0. See the F<LICENSE> file included with
227             this distribution or http://www.perlfoundation.org/artistic_license_2_0. For
228             clarification, see http://www.perlfoundation.org/artistic_2_0_notes.
229              
230             When separated from the distribution, all original POD documentation is covered
231             by the Creative Commons Attribution-Share Alike 3.0 License. See
232             http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For clarification,
233             see http://creativecommons.org/licenses/by-sa/3.0/us/.
234              
235             =cut