Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / i486-linux-gnu-thread-multi / Template / Plugin / Filter.pm
1 #============================================================= -*-Perl-*-
2 #
3 # Template::Plugin::Filter
4 #
5 # DESCRIPTION
6 #   Template Toolkit module implementing a base class plugin
7 #   object which acts like a filter and can be used with the 
8 #   FILTER directive.
9 #
10 # AUTHOR
11 #   Andy Wardley   <abw@wardley.org>
12 #
13 # COPYRIGHT
14 #   Copyright (C) 2001-2009 Andy Wardley.  All Rights Reserved.
15 #
16 #   This module is free software; you can redistribute it and/or
17 #   modify it under the same terms as Perl itself.
18 #
19 #============================================================================
20
21 package Template::Plugin::Filter;
22
23 use strict;
24 use warnings;
25 use base 'Template::Plugin';
26 use Scalar::Util 'weaken';
27
28
29 our $VERSION = 1.38;
30 our $DYNAMIC = 0 unless defined $DYNAMIC;
31
32
33 sub new {
34     my ($class, $context, @args) = @_;
35     my $config = @args && ref $args[-1] eq 'HASH' ? pop(@args) : { };
36
37     # look for $DYNAMIC
38     my $dynamic;
39     {
40         no strict 'refs';
41         $dynamic = ${"$class\::DYNAMIC"};
42     }
43     $dynamic = $DYNAMIC unless defined $dynamic;
44
45     my $self = bless {
46         _CONTEXT => $context,
47         _DYNAMIC => $dynamic,
48         _ARGS    => \@args,
49         _CONFIG  => $config,
50     }, $class;
51
52     return $self->init($config)
53         || $class->error($self->error());
54 }
55
56
57 sub init {
58     my ($self, $config) = @_;
59     return $self;
60 }
61
62
63 sub factory {
64     my $self = shift;
65     my $this = $self;
66     
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.  
73     
74     # weaken($this);
75
76     if ($self->{ _DYNAMIC }) {
77         return $self->{ _DYNAMIC_FILTER } ||= [ sub {
78             my ($context, @args) = @_;
79             my $config = ref $args[-1] eq 'HASH' ? pop(@args) : { };
80
81             return sub {
82                 $this->filter(shift, \@args, $config);
83             };
84         }, 1 ];
85     }
86     else {
87         return $self->{ _STATIC_FILTER } ||= sub {
88             $this->filter(shift);
89         };
90     }
91 }
92
93 sub filter {
94     my ($self, $text, $args, $config) = @_;
95     return $text;
96 }
97
98
99 sub merge_config {
100     my ($self, $newcfg) = @_;
101     my $owncfg = $self->{ _CONFIG };
102     return $owncfg unless $newcfg;
103     return { %$owncfg, %$newcfg };
104 }
105
106
107 sub merge_args {
108     my ($self, $newargs) = @_;
109     my $ownargs = $self->{ _ARGS };
110     return $ownargs unless $newargs;
111     return [ @$ownargs, @$newargs ];
112 }
113
114
115 sub install_filter {
116     my ($self, $name) = @_;
117     $self->{ _CONTEXT }->define_filter( $name => $self->factory );
118     return $self;
119 }
120
121
122
123 1;
124
125 __END__
126
127 =head1 NAME
128
129 Template::Plugin::Filter - Base class for plugin filters
130
131 =head1 SYNOPSIS
132
133     package MyOrg::Template::Plugin::MyFilter;
134     
135     use Template::Plugin::Filter;
136     use base qw( Template::Plugin::Filter );
137     
138     sub filter {
139         my ($self, $text) = @_;
140         
141         # ...mungify $text...
142         
143         return $text;
144     }
145
146     # now load it...
147     [% USE MyFilter %]
148     
149     # ...and use the returned object as a filter
150     [% FILTER $MyFilter %]
151       ...
152     [% END %]
153
154 =head1 DESCRIPTION
155
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.
159
160 To use the module, simply create your own plugin module that is 
161 inherited from the C<Template::Plugin::Filter> class.
162
163     package MyOrg::Template::Plugin::MyFilter;
164     
165     use Template::Plugin::Filter;
166     use base qw( Template::Plugin::Filter );
167
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
170 to be filtered.
171
172     sub filter {
173         my ($self, $text) = @_;
174         
175         # ...mungify $text...
176         
177         return $text;
178     }
179
180 To use your custom plugin, you have to make sure that the Template
181 Toolkit knows about your plugin namespace.
182
183     my $tt2 = Template->new({
184         PLUGIN_BASE => 'MyOrg::Template::Plugin',
185     });
186
187 Or for individual plugins you can do it like this:
188
189     my $tt2 = Template->new({
190         PLUGINS => {
191             MyFilter => 'MyOrg::Template::Plugin::MyFilter',
192         },
193     });
194
195 Then you C<USE> your plugin in the normal way.
196
197     [% USE MyFilter %]
198
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).
205
206     [% FILTER $MyFilter %]
207        ...text to be filtered...
208     [% END %]
209
210 You can, of course, assign it to a different variable.
211
212     [% USE blat = MyFilter %]
213     
214     [% FILTER $blat %]
215        ...text to be filtered...
216     [% END %]
217
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.
224
225 For example, loading a plugin as shown here:
226
227     [% USE blat = MyFilter 'foo' 'bar' baz = 'blam' %]
228
229 would allow the C<filter()> method to do something like this:
230
231     sub filter {
232         my ($self, $text) = @_;
233         
234         my $args = $self->{ _ARGS   };  # [ 'foo', 'bar' ]
235         my $conf = $self->{ _CONFIG };  # { baz => 'blam' }
236         
237         # ...munge $text...
238         
239         return $text;
240     }
241
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.
247
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.  
252
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.
255
256     package MyOrg::Template::Plugin::MyFilter;
257     use base 'Template::Plugin::Filter';
258     our $DYNAMIC = 1;
259
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.
262
263     sub init {
264         my $self = shift;
265         $self->{ _DYNAMIC } = 1;
266         return $self;
267     }
268
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.
273
274 So, using a plugin filter like this:
275
276     [% FILTER $blat 'foo' 'bar' baz = 'blam' %]
277
278 would allow the C<filter()> method to work like this:
279
280     sub filter {
281         my ($self, $text, $args, $conf) = @_;
282         
283         # $args = [ 'foo', 'bar' ]
284         # $conf = { baz => 'blam' }
285     }
286
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.  
289
290     [% USE MyFilter 'foo' wiz => 'waz' %]
291     
292     [% FILTER $MyFilter 'bar' biz => 'baz' %]
293        ...
294     [% END %]
295
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
299 data.
300
301     sub filter {
302         my ($self, $text, $args, $conf) = @_;
303         
304         $args = $self->merge_args($args); 
305         $conf = $self->merge_config($conf);
306         
307         # $args = [ 'foo', 'bar' ]      
308         # $conf = { wiz => 'waz', biz => 'baz' }        
309         ...
310     }
311
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.
316
317     sub init {
318         my $self = shift;
319         my $name = $self->{ _CONFIG }->{ name } || 'myfilter';
320         $self->install_filter($name);
321         return $self;
322     }
323
324 This allows the plugin filter to be used as follows:
325
326     [% USE MyFilter %]
327     
328     [% FILTER myfilter %] 
329        ... 
330     [% END %]
331
332 or
333
334     [% USE MyFilter name = 'swipe' %]
335         
336     [% FILTER swipe %] 
337        ... 
338     [% END %]
339
340 Alternately, you can allow a filter name to be specified as the 
341 first positional argument.
342
343     sub init {
344         my $self = shift;
345         my $name = $self->{ _ARGS }->[0] || 'myfilter';
346         $self->install_filter($name);
347         return $self;
348     }
349
350     [% USE MyFilter 'swipe' %]
351     
352     [% FILTER swipe %]
353        ...
354     [% END %]
355
356 =head1 EXAMPLE
357
358 Here's a complete example of a plugin filter module.
359
360     package My::Template::Plugin::Change;
361     use Template::Plugin::Filter;
362     use base qw( Template::Plugin::Filter );
363     
364     sub init {
365         my $self = shift;
366         
367         $self->{ _DYNAMIC } = 1;
368         
369         # first arg can specify filter name
370         $self->install_filter($self->{ _ARGS }->[0] || 'change');
371         
372         return $self;
373     }
374     
375     sub filter {
376         my ($self, $text, $args, $config) = @_;
377         
378         $config = $self->merge_config($config);
379         my $regex = join('|', keys %$config);
380         
381         $text =~ s/($regex)/$config->{ $1 }/ge;
382         
383         return $text;
384     }
385     
386     1;
387
388 =head1 AUTHOR
389
390 Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/>
391
392 =head1 COPYRIGHT
393
394 Copyright (C) 1996-2007 Andy Wardley.  All Rights Reserved.
395
396 This module is free software; you can redistribute it and/or
397 modify it under the same terms as Perl itself.
398
399 =head1 SEE ALSO
400
401 L<Template::Plugin>, L<Template::Filters>, L<Template::Manual::Filters>
402
403 =cut
404
405 # Local Variables:
406 # mode: perl
407 # perl-indent-level: 4
408 # indent-tabs-mode: nil
409 # End:
410 #
411 # vim: expandtab shiftwidth=4: