MT4でMT::Objectを継承したサブクラスを作ってDBのテーブルを拡張する(メモ)。

| コメント(0) | トラックバック(0)

メモ。

MTの「コア」のテーブルにカラムを追加するのってどうなのよ! バージョンアップの際にも困るんでないの? ってかプラグインみたいな気軽に付けたり外したりするものでカラムを追加するのってさぁ...というお話があがっているので素直にMT4でMT::Objectを継承したサブクラスを作ってDBのテーブルを拡張する方法でやってみようかと。

モデルは数日前に作った「TemplateSelector」プラグイン。

# 何とか出来たっぽいけど効率が良いとは言えないなぁ...ということでテストも不十分だしまだ公開はしない。あくまでも備忘録です。

TemplateSelector(改)プラグインの構成

Selector.pm をプラグインフォルダの lib/TemplateSelector 以下に設置


plugins/TemplateSelector/lib/TemplateSelector/Selector.pm

Selector.pm


package TemplateSelector::Selector;
use strict;

@TemplateSelector::Selector::ISA = qw( MT::Object );
__PACKAGE__->install_properties({
	column_defs => {
		'id' => 'integer not null auto_increment',
		'blog_id' => 'integer not null',
		'entry_id' => 'integer not null',
		'template_name' => 'string(255)',
	},
	indexes => {
		blog_id => 1,
		entry_id => 1,
		template_name => 1,
	},
	child_of => 'MT::Entry',
	datasource => 'selector',
	primary_key => 'id',
});

1;

TemplateSelector.pl


use TemplateSelector::Selector;


中略

sub init_registry {
    my $plugin = shift;
    $plugin->registry({
        object_types => {
            'selector' =>  'TemplateSelector::Selector',
        },

以下略

これで、プラグインを「new」する時に schema_version を指定してやればUpgraderが起動してデータベースにテーブルを追加してくれる。

Selector.pmで「child_of => 'MT::Entry',」とすることで、該当のエントリーが削除されたらSelectorの該当するフィールドを削除してくれる。このあたりはさすが!

entry_idで紐付をして、エントリーがどのテンプレートを選択しているかを template_name に突っ込みたいが、これはさすがに自前でコードを書く必要がある。カラムの拡張ならフォームのname属性をtemplate_nameにしたセレクトメニューとかチェックボックスを用意すれば保存時に勝手に保存してくれる。これが便利すぎて嫌になる(カラムを拡張する誘惑に負けそうになる)。

気を取り直して、コード部分。

init_registryにコールバックを登録する。

  • 'MT::App::CMS::template_source.edit_entry' → セレクトメニューを登録するTransformer
  • 'cms_post_save.entry'→エントリーが保存された後処理(このタイミングで処理する)

TemplateSelector.pl (続き)


        callbacks => {
            'MT::App::CMS::template_source.edit_entry'
                => ¥&_add_template_selector,
            'cms_post_save.entry'
                => ¥&_entry_selector,


中略

sub _entry_selector {
    my ($eh, $app, $obj, $original) = @_;
    my $q = $app->param;
    my $template_name = $q->param('template_name');
    my $id = $obj->id;
    my $sel = TemplateSelector::Selector->load({ entry_id => $id });
    if ($template_name) {
        unless (defined $sel) {
            $sel = TemplateSelector::Selector->new;
            $sel->entry_id($id);
        }
        $sel->template_name($template_name);
        $sel->blog_id($app->blog->id);
        $sel->save or die $sel->errstr;
    } else {
        if (defined $sel) {
            $sel->remove or die $sel->errstr;
        }
    }
}

これで、エントリーが保存されるのと同時に selector_template_name が保存されるようになった。

これで「出来た!」という程世の中甘くなかったよ。問題はテンプレートを選択した時のプレビュー(「確認」ボタンクリックした時の画面)。プレビューではテンプレートが選択されたテンプレートになってくれない。一旦エントリーを保存すれば良いわけだけど、これは多分「あり得ない」仕様だろうなぁ。テンプレートを切り替えてもエントリー公開するまでデザインが確認できないなんて!

ということで、プレビューも自前で実装(何とかならんものか)。でもこれやっとかないと「フィールド拡張」も出来ないし。

コールバックに以下を追加。

TemplateSelector.pl (さらに続き)


            'MT::App::CMS::template_output.preview_strip'
                => ¥&_style_preview,

CMS.pmのコードを読むと、未保存のエントリーのプレビュー時には entry_id(-1) としてるようなので、一時的に TemplateSelector::Selector->new;して entry_id(-1) として selector_template_name にテンプレート名をセットして保存、プレビュー用のHTMLをbuildしたらそのレコードは削除することにした。


sub _style_preview {
    my ($eh, $app, $tmpl) = @_;
    my $q = $app->param;
    my $id = $q->param('id');
    my $template_name = $q->param('template_name');
    my $sel; my $org_templ_name; my $tmp_sel;
    unless ($id) {
        $sel = TemplateSelector::Selector->new;
        $sel->id(-1);
        $sel->entry_id(-1);
        $sel->template_name($template_name);
        $sel->blog_id($app->blog->id);       
        $sel->save or die $sel->errstr;
    } else {
        $tmp_sel = TemplateSelector::Selector->load( { entry_id => $id } );
        if (defined $tmp_sel) {
            $tmp_sel->template_name($template_name);
        }
    }
    my $blog = $app->blog;
    my $blog_id = $blog->id;
    my $tmap = MT::TemplateMap->load(
                            {    blog_id => $blog_id,
                                 archive_type => 'Individual',
                                 is_preferred => 1
                            },);
    my $template = MT::Template->load({id => $tmap->template_id});
    my $preview_tmpl = $app->translate_templatized($template->output);
    $$tmpl = $preview_tmpl;
    unless ($id) {
        $sel->remove or die $sel->errstr;
    }
}

とりあえず「保存」ボタンとか「エントリー編集画面に戻る」ボタンが無いので「ブラウザのバックボタン」で戻ってね状態だけどプレビューにテンプレートの変更が反映されるようになった。フーーーッ! 結構面倒だなぁ、というのが正直な感想。

MT3.xでも有効な例はこちらに↓。

トラックバック(0)

トラックバックURL: http://junnama.alfasado.net/cgi/mt/mt-tb.cgi/193

コメントする

Facebook

Twitter

このブログ記事について

このページは、Junnama Nodaが2007年9月 3日 19:59に書いたブログ記事です。

ひとつ前のブログ記事は「ウェブ制作者に求められているのは「プロセスをデザインする力」。」です。

次のブログ記事は「評論家になんてなるんじゃねぇぞ。」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.2.6