MT4.1:MTの計算機能を拡張するプラグイン(CalcExp)開発の話
MTの計算機能を拡張するプラグイン(CalcExp)開発のときの話を書いておきます。
誰かの何かの参考になれば。また、自分のメモのためにも。
作った経緯
mixiの変態コミュで、3のつく時にアホになり、5がつくときに犬っぽくなるコードを書くとき、アホ具合と犬具合をランダムに切り替えると面白いかな?と。アホデータと犬データを配列で準備しておき、乱数を用いてそれを配列の要素とすれば簡単なのですが...MTで乱数って取得できない。
よく見るサイト、Open MagicVox.net さんとこにそういうプラグインがあるのは知っていました。
変数操作を無駄に拡張するMovableTypeプラグイン:MathOperatorExpander
あと、MTプラグインでは有名な The blog of H.Fujimoto さんも作成されています。
パクろうと思えばできなくもないですが、勉強のため、自分で後々拡張する可能性もあるので、イチから自分で書いてみた次第です。
プラグインコード
※日本語化の部分は掲載していません。
package MT::Plugin::CalcExp;
use strict;
use MT;
use MT::Template::Context;
use base qw(MT::Plugin);
use POSIX;
use List::Util qw(sum);
use List::Util qw(max);
use List::Util qw(min);
use vars qw($PLUGIN_NAME $VERSION);
$PLUGIN_NAME = 'CalcExp';
$VERSION = '0.3';
my $plugin = new MT::Plugin::CalcExp({
id => 'CalcExp',
key => 'calc_exp',
name => 'CalcExp',
version => $VERSION,
description => '<__TRANS phrase="Calculation Value Expander Plugin">',
author_name => 'apstar',
author_link => 'http://www.mtde.info/',
l10n_class => 'CalcExp::L10N',
});
MT->add_plugin($plugin);
sub init_registry {
my $plugin = shift;
$plugin->registry({
tags => {
function => {
'CalcExp' => \&_hdlr_getvalue,
'CalcExpArray' => \&_hdlr_getvalue_array,
},
},
});
}
sub _hdlr_getvalue {
my($ctx, $args) = @_;
my $op = $args->{op};
my $base = $args->{base};
my $palam = $args->{palam};
use constant PI => 3.14159265358979;
if (('+' eq $op) || ('add' eq $op)) {
return $base + $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('-' eq $op) || ('sub' eq $op)) {
return $base - $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('*' eq $op) || ('mul' eq $op)) {
return $base * $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('/' eq $op) || ('div' eq $op)) {
return $base / $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('%' eq $op) || ('mod' eq $op)) {
# Perl % is integer only
$base = int($base);
$palam = int($palam);
return $ctx->error(MT->translate('Division by zero.'))
if $palam == 0;
return $base % $palam if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('++' eq $op) || ('inc' eq $op)) {
return ++$base if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('--' eq $op) || ('dec' eq $op)) {
return --$base if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif (('&' eq $op) || ('append' eq $op)) {
return $base . $palam;
}
elsif (('&' eq $op) || ('prepend' eq $op)) {
return $palam . $base;
}
elsif ('zero' eq $op) {
return sprintf("%0".$palam."d", $base);
}
elsif ('rand' eq $op) {
return $base + int(rand($palam))+1 if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('int' eq $op) {
return int($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('round' eq $op) {
return round($base, $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('floor' eq $op) {
return floor($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
}
elsif ('ceil' eq $op) {
return ceil($base) if defined $base && $base =~ m/^\-?[\d\.]+$/; #by POSIX
}
elsif ('sin' eq $op) {
return sin($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('cos' eq $op) {
return cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('tan' eq $op) {
return sin($base)/cos($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('deg2rad' eq $op) {
return ($base / 180) * PI if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('rad2deg' eq $op) {
return ($base / PI) * 180 if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('log' eq $op) {
return log($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('pow' eq $op) {
return ($base ** $palam) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
elsif ('sqrt' eq $op) {
return sqrt($base) if defined $base && $base =~ m/^\-?[\d\.]+$/;
}
return $base;
}
sub round {
my $val = shift;
my $col = shift;
my $r = 10 ** $col;
my $a = ($val > 0) ? 0.5 : -0.5;
return int($val * $r + $a) / $r;
}
sub _hdlr_getvalue_array {
my($ctx, $args) = @_;
my $op = $args->{op};
my $palam = $args->{palam};
my @palamlist = split( /,/ , $palam );
if ('avg' eq $op) {
my $sum = sum @palamlist;
my $num = @palamlist;
my $avg = $sum / $num if defined $palam && $num >0;
return $avg;
}
elsif ('max' eq $op) {
my $max = max @palamlist;
return $max;
}
elsif ('min' eq $op) {
my $min = min @palamlist;
return $min;
}
}
1;
特徴
出来合いのperlモジュールを幾つか使用しています。計算系の拡張モジュールです。いわゆるライブラリ的なもので、例えば、私が複雑な演算のコードを書くよりは格段にエラー発生の確率が低く、汎用性に優れています。
私は本職でプログラムも触るので、ライブラリを利用して楽をしなければいけない(できれば...ではなく、やれ!Must!です)という感覚が強いです。車輪の再開発、みたいなことが嫌いです。しかし世の中にない車輪の開発は好きです。
話がそれた...このあたりです。
use POSIX;
use List::Util qw(sum);
use List::Util qw(max);
use List::Util qw(min);
あと、プラグインの拡張はとても簡単そうな感じとなりました。
使途
もともとMTのテンプレートタグで変数を用いた演算を行おうとすると、かなりコードが長くなってしまう場合があります。とくに繰り返し演算が必要になるときに威力を発揮しそうです。
mtde.info「縦横比を保持して全ての画像の幅をそろえる」こんな簡単なことをやるのにありえないコードの長さ。こういうのが改善されそうです。
ほか、思いつく使途は、「CSSにおけるpaddingの自動演算」、「一日辺り何件の記事をポストしているか平均値計算」、「一番コメント数・トラックバック数が多い記事を全エントリよりピックアップ」、「画像ファイルの平均ファイル容量を計算」などなど。
資料とか
このようなプラグインを作る場合、MTソースを見るといいと思います。MTのlib\MT\Templateフォルダ内に、ContextHandlers.pmというファイルがあります。その8500行目辺り以降に、_math_operationという関数があります。そこが参考になります。
型ができてしまえば、後は拡張するだけ。必要なのは、perlのコードを書く知識となります。
私は、Perl表技集 、とほほのperl入門 あたりをよく参考にします、今のところ。
先日リャマ本も買いましたが、買った日にナナメ読みしただけで、あまり読まないです。
- カテゴリ:215プラグイン関係
トラックバック(0)
このブログ記事を参照しているブログ一覧: MT4.1:MTの計算機能を拡張するプラグイン(CalcExp)開発の話
このブログ記事に対するトラックバックURL:
- Categories
- Entries
-
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(Ver0.5)
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(Ver0.4)
- memo:perlでプラグイン Image::ExifとImage::Info
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(Ver0.3)
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(Ver0.2)
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(GPS Ready)
- MT4:エントリのURLをQRコードで自動生成する
- MT4.2:QRコード画像を生成するプラグイン(改)
- 嵌りメモ(perlのxampp環境でのファイル吐き出し実験)
- MT4.2:QRコード画像を生成するプラグイン
- MT4.2:JPEGファイルのEXIF情報を取得するプラグイン(失敗)
- 管理画面を拡張する(メニューとメソッド追加)
- MT4.1:追加したファンクションタグのみへモデファイア追加
- MT4.1:エントリの既存DBへアクセスしてデータ取得
- MT4.1:MTの計算機能を拡張するプラグイン(CalcExp)開発の話
- MT4.1:MTの計算機能を拡張するプラグイン(CalcExp)配布
- MT4.1:営業日(休日)をイッパツで表現するカレンダープラグイン(改)
- MT4.1:プラグイン作成におけるDBへのフィールド追加について(プラグイン設定編)
- MT4.1:プラグイン作成におけるDBへのフィールド追加について(ブログ毎編)
- MT4.1:プラグイン作成におけるDBへのフィールド追加について(カテゴリ編)
- MT4.1:プラグイン作成におけるDBへのフィールド追加について(エントリ編)
- MT4.1:カテゴリの並べ替え(オリジナルプラグイン+ハッシュ変数)
- サンプルプラグインを手入力した(AddField)
- MT4.1:営業日(休日)をイッパツで表現するカレンダープラグイン
- サンプルプラグインを手入力した(RandomEntry)
- 最小単位のプラグインを生成するサンプル(ファンクション、ブロック、モデファイア、コールバック)
コメントする