ワードプレスが動くとき、どんなphpが動いているか8:wp-login.php:前半部分

2010 11/25

ここまでは、インストールにまつわるPHPファイル群を見てきましたが、ここからは普段動くときのファイルに入ります。

更新時にはいつも動くものです。
またログインしているユーザに限定して記事を公開したい時にも使えるところです。

最初のコメント

/**
 * WordPress User Page
 *
 * Handles authentication, registering, resetting passwords, forgot password,
 * and other user handling.
 */

ワードプレスの持ち主のためのページ。

認証、登録、パスワードリセット、パスワードを忘れてしまった時の処理、その他のユーザ操作。

環境設定

/** Make sure that the WordPress bootstrap has run before continuing. */
require( dirname(__FILE__) . '/wp-load.php' );

wp-load.phpが動いているはずだけど、動いてなかったら動かそう。
(wp-load.phpは、ワードプレスが動くための諸々のファイルを読み込む処理をします。)

SSLの場合は、転送。

// Redirect to https login if forced to use SSL
if ( force_ssl_admin() && !is_ssl() ) {
	if ( 0 === strpos($_SERVER['REQUEST_URI'], 'http') ) {
		wp_redirect(preg_replace('|^http://|', 'https://', $_SERVER['REQUEST_URI']));
		exit();
	} else {
		wp_redirect('https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
		exit();
	}
}

ここで使われているいろんな関数

force_ssl_admin()</dt>

管理者ページのリクエストをSSLのみに制限にする
is_ssl()
リクエストがSSLかどうか調べる

最初のif文は、「管理者ページがSSLに限定されていて、現在のリクエストがSSLじゃない場合」

strpos()
strpos(文字列1, 文字列2)で、文字列1の中で文字列2が最初に現れる場所を見つける。返り値は一なので、0===としているのは、ゼロ番目だったらつまり最初の文字列だったら、の意味。
関数じゃないけど$_SERVER[‘REQUEST_URI’]
ブラウザとサーバがやりとりしている情報が、連想配列で格納されているようだ。ここでは、今のURIくらいに思っておく
wp_redirect()
リダイレクト。wp_redirect(‘http://www.example.com’, 301);みたいな感じで、リダイレクトのステータスも指定できる。
preg_replace()
正規表現を使って検索したり置換したり。preg_replace(検索して置換したい文字列, これに置換するよ文字列, 検索範囲)なので、ここでは、今いるURIからhttpを検索してhttpsに置換する、の意味。

とにかく、http://をhttps://にすればいいとのこと。

ログインヘッダーを出力&フックを挿入する、というコメント

/**
 * Outputs the header for the login page.
 *
 * @uses do_action() Calls the 'login_head' for outputting HTML in the Log In
 *		header.
 * @uses apply_filters() Calls 'login_headerurl' for the top login link.
 * @uses apply_filters() Calls 'login_headertitle' for the top login title.
 * @uses apply_filters() Calls 'login_message' on the message to display in the
 *		header.
 * @uses $error The error global, which is checked for displaying errors.
 *
 * @param string $title Optional. WordPress Log In Page title to display in
 *		<title/> element.
 * @param string $message Optional. Message to display in header.
 * @param WP_Error $wp_error Optional. WordPress Error Object
 */

ここから先で、ログインページのヘッダーを出力する関数を定義するんだけど、その合間あいまでアクションフック、フィルターを仕掛けておきますよ、とコメントで教えてくれてます。

login_header()関数を定義する

function login_header($title = 'Log In', $message = '', $wp_error = '') {
	global $error, $is_iphone, $interim_login, $current_site;

	// Don't index any of these forms
	add_filter( 'pre_option_blog_public', '__return_zero' );
	add_action( 'login_head', 'noindex' );

	if ( empty($wp_error) )
		$wp_error = new WP_Error();

	// Shake it!
	$shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password' );
	$shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );

	if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) )
		add_action( 'login_head', 'wp_shake_js', 12 );

	?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
<head>
	<title><?php bloginfo('name'); ?> &rsaquo; <?php echo $title; ?></title>
	<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<?php
	wp_admin_css( 'login', true );
	wp_admin_css( 'colors-fresh', true );

	if ( $is_iphone ) { ?>
	<meta name="viewport" content="width=320; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;" />
	<style type="text/css" media="screen">
	form { margin-left: 0px; }
	#login { margin-top: 20px; }
	</style>
<?php
	} elseif ( isset($interim_login) && $interim_login ) { ?>
	<style type="text/css" media="all">
	.login #login { margin: 20px auto; }
	</style>
<?php
	}

	do_action('login_head'); ?>
</head>
<body class="login">
<?php   if ( !is_multisite() ) { ?>
<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', 'http://wordpress.org/'); ?>" title="<?php echo apply_filters('login_headertitle', __('Powered by WordPress')); ?>"><?php bloginfo('name'); ?></a></h1>
<?php   } else { ?>
<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', network_home_url() ); ?>" title="<?php echo apply_filters('login_headertitle', $current_site->site_name ); ?>"><span class="hide"><?php bloginfo('name'); ?></span></a></h1>
<?php   }

	$message = apply_filters('login_message', $message);
	if ( !empty( $message ) ) echo $message . "¥n";

	// Incase a plugin uses $error rather than the $errors object
	if ( !empty( $error ) ) {
		$wp_error->add('error', $error);
		unset($error);
	}

	if ( $wp_error->get_error_code() ) {
		$errors = '';
		$messages = '';
		foreach ( $wp_error->get_error_codes() as $code ) {
			$severity = $wp_error->get_error_data($code);
			foreach ( $wp_error->get_error_messages($code) as $error ) {
				if ( 'message' == $severity )
					$messages .= '	' . $error . "<br />¥n";
				else
					$errors .= '	' . $error . "<br />¥n";
			}
		}
		if ( !empty($errors) )
			echo '<div id="login_error">' . apply_filters('login_errors', $errors) . "</div>¥n";
		if ( !empty($messages) )
			echo '<p class="message">' . apply_filters('login_messages', $messages) . "</p>¥n";
	}
} // End of login_header()

長いので、以下分割して読む。

グローバル宣言

global $error, $is_iphone, $interim_login, $current_site;

よそで値が代入されていたり、クラスになっている?変数を使うらしい。

検索?

	// Don't index any of these forms
	add_filter( 'pre_option_blog_public', '__return_zero' );
	add_action( 'login_head', 'noindex' );

よく分からないけど、多分、このページを検索結果にインデックスさせないようにしてる。

エラーインスタンスの作成

	if ( empty($wp_error) )
		$wp_error = new WP_Error();

WP_Error()は、エラーとそのエラーメッセージを保持したりしてくれるクラスで、その場に応じてエラーを出力したりしたい時に使います。

なので、ここで使われている new はWP_Error()というクラスのインスタンスを生成しますよ、という意味で、今後 $wp_error が使われるときには、このインスタンスが代入されていることになります。
オブジェクト指向的な何かのようです。

ログイン失敗の場合

	// Shake it!
	$shake_error_codes = array( 'empty_password', 'empty_email', 'invalid_email', 'invalidcombo', 'empty_username', 'invalid_username', 'incorrect_password' );
	$shake_error_codes = apply_filters( 'shake_error_codes', $shake_error_codes );

	if ( $shake_error_codes && $wp_error->get_error_code() && in_array( $wp_error->get_error_code(), $shake_error_codes ) )
		add_action( 'login_head', 'wp_shake_js', 12 );

ここでの Shake は、WP3.0から導入されたログインに失敗したらフォームがブルブルする効果のことだと思います。
$shake_error_codesで定義されたパスワードがないなどのエラーの場合、wp_shake_jsが動きます。

HTMLソースの出力(</head>まで)

	?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
<head>
	<title><?php bloginfo('name'); ?> &rsaquo; <?php echo $title; ?></title>
	<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<?php
	wp_admin_css( 'login', true );
	wp_admin_css( 'colors-fresh', true );

	if ( $is_iphone ) { ?>
	<meta name="viewport" content="width=320; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;" />
	<style type="text/css" media="screen">
	form { margin-left: 0px; }
	#login { margin-top: 20px; }
	</style>
<?php
	} elseif ( isset($interim_login) && $interim_login ) { ?>
	<style type="text/css" media="all">
	.login #login { margin: 20px auto; }
	</style>
<?php
	}

	do_action('login_head'); ?>
</head>

普通にHTMLソースが書かれていますが、Change Log-In page’s style < Creating Admin Themesに書かれているように、wp_admin_css()関数でwp-login.php専用のcssを読み込んでいます。wp_admin_css()には、プラグインを作成して、読み込み先を変更できるようになっています。

iPhoneの場合のmetaタグとcss、暫定(interim)ログイン時のcssが指定され、login_headフックが発行されます。

マルチサイト場合分け

<body class="login">
<?php   if ( !is_multisite() ) { ?>
<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', 'http://wordpress.org/'); ?>" title="<?php echo apply_filters('login_headertitle', __('Powered by WordPress')); ?>"><?php bloginfo('name'); ?></a></h1>
<?php   } else { ?>
<div id="login"><h1><a href="<?php echo apply_filters('login_headerurl', network_home_url() ); ?>" title="<?php echo apply_filters('login_headertitle', $current_site->site_name ); ?>"><span class="hide"><?php bloginfo('name'); ?></span></a></h1>
<?php   }

WP3から導入されたマルチサイトの場合で場合分け。

メッセージ出力

	$message = apply_filters('login_message', $message);
	if ( !empty( $message ) ) echo $message . "¥n";

ログイン時に表示させることもできるらしい。

エラーメッセージ出力

	// Incase a plugin uses $error rather than the $errors object
	if ( !empty( $error ) ) {
		$wp_error->add('error', $error);
		unset($error);
	}

	if ( $wp_error->get_error_code() ) {
		$errors = '';
		$messages = '';
		foreach ( $wp_error->get_error_codes() as $code ) {
			$severity = $wp_error->get_error_data($code);
			foreach ( $wp_error->get_error_messages($code) as $error ) {
				if ( 'message' == $severity )
					$messages .= '	' . $error . "<br />¥n";
				else
					$errors .= '	' . $error . "<br />¥n";
			}
		}
		if ( !empty($errors) )
			echo '<div id="login_error">' . apply_filters('login_errors', $errors) . "</div>¥n";
		if ( !empty($messages) )
			echo '<p class="message">' . apply_filters('login_messages', $messages) . "</p>¥n";
	}
} // End of login_header()

エラーメッセージを出力する。$errorsや$wp_error->get_error_codes()でエラーメッセージを取得して出力。

ここまでで、login_header()関数の定義が完了。
login_header()ログイン画面の前半部分が出力されます。

iPhoneでもShakeするけどちょっと動きが違う

function wp_shake_js() {
	global $is_iphone;
	if ( $is_iphone )
		return;
?>
<script type="text/javascript">
addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
function s(id,pos){g(id).left=pos+'px';}
function g(id){return document.getElementById(id).style;}
function shake(id,a,d){c=a.shift();s(id,c);if(a.length>0){setTimeout(function(){shake(id,a,d);},d);}else{try{g(id).position='static';wp_attempt_focus();}catch(e){}}}
addLoadEvent(function(){ var p=new Array(15,30,15,0,-15,-30,-15,0);p=p.concat(p.concat(p));var i=document.forms[0].id;g(i).position='relative';shake(i,p,20);});
</script>
<?php
}

ここまでで、wp-login.phpの前半戦。中盤戦に続きますー。
後半戦では、登録、パスワードリセットなどをswitch構文で分岐させながら処理しているようです。本格的ですね。

中盤こちら

この記事が気に入ったら
フォローしてね!

関連記事

コメント

コメントする

目次