Skip to content

Japanese plugin dev 2 3

uehatsu edited this page May 10, 2011 · 19 revisions

コンディショナルタグ プラグインの開発について

はじめに

今回はコンディショナルタグを実現するプラグインを解説します。

コンディショナルタグとは?

コンディショナルタグの代表格は<MTIf><MTIfBlog><MTIfCategory>などのタグです。

<MTIfBlog>〜<MTElse>〜</MTIfBlog> のように利用します。

これらは条件分岐を実装したMTタグです。

コンディショナルタグもブロックタグと同じようにPerl版とPHP版で記述方法が若干違いますがPHPの実装の章で解説させていただきます。

プラグインの仕様とテストケースの作成

プラグインの仕様

プラグインの仕様は以下になります。

  • タグ名(<MTCategoryIfToplevel>)
  • ブログ記事アーカイブで利用する
  • メインのカテゴリがトップレベル(親)カテゴリの時は正、違えば負
  • ブログ記事にカテゴリが設置されていない場合も負
  • 以下のようにタグを記述する
<MTCategoryIfToplevel>
<p>このブログ記事にはトップレベルカテゴリが設定されています。</p>
<MTElse>
<p>このブログ記事にはカテゴリが設定されていないか、トップレベルカテゴリ以外が設定されています。</p>
</MTCategoryIfToplevel
  • 結果が正な場合 <p>このブログ記事にはトップレベルカテゴリが設定されています。</p> が表示される
  • 結果が負な場合 <p>このブログ記事にはカテゴリが設定されていないか、トップレベルカテゴリ以外が設定されています。</p> が表示される

テストケース1(00-compile.t)の作成

以前に行ったものと同じです。各オブジェクトが正しくロードされているかを確認します。

use strict;
use lib qw( t/lib lib extlib );
use warnings;
use MT;
use Test::More tests => 5;
use MT::Test;

ok(MT->component ('MyPlugin07'), "MyPlugin07 plugin loaded correctry");

require_ok('MyPlugin07::L10N');
require_ok('MyPlugin07::L10N::ja');
require_ok('MyPlugin07::L10N::en_us');
require_ok('MyPlugin07::Tags');

1;

テストケース2(01-tags.t)の作成

テストするのは以下の3項目です。

  1. 空文字列をインプットすると、空文字列が戻ってくる
  2. メインカテゴリにトップレベルカテゴリが設定されている場合文字列"AAA"が返る
  3. メインカテゴリにトップレベルカテゴリが設定されていない場合文字列"BBB"が返る
(前略)
#===== Edit here
my $test_json = <<'JSON';
[
{ "r" : "1", "t" : "", "e" : ""},
{ "r" : "1", "t" : "<mt:Entries id=\"6\"><MTCategoryIfToplevel>AAA<MTElse>BBB</MTCategoryIfToplevel></mt:Entries>", "e" : "AAA"},
{ "r" : "1", "t" : "<mt:Entries id=\"8\"><MTCategoryIfToplevel>AAA<MTElse>BBB</MTCategoryIfToplevel></mt:Entries>", "e" : "BBB"}
]
JSON
#=====
(後略)

コンディショナルタグ プラグインの開発(Perl)

前章で作成したMyPlugin06を元にプラグインを作成します。

config.yaml

グローバル・モディファイアの追加には以下のように"tags"=> “modifier”=> “モディファイア名?” => $プラグイン名::ハンドラ名 を記述します。

"modifier"には、ブロックタグは"block"を記載します。

モディファイア名の後に"?"が入っているのに注意してください。このように書くとブロックタグではなくコンディショナルタグと認識されます。

id: MyPlugin07
name: <__trans phrase="Sample Plugin Conditional tag">
version: 1.0
description: <__trans phrase="_PLUGIN_DESCRIPTION">
author_name: <__trans phrase="_PLUGIN_AUTHOR">
author_link: http://www.example.com/about/
doc_link: http://www.example.com/docs/
l10n_class: MyPlugin07::L10N

tags:
    block:
        CategoryIfToplevel?: $MyPlugin07::MyPlugin07::Tags::hdlr_category_if_toplevel

L10N.pm

package MyPlugin07::L10N;
use strict;
use base 'MT::Plugin::L10N';

1;

L10N/en_us.pm

package MyPlugin07::L10N::en_us;

use strict;
use base 'MyPlugin07::L10N';
use vars qw( %Lexicon );

%Lexicon = (
    '_PLUGIN_DESCRIPTION' => 'Sample conditional tag',
    '_PLUGIN_AUTHOR' => 'Plugin author',
);

1;

L10N/ja.pm

package MyPlugin07::L10N::ja;

use strict;
use base 'MyPlugin07::L10N::en_us';
use vars qw( %Lexicon );

%Lexicon = (
    'Sample Plugin Conditional tag' => 'サンプルプラグイン コンディショナルタグ',
    '_PLUGIN_DESCRIPTION' => ' テストプラグイン',
    '_PLUGIN_AUTHOR' => 'プラグイン作者',
);

1;

Tags.pm

package MyPlugin07::Tags;
use strict;

sub hdlr_category_if_toplevel {
    my ($ctx, $args, $cond) = @_;

    my $entry = $ctx->stash('entry');
    my $cat = $entry->category() || return 0;

    return ($cat->parent() == 0);
}

1;

解説

  • パッケージ宣言
    初めにpackage宣言をし、"use strict;"しています。

  • ハンドラ宣言(<MTCategoryIfToplevel>)
    ハンドラ関数宣言と呼び出し時の"$ctx", “$args”の代入です。この関数はブロックタグ(<MTCategoryIfToplevel>)になります。

  • コンテキスト($ctx)からのオブジェクトの取得
    7行めでコンテキストからブログ記事オブジェクト(エントリオブジェクト)を取得します。
    8行めでエントリのカテゴリを取得します。取得できない(カテゴリが設定されていない)場合は0(負)を返します。

  • 正・負の判定
    親カテゴリのカテゴリIDをチェックし、値が"0"だった場合は親カテゴリなので1(正)を返します。値が"0"以外だった場合は親カテゴリではないので0(負)を返します。

コンディショナルタグ プラグインの開発(PHP)

block.mtcategoryiftoplevel.php

ファイル名はコンディショナルタグの場合でもblockタグとして扱い、<MTCategoryIfToplevel>タグである事から、block.mtcategoryiftoplevel.phpとなります。

<?php
    function smarty_block_mtcategoryiftoplevel ($args, $content, &$ctx, &$repeat) {
        if (!isset($content)) {
            $entry = $ctx->stash('entry');
            $cat = $entry->category();
            if (!$cat) {
                $flag = 0;
            } else {
                if ($cat->parent == 0) {
                    $flag = 1;
                } else {
                    $flag = 0;
                }
            }
            return $ctx->_hdlr_if($args, $content, $ctx, $repeat, $flag);
        } else {
            return $ctx->_hdlr_if($args, $content, $ctx, $repeat);
        }
    }
?>

解説

  • ハンドラ関数宣言(<MTCategoryIfToplevel>)
    block名はsmarty記法にのっとって smarty_block_mtcategoryiftoplevel となります。一緒に呼び出し時の"$args", “$content”, “$ctx”, “$repeat”の取得をします。Perl版と異なる事に注意してください。

  • 正・負判定
    1行目で$contentに何もセットされない場合は2〜15行が実行されます。セットされていた場合は17行目で次の処理に移行します。
    4行目で$ctxからブログ記事(エントリ)オブジェクトを取得します。5行目でブログ記事のカテゴリを取得します。
    6行目でカテゴリが取得できない(カテゴリが設定されていない)場合、$flagに0(負)を設定し、15行目で処理を戻します。
    カテゴリが取得できた場合は、親カテゴリのIDが0の場合、設定されているカテゴリは親カテゴリなので$flagに1(正)を設定し、15行目で処理を戻します。親カテゴリのIDが0以外の場合、親カテゴリではないため、$flagに0(負)を設定し、15行目で処理を戻します。

ファイルの配置

$MT_DIR/
|__ plugins/
   |__ MyPlugin07/
      |__ config.yaml
      |__ lib/
      |  |_ MyPlugin07/
      |     |__ L10N.pm
      |     |_ L10N/
      |     |  |_ en_us.pm
      |     |  |_ ja.pm
      |     |_ Tags.pm
      |__ php/
      |  |_block.mtcategoryiftoplevel.php
      |__ t/
         |_00-compile.t
         |_01-tags.t

テストの実行

では、作成したプラグインに対してテストを行います。

00-compile.t

$ perl plugins/MyPlugin07/t/00-compile.t 
1..5
ok 1 - MyPlugin07 plugin loaded correctry
ok 2 - require MyPlugin07::L10N;
ok 3 - require MyPlugin07::L10N::ja;
ok 4 - require MyPlugin07::L10N::en_us;
ok 5 - require MyPlugin07::Tags;

01-tags.t

$ perl plugins/MyPlugin07/t/01-tags.t 
1..7
ok 1 - 'blog-name' template found
ok 2 - Test blog loaded
ok 3 - Test entry loaded
ok 4 - perl test 1
ok 5 - perl test 2
ok 6 - perl test 3
ok 7 - ok - php test 1 ok - php test 2 ok - php test 3 

proveコマンドでのテスト

$ prove plugins/MyPlugin07/t/*.t
plugins/MyPlugin07/t/00-compile.t .. ok   
plugins/MyPlugin07/t/01-tags.t ..... ok   
All tests successful.
Files=2, Tests=12, 29 wallclock secs ( 0.08 usr  0.07 sys + 15.45 cusr  4.73 csys = 20.33 CPU)
Result: PASS

テストでの確認は終了しました。実際に管理画面からブログ記事アーカイブの"<div id=“alphe-inner”>"の下にタグを記入し、スタティックの場合は再構築後、ダイナミックではそのまま各ブログ記事にトップレベルカテゴリに関する事が書き込まれます。

  • 記入例
(前略)
<div id="alpha">
  <div id="alpha-inner">
    <MTCategoryIfToplevel>
    <p>このブログ記事にはトップレベルカテゴリが設定されています。</p>
    <MTElse>
    <p>このブログ記事にはカテゴリが設定されていないか、トップレベルカテゴリ以外が設定されています。</p>
    </MTCategoryIfToplevel>
(後略)
  • 出力例
(前略)
<div id="alpha">
  <div id="alpha-inner">

    <p>このブログ記事にはトップレベルカテゴリが設定されています。</p>
(後略)

まとめ

前回のブロックタグと同じく、Perl版はコード内で処理をし、PHP版はコードを一旦抜けるようになっています。

やはり直感的なのはPerl版ですが、PHP版も今回の解説でご理解頂いたと思います。Perl版のプラグインを書く場合は一緒にPHP版も書いてみましょう。

プラグインダウンロード

MyPlugin07.zip(5.98KB)

プラグイン開発ガイド インデックス

  1. プラグイン開発のためのファーストステップ
  2. レジストリ、YAMLについて
  3. 環境変数について
  4. プラグインのローカライゼーションについて
  5. テストドリブンでのプラグインの開発について
  6. グローバル・モディファイアプラグインの開発について
  7. ファンクションタグ プラグインの開発について
  8. ブロックタグ プラグインの開発について
  9. コンディショナルタグ プラグインの開発について
  10. プラグインのデバッグ
  11. プラグインの設定方法
  12. コールバックとフックポイント
  13. スケジュールタスクの開発
  14. MTオブジェクトの利用方法
  15. 独自オブジェクトの作成
  16. 新規アプリケーションの作成
  17. Transformerプラグインの開発
  18. 管理画面のメニュー修正
  19. リストアクションの追加
  20. 動作モードの追加とモーダルウィンドウの表示
  21. 外部Web APIとの連携
  22. 権限とロール
Clone this wiki locally