- 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を実行) - へぼい日記 より