1. Code
  2. WordPress
  3. Plugin Development

Construir un flujo de usuario de WordPress personalizado — parte 3: restablecimiento de contraseña

Scroll to top
This post is part of a series called Build a Custom WordPress User Flow.
Build a Custom WordPress User Flow — Part 2: New User Registration

Spanish (Español) translation by CYC (you can also view the original English article)

En los primeros dos tutoriales de esta serie, hemos creado páginas personalizadas para iniciar sesión y registrar un nuevo usuario. Ahora, solo queda una parte del flujo de inicio de sesión para buscar y reemplazar: lo que sucede si un usuario olvida su contraseña y desea restablecerla.

En este tutorial, abordaremos ese último paso y completaremos el plugin de Personalizar sesión que hemos estado creando a lo largo de la serie.

La funcionalidad de recuperación de contraseña en WordPress sigue siendo lo que se ha convertido más o menos en el enfoque estándar en los sitios web de hoy en día:

  1. Un usuario inicia el restablecimiento ingresando su nombre de usuario o dirección de correo electrónico y solicitando un restablecimiento de contraseña.
  2. Se crea un token de restablecimiento de contraseña temporal y se almacena en los datos del usuario. Un enlace que contiene este token se envía a la dirección de correo electrónico del usuario.
  3. El usuario hace clic en el enlace.
  4. En la página de restablecimiento de contraseña, el token se verifica y, si coincide con los datos del usuario, puede elegir una nueva contraseña.

Al igual que el inicio de sesión y el nuevo registro de usuarios, esta funcionalidad se maneja a través de wp-login.php, por lo que la idea general de cómo vamos a personalizar este flujo ya estará familiarizada con los tutoriales anteriores.

Si aún no has leído los primeros primeros tutoriales, es mejor comenzar de la Parte 1 y pasar por la serie en orden. Puedes seguir el tutorial mientras escribes el mismo código o descargar el código fuente completo del repositorio vinculado de Github.

Ahora, comencemos reemplazando la primera pantalla en el flujo.

Iniciar el restablecimiento de contraseña

El restablecimiento de la contraseña comienza cuando un usuario llega a tu página de inicio, pero no tiene contraseña para este sitio.

Para esto, colocamos un enlace que diga ¿Olvidó su contraseña? en la parte inferior del formulario de inicio de sesión en la primera parte de la serie. De forma predeterminada, en los sitios con WordPress, este enlace apunta a wp-login.php?action=lostpassword, una página que se ve así:

WordPress Forgot Your Password screenWordPress Forgot Your Password screenWordPress Forgot Your Password screen

Para reemplazar esta página por una personalizada, crearemos una función para redirigir al usuario a nuestra página personalizada y enganchar esa función a una acción de WordPress.

En este caso, tenemos las opciones para elegir: podemos usar la acción lost_password, que se llama justo antes de mostrar la página, o la acción que has estado usando en anteriores tutoriales: login_form_{action}, esta vez, login_form_lostpassword.

Podríamos ir en ambos sentidos, pero para limitar la cantidad de código innecesario que se está ejecutando, escojamos la última opción.

Pero primero, creemos la nueva página.

Paso 1: Crea una página para iniciar el restablecimiento de contraseña

Como recordaráw, en la Parte 1, creamos una función para crear páginas de WordPress en la activación del complemento, utilizando la función callback plugin_activated.

En esta función, agrega la definición de la página nueva al final de la matriz $page_definitions. En el flujo de restauración de contraseña, también falta una segunda página para elegir la nueva contraseña. Entonces, para ahorrar tiempo, también agreguemos esta segunda página ahora.

Aquí está toda la matriz para mayor claridad (con las últimas definiciones de página agregadas):

1
// Information needed for creating the plugin's pages

2
$page_definitions = array(
3
    'member-login' => array(
4
        'title' => __( 'Sign In', 'personalize-login' ),
5
        'content' => '[custom-login-form]'
6
    ),
7
    'member-account' => array(
8
        'title' => __( 'Your Account', 'personalize-login' ),
9
        'content' => '[account-info]'
10
    ),
11
    'member-register' => array(
12
        'title' => __( 'Register', 'personalize-login' ),
13
        'content' => '[custom-register-form]'
14
    ),
15
    'member-password-lost' => array(
16
        'title' => __( 'Forgot Your Password?', 'personalize-login' ),
17
        'content' => '[custom-password-lost-form]'
18
    ),
19
    'member-password-reset' => array(
20
        'title' => __( 'Pick a New Password', 'personalize-login' ),
21
        'content' => '[custom-password-reset-form]'
22
    )
23
);

La activación del complemento callback solo se realiza cuando el complemento está explícitamente activado, por lo que para crear estas páginas nuevas, deberás desactivar el complemento y luego activarlo nuevamente.

Ahora, con las páginas creadas, podemos redirigir al usuario a member-password-lost en lugar de wp-login?action=lostpassword.

Paso 2: Redirige al usuario a la página personalizada

Como mencioné anteriormente, usaremos login_form_{action} o login_form_lostpassword para cortar antes de que wp-login.php tenga la oportunidad de presentar la versión predeterminada de la pantalla "Olvidaste tu contraseña?".

En el constructor del complemento, agrega la siguiente línea:

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

Luego, crea la función redirect_to_custom_lostpassword.

Esta función revisa el método de la solicitud: por ahora, solo actuaremos en las solicitudes enviadas por el método GET, ya que son las que se utilizan para mostrar la pantalla. Echaremos un vistazo a lo que sucede en POST en un momento.

1
/**

2
 * Redirects the user to the custom "Forgot your password?" page instead of

3
 * wp-login.php?action=lostpassword.

4
 */
5
public function redirect_to_custom_lostpassword() {
6
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
7
        if ( is_user_logged_in() ) {
8
            $this->redirect_logged_in_user();
9
            exit;
10
        }
11
12
        wp_redirect( home_url( 'member-password-lost' ) );
13
        exit;
14
    }
15
}

La función es en realidad la misma que usamos para redirigir al usuario a nuestra página de registro personalizado en el tutorial anterior, con solo el redireccionamiento reemplazado por la página de la nueva página que creamos anteriormente (¿un buen lugar para refactorizar en el futuro, tal vez?).

Ahora, si haces clic en ¿Olvidaste tu contraseña? en la página de inicio de sesión, te enviará a una página personalizada y no a la de Olvidaste la contraseña. Ahora, creemos un shortcode para agregar el formulario para iniciar el restablecimiento de contraseña.

Paso 3: crea un código abreviado para el formulario de restauración de contraseña

Al crear la página para iniciar el restablecimiento de contraseña, agregamos el shortcode, [custom-lost-password-form] al body. Ahora, para reemplazar el shortcode con un formulario, creemos un manejador shortcode.

En el constructor del complemento, agrega la siguiente línea:

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

A continuación, crea la función para representar el formulario:

1
/**

2
 * A shortcode for rendering the form used to initiate the password reset.

3
 *

4
 * @param  array   $attributes  Shortcode attributes.

5
 * @param  string  $content     The text content for shortcode. Not used.

6
 *

7
 * @return string  The shortcode output

8
 */
9
public function render_password_lost_form( $attributes, $content = null ) {
10
    // Parse shortcode attributes

11
    $default_attributes = array( 'show_title' => false );
12
    $attributes = shortcode_atts( $default_attributes, $attributes );
13
14
    if ( is_user_logged_in() ) {
15
        return __( 'You are already signed in.', 'personalize-login' );
16
    } else {
17
        return $this->get_template_html( 'password_lost_form', $attributes );
18
    }
19
}

Por ahora, la mayoría de esta función ya es familiar para ti: Primero analizamos los parámetros del shortcode (show_title se usa para decidir si un título debe representarse antes del formulario para iniciar el restablecimiento de contraseña). Luego, si el usuario no está conectado, la función representa una plantilla que contiene el formulario para iniciar el restablecimiento de contraseña.

Agreguemos esa plantilla ahora. En el directorio templates, crea un nuevo archivo y asígnale el nombre password_lost_form.php. Luego, agrega el próximo código a esa plantilla:

1
<div id="password-lost-form" class="widecolumn">
2
    <?php if ( $attributes['show_title'] ) : ?>
3
        <h3><?php _e( 'Forgot Your Password?', 'personalize-login' ); ?></h3>
4
    <?php endif; ?>
5
6
    <p>
7
        <?php
8
            _e(
9
                "Enter your email address and we'll send you a link you can use to pick a new password.",
10
                'personalize_login'
11
            );
12
        ?>
13
    </p>
14
15
    <form id="lostpasswordform" action="<?php echo wp_lostpassword_url(); ?>" method="post">
16
        <p class="form-row">
17
            <label for="user_login"><?php _e( 'Email', 'personalize-login' ); ?>
18
            <input type="text" name="user_login" id="user_login">
19
        </p>
20
21
        <p class="lostpassword-submit">
22
            <input type="submit" name="submit" class="lostpassword-button"
23
                   value="<?php _e( 'Reset Password', 'personalize-login' ); ?>"/>
24
        </p>
25
    </form>
26
</div>

La primera y la segunda presentación se muestran en el perfil show_title se establece en (líneas 2-4).

Esto es seguido por algunas instrucciones en las líneas 6-13 y la forma real. Como verás en la línea 15, el formulario se publicará en la URL devuelta por la función de WordPress wp_lostpassword_url, la misma URL que vimos anteriormente cuando redirigimos al usuario a nuestra página personalizada.

Este formulario contiene solo un campo de texto, user_login (línea 18). En este campo, la funcionalidad de restablecimiento de contraseña predeterminada en WordPress acepta el nombre de usuario o el correo electrónico del usuario. Como usamos el correo electrónico como nombre de usuario, ambos son iguales, por lo que pediremos solo el correo electrónico en la etiqueta del campo (línea 17).

Con esta plantilla agregada, haz clic en ¿Olvidaste tu contraseña? para que veas una página que se parece a esto (si el nombre predeterminado actual de WordPress, Twenty Fifteen)

Custom Forgot Your Password screenCustom Forgot Your Password screenCustom Forgot Your Password screen

Paso 4: Manejar el formulario Enviar

Ahora que hemos creado el formulario, es hora de ver qué sucede cuando el usuario lo envía.

Para que los errores no sean recurrentes, es necesario codificar las funciones de los mismos, usar las funciones de ayuda de wp-login.php tanto como sea posible, naturalmente.

Para hacer esto, agrega una nueva función para manejar las solicitudes POST en la acción login_form_lostpassword.

Esta función utiliza la  función  retrieve_password  definida en  wp-login.php  para buscar usuario e inicia el procedimiento de actualización de la contraseña. Luego, dependiendo de si hubo errores o no, la función redirige al usuario a la página correcta: en caso de errores, vuelve a la página Olvidaste tu contraseña y, cuando tenga éxito, a la página de inicio de sesión.

En el constructor, agrega la siguiente línea:

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

A continuación, crea la función:

1
/**

2
 * Initiates password reset.

3
 */
4
public function do_password_lost() {
5
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
6
        $errors = retrieve_password();
7
        if ( is_wp_error( $errors ) ) {
8
            // Errors found

9
            $redirect_url = home_url( 'member-password-lost' );
10
            $redirect_url = add_query_arg( 'errors', join( ',', $errors->get_error_codes() ), $redirect_url );
11
        } else {
12
            // Email sent

13
            $redirect_url = home_url( 'member-login' );
14
            $redirect_url = add_query_arg( 'checkemail', 'confirm', $redirect_url );
15
        }
16
17
        wp_redirect( $redirect_url );
18
        exit;
19
    }
20
}

La función comienza al verificar el método de solicitud (en la línea 5). Como estamos interesados ​​en el caso cuando se envía el formulario de contraseña perdida, esta función solo salta cuando encuentra una solicitud POST. Las solicitudes GET ya están manejadas por la función redirect_to_custom_lostpassword que creamos anteriormente.

Luego, en la línea 6 , llamamos a la función WordPress retrieve_password. El nombre de la función es un poco engañosa: la función realmente no recupera la contraseña, sino que verifica los datos del formulario y luego prepara la cuenta del usuario para el restablecimiento de contraseña creando el token de restablecimiento de contraseña y enviándolo por correo electrónico al usuario.

Si hay errores (línea 7), redirigimos al usuario a la página member-password-lost, con los códigos de error pasados ​​como un elemento de la solicitud (líneas 8-10, con el redireccionamiento real hecho en línea 17).

Si todo va bien, se redirige al usuario a la página de inicio de sesión con el parámetro de solicitud checkemail establecido (líneas 12-14) para que se pueda mostrar un mensaje al usuario.

Ahora, si envía el formulario, todo debería funcionar bien. Pero para completar la experiencia del usuario, los shortcodes que representan la pérdida de la contraseña y los formularios de inicio de sesión, los errores y las notificaciones de éxito.

Comencemos por lo positivo y agreguemos el mensaje de éxito.

En la función shortcode render_login_form, agrega las siguientes líneas en algún lugar antes de la llamada get_template_html:

1
// Check if the user just requested a new password 

2
$attributes['lost_password_sent'] = isset( $_REQUEST['checkemail'] ) && $_REQUEST['checkemail'] == 'confirm';

En la plantilla de formulario, agrega un mensaje, usando el atributo de arriba:

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

Ahora, después de iniciar con éxito un restablecimiento de contraseña, el formulario de inicio de sesión

Password reset instructions shown on Sign In pagePassword reset instructions shown on Sign In pagePassword reset instructions shown on Sign In page

Para mostrar los errores, volveremos al formulario de contraseña perdida.

Primero, en el controlador shortcode, render_password_lost_form, justo antes de representar la plantilla, agrega las siguientes líneas para revisar los códigos de error y recopila los mensajes de error coincidentes en la matriz $attributes ['errors']:

1
// Retrieve possible errors from request parameters

2
$attributes['errors'] = array();
3
if ( isset( $_REQUEST['errors'] ) ) {
4
    $error_codes = explode( ',', $_REQUEST['errors'] );
5
6
    foreach ( $error_codes as $error_code ) {
7
        $attributes['errors'] []= $this->get_error_message( $error_code );
8
    }
9
}

Luego, en la plantilla, presentaremos los errores:

1
<?php if ( count( $attributes['errors'] ) > 0 ) : ?>
2
    <?php foreach ( $attributes['errors'] as $error ) : ?>
3
        <p>
4
            <?php echo $error; ?>
5
        </p>
6
    <?php endforeach; ?>
7
<?php endif; ?>

Finalmente, agregue los mensajes de error a nuestra función get_error_messages:

1
// Lost password

2
3
case 'empty_username':
4
    return __( 'You need to enter your email address to continue.', 'personalize-login' );
5
6
case 'invalid_email':
7
case 'invalidcombo':
8
    return __( 'There are no users registered with this email address.', 'personalize-login' );

A continuación, para completar el primer paso en el flujo de restablecimiento de contraseña, veamos cómo podemos personalizar el correo electrónico que se envía al usuario.

Paso 5: Personaliza la contraseña Restablecer el correo electrónico

Como vimos anteriormente, cuando se envía la solicitud para restablecer una contraseña, en la función recuperación de contraseña llamada retrieve_password, WordPress envía un mensaje de correo electrónico que contiene instrucciones rápidas sobre qué hacer y un enlace que puede ser utilizado para finalizar el restablecimiento de la contraseña.

El mensaje es corto y al grano. Hace lo que se supone que debe hacer, pero es posible que desees personalizarlo para darle un toque personal y tal vez hacerlo un poco más descriptivo.

El texto predeterminado está codificado en wp-login.php, pero antes de enviar el mensaje, WordPress ofrece a los desarrolladores de complementos la posibilidad de reemplazarlo utilizando dos filtros.

Primero, para reemplazar el cuerpo del mensaje, puedes usar el filtro retrieve_password_message . Hagámoslo ahora.

En el constructor del complemento, agrega la siguiente línea:

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

Luego, crea la función, replace_retrieve_password_message :

1
/**

2
 * Returns the message body for the password reset mail.

3
 * Called through the retrieve_password_message filter.

4
 *

5
 * @param string  $message    Default mail message.

6
 * @param string  $key        The activation key.

7
 * @param string  $user_login The username for the user.

8
 * @param WP_User $user_data  WP_User object.

9
 *

10
 * @return string   The mail message to send.

11
 */
12
public function replace_retrieve_password_message( $message, $key, $user_login, $user_data ) {
13
    // Create new message

14
    $msg  = __( 'Hello!', 'personalize-login' ) . "\r\n\r\n";
15
    $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";
16
    $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";
17
    $msg .= __( 'To reset your password, visit the following address:', 'personalize-login' ) . "\r\n\r\n";
18
    $msg .= site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ) . "\r\n\r\n";
19
    $msg .= __( 'Thanks!', 'personalize-login' ) . "\r\n";
20
21
    return $msg;
22
}

La función recibe cuatro parámetros:

  • $message es la versión predeterminada del mensaje que se enviará al usuario. Ignoraremos este parámetro y crearemos nuestro propio texto desde cero.
  • $key es el token utilizado para verificar la solicitud de restablecimiento de contraseña del usuario. Debe estar incluido en el enlace de restablecimiento de contraseña.
  • $ user_login es el nombre de usuario del usuario (en nuestro caso, dirección de correo electrónico), también se necesita en el enlace de restablecimiento de contraseña.
  • $ user_data contiene algunos datos sobre el usuario. Vamos a ignorar esto por ahora, pero puedes explorarlo más en tu propia personalización si quieres.

La mayor parte de la función solo crea un mensaje como una serie de concatenaciones de cadenas. La URL para completar el restablecimiento de contraseña se crea en la línea 18 .

Para una personalización más completa, una idea sería agregar un campo de configuración para editar el contenido del mensaje de recuperación de contraseña y usarlo en lugar de codificar el mensaje dentro de la función de esta manera.

Si lo deseas, puedes usar el filtro retrieve_password_title para reemplazar el título del mensaje de correo electrónico de la misma manera. La función de filtro toma un parámetro, el título predeterminado que se enviará al usuario, y debe devolver el nuevo título.

Otra forma de personalizar aún más es reemplazar todo el mensaje y enviar un mensaje HTML en su lugar, por ejemplo, utilizando el método que expliqué en un tutorial anterior sobre el uso de Mandrill para enviar mensajes de correo electrónico desde WordPress . En este caso, usaría la API de Mandrill para enviar el mensaje en la función de filtro anterior y devolvería falso para que WordPress no intentara enviar el correo electrónico nuevamente.

Ya has completado el primer paso en el procedimiento de restablecimiento de contraseña: el usuario puede solicitar restablecer la contraseña y WordPress inicia el proceso.

A continuación, veremos qué sucede cuando el usuario hace clic en el enlace en el correo electrónico de restablecimiento de contraseña.

Restablecer contraseña

Como vimos anteriormente, después de iniciar un restablecimiento de contraseña, el usuario es redirigido a la página de inicio de sesión, con instrucciones para verificar su correo electrónico.

En ese correo electrónico, hay un enlace de regreso a wp-login.php con los parámetros login y una key para identificar al usuario y verificar la solicitud de restablecimiento de contraseña. Cuando el usuario hace clic en el enlace, WordPress verifica al usuario y la clave de validez, y luego, si todo está bien, le permite al usuario establecer una nueva contraseña.

La funcionalidad funciona bien, y utilizaremos partes de ella, llamando a funciones de ayuda existentes en wp-login.php , pero de nuevo, debido a la forma en que las acciones y los filtros están organizados en el código de restablecimiento de contraseña, tendremos que reescribir algunos del código para poder completar la personalización.

Paso 1: Redirigir al usuario a una página personalizada

Primero, comenzaremos redireccionando al usuario a nuestra propia página de restablecimiento de contraseña (que creamos al comienzo de este tutorial).

A estas alturas, probablemente te resulte familiar: del mismo modo que lo hicimos en las acciones de inicio de sesión y registro, así como en la primera página del flujo de restablecimiento de contraseña, usaremos la acción login_form_ {action} para desviar la acción de restablecimiento de contraseña. a nuestras propias funciones personalizadas antes de que WordPress llegue a hacer algo.

Hay dos acciones de wp-login.php que se usan para la misma funcionalidad, rp y resetpass, por lo que necesitaremos redirigirlas a la misma función, redirect_to_custom_password_reset.

En el constructor del complemento, agrega las siguientes líneas:

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

Luego, crea la función:

1
/**

2
 * Redirects to the custom password reset page, or the login page

3
 * if there are errors.

4
 */
5
public function redirect_to_custom_password_reset() {
6
    if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
7
        // Verify key / login combo

8
        $user = check_password_reset_key( $_REQUEST['key'], $_REQUEST['login'] );
9
        if ( ! $user || is_wp_error( $user ) ) {
10
            if ( $user && $user->get_error_code() === 'expired_key' ) {
11
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
12
            } else {
13
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
14
            }
15
            exit;
16
        }
17
18
        $redirect_url = home_url( 'member-password-reset' );
19
        $redirect_url = add_query_arg( 'login', esc_attr( $_REQUEST['login'] ), $redirect_url );
20
        $redirect_url = add_query_arg( 'key', esc_attr( $_REQUEST['key'] ), $redirect_url );
21
22
        wp_redirect( $redirect_url );
23
        exit;
24
    }
25
}

La función comienza comprobando que se trata de una solicitud GET. Las solicitudes POST enviadas a esta misma URL se tratarán a continuación.

Luego, en la línea 8 , llamamos a la función WordPress check_password_reset_key para verificar que los parámetros pasados ​​con el enlace de restablecimiento de contraseña sean válidos. Si hubo un error, redirigimos al usuario a la página de inicio de sesión, con el código de error como parámetro de solicitud (líneas 9-16). Agregaremos el código para mostrar el error pronto.

Si los parámetros se validaron con éxito y el usuario puede actualizar su contraseña, la función continúa al redireccionar al usuario a nuestra página de restablecimiento de contraseña personalizada (aún vacía), member-password-reset.

En las líneas 19-20, agregamos los parámetros key y login a la URL de redireccionamiento para que estén disponibles para otra verificación cuando el usuario intente establecer una nueva contraseña en la pantalla siguiente. La versión predeterminada del restablecimiento de contraseña de WordPress usa una cookie para esto, pero para el tutorial, decidí ir con los parámetros de solicitud para mantener el código más fácil de seguir.

A continuación, creemos una versión personalizada del formulario de restablecimiento de contraseña.

Paso 2: Mostrar el formulario Restablecer contraseña

El formulario de restablecimiento de contraseña que se muestra al usuario después de hacer clic en el enlace recibido en el correo electrónico, por defecto se ve así:

WordPress Reset Password screenWordPress Reset Password screenWordPress Reset Password screen

Es un formulario simple con dos campos, pass1 y pass2, uno para ingresar la contraseña y el otro para volver a escribirlo y verificar que no haya errores tipográficos.

Para crear nuestra versión personalizada de este formulario, utilizaremos un código breve.

Primero, agrega la siguiente línea en el constructor del complemento:

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

A continuación, crea la función para representar el formulario:

1
/**

2
 * A shortcode for rendering the form used to reset a user's password.

3
 *

4
 * @param  array   $attributes  Shortcode attributes.

5
 * @param  string  $content     The text content for shortcode. Not used.

6
 *

7
 * @return string  The shortcode output

8
 */
9
public function render_password_reset_form( $attributes, $content = null ) {
10
    // Parse shortcode attributes

11
    $default_attributes = array( 'show_title' => false );
12
    $attributes = shortcode_atts( $default_attributes, $attributes );
13
14
    if ( is_user_logged_in() ) {
15
        return __( 'You are already signed in.', 'personalize-login' );
16
    } else {
17
        if ( isset( $_REQUEST['login'] ) && isset( $_REQUEST['key'] ) ) {
18
            $attributes['login'] = $_REQUEST['login'];
19
            $attributes['key'] = $_REQUEST['key'];
20
21
            // Error messages

22
            $errors = array();
23
            if ( isset( $_REQUEST['error'] ) ) {
24
                $error_codes = explode( ',', $_REQUEST['error'] );
25
26
                foreach ( $error_codes as $code ) {
27
                    $errors []= $this->get_error_message( $code );
28
                }
29
            }
30
            $attributes['errors'] = $errors;
31
32
            return $this->get_template_html( 'password_reset_form', $attributes );
33
        } else {
34
            return __( 'Invalid password reset link.', 'personalize-login' );
35
        }
36
    }
37
}

El núcleo de esta función comienza en la línea 17, donde verificamos que los parámetros de identificación del usuario, inicio de sesión y la clave estén presentes. De lo contrario, el enlace de restablecimiento de contraseña no es válido, y solo presentamos un mensaje de error (línea 34).

Si la comprobación es correcta, las dos variables se agregan a la matriz $attributes para que estén disponibles para la plantilla de formulario (líneas 18-19).

Luego, en las líneas 21-30, ya nos preparamos para los errores que pueden ocurrir cuando se envía el formulario, utilizando el mismo método de aprobación de errores de los formularios anteriores en el tutorial.

Finalmente, en la línea 32, la función lee la plantilla y la devuelve a WordPress para su representación.

Vamos a crear la siguiente plantilla. En el directorio templates, crea un nuevo archivo y asígnale el nombre password_reset_form.php . Agrega el siguiente contenido:

1
<div id="password-reset-form" class="widecolumn">
2
    <?php if ( $attributes['show_title'] ) : ?>
3
        <h3><?php _e( 'Pick a New Password', 'personalize-login' ); ?></h3>
4
    <?php endif; ?>
5
6
    <form name="resetpassform" id="resetpassform" action="<?php echo site_url( 'wp-login.php?action=resetpass' ); ?>" method="post" autocomplete="off">
7
        <input type="hidden" id="user_login" name="rp_login" value="<?php echo esc_attr( $attributes['login'] ); ?>" autocomplete="off" />
8
        <input type="hidden" name="rp_key" value="<?php echo esc_attr( $attributes['key'] ); ?>" />
9
        
10
        <?php if ( count( $attributes['errors'] ) > 0 ) : ?>
11
            <?php foreach ( $attributes['errors'] as $error ) : ?>
12
                <p>
13
                    <?php echo $error; ?>
14
                </p>
15
            <?php endforeach; ?>
16
        <?php endif; ?>
17
18
        <p>
19
            <label for="pass1"><?php _e( 'New password', 'personalize-login' ) ?></label>
20
            <input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" />
21
        </p>
22
        <p>
23
            <label for="pass2"><?php _e( 'Repeat new password', 'personalize-login' ) ?></label>
24
            <input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
25
        </p>
26
        
27
        <p class="description"><?php echo wp_get_password_hint(); ?></p>
28
        
29
        <p class="resetpass-submit">
30
            <input type="submit" name="submit" id="resetpass-button"
31
                   class="button" value="<?php _e( 'Reset Password', 'personalize-login' ); ?>" />
32
        </p>
33
    </form>
34
</div>

El formulario comienza con un título opcional, que se muestra si el atributo shortcode show_title se establece en verdadero  líneas 2-4).

La forma actual sigue justo después del título. Ten en cuenta que el formulario se publicará en wp-login.php?action=resetpass (línea 6), la misma URL utilizada en el enlace en el correo electrónico de restablecimiento de contraseña, excepto que el enlace de correo electrónico utilizó una versión corta, rp , en lugar de resetpass.

Al principio del formulario (líneas 7-8), configuramos dos campos ocultos rp_key y rp_login para pasar los parámetros login y key al controlador de formulario que los usará para validar la solicitud de cambio de contraseña.

En las líneas 10-16, la plantilla mostrará errores en caso de haberlos. Este código es exactamente igual al de la plantilla anterior de  este tutorial.

Los dos campos se imprimen en las líneas 18-25, seguido por algunas instrucciones para elegir una buena contraseña y el botón para enviar el formulario.

Así es como debería verse el formulario ahora:

Custom Reset Password screenCustom Reset Password screenCustom Reset Password screen

Paso 3: Controlar la acción de restablecer contraseña

Cuando el usuario envía el formulario haciendo clic en el botón Restablecer contraseña, sus contenidos se envían a wp-login.php?action=resetpass, la misma URL que hemos usado arriba para redirigir al usuario a nuestra página de restablecimiento de contraseña personalizada.

Naturalmente, como hemos creado el formulario, nosotros mismos, sólo así podríamos utilizar una URL diferente. Sin embargo, por mantener esta dirección URL predeterminada y usar la acción login_form_resetpass (y login_form_rp, sólo para estar seguro) para sustituir la funcionalidad por defecto, podemos asegurarnos que nadie llame accidentalmente a la versión predeterminada del restablecimiento de contraseña.

Para ello, una vez más, agrega dos líneas al constructor:

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

A continuación, crea la función:

1
/**

2
 * Resets the user's password if the password reset form was submitted.

3
 */
4
public function do_password_reset() {
5
    if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
6
        $rp_key = $_REQUEST['rp_key'];
7
        $rp_login = $_REQUEST['rp_login'];
8
9
        $user = check_password_reset_key( $rp_key, $rp_login );
10
11
        if ( ! $user || is_wp_error( $user ) ) {
12
            if ( $user && $user->get_error_code() === 'expired_key' ) {
13
                wp_redirect( home_url( 'member-login?login=expiredkey' ) );
14
            } else {
15
                wp_redirect( home_url( 'member-login?login=invalidkey' ) );
16
            }
17
            exit;
18
        }
19
20
        if ( isset( $_POST['pass1'] ) ) {
21
            if ( $_POST['pass1'] != $_POST['pass2'] ) {
22
                // Passwords don't match

23
                $redirect_url = home_url( 'member-password-reset' );
24
25
                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
26
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url )
27
                $redirect_url = add_query_arg( 'error', 'password_reset_mismatch', $redirect_url );
28
29
                wp_redirect( $redirect_url );
30
                exit;
31
            }
32
33
            if ( empty( $_POST['pass1'] ) ) {
34
                // Password is empty

35
                $redirect_url = home_url( 'member-password-reset' );
36
37
                $redirect_url = add_query_arg( 'key', $rp_key, $redirect_url );
38
                $redirect_url = add_query_arg( 'login', $rp_login, $redirect_url );
39
                $redirect_url = add_query_arg( 'error', 'password_reset_empty', $redirect_url );
40
41
                wp_redirect( $redirect_url );
42
                exit;
43
            }
44
45
            // Parameter checks OK, reset password

46
            reset_password( $user, $_POST['pass1'] );
47
            wp_redirect( home_url( 'member-login?password=changed' ) );
48
        } else {
49
            echo "Invalid request.";
50
        }
51
52
        exit;
53
    }
54
}

La función comienza marcando el método de la petición, que debe ser puesto; POST; las solicitudes GET ya han sido manipulados por la función de redirección arriba.

Luego, recoge los parámetros key y login de los datos del formulario y los utiliza para verificar el enlace de restablecimiento de la contraseña en la línea 9, con la función check_password_reset_key de WordPress (la misma función que hemos utilizado ya en la función de redirección).

En las líneas del 10-18, otra vez comprobamos posibles errores en la verificación de clave de restablecimiento de contraseña, redireccionamos al usuario a la página ¿perdiste tu contraseña? para mostrar los errores.

Entonces, si la clave reset es válida, podemos centramos en el formulario.

En primer lugar, la función comprueba que las dos contraseñas coinciden (líneas 21-31) y luego que ellos no están vacíos (líneas 33-43). En ambos casos, se redirige al usuario a nuestra página de restablecimiento de contraseña, con los parámetros key y login en la URL para que el usuario vuelva a intentar la actualización de la contraseña.

Finalmente, si todas las comprobaciones son exitosas (siéntete libre de agregar más comprobaciones si lo deseas), la función restablece la contraseña utilizando la función reset_password (en la línea 46) y redirige al usuario a la página de inicio de sesión con un parámetro password=changed agregado al URL para mostrar una notificación.

La contraseña se ha actualizado con éxito, y todo lo que queda es mostrar la notificación de éxito y agregar mensajes de error.

En primer lugar, vamos a agregar la notificación. En la función shortcode render_login_form agrega la siguiente comprobación:

1
// Check if user just updated password

2
$attributes['password_updated'] = isset( $_REQUEST['password'] ) && $_REQUEST['password'] == 'changed';

Luego, agrega el mensaje a la plantilla, login_form.php, justo antes de mostrar el formulario:

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

Como ya has añadido soporte para los mensajes de error por encima, todo lo que queda de la representación es agregar los mensajes de error descriptivos a nuestra función get_error_message.

Agrega las siguientes líneas justo antes de la rama default en el constructor switch...case:

1
// Reset password

2
3
case 'expiredkey':
4
case 'invalidkey':
5
    return __( 'The password reset link you used is not valid anymore.', 'personalize-login' );
6
7
case 'password_reset_mismatch':
8
    return __( "The two passwords you entered don't match.", 'personalize-login' );
9
    
10
case 'password_reset_empty':
11
    return __( "Sorry, we don't accept empty passwords.", 'personalize-login' );

Conclusión

¡Eso es todo! La funcionalidad de restablecimiento de contraseña está lista, y por lo tanto, hemos terminado de personalizar la experiencia de inicio de sesión de WordPress para registrar un nuevo usuario, para iniciar sesión y restablecer una contraseña perdida.

Espero que la serie te haya dado herramientas suficientes para que te sientas bien equipado para otras personalizaciones, por ejemplo para la adición de un nuevo paso con la contraseña y restablecer el flujo — y un mejor entendimiento de lo que sucede dentro de wp-login.php.

¡Ahora, ve y personaliza algo más!