WordPressへ外部サービスから下書き投稿したpostオブジェクトを操作する方法

2019/11/15

WordPress

t f B! P L
ワードプレスにはXMLRPCから使えるAPIがあり、外部サービス・ソフトウェアから記事を投稿したりできます(他にも色々できますが省略)。

記事投稿の場合は、postオブジェクトが生成され、DBに書き込まれるわけですが、外部サービスのインターフェイスによっては、postの細かいところを自由に設定できない場合があります。

postオブジェクト

postの細かい設定は、postオブジェクトのメンバ変数で設定できるような項目です。

https://wpdocs.osdn.jp/%E3%82%AF%E3%83%A9%E3%82%B9%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/WP_Post

具体的には、post_author(投稿ユーザー名)、post_name(スラッグ)、post_date(投稿時刻)、post_status(下書き、公開、予約投稿)などですね。


アクションフック

これをいじいじしたいときは、ワードプレスのアクションフックを利用します。
アクションフックで「下書きの新規投稿」があったときに、そのpostオブジェクトを操作するよう、お馴染みのfunctions.phpに書くことで実現可能です。

動作確認してますが、もし使う場合は要バックアップ。

function draft_editor( $ID, $post ) {
 $post->post_author = "3"; // 投稿用ユーザーID
 $post->post_name = date("YmdHi"); // スラッグ
 $post->edit_date = true; // 時刻編集の場合必須
 $post->post_date = date('Y-m-d H:i:s' , strtotime('+1 day')); // +1日後
 $post->post_status = "future"; // 公開予約
 
 remove_action('draft_post', 'draft_editor', 10, 2);
 wp_update_post( $post );
 add_action('draft_post', 'draft_editor', 10, 2);
 
 return false;
}
add_action( 'draft_post', 'draft_editor', 10, 2 );

draft_postというアクションに自作関数をひっかけます。
draft_postというのは、その名の通り下書き(draft)の新規投稿があったケース場合ですね。

コードに貼っているのものは私がよく編集する項目です(内容は書き換えてます)。

post_author

セキュリティのため、外部サービスからXMLRPCを叩くユーザーと、ブログに投稿するユーザー(フロントに出すユーザー)を分けることができます。
ユーザーIDで指定する必要があり、これはユーザー名とは異なります(通常は整数の連番になっています)。

post_name

これはslugです。パーマリンク設定によっては、URLの一部として表示されます。
標準のパーマリンク設定機能で実現できないほど、複雑な独自ルールを使いたい場合はここで設定します。
上記のコードの通りだと下書き投稿のアクセスがあったYYYYMMDDHHmmになります。

edit_date/post_date

日付をいじる場合はedit_dateをtrueにする。
post_dateはサーバータイムに依存するので、期待動作になるよう要確認。

remove_action/wp_update_post/add_action

この3行は地味に大事です。
まず、アクションフックなので、下書きの投稿後(=DB書き込み後)に、そのpostオブジェクト変数をもらってごにょごにょしているわけです。
つまり、ここでpostオブジェクトを書き換えただけでは、すでにDBに入っているpostは変更されません。
その証拠に呼び出された側のdraft_editor関数は何もreturnしていません。
パイプ処理みたく後ろに何か流してるわけではないのです。

なので、WPの組み込み関数であるwp_update_post関数で更新する必要があります。
しかし、ここで更新すると、また「下書き(draft)が新規投稿された」という扱いになるらしく、アクションフックの無限ループになってしまいます。

これを防ぐため、updateする前に、一旦アクションフックを解除(remove)して、そのあと再登録(add)します。
公式サイトにも載っている伝統の方法です。

上記例では、post_statusをfutureにしているので無限ループは発生しませんが、念のため伝統にしたがっています。

今日のベストプラクティス

外部サービス用ユーザーとフロント表示用のユーザを分けたかっただけなんだ。

ラベル

QooQ