App-Chronicle
view release on metacpan or search on metacpan
lib/Chronicle/Plugin/Filter.pm view on Meta::CPAN
=head1 NAME
Chronicle::Plugin::Filter - Filter individual blog entries.
=head1 DESCRIPTION
This plugin is designed to allow blog entries to be filtered via
external commands.
This is achieved by opening the specified command and using it as
a filter for the entry prior to the insertion into the database.
As an example the following blog-post would be 100% upper-cased:
=for example begin
Title: My Title
Date: 10th March 2015
Filter: tr a-z A-Z
<p>This is a line of text.</p>
=for example end
=cut
=head1 METHODS
Now follows documentation on the available methods.
=cut
package Chronicle::Plugin::Filter;
use strict;
use warnings;
our $VERSION = "5.1.7";
use IPC::Open2;
use Symbol;
=head2 on_insert
The C<on_insert> method is automatically invoked when a new blog post
must be inserted into the SQLite database, that might be because a post
is new, or because it has been updated.
The method is designed to return an updated blog-post structure,
after performing any massaging required. If the method returns undef
then the post is not inserted.
This plugin will look for a series of headers in the blog-post:
=over 8
=item pre-filter
This will be called first.
=item filter
This will be called in the middle.
=item post-filter
This will be called last.
=back
Any such header will be assumed to contain a command that the blog-post
should be piped through. The post itself will be replaced with C<STDOUT>
from that command.
Because only single headers are examined there can be no more than three
filters per-post. This constraint exists for compability purposes.
=cut
sub on_insert
{
my ( $self, %args ) = (@_);
my $conf = $args{ 'config' };
my $data = $args{ 'data' };
#
# The filters we run.
#
my @filters;
#
# Look for the following keys in our entry
#
foreach my $filter (qw! pre-filter filter post-filter !)
{
push( @filters, $data->{ $filter } ) if ( $data->{ $filter } );
}
#
# No filters defined? Then return the unmodified post.
#
return ($data) unless ( scalar @filters );
foreach my $filter (@filters)
{
#
# Get the post body
#
my $body = $data->{ 'body' };
#
# Report what we're doing.
#
print "Filtering $data->{'file'} via $filter\n"
if ( $conf->{ 'verbose' } );
#
# Apply the filter.
#
my $WTR = gensym();
my $RDR = gensym();
my $pid = open2( $RDR, $WTR, $filter );
print $WTR $body;
close($WTR);
#
# Get the output
#
my $result = "";
while (<$RDR>)
{
$result .= $_;
}
waitpid $pid, 0;
#
# Store the updated body.
#
$data->{ 'body' } = $result;
}
#
# Return the updated post.
#
return ($data);
}
=head2 _order
We want this plugin to be called I<after> the other plugins which
filter new entries.
This method is present such that L<Module::Pluggable::Ordered> can
order our plugins.
=cut
sub _order
{
return 200;
}
1;
=head1 LICENSE
This module is free software; you can redistribute it and/or modify it
under the terms of either:
a) the GNU General Public License as published by the Free Software
Foundation; either version 2, or (at your option) any later version,
or
b) the Perl "Artistic License".
=cut
=head1 AUTHOR
Steve Kemp <steve@steve.org.uk>
=cut
( run in 2.548 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )