line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Text::MicroMason::TemplatePath; |
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
855
|
use strict; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
55
|
|
4
|
2
|
|
|
2
|
|
19
|
use File::Spec; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
46
|
|
5
|
2
|
|
|
2
|
|
10
|
use base 'Text::MicroMason::TemplateDir'; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
805
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
###################################################################### |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
sub resolve_path { |
10
|
16
|
|
|
16
|
0
|
29
|
my ($self, $src_data) = @_; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# Absolute file path: use that filename. |
13
|
16
|
50
|
|
|
|
99
|
return $src_data if File::Spec->file_name_is_absolute($src_data); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# Relative filename: use a path search |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# Our path for this file will be the current directory, if there is |
18
|
|
|
|
|
|
|
# one, followed by the configured path. |
19
|
16
|
|
|
|
|
29
|
my @path = @{$self->{template_path}}; |
|
16
|
|
|
|
|
39
|
|
20
|
16
|
|
|
|
|
32
|
my $current = $self->{source_file}; |
21
|
16
|
100
|
|
|
|
36
|
unshift @path, $current if $current; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Check path for an existing template file. |
24
|
16
|
|
|
|
|
28
|
foreach my $dir (@path) { |
25
|
25
|
|
|
|
|
221
|
my $fn = File::Spec->canonpath(File::Spec->catfile($dir, $src_data)); |
26
|
25
|
100
|
|
|
|
379
|
next unless -e $fn; |
27
|
16
|
|
|
|
|
88
|
return $fn; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
# We couldn't find a matching template, croak. |
31
|
0
|
|
|
|
|
0
|
$self->croak_msg("Text::MicroMason::TemplatePath: template '$src_data' not found in path.\n"); |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# $contents = $mason->read_file( $filename ); |
35
|
|
|
|
|
|
|
sub read_file { |
36
|
12
|
|
|
12
|
1
|
23
|
my ( $self, $file ) = @_; |
37
|
|
|
|
|
|
|
|
38
|
12
|
50
|
|
|
|
28
|
if ( my $root = $self->{strict_root} ) { |
39
|
0
|
|
|
|
|
0
|
my $path = File::Spec->canonpath( $file ); |
40
|
|
|
|
|
|
|
# warn "Checking for '$root' in '$path'\n"; |
41
|
0
|
0
|
|
|
|
0
|
( $path =~ /\A\Q$root\E(\/|(?<=\/))(?!\.\.)/ ) |
42
|
|
|
|
|
|
|
or $self->croak_msg("Text::MicroMason::TemplatePath: Template not in required base path '$root'"); |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
12
|
|
|
|
|
24
|
return $self->NEXT('read_file', $file ); |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub cache_key { |
49
|
6
|
|
|
6
|
0
|
10
|
my $self = shift; |
50
|
6
|
|
|
|
|
14
|
my ($src_type, $src_data, %options) = @_; |
51
|
|
|
|
|
|
|
|
52
|
6
|
100
|
|
|
|
19
|
return $self->NEXT('cache_key', @_) unless $src_type eq 'file'; |
53
|
4
|
|
|
|
|
16
|
return $self->resolve_path($src_data); |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
###################################################################### |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
1; |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
###################################################################### |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 NAME |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Text::MicroMason::TemplatePath - Template Path Searching |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=head1 SYNOPSIS |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
Instead of using this class directly, pass its name to be mixed in: |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
use Text::MicroMason; |
72
|
|
|
|
|
|
|
my $mason = Text::MicroMason->new( -TemplatePath, template_path => [ '/foo', '/bar' ] ); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
Use the standard compile and execute methods to parse and evaluate templates: |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
print $mason->compile( file=>$filepath )->( 'name'=>'Dave' ); |
77
|
|
|
|
|
|
|
print $mason->execute( file=>$filepath, 'name'=>'Dave' ); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
Templates stored in files are searched for in the specified template_path: |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
print $mason->execute( file=>"includes/greeting.msn", 'name'=>'Charles'); |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
When including other files into a template you can use relative paths: |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
<& ../includes/greeting.msn, name => 'Alice' &> |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
When a file is included in the template, the including template's |
88
|
|
|
|
|
|
|
current directory is added to the beginning of the template search path. |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head1 DESCRIPTION |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
This module works similarly to the related TemplateDir mix-in. However, |
94
|
|
|
|
|
|
|
instead of specifying a single root which must contain all templates, |
95
|
|
|
|
|
|
|
TemplatePath allows you to specify an arrayref of directories which will |
96
|
|
|
|
|
|
|
be searched in order whenever a template filename must be resolved. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Using a TemplatePath object, absolute filenames are used as-is. If a |
99
|
|
|
|
|
|
|
relative template filenames or file paths is used, every directory in |
100
|
|
|
|
|
|
|
the specified template_path is checked for the existence of the |
101
|
|
|
|
|
|
|
template, and the first existing template file is used. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
If a template includes another template using <& ... &>, then the |
104
|
|
|
|
|
|
|
including template's location is added to the beginning of the template |
105
|
|
|
|
|
|
|
search path list, for the resolution of the included template's |
106
|
|
|
|
|
|
|
filename. This allows the included template to be specified relative to |
107
|
|
|
|
|
|
|
the including template, but also lets the template search fall back to |
108
|
|
|
|
|
|
|
the configured template search path if necessary. |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head2 Supported Attributes |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=over 4 |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=item template_path |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
An array ref containing a list of directories in which to search for |
118
|
|
|
|
|
|
|
relative template filenames. |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item strict_root |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Optional directory beyond which not to read files. Unlike TemplateDir, |
123
|
|
|
|
|
|
|
this must be a specific file path. Causes read_file to croak if any |
124
|
|
|
|
|
|
|
filename outside of the root is provided. You should make sure that all |
125
|
|
|
|
|
|
|
paths specified in template_path are inside the specified strict_root. |
126
|
|
|
|
|
|
|
(Note that this is not a chroot jail and only affects attempts to load a |
127
|
|
|
|
|
|
|
file as a template; for greater security see the chroot() builtin and |
128
|
|
|
|
|
|
|
L.) |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=back |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
=head2 Private Methods |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=over 4 |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item read_file |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Intercepts file access to check for strict_root. |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=back |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 EXCEPTIONS |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
The following additional exceptions are generated by |
145
|
|
|
|
|
|
|
Text::MicroMason::TemplatePath when appropriate: |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=over 4 |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=item * |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
Text::MicroMason::TemplatePath: template '%s' not found in path. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
This indicates that the specified template name does not exist in any of |
154
|
|
|
|
|
|
|
the directories in the configured path. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=item * |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
Text::MicroMason::TemplatePath: Template not in required base path '%s' |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
The template found in the configured template path was not within the |
161
|
|
|
|
|
|
|
configured strict_root directory. This may be caused by requesting an |
162
|
|
|
|
|
|
|
absolute template filename not within strict_root, or by specifying a |
163
|
|
|
|
|
|
|
strict_root which does not match the configured template path. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=back |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head1 SEE ALSO |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
For an overview of this templating framework, see L. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
This is a mixin class intended for use with L. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
For distribution, installation, support, copyright and license |
174
|
|
|
|
|
|
|
information, see L. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=cut |
177
|
|
|
|
|
|
|
|