プラグインによるテーマフレームワークの拡張
プラグイン作者向けの テーマ フレームワークの拡張方法を説明します。
テーマ フレームワーク と テーマ パッケージ
テーマ パッケージ とは
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のサブルーチンを指定します。引数として、三つのオブジェクトが渡されます。
- 適用するテーマ エレメント
- テーマ エレメントを含むテーマ全体
- テーマを適用する(多くの場合は作成されたばかりの)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; }
テーマのバージョン管理
テーマ パッケージ と インポータ には、各々二つのバージョン管理設定があります。
- テーマ パッケージ
- 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に最新のバージョンを書くだけで問題ありません。