コードDJ 第7回 – WordPressの擬似cron機構

毎週火曜日、Help me, hackers!に上がったコードを紹介していくコードDJ 第7回。

今、流行の24シーズン1を見ているkomagata a.k.a. DJ(@流行に疎い方)です。

今回紹介するコードはコレ。

任意の期間、ブログが更新されないとメールが飛ぶwordpressのplugin – Help me, hackers!

出題したのは@machida a.k.a. お米嫌い。議論に対していきなりコードで回答を示したのが@terakuma a.k.a. 法務系PHPer。

コード:

[cc lang=”php”]<?php
/*
Plugin Name: Remember The WordPress
Plugin URI: http://github.com/e2esoundcom/Remember-The-WordPress
Description: If you forgot write a new post,this plugin send you E-mail.
Version: 0.2
Author: Yuya Terajima
Author URI: http://www.e2esound.com/
*/

/* When Activate Plugin
==================================================================== */
function rtw_activate() {
$time = time();
$terms = 7; //default terms
$unixtime_per_day = 86400;
$email = get_bloginfo(‘admin_email’);
$subject = “Remember the WordPress!!”;
$message = “Blogの更新が滞っているようです。サイトの更新をお願いします。”;

if(!get_option('rtw_initialized') || get_option('rtw_initialized') !== $time) {
    update_option('rtw_initialized',$time);
}
if(!get_option('rtw_terms')) {
    update_option('rtw_terms',$terms * $unixtime_per_day);
}
if(!get_option('rtw_email')) {
    update_option('rtw_email',$email);
}
if(!get_option('rtw_subject')) {
    update_option('rtw_subject',$subject);
}
if(!get_option('rtw_message')) {
    update_option('rtw_message',$message);
}
wp_schedule_event($time + 86400, 'daily', 'rtw_cron');

}
register_activation_hook(FILE, ‘rtw_activate’);

function get_latest_post_time() {
global $wpdb;
$query = “SELECT post_date FROM “.$wpdb->posts.”

WHERE post_status = ‘publish’

ORDER BY `”.$wpdb->posts.”`.`post_date` DESC LIMIT 0,1″;

$query = $wpdb->prepare($query);

return strtotime($wpdb->get_var($query));

}

function rtw_sendmail()

{

$subject = get_option(‘rtw_subject’);

$mailbody = get_option(‘rtw_message’);

$to_email = get_option(‘rtw_email’);

mb_send_mail($to_email,$subject,$mailbody);

}

function rtw_compare_time(){

$unixtime_per_day = 86400;

$latest = get_latest_post_time();

$terms = intval(get_option(‘rtw_terms’)) + intval($latest);

$time = time();

if(intval($terms) < intval($time)){ rtw_sendmail(); } } add_action(‘rtw_cron’, ‘rtw_compare_time’); /* When New Post or Edited Post. ==================================================================== */ function rtw_new_posted(){ update_option(‘rtw_initialized’,time()); } add_action(‘publish_post’,‘rtw_new_posted’); /* When De-Activate Plugin ==================================================================== */ function rtw_deactivate() { wp_clear_scheduled_hook(‘rtw_cron’); delete_option(‘rtw_initialized’); delete_option(‘rtw_terms’); delete_option(‘rtw_message’); delete_option(‘rtw_subject’); delete_option(‘rtw_email’); } register_deactivation_hook(__FILE__, ‘rtw_deactivate’); /* Admin ==================================================================== */ function rtw_add_admin_menu(){ add_options_page(‘Remember The WordPress’,‘Remember The WP’,‘administrator’,__FILE__,‘rtw_add_admin_page’); } add_action(‘admin_menu’,‘rtw_add_admin_menu’); function rtw_add_admin_page(){ if(isset($_POST[‘posted’]) === FALSE){ $posted = FALSE; }elseif(isset($_POST[‘posted’]) === TRUE){ $posted = TRUE; } $unixtime_per_day = 86400; if($posted) { //Validation if(preg_match(‘/[1-3][0-9]|[1-9]/‘,intval($_POST[‘terms’]) AND intval($_POST[‘terms’]) <= 30)){ update_option(‘rtw_terms’,intval($_POST[‘terms’] * $unixtime_per_day)); update_option(‘rtw_email’,stripslashes($_POST[‘email’])); update_option(‘rtw_subject’,stripslashes($_POST[‘subject’])); update_option(‘rtw_message’,stripslashes($_POST[‘message’])); $rtw_error = FALSE; }else{ $rtw_error = TRUE; } } ?>

<?php
//Admin Page Start
//Updated Message
if($posted === TRUE AND $rtw_error === FALSE) : ?>

設定を保存しました

<?php elseif($posted === TRUE AND $rtw_error === TRUE):?>

アラート発生日数は1-30の間の値を入力して下さい。

<?php endif; ?>

Remember The WordPress Settings

<?php } ?>[/cc]

少々長いがへこたれずに頑張ってみていくことにしよう。(自分自身を鼓舞)

WordPressプラグインの作成方法

前提としてこれはWordPressプラグインなのでその大まかな作り方を紹介しよう。

まず、単体のphpファイルか、もしくは同名のディレクトリにプラグイン用のファイルを作る。

(例:foo_plugin/foo_plugin.php)

プラグインの各種情報は決まったコメントの書き方があるのでそれにしたがってファイル内先頭に書く。これがWordPressのプラグイン管理画面に出てくる情報になる。

一番単純なプラグインとしては、プラグインを管理画面から有効にすると、プラグインのphpファイルがWordPressにincludeされる。よって適当な関数をプラグイン内で定義しておき、テーマの中で使うといったことが可能だ。(モチロン名前はぶつかる可能性がある。プラグイン名をprefixにした関数を作るか、プラグイン名のクラスに閉じ込めることが推奨されている。)

これでWordPressの関数や変数、DBをプラグイン内からでも使うことが出来る。また、プラグイン用にactionやfilterといったフックをかける事ができる。この辺は公式ドキュメントに全関数リファレンスやプラグイン用のフックの説明がちゃんとあるのでPHPが分かれば理解するのは容易だ。(Main Page – WordPress Codex 日本語版

擬似cron

今回のコードを理解する上でもう一つ必要になるのが、wp_schedule_event関数を使った擬似cronの仕組みだ。WordPressにはwp_schedule_event関数でcronのように定期スケジュールを登録することが出来る。こういう処理はcron daemonのように常に起動しているプロセスと連携する必要があり、一見単純なPHPウェブアプリだけでは無理に思えるが、Webからのユーザーリクエストのみをトリガーにcronのようなスケジュール実行を可能にしている。

もちろんWebからのリクエスト頼みなのでアクセスがまったく来なければスケジュールした時間には実行されない擬似的な機能なので厳密な処理には向かない。しかし、一般的なサイトであれば大抵毎分1アクセスぐらいはあるので大体このぐらいの頻度でやって欲しいといった処理なら実用上は問題なさそうだ。

参照:Function Reference/wp schedule event « WordPress Codex

こんないい加減な仕組み使うなんてありえねー!とヤルタイプからは言われそうだが、phpのsession削除は同様の仕組みで行われている。(アクセスが来なければ永久にセッションファイルは消えない)

根本的なこの仕組の是非は兎も角、PHPの流儀に従った実装方法ではあると言える。

参照:PHP: 実行時設定 – Manual

Remenber The WordPress

まず、38行目でregister_activation_hook関数で自分自身のファイルのrtw_activate関数をactivation_hookに登録している。activationとはプラグイン管理画面でそのプラグインを「有効」にしたときのことだ。データベーステーブルを独自に持つようなプラグインでは大抵この場所でテーブルをCREATEしている。(WordPressはORMを提供していないので、各種プラグインのこの場所にはMySQLに特化したSQLが大抵使用されている。WordPressはプラグインエコシステムがキモであるため、コレのせいで他DBへの対応が非常に難しくなっている。)

rtw_activate関数の中でwp_schedule_eventを使ってdailyで実行されるようにrtw_cronを登録している。

あとは、40行目のget_latest_post_time関数で最終投稿日を取得して、管理画面で設定できる「何日更新が無かったらメールを送るか?」という値と比較してmb_send_mailでメールを送っている。

殆どの行数は管理画面用なので長く見えるし大変そうだが、管理画面からプラグインの設定が出来るというのがWordPressユーザーに非常に訴える箇所なので重要だ。

議論にコードで答えた事。(これが結構貴重なんだが)WordPress流儀に則った実装。管理画面まで手を抜かない所。等々、@terakuma a.k.a. 法務系PHPerは素晴らしい。それにRemember The MilkをパクったRemember The WordPressというプラグイン名も素敵だ。

WordPressプラグインで困ったことがあったら@terakuma a.k.a. 法務系PHPerに相談してみたらいいかもしれない!

comments powered by Disqus