English plugin dev 4 3 - Hiranyaloka/Documentation GitHub Wiki
MT利用していると「管理画面のここを変更したい」「管理画面の使わない箇所を削除してしまいたい」などの欲求が出てくると思います。
そこで今回はTransformerプラグインによる管理画面の表示内容変更について解説します。
Transformerプラグインは名前のとおり「実際の管理画面をトランスフォーム(変身)させることで表示を変更する」ものです。
Transformer用のフックポイントがあるので、コールバックを使って管理画面を変身(修正、追加、削除)させます。
- ブログ記事、ウェブページともエディット画面で「続き」ボタンを消す
- 「お客様から自分が必要無いな機能を外してほしい」と言われたと仮定
-
DOM
ID=keywordsの次にURLを記入できる欄を追加する- URL欄が空白の場合は"http://www.example.com/"を入力する
- URL欄は表示だけで、保存、修正などできなくてよい(あくまで表示例)
id: MyPlugin13
key: MyPlugin13
name: <__trans phrase="Sample Plugin Transformer">
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: MyPlugin13::L10N
callbacks:
MT::App::CMS::template_source.edit_entry: $MyPlugin13::MyPlugin13::Transformer::hdlr_template_source_edit_entry
MT::App::CMS::template_output.edit_entry: $MyPlugin13::MyPlugin13::Transformer::hdlr_template_output_edit_entry
MT::App::CMS::template_param.edit_entry: $MyPlugin13::MyPlugin13::Transformer::hdlr_template_param_edit_entry
config.yamlで注目するのはcallbacks以下の3行です。
- MT::App::CMS::template_source.(テンプレート名): $(プラグイン名)::(Perlモジュール名)::(ハンドラ関数)
-
template_sourceは処理前のテンプレートを変更するためフックポイントです。 - テンプレートは
$MT_DIR/tmpl/cmsの中にあり、設定系はconf_xxx.tmpl、 一覧系はlist_xxx.tmpl、新規・修正系はedit_xxx.tmplのようになっています。今回はブログ記事(entry)の修正なのでedit_entry.tmplとなりますが、拡張子を取った物(edit_entry)がテンプレート名になります。
-
- MT::App::CMS::template_output.(テンプレート名): $(プラグイン名)::(Perlモジュール名)::(ハンドラ関数)
-
template_outputは処理後のテンプレートを変更するためフックポイントです。 - テンプレート名は 。上記と同じ理由で
edit_entryとなります。
-
- MT::App::CMS::template_param.(テンプレート名): $(プラグイン名)::(Perlモジュール名)::(ハンドラ関数)
-
template_paramは値を代入したり、DOMベースでの文字列の挿入などを行うフックポイントです。 - テンプレート名は 。上記と同じ理由で
edit_entryとなります。
-
package MyPlugin13::Transformer;
use strict;
sub hdlr_template_source_edit_entry {
my ($cb, $app, $tmpl_ref) = @_;
my $old = <<EOF;
<div class="tab" mt:command="set-editor-extended" mt:tab="extended">
<label><a href="javascript:void(0);"><__trans phrase="Extended"></a></label>
</div>
EOF
$old = quotemeta($old);
$old =~ s!(\\ )+!\\s+!g;
my $new = "";
$$tmpl_ref =~ s!$old!$new!;
}
sub hdlr_template_output_edit_entry {
my ($cb, $app, $tmpl_str_ref, $param, $tmpl) = @_;
# do something
}
sub hdlr_template_param_edit_entry {
my ($cb, $app, $param, $tmpl) = @_;
my $host_node = $tmpl->getElementById('keywords');
my $innerHTML = '<input type="text" name="url_field" id="url_field" class="full-width" mt:watch-change="1" value="<mt:var name="url_field" escape="html">" autocomplete="off" />';
my $block_node = $tmpl->createElement(
'app:setting',
{
id => 'url_field',
label => 'URL',
label_class => 'top-label',
}
);
$block_node->innerHTML( $innerHTML );
$tmpl->insertAfter($block_node, $host_node);
$param->{url_field} = "http://www.example.com/" if !$param->{url_field};
}
1;
package MyPlugin13::Transformer; use strict;
- パッケージモジュール名を指定し
use strictします。
sub hdlr_template_source_edit_entry {
my ($cb, $app, $tmpl_ref) = @_;
my $old = <<EOF;
<div class="tab" mt:command="set-editor-extended" mt:tab="extended">
<label><a href="javascript:void(0);"><__trans phrase="Extended"></a></label>
</div>
EOF
$old = quotemeta($old);
$old =~ s!(\\ )+!\\s+!g;
my $new = "";
$$tmpl_ref =~ s!$old!$new!;
}
-
sub hdlr_template_source_edit_entry{}-
$cbコールバック、$appアプリケーション情報、$tmp_refテンプレートのリファレンスです。 -
$oldに修正したい文字列を代入します。今回は削除したい箇所(続きタブ)になります。 - 後で利用する置換の文字列に’(‘, ’)’が入っているため、
quotemeta()に通します。 - MT5.0とMT5.1両方に対応するため、空白文字を
\s+に入れ替えます。 - 今回削除なので置換する文字列(
$new)は空文字です。 - テンプレートのリファレンスからテンプレートを引出し(
$$tmpl_ref)、置換を行います。 - これを行うことで「本文」タブの横の「続き」タブが消えます。
-
sub hdlr_template_output_edit_entry {
my ($cb, $app, $tmpl_str_ref, $param, $tmpl) = @_;
# do something
}
-
sub hdlr_template_output_edit_entry {}- この関数も
template_sourceと同じくテンプレートの修正をしますが、template_sourceが手を入れる前のテンプレートに大して行うのと違い、テンプレートの構築処理が終わった後の出力($tmpl_str_ref)に対して修正を行います。 - それ以外の説明は
template_sourceと同じなので省略します。
- この関数も
sub hdlr_template_param_edit_entry {
my ($cb, $app, $param, $tmpl) = @_;
my $host_node = $tmpl->getElementById('keywords');
my $innerHTML = '<input type="text" name="url_field" id="url_field" class="full-width" mt:watch-change="1" value="<mt:var name="url_field" escape="html">" autocomplete="off" />';
my $block_node = $tmpl->createElement(
'app:setting',
{
id => 'url_field',
label => 'URL',
label_class => 'top-label',
}
);
$block_node->innerHTML( $innerHTML );
$tmpl->insertAfter($block_node, $host_node);
$param->{url_field} = "http://www.example.com/" if !$param->{url_field};
}
-
sub hdlr_template_param_edit_entry {}-
$cbコールバック、$appアプリケーション情報、$paramテンプレートの構築時に渡されるパラメータ、$tmplテンプレートオブジェクトです。 -
getElementByIdを使ってDOMの’keywords’のノードを検索します。 -
$innerHTMLに、挿入したい文字列をセットします。 -
createElementを使って新規のノードをセットします。 - 新規ノードに
$innerHTMLをセットします。 -
insertAfter($block_node, $host_node)を使って$host_nodeの後に$block_nodeを挿入します。 - 最後の
$paramはDOMの説明とは関係ありませんがtemplate_paramの本来の使い方で、構築時のパラメータとして任意のものを渡す事ができます。- 例えば今回の場合、新規に追加した行に
<mt:var name="url_field">がありますので、そちらに値(http://www.example.com/)が設定されます。 - 条件としては
$param->{url_field}に値がセットされてい無い場合に値(http://www.example.com/)がセットされるように実装されています。 - このURLはブログ記事を保存してもデータベースに値が保存されません。ブログ記事クラスの拡張や、URLクラスを作成してブログ記事の
post_saveで保存するなど実装方法が色々と考えられますが、今回は省略します。
- 例えば今回の場合、新規に追加した行に
-
DOM関連の関数は MT::Template に実装されています。
| sub getElementsByTagName {} | タグ名でDOMエレメントを検索する |
| sub getElementsByClassName {} | クラス名でDOMエレメントを検索する |
| sub getElementsByName {} | nameでDOMエレメントを検索する |
| sub getElementById {} | idでDOMエレメントを検索する |
| sub createElement {} | 新規ノードを作成する |
| sub createTextNode {} | 新規テキストノードを作成する |
| sub insertAfter {} | 指定されたDOMエレメントの後にエレメントを挿入する |
| sub insertBefore {} | 指定されたDOMエレメントの前にエレメントを挿入する |
| sub childNodes {} | 指定された物の子ノードを取得する |
| sub hasChildNodes {} | 子ノードの有無を確認する |
| sub appendChild {} | 指定されたノードに子ノードを追加する |
取得したノードの操作のために、 MT::Template::Node に関数が用意されています。
| sub nodeValue {} | 与えられたノードの値を取得する |
| sub childNodes {} | 与えられたノードの子ノードを取得する |
| sub attributes {} | ノードの属性を取得する |
| sub attribute_list {} | ノードの属性リストを取得する |
| sub tag {} | ノード名の設定と取得を行う |
| sub setAttribute {} | ノードの属性を設定する |
| sub getAttribute {} | ノードの属性を取得する |
| sub firstChild {} | 最初の子ノードを取得する |
| sub lastChild {} | 最期の子ノードを取得する |
| sub nextSibling {} | 次のノードを取得する |
| sub previousSibling {} | 前のノードを取得する |
| sub ownerDocument {} | ノードのテンプレートオブジェクトを取得する |
| sub hasChildNodes {} | 子ノードの有無を確認する |
| sub nodeType {} | ノードのタイプ名を取得する |
| sub nodeName {} | ノード名を取得する |
| sub innerHTML {} | HTML(もしくはXTML)を挿入する |
| sub appendChild {} | 子ノードを追加する |
| sub removeChild {} | 子ノードを削除する |
| sub upgrade {} | ノードをUTF8にエンコードする |
$MT_DIR/
|__ plugins/
|__ MyPlugin13/
|__ config.yaml
|__ lib/
|_ MyPlugin13/
|__ L10N.pm
|_ L10N/
| |_ en_us.pm
| |_ ja.pm
|__ Transformer.pm
とっかかりは難しそうですが、管理画面で困っている場合は今回解説した管理画面の修正をしてみてはいかがでしょうか?
ただしTransformerプラグインは、MTのバージョンにより置換文字列などを修正する必要など出てくる場合がありますのでご注意ください。
- プラグイン開発のためのファーストステップ
- レジストリ、YAMLについて
- 環境変数について
- プラグインのローカライゼーションについて
- テストドリブンでのプラグインの開発について
- グローバル・モディファイアプラグインの開発について
- ファンクションタグ プラグインの開発について
- ブロックタグ プラグインの開発について
- コンディショナルタグ プラグインの開発について
- プラグインのデバッグ
- プラグインの設定方法
- コールバックとフックポイント
- スケジュールタスクの開発
- MTオブジェクトの利用方法
- 独自オブジェクトの作成
- 新規アプリケーションの作成
- Transformerプラグインの開発
- 管理画面のメニュー修正
- リストアクションの追加
- 動作モードの追加とモーダルウィンドウの表示
- 外部Web APIとの連携
- 権限とロール