blib/lib/HTML/DynamicTemplate.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 61 | 63 | 96.8 |
branch | 16 | 22 | 72.7 |
condition | 6 | 6 | 100.0 |
subroutine | 10 | 10 | 100.0 |
pod | 5 | 5 | 100.0 |
total | 98 | 106 | 92.4 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | #================================================================== | ||||||
2 | # DynamicTemplate.pm | ||||||
3 | |||||||
4 | package HTML::DynamicTemplate; | ||||||
5 | 2 | 2 | 14253 | use strict; | |||
2 | 4 | ||||||
2 | 75 | ||||||
6 | |||||||
7 | 2 | 2 | 10 | use vars qw($VERSION); | |||
2 | 5 | ||||||
2 | 3101 | ||||||
8 | $VERSION = "0.94"; | ||||||
9 | |||||||
10 | |||||||
11 | |||||||
12 | #================================================================== | ||||||
13 | |||||||
14 | =head1 NAME | ||||||
15 | |||||||
16 | HTML::DynamicTemplate - HTML template class. | ||||||
17 | |||||||
18 | =head1 SYNOPSIS | ||||||
19 | |||||||
20 | use HTML::DynamicTemplate; | ||||||
21 | my $template = new HTML::DynamicTemplate 'path/to/template'; | ||||||
22 | $template->set_recursion_limit($integer); | ||||||
23 | $template->set(NAME => $value); | ||||||
24 | $template->set(NAME_1 => $value_1, | ||||||
25 | NAME_2 => $value_2, | ||||||
26 | NAME_3 => $value_3); | ||||||
27 | |||||||
28 | $template->clear(); | ||||||
29 | $template->render(); | ||||||
30 | $template->render(@variables); | ||||||
31 | |||||||
32 | path/to/template | ||||||
33 | ---------------- | ||||||
34 | |||||||
35 | |||||||
36 | $HEADING |
||||||
37 | |||||||
38 | This is standard HTML with |
||||||
39 | arbitrary embedded variable references which are substituted | ||||||
40 | with actual values when the template is rendered. | ||||||
41 | |||||||
42 | Template variables may be set within the template itself |
||||||
43 | with the special $SET directive. This is useful when setting | ||||||
44 | variables for use by included templates. Example: | ||||||
45 | $SET(PAGE_TITLE, "What's New"). Note: Be sure to escape | ||||||
46 | quotes (") and closing parantheses ()) as HTML | ||||||
47 | entities. | ||||||
48 | |||||||
49 | Additionally, templates may be recursively included by |
||||||
50 | specifying a template with the special $INCLUDE directive. | ||||||
51 | Example: $INCLUDE(templates/example.tmpl). Template paths may | ||||||
52 | be variable references as in $INCLUDE($EXAMPLE_FILE). Note: | ||||||
53 | Any variable references found in included templates will be | ||||||
54 | substituted as in the original template. | ||||||
55 | |||||||
56 | Usage note: variable and directive names are always |
||||||
57 | specified in uppercase. | ||||||
58 | |||||||
59 | |||||||
60 | |||||||
61 | |||||||
62 | =head1 DESCRIPTION | ||||||
63 | |||||||
64 | The C |
||||||
65 | template in perl. Significant features include the ability to set | ||||||
66 | template variables from within the template itself, the ability to | ||||||
67 | recursively include other templates, and the ability to selectively | ||||||
68 | render a specified subset of variables. | ||||||
69 | |||||||
70 | =head1 METHODS | ||||||
71 | |||||||
72 | =over 4 | ||||||
73 | |||||||
74 | =cut | ||||||
75 | |||||||
76 | #================================================================== | ||||||
77 | |||||||
78 | =item $template = new HTML::DynamicTemplate $template_filename; | ||||||
79 | |||||||
80 | Constructor for the template. Returns a reference to a | ||||||
81 | HTML::DynamicTemplate object based on the specified template file. | ||||||
82 | |||||||
83 | =cut | ||||||
84 | |||||||
85 | sub new { | ||||||
86 | 2 | 2 | 1 | 58 | my($class, $template) = @_; | ||
87 | |||||||
88 | 2 | 6 | my $self = {}; | ||||
89 | 2 | 6 | bless $self, $class; | ||||
90 | |||||||
91 | 2 | 14 | $self->{'vars'} = {}; | ||||
92 | 2 | 6 | $self->{'source'} = ''; | ||||
93 | 2 | 6 | $self->{'recursion_level'} = 0; | ||||
94 | 2 | 4 | $self->{'recursion_limit'} = 10; | ||||
95 | 2 | 42 | $self->{'template'} = $template; | ||||
96 | |||||||
97 | 2 | 50 | 111 | open TEMPLATE, $template or die $!; | |||
98 | 2 | 48 | while() { $self->{'source'} .= $_ } | ||||
74 | 184 | ||||||
99 | 2 | 24 | close TEMPLATE; | ||||
100 | |||||||
101 | 2 | 9 | return $self; | ||||
102 | } | ||||||
103 | |||||||
104 | |||||||
105 | |||||||
106 | #================================================================== | ||||||
107 | |||||||
108 | =item $template->set_recursion_limit($integer); | ||||||
109 | |||||||
110 | A default recursion limit for template includes is implemented to | ||||||
111 | prevent infinite recursions. Use this method to override the | ||||||
112 | default value (10). | ||||||
113 | |||||||
114 | =cut | ||||||
115 | |||||||
116 | sub set_recursion_limit { | ||||||
117 | 2 | 2 | 1 | 13 | my($self, $limit) = @_; | ||
118 | |||||||
119 | 2 | 50 | 24 | $self->{'recursion_limit'} = $limit | |||
120 | unless $limit !~ m/^\d+$/; | ||||||
121 | |||||||
122 | 2 | 6 | return; | ||||
123 | } | ||||||
124 | |||||||
125 | #================================================================== | ||||||
126 | |||||||
127 | =item $template->set(NAME => $value); | ||||||
128 | |||||||
129 | Sets template variable to given value. | ||||||
130 | |||||||
131 | =cut | ||||||
132 | |||||||
133 | sub set { | ||||||
134 | 8 | 8 | 1 | 57 | my($self, @arguments) = @_; | ||
135 | |||||||
136 | 8 | 21 | while(my $name = shift @arguments) { | ||||
137 | 28 | 30 | my $value = shift @arguments; | ||||
138 | 28 | 50 | 57 | $value = '' unless defined $value; | |||
139 | 28 | 105 | $self->{'vars'}{uc $name} = $value; | ||||
140 | } | ||||||
141 | |||||||
142 | 8 | 19 | return; | ||||
143 | } | ||||||
144 | |||||||
145 | #================================================================== | ||||||
146 | |||||||
147 | =item $template->clear(); | ||||||
148 | |||||||
149 | Clears template variables. Useful when processing table row | ||||||
150 | templates. | ||||||
151 | |||||||
152 | =cut | ||||||
153 | |||||||
154 | sub clear { | ||||||
155 | 2 | 2 | 1 | 9 | my($self) = @_; | ||
156 | |||||||
157 | 2 | 5 | $self->{'vars'} = {}; | ||||
158 | |||||||
159 | 2 | 10 | return; | ||||
160 | } | ||||||
161 | |||||||
162 | #================================================================== | ||||||
163 | |||||||
164 | =item $template->render(); | ||||||
165 | |||||||
166 | Renders template by performing variable substitutions. | ||||||
167 | |||||||
168 | =cut | ||||||
169 | |||||||
170 | =item $template->render(@variables); | ||||||
171 | |||||||
172 | Renders template by performing variable substitutions on only those | ||||||
173 | variable names specified in @variables. | ||||||
174 | |||||||
175 | =cut | ||||||
176 | |||||||
177 | sub render { | ||||||
178 | 2 | 2 | 1 | 17 | my($self, @variables) = @_; | ||
179 | |||||||
180 | 2 | 5 | $self->{'recursion_level'} = 0; | ||||
181 | 2 | 11 | return $self->_substitute($self->{'source'}, @variables); | ||||
182 | } | ||||||
183 | |||||||
184 | |||||||
185 | |||||||
186 | #================================================================== | ||||||
187 | |||||||
188 | sub _substitute { | ||||||
189 | 218 | 218 | 662 | my($self, $source, @variables) = @_; | |||
190 | |||||||
191 | 218 | 1443 | $source =~ s/\$([0-9_A-Z]+)(\(([^)]+)\))?(\n?)/ | ||||
192 | 146 | 100 | 100 | 1894 | if($1 eq 'SET' and defined $2) { | ||
100 | 100 | ||||||
100 | |||||||
193 | 6 | 50 | 38 | if($3 =~ m%^([0-9_A-Z]+)\s*,\s*"([^"]+)"$%) { | |||
194 | 6 | 26 | $self->{'vars'}{$1} = $2 | ||||
195 | } | ||||||
196 | 6 | 33 | ""; | ||||
197 | } elsif($1 eq 'INCLUDE' and defined $2) { | ||||||
198 | 110 | 100 | 261 | if($self->{'recursion_level'} < $self->{'recursion_limit'}) { | |||
199 | 108 | 410 | $self->_include($self->_substitute($3), @variables).$4 | ||||
200 | } else { | ||||||
201 | 2 | 13 | "[ include recursion limit exceeded ]$4" | ||||
202 | } | ||||||
203 | } elsif($#variables > 0) { | ||||||
204 | 14 | 50 | 30 | if($self->_is_in_array($1, @variables)) { | |||
205 | 14 | 73 | $self->{'vars'}{$1}.$4 | ||||
206 | } else { | ||||||
207 | 0 | 0 | $4 | ||||
208 | } | ||||||
209 | } else { | ||||||
210 | 16 | 88 | $self->{'vars'}{$1}.$4 | ||||
211 | } | ||||||
212 | /egm; | ||||||
213 | |||||||
214 | 218 | 761 | return $source; | ||||
215 | } | ||||||
216 | |||||||
217 | #================================================================== | ||||||
218 | |||||||
219 | sub _include { | ||||||
220 | 108 | 108 | 253 | my($self, $template, @variables) = @_; | |||
221 | |||||||
222 | 108 | 115 | my $source; | ||||
223 | 108 | 50 | 3745 | open TEMPLATE, $template or return "[ $template: $! ]"; | |||
224 | 108 | 2370 | while() { $source .= $_ } | ||||
108 | 873 | ||||||
225 | 108 | 1307 | close TEMPLATE; | ||||
226 | 108 | 156 | chomp $source; | ||||
227 | |||||||
228 | 108 | 187 | $self->{'recursion_level'}++; | ||||
229 | 108 | 296 | $source = $self->_substitute($source, @variables); | ||||
230 | 108 | 144 | $self->{'recursion_level'}--; | ||||
231 | |||||||
232 | 108 | 424 | return $source; | ||||
233 | } | ||||||
234 | |||||||
235 | #================================================================== | ||||||
236 | |||||||
237 | sub _is_in_array { | ||||||
238 | 14 | 14 | 40 | my($self, $element, @array) = @_; | |||
239 | |||||||
240 | 14 | 34 | for my $index (0..$#array) { | ||||
241 | 65 | 100 | 143 | return 1 unless $element ne $array[$index]; | |||
242 | } | ||||||
243 | |||||||
244 | 0 | return 0; | |||||
245 | } | ||||||
246 | |||||||
247 | |||||||
248 | |||||||
249 | 1; | ||||||
250 | __END__ |