- 2007/6/18 月曜日 2:23:32
- perl
前回のエントリーでTemplate::Stash::EscapeHTMLByCaseというのを作ったわけですが、こうやっていろいろStashで対応しようとすると、Template::Stash::ForceUTF8も使ってるから使えない~とかが発生する。
というのも、TTのSTASHは一つのObjectしか渡せないからだ。これには多分いろいろ理由があって、Template::Stash::Contextのようにgetのアルゴリズム自体に手を入れてる場合どうすんの?ってことだからだと思う。
ただ、EscapeHTMLByCaseやForceUTF8なんかのように単にfilterを掛けたいだけであれば繋げたい。
というわけでTemplate::Stash::Filters作ってみました。
package Template::Stash::Filters;
use strict;
use Template::Config;
use base ($Template::Config::STASH);
our $VERSION = '0.01';
sub get {
my ($self, @args) = @_;
PRE_PROCESS:
foreach my $filter (@{$self->{FILTERS}}) {
if (!$filter->can('pre_process')) {
next PRE_PROCESS;
}
$filter->pre_process(@args);
}
my $var = $self->SUPER::get(@args);
FILTER:
foreach my $filter (@{$self->{FILTERS}}) {
if (!$filter->can('filter')) {
next GET;
}
$var = $filter->filter($var);
}
return $var;
}
1;
__END__
Template::Stash::XXX系のモジュールを再利用できたらいいんだろうけど、$self->SUPER::getをhackする方法が分らなかったのでFilter実装モジュールも車輪の再発明。
Template::Stash::Filters::EscapeHTMLByCase
package Template::Stash::Filters::EscapeHTMLByCase;
use strict;
our $VERSION = '0.01';
use base qw(Class::Accessor);
__PACKAGE__->mk_accessors(qw(is_raw));
sub pre_process {
my ($self, $args) = @_;
if (is_this_raw(@{$args})) {
$self->is_raw(1);
strip_raw_specifier($args);
}
else {
$self->is_raw(0);
}
}
sub filter {
my ($self, $var) = @_;
if ($self->is_raw || ref $var) {
return $var;
}
return html_filter($var);
}
sub html_filter {
my $text = shift;
for ($text) {
s/&/&/g;
s/</&;t;/g;
s/>/>/g;
s/"/"/g;
}
return $text;
}
sub is_this_raw {
my @args = @_;
if (ref $args[0] ne 'ARRAY') {
return 0;
}
if ($args[0]->[0] ne 'RAW') {
return 0;
}
return 1;
}
sub strip_raw_specifier {
my $args = shift;
splice @{$args->[0]}, 0, 2;
}
1;
pre_processを活用してます。
Template::Stash::Filters::ForceUTF8
package Template::Stash::Filters::ForceUTF8;
use strict;
our $VERSION = '0.01';
use base qw(Class::Accessor);
use Encode;
sub filter {
my ($self, $var) = @_;
return $var if ref $var;
Encode::_utf8_on($var) unless Encode::is_utf8($var);
return $var;
}
1;
__END__
で、使い方はこんな感じ
use Template;
use Template::Stash::Filters;
use Template::Stash::Filters::EscapeHTMLByCase;
use Template::Stash::Filters::ForceUTF8;
my $template = Template->new({
STASH => Template::Stash::Filters->new(
FILTERS => [
Template::Stash::Filters::ForceUTF8->new,
Template::Stash::Filters::EscapeHTMLByCase->new,
],
),
});
うーん、newへの引数が無いモジュールばっかなのでTemplate::Stash::Filters::がうっとうしいなぁ。useするのも面倒だし勝手にuseしちゃう方式つくってみるかなぁ。
まぁまた時間があったときにでも。
コメント:0
トラックバック:0
- この記事のトラックバック URL
- https://blog.everqueue.com/chiba/2007/06/18/13/trackback/
- トラックバックの送信元リスト
- Template::Stash::Filters(TTのStashで複数のfilterを実行) - へぼい日記 より