Using WP Approve User Plugin with WooCommerce
As the WP Approve User plugin appears to not have been maintained for 3 years, I’ve written a new guide to integrate WooComm with the New User Approve plugin instead, which is somewhat better maintained.
WooCommerce is the newest and arguably the best E-Commerce solution available for WordPress. If you aren’t considering using it for your next E-Commerce website, you should seriously rethink your E-Commerce strategy.
In the process of building a new wholesaler website, there were two key modifications that needed to be completed to WooCommerce in order to make it work for the customer’s business:
- New users (distributors) must be able to be moderated by an admin so the site owner can choose to approve or reject them as distributors of their product
- Visitors must be blocked from seeing pricing and adding items to their cart until they have been registered and approved
Catalog Visibility
At the outset this seemed easy enough thanks to some great plugins. In order to hide pricing and block adding items to the cart for users that are not logged in, WooCommerce already has a fantastic (albeit paid – $35) plugin called Catalog Visibility Options. This plugin worked perfectly for what we needed using just a couple drop downs. What it doesn’t do (nor does it claim to do) is manage user registrations – the other half of the puzzle.
User Moderation
User moderation turned out to be a more difficult task. Although the WP Approve User plugin is a well devised addition to WordPress, the custom registration and login capabilities of WooCommerce do not play nicely with plugins that use registration and login hooks. Additionally, WooCommerce has some great email notifications built in, whereas WP Approve User does not do any at all! (This could be for the best – in the end, unification of notifications is likely only possible using one system).
Upon installing WP Approve User, the first problem I ran into went like this:
- User registers
- WooCommerce automatically logs them in [PROBLEM]
- If the user logs out, they can’t get in again since they have yet to be approved
Removing / working around auto login
So at this point, the registration is not obeying the WP Approve User plugin when it automatically logs the user in, but the login form *is* obeying the hooks provided by WP Approve User. In order to fix this automatic login during registration, I wrote the following hooks to be placed in your theme’s functions.php file:
function user_autologout(){ if ( is_user_logged_in() ) { $current_user = wp_get_current_user(); $user_id = $current_user->ID; $approved_status = get_user_meta($user_id, 'wp-approve-user', true); //if the user hasn't been approved yet by WP Approve User plugin, destroy the cookie to kill the session and log them out if ( $approved_status == 1 ){ return $redirect_url; } else{ wp_logout(); return get_permalink(woocommerce_get_page_id('myaccount')) . "?approved=false"; } } } add_action('woocommerce_registration_redirect', 'user_autologout', 2); function registration_message(){ $not_approved_message = '<p class="registration">Send in your registration application today!<br /> NOTE: Your account will be held for moderation and you will be unable to login until it is approved.</p>'; if( isset($_REQUEST['approved']) ){ $approved = $_REQUEST['approved']; if ($approved == 'false') echo '<p class="registration successful">Registration successful! You will be notified upon approval of your account.</p>'; else echo $not_approved_message; } else echo $not_approved_message; } add_action('woocommerce_before_customer_login_form', 'registration_message', 2);
This accomplishes two things. It takes care of making sure the user is logged out immediately after WooCommerce logs them in, and second it notifies the user that their registration completed successfully, but they cannot login until they have been approved. The successful registration notification was never needed by WooCommerce because it normally just logs them right into their account – something we can’t do in this case.
Notification Emails
[Update Feb 6, 2014: WP Approve User now has the ability to set the notification emails in the WordPress UI under Settings > Approve User. The only reason you might wish to use the instructions below rather than the built in UI elements is if you really want to make use of the WooCommerce email design style when sending out the messages.]
Next up I discovered that WP Approve User has a couple of Action Hooks we can plug in to for sending out notification emails. Although I didn’t make use of the unapprove hook, you can easily duplicate my existing work to make that happen if you wish.
You will want to first do as WooCommerce suggests: “For more advanced control copy woocommerce/templates/emails/ to yourtheme/woocommerce/emails/.”
Once you’ve’ copied the templates for safe keeping, head to yourtheme/woocommerce/emails and edit the customer-new-account.php file. You will want this to say that the account has been held for moderation. This means upon user registration, an email with credentials is sent out, but the registrant is again informed that they cannot login immediately.
We also need an email template that is sent when the user is approved by an admin. In yourtheme/woocommerce/emails, create a file called customer-account-approved.php and paste the following in:
<?php if (!defined('ABSPATH')) exit; ?> <?php do_action('woocommerce_email_header', $email_heading); ?> <p><?php echo sprintf(__("Good news! Your account has been approved. You can now login here: %s.", 'woocommerce'), get_permalink(woocommerce_get_page_id('myaccount'))); ?></p> <ul> <li><?php echo sprintf(__('Username: %s', 'woocommerce'), $user_login); ?></li> <li><?php echo sprintf(__('Password: %s', 'woocommerce'), $user_pass); ?></li> </ul> <p><?php echo sprintf(__("Thanks for registering with %s!", 'woocommerce'), $blogname); ?></p> <div style="clear:both;"></div> <?php do_action('woocommerce_email_footer'); ?>
Now that we’ve got our email templates ready to roll, we need an action hook to send off the approval email when the admin clicks “approve” for any user. Again, enter the following in your theme’s functions.php file:
//Email Notifications //Content parsing borrowed from: woocommerce/classes/class-wc-email.php function send_user_approve_email($user_id){ global $woocommerce; //Instantiate mailer $mailer = $woocommerce->mailer(); if (!$user_id) return; $user = new WP_User($user_id); $user_login = stripslashes($user->user_login); $user_email = stripslashes($user->user_email); $user_pass = "As specified during registration"; $blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES); $subject = apply_filters( 'woocommerce_email_subject_customer_new_account', sprintf( __( 'Your account on %s has been approved!', 'woocommerce'), $blogname ), $user ); $email_heading = "User $user_login has been approved"; // Buffer ob_start(); // Get mail template woocommerce_get_template('emails/customer-account-approved.php', array( 'user_login' => $user_login, 'user_pass' => $user_pass, 'blogname' => $blogname, 'email_heading' => $email_heading )); // Get contents $message = ob_get_clean(); // Send the mail woocommerce_mail( $user_email, $subject, $message, $headers = "Content-Type: text/htmlrn", $attachments = "" ); } add_action('wpau_approve', 'send_user_approve_email', 10, 1); function send_user_unapprove_email($user_id){ return; } add_action('wpau_unapprove', 'send_user_unapprove_email', 10, 1);
As I mentioned above, you can do the very same with unapprovals (see the empty function at the bottom?), but I didn’t really need to do so for this project. You would simply create another email template like above, then duplicate most of the approval function into the unapproval function, tweak as necessary and you’re all set!
I hope this helps anyone else trying to use the WP Approve Users plugin! Please leave your comments and suggestions along with any problems you may have encountered — I’d love to help!
If you found this guide helpful, please check out the other posts and guides we have on https://websavers.ca. We’re consultants for everything web, and ultra-fast hosting is what we do best. Keep us in mind for your next project needing shared web hosting or VPS hosting.
Posted in Code
About Websavers
Websavers provides web services like Canadian WordPress Hosting and VPS Hosting to customers all over the globe, from hometown Halifax, CA to Auckland, NZ.
If this article helped you, our web services surely will as well! We might just be the perfect fit for you.
Hi Jordan,
Amazing solution you have right here!
Thank you very much for the code and keeping this thread active!
I have added the code and most of it works just fine besides the below:
• We have 2 Approval emails being sent. Both the new woocommerce email as well as the User Approve plug-in default.
• We are still testing the check out etc.. but it seems a bit glitchy on the “Registration on Check out form”, shoukd it work the same or this solution just doesn’t cover the check out registration?!
Once again thank you very much… I spent literally for ever trying to sort this out!
Hey Gabriel,
I definitely haven’t covered any of the registration portion of the check out process with this. I think I would try to keep the two separate if I could (ie: two levels of customers; normal customers that don’t need to be approved and wholesale customers or something like that). I say this because a customer that just completed a payment probably shouldn’t be blocked from logging in, even if they’re limited to certain pricing or certain areas of the site because of this.
Isn’t there an option in the user approve plugin to disable outgoing emails for registration? I thought that was added in a more recent version of the plugin.
Thank you so much for this. I spent about 5 hours looking into possible solutions. You’re a life-saver!
No problem Katrina! Happy to help 🙂
Hi, I have followed your instructions. Everything seems to be working fine, EXCEPT… after someone has registered,
the “Registration successful! You will be notified upon approval of your account.” Does not show.
It shows the approved=false in the URL and refreshes the page but the text line doesnt change.
Can you please assist.
Thanks
(From the section: if ($approved == ‘false’) echo ‘Registration successful! You will be notified upon approval of your account.’;
else echo $not_approved_message;
}
else echo $not_approved_message;
}
Love this! Helped me alot!! Thank you.
Thank you, you are the man!!
Did you implement the second half of the guide regarding email notifications or did you use the wp approve user built in email notification system? It’s possible that my code for that part could mess with things, especially with the latest release of WooCommerce as that code is quite a bit older now.
Hey Jordan,
Thank you for this, it works like a dream. My only problem is that the admin does not receive notification of new users for approval. Is this easily done?
Thanks
H
Hi Jordan,
Thanks for the code. I’ve got it working but now my admin email isn’t receiving new user registrations anymore.
Could there be an issue with this?
Cheers
J.
Thank you for updating the code. It is really appreciated that you keep the code up to date…
THANKS!!
No problem! Happy to help 🙂
very thanks man
The solution for auto-logout was working well but doesn’t seem to be working the latest version of WordPress. Anyone else experiencing this issue? Any idea for a fix?
Hey ANerdsWorld, change $current_user = get_current_user(); to $current_user = wp_get_current_user();. It worked for me.
Thanks! I’ve updated this in the code above as well.
I have tried all of the solutions mentioned in this great article, but still seem to get a
Fatal error: Call to undefined function login_header() in /home/strutla/public_html/wp-content/plugins/new-user-approve/new-user-approve.php on line 538
after a user registers.
any thoughts?
I had the headers error messages as well, so here’s what I did – found where WooC calls the woocommerce_process_registration function – which was add_action(‘init’, woocommerce_process_registration’)
I then added the following:
remove_action(‘init’, ‘woocommerce_process_registration’);
add_action(‘init’, ‘wp_approve_registration’);
I created the function wp_approve_registration() and copied the code from the woocommerce_process_registration() function found in the file woocommerce-functions.php
I removed the following code from my new function:
// set the WP login cookie
$secure_cookie = is_ssl() ? true : false;
wp_set_auth_cookie($user_id, true, $secure_cookie);
And replaced it with the message code from Klang:
$woocommerce->add_message( ‘Registration successful! You will be notified upon approval of your account.’, ‘woocommerce’ ) ;
And voila! I think it’s working…
Thanks for the tip Elle! It certainly sounds like it should do the trick 🙂
This solution works for the initial login but once I navigate away from the account page, I’m logged out again. Any ideas?
Thanks for the idea. This help me a lot.
For the problem with a lot of “Cannot modify header information” errors, I’ve figured it out.
The hook “woocommerce_before_my_account” is inside the my account page which already been output some code to the browser, so that the function wp_logout() will NOT work.
My quick dirty solution is to change some code in woocommerce-functions.php. (you should do this as a hook instead, but I don’t have time)
In the function woocommerce_process_registration(), comment out this line:
wp_set_auth_cookie($user_id, true, $secure_cookie);
Boom! No more auto-login.
For the custom message, add this line after the one we just comment out:
$woocommerce->add_message( ‘Registration successful! You will be notified upon approval of your account.’, ‘woocommerce’ ) ;
Hope this help!
Thanks Klang! I really appreciate the input as I haven’t had a lot of time to play with this and get the guide updated 🙂
Doesn’t removing the wp_set_auth_cookie then cause issues later when people are approved and trying to log in via the WooCommerce login page?
Hi Jordan,
Thanks for the tutorial.
But I had a hard time making it work with WooCommerce 2.0.13, in the end I had to change some things, mainly because wp_logout() was not logging out the unapproved users.
Once I have the time I will send you my changes.
Regards,
Gabriel
Hi Gabriel,
I’ve been meaning to run through this again and update it, so any input you can provide would be fantastic!
Thanks,
Jordan
Any update on this?
Thanks!
This is the code that I used:
/if the user hasn’t been approved yet by WP Approve User plugin, log them out immediately
if ( empty($approved_status) || $approved_status == 0 ){
//get the nonce value
$nonceUrl = wp_logout_url(get_bloginfo(‘url’));
$noncePos = strpos($nonceUrl, ‘_wpnonce=’) + strlen(‘_wpnonce=’);
$nonceVal = substr($nonceUrl, $noncePos);
//set request headers
$_REQUEST[‘action’] = ‘logout’;
$_REQUEST[‘redirect_to’] = home_url();
$_REQUEST[‘_wpnonce’] = $nonceVal;
//code from wp-login
check_admin_referer(‘log-out’);
wp_logout();
$redirect_to = !empty( $_REQUEST[‘redirect_to’] ) ? $_REQUEST[‘redirect_to’] : ‘wp-login.php?loggedout=true’;
wp_safe_redirect( $redirect_to );
exit();
}
Hi Jordan,
I’m interested to know the price required to enable this in my woocommerce.
Thanks
Simone
Hi! I tried everything, and nothing seems to work. Can you provide a paid support?
Hi Daniel,
Yes we certainly can! Check out our service FixMyWebsite.
Thanks for the response Jordan, unfort the first fix didnt work and the debugging is a little over my head in terms of what your asking for. Can I email you my site domain?
I tried the code and it does not stop the approval because it automatically takes the user to their account. Any ideas?
Brad,
I just updated the code using Mike’s suggestion above. The key change is in this line:
$approved_status = get_user_meta($user_id, ‘pw_user_status’, true);
Replace pw_user_status with wp-approve-user and you should be all set.
Jordan,
Unfort that didnt do the trick, i sign in and it take you to the “account page.” What should display after they enter in their details? Any other ideas?
I’m afraid the site I set this up for is not currently being used, so I don’t have a live test bed to experiment with this. That said, I found another part which could have been problematic but should no longer be so:
if ( empty($approved_status) || $approved_status == 0 )
Why the change to empty() rather than !isset()? According to the WordPress Codex, get_user_meta() returns an empty string if no such meta is found. But isset() only checks if the variable is set at all. No matter what happens with get_user_meta(), it’s going to return something, either 1,0, or an empty string, so we need to be sure the conditional handles all possible values accurately. It is not possible for $approved_status to be not set at this point, so checking for isset() is useless.
If that change still doesn’t work, it’s time for some debugging!
Everything that manages the functionality you’re referring to (where it auto-logs the user in, and we’re trying to prevent this) is in the function user_autologout. I’ll point out some areas you could do some debug logging that should point you in the right direction.
1) $approved_status = get_user_meta($user_id, ‘wp-approve-user’, true);
This is the first likely spot where something could be going wrong. We’re trusting that the WP-Approve-User plugin is setting this in the database properly. It could have three values: “” [empty string], 1 or 0. It should be the empty string by default. Once you login and approve the user it should be 1 and if you decide to revoke their approval, it probably sets it to 0 (though it may just make it empty again). Try putting in a debug line like:
error_log(“Status: $approved_status”, 0);
Refresh the page, then check your web server error log and see what it says.
2) if ( empty($approved_status) || $approved_status == 0 )
This could still be failing, but we should know why it’s failing once we know the value of $approved_status, so the info above is still your next troubleshooting step. Once we know the value of $approved_status, we can see why it’s failing to match this conditional.
It’s unlikely to be failing after this point because the immediate line following is the call to the logout function:
wp_logout();
This is a built in WordPress function, so you’d have to have one messed up WordPress install for that to be failing!
3) The final point of failure is in the WooCommerce action hook itself:
add_action(‘woocommerce_before_my_account’, ‘user_autologout’, 2);
If it’s failing to add the action, then the logout will never occur. Check to be sure woocommerce_before_my_account is still a valid hook location (which it appears to be). Also be sure that the registration page you’re using (and ultimately the login page which the registration form is redirecting to) is the WooCommerce registration page. If it’s not, then the registration form is not going to obey the WooCommerce ‘before_my_account’ hook.
—
I hope this helps! Be sure to let me know your results.
I had the same error messages above and was able to get it working.
Step 1: I noticed that lined 6 of user_autologout function code at top refers to user_meta ‘pw_user_status’. I did find this in the user meta table but found ‘wp-approve-user’ instead.
If it is 1 then the user is approved and null if not.
Step 2: I changed the if statement to:
if ( !isset($approved_status)
All appears to work now. Thanks for a great tip.
Thanks mike! Either the key changed in a recent update or I got it mixed up with another user approval plugin. Sorry for the trouble!
Appending ?approved=false results in the correct message being shown, so that’s all good.
And yes I’m using the designated area in functions.php.
Nothing that is relating to the functions file.. Any other suggestions?
I suggest putting some debug code in the hook function to be sure it’s being called when you load the page. For example, right after:
$approved_status = get_user_meta($user_id, ‘pw_user_status’, true);
Put something like: error_log(“Status: ” . $approved_status, 0)
Then try a new user registration. When the page loads and it logs you in automatically, check the web server or PHP error log and see what status it’s showing you. Then compare that against the conditional to see why it’s failing.
If you get nothing in the error log at all, then the hook is failing to run for some reason – you might need to ask the support forum for woocommerce about that. If the hook is running, then you’ll get some sort of output for the status which should help lead you to the problem.
I’ve tested multiple installations all resulting in the following errors (below) being displayed. These errors were not displayed on first install on the page, but in the error logs. But the second and third installs were attempted on a different server which displayed the errors on the page.
I tried with different themes as well – Sentient and Unsigned. No difference.
Well I’m pretty lost on what to do now, might have to post to the forum as well.
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 686
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 687
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 688
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 689
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 690
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 691
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 694
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 695
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 696
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 697
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 700
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 701
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 702
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 703
Warning: Cannot modify header information – headers already sent by (output started at /var/www/vhosts/~~website~~/wp-content/themes/sentient/header.php:15) in /var/www/vhosts/~~website~~/wp-includes/pluggable.php on line 866
Anthony, the updated code above should fix this by using a hook that runs before header info is output to the browser. Enjoy!
After looking at your posts on woothemes forum about the hooks, and seeing this post I thought I’d try it all out.
Sadly I ran into issues with the auto log out not working not performing (functions exactly the same as if I completely removed the auto login fix code from Sentients functions.php), when I log that test customer out and attempt a log in, it errors saying the user is not currently approved which is how it should be…
Test was with Sentient woocommerce theme (1.0), woocommerce (1.5.3), and WP Approve User (1.1.1).
There is no errors shown at all, the registration just logs the user in.
Any advice would be appreciated!
Anthony,
Hmm, that sounds like the hooks are not functioning for you. Let’s start by testing the message hook (the second one shown called registration_message). If you visit your registration page / my account page URL with “?approved=false” appended, what message do you see?
According to the woocommerce_before_customer_login_form hook (where we’ve hooked in the registration_message function), you should see:
“Registration successful! You will be notified upon approval of your account.”
If you don’t see this then even the second, more basic, hook isn’t working as it should be; perhaps there’s an error in your functions.php file? Are you using the designated area in the functions.php file that WooThemes specifies for adding your custom hooks? Do you see any errors in your web server error log?