とりあえず、昨日考えていた機能を実装したものができた。

しかし、現在のところエラーチェックが殆どされていない。これはまずい。
そして、式の中の変数が評価できない場合の対応が難しい。
MTタグに関しては、文字列が帰ってきた場合、コンテナタグなどを呼んだ場合、そもそも存在しないタグを呼んだ場合など。
VAR変数でも、文字列の場合と、存在しない場合がある。

現状では、すべて 0 扱いして無理やり評価させているのだが、実運用においては再構築時にエラーを出したほうがよいように思える。
これもアトリビュートで指定して、処理を選択できるようにするのがいいだろうか。とりあえず現在のコード。



#Calc Plugin of Movable Type 3.2 #aklaswad 2006 feb


package MT::Plugin::Calc;    #このソースコードのモジュール名を宣言
use strict;                  #紳士的に定義を行うことをコードに対して強制する
use base 'MT::Plugin';       #謎
use vars qw($VERSION);       #バージョン
$VERSION = '0.7';

use MT;                      #MTのモジュールを使用
use MT::Template::Context;   #タグを追加するときに必要?

#プラグインのコンストラクタ
my $plugin = MT::Plugin::Calc->new({
    name => 'MT Calculator',
    description => "calculator",
    doc_link => 'http://www.sixapart.jp',
    author_name => 'aklaswad',
    author_link => 'http://www.aklaswad.com/',
    version => $VERSION,
});

#プラグインのクラスを Movable Type に渡す
MT->add_plugin($plugin);    

#追加するタグの名前とメソッドのアドレスを渡す
MT::Template::Context->add_tag(Calc => \&tag_calc);   

#タグを処理するメソッド
#戻り値がそのままドキュメントに書き出される
sub tag_calc {
  #引数を取り出す
  my ($ctx, $args) = @_;
  my $exoriginal = $args->{"expr"};
  my $ex = $args->{"expr"};

  #MTタグを検索・置換
  while( $ex =~ /MT([A-Za-z]+)/ ){
    my $handler = $ctx->handler_for($1);
    if (defined($handler)) {
      my $tagvalue = $handler->($ctx, { %$args });
      $ex =~ s/MT$1/$tagvalue/;
    } else{
      $ex =~ s/MT$1/0/;
    }
  }
  #MTGetVar変数を検索・置換
  while( $ex =~ /VAR([A-Za-z0-9]+)/ ){
    my $varvalue = $ctx->{__stash}{vars}{$1};
    $ex =~ s/VAR$1/$varvalue/;
  }
  
  #式を評価
  my $ret = eval($ex);
  die "MTCalc can't evaluate this line:$ex:" if $@;
  if ($args->{"setvar"}){
    $ctx->{__stash}{vars}{$args->{"setvar"}} = $ret;
  }
  $ret;

  #デバッグ用の戻り値
  #"$exoriginal == $ex = $ret";
}

1;