<div> や <blockquote> のように、
他の HTML タグやテンプレートタグや文字列を、その中に含むことができるテンプレートタグのことです。
MT のコンテナタグは、その中身(コンテンツ)に対して、何らかの処理を行いたい場合に使用します。<MTEntries> コンテナタグは、
複数のエントリから一つずつエントリを取り出しながら、
その中に含まれる <MTEntryTitle> などのコンテンツを処理します。
また、<MTCalendar> コンテナタグは、
日付を変化させながら、その月の日数分だけ、そのコンテンツを繰返す処理を行います。<blockquote> で囲むだけの
<MTMyBlockquote> コンテナタグを作ってみます。
package MT::Plugin::myplugin_2_1;
use MT::Template::Context;
MT::Template::Context->add_container_tag (MyBlockquote => &my_blockquote);
sub my_blockquote {
my ($ctx, $args, $cond) = @_;
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $out = $builder->build ($ctx, $tokens, $cond);
return $ctx->error ($builder->errstr) if !defined $out;
'<blockquote>'. $out. '</blockquote>';
}
1;
そして、何れかのテンプレートに次のように追記し、そのテンプレートを再構築してみましょう。
<MTMyBlockquote> These string will just be quoted in blockquote section. </MTMyBlockquote>
MT::Template::Context->add_container_tag (MyBlockquote => ¥&my_blockquote);my_blockquote にある、と云うことです。
変数タグで出てきた add_tag と全く同じです。
my ($ctx, $args, $cond) = @_;my $builder = $ctx->stash('builder')my $tokens = $ctx->stash('tokens')<MTMyBlockquote> コンテナタグの
コンテンツ($tokens)と、
それを処理するためのビルダ($builder)を取得します。
my $out = $builder->build ($ctx, $tokens, $cond);$out に代入します。
return $ctx->error ($builder->errstr) if !defined $out;$out が未定義(undef) になるので、
MT のエラーログにエラー内容($builder->errstr)を返して処理を中断します。
'<blockquote>'. $out. '</blockquote>';<MTMyBlockquote> コンテナタグの答え(?)とします。
MTMyBlockquote プラグインのソースコードを見ると、
変数タグの時と同じく $args と書かれた部分が見つかります。
お察しのとおり、変数タグと全く同じ方法でコンテナタグでも引数を取ることができるのです。MTMyBlockquote を改造して、
色々な HTML タグでコンテンツを括ることができる <MTAnyBlock> テンプレートタグを作ってみます。
package MT::Plugin::myplugin_2_2;
use MT::Template::Context;
MT::Template::Context->add_container_tag (AnyBlock => &any_block);
sub any_block {
my ($ctx, $args, $cond) = @_;
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $out = $builder->build ($ctx, $tokens, $cond);
return $ctx->error ($builder->errstr) if !defined $out;
my $tag = $args->{tag} or return $out;
my $class = $args->{class} or "<$tag>". $out. "</$tag>";
"<$tag class="$class">". $out. "</$tag>";
}
1;
そして、何れかのテンプレートに次のように追記し、そのテンプレートを再構築してみましょう。 …このテンプレートタグに意味があるのか、それは考えない方向で(苦笑
<MTAnyBlock tag="blockquote"> These string will just be quoted in blockquote section. </MTAnyBlock> <MTAnyBlock tag="div" class="hoge"> These string will just be quoted in div section with class name. </MTAnyBlock>
my $tag = $args->{tag} or return $out;tag="..." で指定された値を $tag に代入します。
何も指定されていない場合は、コンテンツをそのまま返します。
my $class = $args->{class} or "<$tag>". $out. "</$tag>";class="..." で指定された値を $class に代入します。
何も指定されていない場合は、コンテンツを $tag タグで括って返します。
"<$tag class=¥"$class¥">". $out. "</$tag>";$tag と $class で括って返します。
<MTCalendar> コンテナタグの中で使用される
<MTCalendarDay> 変数タグのように、
様々に値を変化させるような変数タグはどのように実現すれば良いのでしょうか?
package MT::Plugin::myplugin_2_3;
use MT::Template::Context;
MT::Template::Context->add_container_tag (MyLoop => &my_loop);
MT::Template::Context->add_tag (MyLoopCount => &my_loop_count);
sub my_loop {
my ($ctx, $args, $cond) = @_;
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $loop = $args->{count} || 1;
my $html = '';
for (my $count = 1; $count <= $loop; $count++) {
local $ctx->{__stash}{'myplugin::count'} = $count;
my $out = $builder->build ($ctx, $tokens, $cond);
return $ctx->error ($builder->errstr) if !defined $out;
$html .= $out;
}
$html;
}
sub my_loop_count {
my ($ctx, $args) = @_;
$count = $ctx->stash('myplugin::count');
return $ctx->error ('MTMyLoopCount must be used in MTMyLoop') if !defined $count;
$count;
}
1;
そして、何れかのテンプレートに次のように追記し、そのテンプレートを再構築してみましょう。
<MTMyLoop count="5"> Loop Count is <MTMyLoopCount><br /> </MTMyLoop>
my $loop = $args->{count} || 1;<MTMyLoop> コンテナタグの引数
count="..." から繰返す回数を取得します。
for (my $count = 1; $count <= $loop; $count++)$loop 回だけ処理を繰返します。
現在の繰り返し回数は $count です。
local $ctx->{__stash}{'myplugin::count'} = $count;$count を
myplugin::count に記憶しておきます。
$html .= $out;$count = $ctx->stash('myplugin::count');myplugin::count に記憶してある内容を $count に代入します。
return $ctx->error ('MTMyLoopCount must be used in MTMyLoop') if !defined $count;$count が未定義(!defined) だった場合、
<MTMyLoopCount> 変数タグは
<MTMyLoop> コンテナタグの中でしか使えないことを示すエラーメッセージを返します。
<MTEntryIfExtended> のように、
ある条件が成立した場合に、そのコンテンツを表示したい場合に使用します。
条件タグは、コンテナタグと非常に似ています。
例として、その日が日曜日だった場合に成立する
<MTIfSunday> 条件タグを作ってみます。
package MT::Plugin::myplugin_2_4;
use MT::Template::Context;
MT::Template::Context->add_conditional_tag (IfSunday => &if_sunday);
sub if_sunday {
my ($ctx, $args, $cond) = @_;
my $e = $ctx->stash ('entry') or return $ctx->_no_entry_error('MTIfSunday');
my $ts = $e->created_on;
MT::Util::wday_from_ts ($ts =~ m/^(dddd)(dd)(dd)/) == 0;
}
1;
そして、何れかのテンプレートに次のように追記し、そのテンプレートを再構築してみましょう。
<MTEntries>
<MTIfSunday>
<MTEntryTitle> in Wonderful Sunday !<br />
</MTIfSunday>
</MTEntries>
my $e = $ctx->stash('entry') or return $ctx->_no_entry_error('MTIfSunday');$e に代入します。
エントリが無い場合、エラーを返します。
my $ts = $e->created_on;$e の投稿日を $ts に代入します。
MT::Util::wday_from_ts ($ts =‾ m/^(¥d¥d¥d¥d)(¥d¥d)(¥d¥d)/) == 0;MT::Util::wday_from_ts 関数を使用して、投稿日の曜日を取得します。
曜日が日曜日(0)の場合には真、日曜日以外(1〜6)の場合には偽を返します。
<MTIfSunday> 条件タグをコンテナタグとして無理矢理に書き換えてみました。
それが次のソースコード(sample_2_4a.pl)です。
package MT::Plugin::myplugin_2_4a;
use MT::Template::Context;
MT::Template::Context->add_container_tag (IfSunday => &if_sunday);
sub if_sunday {
my ($ctx, $args, $cond) = @_;
my $e = $ctx->stash ('entry') or return $ctx->_no_entry_error('MTIfSunday');
my $ts = $e->created_on;
if (MT::Util::wday_from_ts ($ts =~ m/^(dddd)(dd)(dd)/) == 0) {
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $out = $builder->build ($ctx, $tokens, $cond);
return $ctx->error ($builder->errstr) if !defined $out;
return $out;
}
'';
}
1;
日曜日の場合のみ、ビルダでそのコンテンツを構築し、その内容をそのまま返すようにしています。
ビルダやコンテンツの取得部分は、コンテナタグと全く同じです。
そして日曜日以外の場合には、このコンテナタグは空文字を返すようにしています。
その結果、このプラグインは条件タグとして記述した
<MTIfSunday> と全く同じ機能を持つことがわかります。
このように条件タグと同じ機能をコンテナタグを利用して実装することも可能ですが、
単に条件によってコンテンツを表示するか否かを選択したいだけの場合は、条件タグを使用するのが良いでしょう。
また、変数タグやコンテナタグと同様に、
$args を使用して引数を扱うことができる点も同じです。
stash を使用して条件判定を行うこともできます。
ここでは、先の <MTMyLoop> で、
<MyLoopCount> の値が偶数か奇数かを判定する条件タグを書いてみましょう。
package MT::Plugin::myplugin_2_3a;
use MT::Template::Context;
MT::Template::Context->add_container_tag (MyLoop => &my_loop);
MT::Template::Context->add_tag (MyLoopCount => &my_loop_count);
MT::Template::Context->add_conditional_tag (IfCountOdd => &my_loop_count_odd_even);
MT::Template::Context->add_conditional_tag (IfCountEven => &my_loop_count_odd_even);
sub my_loop {
my ($ctx, $args, $cond) = @_;
my $builder = $ctx->stash('builder');
my $tokens = $ctx->stash('tokens');
my $loop = $args->{count} || 1;
my $html = '';
for (my $count = 1; $count <= $loop; $count++) {
local $ctx->{__stash}{'myplugin::count'} = $count;
my $out = $builder->build ($ctx, $tokens, $cond);
return $ctx->error ($builder->errstr) if !defined $out;
$html .= $out;
}
$html;
}
sub my_loop_count {
my ($ctx, $args) = @_;
$count = $ctx->stash('myplugin::count');
return $ctx->error ('MTMyLoopCount must be used in MTMyLoop') if !defined $count;
$count;
}
sub my_loop_count_odd_even {
my ($ctx, $args, $cond) = @_;
$count = my_loop_count ($ctx, $args) or return $count;
return ($count % 2) == 1 if $ctx->stash('tag') eq 'IfCountOdd';
return ($count % 2) == 0 if $ctx->stash('tag') eq 'IfCountEven';
return 0;
}
1;
そして、この条件タグを使用したテンプレートは次のようになります。
<MTMyLoop count="5"> Number <MTMyLoopCount> is an <MTIfCountOdd>Odd</MTIfCountOdd> <MTIfCountEven>Even</MTIfCountEven> number.<br /> </MTMyLoop>