準備
まず、PEAR::XML_RPCをインストールします。
PEARが入っていれば、特に問題なくインストールできるかと。
PEARのインストールについては、こちらのエントリなどを参考にしてください。
PEAR::Net_UserAgent_Mobileを使う。
サーバサイドのプログラム
いろいろと拙いところもあると思いますが、晒しておきます。
<?php
/**
* POST MovableType Entry by XML-RPC
*
* @version 0.1.0
* @author is
*/
require_once "XML/RPC.php";
// 文字コード設定
$GLOBALS['XML_RPC_defencoding'] = 'UTF-8';
class PostMovableTypeEntry
{
private static $mtHost;
private static $mtXmlrpcPath;
private static $mtPort;
private static $mtUser;
private static $mtXmlrpcPass;
private static $mtBlogId;
private static $client;
private static $appkey;
private static $username;
private static $passwd;
private static $blogId;
private static $publish;
private static $content;
/**
* factory
*
* @param string $host
* @param string $xmlrpcPath
* @param string $port
* @param string $user
* @param string|not login password $xmlrpcPass
* @param string $blogId
*/
public static function factory($args)
{
self::$mtHost = $args['host'];
self::$mtXmlrpcPath = $args['xmlrpcPath'];
self::$mtPort = $args['port'];
self::$mtUser = $args['user'];
self::$mtXmlrpcPass = $args['xmlrpcPass'];
self::$mtBlogId = $args['blogId'];
}
/**
* initialize
*/
private static function initialize()
{
self::$client = new XML_RPC_client(self::$mtXmlrpcPath, self::$mtHost, self::$mtPort);
self::$appkey = new XML_RPC_Value('', 'string');
self::$username = new XML_RPC_Value(self::$mtUser, 'string');
self::$passwd = new XML_RPC_Value(self::$mtXmlrpcPass, 'string');
self::$publish = new XML_RPC_Value(1, 'boolean');
self::$blogId = new XML_RPC_Value(self::$mtBlogId, 'string');
// タイムゾーン設定
date_default_timezone_set('UTC');
}
/**
* エントリ投稿
* $post = array(
* 'title', // タイトル
* 'description', // 本文
* 'dateCreated', // 公開日時(ISO 8601(UTC):2009-01-01T08:35:04+00:00)
* 'mt_allow_comments', // コメントの許可
* 'mt_allow_pings', // トラックバックの許可
* 'mt_convert_breaks', // 改行設定(0:改行しない / 1:改行する)
* 'mt_text_more', // 追記
* 'mt_excerpt', // 概要
* 'mt_keywords', // キーワード
* 'mt_tb_ping_urls', // 送信したいトラックバック
* 'mt_tags', // タグ
* 'publish', // 公開状態の設定(0:下書き / 1:公開)
* 'categoryId', // カテゴリID
* );
*
* @param array $post
*/
public static function post($post)
{
// initilize
self::initialize();
// デフォルト設定
if(empty($post['mt_allow_comments']) === true) $post['mt_allow_comments'] = 0;
if(empty($post['mt_allow_pings']) === true) $post['mt_allow_pings'] = 0;
if(empty($post['dateCreated']) === true) $post['dateCreated'] = date(DATE_ATOM);
// エントリ設定
self::$content = new XML_RPC_Value(array(
'title' => new XML_RPC_Value($post['title'], 'string'),
'description' => new XML_RPC_Value($post['description'], 'string'),
'dateCreated' => new XML_RPC_Value($post['dateCreated'], 'string'),
'mt_allow_comments' => new XML_RPC_Value($post['mt_allow_comments'], 'int'),
'mt_allow_pings' => new XML_RPC_Value($post['mt_allow_pings'], 'int'),
'mt_convert_breaks' => new XML_RPC_Value($post['entryBody'], 'string'),
'mt_text_more' => new XML_RPC_Value($post['entryMore'], 'string'),
'mt_excerpt' => new XML_RPC_Value($post['mt_excerpt'], 'string'),
'mt_keywords' => new XML_RPC_Value($post['mt_keywords'], 'string'),
'mt_tb_ping_urls' => new XML_RPC_Value($post['mt_tb_ping_urls'], 'string'),
'mt_tags' => new XML_RPC_Value($post['mt_tags'], 'string'),
), 'struct');
self::$publish = new XML_RPC_Value($post['publish'], 'boolean');
$message = new XML_RPC_Message(
'metaWeblog.newPost',
array(self::$blogId, self::$username, self::$passwd, self::$content, self::$publish)
);
// エントリ登録:登録が成功するとエントリーIDが返ってくる
$postId = self::$client->send($message);
// カテゴリ設定
$categoryStruct = new XML_RPC_Value(array(
'categoryId' => new XML_RPC_Value($post['categoryId'], 'string'),
'isPrimary' => new XML_RPC_Value(1, 'boolean')
), 'struct');
$category = new XML_RPC_Value(array($categoryStruct), 'array');
if($postId && empty($post['categoryId']) === false):
$message = new XML_RPC_Message(
'mt.setPostCategories',
array($postId->value(), self::$username, self::$passwd, $category)
);
$result = self::$client->send($message);
endif;
// 再構築
if(self::$publish == 1):
$message = new XML_RPC_Message(
'mt.publishPost',
array($postId->value(), self::$username, self::$passwd)
);
$result = self::$client->send($message);
endif;
return false;
}
}
?>
プログラムの構成については、こちらのコードを参考にさせていただきました。
PHPを使って携帯からMTに記事を投稿する | チバのブログ
また、MovableType3.3でのXML-RPCについてはこちらを参考に。
Movable Type 3.3 マニュアル - XML-RPC API
MovableType で使える XML-RPC API
仕様上、「metaWeblog.newPost」は書かれていないようですが…
まぁ使えるのでそれを使いました。
それからこれも仕様には書かれていませんが、
XMLRPCServer.pmを読んでみた限りではタグも扱えるようなので、
そのあたりも追加しています。
lib/MT/XMLRPCServer.pm(206行目)
if (my $tags = $item->{mt_tags}) {
require MT::Tag;
my $tag_delim = chr($author->entry_prefs->{tag_delim});
my @tags = MT::Tag->split($tag_delim, $tags);
$entry->set_tags(@tags);
}
クライアントプログラム
上のプログラムを利用して投稿します。
クライアントプログラムの例はこんな感じです。
<?php
/**
* Client
*/
require_once './PostMovableTypeEntry.class.php';
PostMovableTypeEntry::factory(array(
'host' => 'www.hoge.com',
'xmlrpcPath' => 'http://www.hoge.com/mt/mt-xmlrpc.cgi',
'port' => '80',
'user' => 'user',
'xmlrpcPass' => 'pass',
'blogId' => '1'
));
PostMovableTypeEntry::post(array(
'title' => 'タイトル',
'description' => '本文',
'dateCreated' => '2009-01-01T08:00:00+00:00',
'mt_allow_comments' => '0',
'mt_allow_pings' => '0',
'mt_convert_breaks' => '1',
'mt_text_more' => '追記',
'mt_excerpt' => '概要',
'mt_keywords' => 'キーワード',
'mt_tb_ping_urls' => '送信するトラックバック',
'mt_tags' => 'test, sample',
'publish' => '1',
'categoryId' => '1',
));
?>
投稿上の注意
上のクライアントプログラムを実行するとエントリが投稿できます。
再構築しているので、ブログにも反映されます…が。
投稿日時(dateCreated)とタグ(mt_tags)には注意が必要です。
投稿日時
入力形式は
ISO 8601形式のUTCと決まっています。
仮にタイムゾーンを設定したとしても、UTCとして解釈されるので注意。
ちなみに現在時刻をISO 8601形式(UTC)で書き出したい場合、
次のように書くと書き出せるようです。
date_default_timezone_set('UTC');
echo date(DATE_ATOM)
また仕様上、指定日投稿というのは出来ないようです。
「mt.setNextScheduledPost」というメソッドも一応考えられてはいるようなのですが、
MT3.3では実装されていないような気がします。
(もし実装されていれば、再構築前にそれをセットするってことでしょうね)
なので、たとえ投稿日時を未来に設定したとしても、
普通に公開されてしまいます。
その辺を上手くやるには、再構築の部分を別処理にするか、
クライアントを動かすタイミングを調整するかということになるかと。
タグ
タグの区切り文字に合わせて入力する文字を変える必要があります。
ホントなら配列で与えて、取得した区切り文字で繋いで渡す方が良いんでしょうが…
面倒だったのでw
多分、デフォルトはカンマだとは思いますが。
というわけで、プログラムからMovableTypeに投稿する手段が準備できました。
さてこっからどう実装しようかな。
追記: 2009/01/10
「指定日投稿は出来ない」と書きましたが…モジュールをよく読むと、
未来の投稿に関するコードがいくつかありますね。
もしかすると、仕様書に書かれていないだけで使えるのかもしれません。
手順は次の通り。
- 指定したいエントリを下書きで登録する
- 登録したエントリを指定日投稿に設定する
また今度試してみます。
※ 上のコードですが…「下書きで投稿できない」など、いくつかバグがあるようです。
※ 検証後、差し替えます。