PHPでXML-RPCを使ってWordPressに画像を含めた記事を投稿する方法 〜 その2

前回BlogIDを取るところまでやったので、その続きです。

画像をWordPressへアップロードする

XML-RPC APIで、ローカルにある画像をサーバへ送信します。
とりあえず送信してURL取るところまでのコードです。

$imageFile = 'hoge.png';
$imagePath = '/images/' . $imageFile;
$image = file_get_contents($imagePath);
$extension = pathinfo($imagePath, PATHINFO_EXTENSION);
$file = array(
    'bits' => new XML_RPC_Value($image, 'base64'),
    'name' => new XML_RPC_Value($imageFile, 'string'),
    'type' => new XML_RPC_Value('image/' .$extension, 'string'),
);
$wpFile = new XML_RPC_Value($file, 'struct');
// ファイルのアップロード
$message = new XML_RPC_Message(
    'metaWeblog.newMediaObject',
    array($blogId, $wpUserName, $wpPassword, $wpFile)
);
$wpResult = $cli->send($message);
if (!$wpResult) exit('Could not connect to the server.');
if( $wpResult->faultCode() ) exit($wpResult->faultString());
$resp = XML_RPC_decode($wpResult->value());
$uploadImageUrl = $resp['url']; //アップロードしたファイルのPath

ではコードを見ていきます。

【構造体データを作る】


XML_RPC_Message
でサーバへデータを渡すために、XML_RPC_Valueで構造体データを作ります。
blogger.getUsersBlogsでは配列でデータを渡しましたが、今回は連想配列になっていますね。
これは、XML_RPCの構造体データを作る場合は、連想配列にしなくてはいけないようです。
作成した連想配列を更に「new XML_RPC_Value($file, ‘struct’)」として構造体データにしています。
また、bitsデータの第2引数にbase64を取っていますが、これを指定するとBase64エンコードが透過的におこなわれます。

$file = array(
    'name' => new XML_RPC_Value($imageFile, 'string'),
    'bits' => new XML_RPC_Value($image, 'base64'),
    'type' => new XML_RPC_Value('image/' .$extension, 'string'),
);
$wpFile = new XML_RPC_Value($file, 'struct');

それと上記補足ですが、サーバへアップロードするだけなら、typeは必要無いですが、これが無い場合メディアの一覧にサムネイルが表示され無かったので追加しています。

【画像をアップロード(転送)】

BlogIDを取得した時と同様、XML_RPC_Messageでリクエストを作り、XML_RPC_clientsendメソッドで送信します。
また、画像の転送にはmetaWeblogAPInewMediaObjectメソッドを使います。

$message = new XML_RPC_Message(
    'metaWeblog.newMediaObject',
    array($blogId, $wpUserName, $wpPassword, $wpFile)
);
$wpResult = $cli->send($message);

【アップロードした画像のURLを取得】

画像を転送したら、これもBlogID取得時と同様に、レスポンスをXML_RPC_decodeで変換し、URLを取得します。

$resp = XML_RPC_decode($wpResult->value());
$uploadImageUrl = $resp['url']; //アップロードしたファイルのPath

WordPressへ記事を投稿する

最後に先ほどアップロードした画像を新しい記事に載せて投稿します。
以下コードとなります。

$title = 'XML-RPC テスト'; //タイトルを設定
$categories = array( //複数カテゴリを設定
    new XML_RPC_Value('カテゴリ1', 'string'),
    new XML_RPC_Value('カテゴリ2', 'string')
);
$description = <<< EOF
<p>Test Post</p>
<img src="{$uploadImageUrl}">
EOF;
$wpContent = new XML_RPC_Value(
    array(
        'title' => new XML_RPC_Value($title, 'string'),
        'categories' => new XML_RPC_Value($categories, 'array'),
        'description' => new XML_RPC_Value($description, 'string'),
        'dateCreated' => new XML_RPC_Value(time(), 'dateTime.iso8601')
    ),
    'struct'
);
$publish = new XML_RPC_Value(0, 'boolean'); // 0だと下書き状態でPOST
// 新しい記事の投稿
$wpMessage = new XML_RPC_Message('metaWeblog.newPost',
    array($blogId, $wpUserName, $wpPassword, $wpContent, $publish)
);
$wpResult = $cli->send($wpMessage);
if (!$wpResult) exit('Could not connect to the server.');
if ($wpResult->faultCode()) exit($wpResult->faultString());
$postId = XML_RPC_decode($wpResult->value()); // 必要であれば戻り値のPostIDを保存

コードを見ていきます。

【投稿データを作る】

記事に必要なデータを、XML_RPC_Valueで作ります。
今回作成する記事はタイトル、本文、カテゴリ、投稿日時のみですが他にも、descriptionmt_keywords(タグ)、custom_fields(カスタムフィールド)、wp_slug(スラッグ)などを設定できるようです。

$wpContent = new XML_RPC_Value(
    array(
        'title' =&gt; new XML_RPC_Value($title, 'string'),
        'categories' =&gt; new XML_RPC_Value($categories, 'array'),
        'description' =&gt; new XML_RPC_Value($description, 'string'),
        'dateCreated' =&gt; new XML_RPC_Value(time(), 'dateTime.iso8601')
    ),
    'struct'
);

【記事を下書き状態で投稿】

記事データを作ったので、次は投稿を行うのですが、このまま投稿すると公開状態で投稿されます。
なので、投稿を一度確認したいので、下書き状態で保存することにします。
XML_RPC_Messageで投稿データを配列で渡していますが、配列データの5番目の配列($publish)がステータスとなっています。
これは「$publish = new XML_RPC_Value(0, ‘boolean’);」でfaluse(0)をXML_RPCデータでセットしています。

$publish = new XML_RPC_Value(0, 'boolean'); // 0だと下書き状態でPOST
// 新しい記事の投稿
$wpMessage = new XML_RPC_Message('metaWeblog.newPost',
    array($blogId, $wpUserName, $wpPassword, $wpContent, $publish)
);
$wpResult = $cli->send($wpMessage);

【投稿したPostIDを取得】

sendメソッドで投稿完了なのですが、ローカルデータと投稿したデータを紐付けたい場合があるので、一応PostIDを取っておきます。

$postId = XML_RPC_decode($wpResult->value()); // 必要であれば戻り値のPostIDを保存

簡単にWordPressへ投稿できましたが、そもそものXML-RPCへの理解が乏しかったので、PEARライブラリのドキュメントを良く読まないとなーといった感じでした。

PHPでXML-RPCを使ってWordPressに画像を含めた記事を投稿する方法 〜 その1

WordPressに外部サーバなどから投稿できないかな?と思い、「そういえばXML-RPC APIがあったなぁ」なんと事を思い出したので、少し調べて見ました。
XML-RPCの仕様については下記参照
XML-RPC 仕様書
今回はPHPのPEARライブラリを使ってみます。
まずはPEARのXML_RPCパッケージをインストールします。

pear install XML_RPC

詳しい使い方はXML_RPCのドキュメントを見てください。

BlogIDを取得する

では実際にコードを書いていきたいと思います。
まず記事を投稿する前に、投稿したいWordpressのBlogIDを取得します。

<?php
require_once('XML/RPC.php');
$hostName = 'wp.example.com';
$xmlrpcPath = '/xmlrpc.php';
$appKey = '任意文字列(空で良い)';
$user = 'ユーザー名';
$passwd ='パスワード';
$wpAppKey = new XML_RPC_Value($appKey, 'string');
$wpUserName = new XML_RPC_Value( $user, 'string');
$wpPassword = new XML_RPC_Value( $passwd, 'string');
$message = new XML_RPC_Message(
    'blogger.getUsersBlogs',
    array($wpAppKey, $wpUserName, $wpPassword)
);
$cli = new XML_RPC_client($xmlrpcPath, $hostName, 80);
$wpResult = $cli->send($message);
// 戻り値0はI/Oエラー
if (!$wpResult) exit('I/O Error. '.$cli->errstring);
// faultCode(),戻り値0以外は失敗
if ($wpResult->faultCode()) exit($wpResult->faultString());
$blogs = XML_RPC_decode($wpResult->value());
$blogId = new XML_RPC_Value($blogs[0]['blogid'], 'string');

コード内容を説明しておきますね、若干コードが前後します。

【サーバに送信するリクエストの作成】

まずWordPressに接続するため、XML_RPC_Messageインスタンスを作ります。

$message = new XML_RPC_Message(
    'blogger.getUsersBlogs',
    array($wpAppKey, $wpUserName, $wpPassword)
);

XML_RPC_Messageはサーバに起動したいメソッドとパラメータを送信し、戻り値としてXML_RPC_Responseを受け取ります。
今はBlogIDが欲しいのでBlogger APIgetUsersBlogsメソッドを設定します。
第2引数には、接続に必要なユーザー情報を配列で渡していますが、これは予めXML_RPC_Valueメソッドで作成します。

$wpAppKey = new XML_RPC_Value($appKey, 'string');
$wpUserName = new XML_RPC_Value( $user, 'string');
$wpPassword = new XML_RPC_Value( $passwd, 'string');

先頭のappkeyBlogger APIで利用するもののようですが、WordPressでは必要無いので任意の文字列または空で良いみたいです。
XML_RPC_Valueの第2引数にはXML_RPCの型を入れます。

【サーバへリクエストを送信する】

先ほど作成したXML_RPC_Messageインスタンスを、XML_RPC_clientsendメソッドに渡して、サーバへ送信します。

$wpResult = $cli->send($message);

【エラー確認】

sendメソッドは戻り値としてXML_RPC_Responseを返しますが、戻り値0の場合はI/Oエラーです。

// 戻り値0はI/Oエラー
if (!$wpResult) exit('I/O Error. '.$cli->errstring);

次に、faultCodeメソッドで判定します。0以外の戻り値は失敗となります。

// faultCode(),戻り値0以外は失敗
if ($wpResult->faultCode()) exit($wpResult->faultString());

【取得したデータをPHPデータ型に変換】

valueメソッドでサーバから返されたXML_RPCオブジェクトを受け取り、さらにXML_RPC_decodeでPHPのネイティブデータ型に変換します。
逆に、PHPのネイティブデータ型をXML_RPCオブジェクト型に変換する場合は、XML_RPC_encodeを使用します。

$blogs = XML_RPC_decode($wpResult->value());
$blogId = new XML_RPC_Value($blogs[0]['blogid'], 'string');

これで変換されたデータからBlogIDを取得できますが、このあとの投稿時に利用するので、XML_RPC_Valueでカプセル化しておきます。
ちょっと前置きが長くなったので、続きはその2に書きます。