• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

创建自定义 WordPress 用户功能:密码重置

在本系列的前两个教程中,我们构建了用于登录和注册新用户的自定义页面。现在,登录流程中只剩下一个部分需要探索和替换:如果用户忘记了他或她的密码并想要重置他们的 wordpress 密码会发生什么。 

在本教程中,我们将完成最后一步并完成我们在整个系列中构建 的个性化登录插件。

WordPress 中的密码重置功能或多或少遵循当今网站上的标准方法: 

  1. 用户通过输入他或她的用户名或电子邮件地址并请求 WordPress 重置密码来启动重置。 

  2. 临时密码重置令牌被创建并存储在用户数据中。包含此令牌的链接将发送到用户的电子邮件地址。

  3. 用户点击链接。

  4. 在重置密码页面上,验证令牌,如果它与用户的数据匹配,她可以选择一个新密码。

就像登录和新用户注册一样,这个功能是通过处理的wp-login.php ——因此,我们如何自定义这个流程的总体思路现在大部分来自以前的教程。 

如果您还没有阅读前两个教程,最好从第 1 部分开始,按顺序阅读本系列。您可以在自己编写代码的同时按照教程进行操作,也可以从链接的 Github 存储库下载完整的源代码。

现在,让我们开始替换流程中的第一个屏幕。

启动 WordPress 重置密码

当用户到达您的登录页面但不记得他或她用于该站点的密码时,重置 WP 密码开始。 

为此,我们放置了一个忘记密码?系列第一部分中登录表单底部的消息模板链接。默认情况下,在 WordPress 支持的网站上,此链接指向wp-login.php?action=lostpassword,页面如下所示:

创建自定义 WordPress 用户功能:密码重置  第1张

为了用自定义页面替换这个页面,我们将创建一个函数来将用户重定向到我们的自定义页面并将该函数挂钩到 WordPress 操作。

在这种情况下,我们有两个选项可供选择:我们可以使用在lost_password页面呈现之前调用的操作,或者我们在之前的教程中一直使用的操作:login_form_{action},这次,login_form_lostpassword。

我们可以双向使用,但为了限制执行的不必要代码的数量,让我们选择后一个选项。

但首先,让我们创建新的 WordPress 自定义密码重置页面:

第 1 步:创建重置密码页面 

您还记得,在第 1 部分中,我们使用plugin_activated回调函数创建了一个用于在插件激活时创建 WordPress 页面的函数。

$page_definitions在此函数中,在数组末尾添加新页面的定义。在 WordPress 密码重置流程中,我们还需要第二页来选择新密码。所以,为了节省时间,我们现在也添加第二页。

为了清楚起见,这是整个数组(添加了最后两个页面定义):

// Information needed for creating the plugin's pages
$page_definitions = array(
    'member-login' => array(
        'title' => __( 'Sign In', 'personalize-login' ),
        'content' => '[custom-login-form]'
    ),
    'member-account' => array(
        'title' => __( 'Your Account', 'personalize-login' ),
        'content' => '[account-info]'
    ),
    'member-register' => array(
        'title' => __( 'Register', 'personalize-login' ),
        'content' => '[custom-register-form]'
    ),
    'member-password-lost' => array(
        'title' => __( 'Forgot Your Password?', 'personalize-login' ),
        'content' => '[custom-password-lost-form]'
    ),
    'member-password-reset' => array(
        'title' => __( 'Pick a New Password', 'personalize-login' ),
        'content' => '[custom-password-reset-form]'
    )
);

插件激活回调仅在插件被显式激活时调用,因此要创建这些新页面,您必须停用插件然后再次激活它。

现在,创建页面后,我们可以将用户重定向到member-password-lost而不是wp-login?action=lostpassword. 

第 2 步:将用户重定向到自定义页面

正如我上面提到的,我们将使用 action login_form_{action},或者login_form_lostpassword在wp-login.php有机会呈现“丢失密码?”的默认版本之前插入。屏幕。

在插件的构造函数中,添加以下行:

add_action( 
'login_form_lostpassword'
, 
array
( 
$this
, 
'redirect_to_custom_lostpassword'
 
) );

然后,创建函数redirect_to_custom_lostpassword。 

此函数将检查请求方法:目前,我们将仅处理使用该GET方法发送的请求,因为这些请求用于显示屏幕。稍后我们将看看会发生什么post

/**
 * Redirects the user to the custom "Forgot your password?" page instead of
 * wp-login.php?action=lostpassword.
 */
public function redirect_to_custom_lostpassword() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        if ( is_user_logged_in() ) {
            $this->redirect_logged_in_user();
            exit;
        }
 
        wp_redirect( home_url( 'member-password-lost' ) );
        exit;
    }
}

该功能实际上与我们在上一个教程中用于将用户重定向到自定义注册页面的功能相同,只是将重定向替换为我们在上面创建的新页面的页面 slug(在未来,也许?)。

现在,如果您单击忘记了您的 WordPress 密码?在登录页面上,您将被重定向到 WordPress 自定义密码重置页面。现在,让我们创建一个短代码来添加用于启动密码重置的 WordPress 密码表单。

第 3 步:为 WordPress 更改密码表单创建简码

在创建用于启动 WordPress 密码重置的页面时,我们将短代码添加[custom-lost-password-form]到其正文中。现在,要用表单替换简码,让我们创建一个简码处理程序。

在插件的构造函数中,添加以下行:

add_shortcode( 
'custom-password-lost-form'
, 
array
( 
$this
, 
'render_password_lost_form'
 
) );

然后,创建用于呈现表单的函数:

/**
 * A shortcode for rendering the form used to initiate the password reset.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_lost_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );
 
    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        return $this->get_template_html( 'password_lost_form', $attributes );
    }
}

到目前为止,这个功能的大部分内容你已经很熟悉了:首先我们解析短代码参数(show_title用于决定是否应该在启动密码重置的表单之前呈现标题)。然后,如果用户没有登录,该函数会呈现一个包含 WordPress 忘记密码表单的模板。 

现在让我们添加该模板。在templates目录中,创建一个新文件,将其命名为password_lost_form.php. 然后,将以下代码添加到该模板:

<div id="password-lost-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Forgot Your Password?', 'personalize-login' ); ?></h3>
    <?php endif; ?>
 
    <p>
        <?php
            _e(
                "Enter your email address and we'll send you a link you can use to pick a new password.",
                'personalize_login'
            );
        ?>
    </p>
 
    <form id="lostpasswordform" action="<?php echo wp_lostpassword_url(); ?>" method="post">
        <p class="form-row">
            <label for="user_login"><?php _e( 'Email', 'personalize-login' ); ?>
            <input type="text" name="user_login" id="user_login">
        </p>
 
        <p class="lostpassword-submit">
            <input type="submit" name="submit" class="lostpassword-button"
                   value="<?php _e( 'Reset Password', 'personalize-login' ); ?>"/>
        </p>
    </form>
</div>

show_title如果属性设置为 true,则模板首先显示标题(第 2-4 行)。

接下来是第 6-13 行的一些说明和实际表格。正如您将在第 15 行看到的那样,表单将发布到 WordPress 函数返回的  wp_lostpassword_urlURL,与我们在上面将用户重定向到自定义页面时看到的 URL 相同。

此表单仅包含一个文本字段user_login (第 18 行)。在此字段中,默认的 WordPress 重置密码功能接受用户的用户名或电子邮件。由于我们使用电子邮件作为用户名,它们都是相同的,因此我们只要求字段标签中的电子邮件(第 17 行)。

添加此模板后,当您点击忘记密码?登录页面上的消息模板链接,你会看到一个看起来像这样的页面(如果使用当前的 WordPress 默认主题,二十五)

创建自定义 WordPress 用户功能:密码重置  第2张

第 4 步:处理 WordPress 帐户恢复表单提交

现在我们已经创建了 WordPress 密码表单,是时候看看用户提交它时会发生什么。

为了让我们在不求助于 hack 的情况下进行正确的错误处理,我们需要自己编写一些功能 -wp-login.php自然地尽可能多地使用辅助函数。 

为此,我们将添加一个新函数来处理操作中的POST请求login_form_lostpassword。 

该函数将使用 中retrieve_password定义的函数wp-login.php来查找用户并启动密码更新程序。然后,根据是否有错误,该功能将用户重定向到正确的页面:如果出现错误,返回忘记密码?消息模板页面,成功后进入登录页面。

在构造函数中,添加以下行: 

add_action( 
'login_form_lostpassword'
, 
array
( 
$this
, 
'do_password_lost'
 
) );

然后,创建函数:

/**
 * Initiates password reset.
 */
public function do_password_lost() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $errors = retrieve_password();
        if ( is_wp_error( $errors ) ) {
            // Errors found
            $redirect_url = home_url( 'member-password-lost' );
            $redirect_url = add_query_arg( 'errors', join( ',', $errors->get_error_codes() ), $redirect_url );
        } else {
            // Email sent
            $redirect_url = home_url( 'member-login' );
            $redirect_url = add_query_arg( 'checkemail', 'confirm', $redirect_url );
        }
 
        wp_redirect( $redirect_url );
        exit;
    }
}

该函数首先检查请求方法(第 5 行)。由于我们对提交密码丢失表单的情况感兴趣,因此该函数仅在找到POST请求时才跳转。这些GET请求已经由 redirect_to_custom_lostpassword我们之前创建的函数处理。

然后,在第 6 行,我们调用 WordPress 函数retrieve_password。该函数的名称有点误导:该函数并不真正检索密码,而是检查表单中的数据,然后通过创建重置 WP 密码令牌并将其通过电子邮件发送给用户,为 WordPress 密码重置准备用户帐户。

如果有错误(第 7 行),我们将用户重定向回页面member-password-lost,并将错误代码作为请求参数传递(第 8-10 行,实际重定向在第 17 行完成)。 

如果一切顺利,用户将被重定向到带有请求参数checkemail集的登录页面(第 12-14 行),以便我们向用户显示一条消息。

现在,如果您提交 WordPress 密码表单,一切都会正常。但是为了使用户体验更完整,我们需要回到呈现密码丢失和登录表单的简码,并显示错误和成功通知。

让我们从正面开始,并添加成功消息。 

在简码函数中,在调用render_login_form之前的某处添加以下行get_template_html:

// Check if the user just requested a new password 
$attributes
[
'lost_password_sent'
] = isset( 
$_REQUEST
[
'checkemail'
] ) && 
$_REQUEST
[
'checkemail'
] == 
'confirm'
;

在表单模板中,使用上面的属性添加一条消息:

<?php if( $attributes['lost_password_sent'] ) : ?>   
<p class="login-info">       
<?php _e( 'Check your email for a link to reset your password.', 'personalize-login'); ?>  
</p>
<?php endif; ?>

现在,在成功启动密码重置后,登录表单应如下所示:

创建自定义 WordPress 用户功能:密码重置  第3张

要显示错误,我们将返回丢失的 WordPress 更改密码表单。 

首先,在短代码处理程序中 render_password_lost_form,在渲染模板之前,添加以下行以遍历错误代码并在数组中收集匹配的错误消息$attributes['errors']:

// Retrieve possible errors from request parameters
$attributes['errors'] = array();
if ( isset( $_REQUEST['errors'] ) ) {
    $error_codes = explode( ',', $_REQUEST['errors'] );
 
    foreach ( $error_codes as $error_code ) {
        $attributes['errors'] []= $this->get_error_message( $error_code );
    }
}

然后,在模板中,我们将呈现错误:

<?php if ( count( $attributes['errors'] ) > 0 ) : ?>
    <?php foreach ( $attributes['errors'] as $error ) : ?>
        <p>
            <?php echo $error; ?>
        </p>
    <?php endforeach; ?>
<?php endif; ?>

最后,将错误消息添加到我们的函数中get_error_messages:

// Lost password
 
case 'empty_username':
    return __( 'You need to enter your email address to continue.', 'personalize-login' );
 
case 'invalid_email':
case 'invalidcombo':
    return __( 'There are no users registered with this email address.', 'personalize-login' );

接下来,要完成密码重置流程的第一步,让我们看看如何自定义发送给用户的电子邮件。

第 5 步:自定义 WordPress 更改密码电子邮件

正如我们之前看到的,当发送重置 WP 密码的请求时,在功能中retrieve_password,会发送一封 WordPress 更改密码电子邮件,其中包含有关操作的快速说明以及可用于完成密码重置的链接。

信息简短而切题。它完成了它应该做的事情,但您可能希望对其进行自定义以赋予其个人风格,并可能使其更具描述性。

默认文本是硬编码的wp-login.php,但在发送消息之前,WordPress 为插件开发人员提供了使用两个过滤器替换它的机会。

首先,要替换消息正文,可以使用过滤器 retrieve_password_message。现在让我们这样做。

在插件的构造函数中,添加以下行:

add_filter( 'retrieve_password_message', 
array( $this, 'replace_retrieve_password_message'), 10, 4 );

然后,创建函数 replace_retrieve_password_message:

/**
 * Returns the message body for the password reset mail.
 * Called through the retrieve_password_message filter.
 *
 * @param string  $message    Default mail message.
 * @param string  $key        The activation key.
 * @param string  $user_login The username for the user.
 * @param WP_User $user_data  WP_User object.
 *
 * @return string   The mail message to send.
 */
public function replace_retrieve_password_message( $message, $key, $user_login, $user_data ) {
    // Create new message
    $msg  = __( 'Hello!', 'personalize-login' ) . "\r\n\r\n";
    $msg .= sprintf( __( 'You asked us to reset your password for your account using the email address %s.', 'personalize-login' ), $user_login ) . "\r\n\r\n";
    $msg .= __( "If this was a mistake, or you didn't ask for a password reset, just ignore this email and nothing will happen.", 'personalize-login' ) . "\r\n\r\n";
    $msg .= __( 'To reset your password, visit the following address:', 'personalize-login' ) . "\r\n\r\n";
    $msg .= site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
    $msg .= __( 'Thanks!', 'personalize-login' ) . "\r\n";
 
    return $msg;
}

该函数接收四个参数: 

  • $message是要发送给用户的消息的默认版本。我们将忽略此参数并从头开始创建我们自己的文本。

  • $key是用于验证用户密码重置请求的令牌。它需要包含在密码重置链接中。

  • $user_login是用户的用户名(在我们的例子中是电子邮件地址),在密码重置链接中也需要。

  • $user_data包含有关用户的一些数据。我们暂时忽略这一点,但如果您愿意,您可以在自己的自定义中进一步探索它。

大多数功能只是将消息创建为一系列字符串连接。完成密码重置的 URL 在第 18 行创建。

对于更完整的自定义,一个想法是添加一个设置字段来编辑密码检索消息的内容,并使用它来代替以这种方式在函数内编码消息。

如果您愿意,您可以使用过滤器 retrieve_password_title 以同样的方式替换电子邮件标题。过滤器函数采用一个参数,即发送给用户的默认标题,并应返回新标题。 

进一步自定义的另一种方法是替换整个消息并发送 HTML 消息,例如使用我在早期教程中解释的关于使用 Mandrill 从 WordPress 发送电子邮件的方法。在这种情况下,我会使用 Mandrill api 在上面的过滤器函数中发送消息并返回 false,这样 WordPress 就不会再次尝试发送电子邮件。

您现在已经完成了 WordPress 密码重置过程的第一步:用户可以要求重置 WP 密码,该过程由 WordPress 启动。 

接下来,我们将看看当用户单击 Wordpress 更改密码电子邮件中的链接时会发生什么。

做一个 WordPress 密码重置

正如我们在上面看到的,在启动 WordPress 重置密码后,用户将被重定向回登录页面,并指示检查他或她的电子邮件。 

在该 WordPress 更改密码电子邮件中,有一个返回wp-login.php参数的链接login,key用于识别用户并验证 WordPress 密码重置请求。当用户单击链接时,WordPress 会验证用户和密钥的有效性,然后如果一切正常,则让用户设置新密码。

该功能运行良好,我们将使用wp-login.php其中的一部分,在能够完成定制。

第 1 步:将用户重定向到您的 WordPress 自定义密码重置页面

首先,我们首先将用户重定向到我们自己的 WordPress 自定义密码重置页面(我们在本教程开始时创建的)。 

到目前为止,您可能已经熟悉了:与我们在登录和注册操作以及重置 WP 密码流程的第一页中所做的相同,我们将使用该操作login_form_{action}将密码重置操作转移到我们自己的操作在 WordPress 开始做任何事情之前的自定义函数。 

有两个wp-login.php动作用于相同的功能,rp和resetpass,所以我们需要将它们都重定向到相同的功能,  redirect_to_custom_password_reset。

在插件的构造函数中,添加以下行:

add_action( 'login_form_rp', array( $this, 'redirect_to_custom_password_reset' ) );
add_action( 'login_form_resetpass', array( $this, 'redirect_to_custom_password_reset' ) );

然后,创建函数:

/**
 * Redirects to the custom password reset page, or the login page
 * if there are errors.
 */
public function redirect_to_custom_password_reset() {
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
        // Verify key / login combo
        $user = check_password_reset_key( $_REQUEST['key'], $_REQUEST['login'] );
        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }
 
        $redirect_url = home_url( 'member-password-reset' );
        $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url );
        $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url );
 
        wp_redirect( $redirect_url );
        exit;
    }
}

该函数首先检查这是一个GET请求。POST发送到同一 URL 的请求将在下面处理。 

然后,在第 8 行,我们调用 WordPress 函数check_password_reset_key来验证通过重置 WP 密码链接传递的参数是否有效。如果出现错误,我们会将用户重定向回登录页面,并将错误代码作为请求参数(第 9-16 行)。我们将很快添加用于显示错误的代码。

如果成功验证了参数并且允许用户更新他或她的密码,则该功能会继续通过将用户重定向到我们的 WordPress 自定义密码重置页面(仍然为空)member-password-reset。 

在第 19-20 行,我们将参数key和添加login到重定向 URL,以便当用户尝试在下一个屏幕上设置新密码时,它们将可用于另一次检查。WordPress 密码重置的默认版本为此使用了 cookie,但为了教程的缘故,我决定使用请求参数以使代码更易于理解。

接下来,让我们创建一个自定义版本的重置 WordPress 密码表单。

第 2 步:显示 WordPress 更改密码表格

单击WordPress 更改密码电子邮件链接后,向用户显示的重置 WordPress 密码表单默认如下所示:

创建自定义 WordPress 用户功能:密码重置  第4张

这是一个简单的表单,有两个字段,pass1一个pass2用于输入 WordPress 密码,另一个用于重新输入以检查是否有拼写错误。

要创建此表单的自定义版本,我们将使用简码。 

首先,在插件的构造函数中添加以下行:

add_shortcode( 
'custom-password-reset-form', 
array( 
$this, 'render_password_reset_form'
 ) );

然后,创建用于呈现表单的函数:

/**
 * A shortcode for rendering the form used to reset a user's password.
 *
 * @param  array   $attributes  Shortcode attributes.
 * @param  string  $content     The text content for shortcode. Not used.
 *
 * @return string  The shortcode output
 */
public function render_password_reset_form( $attributes, $content = null ) {
    // Parse shortcode attributes
    $default_attributes = array( 'show_title' => false );
    $attributes = shortcode_atts( $default_attributes, $attributes );
 
    if ( is_user_logged_in() ) {
        return __( 'You are already signed in.', 'personalize-login' );
    } else {
        if ( isset( $_REQUEST['login'] ) && isset( $_REQUEST['key'] ) ) {
            $attributes['login'] = $_REQUEST['login'];
            $attributes['key'] = $_REQUEST['key'];
 
            // Error messages
            $errors = array();
            if ( isset( $_REQUEST['error'] ) ) {
                $error_codes = explode( ',', $_REQUEST['error'] );
 
                foreach ( $error_codes as $code ) {
                    $errors []= $this->get_error_message( $code );
                }
            }
            $attributes['errors'] = $errors;
 
            return $this->get_template_html( 'password_reset_form', $attributes );
        } else {
            return __( 'Invalid password reset link.', 'personalize-login' );
        }
    }
}

该函数的核心从第 17 行开始,我们检查用户标识参数 login 和 key 是否存在。如果不是,则密码重置链接无效,我们只会呈现错误消息(第 34 行)。

如果检查正常,则将这两个变量添加到$attributes数组中以使它们可用于表单模板(第 18-19 行)。 

然后,在第 21-30 行,我们已经准备好在提交 WordPress 帐户恢复表单时可能发生的错误,使用与教程中早期表单相同的错误传递方法。

最后,在第 32 行,函数读取模板并将其返回给 WordPress 进行渲染。 

接下来让我们创建模板。在该templates目录中,创建一个新文件并将其命名为password_reset_form.php. 添加以下内容:

<div id="password-reset-form" class="widecolumn">
    <?php if ( $attributes['show_title'] ) : ?>
        <h3><?php _e( 'Pick a New Password', 'personalize-login' ); ?></h3>
    <?php endif; ?>
 
    <form name="resetpassform" id="resetpassform" action="<?php echo site_url( 'wp-login.php?action=resetpass' ); ?>" method="post" autocomplete="off">
        <input type="hidden" id="user_login" name="rp_login" value="<?php echo esc_attr( $attributes['login'] ); ?>" autocomplete="off" />
        <input type="hidden" name="rp_key" value="<?php echo esc_attr( $attributes['key'] ); ?>" />
         
        <?php if ( count( $attributes['errors'] ) > 0 ) : ?>
            <?php foreach ( $attributes['errors'] as $error ) : ?>
                <p>
                    <?php echo $error; ?>
                </p>
            <?php endforeach; ?>
        <?php endif; ?>
 
        <p>
            <label for="pass1"><?php _e( 'New password', 'personalize-login' ) ?></label>
            <input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" />
        </p>
        <p>
            <label for="pass2"><?php _e( 'Repeat new password', 'personalize-login' ) ?></label>
            <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
        </p>
         
        <p class="description"><?php echo wp_get_password_hint(); ?></p>
         
        <p class="resetpass-submit">
            <input type="submit" name="submit" id="resetpass-button"
                   class="button" value="<?php _e( 'Reset Password', 'personalize-login' ); ?>" />
        </p>
    </form>
</div>

表单以可选标题开头,如果短代码属性show_title设置为 true(第 2-4 行),则会显示该标题。 

实际形式紧跟在标题之后。请注意,表单将发布到wp-login.php?action=resetpass(第 6 行),与密码重置电子邮件中的链接中使用的 URL 相同,只是电子邮件链接使用了一个简短版本,rp而不是resetpass.

在表单的开头(第 7-8 行),我们设置了两个隐藏字段rp_key,rp_login并将keyandlogin参数传递给表单处理程序,该处理程序将使用它们来验证密码更改请求。

在第10-16行,如果有任何错误,模板将打印出错误。此代码与本教程前面的短代码模板完全相同。

这两个字段在第18-25行打印出来,然后是一些选择一个好的 WordPress 密码的说明和提交 WordPress 更改密码表单的按钮。

这是 WordPress 更改密码表单现在的样子:

创建自定义 WordPress 用户功能:密码重置  第5张

第 3 步:处理 WordPress 重置密码操作

当用户通过单击 WordPress重置密码按钮提交表单时,其内容将发送到wp-login.php?action=resetpass,我们上面使用的相同 URL 将用户重定向到我们的自定义密码重置页面。 

当然,当我们自己创建表单时,我们也可以使用不同的 URL。但是,通过保留此默认 URL 并使用login_form_resetpass(并且login_form_rp,只是为了确定)操作来替换默认功能,我们可以确保没有人最终意外调用默认版本的密码重置。

为此,再次向构造函数添加两行:

add_action( 
'login_form_rp', 
array( $this, 'do_password_reset') );
add_action( 'login_form_resetpass', 
array( $this, 'do_password_reset') 
);

然后,创建函数:

/**
 * Resets the user's password if the password reset form was submitted.
 */
public function do_password_reset() {
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
        $rp_key = $_REQUEST['rp_key'];
        $rp_login = $_REQUEST['rp_login'];
 
        $user = check_password_reset_key( $rp_key, $rp_login );
 
        if ( ! $user || is_wp_error( $user ) ) {
            if ( $user && $user->get_error_code() === 'expired_key' ) {
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
            } else {
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
            }
            exit;
        }
 
        if ( isset( $_POST['pass1'] ) ) {
            if ( $_POST['pass1'] != $_POST['pass2'] ) {
                // Passwords don't match
                $redirect_url = home_url( 'member-password-reset' );
 
                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url )
                $redirect_url = add_query_arg( 'error', 'password_reset_mismatch', $redirect_url );
 
                wp_redirect( $redirect_url );
                exit;
            }
 
            if ( empty( $_POST['pass1'] ) ) {
                // Password is empty
                $redirect_url = home_url( 'member-password-reset' );
 
                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
                $redirect_url = add_query_arg( 'error', 'password_reset_empty', $redirect_url );
 
                wp_redirect( $redirect_url );
                exit;
            }
 
            // Parameter checks OK, reset password
            reset_password( $user, $_POST['pass1'] );
            wp_redirect( home_url( 'member-login?password=changed' ) );
        } else {
            echo "Invalid request.";
        }
 
        exit;
    }
}

该函数首先检查请求方法,它应该是POST; GET上面的重定向功能已经处理了请求。 

然后,它从表单数据中收集密钥和登录参数,并使用它们来验证第9 行的密码重置链接,使用 WordPress 函数check_password_reset_key(我们已经在重定向函数中使用了相同的函数)。

在 上lines 10-18,我们再次检查密码重置密钥检查中可能出现的错误,将用户重定向到忘记密码?用于呈现错误的消息模板页面。 

然后,如果重置密钥有效,我们可以专注于 WordPress 帐户恢复表单。 

首先,该函数检查两个密码是否匹配(第 21-31 行),然后检查它们是否为空(第 33-43 行)。在这两种情况下,用户都会被重定向回我们的密码重置页面,并在 URL 中包含key和login参数,让用户重试密码更新。

最后,如果所有检查都成功(如果您愿意,可以添加更多检查),该函数使用该函数重置 WordPress 密码reset_password(第 46 行),并将用户重定向到登录页面,password=changed并在 URL 后附加一个参数以显示通知。 

WordPress 密码现已成功更新,剩下的就是显示成功通知并添加错误消息。

首先,让我们添加通知。在简码函数render_login_form中,添加以下检查:

// Check if user just updated password
$attributes
[
'password_updated'
] = isset( 
$_REQUEST
[
'password'
] ) && 
$_REQUEST
[
'password'
] == 
'changed'
;

然后,在呈现表单之前将实际消息添加到模板中login_form.php:

<?php 
if( $attributes['password_updated'] ) : ?>
<p class="login-info">
<?php _e( 'Your password has been changed. You can sign in now.', 'personalize-login'); ?>
</p>
<?php endif; ?>


由于我们已经添加了对呈现上述错误消息的支持,剩下的就是将描述性错误消息添加到我们的函数get_error_message中。 

在构造中的default分支之前添加以下行:switch...case

// Reset password
 
case 'expiredkey':
case 'invalidkey':
    return __( 'The password reset link you used is not valid anymore.', 'personalize-login' );
 
case 'password_reset_mismatch':
    return __( "The two passwords you entered don't match.", 'personalize-login' );
     
case 'password_reset_empty':
    return __( "Sorry, we don't accept empty passwords.", 'personalize-login' )

结论

而已!重置 WP 密码功能已准备就绪,至此,我们已经完成了从注册新用户到登录和重置丢失密码的 WordPress 登录体验的自定义。

我希望本系列为您提供了足够的工具,让您感觉自己已经为进一步的定制做好了准备——例如通过在密码重置流程中添加一个新步骤——并更好地理解 wp-login.php 中发生的事情。


文章目录
  • 启动 WordPress 重置密码
    • 第 2 步:将用户重定向到自定义页面
    • 第 3 步:为 WordPress 更改密码表单创建简码
    • 第 4 步:处理 WordPress 帐户恢复表单提交
    • 第 5 步:自定义 WordPress 更改密码电子邮件
  • 做一个 WordPress 密码重置
    • 第 1 步:将用户重定向到您的 WordPress 自定义密码重置页面
    • 第 2 步:显示 WordPress 更改密码表格
    • 第 3 步:处理 WordPress 重置密码操作
  • 结论
  • 发表评论