各位观众老爷们,欢迎来到今天的“WordPress源码解剖”讲座。今天咱们要扒的是WordPress里一个非常重要但又容易被忽略的函数:wp_new_user_notification()。这玩意儿负责给新注册的用户和管理员发送邮件,告诉他们“嘿,有人来了!”。
咱们不搞虚的,直接上干货,从源码入手,看看这货到底是怎么运作的。
1. 函数的定义和基本结构
首先,我们找到wp-includes/pluggable.php文件,这个文件里面藏着很多WordPress核心的可插拔函数,wp_new_user_notification()就在其中。
/**
* Sends notification email to admin and new user when a new user is created.
*
* @since 2.0.0
*
* @param int $user_id User ID.
* @param string $notify Optional. Type of notification that should happen. Accepts 'admin', 'user', or empty
* string (admin and user). Default empty string.
* @param string $deprecated Optional. Deprecated in 4.3.0.
*/
function wp_new_user_notification( $user_id = 0, $notify = '', $deprecated = '' ) {
//... 函数体
}
简单解释一下:
$user_id:新注册用户的ID,这是必须的。$notify:通知类型,可以设置成'admin'(只通知管理员),'user'(只通知用户),或者留空(两者都通知)。$deprecated:一个被废弃的参数,不用管它。
2. 参数处理和用户数据获取
函数的第一步是处理参数,并获取用户的相关信息。
global $wpdb, $wp_hasher;
if ( empty( $notify ) ) {
$notify = 'both';
}
$user = get_userdata( $user_id );
if ( ! $user ) {
return;
}
$user_login = stripslashes( $user->user_login );
$user_email = stripslashes( $user->user_email );
$key = '';
这里做了几件事:
- 定义了全局变量
$wpdb(数据库连接) 和$wp_hasher(密码哈希)。 - 如果
$notify为空,默认设置为'both',表示管理员和用户都要通知。 - 使用
get_userdata()函数通过$user_id获取用户数据,如果找不到用户,直接return,结束函数。 - 从用户数据中提取用户名 (
$user_login) 和邮箱 ($user_email),并使用stripslashes()函数去除转义字符,保证数据的干净。
3. 生成激活密钥 (如果需要)
如果启用了用户注册,并且用户需要激活账号,那么就需要生成一个激活密钥。
if ( 'user' === $notify || 'both' === $notify ) {
// Generate something random for a key...
if ( empty( $wp_hasher ) ) {
require_once ABSPATH . 'wp-includes/class-phpass.php';
$wp_hasher = new PasswordHash( 8, true );
}
$key = wp_generate_password( 20, false );
/**
* Filters the user activation key.
*
* @since 3.5.0
*
* @param string $key The activation key.
* @param int $user_id The user ID.
*/
$key = apply_filters( 'user_activation_key', $key, $user_id );
// Now insert the key, so that it can be verified against.
$wpdb->update( $wpdb->users, array( 'user_activation_key' => $key ), array( 'user_login' => $user_login ) );
$blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
}
这段代码做了这些事情:
- 判断
$notify是否为'user'或者'both',只有在这种情况下才生成激活密钥。 - 如果
$wp_hasher对象不存在,则加载class-phpass.php文件,并创建$wp_hasher对象,用于密码哈希。 - 使用
wp_generate_password()函数生成一个 20 位的随机密码作为激活密钥。 - 应用
user_activation_key过滤器,允许开发者修改激活密钥。 - 将激活密钥更新到数据库的
wp_users表中。 - 获取博客名称
$blogname,用于邮件内容。
4. 构建邮件内容
接下来,函数会根据 $notify 的值,分别构建管理员和用户的邮件内容。
4.1 管理员邮件
if ( 'admin' === $notify || 'both' === $notify ) {
$message = sprintf( __( 'New user registration on your site %s:' ), $blogname ) . "rnrn";
$message .= sprintf( __( 'Username: %s' ), $user_login ) . "rn";
$message .= sprintf( __( 'E-mail: %s' ), $user_email ) . "rn";
/**
* Fires after the new user notification email is sent to the site admin.
*
* @since 5.2.0
*
* @param WP_User $user User object.
* @param string $blogname The site title.
*/
do_action( 'wp_new_user_notification_email_admin', $user, $blogname );
@wp_mail( get_option( 'admin_email' ), sprintf( __( '[%s] New User Registration' ), $blogname ), $message );
}
这段代码:
- 构建了管理员邮件的内容,包括网站名称、用户名和邮箱。
- 触发
wp_new_user_notification_email_admin动作钩子,允许开发者在管理员邮件发送之前进行自定义。 - 使用
wp_mail()函数发送邮件给管理员,邮件主题是[网站名称] New User Registration。
4.2 用户邮件
if ( 'user' === $notify || ( 'both' === $notify && empty( $deprecated ) ) ) {
// The `$deprecated` argument is kept to avoid breaking any plugins that may be passing
// a third argument to the function's usage.
$message = sprintf( __( 'Welcome to %s!' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ) . "rnrn";
if ( get_option( 'users_require_email' ) ) {
$message .= sprintf( __( 'To activate your account, please click the following link:' ) . "rnrn" );
$message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . ">rnrn";
$message .= sprintf( __( 'If you have any problems, please contact us at %s.' ), get_option( 'admin_email' ) ) . "rnrn";
} else {
$message .= sprintf( __( 'Your username is: %s' ), $user_login ) . "rnrn";
$message .= sprintf( __( 'To set your password, visit the following address:' ) . "rnrn" );
$message .= '<' . network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . ">rnrn";
$message .= sprintf( __( 'If you have any problems, please contact us at %s.' ), get_option( 'admin_email' ) ) . "rnrn";
}
/**
* Fires after the new user notification email is sent to the new user.
*
* @since 5.2.0
*
* @param WP_User $user User object.
* @param string $blogname The site title.
*/
do_action( 'wp_new_user_notification_email', $user, $blogname );
wp_mail( $user_email, sprintf( __( '[%s] Your username and password info' ), $blogname ), $message );
}
这段代码有点长,我们来分解一下:
- 首先判断
$notify是否为'user'或者'both',并且$deprecated是否为空。这个$deprecated参数是为了兼容旧版本的插件,可以忽略。 - 构建用户邮件的内容,首先是欢迎信息。
- 然后判断是否启用了用户邮箱验证 (
get_option( 'users_require_email' )):- 如果启用了邮箱验证,则生成激活链接,让用户点击激活账号。
- 如果没有启用邮箱验证,则显示用户名,并生成重置密码的链接。
- 触发
wp_new_user_notification_email动作钩子,允许开发者在用户邮件发送之前进行自定义。 - 使用
wp_mail()函数发送邮件给用户,邮件主题是[网站名称] Your username and password info。
5. wp_mail() 函数
在上面,我们多次提到了 wp_mail() 函数,这个函数是WordPress的核心邮件发送函数,它封装了PHP的 mail() 函数,并提供了一些额外的功能,比如支持SMTP服务器。
wp_mail() 函数的定义如下:
/**
* Sends an email, similar to PHP's mail function.
*
* A true return value does not automatically mean that the user received the
* email successfully. It just means that the method that WordPress uses was able
* to process the request without any errors.
*
* The default content type of the email is `text/plain`. For HTML email, set the
* `$headers` parameter accordingly.
*
* @since 1.2.1
*
* @param string|string[] $to Array or comma-separated list of email addresses to send message.
* @param string $subject Email subject.
* @param string $message Message contents.
* @param string|string[] $headers Optional. Additional headers. Use an array to send multiple headers.
* Default empty string.
* @param string|string[] $attachments Optional. Path to file(s) to attach. Use an array to send multiple attachments.
* Default empty array.
* @return bool Whether the email contents were sent successfully.
*/
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
//... 函数体
}
简单来说,wp_mail() 函数接收以下参数:
$to:收件人邮箱地址,可以是字符串或者数组。$subject:邮件主题。$message:邮件内容。$headers:邮件头部信息,比如Content-Type,Cc等,可以是字符串或者数组。$attachments:附件,可以是字符串或者数组。
wp_mail() 函数内部会根据你的WordPress配置,选择合适的邮件发送方式,比如使用PHP的 mail() 函数,或者使用SMTP服务器。
6. 钩子 (Hooks)
在 wp_new_user_notification() 函数中,我们看到了两个动作钩子:
wp_new_user_notification_email_admin:在管理员邮件发送之前触发。wp_new_user_notification_email:在用户邮件发送之前触发。
这些钩子允许开发者修改邮件的内容、主题、头部信息等,提供了非常强大的自定义能力。
例如,你可以使用以下代码修改管理员邮件的主题:
add_action( 'wp_new_user_notification_email_admin', 'my_custom_admin_email', 10, 2 );
function my_custom_admin_email( $user, $blogname ) {
add_filter( 'wp_mail_subject', 'my_custom_admin_email_subject', 10, 1 );
}
function my_custom_admin_email_subject( $subject ) {
return '[重要] 有新人注册啦!';
}
这段代码首先使用 add_action() 函数注册 wp_new_user_notification_email_admin 动作钩子,然后在 my_custom_admin_email() 函数中使用 add_filter() 函数注册 wp_mail_subject 过滤器,修改邮件主题。
7. 总结
好了,各位观众老爷们,今天的“WordPress源码解剖”讲座就到这里了。我们一起深入剖析了 wp_new_user_notification() 函数的源码,了解了它的工作原理,以及如何通过钩子进行自定义。
为了方便大家理解,我把关键步骤总结成一个表格:
| 步骤 | 说明 | 涉及函数/变量 |
|---|---|---|
| 1. 参数处理 | 处理 $user_id 和 $notify 参数,获取用户数据。 |
get_userdata(), stripslashes() |
| 2. 生成密钥 | 如果需要激活账号,则生成激活密钥,并更新到数据库。 | wp_generate_password(), apply_filters( 'user_activation_key' ), $wpdb->update() |
| 3. 构建邮件 | 根据 $notify 的值,分别构建管理员和用户的邮件内容。 |
sprintf(), __( ) |
| 4. 发送邮件 | 使用 wp_mail() 函数发送邮件。 |
wp_mail(), do_action( 'wp_new_user_notification_email_admin' ), do_action( 'wp_new_user_notification_email' ) |
希望今天的讲座能对大家有所帮助。记住,源码是最好的老师,多看源码,才能真正理解WordPress的精髓。下次再见!