transformerの使い方

一般(?)に広くtransformerと呼ばれる、MT3.3から導入された機能群。
プラグインから管理画面を変更する手段を提供することで、より高度なプラグインの作成が可能となります。
しかし、現在日本語では殆どドキュメントが用意されていない状況です。
興味本位でちょっと調べてみたところ、こんなことも出来るのか、という使い勝手の良い部分が、知られずに埋もれていると感じたので、まとめておきます。後でチョコチョコと追記するかもしれません。
妙に堅い説明口調になってしまったのは、何ででしょうね。。。

ちなみに、3.3前後のmtのプロジェクト名は、全てアニメのトランスフォーマーのロボットの名前から取られているそうです ;-)

3つのコールバック

主に以下のコールバックを利用することで、管理画面の変更が行えます。
  • AppTemplateSource
  • AppTemplateParam
  • AppTemplateOutput

それぞれのコールバックでは、実行されるタイミング、および渡される引数が異なるため、目的に応じて使い分けます。引数などの詳細はMovable Type オブジェクト・リファレンス - MT::Appの「コールバック」の項を参照してください。

Movable Typeの管理画面は、HTML::Templateモジュールを利用して出力されています。ある程度踏み込んだ作業を行う場合、HTML::Templateモジュールについての知識も必要になるでしょう。

AppTemplateSource

管理画面のテンプレートを直接変更することが出来ます。実行されるのはHTML::Templateがテンプレートタグのパースを行う前なので、単純な文字列置換のほかにも、HTML::Templateのタグを直接書き換えることも可能です。

TMPL_INCLUDEで読み込まれるテンプレートについては、注意が必要です。AppTemplateSourceコールバックの実行ルーチンは、HTML::Templateのfilterとして登録されるので、TMPL_INCLUDEによって新たにテンプレートが読み込まれる都度、実行されます。

HTML::Template - CGI スクリプトから HTML テンプレートを使うための Perl モジュール

filter - このオプションはテンプレートファイルに対するフィルタを指定します。フィルタは HTML::Template がテンプレートファイルを読み込んだ後、テンプレートタグのパーズを開始する前に呼び出されるサブルーチンです。

(中略)

指定されたフィルタは TMPL_INCLUDE でファイルが読み込まれる度にメインのテンプレートファイルと同様に適用されます。

しかし、filter内でコールバックの判定と実行が行われるため、variant(ポイント以降の部分。この場合はファイル名)が指定されているコールバックは、その段階で「今回実行する必要がないコールバック」と判定されてしまい実行されません。その結果、たとえば

MT->add_callback('MT::App::CMS::AppTemplateSource.list_blog', 9, $plugin, \&transform_routine);
として登録したコードは、list_blog.tmplファイル内部でインクルードされるheader.tmplに対しては実行されません。header.tmplのインクルードの際にコールバックされるのは、AppTemplateSource.headerに登録したコールバックや、variant無しでAppTemplateSourceに登録したコールバックです。
この仕様により、list_blog画面でのみheaderのテンプレートに変更を加える、ということは実現が難しくなっています。もしHTML::Templateによるテンプレートの展開が終了した後でも実現可能な作業ならば、迷わず「AppTemplateOutput」を使うべきでしょう。


管理画面の全てのページにスタイルシートやjavascriptを追加する場合にも、このコールバックを利用するとちょっと便利です。headerテンプレートには「<MT_HEAD:STYLE>」「<MT_HEAD:SCRIPT>」という、スタイルシートとjavascriptをhead要素内に追加するためのプレースホルダーが用意されています。具体的には、以下のサブルーチンを呼び出すことで、これらプレースホルダーの位置に任意の内容を挿入出来ます。

tmpl_prepend
tmpl_prepend($tmpl, $section, $id, $content);
プレースホルダーの先頭に$contentで指定した文字列を追加します。
tmpl_replace
tmpl_replace($tmpl, $section, $id, $content);
プレースホルダー全体を$contentで指定した文字列で置き換えます。
tmpl_append
tmpl_prepend($tmpl, $section, $id, $content);
プレースホルダーの先頭に$contentで指定した文字列を追加します。
tmpl_select
tmpl_select($tmpl, $section, $id);
プレースホルダーの現在の内容を返します。

$tmplには、テンプレートの内容へのリファレンスを指定する必要があります(AppTemplateSourceから渡される$tmpl変数をそのまま渡せばよいです)。

$sectionと$idの組み合わせによってターゲットとなるプレースホルダーを指定します。mt-3.34では、$sectionに文字列「HEAD」、$idには文字列「STYLE」または「SCRIPT」という組み合わせが利用可能です。他には、やはりheaderテンプレートで「TOPNAV」「BLOGMENU」という組み合わせも利用できそうです(未確認)。将来的には、他にもプレースホルダーが追加されるのかもしれません。

例えば、管理画面の背景に何らかの画像を表示させたい場合、次のようなコードになります。

MT->add_callback('MT::App::CMS::AppTemplateSource', 9, $plugin, \&change_background);
 
sub change_background {
    my ($eh, $app, $tmpl) = @_;
    my $contents = 'body { background-image: url(http://www.example.com/some_image.gif); }';
    $app->tmpl_append( $tmpl, 'HEAD', 'STYLE', $contents);
}

なお、最終出力に対してカスタマイズを行うAppTemplateOutputでは、プレースホルダーがすでにテンプレートから削除されているため、これらのサブルーチンは利用できません。

AppTemplateParam

HTML::Templateに渡されるパラメータに対して、追加や変更を行うことが出来ます。

whatisthequicksearch.png


例えば、管理画面の右上にあるクイックサーチ部分はパラメータで表示、非表示を切り替えているため、以下のようなコードで表示を抑制することが出来ます。

MT->add_callback('MT::App::CMS::AppTemplateParam', 9, $plugin, sub{ $_[2]->{quick_search} = 0 });

とはいえ、既存のパラメータについては、あまり多くの変更の余地は無いかもしれません。このコールバックは、(AppTemplateSourceコールバックと組み合わせて、)プラグインで独自にHTML::Templateのタグを追加する場合などに、より大きな威力を発揮するでしょう。

AppTemplateOutput

最終的に出力されるHTMLに対して変更を行うことが出来ます。HTML::Templateのタグはすべて展開済みとなっているため、正規表現による置換を行う場合には注意が必要です。