1 #============================================================= -*-Perl-*-
3 # Template::Plugin::Filter
6 # Template Toolkit module implementing a base class plugin
7 # object which acts like a filter and can be used with the
11 # Andy Wardley <abw@wardley.org>
14 # Copyright (C) 2001-2009 Andy Wardley. All Rights Reserved.
16 # This module is free software; you can redistribute it and/or
17 # modify it under the same terms as Perl itself.
19 #============================================================================
21 package Template::Plugin::Filter;
25 use base 'Template::Plugin';
26 use Scalar::Util 'weaken';
30 our $DYNAMIC = 0 unless defined $DYNAMIC;
34 my ($class, $context, @args) = @_;
35 my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
41 $dynamic = ${"$class\::DYNAMIC"};
43 $dynamic = $DYNAMIC unless defined $dynamic;
52 return $self->init($config)
53 || $class->error($self->error());
58 my ($self, $config) = @_;
67 # This causes problems: https://rt.cpan.org/Ticket/Display.html?id=46691
68 # If the plugin is loaded twice in different templates (one INCLUDEd into
69 # another) then the filter gets garbage collected when the inner template
70 # ends (at least, I think that's what's happening). So I'm going to take
71 # the "suck it and see" approach, comment it out, and wait for someone to
72 # complain that this module is leaking memory.
76 if ($self->{ _DYNAMIC }) {
77 return $self->{ _DYNAMIC_FILTER } ||= [ sub {
78 my ($context, @args) = @_;
79 my $config = ref $args[-1] eq 'HASH' ? pop(@args) : { };
82 $this->filter(shift, \@args, $config);
87 return $self->{ _STATIC_FILTER } ||= sub {
94 my ($self, $text, $args, $config) = @_;
100 my ($self, $newcfg) = @_;
101 my $owncfg = $self->{ _CONFIG };
102 return $owncfg unless $newcfg;
103 return { %$owncfg, %$newcfg };
108 my ($self, $newargs) = @_;
109 my $ownargs = $self->{ _ARGS };
110 return $ownargs unless $newargs;
111 return [ @$ownargs, @$newargs ];
116 my ($self, $name) = @_;
117 $self->{ _CONTEXT }->define_filter( $name => $self->factory );
129 Template::Plugin::Filter - Base class for plugin filters
133 package MyOrg::Template::Plugin::MyFilter;
135 use Template::Plugin::Filter;
136 use base qw( Template::Plugin::Filter );
139 my ($self, $text) = @_;
141 # ...mungify $text...
149 # ...and use the returned object as a filter
150 [% FILTER $MyFilter %]
156 This module implements a base class for plugin filters. It hides
157 the underlying complexity involved in creating and using filters
158 that get defined and made available by loading a plugin.
160 To use the module, simply create your own plugin module that is
161 inherited from the C<Template::Plugin::Filter> class.
163 package MyOrg::Template::Plugin::MyFilter;
165 use Template::Plugin::Filter;
166 use base qw( Template::Plugin::Filter );
168 Then simply define your C<filter()> method. When called, you get
169 passed a reference to your plugin object (C<$self>) and the text
173 my ($self, $text) = @_;
175 # ...mungify $text...
180 To use your custom plugin, you have to make sure that the Template
181 Toolkit knows about your plugin namespace.
183 my $tt2 = Template->new({
184 PLUGIN_BASE => 'MyOrg::Template::Plugin',
187 Or for individual plugins you can do it like this:
189 my $tt2 = Template->new({
191 MyFilter => 'MyOrg::Template::Plugin::MyFilter',
195 Then you C<USE> your plugin in the normal way.
199 The object returned is stored in the variable of the same name,
200 'C<MyFilter>'. When you come to use it as a C<FILTER>, you should add
201 a dollar prefix. This indicates that you want to use the filter
202 stored in the variable 'C<MyFilter>' rather than the filter named
203 'C<MyFilter>', which is an entirely different thing (see later for
204 information on defining filters by name).
206 [% FILTER $MyFilter %]
207 ...text to be filtered...
210 You can, of course, assign it to a different variable.
212 [% USE blat = MyFilter %]
215 ...text to be filtered...
218 Any configuration parameters passed to the plugin constructor from the
219 C<USE> directive are stored internally in the object for inspection by
220 the C<filter()> method (or indeed any other method). Positional
221 arguments are stored as a reference to a list in the C<_ARGS> item while
222 named configuration parameters are stored as a reference to a hash
223 array in the C<_CONFIG> item.
225 For example, loading a plugin as shown here:
227 [% USE blat = MyFilter 'foo' 'bar' baz = 'blam' %]
229 would allow the C<filter()> method to do something like this:
232 my ($self, $text) = @_;
234 my $args = $self->{ _ARGS }; # [ 'foo', 'bar' ]
235 my $conf = $self->{ _CONFIG }; # { baz => 'blam' }
242 By default, plugins derived from this module will create static
243 filters. A static filter is created once when the plugin gets
244 loaded via the C<USE> directive and re-used for all subsequent
245 C<FILTER> operations. That means that any argument specified with
246 the C<FILTER> directive are ignored.
248 Dynamic filters, on the other hand, are re-created each time
249 they are used by a C<FILTER> directive. This allows them to act
250 on any parameters passed from the C<FILTER> directive and modify
251 their behaviour accordingly.
253 There are two ways to create a dynamic filter. The first is to
254 define a C<$DYNAMIC> class variable set to a true value.
256 package MyOrg::Template::Plugin::MyFilter;
257 use base 'Template::Plugin::Filter';
260 The other way is to set the internal C<_DYNAMIC> value within the C<init()>
261 method which gets called by the C<new()> constructor.
265 $self->{ _DYNAMIC } = 1;
269 When this is set to a true value, the plugin will automatically
270 create a dynamic filter. The outcome is that the C<filter()> method
271 will now also get passed a reference to an array of postional
272 arguments and a reference to a hash array of named parameters.
274 So, using a plugin filter like this:
276 [% FILTER $blat 'foo' 'bar' baz = 'blam' %]
278 would allow the C<filter()> method to work like this:
281 my ($self, $text, $args, $conf) = @_;
283 # $args = [ 'foo', 'bar' ]
284 # $conf = { baz => 'blam' }
287 In this case can pass parameters to both the USE and FILTER directives,
288 so your filter() method should probably take that into account.
290 [% USE MyFilter 'foo' wiz => 'waz' %]
292 [% FILTER $MyFilter 'bar' biz => 'baz' %]
296 You can use the C<merge_args()> and C<merge_config()> methods to do a quick
297 and easy job of merging the local (e.g. C<FILTER>) parameters with the
298 internal (e.g. C<USE>) values and returning new sets of conglomerated
302 my ($self, $text, $args, $conf) = @_;
304 $args = $self->merge_args($args);
305 $conf = $self->merge_config($conf);
307 # $args = [ 'foo', 'bar' ]
308 # $conf = { wiz => 'waz', biz => 'baz' }
312 You can also have your plugin install itself as a named filter by
313 calling the C<install_filter()> method from the C<init()> method. You
314 should provide a name for the filter, something that you might
315 like to make a configuration option.
319 my $name = $self->{ _CONFIG }->{ name } || 'myfilter';
320 $self->install_filter($name);
324 This allows the plugin filter to be used as follows:
328 [% FILTER myfilter %]
334 [% USE MyFilter name = 'swipe' %]
340 Alternately, you can allow a filter name to be specified as the
341 first positional argument.
345 my $name = $self->{ _ARGS }->[0] || 'myfilter';
346 $self->install_filter($name);
350 [% USE MyFilter 'swipe' %]
358 Here's a complete example of a plugin filter module.
360 package My::Template::Plugin::Change;
361 use Template::Plugin::Filter;
362 use base qw( Template::Plugin::Filter );
367 $self->{ _DYNAMIC } = 1;
369 # first arg can specify filter name
370 $self->install_filter($self->{ _ARGS }->[0] || 'change');
376 my ($self, $text, $args, $config) = @_;
378 $config = $self->merge_config($config);
379 my $regex = join('|', keys %$config);
381 $text =~ s/($regex)/$config->{ $1 }/ge;
390 Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
394 Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved.
396 This module is free software; you can redistribute it and/or
397 modify it under the same terms as Perl itself.
401 L<Template::Plugin>, L<Template::Filters>, L<Template::Manual::Filters>
407 # perl-indent-level: 4
408 # indent-tabs-mode: nil
411 # vim: expandtab shiftwidth=4: