File Coverage

blib/lib/Text/MicroMason/TemplateDir.pm
Criterion Covered Total %
statement 27 32 84.3
branch 8 16 50.0
condition 4 5 80.0
subroutine 8 8 100.0
pod 3 5 60.0
total 50 66 75.7


line stmt bran cond sub pod time code
1             package Text::MicroMason::TemplateDir;
2              
3 7     7   1874 use strict;
  7         16  
  7         174  
4 7     7   34 use File::Spec;
  7         13  
  7         146  
5 7     7   31 use Cwd;
  7         12  
  7         3021  
6              
7             ######################################################################
8              
9             sub prepare {
10 35     35 1 62 my ( $self, $src_type, $src_data ) = @_;
11            
12 35 100       86 return $self->NEXT('prepare', $src_type, $src_data )
13             unless $src_type eq 'file';
14            
15 28         89 my $path = $self->resolve_path($src_data);
16 28         115 return $self->NEXT('prepare', 'file' => $path, source_file => $path );
17             }
18              
19             sub resolve_path {
20 24     24 0 49 my ($self, $src_data) = @_;
21              
22 24         44 my $current = $self->{source_file};
23 24         47 my $rootdir = $self->template_root();
24            
25 24 100 66     244 my $base = File::Spec->file_name_is_absolute($src_data) ||
26             ! $current ? $rootdir : ( File::Spec->splitpath( $current ) )[1];
27              
28 24         271 return File::Spec->catfile( $base, $src_data );
29             }
30              
31             sub template_root {
32 24     24 1 34 my $self = shift;
33 24 50 100     88 return $self->{template_root} || '.' unless @_;
34            
35 0         0 $self->{template_root} = shift;
36             }
37              
38             sub cache_key {
39 10     10 0 77 my $self = shift;
40 10         17 my ($src_type, $src_data, %options) = @_;
41 10 100       23 return $self->NEXT('cache_key', @_) unless $src_type eq 'file';
42 8         16 return $self->resolve_path($src_data);
43             }
44              
45              
46             # $contents = $mason->read_file( $filename );
47             sub read_file {
48 28     28 1 309 my ( $self, $file ) = @_;
49            
50 28 50       62 if ( my $root = $self->{strict_root} ) {
51 0 0       0 $root = $self->template_root if $root eq '1';
52 0         0 my $path = Cwd::abs_path($file);
53 0 0       0 my $root_path = Cwd::abs_path($root)
54             or $self->croak_msg("Text::MicroMason::TemplateDir: Strict root '$root' doesn't seem to exist");
55             # warn "Checking for '$root_path' in '$path' (file $file)\n";
56 0 0       0 ( $path =~ /\A\Q$root_path\E/)
57             or $self->croak_msg("Text::MicroMason::TemplateDir: Template '$path' not in required base path '$root_path'");
58             }
59            
60 28         66 return $self->NEXT('read_file', $file );
61             }
62              
63             ######################################################################
64              
65             1;
66              
67             ######################################################################
68              
69             =head1 NAME
70              
71             Text::MicroMason::TemplateDir - Use Base Directory and Relative Paths
72              
73              
74             =head1 SYNOPSIS
75              
76             Instead of using this class directly, pass its name to be mixed in:
77              
78             use Text::MicroMason;
79             my $mason = Text::MicroMason->new( -TemplateDir, template_root=>'/foo' );
80              
81             Use the standard compile and execute methods to parse and evaluate templates:
82              
83             print $mason->compile( file=>$filepath )->( 'name'=>'Dave' );
84             print $mason->execute( file=>$filepath, 'name'=>'Dave' );
85              
86             Templates stored in files are looked up relative to the template root:
87              
88             print $mason->execute( file=>"includes/greeting.msn", 'name'=>'Charles');
89              
90             When including other files into a template you can use relative paths:
91              
92             <& ../includes/greeting.msn, name => 'Alice' &>
93              
94              
95             =head1 DESCRIPTION
96              
97             This module changes the resolution of files passed to compile() and execute() to be relative to a base directory path or to the currently executing template.
98              
99              
100             =head2 Supported Attributes
101              
102             =over 4
103              
104             =item template_root
105              
106             Base directory from which to find templates.
107              
108             =item strict_root
109              
110             Optional directory beyond which not to read files. If set to 1, uses
111             template_root, Causes read_file to croak if any filename outside of the
112             root is provided. (Note that this is not a chroot jail and only affects
113             attempts to load a file as a template; for greater security see the
114             chroot() builtin and L.)
115              
116             =back
117              
118             =head2 Private Methods
119              
120             =over 4
121              
122             =item prepare
123              
124             Intercepts uses of file templates and applies the base-path adjustment.
125              
126             =item read_file
127              
128             Intercepts file access to check for strict_root.
129              
130             =back
131              
132             =head2 EXCEPTIONS
133              
134             The following additional exceptions are generated by
135             Text::MicroMason::TemplateDir when appropriate:
136              
137             =over 4
138              
139             =item *
140              
141             Text::MicroMason::TemplateDir: Strict root '%s' doesn't seem to exist
142              
143             The strict_root directory (or template_root if strict_root is '1')
144             doesn't seem to exist. Strict root checking uses Cwd's abs_path(), and
145             requires the strict_root directory to exist at the time the check is
146             performed.
147              
148             =item *
149              
150             Text::MicroMason::TemplatePath: Template '%s' not in required base path '%s'
151              
152             The template found in the configured template path was not within the
153             configured strict_root directory. This may be caused by requesting an
154             absolute template filename not within strict_root, or by specifying a
155             strict_root which does not match the configured template path.
156              
157             =back
158              
159             =head1 SEE ALSO
160              
161             For an overview of this templating framework, see L.
162              
163             This is a mixin class intended for use with L.
164              
165             For distribution, installation, support, copyright and license
166             information, see L.
167              
168             =cut
169