WordpressからTwitterへ自動投稿する(予約投稿対応)

プラグイン(Jetpack等)を使っても予約投稿時にTwitterに投稿されない等の問題が出たため自作しました。

# デモ
![post-twitter-min.gif](https://qiita-image-store.s3.amazonaws.com/0/135478/b6b13d2a-5d40-d4d8-71c3-6ca803b44f46.gif)


# 手順

## 1.  Twitter APIの使用準備
Twitter APIを使うため下記URLにアクセスしてアプリケーションを作成してください。
[https://apps.twitter.com](https://apps.twitter.com)

アプリケーションの作成方法は下記記事を参照。
[Twitter REST APIの使い方｜SYNCER](https://syncer.jp/Web/API/Twitter/REST_API/)

作成後、consumer_key、consumer_secret、access_token、access_token_secretの4つをどこかに保存しておいてください。あとで使います。


## 2.  ライブラリの導入
下記URLからライブラリをダウンロード。
[https://github.com/abraham/twitteroauth](https://github.com/abraham/twitteroauth)
フォルダ名をtwitteroauth-masterからtwitteroauthにリネームしてテーマファイル内にぶち込んでください。

# 3. コード
下記コードをfunctions.phpにコピペしてお使いください。
やっていることはsave_postでTwitterに投稿する内容と投稿するかしないかのデータをwp_postmetaに保存しています。
そしてtransition_post_statusでTwitterへ投稿するファイル「post-twitter.php」を実行しています。
post-twitter.phpではsave_postで保存した内容を元にTwitterに投稿しています。

全てsave_postに書いても良いと思ったのですが、save_postだと予約投稿時に$_POSTデータ(post_idなど)が受け取れなかったので分けました。

```php:functions.php

// ここではTwitterの投稿だけを行う
add_action('transition_post_status', 'post_twitter', 10, 3);
function post_twitter($new_status, $old_status, $post) {
	if ($new_status == 'publish') {
        // コマンドでTwitterに投稿するファイルを実行(引数にpost_idを渡している)
		$command = "/usr/bin/php ".__DIR__."/post-twitter.php $post->ID > /dev/null &";
		exec($command);
	}
}

// 管理画面が開いたときに実行
add_action('admin_menu', 'add_post_twitter_fields');
// カスタムフィールドを投稿画面に追加
function add_post_twitter_fields() {
	// フィールドを追加
	add_meta_box('post_twitter', 'Twitter', 'post_twitter_field', 'post', 'side', 'high');
}

// 投稿画面に表示するフォームのHTMLソース
function post_twitter_field() {
	global $post;

   $twitter_body = get_post_meta($post->ID, 'twitter_body', true);
	$checked = get_post_meta($post->ID, 'whether_to_post', true);
	if ($checked == 'checked') {
		$checked = 'checked="'.$checked.'""';
	}

   echo '<div style="margin-bottom:5px;"><label><input type="checkbox" name="whether_to_post" id="whether_to_post" value="checked" '.$checked.'>Twitterに投稿する</label></div>';
   echo '<textarea name="twitter_body" id="twitter_body" cols="50" rows="5" style="width: 100%;" readonly>'.$twitter_body.'</textarea>';
	echo <<< EOF
<script>
(function($) {
	// ロード時にチェックが入っていれば編集可に、入っていなかったら可に。
	if($("#whether_to_post").prop('checked')) {
		$("#twitter_body").prop('readonly', false);
		$('#twitter_body').css({'background-color':'','color':'', 'pointer-events':''});
	} else {
		$("#twitter_body").prop('readonly', true);
		$('#twitter_body').css({'background-color':'#fff','color':'#ccc', 'pointer-events':'none'});
	}

	// タイトルを自動入力(フォーカスが外れた時に反映)
	$('#title').change(function() {
		if ($('#twitter_body').val() == '') {
			var title = $('input[name="post_title"]').val();
			$('#twitter_body').val(title + "\\n");
		}
	});

	// チェックを入れると編集可能に、外すと不可に。
	$('input[name="whether_to_post"]').change(function() {
		if($("#whether_to_post").prop('checked')) {
			$("#twitter_body").prop('readonly', false);
			$('#twitter_body').css({'background-color':'','color':'', 'pointer-events':''});
		} else {
			$("#twitter_body").prop('readonly', true);
			$('#twitter_body').css({'background-color':'#fff','color':'#ccc', 'pointer-events':'none'});
		}
	});

})(jQuery);
</script>
EOF;

}

// 下書き・公開・更新ボタンが押されたときに実行される(ゴミ箱に移動したときも呼ばれるかも？)
add_action('save_post', 'save_post_twitter', 10, 3);
// 設定したカスタムフィールドの値をDBに書き込むコード
function save_post_twitter($post_id, $post) {
	if (isset($_POST['whether_to_post']) || isset($_POST['twitter_body'])) {
		$post_type = $post->post_type;
		if ($post_type == 'post') {
		   $whether_to_post = $_POST['whether_to_post'] == '' ? '': $_POST['whether_to_post'];
		   update_post_meta($post_id, 'whether_to_post', $whether_to_post);

			$twitter_body = $_POST['twitter_body'] == '' ? '': $_POST['twitter_body'];
			update_post_meta($post_id, 'twitter_body', $twitter_body);
		}
	}
}
```

Twitterに投稿するファイル。
post-twitter.phpをテーマディレクトリに作成し、
下記コードをコピペしてください。(必要箇所は適宜変更)

```php:post-twitter.php
require __DIR__. '/../../../wp-load.php';
require_once __DIR__."/twitteroauth/autoload.php";
use Abraham\TwitterOAuth\TwitterOAuth;

class Twitter {
   private static $consumer_key = "hogehoge";
   private static $consumer_secret = "hogehoge";
   private static $access_token = "hogehoge";
   private static $access_token_secret = "hogehoge";

   public function post($post) {

      // Twitterへ投稿
      $connection = new TwitterOAuth(self::$consumer_key, self::$consumer_secret, self::$access_token, self::$access_token_secret);
      $result = $connection->post("statuses/update", ["status" => $post]);

      if ($connection->getLastHttpCode() == 200) {
          echo "succes";
          return;
      } else {
         // 投稿に失敗したらエラー内容をメールで送る
         mb_language("Japanese");
         mb_internal_encoding("UTF-8");

         $to      = 'to@example.com';
         $subject = 'Twitter Debug';
         $message = "Twitterへの投稿に失敗しました。\n$post\n\nエラーコード：".$result->errors[0]->code."\nエラーメッセージ：".$result->errors[0]->message;
         $headers = 'From: from@example.com' . "\r\n";

         mb_send_mail($to, $subject, $message, $headers);
      }
   }
}
// functions.phpに書いたtransition_post_statusは、
// save_postより先に実行されるので、念のためここで2秒遅らせてる。
sleep(2);

// post_id取得
$post_id = isset($argv[1]) ? $argv[1] : null;

$whether_to_post = get_post_meta($post_id, 'whether_to_post', true);

// checkedじゃなかったら処理中断
if ($whether_to_post != 'checked') return;

$twitter = new Twitter();

// 投稿内容を取得
$post = get_post_meta($post_id, 'twitter_body', true);
// post_url取得
$post_url = get_permalink($post_id);
if(strpos($post_url,'http://') !== false){
	$post_url = str_replace('http://', 'https://', $post_url);
}
// 投稿内容とpost_urlを結合
$post .= "\n".$post_url;
$twitter->post($post);

```


同じツイートを再度投稿しようとすると失敗して下記のようなメールが届きます。
![Twitter-error.jpg](https://qiita-image-store.s3.amazonaws.com/0/135478/5e621f0f-3344-70c7-0226-26d834451258.jpeg)