プラグインによるテーマフレームワークの拡張
プラグイン作者向けの テーマ フレームワークの拡張方法を説明します。
テーマ フレームワーク と テーマ パッケージ
テーマ パッケージ とは
Movable Type で利用できる状態のテーマのデータです。テーマをプラグインで定義するか、あるいは themes ディレクトリに配置します。
テーマ フレームワーク とは
Movable Type がテーマ パッケージのデータを入出力するための仕組です。プラグイン作者は、テーマ フレームワークを拡張することで、自分のプラグインのデータを、テーマ パッケージから利用できます。
テーマ パッケージ の各項目は、テーマ エレメントとして定義されています。このテーマ エレメントの読み込みと書き出しは、インポータと エクスポータ によっておこないます。プラグイン作者は、独自のインポータ と エクスポータ を実装することで、テーマ パッケージに含めるテーマ エレメントのデータ構造を拡張できます。
インポータ と エクスポータ
インポータは、Movable Type がテーマ エレメントを利用するために必要です。
エクスポータは、Movable Type の管理画面からテーマをエクスポートするときに必要です。したがって、既存のウェブサイトやブログからテーマをエクスポートしない場合には、実装する必要はありません。
インポータの仕様をドキュメントなどで詳しく解説することで、エクスポータを実装せずともテーマ作者が、テーマ エレメントを テーマ パッケージに 手書きで含めることが可能です。
インポータ と エクスポータの追加方法
インポータは、レジストリに加えて、Perl のルーチンを用意する必要があります。以下をプラグインに追加します。
- インポート処理をおこなう、Perl で書かれたサブルーチンを用意する。
- 上記のハンドラコードを、Movable Type に登録するレジストリ エントリーを用意する。
レジストリへの登録
以下の yaml コードは、レジストリへの登録例です。
theme_element_handlers: my_element_handler: label: My Element Handler importer: import: $MyPlugin::MyPlugin::Theme::apply info: $MyPlugin::MyPlugin::Theme::info validator: $MyPlugin::MyPlugin::Theme::validator exporter: params: custom_fields_export_ids component: my_plugin condition: $MyPlugin::MyPlugin::Theme::condition template: $MyPlugin::MyPlugin::Theme::template export: $MyPlugin::MyPlugin::Theme::export
インポータ
インポータとテーマ エレメントは対になります。ウェブサイトあるいはブログにテーマを適用するときに、Movable Type はテーマに含まれるすべてのテーマ エレメントについて、対応するインポータを探して、処理を実行します。具体的なデータの処理は、インポータ側に実装します。
もしインポータが見つからない場合は、そのテーマ エレメントが必須であれば、処理を中止してユーザーにエラーを通知します。必須では無いときは次のテーマ エレメントの処理に移りテーマの適用を続行します。
import
テーマを適用する Perl のサブルーチンを指定します。引数として、3 つのオブジェクトが渡されます。
- 適用するテーマ エレメント
- テーマ エレメントを含むテーマ全体
- テーマを適用する(多くの場合は作成されたばかりの) MT::BlogまたはMT::Website のインスタンス
テーマ エレメント および テーマ全体は、それぞれ MT::Theme::Element と MT::Theme クラスに bless されたオブジェクトとして引き渡されます。
以下は、ブログの各種設定を埋め込んだ テーマ エレメントを、MT::Blog クラスに適用するインポータの例です。
sub my_importer { my ( $element, $theme, $obj_to_apply ) = @_; my $data = $element->data; if ( ref $obj_to_apply ne MT->model('blog') ) { return $element->errtrans('this element cannot apply for not blog object.'); } my $blog = $obj_to_apply; for my $conf ( keys $data ) { if ( $blog->has_column($conf) ) { my $value = $data->{$conf}; $blog->$conf($value); } } return 1; }
info
Movable Type がテーマの内容を解析するためのサブルーチンです。テーマを適用したときに、何が起こるかをユーザーに伝えるメッセージを表示します。
sub info { my ($element, $theme, $blog) = @_; my $item_count; ## analyse the $element and set some value for $item_count return sub { MT->translate( '[_1] items would be added to your blog.', $item_count, ); }; }
validator
現在のブログの状態をテストし、テーマ エレメントの読み込みが可能かを判断するサブルーチンを指定します。
sub validator { my ( $element, $theme, $obj_to_apply ) = @_; my $conflict; ## validate $obj_to_apply is okay to apply $element. if ( $conflict) { return $element->error( MT->translate( 'Conflict has occured!', ) ); } return 1; }
エクスポータ
params
テーマをエクスポートするときに、オプション設定画面で使用するパラメータ一の名前を指定します。Movable Type はこの値をもとに、エクスポート設定を保持します。複数のパラメータを利用する場合、Array_ref で指定してください。
component
エクスポートしたデータを、インポートするインポータの ComponentID を指定します。
template
エクスポートのオプション設定画面の出力サブルーチンを指定します。
sub export_template { my $app = shift; my ( $blog, $setting ) = @_; $setting = { some_setting => 'default' } if !defined $setting; my $param = $setting->{some_setting}; my %param = ( param_for_tmpl => $param, ); return $app->load_tmpl( 'include/my_export_screen.tmpl', ¥%param, ); }
export
実際のエクスポート処理を行うサブルーチンを指定します。
sub export { my $app = shift; my ( $blog, $setting ) = @_; my $export_data = {}; ## do copy some data from $blog to $export_data return $export_data; }
export サブルーチンではハッシュリファレンスをリターンするようにしてください。この戻り値が、エクスポートされたテーマ エレメントの data 要素として格納されます。
finalize
エクスポート処理の後に実行するサブルーチンを指定します。ここで指定したサブルーチンは、テーマのデータ構造が問題無く作成され、エクスポート処理用のテンポラリーディレクトリを確保した後に呼び出されます。ファイルコピーのような、テーマへの直接の操作をおこなうことができます。
sub finalize { my $app = shift; my ( $blog, $theme_hash, $tmpdir, $setting ) = @_; my $success = 0; ## some work for $tmpdir return $success ? 1 : 0; }
condition
テーマをエクスポートするウェブサイトあるいはブログで、エクスポートハンドラが利用可能かどうかを判定するサブルーチンを指定します。たとえば、カテゴリが存在しないブログでは、カテゴリのエクスポートオプションを表示しないように判定します。
sub condition { my ( $blog ) = @_; # show export option if blog has at least one template. my $tmpl = MT->model('template')->load( { blog_id => $blog->id }, { limit => 1 }, ); return defined $tmpl ? 1 : 0; }
テーマのバージョン管理
テーマ パッケージ と インポータ には、各々 2 つのバージョン管理設定があります。
- テーマ パッケージ
- schema_version
- min_importer_version
- インポータ
- min_schema_version
- max_schema_version
min_schema_version <= schema_version <= max_schema_version
テーマ パッケージの schema_version が、インポータ の min_schema_version 以上、かつ max_schema_version 以下の場合は、正常に処理が行われます。
schema_version < min_schema_version
ひとつの問題は、プラグインがバージョンアップして、インポータが古いテーマを適用することが出来なくなった場合です。
インポータの min_schema_version よりも、テーマ パッケージの schema_version の方が低い場合、Movable Type はテーマ エレメントが必須であれば処理を中止してユーザーにエラーを通知します。必須では無いときは次のテーマ エレメントの処理に移りテーマの適用を続行します。
ただし、プラグイン作者はテーマの schema_version を確認して適切な代替値を入力するなど、出来得る限り下位互換性を確保することが推奨されます。
max_schema_version < schema_version
インポータの max_schema_version よりも、テーマ パッケージの schema_version が大きい場合も考えられます。最新のプラグインでエクスポートされたテーマを、古いバージョンのプラグインでインポートしようとした場合が考えられます。
この場合は、テーマ作者がテーマ パッケージで指定した min_importer_version を利用します。Movable Type は、テーマを利用するためには、プラグインをアップグレードする必要があることをユーザーに伝え、テーマの適用を続行または中止します。
推奨される設定
以下のようなバージョンの設定が推奨されます。
- テーマ パッケージ
- schema_version
テーマ作成時の最新バージョンを指定します。 - min_importer_version
テーマ作成時に、このテーマが古いインポータをロードできない場合は、ロード可能なインポータのバージョンを指定します。
- schema_version
- インポータ
- min_schema_version
インポータ作成時に、このインポータが古いテーマをロードできない場合は、ロード可能なテーマの schema_version を指定します。 - max_schema_version
インポータ作成時の最新バージョンを指定します。
- min_schema_version
最も良いのは、常に後方互換性を保つことです。インポータがすべてのバージョンのテーマ パッケージを読み込めれば、テーマ パッケージの schema_version と、インポータの max_schema_version に最新のバージョンを書くだけで問題ありません。