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)」を選択し、ファイルを指定して「記事のインポート」ボタンをおすことで行われます。
取り込み先は、インポートを実施したウェブサイト/ブログになります。
WordPressのカスタムフィールドと出力データについて
WordPressのWXRデータは、WordPress各サイト毎のダッシュボードの「ツール」>「エクスポート」から出力できます。
なお、「投稿データ」「固定ページ」「メディア」を一括でダウンロードすることも出来ますが、取り込み時にサーバーのタイム・アウトが返される程ファイルが大きくなりがちでしたので、種類ごとに出力したり、期間を区切って出力したほうが良さそうです。
出力された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上では以下のように定義されています。
定義情報に当たる情報のうち、カスタムフィールドの種類などは、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
}
「いつかやるわ」ってことっぽいですが、多分どれだけ待ってもそのままみたいな気がします。
以下その様に思う理由です。
- そもそもWXRでは、カスタムフィールドフィールド名とベースネームが区別されていない
- WXRにはカスタムフィールドのタイプが含まれない
- 別フィールドなのに、同一のカスタムフィールド名のものが作れてしまう
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インテグレーション事業部 へご相談下さい。
経験豊富なスタッフが対応いたします。
コメントを投稿する