PowerCMS™
2025年1月1日購入分よりライセンスの価格を改定いたします。
[ブログ] PowerCMS 6 でのアップデートまとめ を追加しました。
[よくあるご質問] システムログに「タスクを実行するために必要なロックを獲得できませんでした」というログが残っている を追加しました。
[よくあるご質問] 特定のシステムログに絞って確認できますか? を追加しました。

PowerCMS ブログ

ホーム > PowerCMS ブログ > プラグイン > WordPressの記事をMovable Type(PowerCMS)にインポートする(カスタムフィ…

2016年11月08日

WordPressの記事をMovable Type(PowerCMS)にインポートする(カスタムフィールド対応)

弊社に持ち込まれる案件で、既存 WordPress サイトからの移行ニーズは、一定数あって何度か作業を行っています。
今まで対応して来た案件は、記事部分のみのデータ移行だったのですが、今回カスタムフィールドを複数持つWordPressからの移行だったため、Movable Type 既存の WXRImporter プラグインがどの様にカスタムフィールドを扱うかについて動作を確認してみました。

WXRImporterの動作

WXRImporter は以前から Movable Type の機能(プラグイン)として提供されていますが、今回のようなニーズがなければ、環境作成直後に無効化してしまうプラグインだと思います。

このプラグインは、WordPressから出力された WordPress eXtended RSS (WXR)を取り込み可能で、以下の3種類のデータに対応しているようです。

  • WordPressの投稿データはMTの記事として取り込まれます。
  • WordPressの固定ページはMTのウェブページとして取り込まれます。
  • WordPressのメディアはMTのアイテムとして取り込まれます。

インポートは各ウェブサイト/ブログの「ツール」>「記事のインポート」画面で、インポート元「WordPress eXtended RSS (WXR)」を選択し、ファイルを指定して「記事のインポート」ボタンをおすことで行われます。
取り込み先は、インポートを実施したウェブサイト/ブログになります。
WXRのインポート

WordPressのカスタムフィールドと出力データについて

WordPressのWXRデータは、WordPress各サイト毎のダッシュボードの「ツール」>「エクスポート」から出力できます。
WXRのエクスポート
なお、「投稿データ」「固定ページ」「メディア」を一括でダウンロードすることも出来ますが、取り込み時にサーバーのタイム・アウトが返される程ファイルが大きくなりがちでしたので、種類ごとに出力したり、期間を区切って出力したほうが良さそうです。
出力されたXMLデータは、RSS2.0のフォーマットになっています。

試しにそのまま Movable Type に取り込むと、対応した記事やウェブページなどが作成されます。

ファイルの中身は一般的なRSS2.0フォーマットと変わらず、各データはitemを1データとしており、wp:プレフィックスでカスタム項目を定義しているようです。
もっとも記載されている「xmlns:wp="http://wordpress.org/export/1.2/"」に実ページは存在せず、定義を参照することは出来ないようですが。

<item>
    <title>東北地方太平洋沖地震の被害に対する支援について</title>
    <link>http://www.hogefuga.jp/blog/10/</link>
    <pubDate>Tue, 22 Mar 2011 08:36:13 +0000</pubDate>
    <dc:creator><![CDATA[admin]]></dc:creator>
    <guid isPermaLink="false">http://www.hogefuga.jp/?p=10</guid>
    <description></description>
    <content:encoded><![CDATA[]]></content:encoded>
    <excerpt:encoded><![CDATA[]]></excerpt:encoded>
    <wp:post_id>10</wp:post_id>
    <wp:post_date><![CDATA[2011-03-22 17:36:13]]></wp:post_date>
    <wp:post_date_gmt><![CDATA[2011-03-22 08:36:13]]></wp:post_date_gmt>
    <wp:comment_status><![CDATA[open]]></wp:comment_status>
    <wp:ping_status><![CDATA[open]]></wp:ping_status>
    <wp:post_name><![CDATA[%e6%9d%b1%e5%8c%97%e5%9c%b0%e6%96%b9%e5%a4%aa%e5%b9%b3%e6%b4%8b%e6%b2%96%e5%9c%b0%e9%9c%87%e3%81%ae%e8%a2%ab%e5%ae%b3%e3%81%ab%e5%af%be%e3%81%99%e3%82%8b%e6%94%af%e6%8f%b4%e3%81%ab%e3%81%a4%e3%81%84]]></wp:post_name>
    <wp:status><![CDATA[publish]]></wp:status>
    <wp:post_parent>0</wp:post_parent>
    <wp:menu_order>0</wp:menu_order>
    <wp:post_type><![CDATA[post]]></wp:post_type>
    <wp:post_password><![CDATA[]]></wp:post_password>
    <wp:is_sticky>0</wp:is_sticky>
    <category domain="category" nicename="%e6%9c%aa%e5%88%86%e9%a1%9e"><![CDATA[未分類]]></category>
    <wp:postmeta>
        <wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
        <wp:meta_value><![CDATA[4]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key><![CDATA[day]]></wp:meta_key>
        <wp:meta_value><![CDATA[2011/03/22]]></wp:meta_value>
    </wp:postmeta>
    <wp:postmeta>
        <wp:meta_key><![CDATA[target]]></wp:meta_key>
        <wp:meta_value><![CDATA[blank]]></wp:meta_value>
    </wp:postmeta>
</item>

上記コード最後の方に有る「<wp:postmeta>」内の「<wp:meta_key>」と「<wp:meta_key>」の組み合わせのうち、最後の2つがカスタムフィールドのデータになります。
WordPress上では以下のように定義されています。
WordPressでのカスタムフィールド設定
定義情報に当たる情報のうち、カスタムフィールドの種類などは、WXR に出力されないようです。また「[」と「]」に囲まれたデータの識別部分が「wp:meta_key」としてWXRに出力されるわけですが、 Movable Type のカスタムフィールド・ベースネームの様に使える文字が限定されてはおらず、日本語で出力されるケースも存在するようです。

インポート時に記事等のデータは取り込まれるのですが、そのままではカスタムフィールドは反映されませんでした。コードを追いかけて見ると、プラグイン内でカスタムフィールドの読み込みまでは行われているようです。

plugins/WXRImporter/lib/WXRImporter/WXRHandler.pm

    elsif ( 'wp_postmeta' eq $name_element ) {
        $self->_setup_metadata($data);
    }

上記から呼び出される、_setup_metadata を見ると読み込んでセットするところまでは行われています。

plugins/WXRImporter/lib/WXRImporter/WXRHandler.pm

sub _setup_metadata {
    my $self = shift;
    my $data = shift;

    my $cb   = $self->{callback};
    my $blog = $self->{blog};

    my $meta = {};
    my $current_key;
    my $current_value;
    while ( my $hash = pop @{ $self->{'bucket'} } ) {
        last if 'wp_postmeta' eq $hash;
        next if 'HASH' ne ref $hash;
        my @hash_array = %$hash;
        my $key        = $hash_array[0];
        my $value      = $hash_array[1];
        if ( 'wp_meta_key' eq $key ) {
            $current_key = $value;
        }
        elsif ( 'wp_meta_value' eq $key ) {
            $current_value = $value;
        }
        if ( $current_key && $current_value ) {
            $meta->{$current_key} = $current_value;
            $current_key = $current_value = undef;
        }
    }
    push @{ $self->{'bucket'} }, { 'wp_postmeta' => $meta };
}

このセットされている値をそのまま使って保存すれば、カスタムフィールドの保存が行われるはずですが、実際はそうなってはいないようです。
記事データの取り込みしている箇所を探してみると、カスタムフィールドについての処理する分岐でハッシュにデータを保存するだけで、処理自体をスキップしていました。

plugins/WXRImporter/lib/WXRImporter/WXRHandler.pm

        elsif ( 'wp_postmeta' eq $key ) {
            for my $meta_key ( keys %$value ) {
                $meta_hash{$meta_key} = $value->{$meta_key};
            }

            # TODO: how we should handle metadata is to be decided later
        }

「いつかやるわ」ってことっぽいですが、多分どれだけ待ってもそのままみたいな気がします。
以下その様に思う理由です。

  1. そもそもWXRでは、カスタムフィールドフィールド名とベースネームが区別されていない
  2. WXRにはカスタムフィールドのタイプが含まれない
  3. 別フィールドなのに、同一のカスタムフィールド名のものが作れてしまう

1. は、自動でカスタムフィールドを作る場合に、そのままベースネームとして利用できない可能性が高い。
2. は、どのタイプのカスタムフィールドを作成すればいいかの情報がない。
3. については、WordPressの機能としては便利なのでしょうが、一括で取り込むことを考えると同名で上書きになり、面倒なことが起こりそうです。
上記のようなことを考えると、あくまでも個人的な感想ですが、WXRのインポート時に自動で適切なカスタムフィールドを作るようにすることは難しいだろうと思います。

カスタムフィールドを Movable Type に取り込むには

今回は汎用的な処理ではなく案件固有の対応で済み、データ自体は読み込まれているので、これを保存する処理さえ追加すれば、カスタムフィールドにも対応できるのではないかと思い、以下の方針でコードを書き足してみました。

  • カスタムフィールドは、「wp:meta_key」の値をそのままベースネームにして事前に作成する
  • カスタムフィールドのタイプは、元データを見て、テキストかテキスト複数行とする
  • 取り込むベースネームをハードコードで限定する

その上で、次のようなコードを書き加えて、記事追加時にカスタムフィールドが保存されるようにしました。

plugins/WXRImporter/lib/WXRImporter/WXRHandler.pm

        elsif ( 'wp_postmeta' eq $key ) {
            for my $meta_key ( keys %$value ) {
                $meta_hash{$meta_key} = $value->{$meta_key};
#CustomField
                next if $meta_key =~ /^_/;
                my $field = 'field.' . $meta_key;
                my $meta_value = $value->{$meta_key};
                if ( $meta_key eq 'day' ) {
                    $meta_value =~ s{/+}{}g;
                    $field = 'field.e_displaydate';
                    $post->$field( $meta_value . '000000' );
                } elsif ( $meta_key =~ /^(?:link|target)$/ ) {
                    $post->$field( $meta_value );
                }
#/CustomField
            }

            # TODO: how we should handle metadata is to be decided later
        }

日付(ベースネーム e_displaydate)についての処理は、分岐して加工した上でカスタムフィールドに保存しています。
上記で取り込み自体は行えましたので、フィールドの処理部分を汎用化する事が出来れば、汎用のプラグインとすることもできそうです。

こちらは、あくまでも処理を限定した対応で、テスト的に意味合いで書いてみたものなので、すべての動作を保証するものではありません

なお、WordPressで大人気、大抵の環境に入っている All In One SEO Pack などプラグイン情報も、同じく「wp:postmeta」に書き出されるようなので、このデータの取り込みも可能でした。(「wp:meta_key」が「_aioseop_title」「_aioseop_keywords」「_aioseop_description」のデータ)

全般的なCMSの載せ替えに関して

WordPressを含む他のCMSからのデータ移行がある場合、PowerCMSには幾つかの対処方法があります。

  • 元CMSからMovable Type形式のエクスポートデータが出力可能な場合には、Movable Type標準機能としてのインポート
  • 元CMS側でCSV形式に加工した出力ファイルの、CSVインポート
  • 元CMSから出力されたHTMLをパースしての、HTML インポート(動的CMSなのでHTMLファイルが存在しないというケースでも、wgetなどのツールでローカルにファイルとして保存してからならば取り込めます)

また移行作業に関して、製品に対する理解不足により見通しが立てられない場合や、移行作業自体を依頼したいなど、お困りのことがありましたら、様々な移行作業を経験している弊社 Webインテグレーション事業部 へご相談下さい。

経験豊富なスタッフが対応いたします。


カテゴリー
その他
プラグイン
投稿者
小野崎@アルファサード

Recent Entries