Allow Email as Username within WP-Members Plugin

Today I figured out how to let people use their email to login instead of their username to the WordPress driven site called Jacked Pack. I had already installed the WP-Members plugin in order to add custom registration fields to the WordPress account page (for the “HUGEness profile”), but when I tried installing the WP Email Login plugin it didn’t have any effect. I figured this was because the WP-Members plugin already supercedes the regular login functionality, so I asked Chad Butler (who created the WP-Members plugin) about the issue.

Fortunately Chad had already created a way for people to add plugins to his plugin, so that’s what I ended up doing in this case. I followed his instructions by creating a file called wp-members-pluggable.php in my /wp-content/plugins directory and copying the wpmem-login function into it (I found that function in the wp-members-core.php file in the wp-members plugin folder). Then I added my own simple function (which was taken from the WP Email Login plugin) to get the username from an email address in case someone enters an email in the username field. Then I added just one line to the wpmem-login function which calls my function. Once I got that working, I copied the wpmem_inc_login function (which I found in the wp-members-dialogs.php file in the wp-members plugin folder) into my wp-members-pluggable.php file and changed one line to tell people they can use Username or Email in the first field.

See below for my complete plugin for the WP-Members WordPress Plugin, or download it here:

<?php
/**
 * WP-Members Pluggable Functions
 *
 * These functions replace those in the wp-members plugin
 * 
 */

if( ! function_exists( 'wpmem_login' ) ):
/**
 * Logs in the user
 *
 * Logs in the the user using wp_signon (since 2.5.2). If login 
 * is successful, it redirects and exits; otherwise "loginfailed"
 * is returned.
 *
 * @since 0.1
 *
 * @uses apply_filters Calls 'wpmem_login_redirect' hook to get $redirect_to
 *
 * @uses wp_signon
 * @uses wp_redirect Redirects to $redirect_to if login is successful
 * @return string Returns "loginfailed" if the login fails
 */
function wpmem_login()
{
	if( isset( $_POST['redirect_to'] ) ) {
		$redirect_to = $_POST['redirect_to'];
	} else {
		$redirect_to = $_SERVER['PHP_SELF'];
	}
	
	$redirect_to = apply_filters( 'wpmem_login_redirect', $redirect_to );

	if( isset( $_POST['rememberme'] ) == 'forever' ) {
		$rememberme = true;
	} else {
		$rememberme = false;
	}

	if( $_POST['log'] &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; $_POST['pwd'] ) {
		
		$user_login = sanitize_user( $_POST['log'] );

		$user_login = wpmem_login_check_for_email($user_login);
		
		$creds = array();
		$creds['user_login']    = $user_login;
		$creds['user_password'] = $_POST['pwd'];
		$creds['remember']      = $rememberme;
		
		$user = wp_signon( $creds, false );

		if( ! is_wp_error( $user ) ) {
			if( ! $using_cookie )
				wp_setcookie( $user_login, $user_pass, false, '', '', $rememberme );
			wp_redirect( $redirect_to );
			exit();
		} else {
			return "loginfailed";
		}
	
	} else {
		//login failed
		return "loginfailed";
	}	

} // end of login function
endif;


if ( ! function_exists( 'wpmem_login_check_for_email' ) ):
/**
 * Get Username from Email
 *
 * Takes the username and checks if there is a user with an email that matches.
 * 	If there is, the username associated with the email is returned.
 * 	Otherwise the username is returned as it was passed in.
 *
 * @uses get_user_by
 * @return string Returns username associated with email or the same
 * 	username that was passed in
 */
function wpmem_login_check_for_email($username) {
	if ( !empty( $username ) )
		$user = get_user_by( 'email', $username );
	if ( isset( $user->user_login, $user ) )
		$username = $user->user_login;
	return $username;
} // end of check for email in the username
endif;



if ( ! function_exists( 'wpmem_inc_login' ) ):
/**
 * Login Dialog
 *
 * Loads the login form for user login
 *
 * @since 1.8
 *
 * @uses apply_filters Calls wpmem_restricted_msg filters message content
 * @uses wpmem_login_form()
 *
 * @param string $page
 * @return string the generated html for the login form
 */
function wpmem_inc_login( $page="page" )
{ 	
	global $wpmem_regchk;

	$str = '';
	$arr = get_option( 'wpmembers_dialogs' );

	if( $page == "page" ){
	     if( $wpmem_regchk!="success" ){
		
			// this shown above blocked content
			$str = '<p>' . stripslashes($arr[0]) . '</p>';
			
			// filter blocked content message
			$str = apply_filters( 'wpmem_restricted_msg', $str );

		} 	
	} 

    //$arr = array( __( 'Existing users Login', 'wp-members' ), __( 'Username', 'wp-members' ), 'text', 'log', __( 'Password', 'wp-members' ), 'password', 'pwd', 'login', __( 'Login', 'wp-members' ), 'username', 'password' );
	$arr = array( __( 'Existing users Login', 'wp-members' ), __( 'Username or Email', 'wp-members' ), 'text', 'log', __( 'Password', 'wp-members' ), 'password', 'pwd', 'login', __( 'Login', 'wp-members' ), 'username', 'password' );
	
	$str = $str . wpmem_login_form( $page, $arr );
	return $str;
}
endif;
?>

Update July 5th, 2013

I was asked about the registration function as well (see comments from Brian Weiss below) and although I haven’t made a plugin for the WP-Members registration function I have done auto registrations in a separate file. I tried posting code in a comment and it didn’t turn out well, so here is the relevant code I used (in a separate php file I created in the wordpress directory) to auto create wordpress accounts based on their email and firstname (you could do it without using their name if you want, since the users will never need to know their username). If someone puts this into a plugin for the WP-Members registration function please let me know and I’ll link to it so others who want to do that can see the solution.

#Initial try at an unclaimed username
$username = $firstName.rand(1,1000);

#Now create a WP account
include('wp-config.php');

// Initialize connection and select database
mysql_connect(DB_HOST, DB_USER, DB_PASSWORD)
    or die('Could not connect: ' . mysql_error());
//echo 'Connected successfully';
mysql_select_db(DB_NAME) or die('Could not select database');
//echo "connected to db<br>";

#WP Username has to be unique
while (username_exists( $username )) {
	$username = $firstName.rand(1,1000);
}
$random_password = wp_generate_password( $length=12, $include_standard_special_chars=false );
//echo "about to create user $username with pwd $random_password and email $email<br>";
$user_id = wp_create_user( $username, $random_password, $email );
if (is_int($user_id)) {
	//echo "new user id is $user_id<br>";
} else {
    if(is_wp_error($user_id)) { echo $user_id->get_error_message(); }
    exit;
}
// then send a welcome email and/or redirect wherever you want...

Join the Conversation

27 Comments

  1. Thanks for this, was searching last week and found nothing, then saw this just in time.
    It worked a treat!

  2. Hi Robert, thanks for this solution! Saved a lot of time! I’ve just replaced the end of it for the new WP-Members 2.7.4 version, where it was “Existing users Login” Chad Butler changed it to “Existing Users Login”. That’s it, thanks again.

  3. Hi Robert. Great solution!!
    I have a question on it. Is it possible to register a new user only with its email?
    I need to register and log users only with email.
    Thank you in advance.

  4. Hi Alberto,
    I believe username is required in wordpress for people to have accounts, but you could try inserting the email into both fields (I’m not sure if the @ character is allowed in WP usernames though). What I did so people wouldn’t need to create a separate username is to create one behind the scenes using their first name and a random number (and making sure it was unique before adding it), then in the confirmation email I just tell them to login using their email address.
    Regards,
    Robert
    Robert recently posted..How to integrate existing website into Amazon Simple Email ServiceMy Profile

    1. I’m using the built in user generation function from WP-Members, and simply filtering the data that the plugin uses before it creates the user. It turns out that you can use an @ symbol in WordPress usernames (see WP codex for sanitize_user)

      Since the email address is (presumably) unique to the registrant, and since WP checks to see if an email address exists before creating a user, we can simply filter the registrant’s email address with sanatize_user and then apply that as the generated user name — no need to use first name and random numbers.

      We need then to remove the username field from the registration form, which can also be accomplished through filters.

      This approach also does not require overwriting any of the WP-Members built-in functions, allowing for easier/safer plugin auto-updates.

      Gist is here: https://gist.github.com/lucasbalzer/7010324

      1. Hi Lucas,

        I’ve been looking for a way to remove the username field from the registartion page and use the email instead and was happy to see you’d written the code for it as it’s beyond my ability! I’ve added your php file but it breaks the site and throws the error:

        “Parse error: syntax error, unexpected T_IF in /home/jodywhit/public_html/hourlogic/wp-content/plugins/wp-members-pluggable.php on line 38”

        Any ideas? Any help would be greatly appreciated!

        thanks

        J

        1. @Jody –
          My bad for posting code that wasn’t completely debugged. I actually had to make a couple of changes to the code and then didn’t update the file at GitHub. I’ve updated the GitHub gist to the most recent (and working) version I have.

          Please also note the requirement to include the simple DOM parser on line 56. Simply download that PHP file from http://simplehtmldom.sourceforge.net/ and place it in the same directory as wp-members-pluggable.php — it should automagically work.

          Let me know if you have any other questions! You can find my contact info at somadg.com/contact/

          1. Lucas you star!

            Thanks so much man, that worked a treat. Very happy face 🙂

            It’s people like you who write and share these extremely helpful little tidbits that keeps me coming back to wordpress again and again.

            Have a wicked day dude!

      2. Hi,
        Thanks for your code, works like a charm!
        Did you also find a way to remove the username field from the “forgot password”-form?
        Thanks in advance!

        1. That’s an excellent question! I also ran into that issue when doing unit testing (read here: I forgot the password on m own website and had to request it).

          Unfortunately, you can’t just get rid of one of the fields, since the password reset is built into the WP Members plugin.

          First, the function looks up the user by username, and then checks to see if the email address on file matches the address submitted in the form.

          Since the username is the email address, and I didn’t want to replace the reset function, I’ve solved the problem through an alternate labeling scheme on the reset form.

          To this end, I’ve modified the wpmem_login_form_filter function to check to see what form is being rendered, and to replace the label text accordingly.

          Now, on the reset form, the label ‘Username’ is replaced with ‘Email address’ and the label ‘Email’ is replaced with ‘Confirm email address’.

          This is a common pattern with email address fields, so it does not feel strange to type your address in twice.

          In actuality, what you’re doing is submitting your ‘user name’ and your ’email’, except they’re both the same in the database, so you need to type the same thing into each field. We’re just telling the user that they’re doing different things with each field.

          Link to the revised Gist is here.

          1. Thanks for the quick reply! That’s how I had done it, but if the users don’t enter their email address twice they get told that the password reset failed since their email address wasn’t recognised. Unfortunately, I couldn’t find a way to just set username=email after the form is submitted. That way one could just hide either one of the fields without having to modify the reset-function. Have you considered doing it that way? Do you think this might be an option? Or are we missing a hook/filter to do it? I have no experience as a developer, frankly.

        2. Your suggestion is a way better solution than what I had done. However, what you want to do only became available in the most recent update of the plugin, so send your thanks to Chad for adding so many hooks and filters. Anyway, the Gist is updated and sort of tested.

          1. Thank you so much, Lucas! Works perfectly fine and, together with your other modifications, makes the plugin so much more useful!

  5. This looks like exactly what I need but I am not a developer and don’t know how to take the PHP file you provided and deploy/install it successfully. Can you provide some guidance?

    1. Hi Brian,
      First you’ll need to install the WP Members plugin (see http://butlerblog.com/wp-members/wp-members-quick-start-guide/ for instructions) and then follow the instructions at http://butlerblog.com/2011/11/29/customizing-wp-members-with-pluggable-functions/ (look for “Getting Started” on that page) to create the file that you then can populate with the code I shared on this page. Does that help?
      Regards,
      Robert
      Robert recently posted..Google Maps API Version 3 Geocoding ExampleMy Profile

      1. Worked like a charm, thanks!

        So, now I have a login screen that only requires E-mail and Password.

        But what I also need is a register screen (what is displayed via the [wp-members page=”register”] shortcut) that similarly drops “Username” (which is a required field) and auto-generates a fictitious Username (e.g. firstname_lastname_randomnumber) so the registration process is e-mail based as well. Can we work similar magic there?

        1. Hi Brian,
          I’m sure that is possible but I haven’t done it myself. I think what I did for the Jacked Pack site was to auto-register people in wordpress when they first purchased something on the site. That was awhile ago though, they moved away from wordpress last year because their focus was on products instead of information (ie blog posts). There should be another function in the WP-Members plugin that can be modified to auto-create a semi-random username.
          Regards,
          Robert

          1. Thanks. I was able to find the equivalent registration function but it seems more complex. I can force a semi-random username that I create but I also have to adjust the form, and there are issues in the e-mails going out. In short, I think there are more dependencies here and it would need to be baked into a future version of WP-Members. Anyway, thanks again for your useful post here…

          2. Hi Brian,
            I dug up the code I used for registration and it was in a helper file outside of wordpress (because it was triggered by a 3rd party hosted shopping cart sign up). Here’s the relevant code I used to register people (in a separate file but in the same directory as wordpress since I used the wordpress functions), maybe this will help you (see update in the post above, code looks better there).
            Regards,
            Robert

          3. Thanks. Chad from WP-Members provided me with a great solution (via PHP code to include in functions.php) that make the e-mail address the user name and removes the username field from the registration form.

      1. I need to check with Chad. I think such enhancements should require paid membership for WP-Members (I think it goes without saying that anyone using WP-Members in a significant way should be paying Chad – but sometimes you have to provide additional incentive for folks to do the right thing…).

        Chad’s call… he’s been incredible about providing first-rate support…

Leave a comment

Your email address will not be published. Required fields are marked *

CommentLuv badge