新「WordPress Events and News」ウィジェットが興味深い

説明

4.8のベータ版ですぐに新機能とわかるのが管理者ダッシュボードの新「WordPress Events and News」ウィジェット。ユーザーが指定した地域近隣で開催されるイベント情報を表示してくれるウィジェットで、この中のフォームがちょっと興味深かった。なおこの記事はWordPress 4.8 beta-2をもとにしており、以降のバージョンで変更される可能性があることをあらかじめ断っておく。

地域を指定するフォームにnonceがない

「WordPress Events and News」ウィジェット

「WordPress Events and News」ウィジェットの「地域登録フォーム」は通常は非表示になっており、「鉛筆」アイコンをクリックすることで表示と非表示を切り替えできる。この地域登録フォームのHTMLは次のようになっている(便宜上、空白文字を除外)。

<form class="community-events-form" aria-hidden="false" action="http://localhost/wp-admin/admin-ajax.php" method="post">
<label for="community-events-location">City:</label>
<input id="community-events-location" class="regular-text" type="text" name="community-events-location" placeholder="Cincinnati">
<input type="submit" name="community-events-submit" id="community-events-submit" class="button" value="送信">
<button class="community-events-cancel button-link" type="button" aria-expanded="true">キャンセル</button>
<span class="spinner"></span>
</form>

とてもシンプルな内容だが、「クイックドラフト」ウィジェットなどにある「クロスサイトリクエストフォージェリ(CSRF)」対策でおなじみの「nonce」設定が見当たらない。「nonce」設定をどこで行っているのか気になったので、リクエストの流れを追ってみた。

AJAXのリクエストハンドラを探す

4.8で追加されたAJAX関連を見ていくと、/wp-admin/includes/ajax-actions.phpにwp_ajax_get_community_events関数が追加されている。この関数の冒頭部分では次のように check_ajax_referer関数が呼び出されており、nonce値のチェックは行われていることがわかる。

check_ajax_referer( 'community_events' );

ここでチェックしているnonce値は動的に生成するものなので、「WordPress Events and News」ウィジェットのあるページに出力されていると予想して出力されたHTMLソースを見てみると、フッター部分のJavaScriptに次のような記述が見つかりました(そのままだと見難いので整形)。

var communityEventsData = {
	"nonce":"67f3177442",
	"cache":"",
	"l10n":{
		"enter_closest_city":"Enter your closest city to find nearby events.",
		"error_occurred_please_try_again":"An error occurred. Please try again.",
		"attend_event_near_generic":"Attend an upcoming event near you.",
		"could_not_locate_city":"We couldn’t locate %s. Please try another nearby city. For example: Kansas City; Springfield; Portland.",
		"city_updated":"City updated. Listing events near %s."
		}
	};

この変数の定義がどこで出力されているかというと、'admin_print_scripts-index.php'アクションとして実行されるwp_localize_community_events関数で wp_localize_script関数を使っていました。communityEventsData変数のconce値は、「地域登録フォーム」で「送信」ボタンが押された場合に動作する/wp-admin/js/dashboard.jsのgetEventsメソッドにおいてAJAXリクエスト時に使用されている。

requestParams          = requestParams || {};
requestParams._wpnonce = communityEventsData.nonce;
requestParams.timezone = window.Intl ? window.Intl.DateTimeFormat().resolvedOptions().timeZone : '';

initiatedBy = requestParams.location ? 'user' : 'app';

$spinner.addClass( 'is-active' );

wp.ajax.post( 'get-community-events', requestParams )

wp.ajax.postメソッドの第1パラメータで指定している'get-community-events'がWordPressのAJAXリクエストのactionパラメータ、第2パラメータが実際に送信されるパラメータ(この場合は$_POSTに格納される内容)のようだ。

これからのAJAXリクエストフォーム

JavaScriptのプログラム要素はファイルに記載し、リクエスト時の状況に応じて変動するデータをwp_localize_script関数で動的に出力するこの方法は個人的には好ましい。プラグイン開発においてフォームからAJAXリクエストする方法として参考にしたいと思う。


最終更新 : 2018年05月27日 10:43


お勧め

get_cat_name(2018年5月27日 更新)

string get_cat_name( int $cat_id )
カテゴリーIDからカテゴリー名を取得する。

wp_kses_no_null(2012年4月25日 更新)

string wp_kses_no_null( string $string )
文字列からNULL文字を取り除く。

__(2018年5月27日 更新)

string __( string $text [ , string $domain = 'default' ] )
現在のロケールに応じた翻訳テキストを取得する。

username_exists(2018年5月27日 更新)

mixed username_exists( string $username )
ユーザ名が登録されているか確認する。

get_approved_comments(2011年6月19日 更新)

array get_approved_comments( int $post_id )
投稿記事の公開許諾されているコメント情報を取得する。