Introduction to Template::Toolkit

Post on 07-Jul-2015

298 views 0 download

Tags:

description

London Perl Workshop 2012 Slides

Transcript of Introduction to Template::Toolkit

Introduction To Template::Toolkit

IntroductionBasics: Part One

Exercises (Hands On)Basics: Part Two

Exercises (Hands On)References and Further Reading

Introduction

•Who am I?•What level of Perl expertise is required?•What is Template::Toolkit?

Part One

•Simple mail-merge type example

Template for a letter

Dear [% name %], It has come to our attention that your account is in arrears to the sum of [% debt %]. Please settle your account before [% deadline %] or we will be forced to revoke your Licence to Thrill. The Management.

Perl script to call ituse strict;use Template;my $tt = Template->new({ INCLUDE_PATH => '/usr/local/templates', INTERPOLATE => 1,}) || die "$Template::ERROR\n";

my $vars = { name => 'Count Edward van Halen', debt => '3 riffs and a solo', deadline => 'the next chorus', }; $tt->process('letters/overdrawn', $vars) || die $tt->error(), "\n";

Multiple letters

[% FOREACH d IN debtors %]Dear [% d.name %], It has come to our attention that your account is in arrears to the sum of [% d.debt %]. Please settle your account before [% d.deadline %] or we will be forced to revoke your Licence to Thrill. The Management.[% END %]

Perl fragmentmy $vars = { debtors => [ { name => 'Count Edward van Halen', debt => '3 riffs and a solo', deadline => 'the next chorus', }, { name => ‘Baron Eric Clapton', debt => ‘1 badge', deadline => ‘tomorrow', }]}; $tt->process('letters/overdrawn', $vars) || die $tt->error(), "\n";

Multiple letters with logic[% FOREACH d = debtors %]Dear [% d.name %], It has come to our attention that your account is in arrears to the sum of [% d.debt %]. Please settle your account before [% d.deadline %] or we will be forced to revoke your Licence to Thrill.

[% IF d.final %]This is your last chance.[% END %] The Management.[% END %]

Perl fragmentmy $debtors = [ { name => 'Count Edward van Halen', debt => '3 riffs and a solo', deadline => 'the next chorus', }, { name => ‘Baron Eric Clapton', debt => ‘1 badge', deadline => ‘tomorrow', final => 1 }]; $tt->process('letters/overdrawn', $debtors) || die $tt->error(), "\n";

Boolean logic: IF ELSE[% IF age < 10 %][% ELSIF age < 18 %][% ELSE %][% END %]

The following conditional and boolean operators may be used: == != < <= > >= && || ! and or not

Boolean logic: SWITCH

[% SWITCH myvar %][% CASE 'value1' %][% CASE ['value2', 'value3'] %] # multiple values[% CASE myhash.keys %] # ditto[% CASE %] # default[% END %]

Alternative contents[% FOREACH d IN debtors %]Dear [% d.name %], Thank you for your recent payment of [% d.debt %]. Your account is now clear and you may continue to thrill. The Management.[% END %]

Include other templates[% FOREACH d IN debtors %]Dear [% d.name %], [% IF d.angry -%][% INCLUDE angry_letter.tt2 %][% ELSE -%][% INCLUDE grateful_letter.tt2 %][% END -%] The Management.[% END %]

Perl fragmentmy $debtors = [ { name => 'Count Edward van Halen', debt => '3 riffs and a solo', deadline => 'the next chorus', }, { name => ‘Baron Eric Clapton', debt => ‘1 badge', deadline => ‘tomorrow', final => 1, angry => 1, }]; $tt->process('letters/overdrawn', $debtors) || die $tt->error(), "\n";

Exercises

Part Two•Adding a wrapper for the header and footer•Adding simple filters to encoding entities or control case•Using a vmethod to add row numbers•Sorting a select list•Formatting currency

Adding a wrapperContent-Type: text/html; charset=ISO-8859-1

<html><head></head><body><h1>Introduction to TT</h2>

[%# Header and footer will be the same on all pages %]

<table><tr><th>Something</th><th>Something Else</th></tr>[% FOREACH r IN rows %]<tr><td>[% r.something %]</td><td>[% r.something_else %]</td></tr>[% END %]</table>

</body></html>

Move the common content to wrapper.tt

Content-Type: text/html; charset=ISO-8859-1

<html><head></head><body><h1>Introduction to TT</h2>

[% content %]

</body></html>

Tell TT about the wrapper#! /usr/bin/perl

use strict; use warnings; use CGI; use Template;

# Using a wrapper.

my $tt = Template->new( { INCLUDE_PATH => '/home/duncan/tt/htdocs/tt2', INTERPOLATE => 1, WRAPPER => 'wrapper.tt2' }) || die "$Template::ERROR\n";

$tt->process( 's2.tt2', { rows => [ { something => 'apples', something_else => '1 kg' }, { something => 'pears', something_else => '2 kg' } ] }) || die $tt->error() . "\n";

Dodgy datamy $tt = Template->new( { INCLUDE_PATH => '/home/duncan/tt/htdocs/tt2', INTERPOLATE => 1, WRAPPER => 'wrapper.tt2' }) || die "$Template::ERROR\n";

$tt->process( 's2.tt2', { rows => [ { something => 'apples', something_else => '1 kg' }, { something => 'pears', something_else => '2 kg' }, { something => 'turnips > pears > grapes', something_else => '2 & 3 kg' }, { something => '<script type="text/javascript">alert("Hi");</script>', something_else => '2 & 3 kg' }, ] }) || die $tt->error() . "\n";

Encode it!<! [% component.name %] -->

[%# Using a filter to encode entities and control case. %]

<table><tr><th>Something</th><th>Something Else</th></tr>[% FOREACH r IN rows %]<tr><td>[% r.something FILTER html_entity %]</td><td>[% r.something_else FILTER html_entity FILTER upper %]</td></tr>[% END %]</table><!-- End [% component.name %] -->

That’s better<tr><td>apples</td><td>1 KG</td></tr> <tr><td>pears</td><td>2 KG</td></tr>

<tr><td>turnips &gt; pears &gt; grapes</td><td>2 &amp; 3 KG</td></tr>

<tr><td>&lt;script type=&quot;text/javascript&quot;&gt;alert(&quot;Hi&quot;);&lt;/script&gt;</td><td>2 &amp; 3 KG</td></tr>

Use a vmethod to add row numbers

<! [% component.name %] -->

[%# Using a vmethod to add row number %]

<table><tr><th>No</th><th>Something</th><th>Something Else</th></tr>[% FOREACH r IN rows %]<tr><td>([% loop.index %])</td><td>[% r.something FILTER html_entity %]</td><td>[% r.something_else FILTER html_entity FILTER upper %]</td></tr>[% END %]</table><!-- End [% component.name %] -->

With row numbers

No Something Something Else

(0) apples 1 KG

(1) pears 2 KG

(2) turnips > pears > grapes 2 & 3 KG

(3) <>peas 2 & 3 KG

(4) apricots 2 & 3 KG

Use a vmethod to do a simple sort on a select list.

my $tt = Template->new( { INCLUDE_PATH => '/home/duncan/tt/htdocs/tt2', INTERPOLATE => 1, WRAPPER => 'wrapper.tt2' }) || die "$Template::ERROR\n";

$tt->process( 's5.tt2', { rows => [ { something => 'apples', something_else => '1 kg' }, { something => 'pears', something_else => '2 kg' }, { something => 'turnips > pears > grapes', something_else => '2 & 3 kg' }, { something => '<>peas', something_else => '2 & 3 kg' }, { something => 'apricots', something_else => '2 & 3 kg' }, ], suppliers => [ 'Fred', 'Alan', 'Joe', 'Bert' ] }) || die $tt->error() . "\n";

Adding the sort vmethod[%# Using a vmethod to do a simple sort on a select list %]

<! [% component.name %] -->

<select>[% FOREACH s IN suppliers.sort %]<option value="s"/>[% s %][% END %]</select>

<table><tr><th>No</th><th>Something</th><th>Something Else</th></tr>[% FOREACH r IN rows %]<tr><td> ([% loop.index %])</td><td>[% r.something FILTER html_entity %]</td><td>[% r.something_else FILTER html_entity FILTER upper %]</td></tr>[% END %]</table><!-- End [% component.name %] -->

Using the Format plugin on currency

No Something Something Else Cost

(0) apples 1 KG £5.67

(1) pears 2 KG £3.33333333333333

(2) turnips > pears > grapes 2 & 3 KG £4.123

(3) <>peas 2 & 3 KG £2

(4) apricots 2 & 3 KG £3

The script with the plugin[% USE money=format('%.2f') -%]

<select>[% FOREACH s IN suppliers.sort %]<option value="s"/>[% s %][% END %]</select>

<table><tr><th>No</th><th>Something</th><th>Something Else</th><th>Cost</ht></tr>[% FOREACH r IN rows %]<tr><td> ([% loop.index %])</td><td>[% r.something FILTER html_entity %]</td><td>[% r.something_else FILTER html_entity FILTER upper %]</td><td>&pound;[% money(r.cost) %]</td></tr>[% END %]</table><!-- End [% component.name %] -->

Further Reading

Template Toolkit [Paperback] •Darren Chamberlain,

•Dave Cross, •Andy Wardley

Also documented on MetaCPAN: https://metacpan.org/

It has its own website: http://www.template-toolkit.org/

226 plugins listed on MetaCPAN