line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Template::Plugin::Next; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
162209
|
use warnings; |
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
75
|
|
4
|
2
|
|
|
2
|
|
13
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
80
|
|
5
|
|
|
|
|
|
|
|
6
|
2
|
|
|
2
|
|
13
|
use base qw( Template::Plugin ); |
|
2
|
|
|
|
|
9
|
|
|
2
|
|
|
|
|
2916
|
|
7
|
2
|
|
|
2
|
|
8136
|
use Template::Plugin (); |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
36
|
|
8
|
2
|
|
|
2
|
|
1162
|
use Template::Exception (); |
|
2
|
|
|
|
|
3974
|
|
|
2
|
|
|
|
|
40
|
|
9
|
|
|
|
|
|
|
|
10
|
2
|
|
|
2
|
|
15
|
use File::Spec (); |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
35
|
|
11
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
|
62
|
use 5.006; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
1893
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Template::Plugin::Next - include the 'next' template file with identical relative path |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 VERSION |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Version 0.03 |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=cut |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our $VERSION = '0.03'; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 SYNOPSIS |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
This is a plugin for the Template Toolkit distribution that allows the inclusion of template files with identical relative paths like the present template. Those templates are 'hidden' by the present template, because their respective INCLUDE_PATH entries are dominated by the one of the including template. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
The functionality provided by this plugin might come handy in multi skin situations where default templates are selectively redefined by a skin using a dominating INCLUDE_PATH entry for the skin and identical relative paths to the templates as with the default templates - thus hiding them. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
The Next-plugin allows to include the dominated default templates from inside the hiding template in order to decorate the default template or include a parameterized version of it. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
Example: |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# We assume: INCLUDE_PATH='/templates/c:/templates/b:/templates/a' |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# template a/test.tt (note this template accepts a "parameter" called 'repeat'): |
40
|
|
|
|
|
|
|
[% repeat = repeat || 1; 'a' | repeat(repeat) %] |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# template b/test.tt: |
43
|
|
|
|
|
|
|
b |
44
|
|
|
|
|
|
|
[% USE Next; Next.include( repeat => 3 ); %] |
45
|
|
|
|
|
|
|
b |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# template c/test.tt: |
48
|
|
|
|
|
|
|
c |
49
|
|
|
|
|
|
|
[% USE Next; Next.include(); %] |
50
|
|
|
|
|
|
|
c |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# a call to template test.tt |
53
|
|
|
|
|
|
|
[% INCLUDE test.tt %] |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# would yield something like the following (with POST_CHOMP set to 1): |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
c |
58
|
|
|
|
|
|
|
b |
59
|
|
|
|
|
|
|
aaa |
60
|
|
|
|
|
|
|
b |
61
|
|
|
|
|
|
|
c |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=head1 EXPORT |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Exported stash variable: Next_ |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head1 METHODS |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub new { |
73
|
|
|
|
|
|
|
# called as Template::Plugin::Next->new($context) |
74
|
4
|
|
|
4
|
1
|
35436
|
my ($class, $context, %params) = @_; |
75
|
|
|
|
|
|
|
|
76
|
4
|
|
|
|
|
21
|
my $self = |
77
|
|
|
|
|
|
|
bless { |
78
|
|
|
|
|
|
|
_CONTEXT => $context |
79
|
|
|
|
|
|
|
}, $class; |
80
|
|
|
|
|
|
|
|
81
|
4
|
|
|
|
|
13
|
$self; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub error { |
85
|
0
|
|
|
0
|
1
|
0
|
my $proto = shift; |
86
|
0
|
0
|
|
|
|
0
|
die( ref( $_[0] ) ? @_ : do { $proto->SUPER::error(@_); Template::Exception->new( 'Next', $proto->SUPER::error ) } ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=head2 process |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
Includes the 'next' dominated template with an identical relative path like the one this plugin method is called from. It accepts named parameters like its TT directive counterpart PROCESS that will result in stash variables. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=cut |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub process { |
96
|
2
|
|
|
2
|
1
|
77
|
my $self = shift; |
97
|
2
|
|
|
|
|
3
|
my $params = shift; |
98
|
2
|
|
50
|
|
|
15
|
my $localise = shift || 0; |
99
|
2
|
|
|
|
|
13
|
my $context = $self->{_CONTEXT}; |
100
|
2
|
|
|
|
|
8
|
my $stash = $context->stash(); |
101
|
|
|
|
|
|
|
|
102
|
2
|
|
|
|
|
50
|
my $name = $stash->get( 'component.name' ); # template file path not file name |
103
|
|
|
|
|
|
|
|
104
|
2
|
|
33
|
|
|
44
|
my $providers = $context->{ PREFIX_MAP }->{ default } || $context->{ LOAD_TEMPLATES }; |
105
|
|
|
|
|
|
|
|
106
|
2
|
|
|
|
|
5
|
foreach my $provider ( grep { ref( $_ ) eq 'Template::Provider' } @$providers ) { |
|
2
|
|
|
|
|
9
|
|
107
|
|
|
|
|
|
|
# we know only how to handle the standard behaviour of providers |
108
|
|
|
|
|
|
|
|
109
|
2
|
|
|
|
|
4
|
my $rel_path = $name; |
110
|
2
|
|
|
|
|
3
|
my @include_paths = @{$provider->paths}; |
|
2
|
|
|
|
|
9
|
|
111
|
|
|
|
|
|
|
# include paths are returned in a list even if |
112
|
|
|
|
|
|
|
# multiple include paths have been specified via a colon separated scalar |
113
|
|
|
|
|
|
|
|
114
|
2
|
50
|
|
|
|
71
|
$self->error( 'Not applicable. There is no second include path!' ) if scalar(@include_paths) == 1; |
115
|
|
|
|
|
|
|
|
116
|
2
|
100
|
|
|
|
29
|
if ( File::Spec->file_name_is_absolute( my $abs_path = $rel_path ) ) { |
117
|
|
|
|
|
|
|
# this is for subsequent calls to NEXT |
118
|
1
|
50
|
33
|
|
|
35
|
( my( $include_path ), $rel_path ) = |
119
|
|
|
|
|
|
|
@{ |
120
|
1
|
|
|
|
|
2
|
( ( $stash->get( 'Next_' ) || $self->error( 'Could not find Next_ stash entry!' ) )->{$abs_path} |
121
|
|
|
|
|
|
|
|| |
122
|
|
|
|
|
|
|
$self->error( "Could not find abs path $abs_path in Next_ map!" ) |
123
|
|
|
|
|
|
|
) |
124
|
|
|
|
|
|
|
}; |
125
|
|
|
|
|
|
|
|
126
|
1
|
|
|
|
|
4
|
while ( @include_paths ) { |
127
|
3
|
100
|
|
|
|
12
|
last if ( shift @include_paths ) eq $include_path; |
128
|
|
|
|
|
|
|
} |
129
|
1
|
|
|
|
|
3
|
$rel_path =~ s/^\///; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
} else { |
132
|
|
|
|
|
|
|
# this is for the initial call to NEXT |
133
|
1
|
|
|
|
|
5
|
while ( @include_paths ) { |
134
|
2
|
100
|
|
|
|
7
|
last if scalar stat( _concat_path( (shift @include_paths ), $rel_path ) ); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
2
|
|
|
|
|
7
|
foreach my $include_path ( @include_paths ) { |
139
|
2
|
|
|
|
|
6
|
my $path = _concat_path( $include_path, $rel_path ); |
140
|
|
|
|
|
|
|
|
141
|
2
|
50
|
|
|
|
57
|
if( scalar stat( $path ) ) { |
142
|
2
|
|
|
|
|
3
|
my $template; |
143
|
|
|
|
|
|
|
{ |
144
|
|
|
|
|
|
|
# make abs. template paths local to this template retrieval |
145
|
2
|
|
|
|
|
3
|
local $provider->{ABSOLUTE} = 1; |
|
2
|
|
|
|
|
7
|
|
146
|
2
|
|
|
|
|
10
|
$template = $context->template($path); |
147
|
|
|
|
|
|
|
} |
148
|
2
|
50
|
|
|
|
6885
|
defined $template || $self->error( $context->error ); |
149
|
2
|
|
100
|
|
|
35
|
my $map = $stash->get( 'Next_' ) || {}; |
150
|
2
|
|
|
|
|
22
|
$map->{$path} = [ $include_path, $rel_path ]; |
151
|
2
|
|
|
|
|
19
|
$stash->set( 'Next_' => $map ); |
152
|
2
|
|
|
|
|
22
|
return $context->process( $template, $params, $localise ); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
0
|
|
|
|
|
0
|
$self->error( "No 'Next' template!" ); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 include |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Same as process() but with stash localisation. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=cut |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub include { |
167
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
168
|
0
|
|
|
|
|
0
|
$self->process( @_, 1 ); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub _concat_path { |
172
|
4
|
|
|
4
|
|
9
|
my ( $base_path, $append_dirs ) = @_; |
173
|
|
|
|
|
|
|
# $base_dir: base path (no filename) as string |
174
|
|
|
|
|
|
|
# $append_dirs: directories to append as string or an array reference |
175
|
|
|
|
|
|
|
|
176
|
4
|
|
|
|
|
32
|
my ($base_volume, $base_directories, $base_file) = File::Spec->splitpath( $base_path, 1 ); |
177
|
0
|
|
|
|
|
|
File::Spec->catpath( |
178
|
|
|
|
|
|
|
$base_volume, |
179
|
|
|
|
|
|
|
File::Spec->catdir( |
180
|
|
|
|
|
|
|
File::Spec->splitdir( $base_directories ), |
181
|
4
|
50
|
|
|
|
147
|
( ref($append_dirs) ? @{$append_dirs} : File::Spec->splitdir( $append_dirs ) ) |
182
|
|
|
|
|
|
|
) |
183
|
|
|
|
|
|
|
, |
184
|
|
|
|
|
|
|
$base_file |
185
|
|
|
|
|
|
|
); |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head1 CAVEATS |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=over 4 |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=item * INCLUDE_PATH stability is required during a single call to Template::process(). |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item * Only template providers of class Template::Provider are supported. |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=back |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=head1 AUTHOR |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Alexander Kühne, C<< >> |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head1 BUGS |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through |
205
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll |
206
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=head1 SUPPORT |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
perldoc Template::Plugin::Next |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
You can also look for information at: |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=over 4 |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
L |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
L |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item * CPAN Ratings |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
L |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item * Search CPAN |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
L |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=back |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
Copyright 2010 Alexander Kühne, all rights reserved. |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
245
|
|
|
|
|
|
|
under the same terms as Perl itself. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=cut |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
1; # End of Template::Plugin::Next |