movabletype.jp
検索

プラグインによるテーマフレームワークの拡張

プラグイン作者向けの テーマ フレームワークの拡張方法を説明します。

テーマ フレームワーク と テーマ パッケージ

テーマ パッケージ とは

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
      テーマ作成時に、このテーマが古いインポータをロードできない場合は、ロード可能なインポータのバージョンを指定します。
  • インポータ
    • min_schema_version
      インポータ作成時に、このインポータが古いテーマをロードできない場合は、ロード可能なテーマの schema_version を指定します。
    • max_schema_version
      インポータ作成時の最新バージョンを指定します。

最も良いのは、常に後方互換性を保つことです。インポータがすべてのバージョンのテーマ パッケージを読み込めれば、テーマ パッケージの schema_version と、インポータの max_schema_version に最新のバージョンを書くだけで問題ありません。

Updated on 2017-01-17, 09:35 .

関連ページ