アルファサード株式会社 代表取締役 野田 純生のブログ


Movable Type管理画面の「壊れにくい」カスタマイズのために。


公開日 : 2008-06-11 11:21:26


MT4LP5(CSS Nite LP, Disk 5)「Movable Type プロフェッショナルスタイル」の中でalt-tmplフォルダに代替テンプレートを放り込んでそれに手を入れる方法があるよ、ということを例をあげて説明しているのですが、「管理画面をカスタマイズするとバージョンアップで管理画面のインターフェイスが変更された時どうよ」みたいな話が出ます。

実際問題、これはどうしようもないと思います。MT3→MT4で管理画面カスタマイズ系のプラグインの多くがそのままでは動かなくなったことは記憶に新しいと思うわけですが、それでも「壊れにくい」「修正対応しやすい」カスタマイズの方法とか注意点とかがそれなりにあるのでそのあたりを少しご紹介します。

可能な限りプラグインで拡張可能なアクション、ウィジェット、メニュー等として登録するように

例えばボタンひとつ追加、とかの場合は以下のようにMTのプラグインによって拡張する方法が提供されているので、基本的にバージョンアップ時にもそのまま使えます。実際list_actions, page_actionsはMT3系の時も提供されていました。ただ、メジャーバージョンアップの時に仕組み自体が変更になるかならないかはわかりません(menu等はMT4で導入されているし、その辺のしくみが変更になる可能性はないとはいえません*)。

* ただ、これまでの流れを見る限りMTの場合移行の際の互換性には最大限の気配りがされているので、少なくともバージョン一つアップして使えないってことは考えにくいと思います。

プラグインアクション(list)


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                list_actions =>

プラグインアクション(リスト)

プラグインアクション(page)


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                page_actions =>

プラグインアクション(ページ)

メニュー(dialog)

sub init_registry {

    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                menus => {
                    'create:ui_sample_dialog' => {
                        dialog => 'foo',

メニュー(mode)


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                menus => {
                    'create:ui_sample_mode' => {
                        mode => 'foo',

メニュー

ダッシュボード(widget)


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        widgets => {
            my_widgets => {
                label    => 'My Widget',

ダッシュボードウィジェット

カスタムインポートフォーマット


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        'import_formats' => {
            'import_ctsv' => {
                label => 'CSV or Tab-Separated Values',

インポートフォーマット

クイックフィルタ


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        applications => {
            cms => {
                list_filters   => {
                    entry => {
                        next_approval => {
                            label => 'Next revision awaiting approval',
                            order   => 1000,
                            handler => sub {
                                my ( $terms, $args ) = @_;
                                $terms->{next_status} = 6;
                            },
                        },

クイックフィルタ

template_paramコールバックのDOMScriptingで拡張する

template_param, template_source, template_output コールバックで管理画面に変更を加えるときは正規表現でソース等を書き換えるよりもtemplate_paramコールバックのDOMScriptingで拡張するほうが(比較的)壊れにくい。正規表現で置換とかやらないと実現出来ないケースも多いとは思うけれど、その場合でもソースの書き換えは最小限ので済ませ、template_paramで値をセットしたり書き換える箇所が後から変更になっても柔軟に対応出来るようにalt-tmplと組み合わせる(テンプレートにソースを挿入するポイントにコメントを入れるとか)等、工夫次第でメンテナンス性の高いカスタマイズとすることもできるでしょう。

BlogBody, BlogMore, BlogKeyword, BlogExcerptフィールドを追加する例


sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        object_types => {
            'blog' => {
                'text' => 'text',
                'keywords' => 'text',
                'text_more' => 'text',
                'excerpt' => 'text',
            },
        },
        callbacks => {
            'MT::App::CMS::template_param.cfg_prefs'
                => ¥&_blog_extras_param,
        },
   });
}

sub _blog_extras_param {
    my ($cb, $app, $param, $tmpl) = @_;
    my $pointer_field = $tmpl->getElementById('description');
    my $nodeset = $tmpl->createElement('app:setting', { id => 'keywords', label => $plugin->translate('Keywords') , required => 0 });
    my $innerHTML = '<div class="textarea-wrapper"><textarea name="keywords" id="keywords" class="full-width short" cols="" rows=""><mt:var name="keywords" escape_html="1"></textarea></div>';
    $nodeset->innerHTML($innerHTML);
    $tmpl->insertAfter($nodeset, $pointer_field);
    $nodeset = $tmpl->createElement('app:setting', { id => 'excerpt', label => $plugin->translate('Excerpt') , required => 0 });
    $innerHTML = '<div class="textarea-wrapper"><textarea name="excerpt" id="excerpt" class="full-width short" cols="" rows=""><mt:var name="excerpt" escape_html="1"></textarea></div>';
    $nodeset->innerHTML($innerHTML);
    $tmpl->insertAfter($nodeset, $pointer_field);
    $nodeset = $tmpl->createElement('app:setting', { id => 'text_more', label => $plugin->translate('Extended Page') , required => 0 });
    $innerHTML = '<div class="textarea-wrapper"><textarea name="text_more" id="text_more" class="full-width short" cols="" rows=""><mt:var name="text_more" escape_html="1"></textarea></div>';
    $nodeset->innerHTML($innerHTML);
    $tmpl->insertAfter($nodeset, $pointer_field);
    $nodeset = $tmpl->createElement('app:setting', { id => 'text', label => $plugin->translate('Text') , required => 0 });
    $innerHTML = '<div class="textarea-wrapper"><textarea name="text" style="height:150px" id="text" class="full-width short" cols="" rows=""><mt:var name="text" escape_html="1"></textarea></div>';
    $nodeset->innerHTML($innerHTML);
    $tmpl->insertAfter($nodeset, $pointer_field);
}

ブログのフィールド拡張

alt-tmplの書き換えでは追加・変更箇所をできるだけ外部ファイルとしてインクルードする

alt-tmplにコピーを置いて直接手を入れる場合は「テンプレートの見通しを良くする」「変更箇所がわかりやすいようにする」というオーソドックスな考え方でメンテナンス性向上とバージョンアップ時の対応コストを下げることができるでしょう。

例えば以下のようにして変更箇所をインクルードファイルにしておけばバージョンアップの際にそのまま使えるかもしれない(CSSとかid/class名の変更くらいは必要かもしれないけれど)。


<mt:include name="include/edit_entry_extra.tmpl" id="edit_entry_extra">

テンプレートの変更箇所にコメントを入れる

お約束ということで。


<mt:ignore>======拡張フィールドの追加======</mt:ignore>
<mt:include name="include/edit_entry_extra.tmpl" id="edit_entry_extra">
カテゴリ


このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の代表取締役社長であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ