WordCamp Yokohama 公式サイトの作り方 – プラグイン編 (2)

さて、前日に引き続いて WordCamp Yokohama 公式サイトに導入したプラグインの解説。
今回の公式サイト構築にあたり、2つほど専用プラグインを新規で作りました。
時間が無い中で作ったんで汎用的なモノでは無いですが、WordCamp Yokohama が終了したら、改良してリリースしようとは思っています。
気長に待ってくださいね。

で、今回作ったプラグインは以下の2つ

  • Custom Register – 独自のサインアップ画面、ログイン画面をページに実装
    WordCamp Yokohama に参加登録するには WordPress で作成された公式サイトにユーザ登録・ログインしてもらい、アンケートに答えてもらう必要があります。
    ここでサインアップ画面やログイン画面が、デフォルトの WordPress のモノだと芸が無いので、カッコイイサインアップ画面・ログイン画面を実装するためのプラグインです。
  • Custom Profile – プロフィール登録画面の拡張
    WordCamp Yokohama 公式サイトでは、WordPress のプロフィール登録画面で参加登録を行います。
    この画面に、参加登録や簡単なアンケート機能を追加するためのプラグインです。

まずは、Custom Register プラグインについて解説しましょう。

デフォルトの WordPress ログイン画面は簡素

options generalWordPress では、一般設定の「メンバーシップ」欄で「誰でもユーザー登録ができるようにする」にチェックを入れると、ユーザー名・メールアドレスを入力することで、誰でもサイトにユーザー登録をすることができるようになります。
WordCamp Yokohama では、この機能を使って公式サイトにユーザー登録してもらい、参加登録してもらうことにしましょう。

registerデフォルトの WordPress のサインアップ画面は簡素なモノです。
しかし、先日開催された WordCamp Fukuoka 2010 では、サイトデザインにあわせたカッコイイサインアップ画面を用意していました。
Fukuokaの公式サイトを構築した三好さんに聞いてみたら、どうやら WordPress MU を導入していたため、特に意識しなくてもサインアップ画面はサイトデザインにあわせて作れるとのこと。
しかし、今回の公式サイトは WordPress 2.9.2 で行くことが決定していたため、サインアップ画面・ログイン画面をサイトデザインにあわせた独自のフォームが表示できるプラグインを作成することにしました。

通常ページにログイン画面を埋め込むことができれば、簡単にデザインが統一できるんじゃね?

custom registerこのプラグインでは [register_form][login_form] という二つのショートコードを用意し、通常ページにAjax化された登録フォーム・ログインフォームを埋め込めるようにしました。
もちろん、JavaScript が切られている場合でも正常に動作するように設計します。
ログイン画面のデザインを変更するプラグインは幾つかあるのですが、ここまで大胆にログイン画面のデザインを変更できるプラグインは、おそらく他には無いでしょう。

通常のページなので登録画面・ログイン画面に任意のURLを割り当てることも可能です。
今回は http://yokohama2010.wordcamp.jp/register/signup/ , http://yokohama2010.wordcamp.jp/register/login/ というURLを割り当てました。
また、ページ内に任意の説明文を追加することも可能です。
動作が気になる方は、アカウントを取得して参加登録してみてください。

ショートコードプラグインを実装してみよう

以下に、ログインフォームを表示するために作成したショートコードのソースをさらしておきますね。

//******************************************************************************
// ログインフォームをページに表示するためのショートコード [login_form]
//******************************************************************************
function show_login_form(){
	global $user_login;

	// アクションフック login_form を動作させておきます。
	ob_start();
	do_action('login_form');
	$action_login_form = ob_get_clean();

	// ログインフォームを編集
	$action_url  = site_url('wp-login.php', 'login_post');
	$profile_url = site_url('/wp-admin/profile.php');
	$label_user  = __('Username');
	$label_pwd   = __('Password');
	$value_user  = esc_attr($user_login);
	$msg_rememberme = esc_attr(__('Remember Me'));
	$msg_login      = esc_attr(__('Log In'));

	$retval = <<<EOT
					<div class="login">
						<form name="loginform" id="loginform" action="$action_url" method="post">
							<p>
								<label>$label_user<br />
								<input type="text" name="log" id="user_login" class="input" value="$value_user" size="20" tabindex="10" /></label>
							</p>
							<p>
								<label>$label_pwd<br />
								<input type="password" name="pwd" id="user_pass" class="input" value="" size="20" tabindex="20" /></label>
							</p>
							$action_login_form
							<p class="forgetmenot"">
								<label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90" style="width:1em;" /> $msg_rememberme</label>
							</p>
							<br class="clear" />
							<p class="submit">
								<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary" value="$msg_login" tabindex="100" />
								<input type="hidden" name="redirect_to" value="$profile_url" />
								<input type="hidden" name="testcookie" value="1" />
							</p>
						</form>
					</div>
EOT;

	// footer 部に JavaScript を追加
	add_action('wp_footer', 'login_js');

	// 編集したログインフォームを返す
	return $retval;
}
add_shortcode("login_form", "show_login_form");

//******************************************************************************
// ログイン用の JavaScript を footer 部に書き出すための関数
//******************************************************************************
function login_js(){
	$profile_url = site_url('/wp-admin/profile.php');
	$plugin_directory = str_replace(ABSPATH, site_url('/'), dirname(__FILE__));

	// ログイン用の JavaScript
	echo <<<EOT
<script src="$plugin_directory/js/jquery.blockUI.min.js"></script>
<script type="text/javascript">
try{document.getElementById('user_login').focus();}catch(e){}

jQuery(function(){
	var messages = {
		'error':   '<p id="login_error"><strong>エラー</strong>: ログインに失敗しました。しばらくしてから、再度ログインしてみてください。</p>' ,
		'loading': '<div style="margin:0 auto;padding:0 1em 0;"><p style="margin:1.5em 0;white-space: nowrap;font-size:12px;"><img src="$plugin_directory/img/ajax-loader.gif" alt="loading" style="margin-right:.25em;float:left;" />送信中</p></div>'
		};

	// success
	var successCallback = function(responseText) {
		var response = jQuery(responseText.replace(/[\\r\\n\\t]/g, '').replace(/^.*<body&#91;^>]*>(.*?)<\\/body>.*$/i, '$1'));

		jQuery('#loginform').unblock();
		if ( jQuery('.login p.message').length <= 0 ) {
			jQuery('.login').append('<p class="message"></p>');
		} else {
			jQuery('.login p.message').fadeOut('fast',function(){jQuery(this).html('');});
		}

		var err_msg = jQuery('#login_error', response).css({'display':'none'});
		if ( err_msg.length > 0 ) {
			jQuery('.login p.message').append(err_msg);
			err_msg.fadeIn('fast');
		} else if ( jQuery('#loginform', response).length <= 0 || responseText == '' ) {
			location.href = '$profile_url';
		}
	};

	// error
	var errorCallback = function(httpRequest, status, e) {
		jQuery('#loginform').unblock();
		if ( jQuery('.login p.message').length <= 0 ) {
			jQuery('.login').append('<p class="message"></p>');
		} else {
			jQuery('.login p.message').fadeOut('fast',function(){jQuery(this).html('');});
		}

		var err_msg = jQuery(messages.error).css({'display':'none'});
		jQuery('.login p.message').append(err_msg);
		err_msg.fadeIn('fast');
	};

	jQuery('#loginform').unbind('submit').submit(function(){
		jQuery(this).block({
			message: messages.loading ,
			css: {border:'1px solid #8C8C8C', font:'normal 12px Arial'} ,
			overlayCSS: {backgroundColor:'#FFF', opacity:'0.6'}
		})

		if ( jQuery('.login p.message').length > 0 ) {
			jQuery('.login p.message').fadeOut('fast',function(){jQuery(this).remove();});
		}

		var param = jQuery('input, textarea', jQuery(this)).serialize();
		jQuery.ajax({
			type:    "POST" ,
			cache:   false ,
			url:     this.action ,
			data:    param ,
			success: successCallback ,
			error:   errorCallback ,
		});

		return false;
	});
});
</script>
EOT;
}

1〜52行目で、[login_form] ショートコードを実装しています。
54行目以降はログインボタンをクリックされた際、jQuery を使用してログイン動作を行うための JavaScript を、WordPress の footer 部に埋め込むためのコードです。
ショートコードを実装している部分の47行目で add_action('wp_footer', 'login_js'); しているため、ショートコードが埋め込まれたページにしか、この JavaScript はセットされません。
※JavaScript 部は jQuery で処理してるので wp_enqueue_script('jquery'); などとして、jQuery をロードしておく必要があります。

ついでに登録メールもカスタマイズしてみよう

サイトに登録した際、送られてくるメールは「ログインURL」と「ログインアカウント」、「仮パスワード」が記述されただけの簡素なモノです。
せっかくイベントに登録してもらったんだから、このメールの文面も変更したいですよね。
それを変更するには、Pluggable Functions として登録されている wp_new_user_notification() 関数をプラグイン内で再定義してあげましょう。

これもソースをさらしておきますね。

//******************************************************************************
// ユーザー登録メールの文面を変更
//******************************************************************************
if ( !function_exists('wp_new_user_notification') ) {

function wp_new_user_notification($user_id, $plaintext_pass = '') {
	$user = new WP_User($user_id);

	$user_login = stripslashes($user->user_login);
	$user_email = stripslashes($user->user_email);
	
	// 管理者に送る新規ユーザ登録されたよメールの編集
	$blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);

	$subject  = sprintf(__('[%s] New User Registration'), $blogname);

	$message  = sprintf(__('New user registration on your blog %s:'), $blogname) . "\r\n\r\n";
	$message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
	$message .= sprintf(__('E-mail: %s'), $user_email) . "\r\n";

	// 管理者に新規ユーザ登録されたよメールを送信
	@wp_mail(get_option('admin_email'), $subject, $message);

	// 何らかの理由でパスワードが作成されなかった場合は、新規ユーザにはメールを送信しない
	if ( empty($plaintext_pass) )
		return;

	// 新規登録ユーザに送るウェルカムメールを編集
	$subject  = 'WordCamp Yokohama ログイン情報';

	// ログインURLは、通常の wp-login.php では無いため独自設定
	$login_url = site_url('/register/login/');

	$message  = <<<EOT
WordCamp Yokohama 2010への参加登録ありがとうございます。

引き続き、お送りしたユーザー名とパスワードでログインして、
懇親会への参加希望、プロフィールの登録をお願いいたします。

ログインURL: $login_url
ユーザー名: $user_login
初期パスワード: $plaintext_pass

ログイン後、プロフィール登録画面での簡単なアンケート回答にも
ご協力いただければ幸いです。

不明な点がございましたら、下記までご連絡ください。
───────────────────────────────────
 WordPressでつながろう!
 WordCamp Yokohama 2010 5月29日(土)開催
 WordCamp横浜実行委員会
 Web site: http://yokohama2010.wordcamp.jp/
 E-mail : hogehoge@example.com
───────────────────────────────────
EOT;

	$headers  = array(
		'From: WordCamp横浜実行委員会 <hogehoge@example.com>' ,
		);

	// 新規登録ユーザにウェルカムメールを送信
	wp_mail($user_email, $subject, $message, $headers);
}

}

※ ソース中に記載されているメールアドレスは架空のものです。

Pluggable Functions を再定義するプラグインを作成する時の注意点としては、 if ( !function_exists('再定義したい Pluggable Function 名') ) { } で括ってあげましょう。
これを忘れると、関数の二重定義エラーが発生してプラグインを有効化することができません。

結局、このプラグインは「ショートコードAPI」「フィルタフック」「Pluggable Functions」と言う WordPress が用意してくれているプラグイン用APIをフルに活用して完成しました。
WordPress が提供している様々なプラグイン用APIを活用すれば、コアソースを修正することなく色々なことができてしまいます。
スゴイですね。

このプラグインは、時間が無い中で作ったので、ハードコードしているところもかなり有ります。
その辺を修正して管理画面を付けたら、公式プラグインディレクトリで公開しますね。

WordCamp Yokohama 公式サイトの作り方 – プラグイン編 (2)」への2件のフィードバック

  1. ピンバック: WordCamp Yokohama 2010 に行ってきました : dogmap.jp

  2. ピンバック: 祝!7周年のWordPress!「WordCamp Yokohama 2010」イベントレポート | 本質思考道場

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください