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