line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Template::Alloy::Play; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Template::Alloy::Play - Play role - allows for playing out the AST |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=cut |
8
|
|
|
|
|
|
|
|
9
|
10
|
|
|
10
|
|
66
|
use strict; |
|
10
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
525
|
|
10
|
10
|
|
|
10
|
|
61
|
use warnings; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
451
|
|
11
|
10
|
|
|
10
|
|
59
|
use Template::Alloy; |
|
10
|
|
|
|
|
19
|
|
|
10
|
|
|
|
|
75
|
|
12
|
10
|
|
|
10
|
|
9808
|
use Template::Alloy::Iterator; |
|
10
|
|
|
|
|
31
|
|
|
10
|
|
|
|
|
300
|
|
13
|
10
|
|
|
10
|
|
12717
|
use Template::Alloy::Context; |
|
10
|
|
|
|
|
33
|
|
|
10
|
|
|
|
|
111355
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = $Template::Alloy::VERSION; |
16
|
|
|
|
|
|
|
our $QR_NUM = '(?:\d*\.\d+ | \d+)'; |
17
|
|
|
|
|
|
|
our $DIRECTIVES = { |
18
|
|
|
|
|
|
|
BLOCK => \&play_BLOCK, |
19
|
|
|
|
|
|
|
BREAK => \&play_control, |
20
|
|
|
|
|
|
|
CALL => \&play_CALL, |
21
|
|
|
|
|
|
|
CASE => undef, |
22
|
|
|
|
|
|
|
CATCH => undef, |
23
|
|
|
|
|
|
|
CLEAR => \&play_CLEAR, |
24
|
|
|
|
|
|
|
'#' => sub {}, |
25
|
|
|
|
|
|
|
COMMENT => sub {}, |
26
|
|
|
|
|
|
|
CONFIG => \&play_CONFIG, |
27
|
|
|
|
|
|
|
DEBUG => \&play_DEBUG, |
28
|
|
|
|
|
|
|
DEFAULT => \&play_DEFAULT, |
29
|
|
|
|
|
|
|
DUMP => \&play_DUMP, |
30
|
|
|
|
|
|
|
ELSE => undef, |
31
|
|
|
|
|
|
|
ELSIF => undef, |
32
|
|
|
|
|
|
|
END => sub {}, |
33
|
|
|
|
|
|
|
EVAL => \&play_EVAL, |
34
|
|
|
|
|
|
|
FILTER => \&play_FILTER, |
35
|
|
|
|
|
|
|
'|' => \&play_FILTER, |
36
|
|
|
|
|
|
|
FINAL => undef, |
37
|
|
|
|
|
|
|
FOR => \&play_FOR, |
38
|
|
|
|
|
|
|
FOREACH => \&play_FOR, |
39
|
|
|
|
|
|
|
GET => \&play_GET, |
40
|
|
|
|
|
|
|
IF => \&play_IF, |
41
|
|
|
|
|
|
|
INCLUDE => \&play_INCLUDE, |
42
|
|
|
|
|
|
|
INSERT => \&play_INSERT, |
43
|
|
|
|
|
|
|
LAST => \&play_control, |
44
|
|
|
|
|
|
|
LOOP => \&play_LOOP, |
45
|
|
|
|
|
|
|
MACRO => \&play_MACRO, |
46
|
|
|
|
|
|
|
META => \&play_META, |
47
|
|
|
|
|
|
|
NEXT => \&play_control, |
48
|
|
|
|
|
|
|
PERL => \&play_PERL, |
49
|
|
|
|
|
|
|
PROCESS => \&play_PROCESS, |
50
|
|
|
|
|
|
|
RAWPERL => \&play_RAWPERL, |
51
|
|
|
|
|
|
|
RETURN => \&play_RETURN, |
52
|
|
|
|
|
|
|
SET => \&play_SET, |
53
|
|
|
|
|
|
|
STOP => \&play_control, |
54
|
|
|
|
|
|
|
SWITCH => \&play_SWITCH, |
55
|
|
|
|
|
|
|
TAGS => sub {}, |
56
|
|
|
|
|
|
|
THROW => \&play_THROW, |
57
|
|
|
|
|
|
|
TRY => \&play_TRY, |
58
|
|
|
|
|
|
|
UNLESS => \&play_UNLESS, |
59
|
|
|
|
|
|
|
USE => \&play_USE, |
60
|
|
|
|
|
|
|
VIEW => \&play_VIEW, |
61
|
|
|
|
|
|
|
WHILE => \&play_WHILE, |
62
|
|
|
|
|
|
|
WRAPPER => \&play_WRAPPER, |
63
|
|
|
|
|
|
|
}; |
64
|
|
|
|
|
|
|
|
65
|
0
|
|
|
0
|
0
|
0
|
sub new { die "This class is a role for use by packages such as Template::Alloy" } |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub play_tree { |
70
|
5220
|
|
|
5220
|
1
|
9115
|
my ($self, $tree, $out_ref) = @_; |
71
|
|
|
|
|
|
|
|
72
|
5220
|
100
|
|
|
|
17280
|
return $self->stream_tree($tree) if $self->{'STREAM'}; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
# node contains (0: DIRECTIVE, |
75
|
|
|
|
|
|
|
# 1: start_index, |
76
|
|
|
|
|
|
|
# 2: end_index, |
77
|
|
|
|
|
|
|
# 3: parsed tag details, |
78
|
|
|
|
|
|
|
# 4: sub tree for block types |
79
|
|
|
|
|
|
|
# 5: continuation sub trees for sub continuation block types (elsif, else, etc) |
80
|
|
|
|
|
|
|
# 6: flag to capture next directive |
81
|
3797
|
|
|
|
|
8452
|
for my $node (@$tree) { |
82
|
|
|
|
|
|
|
### text nodes are just the bare text |
83
|
7172
|
100
|
|
|
|
17194
|
if (! ref $node) { |
84
|
1532
|
50
|
|
|
|
3943
|
$$out_ref .= $node if defined $node; |
85
|
1532
|
|
|
|
|
3212
|
next; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
5640
|
100
|
66
|
|
|
18860
|
$$out_ref .= $self->debug_node($node) if $self->{'_debug_dirs'} && ! $self->{'_debug_off'}; |
89
|
|
|
|
|
|
|
|
90
|
5640
|
|
|
|
|
23736
|
$DIRECTIVES->{$node->[0]}->($self, $node->[3], $node, $out_ref); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub _is_empty_named_args { |
95
|
243
|
|
|
243
|
|
443
|
my ($hash_ident) = @_; |
96
|
|
|
|
|
|
|
# [[undef, '{}', 'key1', 'val1', 'key2, 'val2'], 0] |
97
|
243
|
|
|
|
|
344
|
return @{ $hash_ident->[0] } <= 2; |
|
243
|
|
|
|
|
1023
|
|
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub play_BLOCK { |
103
|
202
|
|
|
202
|
0
|
454
|
my ($self, $block_name, $node, $out_ref) = @_; |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# store a named reference - but do nothing until something processes it |
106
|
202
|
|
|
|
|
380
|
my $comp = $self->{'_component'}; |
107
|
202
|
50
|
|
|
|
1910
|
$self->{'BLOCKS'}->{$block_name} = { |
108
|
|
|
|
|
|
|
_tree => $node->[4], |
109
|
|
|
|
|
|
|
name => $comp->{'name'} .'/'. $block_name, |
110
|
|
|
|
|
|
|
($comp->{'_filename'} ? (_filename => $comp->{'_filename'}) : ()), |
111
|
|
|
|
|
|
|
}; |
112
|
|
|
|
|
|
|
|
113
|
202
|
|
|
|
|
508
|
return; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub play_CALL { |
117
|
52
|
|
|
52
|
0
|
92
|
my ($self, $ident, $node) = @_; |
118
|
52
|
|
|
|
|
245
|
my $var = $self->play_expr($ident); |
119
|
52
|
50
|
|
|
|
157
|
$var = $self->undefined_get($ident, $node) if ! defined $var; |
120
|
52
|
|
|
|
|
149
|
return; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub play_control { |
124
|
26
|
|
|
26
|
0
|
58
|
my ($self, $undef, $node) = @_; |
125
|
26
|
|
|
|
|
154
|
$self->throw(lc($node->[0]), 'Control exception', $node); |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub play_CLEAR { |
129
|
7
|
|
|
7
|
0
|
13
|
my ($self, $undef, $node, $out_ref) = @_; |
130
|
7
|
|
|
|
|
13
|
$$out_ref = ''; |
131
|
7
|
|
|
|
|
17
|
return; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub play_CONFIG { |
135
|
121
|
|
|
121
|
0
|
249
|
my ($self, $config, $node, $out_ref) = @_; |
136
|
|
|
|
|
|
|
|
137
|
121
|
|
|
|
|
258
|
my %rtime = map {$_ => 1} @Template::Alloy::CONFIG_RUNTIME; |
|
605
|
|
|
|
|
1319
|
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
### do runtime config - not many options get these |
140
|
121
|
|
|
|
|
321
|
my ($named, @the_rest) = @$config; |
141
|
121
|
|
|
|
|
483
|
$named = $self->play_expr($named); |
142
|
121
|
100
|
100
|
|
|
525
|
$self->throw("config.strict", "Cannot disable STRICT once it is enabled", $node) if exists $named->{'STRICT'} && ! $named->{'STRICT'}; |
143
|
118
|
|
|
|
|
332
|
@{ $self }{keys %$named} = @{ $named }{keys %$named}; |
|
118
|
|
|
|
|
266
|
|
|
118
|
|
|
|
|
286
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
### show what current values are |
146
|
118
|
50
|
|
|
|
380
|
$$out_ref .= join("\n", map { $rtime{$_} ? ("CONFIG $_ = ".(defined($self->{$_}) ? $self->{$_} : 'undef')) : $_ } @the_rest); |
|
15
|
100
|
|
|
|
78
|
|
147
|
118
|
|
|
|
|
1736
|
return; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub play_DEBUG { |
151
|
2
|
|
|
2
|
0
|
9
|
my ($self, $ref) = @_; |
152
|
2
|
50
|
|
|
|
32
|
if ($ref->[0] eq 'on') { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
153
|
0
|
|
|
|
|
0
|
delete $self->{'_debug_off'}; |
154
|
|
|
|
|
|
|
} elsif ($ref->[0] eq 'off') { |
155
|
0
|
|
|
|
|
0
|
$self->{'_debug_off'} = 1; |
156
|
|
|
|
|
|
|
} elsif ($ref->[0] eq 'format') { |
157
|
2
|
|
|
|
|
9
|
$self->{'_debug_format'} = $ref->[1]; |
158
|
|
|
|
|
|
|
} |
159
|
2
|
|
|
|
|
8
|
return; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub play_DEFAULT { |
163
|
6
|
|
|
6
|
0
|
45
|
my ($self, $set) = @_; |
164
|
6
|
|
|
|
|
19
|
foreach my $item (@$set) { |
165
|
6
|
|
|
|
|
14
|
my ($op, $set, $default) = @$item; |
166
|
6
|
50
|
|
|
|
29
|
next if ! defined $set; |
167
|
6
|
|
|
|
|
28
|
my $val = $self->play_expr($set); |
168
|
6
|
100
|
|
|
|
22
|
if (! $val) { |
169
|
4
|
50
|
|
|
|
21
|
$default = defined($default) ? $self->play_expr($default) : ''; |
170
|
4
|
|
|
|
|
20
|
$self->set_variable($set, $default); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
} |
173
|
6
|
|
|
|
|
15
|
return; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub play_DUMP { |
177
|
84
|
|
|
84
|
0
|
170
|
my ($self, $dump, $node, $out_ref) = @_; |
178
|
|
|
|
|
|
|
|
179
|
84
|
|
|
|
|
159
|
my $conf = $self->{'DUMP'}; |
180
|
84
|
100
|
100
|
|
|
481
|
return if ! $conf && defined $conf; # DUMP => 0 |
181
|
78
|
100
|
|
|
|
239
|
$conf = {} if ref $conf ne 'HASH'; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
### allow for handler override |
184
|
78
|
|
|
|
|
152
|
my $handler = $conf->{'handler'}; |
185
|
78
|
100
|
|
|
|
202
|
if (! $handler) { |
186
|
75
|
|
|
|
|
1618
|
require Data::Dumper; |
187
|
75
|
|
|
|
|
7560
|
my $obj = Data::Dumper->new([]); |
188
|
75
|
|
|
|
|
2524
|
my $meth; |
189
|
75
|
100
|
66
|
|
|
243
|
foreach my $prop (keys %$conf) { $obj->$prop($conf->{$prop}) if $prop =~ /^\w+$/ && ($meth = $obj->can($prop)) } |
|
60
|
|
|
|
|
822
|
|
190
|
75
|
100
|
|
|
|
353
|
my $sort = defined($conf->{'Sortkeys'}) ? $obj->Sortkeys : 1; |
191
|
21
|
50
|
66
|
21
|
|
527
|
$obj->Sortkeys(sub { my $h = shift; [grep {! $Template::Alloy::QR_PRIVATE |
|
21
|
|
|
|
|
117
|
|
|
27
|
|
|
|
|
449
|
|
192
|
75
|
|
|
|
|
569
|
|| $_ !~ $Template::Alloy::QR_PRIVATE} ($sort ? sort keys %$h : keys %$h)] }); |
193
|
72
|
|
|
72
|
|
326
|
$handler = sub { $obj->Values([@_]); $obj->Dump } |
|
72
|
|
|
|
|
861
|
|
194
|
75
|
|
|
|
|
625
|
} |
195
|
|
|
|
|
|
|
|
196
|
78
|
|
|
|
|
197
|
my ($named, @dump) = @$dump; |
197
|
78
|
100
|
|
|
|
209
|
push @dump, $named if ! _is_empty_named_args($named); # add named args back on at end - if there are some |
198
|
78
|
|
|
|
|
371
|
$_ = $self->play_expr($_) foreach @dump; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
### look for the text describing what to dump |
201
|
78
|
|
50
|
|
|
184
|
my $info = eval { $self->node_info($node) } || {text => 'unknown', file => 'unknown', line => 'unknown'}; |
202
|
78
|
|
|
|
|
126
|
my $out; |
203
|
78
|
100
|
100
|
|
|
203
|
if (@dump) { |
|
|
100
|
|
|
|
|
|
204
|
69
|
100
|
66
|
|
|
478
|
$out = $handler->(@dump && @dump == 1 ? $dump[0] : \@dump); |
205
|
69
|
|
|
|
|
1509
|
my $name = $info->{'text'}; |
206
|
69
|
|
|
|
|
354
|
$name =~ s/^[+=~-]?\s*DUMP\s+//; |
207
|
69
|
|
|
|
|
283
|
$name =~ s/\s*[+=~-]?$//; |
208
|
69
|
|
|
|
|
215
|
$out =~ s/\$VAR1/$name/; |
209
|
|
|
|
|
|
|
} elsif (defined($conf->{'EntireStash'}) && ! $conf->{'EntireStash'}) { |
210
|
3
|
|
|
|
|
7
|
$out = ''; |
211
|
|
|
|
|
|
|
} else { |
212
|
6
|
|
|
|
|
20
|
$out = $handler->($self->{'_vars'}); |
213
|
6
|
|
|
|
|
34
|
$out =~ s/\$VAR1/EntireStash/g; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
78
|
100
|
100
|
|
|
537
|
if ($conf->{'html'} || (! defined($conf->{'html'}) && $ENV{'REQUEST_METHOD'})) { |
|
|
|
66
|
|
|
|
|
217
|
9
|
|
|
|
|
57
|
$out = $Template::Alloy::SCALAR_OPS->{'xml'}->($out); |
218
|
9
|
|
|
|
|
28
|
$out = "$out "; |
219
|
9
|
100
|
66
|
|
|
67
|
$out = "DUMP: File \"$info->{file}\" line $info->{line}$out" if $conf->{'header'} || ! defined $conf->{'header'}; |
220
|
|
|
|
|
|
|
} else { |
221
|
69
|
100
|
66
|
|
|
511
|
$out = "DUMP: File \"$info->{file}\" line $info->{line}\n $out" if $conf->{'header'} || ! defined $conf->{'header'}; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
78
|
|
|
|
|
163
|
$$out_ref .= $out; |
225
|
78
|
|
|
|
|
1786
|
return; |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub play_EVAL { |
229
|
20
|
|
|
20
|
0
|
32
|
my ($self, $ref, $node, $out_ref) = @_; |
230
|
20
|
|
|
|
|
46
|
my ($named, @strs) = @$ref; |
231
|
|
|
|
|
|
|
|
232
|
20
|
|
|
|
|
30
|
foreach my $str (@strs) { |
233
|
20
|
|
|
|
|
206
|
$str = $self->play_expr($str); |
234
|
20
|
50
|
|
|
|
56
|
next if ! defined $str; |
235
|
20
|
|
|
|
|
94
|
$str = $self->play_expr([[undef, '-temp-', $str], 0, '|', 'eval', [$named]]); |
236
|
17
|
50
|
|
|
|
236
|
$$out_ref .= $str if defined $str; |
237
|
|
|
|
|
|
|
} |
238
|
17
|
|
|
|
|
219
|
return; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub play_FILTER { |
242
|
49
|
|
|
49
|
0
|
87
|
my ($self, $ref, $node, $out_ref) = @_; |
243
|
49
|
|
|
|
|
87
|
my ($name, $filter) = @$ref; |
244
|
|
|
|
|
|
|
|
245
|
49
|
50
|
|
|
|
115
|
return '' if ! @$filter; |
246
|
|
|
|
|
|
|
|
247
|
49
|
100
|
|
|
|
145
|
$self->{'FILTERS'}->{$name} = $filter if length $name; |
248
|
|
|
|
|
|
|
|
249
|
49
|
|
|
|
|
72
|
my $sub_tree = $node->[4]; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
### play the block |
252
|
49
|
|
|
|
|
62
|
my $out = ''; |
253
|
49
|
|
|
|
|
64
|
eval { local $self->{'STREAM'} = undef; $self->play_tree($sub_tree, \$out) }; |
|
49
|
|
|
|
|
98
|
|
|
49
|
|
|
|
|
148
|
|
254
|
49
|
50
|
33
|
|
|
163
|
die $@ if $@ && ! UNIVERSAL::can($@, 'type'); # TODO - shouldn't they all die ? |
255
|
|
|
|
|
|
|
|
256
|
49
|
|
|
|
|
271
|
$out = $self->play_expr([[undef, '-temp-', $out], 0, '|', @$filter]); |
257
|
49
|
50
|
|
|
|
192
|
$$out_ref .= $out if defined $out; |
258
|
49
|
|
|
|
|
158
|
return; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub play_FOR { |
262
|
172
|
|
|
172
|
0
|
532
|
my ($self, $ref, $node, $out_ref) = @_; |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
### get the items - make sure it is an arrayref |
265
|
172
|
|
|
|
|
337
|
my ($var, $items) = @$ref; |
266
|
|
|
|
|
|
|
|
267
|
172
|
|
|
|
|
681
|
$items = $self->play_expr($items); |
268
|
172
|
100
|
|
|
|
487
|
return '' if ! defined $items; |
269
|
|
|
|
|
|
|
|
270
|
168
|
50
|
|
|
|
735
|
if (ref($items) !~ /Iterator$/) { |
271
|
168
|
|
|
|
|
642
|
$items = $self->iterator($items); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
168
|
|
|
|
|
286
|
my $sub_tree = $node->[4]; |
275
|
|
|
|
|
|
|
|
276
|
168
|
|
|
|
|
642
|
local $self->{'_vars'}->{'loop'} = $items; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
### if the FOREACH tag sets a var - then nothing but the loop var gets localized |
279
|
168
|
100
|
|
|
|
406
|
if (defined $var) { |
280
|
129
|
|
|
|
|
574
|
my ($item, $error) = $items->get_first; |
281
|
129
|
|
|
|
|
333
|
while (! $error) { |
282
|
326
|
|
|
|
|
1434
|
$self->set_variable($var, $item); |
283
|
|
|
|
|
|
|
|
284
|
326
|
|
|
|
|
575
|
eval { $self->play_tree($sub_tree, $out_ref) }; |
|
326
|
|
|
|
|
927
|
|
285
|
326
|
100
|
|
|
|
997
|
if (my $err = $@) { |
286
|
18
|
50
|
|
|
|
79
|
die $err if ! UNIVERSAL::can($err, 'type'); |
287
|
18
|
100
|
|
|
|
60
|
last if $err->type =~ /last|break/; |
288
|
14
|
100
|
|
|
|
50
|
die if $err->type ne 'next'; |
289
|
|
|
|
|
|
|
} |
290
|
312
|
|
|
|
|
1158
|
($item, $error) = $items->get_next; |
291
|
|
|
|
|
|
|
} |
292
|
119
|
50
|
66
|
|
|
787
|
die $error if $error && $error != 3; # Template::Constants::STATUS_DONE; |
293
|
|
|
|
|
|
|
### if the FOREACH tag doesn't set a var - then everything gets localized |
294
|
|
|
|
|
|
|
} else { |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
### localize variable access for the foreach |
297
|
39
|
|
|
|
|
88
|
my $swap = $self->{'_vars'}; |
298
|
39
|
|
|
|
|
245
|
local $self->{'_vars'} = my $copy = {%$swap}; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
### iterate use the iterator object |
301
|
|
|
|
|
|
|
#foreach (my $i = $items->index; $i <= $#$vals; $items->index(++ $i)) { |
302
|
39
|
|
|
|
|
1098
|
my ($item, $error) = $items->get_first; |
303
|
39
|
|
|
|
|
126
|
while (! $error) { |
304
|
129
|
100
|
|
|
|
421
|
@$copy{keys %$item} = values %$item if ref($item) eq 'HASH'; |
305
|
|
|
|
|
|
|
|
306
|
129
|
|
|
|
|
179
|
eval { $self->play_tree($sub_tree, $out_ref) }; |
|
129
|
|
|
|
|
341
|
|
307
|
129
|
50
|
|
|
|
564
|
if (my $err = $@) { |
308
|
0
|
0
|
|
|
|
0
|
die $err if ! UNIVERSAL::can($err, 'type'); |
309
|
0
|
0
|
|
|
|
0
|
last if $err->type =~ /last|break/; |
310
|
0
|
0
|
|
|
|
0
|
die if $err->type ne 'next'; |
311
|
|
|
|
|
|
|
} |
312
|
129
|
|
|
|
|
439
|
($item, $error) = $items->get_next; |
313
|
|
|
|
|
|
|
} |
314
|
39
|
50
|
33
|
|
|
441
|
die $error if $error && $error != 3; # Template::Constants::STATUS_DONE; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
158
|
|
|
|
|
1304
|
return; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub play_GET { |
321
|
3757
|
|
|
3757
|
0
|
7066
|
my ($self, $ident, $node, $out_ref) = @_; |
322
|
3757
|
|
|
|
|
11600
|
my $var = $self->play_expr($ident); |
323
|
3711
|
100
|
|
|
|
10936
|
if (defined $var) { |
324
|
3314
|
|
|
|
|
7310
|
$$out_ref .= $var; |
325
|
|
|
|
|
|
|
} else { |
326
|
397
|
|
|
|
|
1301
|
$var = $self->undefined_get($ident, $node); |
327
|
397
|
50
|
|
|
|
1199
|
$$out_ref .= $var if defined $var; |
328
|
|
|
|
|
|
|
} |
329
|
3711
|
|
|
|
|
10852
|
return; |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub play_IF { |
333
|
152
|
|
|
152
|
0
|
299
|
my ($self, $var, $node, $out_ref) = @_; |
334
|
|
|
|
|
|
|
|
335
|
152
|
|
|
|
|
550
|
my $val = $self->play_expr($var); |
336
|
150
|
100
|
|
|
|
414
|
if ($val) { |
337
|
78
|
|
50
|
|
|
257
|
my $body_ref = $node->[4] ||= []; |
338
|
78
|
|
|
|
|
259
|
$self->play_tree($body_ref, $out_ref); |
339
|
56
|
|
|
|
|
201
|
return; |
340
|
|
|
|
|
|
|
} |
341
|
|
|
|
|
|
|
|
342
|
72
|
|
|
|
|
306
|
while ($node = $node->[5]) { # ELSE, ELSIF's |
343
|
29
|
100
|
|
|
|
104
|
if ($node->[0] eq 'ELSE') { |
344
|
13
|
|
50
|
|
|
50
|
my $body_ref = $node->[4] ||= []; |
345
|
13
|
|
|
|
|
42
|
$self->play_tree($body_ref, $out_ref); |
346
|
13
|
|
|
|
|
115
|
return; |
347
|
|
|
|
|
|
|
} |
348
|
16
|
|
|
|
|
31
|
my $var = $node->[3]; |
349
|
16
|
|
|
|
|
70
|
my $val = $self->play_expr($var); |
350
|
16
|
100
|
|
|
|
78
|
if ($val) { |
351
|
6
|
|
50
|
|
|
28
|
my $body_ref = $node->[4] ||= []; |
352
|
6
|
|
|
|
|
24
|
$self->play_tree($body_ref, $out_ref); |
353
|
6
|
|
|
|
|
25
|
return; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} |
356
|
53
|
|
|
|
|
150
|
return; |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
sub play_INCLUDE { |
360
|
146
|
|
|
146
|
0
|
333
|
my ($self, $str_ref, $node, $out_ref) = @_; |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
### localize the swap |
363
|
146
|
|
50
|
|
|
500
|
my $swap = $self->{'_vars'} || {}; |
364
|
146
|
|
|
|
|
734
|
local $self->{'_vars'} = {%$swap}; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
### localize the blocks |
367
|
146
|
|
50
|
|
|
518
|
my $blocks = $self->{'BLOCKS'} || {}; |
368
|
146
|
|
|
|
|
2264
|
local $self->{'BLOCKS'} = {%$blocks}; |
369
|
|
|
|
|
|
|
|
370
|
146
|
|
|
|
|
572
|
return $DIRECTIVES->{'PROCESS'}->($self, $str_ref, $node, $out_ref); |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub play_INSERT { |
374
|
21
|
|
|
21
|
0
|
50
|
my ($self, $args, $node, $out_ref) = @_; |
375
|
21
|
50
|
|
|
|
76
|
if ($self->{'NO_INCLUDES'}) { |
376
|
0
|
|
|
|
|
0
|
$self->throw('file', "NO_INCLUDES was set during a $node->[0] directive"); |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
21
|
|
|
|
|
55
|
my ($named, @files) = @$args; |
380
|
|
|
|
|
|
|
|
381
|
21
|
|
|
|
|
47
|
foreach my $name (@files) { |
382
|
21
|
|
|
|
|
81
|
my $file = $self->play_expr($name); |
383
|
21
|
|
|
|
|
83
|
my $ref = $self->slurp($self->include_filename($file)); |
384
|
21
|
|
|
|
|
85
|
$$out_ref .= $$ref; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
21
|
|
|
|
|
274
|
return; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
sub play_JS { |
391
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
392
|
0
|
0
|
|
|
|
0
|
$self->throw('js', 'COMPILE_JS not set while running a JS block') if ! $self->{'COMPILE_JS'}; |
393
|
0
|
|
|
|
|
0
|
$self->throw('js', 'Cannot run JS directly'); |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
sub play_LOOP { |
397
|
23
|
|
|
23
|
0
|
46
|
my ($self, $ref, $node, $out_ref) = @_; |
398
|
|
|
|
|
|
|
|
399
|
23
|
100
|
|
|
|
111
|
my $var = $self->play_expr(ref($ref) ? $ref : [$ref,0]); # allow for "string" identified loops |
400
|
23
|
|
|
|
|
50
|
my $sub_tree = $node->[4]; |
401
|
|
|
|
|
|
|
|
402
|
23
|
|
100
|
|
|
138
|
my $global = ! $self->{'SYNTAX'} || $self->{'SYNTAX'} ne 'ht' || $self->{'GLOBAL_VARS'}; |
403
|
|
|
|
|
|
|
|
404
|
23
|
100
|
|
|
|
77
|
my $items = ref($var) eq 'ARRAY' ? $var : ref($var) eq 'HASH' ? [$var] : []; |
|
|
100
|
|
|
|
|
|
405
|
|
|
|
|
|
|
|
406
|
23
|
|
|
|
|
30
|
my $i = 0; |
407
|
23
|
|
|
|
|
42
|
for my $ref (@$items) { |
408
|
|
|
|
|
|
|
### setup the loop |
409
|
46
|
50
|
66
|
|
|
232
|
$self->throw('loop', 'Scalar value used in LOOP') if $ref && ref($ref) ne 'HASH'; |
410
|
46
|
100
|
50
|
|
|
202
|
local $self->{'_vars'} = (! $global) ? ($ref || {}) : (ref($ref) eq 'HASH') ? {%{ $self->{'_vars'} }, %$ref} : $self->{'_vars'}; |
|
36
|
100
|
|
|
|
228
|
|
411
|
46
|
100
|
66
|
|
|
168
|
if ($self->{'LOOP_CONTEXT_VARS'} && ! $Template::Alloy::QR_PRIVATE) { |
412
|
9
|
|
|
|
|
26
|
$self->{'_vars'}->{'__counter__'} = ++$i; |
413
|
9
|
100
|
|
|
|
65
|
$self->{'_vars'}->{'__first__'} = $i == 1 ? 1 : 0; |
414
|
9
|
100
|
|
|
|
37
|
$self->{'_vars'}->{'__last__'} = $i == @$items ? 1 : 0; |
415
|
9
|
100
|
100
|
|
|
54
|
$self->{'_vars'}->{'__inner__'} = $i == 1 || $i == @$items ? 0 : 1; |
416
|
9
|
100
|
|
|
|
37
|
$self->{'_vars'}->{'__odd__'} = ($i % 2) ? 1 : 0; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
### execute the sub tree |
420
|
46
|
|
|
|
|
124
|
$self->play_tree($sub_tree, $out_ref); |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
|
423
|
23
|
|
|
|
|
65
|
return; |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub play_MACRO { |
427
|
44
|
|
|
44
|
0
|
95
|
my ($self, $ref, $node, $out_ref) = @_; |
428
|
44
|
|
|
|
|
100
|
my ($name, $args) = @$ref; |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
### get the sub tree |
431
|
44
|
|
|
|
|
74
|
my $sub_tree = $node->[4]; |
432
|
44
|
50
|
33
|
|
|
506
|
if (! $sub_tree || ! $sub_tree->[0]) { |
|
|
100
|
100
|
|
|
|
|
433
|
0
|
|
|
|
|
0
|
$self->set_variable($name, undef); |
434
|
0
|
|
|
|
|
0
|
return; |
435
|
|
|
|
|
|
|
} elsif (ref($sub_tree->[0]) && $sub_tree->[0]->[0] eq 'BLOCK') { |
436
|
31
|
|
|
|
|
69
|
$sub_tree = $sub_tree->[0]->[4]; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
### install a closure in the stash that will handle the macro |
440
|
44
|
|
|
|
|
164
|
$self->set_variable($name, $self->_macro_sub($args, $sub_tree, $out_ref)); |
441
|
|
|
|
|
|
|
|
442
|
44
|
|
|
|
|
113
|
return; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub _macro_sub { |
446
|
71
|
|
|
71
|
|
154
|
my ($self, $args, $sub_tree, $out_ref) = @_; |
447
|
|
|
|
|
|
|
|
448
|
71
|
|
|
|
|
119
|
my $self_copy = $self; |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
my $sub = sub { |
451
|
|
|
|
|
|
|
### macros localize |
452
|
94
|
|
|
94
|
|
232
|
my $copy = $self_copy->{'_vars'}; |
453
|
94
|
|
|
|
|
688
|
local $self_copy->{'_vars'}= {%$copy}; |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
### prevent recursion |
456
|
94
|
|
100
|
|
|
478
|
local $self_copy->{'_macro_recurse'} = $self_copy->{'_macro_recurse'} || 0; |
457
|
94
|
|
66
|
|
|
283
|
my $max = $self_copy->{'MAX_MACRO_RECURSE'} || $Template::Alloy::MAX_MACRO_RECURSE; |
458
|
94
|
100
|
|
|
|
243
|
$self_copy->throw('macro_recurse', "MAX_MACRO_RECURSE $max reached") |
459
|
|
|
|
|
|
|
if ++$self_copy->{'_macro_recurse'} > $max; |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
### set arguments |
462
|
92
|
50
|
100
|
|
|
602
|
my $named = pop(@_) if $_[-1] && UNIVERSAL::isa($_[-1],'HASH') && $#_ > $#$args; |
|
|
|
66
|
|
|
|
|
463
|
92
|
|
|
|
|
331
|
my @positional = @_; |
464
|
92
|
|
|
|
|
190
|
foreach my $var (@$args) { |
465
|
83
|
|
|
|
|
315
|
$self_copy->set_variable($var, shift(@positional)); |
466
|
|
|
|
|
|
|
} |
467
|
92
|
|
|
|
|
360
|
foreach my $name (sort keys %$named) { |
468
|
0
|
|
|
|
|
0
|
$self_copy->set_variable([$name, 0], $named->{$name}); |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
92
|
|
|
|
|
218
|
local $self->{'STREAM'} = undef; |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
### finally - run the sub tree |
474
|
92
|
|
|
|
|
161
|
my $out = ''; |
475
|
92
|
|
|
|
|
126
|
eval { $self_copy->play_tree($sub_tree, \$out) }; |
|
92
|
|
|
|
|
266
|
|
476
|
92
|
50
|
|
|
|
314
|
if (my $err = $@) { |
477
|
0
|
0
|
|
|
|
0
|
die $err if $err->type ne 'return'; |
478
|
0
|
0
|
|
|
|
0
|
return $err->info->{'return_val'} if UNIVERSAL::isa($err->info, 'HASH'); |
479
|
0
|
|
|
|
|
0
|
return; |
480
|
|
|
|
|
|
|
} |
481
|
92
|
|
|
|
|
711
|
return $out; |
482
|
71
|
|
|
|
|
576
|
}; |
483
|
|
|
|
|
|
|
|
484
|
71
|
|
|
|
|
134
|
eval {require Scalar::Util; Scalar::Util::weaken($self_copy)}; |
|
71
|
|
|
|
|
578
|
|
|
71
|
|
|
|
|
315
|
|
485
|
71
|
|
|
|
|
309
|
return $sub; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
sub play_META { |
489
|
152
|
|
|
152
|
0
|
255
|
my ($self, $hash) = @_; |
490
|
152
|
100
|
|
|
|
436
|
return if ! $hash; |
491
|
76
|
50
|
|
|
|
383
|
$hash = {@$hash} if ref($hash) eq 'ARRAY'; |
492
|
76
|
|
|
|
|
272
|
my @keys = keys %$hash; |
493
|
|
|
|
|
|
|
|
494
|
76
|
|
|
|
|
124
|
my $ref; |
495
|
76
|
100
|
|
|
|
192
|
if ($self->{'_top_level'}) { |
496
|
52
|
|
50
|
|
|
200
|
$ref = $self->{'_template'} ||= {}; |
497
|
|
|
|
|
|
|
} else { |
498
|
24
|
|
50
|
|
|
84
|
$ref = $self->{'_component'} ||= {}; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
76
|
|
|
|
|
133
|
@{ $ref }{ @keys } = @{ $hash }{ @keys }; |
|
76
|
|
|
|
|
223
|
|
|
76
|
|
|
|
|
133
|
|
502
|
76
|
|
|
|
|
280
|
return; |
503
|
|
|
|
|
|
|
} |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
sub play_PERL { |
506
|
12
|
|
|
12
|
0
|
23
|
my ($self, $info, $node, $out_ref) = @_; |
507
|
12
|
100
|
|
|
|
44
|
$self->throw('perl', 'EVAL_PERL not set') if ! $self->{'EVAL_PERL'}; |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
### fill in any variables |
510
|
10
|
|
50
|
|
|
32
|
my $perl = $node->[4] || return; |
511
|
10
|
|
|
|
|
16
|
my $out = ''; |
512
|
|
|
|
|
|
|
{ |
513
|
10
|
|
|
|
|
13
|
local $self->{'STREAM'} = undef; |
|
10
|
|
|
|
|
23
|
|
514
|
10
|
|
|
|
|
32
|
$self->play_tree($perl, \$out); |
515
|
|
|
|
|
|
|
}; |
516
|
10
|
50
|
|
|
|
68
|
$out = $1 if $out =~ /^(.+)$/s; # blatant untaint - shouldn't use perl anyway |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
### try the code |
519
|
10
|
|
|
|
|
10
|
my $err; |
520
|
10
|
|
|
|
|
16
|
eval { |
521
|
|
|
|
|
|
|
package Template::Alloy::Perl; |
522
|
|
|
|
|
|
|
|
523
|
10
|
|
|
|
|
42
|
my $context = $self->context; |
524
|
10
|
|
|
|
|
38
|
my $stash = $context->stash; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
### setup a fake handle |
527
|
10
|
|
|
|
|
29
|
local *PERLOUT; |
528
|
10
|
|
|
|
|
125
|
tie *PERLOUT, 'Template::Alloy::EvalPerlHandle', $out_ref; |
529
|
10
|
|
|
|
|
28
|
my $old_fh = select PERLOUT; |
530
|
|
|
|
|
|
|
|
531
|
10
|
|
|
|
|
870
|
eval $out; |
532
|
10
|
|
|
|
|
35
|
$err = $@; |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
### put the handle back |
535
|
10
|
|
|
|
|
77
|
select $old_fh; |
536
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
}; |
538
|
10
|
|
33
|
|
|
46
|
$err ||= $@; |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
|
541
|
10
|
50
|
|
|
|
22
|
if ($err) { |
542
|
0
|
0
|
|
|
|
0
|
$self->throw('undef', $err) if ! UNIVERSAL::can($err, 'type'); |
543
|
0
|
|
|
|
|
0
|
die $err; |
544
|
|
|
|
|
|
|
} |
545
|
|
|
|
|
|
|
|
546
|
10
|
|
|
|
|
31
|
return; |
547
|
|
|
|
|
|
|
} |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
sub play_PROCESS { |
550
|
541
|
|
|
541
|
0
|
1327
|
my ($self, $info, $node, $out_ref) = @_; |
551
|
541
|
100
|
|
|
|
1785
|
if ($self->{'NO_INCLUDES'}) { |
552
|
2
|
|
|
|
|
16
|
$self->throw('file', "NO_INCLUDES was set during a $node->[0] directive"); |
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
|
555
|
539
|
|
|
|
|
1361
|
my ($args, @files) = @$info; |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
### process files first |
558
|
539
|
|
|
|
|
1009
|
foreach my $ref (@files) { |
559
|
551
|
50
|
|
|
|
2672
|
$ref = $self->play_expr($ref) if defined $ref; |
560
|
|
|
|
|
|
|
} |
561
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
### set passed args |
563
|
|
|
|
|
|
|
# [[undef, '{}', 'key1', 'val1', 'key2', 'val2'], 0] |
564
|
539
|
|
|
|
|
1621
|
$args = $args->[0]; |
565
|
539
|
|
|
|
|
17520
|
foreach (my $i = 2; $i < @$args; $i+=2) { |
566
|
94
|
|
|
|
|
212
|
my $key = $args->[$i]; |
567
|
94
|
|
|
|
|
359
|
my $val = $self->play_expr($args->[$i+1]); |
568
|
94
|
0
|
66
|
|
|
433
|
if (ref($key) && @$key == 2 && $key->[0] eq 'import' && UNIVERSAL::isa($val, 'HASH')) { # import ?! - whatever |
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
569
|
0
|
|
|
|
|
0
|
foreach my $key (keys %$val) { |
570
|
0
|
|
|
|
|
0
|
$self->set_variable([$key,0], $val->{$key}); |
571
|
|
|
|
|
|
|
} |
572
|
0
|
|
|
|
|
0
|
next; |
573
|
|
|
|
|
|
|
} |
574
|
94
|
|
|
|
|
374
|
$self->set_variable($key, $val); |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
### iterate on any passed block or filename |
578
|
539
|
|
|
|
|
989
|
foreach my $filename (@files) { |
579
|
551
|
50
|
|
|
|
1494
|
next if ! defined $filename; |
580
|
551
|
|
|
|
|
967
|
my $out = ''; # have temp item to allow clear to correctly clear |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
### normal blocks or filenames |
583
|
551
|
100
|
100
|
|
|
1908
|
if (! ref($filename) || ref($filename) eq 'SCALAR') { |
584
|
537
|
|
|
|
|
697
|
eval { $self->_process($filename, $self->{'_vars'}, \$out) }; # restart the swap - passing it our current stash |
|
537
|
|
|
|
|
2210
|
|
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
### allow for $template which is used in some odd instances |
587
|
|
|
|
|
|
|
} else { |
588
|
14
|
|
|
|
|
31
|
my $doc = $filename; |
589
|
|
|
|
|
|
|
|
590
|
14
|
50
|
|
|
|
49
|
$self->throw('process', "Recursion detected in $node->[0] \$template") if $self->{'_process_dollar_template'}; |
591
|
14
|
|
|
|
|
46
|
local $self->{'_process_dollar_template'} = 1; |
592
|
14
|
|
|
|
|
35
|
local $self->{'_component'} = $doc; |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
### run the document however we can |
595
|
14
|
50
|
66
|
|
|
147
|
if (ref($doc) ne 'HASH' || (! $doc->{'_perl'} && ! $doc->{'_tree'})) { |
|
|
100
|
33
|
|
|
|
|
596
|
0
|
|
|
|
|
0
|
$self->throw('process', "Passed item doesn't appear to be a valid document"); |
597
|
|
|
|
|
|
|
} elsif ($doc->{'_perl'}) { |
598
|
5
|
|
|
|
|
13
|
eval { $doc->{'_perl'}->{'code'}->($self, \$out) }; |
|
5
|
|
|
|
|
159
|
|
599
|
|
|
|
|
|
|
} else { |
600
|
9
|
|
|
|
|
13
|
eval { $self->play_tree($doc->{'_tree'}, \$out) }; |
|
9
|
|
|
|
|
34
|
|
601
|
|
|
|
|
|
|
} |
602
|
|
|
|
|
|
|
|
603
|
14
|
50
|
|
|
|
55
|
if ($self->{'TRIM'}) { |
604
|
0
|
|
|
|
|
0
|
$out =~ s{ \s+ $ }{}x; |
605
|
0
|
|
|
|
|
0
|
$out =~ s{ ^ \s+ }{}x; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
### handle exceptions |
609
|
14
|
50
|
|
|
|
73
|
if (my $err = $@) { |
610
|
0
|
0
|
|
|
|
0
|
$err = $self->exception('undef', $err) if ! UNIVERSAL::can($err, 'type'); |
611
|
0
|
0
|
0
|
|
|
0
|
$err->doc($doc) if $doc && $err->can('doc') && ! $err->doc; |
|
|
|
0
|
|
|
|
|
612
|
|
|
|
|
|
|
} |
613
|
|
|
|
|
|
|
|
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
### append any output |
617
|
551
|
|
|
|
|
1088
|
$$out_ref .= $out; |
618
|
551
|
100
|
|
|
|
2296
|
if (my $err = $@) { |
619
|
87
|
100
|
33
|
|
|
569
|
die $err if ! UNIVERSAL::can($err, 'type') || $err->type !~ /return/; |
620
|
|
|
|
|
|
|
} |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
|
623
|
455
|
|
|
|
|
6204
|
return; |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
sub play_RAWPERL { |
627
|
3
|
|
|
3
|
0
|
9
|
my ($self, $info, $node, $out_ref) = @_; |
628
|
3
|
50
|
|
|
|
14
|
$self->throw('perl', 'EVAL_PERL not set') if ! $self->{'EVAL_PERL'}; |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
### fill in any variables |
631
|
3
|
|
50
|
|
|
15
|
my $tree = $node->[4] || return; |
632
|
3
|
|
|
|
|
8
|
my $perl = ''; |
633
|
|
|
|
|
|
|
{ |
634
|
3
|
|
|
|
|
6
|
local $self->{'STREAM'} = undef; |
|
3
|
|
|
|
|
9
|
|
635
|
3
|
|
|
|
|
18
|
$self->play_tree($tree, \$perl); |
636
|
|
|
|
|
|
|
} |
637
|
3
|
50
|
|
|
|
27
|
$perl = $1 if $perl =~ /^(.+)$/s; # blatant untaint - shouldn't use perl anyway |
638
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
### try the code |
640
|
3
|
|
|
|
|
6
|
my $err; |
641
|
3
|
|
|
|
|
84
|
my $output = ''; |
642
|
3
|
|
|
|
|
7
|
eval { |
643
|
|
|
|
|
|
|
package Template::Alloy::Perl; |
644
|
|
|
|
|
|
|
|
645
|
3
|
|
|
|
|
14
|
my $context = $self->context; |
646
|
3
|
|
|
|
|
14
|
my $stash = $context->stash; |
647
|
|
|
|
|
|
|
|
648
|
3
|
|
|
|
|
192
|
eval $perl; |
649
|
3
|
|
|
|
|
19
|
$err = $@; |
650
|
|
|
|
|
|
|
}; |
651
|
3
|
|
33
|
|
|
20
|
$err ||= $@; |
652
|
|
|
|
|
|
|
|
653
|
3
|
|
|
|
|
6
|
$$out_ref .= $output; |
654
|
|
|
|
|
|
|
|
655
|
3
|
50
|
|
|
|
15
|
if ($err) { |
656
|
0
|
0
|
|
|
|
0
|
$self->throw('undef', $err) if ! UNIVERSAL::can($err, 'type'); |
657
|
0
|
|
|
|
|
0
|
die $err; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
3
|
|
|
|
|
42
|
return; |
661
|
|
|
|
|
|
|
} |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
sub play_RETURN { |
664
|
10
|
|
|
10
|
0
|
17
|
my ($self, $undef, $node) = @_; |
665
|
10
|
|
|
|
|
15
|
my $var = $node->[3]; |
666
|
10
|
50
|
|
|
|
28
|
$var = {return_val => $self->play_expr($var)} if defined $var; |
667
|
10
|
|
|
|
|
34
|
$self->throw('return', $var, $node); |
668
|
|
|
|
|
|
|
} |
669
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
sub play_SET { |
671
|
1020
|
|
|
1020
|
0
|
2203
|
my ($self, $set, $node) = @_; |
672
|
1020
|
|
|
|
|
1770
|
foreach my $item (@$set) { |
673
|
1028
|
|
|
|
|
2264
|
my ($op, $set, $val) = @$item; |
674
|
1028
|
100
|
66
|
|
|
4897
|
if (! defined $val) { # not defined |
|
|
100
|
|
|
|
|
|
675
|
|
|
|
|
|
|
# do nothing - allow for setting to undef |
676
|
|
|
|
|
|
|
} elsif ($node->[4] && $val == $node->[4]) { # a captured directive |
677
|
54
|
|
|
|
|
78
|
my $sub_tree = $node->[4]; |
678
|
54
|
100
|
66
|
|
|
254
|
$sub_tree = $sub_tree->[0]->[4] if $sub_tree->[0] && $sub_tree->[0]->[0] eq 'BLOCK'; |
679
|
54
|
|
|
|
|
88
|
$val = ''; |
680
|
54
|
|
|
|
|
118
|
local $self->{'STREAM'} = undef; |
681
|
54
|
|
|
|
|
135
|
$self->play_tree($sub_tree, \$val); |
682
|
|
|
|
|
|
|
} else { # normal var |
683
|
956
|
|
|
|
|
3101
|
$val = $self->play_expr($val); |
684
|
|
|
|
|
|
|
} |
685
|
|
|
|
|
|
|
|
686
|
1027
|
|
|
|
|
3575
|
$self->set_variable($set, $val); |
687
|
|
|
|
|
|
|
} |
688
|
1017
|
|
|
|
|
3229
|
return; |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
sub play_SWITCH { |
692
|
20
|
|
|
20
|
0
|
42
|
my ($self, $var, $node, $out_ref) = @_; |
693
|
|
|
|
|
|
|
|
694
|
20
|
|
|
|
|
77
|
my $val = $self->play_expr($var); |
695
|
20
|
50
|
|
|
|
53
|
$val = '' if ! defined $val; |
696
|
|
|
|
|
|
|
### $node->[4] is thrown away |
697
|
|
|
|
|
|
|
|
698
|
20
|
|
|
|
|
29
|
my $default; |
699
|
20
|
|
|
|
|
60
|
while ($node = $node->[5]) { # CASES |
700
|
20
|
|
|
|
|
31
|
my $var = $node->[3]; |
701
|
20
|
100
|
|
|
|
49
|
if (! defined $var) { |
702
|
6
|
|
|
|
|
9
|
$default = $node->[4]; |
703
|
6
|
|
|
|
|
17
|
next; |
704
|
|
|
|
|
|
|
} |
705
|
|
|
|
|
|
|
|
706
|
14
|
|
|
|
|
45
|
my $val2 = $self->play_expr($var); |
707
|
14
|
100
|
|
|
|
66
|
$val2 = [$val2] if ! UNIVERSAL::isa($val2, 'ARRAY'); |
708
|
14
|
|
|
|
|
24
|
for my $test (@$val2) { # find matching values |
709
|
32
|
50
|
33
|
|
|
80
|
next if ! defined $val && defined $test; |
710
|
32
|
100
|
66
|
|
|
148
|
next if defined $val && ! defined $test; |
711
|
30
|
100
|
|
|
|
122
|
next if $val ne $test; |
712
|
8
|
|
50
|
|
|
27
|
my $body_ref = $node->[4] ||= []; |
713
|
8
|
|
|
|
|
29
|
$self->play_tree($body_ref, $out_ref); |
714
|
8
|
|
|
|
|
31
|
return; |
715
|
|
|
|
|
|
|
} |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
12
|
100
|
|
|
|
31
|
if ($default) { |
719
|
6
|
|
|
|
|
21
|
$self->play_tree($default, $out_ref); |
720
|
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
|
|
722
|
12
|
|
|
|
|
32
|
return; |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
sub play_THROW { |
726
|
67
|
|
|
67
|
0
|
160
|
my ($self, $ref, $node) = @_; |
727
|
67
|
|
|
|
|
135
|
my ($name, $args) = @$ref; |
728
|
|
|
|
|
|
|
|
729
|
67
|
|
|
|
|
246
|
$name = $self->play_expr($name); |
730
|
|
|
|
|
|
|
|
731
|
67
|
|
|
|
|
172
|
my ($named, @args) = @$args; |
732
|
67
|
50
|
|
|
|
166
|
push @args, $named if ! _is_empty_named_args($named); # add named args back on at end - if there are some |
733
|
|
|
|
|
|
|
|
734
|
67
|
|
|
|
|
148
|
@args = map { $self->play_expr($_) } @args; |
|
58
|
|
|
|
|
186
|
|
735
|
67
|
|
|
|
|
288
|
$self->throw($name, \@args, $node); # dies |
736
|
0
|
|
|
|
|
0
|
return; # but return just in case |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
sub play_TRY { |
740
|
156
|
|
|
156
|
0
|
275
|
my ($self, $foo, $node, $out_ref) = @_; |
741
|
156
|
|
|
|
|
245
|
my $out = ''; |
742
|
|
|
|
|
|
|
|
743
|
156
|
|
|
|
|
435
|
my $body_ref = $node->[4]; |
744
|
156
|
|
|
|
|
203
|
eval { $self->play_tree($body_ref, \$out) }; |
|
156
|
|
|
|
|
598
|
|
745
|
156
|
|
|
|
|
325
|
my $err = $@; |
746
|
|
|
|
|
|
|
|
747
|
156
|
100
|
|
|
|
388
|
if (! $node->[5]) { # no catch or final |
748
|
10
|
100
|
|
|
|
36
|
if (! $err) { # no final block and no error |
749
|
8
|
|
|
|
|
19
|
$$out_ref .= $out; |
750
|
8
|
|
|
|
|
26
|
return; |
751
|
|
|
|
|
|
|
} |
752
|
2
|
|
|
|
|
9
|
$self->throw('parse.missing', "Missing CATCH block", $node); |
753
|
|
|
|
|
|
|
} |
754
|
146
|
100
|
|
|
|
440
|
if ($err) { |
755
|
94
|
100
|
|
|
|
396
|
$err = $self->exception('undef', $err) if ! UNIVERSAL::can($err, 'type'); |
756
|
94
|
50
|
|
|
|
301
|
if ($err->type =~ /stop|return/) { |
757
|
0
|
|
|
|
|
0
|
$$out_ref .= $out; |
758
|
0
|
|
|
|
|
0
|
die $err; |
759
|
|
|
|
|
|
|
} |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
### loop through the nested catch and final blocks |
763
|
146
|
|
|
|
|
225
|
my $catch_body_ref; |
764
|
|
|
|
|
|
|
my $last_found; |
765
|
146
|
100
|
|
|
|
342
|
my $type = $err ? $err->type : ''; |
766
|
146
|
|
|
|
|
189
|
my $final; |
767
|
146
|
|
|
|
|
350
|
while ($node = $node->[5]) { # CATCH |
768
|
152
|
100
|
|
|
|
350
|
if ($node->[0] eq 'FINAL') { |
769
|
6
|
|
|
|
|
10
|
$final = $node->[4]; |
770
|
6
|
|
|
|
|
15
|
next; |
771
|
|
|
|
|
|
|
} |
772
|
146
|
100
|
|
|
|
367
|
next if ! $err; |
773
|
96
|
|
|
|
|
331
|
my $name = $self->play_expr($node->[3]); |
774
|
96
|
100
|
66
|
|
|
390
|
$name = '' if ! defined $name || lc($name) eq 'default'; |
775
|
96
|
50
|
66
|
|
|
1284
|
if ($type =~ / ^ \Q$name\E \b /x |
|
|
|
66
|
|
|
|
|
776
|
|
|
|
|
|
|
&& (! defined($last_found) || length($last_found) < length($name))) { # more specific wins |
777
|
88
|
|
50
|
|
|
235
|
$catch_body_ref = $node->[4] || []; |
778
|
88
|
|
|
|
|
303
|
$last_found = $name; |
779
|
|
|
|
|
|
|
} |
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
### play the best catch block |
783
|
146
|
100
|
|
|
|
344
|
if ($err) { |
784
|
94
|
100
|
|
|
|
246
|
if (! $catch_body_ref) { |
785
|
8
|
|
|
|
|
14
|
$$out_ref .= $out; |
786
|
8
|
|
|
|
|
52
|
die $err; |
787
|
|
|
|
|
|
|
} |
788
|
86
|
|
|
|
|
294
|
local $self->{'_vars'}->{'error'} = $err; |
789
|
86
|
|
|
|
|
269
|
local $self->{'_vars'}->{'e'} = $err; |
790
|
86
|
|
|
|
|
137
|
eval { $self->play_tree($catch_body_ref, \$out) }; |
|
86
|
|
|
|
|
210
|
|
791
|
86
|
50
|
|
|
|
362
|
if (my $err = $@) { |
792
|
0
|
|
|
|
|
0
|
$$out_ref .= $out; |
793
|
0
|
|
|
|
|
0
|
die $err; |
794
|
|
|
|
|
|
|
} |
795
|
|
|
|
|
|
|
} |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
### the final block |
798
|
138
|
100
|
|
|
|
308
|
$self->play_tree($final, \$out) if $final; |
799
|
|
|
|
|
|
|
|
800
|
138
|
|
|
|
|
199
|
$$out_ref .= $out; |
801
|
|
|
|
|
|
|
|
802
|
138
|
|
|
|
|
564
|
return; |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
14
|
|
|
14
|
0
|
57
|
sub play_UNLESS { return $DIRECTIVES->{'IF'}->(@_) } |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
sub play_USE { |
808
|
98
|
|
|
98
|
0
|
221
|
my ($self, $ref, $node, $out_ref, $foreign) = @_; # foreign allows for usage from JS |
809
|
98
|
|
|
|
|
255
|
my ($var, $module, $args) = @$ref; |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
### get the stash storage location - default to the module |
812
|
98
|
100
|
|
|
|
369
|
$var = $module if ! defined $var; |
813
|
98
|
|
|
|
|
620
|
my @var = map {($_, 0, '.')} split /(?:\.|::)/, $var; |
|
98
|
|
|
|
|
498
|
|
814
|
98
|
|
|
|
|
199
|
pop @var; # remove the trailing '.' |
815
|
|
|
|
|
|
|
|
816
|
98
|
|
|
|
|
236
|
my ($named, @args) = @$args; |
817
|
98
|
100
|
|
|
|
344
|
push @args, $named if ! _is_empty_named_args($named); # add named args back on at end - if there are some |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
### try and load the module - fall back to bare module if allowed |
820
|
98
|
|
|
|
|
171
|
my $obj; |
821
|
98
|
50
|
33
|
|
|
1735
|
if (my $fact = $self->{'PLUGIN_FACTORY'}->{$module} || $self->{'PLUGIN_FACTORY'}->{lc $module}) { |
|
|
100
|
66
|
|
|
|
|
|
|
100
|
|
|
|
|
|
822
|
0
|
0
|
|
|
|
0
|
if (UNIVERSAL::isa($fact, 'CODE')) { |
823
|
0
|
0
|
|
|
|
0
|
$obj = $fact->($self->context, $foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
0
|
|
|
|
|
0
|
|
824
|
|
|
|
|
|
|
} |
825
|
|
|
|
|
|
|
|
826
|
|
|
|
|
|
|
} elsif (my $pkg = $self->{'PLUGINS'}->{$module} || $self->{'PLUGINS'}->{lc $module}) { |
827
|
6
|
|
|
|
|
28
|
(my $req = "$pkg.pm") =~ s|::|/|g; |
828
|
6
|
50
|
33
|
|
|
62
|
if (UNIVERSAL::isa($pkg, 'UNIVERSAL') || eval { require $req }) { |
|
0
|
|
|
|
|
0
|
|
829
|
6
|
|
|
|
|
100
|
my $shape = $pkg->load; |
830
|
3
|
50
|
|
|
|
30
|
$obj = $shape->new($self->context, $foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
3
|
|
|
|
|
15
|
|
831
|
|
|
|
|
|
|
} |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
} elsif (lc($module) eq 'iterator') { # use our iterator if none found (TT's works fine too) |
834
|
3
|
50
|
|
|
|
11
|
$obj = $self->iterator($foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
3
|
|
|
|
|
20
|
|
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
} else { |
837
|
89
|
|
|
|
|
173
|
my $found; |
838
|
89
|
|
|
|
|
162
|
my $BASE = $self->{'PLUGIN_BASE'}; |
839
|
89
|
100
|
|
|
|
456
|
foreach my $base ((ref($BASE) eq 'ARRAY' ? @$BASE : $BASE), (my $e = 'TP-Fallback')) { |
840
|
163
|
100
|
100
|
|
|
697
|
if ($base && $base eq 'TP-Fallback' && eval { require Template::Plugins }) { # want to allow Template::Plugins without requiring we use them |
|
71
|
|
66
|
|
|
2845
|
|
841
|
71
|
|
50
|
|
|
3269
|
$base = $Template::Plugins::PLUGIN_BASE || next; |
842
|
71
|
100
|
66
|
|
|
2179
|
if ($Template::Plugins::STD_PLUGINS |
843
|
|
|
|
|
|
|
&& (my $pkg = $Template::Plugins::STD_PLUGINS->{lc $module})) { |
844
|
62
|
|
|
|
|
395
|
(my $req = "$pkg.pm") =~ s|::|/|g; |
845
|
62
|
|
|
|
|
83
|
$found = 1; |
846
|
62
|
50
|
|
|
|
103
|
if (eval { require $req }) { |
|
62
|
|
|
|
|
1915
|
|
847
|
62
|
|
|
|
|
2966
|
my $shape = $pkg->load; |
848
|
62
|
50
|
|
|
|
828
|
$obj = $shape->new($self->context, $foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
40
|
|
|
|
|
252
|
|
849
|
|
|
|
|
|
|
} |
850
|
62
|
|
|
|
|
9019
|
last; |
851
|
|
|
|
|
|
|
} |
852
|
|
|
|
|
|
|
} |
853
|
101
|
100
|
|
|
|
284
|
next if ! $base; |
854
|
|
|
|
|
|
|
|
855
|
39
|
|
|
|
|
91
|
my $pkg = "${base}::${module}"; |
856
|
39
|
|
|
|
|
200
|
(my $req = "$pkg.pm") =~ s|::|/|g; |
857
|
39
|
100
|
66
|
|
|
385
|
if ($pkg->can('load') || eval { require $req }) { |
|
21
|
|
|
|
|
11144
|
|
858
|
18
|
|
|
|
|
74
|
my $shape = $pkg->load; |
859
|
18
|
50
|
|
|
|
142
|
$obj = $shape->new($self->context, $foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
12
|
|
|
|
|
53
|
|
860
|
18
|
|
|
|
|
190
|
$found = 1; |
861
|
18
|
|
|
|
|
46
|
last; |
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
} |
864
|
|
|
|
|
|
|
|
865
|
89
|
100
|
66
|
|
|
437
|
if (! $found && $self->{'LOAD_PERL'}) { |
866
|
9
|
|
|
|
|
38
|
(my $req = "$module.pm") =~ s|::|/|g; |
867
|
9
|
100
|
66
|
|
|
112
|
if ($module->can('new') || eval { require $req }) { |
|
3
|
|
|
|
|
1205
|
|
868
|
6
|
50
|
|
|
|
41
|
$obj = $module->new($foreign ? @$foreign : map { $self->play_expr($_) } @args); |
|
3
|
|
|
|
|
25
|
|
869
|
|
|
|
|
|
|
} |
870
|
|
|
|
|
|
|
} |
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
95
|
100
|
|
|
|
355
|
if (! defined $obj) { |
874
|
3
|
|
|
|
|
9
|
my $err = "$module: plugin not found"; |
875
|
3
|
|
|
|
|
18
|
$self->throw('plugin', $err); |
876
|
|
|
|
|
|
|
} |
877
|
|
|
|
|
|
|
|
878
|
92
|
50
|
|
|
|
259
|
return $obj if $foreign; |
879
|
92
|
|
|
|
|
523
|
$self->set_variable(\@var, $obj); |
880
|
|
|
|
|
|
|
|
881
|
92
|
|
|
|
|
5417
|
return; |
882
|
|
|
|
|
|
|
} |
883
|
|
|
|
|
|
|
|
884
|
|
|
|
|
|
|
sub play_VIEW { |
885
|
28
|
|
|
28
|
0
|
59
|
my ($self, $ref, $node, $out_ref) = @_; |
886
|
|
|
|
|
|
|
|
887
|
28
|
|
|
|
|
206
|
my ($blocks, $args, $name) = @$ref; |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
### get args ready |
890
|
|
|
|
|
|
|
# [[undef, '{}', 'key1', 'val1', 'key2', 'val2'], 0] |
891
|
28
|
|
|
|
|
49
|
$args = $args->[0]; |
892
|
28
|
|
|
|
|
55
|
my $hash = {}; |
893
|
28
|
|
|
|
|
101
|
foreach (my $i = 2; $i < @$args; $i+=2) { |
894
|
35
|
|
|
|
|
54
|
my $key = $args->[$i]; |
895
|
35
|
|
|
|
|
114
|
my $val = $self->play_expr($args->[$i+1]); |
896
|
35
|
50
|
|
|
|
99
|
if (ref $key) { |
897
|
0
|
0
|
0
|
|
|
0
|
if (@$key == 2 && ! ref($key->[0]) && ! $key->[1]) { |
|
|
|
0
|
|
|
|
|
898
|
0
|
|
|
|
|
0
|
$key = $key->[0]; |
899
|
|
|
|
|
|
|
} else { |
900
|
0
|
|
|
|
|
0
|
$self->set_variable($key, $val); |
901
|
0
|
|
|
|
|
0
|
next; # what TT does |
902
|
|
|
|
|
|
|
} |
903
|
|
|
|
|
|
|
} |
904
|
35
|
|
|
|
|
149
|
$hash->{$key} = $val; |
905
|
|
|
|
|
|
|
} |
906
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
### prepare the blocks |
908
|
28
|
100
|
66
|
|
|
444
|
my $prefix = $hash->{'prefix'} || (ref($name) && @$name == 2 && ! $name->[1] && ! ref($name->[0])) ? "$name->[0]/" : ''; |
909
|
28
|
|
|
|
|
100
|
foreach my $key (keys %$blocks) { |
910
|
19
|
|
|
|
|
109
|
$blocks->{$key} = {name => "${prefix}${key}", _tree => $blocks->{$key}}; |
911
|
|
|
|
|
|
|
} |
912
|
28
|
|
|
|
|
79
|
$hash->{'blocks'} = $blocks; |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
### get the view |
915
|
28
|
50
|
|
|
|
42
|
if (! eval { require Template::View }) { |
|
28
|
|
|
|
|
272
|
|
916
|
0
|
|
|
|
|
0
|
$self->throw('view', 'Could not load Template::View library'); |
917
|
|
|
|
|
|
|
} |
918
|
28
|
|
33
|
|
|
129
|
my $view = Template::View->new($self->context, $hash) |
919
|
|
|
|
|
|
|
|| $self->throw('view', $Template::View::ERROR); |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
### 'play it' |
922
|
28
|
|
|
|
|
5038
|
my $old_view = $self->play_expr(['view', 0]); |
923
|
28
|
|
|
|
|
123
|
$self->set_variable($name, $view); |
924
|
28
|
|
|
|
|
122
|
$self->set_variable(['view', 0], $view); |
925
|
|
|
|
|
|
|
|
926
|
28
|
50
|
|
|
|
96
|
if ($node->[4]) { |
927
|
28
|
|
|
|
|
44
|
my $out = ''; |
928
|
28
|
|
|
|
|
85
|
$self->play_tree($node->[4], \$out); |
929
|
|
|
|
|
|
|
# throw away $out |
930
|
|
|
|
|
|
|
} |
931
|
|
|
|
|
|
|
|
932
|
28
|
|
|
|
|
152
|
$self->set_variable(['view', 0], $old_view); |
933
|
28
|
|
|
|
|
108
|
$view->seal; |
934
|
|
|
|
|
|
|
|
935
|
28
|
|
|
|
|
166
|
return; |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
sub play_WHILE { |
939
|
26
|
|
|
26
|
0
|
47
|
my ($self, $var, $node, $out_ref) = @_; |
940
|
26
|
50
|
|
|
|
70
|
return if ! defined $var; |
941
|
|
|
|
|
|
|
|
942
|
26
|
|
|
|
|
52
|
my $sub_tree = $node->[4]; |
943
|
|
|
|
|
|
|
|
944
|
|
|
|
|
|
|
### iterate use the iterator object |
945
|
26
|
|
|
|
|
42
|
my $count = $Template::Alloy::WHILE_MAX; |
946
|
26
|
|
|
|
|
71
|
while (--$count > 0) { |
947
|
|
|
|
|
|
|
|
948
|
2180
|
100
|
|
|
|
6515
|
$self->play_expr($var) || last; |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
### execute the sub tree |
951
|
2158
|
|
|
|
|
3400
|
eval { $self->play_tree($sub_tree, $out_ref) }; |
|
2158
|
|
|
|
|
4893
|
|
952
|
2158
|
100
|
|
|
|
8449
|
if (my $err = $@) { |
953
|
2
|
50
|
|
|
|
10
|
if (UNIVERSAL::can($err, 'type')) { |
954
|
2
|
50
|
|
|
|
8
|
next if $err->type =~ /next/; |
955
|
2
|
50
|
|
|
|
8
|
last if $err->type =~ /last|break/; |
956
|
|
|
|
|
|
|
} |
957
|
0
|
|
|
|
|
0
|
die $err; |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
26
|
100
|
|
|
|
103
|
die "WHILE loop terminated (> $Template::Alloy::WHILE_MAX iterations)\n" if ! $count; |
961
|
|
|
|
|
|
|
|
962
|
24
|
|
|
|
|
249
|
return; |
963
|
|
|
|
|
|
|
} |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
sub play_WRAPPER { |
966
|
18
|
|
|
18
|
0
|
41
|
my ($self, $args, $node, $out_ref) = @_; |
967
|
18
|
|
50
|
|
|
58
|
my $sub_tree = $node->[4] || return; |
968
|
|
|
|
|
|
|
|
969
|
18
|
|
|
|
|
45
|
my ($named, @files) = @$args; |
970
|
|
|
|
|
|
|
|
971
|
18
|
|
|
|
|
31
|
my $out = ''; |
972
|
|
|
|
|
|
|
{ |
973
|
18
|
|
|
|
|
22
|
local $self->{'STREAM'} = undef; |
|
18
|
|
|
|
|
42
|
|
974
|
18
|
|
|
|
|
57
|
$self->play_tree($sub_tree, \$out); |
975
|
18
|
|
|
|
|
46
|
foreach my $name (reverse @files) { |
976
|
18
|
|
|
|
|
60
|
local $self->{'_vars'}->{'content'} = $out; |
977
|
18
|
|
|
|
|
30
|
$out = ''; |
978
|
18
|
|
|
|
|
83
|
$DIRECTIVES->{'INCLUDE'}->($self, [$named, $name], $node, \$out); |
979
|
|
|
|
|
|
|
} |
980
|
|
|
|
|
|
|
} |
981
|
18
|
100
|
|
|
|
55
|
if ($self->{'STREAM'}) { |
982
|
9
|
|
|
|
|
31
|
print $out; |
983
|
9
|
|
|
|
|
18
|
$out = ''; |
984
|
|
|
|
|
|
|
} |
985
|
|
|
|
|
|
|
|
986
|
18
|
|
|
|
|
36
|
$$out_ref .= $out; |
987
|
18
|
|
|
|
|
55
|
return; |
988
|
|
|
|
|
|
|
} |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
package Template::Alloy::EvalPerlHandle; |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
sub TIEHANDLE { |
995
|
15
|
|
|
15
|
|
28
|
my ($class, $out_ref) = @_; |
996
|
15
|
|
|
|
|
227
|
return bless [$out_ref], $class; |
997
|
|
|
|
|
|
|
} |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
sub PRINT { |
1000
|
15
|
|
|
15
|
|
31
|
my $self = shift; |
1001
|
15
|
50
|
|
|
|
37
|
${ $self->[0] } .= $_ for grep {defined && length} @_; |
|
15
|
|
|
|
|
299
|
|
|
15
|
|
|
|
|
65
|
|
1002
|
15
|
|
|
|
|
396
|
return 1; |
1003
|
|
|
|
|
|
|
} |
1004
|
|
|
|
|
|
|
|
1005
|
|
|
|
|
|
|
###----------------------------------------------------------------### |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
1; |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
__END__ |