While filters are an interface to simple Perl functionality--built-in functions like eval, uc, and sprintf, or simple text substitutions--plugins are used to interface to more complex functions. Typically, they're used to expose the functionality of a Perl module to the format language.
For instance, the Template::Plugin::Autoformat plugin allows one to use Text:: Autoformat's autoformatting functionality. Just as with the Perl module, use the USE directive to tell the format processor to load the plugin. This then exports the autoformat subroutine and a corresponding autoformat filter:
[% USE autoformat(right=78) %] [% address | autoformat %]
This assures that the address is printed in a nice block on the right-hand side of the page.
A particularly neat plugin is the Template::Plugin::XML::Simple module, which allows you to parse an XML data file using XML::Simple and manipulate the resulting data structure from inside a template. Here we use USE to return a value:
[% USE document = XML.Simple("app2ed.xml") %]
And now we have a data structure created from the structure and text of an XML document. We can explore this data structure by entering the elements, just as we did in "XML Parsing" in Chapter 2:
The author of this book is [% document.bookinfo.authorgroup.author.firstname # 'Simon' %] [% document.bookinfo.authorgroup.author.surname # 'Cozens' %]
Actually writing a plugin module like this is surprisingly easy--and, in fact, something we're going to need to do for our RSS example. First, we create a new module called Template::Plugin::Whatever, where Whatever is what we want our plugin to be known as inside the template language. This module will load up whatever module we want to interface to. We'll also need it to inherit from Template::Plugin. Let's go ahead and write an interface to Tony Bowden's Data::BT::PhoneBill, a module for querying UK telephone bills.
package Template::Plugin::PhoneBill; use base 'Template::Plugin'; use Data::BT::PhoneBill;
Now we want to receive a filename when the plugin is USEd and turn that into the appropriate object. Therefore we write a new method to do just that:
sub new { my ($class, $context, $filename) = @_; return Data::BT::PhoneBill->new($filename); }
$context is an object passed by Template Toolkit to represent the context we're being evaluated in. And that's basically it--you can add error checking to make sure the filename exists and that the module can parse the phone bill properly, but the guts of a plugin are as we've shown.
Now that we've created the plugin, we can access the phone bill just like we did with the XML::Simple data structure:
[% USE bill = PhoneBill("mybill.txt") %]
[% WHILE call = bill.next_call %] Call made on [% call.date %] to [% call.number %]... [% END %]
An interesting thing to notice is that when we were using the XML.Simple plugin, we accessed elements of the data structure with the dot operator: document.bookinfo and so on. In that case, we were navigating hash references; the Perl code would have looked like $document->{bookinfo}->{authorgroup}->{author}.... In this example, we're using precisely the same dot operator syntax, but, instead of navigating hash references, we're calling methods: call.date would translate to $call->date. However, it all looks the same to the template writer. This abstraction of the underlying data structure is one of the big strengths of Template Toolkit.