[訂正あり][wordpress] cron_request フィルターでwp-cron.phpへのリクエストをカスタマイズする

この記事は公開されてから8年経過しています。現在とは内容が異なる場合がありますのでご注意ください。
最新の記事や関連記事をお探しの方は下の「サイト内検索」で検索してみてください。

訂正: 2016-07-14
add_filter()でフィルターアクション関数を設定するときに、関数が複数の引数を受け取る場合は add_filter の第4引数に受け取る引数の数を指定する必要がありました。

SNS Count Cache という様々なSNSでのシェア数をカウントしてくれるプラグインをインストールしたんですが、いつまでたってもカウントされなかったんです。
たまたま設定を確認したらこんなメッセージが表示されていました。

あなたのサイト上でWP-Cronシステムの呼び出し処理に問題が見つかりました。あなたのサイト上でWP-Cronジョブが動作しない可能性があります。問題は次の通りです。Failed to connect to <サイトドメイン> port 443: connection refused

なんで???

これはある特定の条件が重なった結果なんですが、以下の構成図のような状態になっていると、WordPress 自身がhttpsリクエストに失敗します。

Intra側はプライベートアドレスで名前解決を行っています。
そのため、WordPress のサーバから自分自身への https リクエストを行っても LoadBalancer 経由ではないため、 https 接続ができず失敗します。
WordPress のサイトURLは https://example.com/ といった https でのURLが指定されているためですね。

じゃぁどうするか

内部のWordPress サーバにも SSL ポートの接続を設定すればいいように見えますがめんどくさい(コラ。
かといって、 WP-CLI を使おうにもこれまためんどくさい(マテ。
あとは WordPress サーバは1ホスト1サイトなので、 http://localhost/wp-cron.php とかで呼び出しても大丈夫だろうけど、WordPress のコア部分に手を入れないといけないので、バージョンアップのときにこれまためんどくさい。

cron_request というフィルターがあるので、このフィルターで https:// から http:// にプロトコルを変えちゃえばいいじゃない。

こうしました

ということで、テーマの functions.php に以下のコードを追加します。
$cron_request に含まれる url というキーに wp-cron.php のURLを設定するのですが、この時に site_url() を使っているので、ここの第2引数に http を指定するとサイトのURLの scheme を上書きしてくれて http://example.com/wp-cron.php というURLになります。