WordPressのブログタイトル・URLを1時間ごとにループで順番にツイートするSQL

アドベントカレンダー初投稿です。よろしくお願いいたします。
WordPressのブログタイトル・URLを1時間ごとにループで順番にツイートするシステムを作成してみました。
私はwordpress初心者ですので、wordpress関数や、プラグインとか使わずにやる方法でやっています。
また自動ツイートはwp_cronではなく、crontabで行なっています。

# 仕様など
1. 1時間に一回、ブログ記事のタイトルとURLをツイートしていく。
2. 公開日の古い順番にツイートしていく。全てツイートしたら最も古い投稿に戻ってまた順番にツイートする。
3. 新しいブログ記事が公開されたら、直近のツイートは最新記事をツイートし、その後は元の順番に戻ってツイートしていく。
4. 新しいブログ記事が2つ以上だった場合は、そのうちの古い投稿からツイートしていく。
5. ツイートしたブログ記事は回数、ツイート日時を全て保存しておく。

また、今回作成したものは自分のSQLの勉強のために作ったものです。

### cron設定
1時間おきに設定

```
0 */1 * * * /usr/local/bin/php /var/www/html/tweet.php
```

### ツイートしたID、日時を保存しておくテーブルを作成

```sql
CREATE TABLE IF NOT EXISTS `wp_tweet` (
  `wp_posts_id` bigint(20) unsigned NOT NULL,
  `tweet_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`wp_posts_id`,`tweet_date`)
) DEFAULT CHARSET=utf8mb4;
```

### 現在のツイート数を見れるVIEWを作成

```sql
CREATE OR REPLACE VIEW `wp_tweet_cnt` AS
SELECT wp_posts_id,
       MAX(tweet_date) tweet_date,
       COUNT(*) cnt
FROM wp_tweet
GROUP BY wp_posts_id;

CREATE OR REPLACE VIEW `wp_posts_tweet` AS
SELECT a.id,
       a.post_date,
       a.post_title,
       a.guid,
       a.post_status,
       a.post_type,
       b.tweet_date,
       b.cnt
FROM wp_posts a
LEFT JOIN wp_tweet_cnt b
ON a.id = b.wp_posts_id
WHERE a.post_status = 'publish' -- 公開済のみを選択
AND a.post_type = 'post'; -- ブログ記事のみを選択
```

### SQL作成
以下のようにすることで現在ある記事を順番にループしてツイートすることができました。
処理の流れとしては、対象のidをwp_tweetにインサート→wp_tweetの最新データをツイートするという感じです。
新しいブログ記事が公開されたら、次のツイートは元の順番に戻ってツイートするというのがかなりややこしい、、

```php:tweet.php
<?php
require_once __DIR__.'/vendor/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;

try {
    $pdo = new PDO('mysql:dbname=wp_tests;host=localhost;charset=utf8','root','password');

    $stmt = $pdo->exec(
       "INSERT INTO wp_tweet(
           wp_posts_id
        )
        SELECT a.id
        FROM   wp_posts_tweet a
        JOIN (
            SELECT tmp.*
                  ,CASE WHEN new_flg = 1
                        AND  min_cnt < last_cnt_tmp
                        THEN last_cnt_tmp
                        ELSE last_cnt    -- 前回ツイートが新規投稿だった場合、次のツイートは元の順番に戻さないといけないため、
                   END  last_tweet_cnt   -- 合計ツイート数が1 より大きいもの中で直近を前回ツイート数とする
            FROM (
                SELECT (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt IS NULL) new_post_cnt
                      ,(SELECT MIN(cnt) FROM wp_posts_tweet WHERE tweet_date <= (SELECT tweet_date FROM wp_posts_tweet WHERE cnt > 1 ORDER BY tweet_date DESC LIMIT 1)) min_cnt
                      ,(SELECT cnt FROM wp_posts_tweet ORDER BY tweet_date DESC LIMIT 1) last_cnt
                      ,(SELECT cnt FROM wp_posts_tweet WHERE cnt > 1 ORDER BY tweet_date DESC LIMIT 1) last_cnt_tmp
                      ,CASE WHEN (SELECT cnt FROM wp_posts_tweet ORDER BY tweet_date DESC LIMIT 1) = 1
                            AND  (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt > 1) > 0
                            THEN 1
                       END  new_flg  -- 前回ツイートが新規投稿だったかどうか判定するフラグ
            ) tmp
        ) b
        WHERE IFNULL(a.cnt,0) = 
                   -- 条件  :まだツイートしていない記事が1つ以上ある場合
                   -- true :合計ツイート数0のものをツイートする
              CASE WHEN b.new_post_cnt > 0
                   THEN 0
                   -- 条件  :「直近にツイートしたidの合計ツイート数-1」と同じ合計ツイート数の記事が1つ以上ある場合
                   -- true :「直近にツイートしたidの合計ツイート数-1」と同じの合計ツイート数の記事を次にツイートする 
                   WHEN (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt = b.last_tweet_cnt - 1) > 0
                   THEN b.last_tweet_cnt - 1
                   -- 条件  :「直近にツイートしたidの合計ツイート数-1」より小さい合計ツイート数の記事が1つ以上ある場合
                   -- true :「「直近にツイートしたidの合計ツイート数-1」より小さい合計ツイート数」の記事の中で最大の合計ツイート数の記事を次にツイートする
                   -- false:合計ツイート数が最大のものをツイートする
                   WHEN (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt < b.last_tweet_cnt - 1) > 0
                   THEN (SELECT MAX(cnt) FROM wp_posts_tweet WHERE cnt < b.last_tweet_cnt - 1)
                   ELSE (SELECT MAX(cnt) FROM wp_posts_tweet)
              END
        ORDER BY post_date
        LIMIT 1"
   );

    $stmt = $pdo->query("SELECT CONCAT(post_title,'\r\n',guid) post 
                         FROM wp_posts_tweet 
                         WHERE tweet_date = (SELECT MAX(tweet_date) FROM wp_posts_tweet)");
                         
    $res = $stmt->fetch(PDO::FETCH_ASSOC);
    $paramater['status'] = $res['post'];

    $connection = new TwitterOAuth(
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx'
    );
    $connection->post(
        'statuses/update',
        $paramater
    );

} catch (PDOException $e) {

    exit($e->getMessage()); 

}
```

### 動作

---

最初にブログ記事が3つある場合、古いものから順にツイート(データを保存)していき、全てツイートしたら、最初のidに戻る。
![Cuy7ctupkx.gif](https://qiita-image-store.s3.amazonaws.com/0/142910/3866d069-da8f-b5ce-e91b-634f0edd3edc.gif)

---

さらに、新しい記事が2つ追加される。
この状態ですと、まず新しい記事を2つツイートした後に、元の順番に戻るので、id:182が新しい記事の次にツイートされます。

![WhLxHT9vjt.gif](https://qiita-image-store.s3.amazonaws.com/0/142910/d56e1f3e-74f1-22eb-fbf4-ce6eaaea63d2.gif)

もっと色々なテスト条件でテストした方がいいですが、とりあえず仕様通りの動きにできたようです。
人によって、全然違う書き方をするような内容だと思いますので、やってみると結構面白いんじゃないかなと思います。

最後まで読んでいただきありがとうございました。