BLOG

Go to top


Movable Type 6 の Data API で再構築する

August 10, 2013 2:23 AM

概要

定期的に再構築を回す、という手段は、例えばランキングを反映したいとか RSS から取り込んで表示したいといったような積極的な目的から、何かしらの問題を回避するための消極的な目的まで含め、比較的便利なソリューションのひとつです。

Movable Type 6 では、Data API によって再構築を行う手段が提供されています。覚えておけば余計なプラグインを入れる必要もありませんね。

リクエストの形式

端的には以下のような形式でリクエストを送ります。MT::App::DataAPI::core_endpoints でハンドラを確認すると、「/path/to/mt/lib/MT/DataAPI/Endpoint/Publish.pm」の MT::DataAPI::Endpoint::Publish::entries が受け手の処理になるようですね。

ここでは特に触れませんが、ヘッダ情報に認証のための accessToken を含める必要があります。


http://example.com/mt/mt-data-api.cgi/v1/publish/entries?ids=1,2,3,4,5,6,7,8,9,10

パラメータ ids には再構築したいエントリー ID をカンマ区切りで指定します。再構築させるエントリーが決まっていればそれを指定しましょう。そうでない場合は事前にエントリーのリストを取得するリクエストを送り、ID を取り出して連結したものを指定しましょう。なお、指定する ID はブログ記事でもウェブページのものでもかまいません。

この ids パラメータは必須なので、指定しないと何もしてくれません。ただ、Movable Type は前後のエントリーも合わせて再構築するので、厳密にはすべてのエントリーの ID を付与する必要があるわけではないといえばないのですが、とはいえ間引く方が手間がかかるので、全部指定してしまう方が楽でしょう。また、エントリーの再構築に合わせてインデックステンプレートも再構築されます。このあたりの動きは Data API でなくとも同じですね。特定のインデックステンプレートだけを再構築するためのエンドポイントはないようですが、同じブログのどれかひとつのエントリーを再構築させておくことでカバーできそうです。

戻り値

指定した ID のエントリー全ての再構築が終わったか、そうでないかで戻り値が異なります。再構築が終わった場合は以下です。


$VAR1 = {
          'status' => 'Complete',
          'restIds' => '',
          'startTime' => '2013-08-10T01:13:55+09:00'
        };

再構築が終わっていない場合は以下のようになります。


$VAR1 = {
          'status' => 'Rebuilding',
          'restIds' => '6,7,8,9,10',
          'startTime' => '2013-08-10T01:13:55+09:00'
        };

このとき、レスポンスヘッダには「X-MT-Next-Phase-URL」という情報が含まれています。Complete になるまで「X-MT-Next-Phase-URL」にアクセスし、再構築を繰り返します。Perl でやるなら以下のような感じです。


&rebuilding( '/publish/entries?ids=1,2,3,4,5,6,7,8,9,10' );

sub rebuilding {
    my ( $path ) = @_;
    my $endpoint = $api_url . $path;
    my $request = HTTP::Request->new( 'GET', $endpoint );
    $request->header( 'X-MT-Authorization' => "MTAuth accessToken=$accessToken" );
    my $ua = MT->new_ua;
    my $res = $ua->request( $request );
    my $content = MT::Util::from_json( $res->content );
    print Dumper( $content );
    if ( my $next_url = $res->header( 'X-MT-Next-Phase-URL' ) ) {
        &rebuilding( $next_url );
    }
}

なお、MT::DataAPI::Endpoint::Publish::entries を見ると、再構築処理は MT::App::CMS::rebuild_these に渡されていることがわかります。再構築処理実行前のコールバック pre_build が実行されますし、環境変数 EntriesPerRebuild の値によって一回あたりの再構築件数を制御することもできます。

たとえば、ID が 1 のブログについて、デフォルトである 10 件ごとにエントリーを取得しつつ再構築を回すのであれば、以下のように行うことができます。もちろんエントリー取得の際の limit を増やして一回で取得してしまってもよいでしょう。


my @rebuit_ids = ();
rebuild_all_entries();

sub rebuild_all_entries {
    my ( $offset ) = @_;
    $offset ||= 0;
    my $endpoint = $api_url . "/sites/$blog_id/entries?fields=id,title&offset=$offset"; # specific fields
    my $request = HTTP::Request->new( 'GET', $endpoint );
    $request->header( 'X-MT-Authorization' => "MTAuth accessToken=$accessToken" );
    my $ua = MT->new_ua;
    my $res = $ua->request( $request );
    unless ( $res->is_success ) {
        if ( $res->code == 500 ) {
            my $content = MT::Util::from_json( $res->content );
            my $message = $content->{ error }->{ message };
            $message =~ s/\\x{([0-9a-z]+)}/chr(hex($1))/ge;
            die $message; # invalid request, and so on...
        } else {
            die $res->as_string;
        }
    }
    my $content = MT::Util::from_json( $res->content );
    my $total_results = $content->{ totalResults };
    my $items = $content->{ items } || [];
    my @entry_ids = map { $_->{ id } } @$items;
    push( @rebuit_ids, @entry_ids );

    print "rebuit num: " . scalar @rebuit_ids . "\n";
    print "total_results: " . $total_results . "\n";
    &rebuilding( '/publish/entries?ids=' . join( ',', @entry_ids ) );
    
    unless ( $total_results == scalar @rebuit_ids ) {
        &rebuild_all_entries( $offset + 10 );
    }
}

sub rebuilding {
    my ( $path ) = @_;
    my $endpoint = $api_url . $path;
    my $request = HTTP::Request->new( 'GET', $endpoint );
    $request->header( 'X-MT-Authorization' => "MTAuth accessToken=$accessToken" );
    my $ua = MT->new_ua;
    my $res = $ua->request( $request );
    my $content = MT::Util::from_json( $res->content );
    print Dumper( $content );
    if ( my $next_url = $res->header( 'X-MT-Next-Phase-URL' ) ) {
        &rebuilding( $next_url );
    }
}

Comments


Contact me

Copyright © 2005 - 2017 okayama All rights reserved.