1Template::Manual::InterUnsaelrs(C3o)ntributed Perl DocumTeenmtpaltaitoen::Manual::Internals(3)
2
3
4

NAME

6       Template::Manual::Internals - Template Toolkit internals
7

Introduction

9       This section of the documentation is aimed at developers wishing to
10       know more about how the Template Toolkit works on the inside in order
11       to extend or adapt it to their own needs.
12
13       If that doesn't sound like you then you probably don't need to read
14       this.  There is no test afterwards.
15

Outside Looking In

17       The Template module is simply a front end module which creates and uses
18       a Template::Service and pipes the output wherever you want it to go
19       ("STDOUT" by default, or maybe a file, scalar, etc).  The
20       "Apache::Template" module (available separately from CPAN) is another
21       front end.  That creates a "Template::Service::Apache" object, calls on
22       it as required and sends the output back to the relevant
23       "Apache::Request" object.
24
25       These front-end modules are really only there to handle any specifics
26       of the environment in which they're being used.  The "Apache::Template"
27       front end, for example, handles "Apache::Request" specifics and
28       configuration via the httpd.conf.  The regular Template front-end deals
29       with "STDOUT", variable refs, etc.  Otherwise it is Template::Service
30       (or subclass) which does all the work.
31
32       The Template::Service module provides a high-quality template delivery
33       service, with bells, whistles, signed up service level agreement and a
34       30-day no quibble money back guarantee.  "Have a good time, all the
35       time", that's our motto.
36
37       Within the lower levels of the Template Toolkit, there are lots of
38       messy details that we generally don't want to have to worry about most
39       of the time.  Things like templates not being found, or failing to
40       parse correctly, uncaught exceptions being thrown, missing plugin
41       modules or dependencies, and so on.  Template::Service hides that all
42       away and makes everything look simple to the outsider. It provides
43       extra features, like "PRE_PROCESS", "PROCESS" and "POST_PROCESS", and
44       also provides the error recovery mechanism via "ERROR".  You ask it to
45       process a template and it takes care of everything for you. The
46       "Template::Service::Apache" module goes a little bit further, adding
47       some extra headers to the Apache::Request, setting a few extra template
48       variables, and so on.
49
50       For the most part, the job of a service is really just one of
51       scheduling and dispatching. It receives a request in the form of a call
52       to its process() method and schedules the named template specified as
53       an argument, and possibly several other templates ("PRE_PROCESS", etc)
54       to be processed in order. It doesn't actually process the templates
55       itself, but instead makes a process() call against a Template::Context
56       object.
57
58       Template::Context is the runtime engine for the Template Toolkit - the
59       module that hangs everything together in the lower levels of the
60       Template Toolkit and that one that does most of the real work, albeit
61       by crafty delegation to various other friendly helper modules.
62
63       Given a template name (or perhaps a reference to a scalar or file
64       handle) the context process() method must load and compile, or fetch a
65       cached copy of a previously compiled template, corresponding to that
66       name.  It does this by calling on a list of one or more
67       Template::Provider objects (the "LOAD_TEMPLATES" posse) who themselves
68       might get involved with a Template::Parser to help turn source
69       templates into executable Perl code (but more on that later).
70
71       Thankfully, all of this complexity is hidden away behind a simple
72       template() method. You call it passing a template name as an argument,
73       and it returns a compiled template in the form of a Template::Document
74       object, or otherwise raises an exception.
75
76       A Template::Document is a thin object wrapper around a compiled
77       template subroutine. The object implements a process() method which
78       performs a little bit of housekeeping and then calls the template
79       subroutine. The object also defines template metadata (defined in "[%
80       META ... %]" directives) and has a block() method which returns a hash
81       of any additional "[% BLOCK xxxx %]" definitions found in the template
82       source.
83
84       So the context fetches a compiled document via its own template()
85       method and then gets ready to process it. It first updates the stash
86       (the place where template variables get defined - more on that shortly)
87       to set any template variable definitions specified as the second
88       argument by reference to hash array. Then, it calls the document
89       process() method, passing a reference to itself, the context object, as
90       an argument. In doing this, it provides itself as an object against
91       which template code can make callbacks to access runtime resources and
92       Template Toolkit functionality.
93
94       What we're trying to say here is this:  not only does the
95       Template::Context object receive calls from the outside, i.e. those
96       originating in user code calling the process() method on a Template
97       object, but it also receives calls from the inside, i.e. those
98       originating in template directives of the form "[% PROCESS template
99       %]".
100
101       Before we move on to that, here's a simple structure diagram showing
102       the outer layers of the Template Toolkit heading inwards, with pseudo
103       code annotations showing a typical invocation sequence.
104
105            ,--------.
106            | Caller |     use Template;
107            `--------'     my $tt = Template->new( ... );
108                 |         $tt->process($template, \%vars);
109                 |                                                     Outside
110           - - - | - - - - - - - - - - - - - - - - - - - - - - - - - - - - T T
111                 |         package Template;                            Inside
112                 V
113           +----------+    sub process($template, \%vars) {
114           | Template |        $out = $self->SERVICE->process($template, $vars);
115           +----------+        print $out or send it to $self->OUTPUT;
116                 |         }
117                 |
118                 |         package Template::Service;
119                 |
120                 |         sub process($template, \%vars) {
121                 |             try {
122           +----------+            foreach $p in @self->PRE_PROCESS
123           | Service  |                $self->CONTEXT->process($p, $vars);
124           +----------+
125                 |                 $self->CONTEXT->process($template, $vars);
126                 |
127                 |                 foreach $p @self->POST_PROCESS
128                 |                     $self->CONTEXT->process($p, $vars);
129                 |             }
130                 |             catch {
131                 |                 $self->CONTEXT->process($self->ERROR);
132                 |             }
133                 |         }
134                 |
135                 V         package Template::Context;
136           +----------+
137           | Context  |    sub process($template, \%vars) {
138           +----------+        # fetch compiled template
139                 |             $template = $self->template($template)
140                 |             # update stash
141                 |             $self->STASH->update($vars);
142                 |             # process template
143                 |             $template->process($self)
144                 |         }
145                 V
146           +----------+    package Template::Document;
147           | Document |
148           +----------+    sub process($context) {
149                               $output = &{ $self->BLOCK }($context);
150                           }
151

Inside Looking Out

153       To understand more about what's going on in these lower levels, we need
154       to look at what a compiled template looks like.  In fact, a compiled
155       template is just a regular Perl sub-routine.  Here's a very simple one.
156
157           sub my_compiled_template {
158               return "This is a compiled template.\n";
159           }
160
161       You're unlikely to see a compiled template this simple unless you wrote
162       it yourself but it is entirely valid.  All a template subroutine is
163       obliged to do is return some output (which may be an empty of course).
164       If it can't for some reason, then it should raise an error via "die()".
165
166           sub my_todo_template {
167               die "This template not yet implemented\n";
168           }
169
170       If it wants to get fancy, it can raise an error as a
171       Template::Exception object.  An exception object is really just a
172       convenient wrapper for the '"type"' and '"info"' fields.
173
174           sub my_solilique_template {
175               die (Template::Exception->new('yorrick', 'Fellow of infinite jest'));
176           }
177
178       Templates generally need to do a lot more than just generate static
179       output or raise errors. They may want to inspect variable values,
180       process another template, load a plugin, run a filter, and so on.
181       Whenever a template subroutine is called, it gets passed a reference to
182       a Template::Context object. It is through this context object that
183       template code can access the features of the Template Toolkit.
184
185       We described earlier how the Template::Service object calls on
186       Template::Context to handle a process() request from the outside. We
187       can make a similar request on a context to process a template, but from
188       within the code of another template. This is a call from the inside.
189
190           sub my_process_template {
191               my $context = shift;
192               my $output = $context->process('header', { title => 'Hello World' })
193                          . "\nsome content\n"
194                          . $context->process('footer');
195           }
196
197       This is then roughly equivalent to a source template something like
198       this:
199
200           [% PROCESS header
201               title = 'Hello World'
202           %]
203           some content
204           [% PROCESS footer %]
205
206       Template variables are stored in, and managed by a Template::Stash
207       object.  This is a blessed hash array in which template variables are
208       defined. The object wrapper provides get() and set() method which
209       implement all the magical.variable.features of the Template Toolkit.
210
211       Each context object has its own stash, a reference to which can be
212       returned by the appropriately named stash() method. So to print the
213       value of some template variable, or for example, to represent the
214       following source template:
215
216           <title>[% title %]</title>
217
218       we might have a subroutine definition something like this:
219
220           sub {
221               my $context = shift;
222               my $stash = $context->stash();
223               return '<title>' . $stash->get('title') . '</title>';
224           }
225
226       The stash get() method hides the details of the underlying variable
227       types, automatically calling code references, checking return values,
228       and performing other such tricks. If '"title"' happens to be bound to a
229       subroutine then we can specify additional parameters as a list
230       reference passed as the second argument to get().
231
232           [% title('The Cat Sat on the Mat') %]
233
234       This translates to the stash call:
235
236           $stash->get([ 'title', ['The Cat Sat on the Mat'] ]);
237
238       Dotted compound variables can be requested by passing a single list
239       reference to the "get()" method in place of the variable name.  Each
240       pair of elements in the list should correspond to the variable name and
241       reference to a list of arguments for each dot-delimited element of the
242       variable.
243
244           [% foo(1, 2).bar(3, 4).baz(5) %]
245
246       is thus equivalent to
247
248           $stash->get([ foo => [1,2], bar => [3,4], baz => [5] ]);
249
250       If there aren't any arguments for an element, you can specify an empty,
251       zero or null argument list.
252
253           [% foo.bar %]
254           $stash->get([ 'foo', 0, 'bar', 0 ]);
255
256       The set() method works in a similar way. It takes a variable name and a
257       variable value which should be assigned to it.
258
259           [% x = 10 %]
260           $stash->set('x', 10);
261
262           [% x.y = 10 %]
263           $stash->set([ 'x', 0, 'y', 0 ], 10);
264
265       So the stash gives us access to template variables and the context
266       provides the higher level functionality.
267
268       Alongside the process() method lies the include() method. Just as with
269       the "PROCESS" / "INCLUDE" directives, the key difference is in variable
270       localisation. Before processing a template, the "process()" method
271       simply updates the stash to set any new variable definitions,
272       overwriting any existing values. In contrast, the "include()" method
273       creates a copy of the existing stash, in a process known as cloning the
274       stash, and then uses that as a temporary variable store. Any previously
275       existing variables are still defined, but any changes made to
276       variables, including setting the new variable values passed aas
277       arguments will affect only the local copy of the stash (although note
278       that it's only a shallow copy, so it's not foolproof). When the
279       template has been processed, the "include()" method restores the
280       previous variable state by decloning the stash.
281
282       The context also provides an insert() method to implement the "INSERT"
283       directive, but no "wrapper()" method. This functionality can be
284       implemented by rewriting the Perl code and calling "include()".
285
286           [% WRAPPER foo -%]
287              blah blah [% x %]
288           [%- END %]
289
290           $context->include('foo', {
291               content => 'blah blah ' . $stash->get('x'),
292           });
293
294       Other than the template processing methods "process()", "include()" and
295       "insert()", the context defines methods for fetching plugin objects,
296       plugin(), and filters, filter().
297
298           # TT USE directive
299           [% USE foo = Bar(10) %]
300
301           # equivalent Perl
302           $stash->set('foo', $context->plugin('Bar', [10]));
303
304           # TT FILTER block
305           [% FILTER bar(20) %]
306              blah blah blah
307           [% END %]
308
309           # equivalent Perl
310           my $filter = $context->filter('bar', [20]);
311           &$filter('blah blah blah');
312
313       Pretty much everything else you might want to do in a template can be
314       done in Perl code. Things like "IF", "UNLESS", "FOREACH" and so on all
315       have direct counterparts in Perl.
316
317           # TT IF directive
318           [% IF msg %]
319              Message: [% msg %]
320           [% END %];
321
322           # equivalent Perl
323           if ($stash->get('msg')) {
324               $output .=  'Message: ';
325               $output .= $stash->get('msg');
326           }
327
328       The best way to get a better understanding of what's going on
329       underneath the hood is to set the $Template::Parser::DEBUG flag to a
330       true value and start processing templates.  This will cause the parser
331       to print the generated Perl code for each template it compiles to
332       "STDERR".  You'll probably also want to set the
333       $Template::Directive::PRETTY option to have the Perl pretty-printed for
334       human consumption.
335
336           use Template;
337           use Template::Parser;
338           use Template::Directive;
339
340           $Template::Parser::DEBUG = 1;
341           $Template::Directive::PRETTY = 1;
342
343           my $template = Template->new();
344           $template->process(\*DATA, { cat => 'dog', mat => 'log' });
345
346           __DATA__
347           The [% cat %] sat on the [% mat %]
348
349       The output sent to "STDOUT" remains as you would expect:
350
351           The dog sat on the log
352
353       The output sent to "STDERR" would look something like this:
354
355           compiled main template document block:
356           sub {
357               my $context = shift || die "template sub called without context\n";
358               my $stash   = $context->stash;
359               my $output  = '';
360               my $error;
361
362               eval { BLOCK: {
363                   $output .=  "The ";
364                   $output .=  $stash->get('cat');
365                   $output .=  " sat on the ";
366                   $output .=  $stash->get('mat');
367                   $output .=  "\n";
368               } };
369               if ($@) {
370                   $error = $context->catch($@, \$output);
371                   die $error unless $error->type eq 'return';
372               }
373
374               return $output;
375           }
376

Hacking on the Template Toolkit

378       Please feel free to hack on the Template Toolkit.  If you find a bug
379       that needs fixing, if you have an idea for something that's missing, or
380       you feel inclined to tackle something on the TODO list, then by all
381       means go ahead and do it!
382
383       If you're contemplating something non-trivial then you'll probably want
384       to bring it up on the mailing list first to get an idea about the
385       current state of play, find out if anyone's already working on it, and
386       so on.
387
388       The source code repository for the Template Toolkit is hosted at
389       Github.
390
391           https://github.com/abw/Template2
392
393       Clone the repository, make your changes, commit them, then send a pull
394       request.
395
396       Once you've made your changes, please remember to update the test suite
397       by adding extra tests to one of the existing test scripts in the "t"
398       sub-directory, or by adding a new test script of your own.  And of
399       course, run "make test" to ensure that all the tests pass with your new
400       code.
401
402       Don't forget that any files you do add will need to be added to the
403       MANIFEST.  Running "make manifest" will do this for you, but you need
404       to make sure you haven't got any other temporary files lying around
405       that might also get added to it.
406
407       Documentation is often something that gets overlooked but it's just as
408       important as the code. If you're adding a new module, a plugin module,
409       for example, then it's OK to include the POD documentation in with the
410       module, but please write it all in one piece at the end of the file,
411       after the code (just look at any other "Template::*" module for an
412       example). It's a religious issue, I know, but I have a strong distaste
413       for POD documentation interspersed throughout the code. In my not-so-
414       humble opinion, it makes both the code and the documentation harder to
415       read (same kinda problem as embedding Perl in HTML).
416
417       Then add a line to the Changes file giving a very brief description of
418       what you've done.  There's no need to go into detail here (save that
419       for the commit message, comments in code or docuemtation where
420       appropriate).
421
422       Please also make sure you add your name to the
423       lib/Template/Manual/Credits.pod file (if it isn't already there).
424
425       Then commit your changes and send a pull request.
426
427
428
429perl v5.36.0                      2022-07-22    Template::Manual::Internals(3)
Impressum