WooCommerce lost password form on another page

Using the latest version of WooCommerce, I’m trying to get the lost password form to show up on several different pages. The problem is, copying the default form from woocommerce > templates > myaccount > form-lost-password.php and placing the code on another page would not work.

Here is the default code for the form:

Read More
<form method="post" class="lost_reset_password">

    <?php if( 'lost_password' == $args['form'] ) : ?>

        <p><?php echo apply_filters( 'woocommerce_lost_password_message', __( 'Lost your password? Please enter your username or email address. You will receive a link to create a new password via email.', 'woocommerce' ) ); ?></p>

        <p class="form-row form-row-first"><label for="user_login"><?php _e( 'Username or email', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="user_login" id="user_login" /></p>

    <?php else : ?>

        <p><?php echo apply_filters( 'woocommerce_reset_password_message', __( 'Enter a new password below.', 'woocommerce') ); ?></p>

        <p class="form-row form-row-first">
            <label for="password_1"><?php _e( 'New password', 'woocommerce' ); ?> <span class="required">*</span></label>
            <input type="password" class="input-text" name="password_1" id="password_1" />
        </p>
        <p class="form-row form-row-last">
            <label for="password_2"><?php _e( 'Re-enter new password', 'woocommerce' ); ?> <span class="required">*</span></label>
            <input type="password" class="input-text" name="password_2" id="password_2" />
        </p>

        <input type="hidden" name="reset_key" value="<?php echo isset( $args['key'] ) ? $args['key'] : ''; ?>" />
        <input type="hidden" name="reset_login" value="<?php echo isset( $args['login'] ) ? $args['login'] : ''; ?>" />

    <?php endif; ?>

    <div class="clear"></div>

    <p class="form-row">
        <input type="hidden" name="wc_reset_password" value="true" />
        <input type="submit" class="button" value="<?php echo 'lost_password' == $args['form'] ? __( 'Reset Password', 'woocommerce' ) : __( 'Save', 'woocommerce' ); ?>" />
    </p>

    <?php wp_nonce_field( $args['form'] ); ?>

</form>

And here’s what I’m using:

<form method="post" class="lost_reset_password">
  <h2 id="reset-h2">Recover your password</h2>
  <p id="reset-p">Please enter your email address below to receive a link where you can create a new password</p>
  <input class="input-text reset-email-password" type="text" name="user_login" id="user_login" placeholder="Enter your email"/>
  <input type="hidden" name="wc_reset_password" value="true" />
  <input type="submit" class="button submit-button custom-reset" value="<?php _e( 'Reset Password', 'woocommerce' ); ?>" />
  <a href="#" id="reset-back">Back</a>
  <?php wp_nonce_field( $args['form'] ); ?>
</form>

Notice that I stripped the else part because I only want the form where the user submits to get an email with a link to reset their password (which evidently would take you to the code the I’ve removed).

The only thing that I can think of why this isn’t working is because I’m missing the actions like <?php do_action( 'woocommerce_login_form_end' ); ?> but I wouldn’t know what the action I need for the lost password is.

Would love to get some help on this so let me know if I need to provide anything else, thanks!

Related posts

Leave a Reply

2 comments

  1. Try inserting this line of code into the template file where you want the form to show up:

    wc_get_template( 'myaccount/form-lost-password.php', array( 'form' => 'lost_password' ) );
    
  2. This maybe an old question, I run into the same problem but the accepted answer will just display the lost password form. After submitting your email address, it will go back to the default form which is located in my-account/lost-password.

    In my case, I want to remove the default lost password page or endpoint and use my custom page but I still want to use the default form.

    So, to completely show the lost password form, confirmation message, and new password form in another page;

    1: Remove the endpoint for Lost Password.
    Go to WooCoommerce > Settings > Advanced, then scroll to Account endpoints and you will see the Lost password. Just remove its value and save the settings.

    2: Change the URL of the default lost password to your new lost password page.
    Add the below hook into your functions.php, notice the /password-recovery, change it depending on the slug of your new lost password page..

    function wdm_lostpassword_url() {
      return site_url( '/password-recovery' );
    }
    add_filter( 'lostpassword_url', 'wdm_lostpassword_url', 10, 0 );
    

    3: Set where to redirect the user after successfully change the password.
    In my case, I wanted to redirect the user into sign-in page and add a notice message that he/she successfully change the password. Use the below hook to change it depending on your situation, but what ever url you set, make sure to add the query of new-password-created=true at the end of the url just like what I did at "/sign-in/?new-password-created=true".

    function woocommerce_new_pass_redirect( $user ) {
        wc_add_notice( __( 'Your password has been changed successfully! Please login to continue.', 'woocommerce' ), 'success' );
        wp_redirect( home_url() . "/sign-in/?new-password-created=true" );
        exit;
    }
    add_action( 'woocommerce_customer_reset_password', 'woocommerce_new_pass_redirect' );
    

    4: Create a shortcode for Lost Password Form.
    This is where the magic happened, use the below code to create the shortcode for lost password form. The default form of WooCoommerce still in used.

    //Create shortcode for lost password form [lost_password_form]
    function wc_custom_lost_password_form( $atts ) {
        if ( !empty( $_COOKIE[ "csx-reset-link-set" ] ) && isset( $_COOKIE[ "csx-reset-link-set" ] ) && $_COOKIE[ "csx-reset-link-set" ] === "true" ) { // WPCS: input var ok, CSRF ok.
            return wc_get_template( 'myaccount/lost-password-confirmation.php' );
        } elseif ( !empty( $_SESSION[ "csx-show-reset-form" ] ) && isset( $_SESSION[ "csx-show-reset-form" ] ) && $_SESSION[ "csx-show-reset-form" ] === "true" ) {
            $rp_id = $_SESSION[ "csx-id" ];
            $rp_key = $_SESSION[ "csx-key" ];
            if ( isset( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ) && 0 < strpos( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ], ':' ) ) { // @codingStandardsIgnoreLine
                list( $rp_id, $rp_key ) = array_map( 'wc_clean', explode( ':', wp_unslash( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ), 2 ) ); // @codingStandardsIgnoreLine
                $userdata = get_userdata( absint( $rp_id ) );
                $rp_login = $userdata ? $userdata->user_login : '';
                $user = WC_Shortcode_My_Account::check_password_reset_key( $rp_key, $rp_login );
    
                // Reset key / login is correct, display reset password form with hidden key / login values.
                if ( is_object( $user ) ) {
                    return wc_get_template(
                        'myaccount/form-reset-password.php',
                        array(
                            'key' => $rp_key,
                            'login' => $rp_login,
                        )
                    );
                }
            }
        }
    
        // Show lost password form by default.
        return wc_get_template(
            'myaccount/form-lost-password.php',
            array(
                'form' => 'lost_password',
            )
        );
    }
    add_shortcode( 'lost_password_form', 'wc_custom_lost_password_form' );
    
    //Handling query
    function csx_process_query() {
    
        if ( isset( $_GET[ 'reset-link-sent' ] ) && $_GET[ 'reset-link-sent' ] === "true" ) {
            setcookie( 'csx-reset-link-set', "true", time() + ( 300 * 1 ), "/" ); //Allow to submit email for reset after 5 minutes only.
            unset( $_SESSION[ "csx-show-reset-form" ] );
        }
    
        if ( isset( $_GET[ 'show-reset-form' ] ) && $_GET[ 'show-reset-form' ] === "true" ||
            isset( $_GET[ 'key' ] ) && isset( $_GET[ 'id' ] ) ) {
            $_SESSION[ "csx-show-reset-form" ] = "true";
            setcookie( 'csx-reset-link-set', "", time() - 3600, "/" );
        }
    
        //Set session and cookie if key and id are existed
        if ( isset( $_GET[ 'key' ] ) && isset( $_GET[ 'id' ] ) ) {
            $_SESSION[ "csx-key" ] = $_GET[ 'key' ];
            $_SESSION[ "csx-id" ] = $_GET[ 'id' ];
    
            $value = sprintf( "%s:%s", wp_unslash( $_GET[ 'id' ] ), wp_unslash( $_GET[ 'key' ] ) );
            WC_Shortcode_My_Account::set_reset_password_cookie( $value );
        }
    
        //Unset session and cookie after successfully changed the password.
        if ( isset( $_GET[ 'new-password-created' ] ) && $_GET[ 'new-password-created' ] === "true" ) {
            setcookie( 'wp-resetpass-' . COOKIEHASH, "", time() - 3600 );
            unset( $_SESSION[ "csx-show-reset-form" ] );
            unset( $_SESSION[ "csx-reset-link-set" ] );
            unset( $_SESSION[ "csx-id" ] );
            unset( $_SESSION[ "csx-key" ] );
        }
    }
    add_action( 'init', 'csx_process_query' );
    
    //Redirect to custom lost password on request
    function csx_redirections() {
        if ( isset( $_GET[ 'reset-link-sent' ] ) || isset( $_GET[ 'show-reset-form' ] ) ||
            isset( $_GET[ 'key' ] ) && isset( $_GET[ 'id' ] ) ) {
            wp_redirect( home_url() . '/password-recovery' );
            exit;
        }
    }
    add_action( 'template_redirect', 'csx_redirections' );
    

    You can now use the ShortCode [lost_password_form], just put it into your page and the form should be shows up. Notice that you need to change the slug of password-recovery.

    5: Change the URL in the email message that send to users when they request for lost password.
    Override the templates located at woocommerce/templates/emails/customer-reset-password.php and woocommerce/templates/emails/plain/customer-reset-password.php.

    Here’s an example for plain email message;

    <?php
    /**
     * Customer Reset Password email
     *
     * This template can be overridden by copying it to yourtheme/woocommerce/emails/plain/customer-reset-password.php.
     *
     * HOWEVER, on occasion WooCommerce will need to update template files and you
     * (the theme developer) will need to copy the new files to your theme to
     * maintain compatibility. We try to do this as little as possible, but it does
     * happen. When this occurs the version of the template file will be bumped and
     * the readme will list any important changes.
     *
     * @see https://docs.woocommerce.com/document/template-structure/
     * @package WooCommerce/Templates/Emails/Plain
     * @version 3.7.0
     */
    
    defined( 'ABSPATH' ) || exit;
    
    echo "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=n";
    echo esc_html( wp_strip_all_tags( $email_heading ) );
    echo "n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=nn";
    
    /* translators: %s: Customer username */
    echo sprintf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ) . "nn";
    /* translators: %s: Store name */
    echo sprintf( esc_html__( 'Someone has requested a new password for the following account on %s:', 'woocommerce' ), esc_html( wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ) ) . "nn";
    /* translators: %s: Customer username */
    echo sprintf( esc_html__( 'Username: %s', 'woocommerce' ), esc_html( $user_login ) ) . "nn";
    echo esc_html__( 'If you didn't make this request, just ignore this email. If you'd like to proceed:', 'woocommerce' ) . "nn";
    echo esc_url( add_query_arg( array( 'key' => $reset_key, 'id' => $user_id ), home_url().'/your-custom-url/' ) ) . "nn"; // phpcs:ignore
    
    echo "nn----------------------------------------nn";
    
    /**
     * Show user-defined additional content - this is set in each email's settings.
     */
    if ( $additional_content ) {
        echo esc_html( wp_strip_all_tags( wptexturize( $additional_content ) ) );
        echo "nn----------------------------------------nn";
    }
    

    for non-plain email message;

    <?php
    /**
     * Customer Reset Password email
     *
     * This template can be overridden by copying it to yourtheme/woocommerce/emails/customer-reset-password.php.
     *
     * HOWEVER, on occasion WooCommerce will need to update template files and you
     * (the theme developer) will need to copy the new files to your theme to
     * maintain compatibility. We try to do this as little as possible, but it does
     * happen. When this occurs the version of the template file will be bumped and
     * the readme will list any important changes.
     *
     * @see https://docs.woocommerce.com/document/template-structure/
     * @package WooCommerce/Templates/Emails
     * @version 4.0.0
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit; // Exit if accessed directly.
    }
    
    ?>
    
    <?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    
    <?php /* translators: %s: Customer username */ ?>
    <p><?php printf( esc_html__( 'Hi %s,', 'woocommerce' ), esc_html( $user_login ) ); ?></p>
    <?php /* translators: %s: Store name */ ?>
    <p><?php printf( esc_html__( 'Someone has requested a new password for the following account on %s:', 'woocommerce' ), esc_html( wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ) ); ?></p>
    <?php /* translators: %s: Customer username */ ?>
    <p><?php printf( esc_html__( 'Username: %s', 'woocommerce' ), esc_html( $user_login ) ); ?></p>
    <p><?php esc_html_e( 'If you didn't make this request, just ignore this email. If you'd like to proceed:', 'woocommerce' ); ?></p>
    <p>
        <a class="link" href="<?php 
                              echo esc_url( add_query_arg( array( 'key' => $reset_key, 'id' => $user_id ), home_url()."/your-custom-url/" ) ); ?>"><?php // phpcs:ignore ?>
            <?php esc_html_e( 'Click here to reset your password', 'woocommerce' ); ?>
        </a>
    </p>
    
    <?php
    /**
     * Show user-defined additional content - this is set in each email's settings.
     */
    if ( $additional_content ) {
        echo wp_kses_post( wpautop( wptexturize( $additional_content ) ) );
    }
    
    do_action( 'woocommerce_email_footer', $email );
    

    Just change the url to your page. Note that you need to do it both in plain and non-plain email message.