「Movable Type Advent Calendar 2015」23日目の記事です。
今年は趣味でMovable Typeのプラグイン開発に本格的にチャレンジしてみました。MTがラズパイで、プラグインを使ってLチカさせているような、そんな気分で書いてきました。
勉強するにあたって読んだものは以下のドキュメントなどです。
- Movable Type 開発者向けガイド
- Movable Type Developer's Guide Volume 1
- GitHubに上がっているMTプラグイン
ドキュメントを読むと、MT::Entry->load()
のような記述で情報が得られることが分かったのですが、少し単純すぎて面白みに欠けます。そこで題に掲げたように、記事のカスタムフィールドを特殊な条件でフィルタできないか試してみました。
用意したデータ
主力機材と従業員数をカスタムフィールドに格納しています。なお、従業員数は「Custom Custom Field Types」を参考に、数値型で格納できるように拡張しました。(ただ、config.yamlを書いても上手くいかなかったので、アルファサードさんの「mt-plugin-numeric-fieldsプラグイン」を使用しました。)
航空会社 | 主力機材 | 従業員数 |
---|---|---|
ANA | B787 | 12360 |
JAL | A350 | 11007 |
JTA | B737 | 718 |
ADO | B737 | 954 |
※tableとh5のスタイルを書いていなかったので、ひとまず現状でお許しを...。
フィルタの実験
基礎
単純なフィルタです。次のコードは主力機材が「B787」である記事を抽出します。書き方は[mtdir]/lib/MT/Template/Tags/Entry.pm
も参考にしました。(違う書き方もあるようですが、今パッと思い出せません...。)
my $col = 'data_aircraft_type';
my $class = MT->model('entry');
my $type = MT::Meta->metadata_by_name($class, 'field.' . $col);
my @entries = MT::Entry->load(
{
blog_id => 1,
status => MT::Entry::RELEASE()
},
{
join => [
$class->meta_pkg,
undef,
{
'entry_id' => \'= entry_id',
type => 'field.' . $col,
$type->{type} => 'B787'
}
],
sort => 'authored_on',
direction => 'descend',
limit => 10
}
);
結果
- ANA
ORフィルタ
ここからが実験的内容です。例えば主力機材が「B787」か「A350」のようにOR検索的なフィルタができないか試してみました。書き方はokayamaさんのウェッッッブサイト(←metaにそう書いてある)の記事「特定のカラムを or 条件指定して Movable Type オブジェクトを load する | Blog | weeeblog+」を参考にしました。
my $col = 'data_aircraft_type';
my $class = MT->model('entry');
my $type = MT::Meta->metadata_by_name($class, 'field.' . $col);
my @conditions = ('B787', 'A350');
my @entries = MT::Entry->load(
{
blog_id => 1,
status => MT::Entry::RELEASE()
},
{
join => [
$class->meta_pkg,
undef,
{
'entry_id' => \'= entry_id',
type => 'field.' . $col,
$type->{type} => \@conditions
}
],
sort => 'authored_on',
direction => 'descend',
limit => 10
}
);
my @conditions = ('B787', 'A350');
のように配列で指定するのがポイントです。
結果
- ANA
- JAL
LIKEフィルタ
ORはまだ序の口。例えば「B%」を指定して、ボーイング社製機材が主力である記事を抽出できないかと試しました。書き方は、藤本壱さんの「Movable Type Developer's Guide Volume 1」を参考にしました。
my $col = 'data_aircraft_type';
my $class = MT->model('entry');
my $type = MT::Meta->metadata_by_name($class, 'field.' . $col);
my @entries = MT::Entry->load(
{
blog_id => 1,
status => MT::Entry::RELEASE()
},
{
join => [
$class->meta_pkg,
undef,
{
'entry_id' => \'= entry_id',
type => 'field.' . $col,
$type->{type} => { 'like' => 'B%' }
}
],
sort => 'authored_on',
direction => 'descend',
limit => 10
}
);
$type->{type} => { 'like' => 'B%' }
と指定するのがポイントです。
結果
- ANA
- JTA
- ADO
x以上やy未満のフィルタ
数値型のカスタムフィールドに数値を入力したならば、x以上やy未満のフィルタができないか試してみました。例えば以下のコードは従業員数が10,000人以上の記事を抽出します。
my $col = 'data_int_number_of_employees';
my $class = MT->model('entry');
my $type = MT::Meta->metadata_by_name($class, 'field.' . $col);
my @entries = MT::Entry->load(
{
blog_id => 1,
status => MT::Entry::RELEASE()
},
{
join => [
$class->meta_pkg,
undef,
{
'entry_id' => \'= entry_id',
type => 'field.' . $col,
$type->{type} => { '>=' => 10000 }
}
],
sort => 'authored_on',
direction => 'descend',
limit => 10
}
);
$type->{type} => { '>=' => 10000 }
がポイントです。
結果
- ANA
- JAL
プラグイン化へ
Perlで記事を抽出するコードが書けるようになると、標準のテンプレートタグでは実現できないフィルタ条件を指定できることが分かりました。折角なのでプラグイン化し、テンプレートに記述することでLIKEフィルタなどができるようにならないかと考えました。
タグの拡張の仕方がよく分からなかったのですが、アルファサードさんの記事「細かすぎて伝わらない FieldIsNotEmpty プラグインの実装 | PowerCMS ブログ」に似たような事例が書いてありましたので参考にしました。そして、「ExtendEntryFieldFilter」が完成しました。
細かいことはGitHubに書いているのですが、<mt:Entries field:data_aircraft_type="LIKE","B%">
で主力機材が「B」から始まる記事を抽出したり、<mt:Entries field:data_int_number_of_employees="[比較条件]","[数値]">
で数値の以上・より大きい・以下・未満の記事を抽出したりできます。
まとめ
このように、MTプラグインが書けるようになると、標準では実現できない機能が実現できるようになり、MTがより便利になることが分かりました。MTの世界が広がるような気分です。
最初は「Perlだし敷居が高いな」と思っていたのですが、よい意味で模倣をしたり題材を設定してコードを書いてみたりすると、だんだん書けるようになってきます。JavaScriptやPHPが書けるなら、一からPerlの書籍を読まなくてもPerlも分かってくるようになります。(さすがにmy ($ctx, $args, $cond) = @_;
は「なんだこりゃ」と思いましたが。)
要望としては、プラグイン開発のドキュメントがもう少し充実しないかな、というところですね。MT Liveへ通ってポイントを伺ったり質問をしたりしたいなと思うのですが、さすがに東京へはなかなか行けず...。