Email validation with Ultimate Member Plugin - php

I need help modifying the code below. I'm using the Ultimate Member plugin on my Wordpress site for membership. I only want those people within my organization to be able to register for the site (my departments use different domains for their email addresses, it's a headache and I don't want to get into that). Right now, it will automatically validate emails from #company1.com, but I need to add up to 10 more email addresses to that code to perform automatic validation. Basically, anyone that doesn't have an email address listed, is automatically denied membership to the site.
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
if ( !strstr( $user_email, '#company1.com' ) )
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}

"um_before_new_user_register" has been removed from the 2.x version. You can use the below working code for complete form validation not just a single field.
add_action('um_submit_form_errors_hook_','um_custom_validate_form', 999, 1);
function um_custom_validate_form( $args ) {
global $ultimatemember;
$user_email = $args['user_email'];
if ( !strstr( $user_email, '#domain1.com' )){
$ultimatemember->classes['form']->add_error( 'user_email', 'You must register with a valid email address.' );
}
}

strstr() is more memory intensive compared to strpos(), so I will recommend using the latter. When dealing with an array, you can use the following iterative logic:
Set a variable, say $check, to false
Iterate through each allowed domain in a for loop
Whenever a match is found (by using strpos()), we set $check to true and break out of the loop. This ensures that we do not traverse the entire array when a match is already found
Evaluate $check, and decide whether to throw an error / exit
Hint: I would recommend converting your user-email to lowercase when using strpos (or you can use stripos()), because some users may enter emails that are of mixed cases.
With that in mind, here is an example:
<?php
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
// Store allowed domains in an array
$allowed_domains = ['#company1.com', '#company2.com', '#company3.com'];
// Set flag to false (fail-safe)
$check = false;
// Iterate through all allowed domains
foreach( $allowed_domains as $domain ) {
// If a match is found (remember to use lowercase emails!)
// Update flag and break out of for loop
if ( strpos( strtolower( $user_email ), $domain ) !== false ) {
$check = true;
break;
}
}
if ( !$check )
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}

Use this code:
<?php
add_action('um_before_new_user_register', 'require_google_email_for_signup');
function require_google_email_for_signup( $args ) {
extract($args);
/* add multiple domains name here */
$allow_domains = ['company1.com', 'company2.com', 'company3.com'];
/* get domain name from user email */
$domain_name = substr(strrchr($user_email, "#"), 1);
if (!in_array($domain_name, $allow_domains)){
exit( wp_redirect( add_query_arg('err', 'you_must_have_googlemail') ) );
}
}
?>

This custom code no longer works in the latest version 2 update to ultimate member. The hook was removed, so it’s no longer possible to do email address blocking with this code. Does anyone have any suggestions on how to get this to work again? Here is the code I'm using:
/* ULTIMATE MEMBER PLUGIN DOMAIN WHITELISTING CODE SNIPPET
enter code here`The following code will require a domain name to be
whitelisted for user `enter code here`registrations.
It forces a user email to match one included in this code at registration.
You can add any provider you want by copying and pasting a new line as per
instructions.*/
add_action('um_before_new_user_register', 'force_google_email_for_avnw_signup');
function force_google_email_for_avnw_signup( $args ) {
extract($args);
if ( !strstr( $user_email, '#anydomain.com' ) )
exit( wp_redirect( add_query_arg('err', 'whitelisted_email_required') ) );
}

Related

Woocommerce: Redirect after lost password submitted

I try to redirect my users to a custom page after successfully submitting the lost password form. By default, users are redirected to the "my-account" page.
The method responsible for doing this redirect is called process_lost_password() and is located in plugins/woocommerce/includes/class-wc-form-handler.php and looks like follows:
/**
* Handle lost password form.
*/
public static function process_lost_password() {
if ( isset( $_POST['wc_reset_password'] ) && isset( $_POST['user_login'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'lost_password' ) ) {
$success = WC_Shortcode_My_Account::retrieve_password();
// If successful, redirect to my account with query arg set.
if ( $success ) {
wp_redirect( add_query_arg( 'reset-link-sent', 'true', wc_get_account_endpoint_url( 'lost-password' ) ) );
exit;
}
}
}
Unfortunately, this method does not offer any action to hook into.
Is there a way to override this method or change the redirect link in any other way?
Since process_lost_password() is run as an 'wp_load' action
add_action( 'wp_loaded', array( __CLASS__, 'process_lost_password' ), 20 );
You simply need to add your own action with a higher priority
add_action( 'wp_loaded', 'your_handler', 19 );
I RESOLVED the issue by going under
WooCommerce
Emails****
Place your email in the box all the way to the bottom where it states From address because I am the administrator and Remove the admin email address.
I did a couple of dummy accounts and it work fine now all passwords work very well.
I created a page added the end points to /lost-password/ for my permalinks. Checked the custom header and checked the title boxes towards the middle of page and Published the page. That fixed the issue for me.

WooCommerce Memberships: Conditional to check a page access

I have a Wordpress Memberships website that is built on WooCommerce with WooCommerce Memberships plugin to restrict certain pages to members only.
Some of those pages are "drip-fed"... ie. Access to those pages opens 3 days after purchase, etc. I have set this up in WooMemberships.
I am trying to simply do a PHP conditional check to see if the current user has access to a certain page.
I have found this code piece in the docs: wc_memberships_is_post_content_restricted()
However, I have been unable to make it work.
Is there a code snippet which will basically do a PHP IF statement on whether the current user has access to a certain page (using page ID)?
eg:
if ( current_user_has_access(page_ID) ) { DO SOMETHING } else { DON'T }
Thanks.
I'm not sure if this helps but here is my take on it. I first go through all of the users active membership and then I check the content $rules to see if the restricted plans are a part of the users membership plans (in_array)
function can_user_access_content($user_id,$post_id){
//check if there's a force public on this content
if(get_post_meta($post_id,'_wc_memberships_force_public',true)=='yes') return true;
$args = array( 'status' => array( 'active' ));
$plans = wc_memberships_get_user_memberships( $user_id, $args );
$user_plans = array();
foreach($plans as $plan){
array_push($user_plans,$plan->plan_id);
}
$rules = wc_memberships()->get_rules_instance()->get_post_content_restriction_rules( $post_id );
foreach($rules as $rule){
if(in_array($rule->get_membership_plan_id(), $user_plans)){
return true;
}
}
return false;
}
Usage would be something like:
if(can_user_access_content(get_current_user_id(),$post->ID)){
//do whatever here
}
I'm dealing with the same issue at StoryMoment.com (we produce audio + eBook story series for kids).
This is how I've dealt with it. I use the following in a page template to show or hide page elements based on access. The wc_memberships_view_delayed_post_content would change based on the type of content.
You can see the other options in the file:
class-wc-memberships-capabilities.php
<?php
$has_access = current_user_can( 'wc_memberships_view_delayed_post_content', $post->ID );
if ($has_access) {
//do something
} else {
//do something else
}
?>
You will have to Replace (in the conditions):
$page_id by your page ID number (for example: is_page(42))
$membership_plan by the slug of the plan ('plan_slug') or related post ID.
The conditions:
wc_memberships_is_post_content_restricted($page_id) => true if $page_id is retracted.
is_page($page_id) => true if is actual $page_id.
wc_memberships_is_user_active_member( $membership_plan ) => true actual user is an active member for this $membership_plan plan. In that case the access to the page is granted by the suscription plan of the user.
You can remove some of the conditions, if not needed, and fine tune for your needs.
if( wc_memberships_is_post_content_restricted() && is_page($page_id) && wc_memberships_is_user_active_member( $membership_plan ) ) {
// do something
} else {
// don't
}
--- Update ---
The only function related to restriction and (or) time access are:
1) wc_memberships_restrict( $content, $membership_plans, $delay, $exclude_trial ) just like shortcode [wcm_restrict] (so not useful)…
2) wc_memberships_get_user_access_time( $user_id, $target, $action, $gmt ): Parameters
$user_id // for a logged 'user ID'
$target : array('post' => id, 'product' => id) // content_type and content_id
$action : 'view' or 'purchase' // Type of access (products only)<br>
$gmt => : true or false // (selection of the time zone)
// Returns user access start timestamp (in site timezone) for content or a product
Reference: WooCommerce Memberships Function Reference

Wordpress - create route to action in plugin

I want to create a route in my wordpress plugin that isn't linked to a page but to an action that sends an email. So i would send a get request like this
example.com/send/email?email=test#test.co.uk
and this would link to an action with the email as a parameter. I'm very new to Wordpress so forgive me if this is a stupid question but I'm really struggling to achieve this or evebn find a good starting point, can anyone help?
A good option in your case would be to use a rewrite endpoint. A rewrite endpoint allows you to add extra query parameters to certain URLs. For instance you can add a gallery endpoint to all posts, that could render a different template showing all images for the given post. More information about add_rewrite_endpoint() can be seen in the Codex.
Below is some code that adds a send endpoint to EP_ROOT(the home page of the site). Note that you'll have to go to Settings > Permalinks after adding this code in order for the rewrite endpoint to start working.
Once we have the rewrite endpoint in place, we hook to the template_redirect action in order to check for the presence of the send query var. If send is not present, then we do nothing.
If send is present, but empty(like for instance if you load the page http://example.com/send/), then we redirect to the home page.
Otherwise we split send into multiple parts at every / and assign that to the $send_parts variable. We then use a switch statement to see what the $send_action(the first part after /send/) and act accordingly.
Right now we're only checking for the email action(if it's not email, we redirect to the home page again). We check if there's an actual email($send_parts[1]) and whether it's a valid email(I have to note that is_email() is not RFC compliant and it might reject valid email addresses, so use with caution). If it's a valid email, we use wp_mail() to send the email, otherwise we redirect to the home page.
Now, since I don't know how you're planning to implement this my code doesn't cover things like authentication(who can send emails - if it's everyone, I can abuse your site and spam users and get your mail server blacklisted - bad :( ), generation of the email Subject and Message(is it going to be dynamic via $_POST variables, is it going to be pre-defined, etc.). Those are specifics that you will have to implement on your own.
Once the code below is placed in an appropriate file(a .php file that gets loaded in the current theme, or an active plugin's file) and you regenerate your Rewrite Rules(by going to Settings > Permalinks), you can go to http://example.com/send/email/your.email#example.com/ and you should receive an email with a subject "Hello" and a message "This is a message".
function so_34002145_add_email_endpoint() {
add_rewrite_endpoint( 'send', EP_ROOT );
}
add_action( 'init', 'so_34002145_add_email_endpoint', 10 );
function so_34002145_handle_send_email() {
$send = get_query_var( 'send', null );
// This is not a /send/ URL
if ( is_null( $send ) ) {
return;
}
// We're missing an action, the URL is /send/
// Take the user to the home page, since this is an incomplete request.
if ( empty( $send ) ) {
wp_redirect( home_url( '/' ) );
exit;
}
$send_parts = explode( '/', $send );
$send_action = $send_parts[0];
switch ( $send_action ) {
case 'email':
$email = ! empty( $send_parts[1] ) ? $send_parts[1] : false;
if ( ! $email || ! is_email( $email ) ) {
// A missing or invalid email address, abort
wp_redirect( home_url( '/' ) );
exit;
}
wp_mail( $email, 'Hello', 'This is a message' );
break;
default:
// This is an unknown action, send to the home page
wp_redirect( home_url( '/' ) );
exit;
break;
}
}
add_action( 'template_redirect', 'so_34002145_handle_send_email', 10 );

Woocommerce - Need to send email to specific address based on zip code

Basically, in woocommerce you have the option to input multiple email addresses (separated by commas) of who to send the completed order to, in WooCommerce -> Settings -> Emails -> New order. But I need a way to send to only one of these recipients based on the zip code of the customer who is ordering the product. Or completely overwrite woocommerce's way of handling this.
How can I tie into the function responsible for this, in order to send to the correct recipient? Basically, is there a hook defined for this, or does a plugin exist for something like this, or will I have to edit core WooCommerce files? If edits are needed to core files, can someone point me in the right direction as to which files will need edits?
I had a bit of trouble with helgatheviking's answer above and also a slightly different use case.
My problems/needs were:
I didn't quite understand the filter name as presented above.
The public function get_recipient() inside of class-wc-email.php expected a string but was getting an array.
A also wanted to conditionally add the extra recipient based on the payment method, rather than postcode.
Here's what I did instead:
Added full filter name, not just the suffix: woocommerce_email_recipient_new_order
Replaced explode() and array_push() with string concatenation $email .= ',' . $additional_email;.
Conditionally checked payment method: if( $order->get_payment_method() == "cod" ).
Full example:
add_filter( 'woocommerce_email_recipient_new_order' , 'so_26429482_add_recipient', 20, 2 );
function so_26429482_add_recipient( $email, $order ) {
// !empty($order) prevents a fatal error in WooCommerce Settings
// !empty($email) prevents the duplicate email from being sent in cases where the filter is run outside of when emails are normally sent. In my case, when using https://wordpress.org/plugins/woo-preview-emails/
if(!empty($order) && !empty($email)) {
$additional_email = "isf#domain.co";
if( $order->get_payment_method() == "cod" ) {
$email .= ',' . $additional_email;
} else {
$email .= ',another#domain.co';
}
}
return $email;
}
Each email has a filter that allows you to adjust the recipients of that email. The filter name is essentially woocommerce_email_recipient_{$email_id}.
So the following would filter the "to" addresses for the "new_order" email.
add_filter( 'new_order' , 'so_26429482_add_recipient', 20, 2 );
function so_26429482_add_recipient( $email, $order ) {
$additional_email = "somebody#somewhere.net";
if( $order->shipping_postcode == "90210" ){
$email = explode( ',', $email );
array_push( $email, $additional_email );
}
return $email;
}
I'm not 100% certain on the conditional logic, but I think that should check the shipping zip code and subsequently send to the additional email address.

How to log a user in to Wordpress using only their user_id

Is there any way I can log a Wordpress user in given only their wp user_ID?
I'm sending users emails to confirm something and when they click on the given link to come to the website they need to be logged in to see the page I'm taking them to, so I have to log the user in and then do a header redirect.
I need a php function provided by wordpress, one that I can use in php, could you also give me any extra details as to how I can implement it (if any)
Here a function to auto-log an user (not tested) :
function auto_login() {
if (!is_user_logged_in()) {
//determine WordPress user account to impersonate
$user_login = 'guest';
//get user's ID
$user = get_userdatabylogin($user_login);
$user_id = $user->ID;
//login
wp_set_current_user($user_id, $user_login);
wp_set_auth_cookie($user_id);
do_action('wp_login', $user_login);
}
}
You have to pass 2 parameters in wp_login hook. See Wp codex
wp_set_current_user( $user_id, $user->user_login );
wp_set_auth_cookie( $user_id );
do_action( 'wp_login', $user->user_login, $user );
Create separate table to store all the links you sent and respective temp authentication code, which may be valid only for some time, then pass that temp auth code and email as a url param -
Write a code to validate user based on temp auth code, so that as soon as user clicks on email you can redirect him.
The WordPress plugin temporary-login-without-password implements that and a unique hash / key as per your comments.
Open Source code is here:
https://plugins.trac.wordpress.org/browser/temporary-login-without-password/trunk/public/class-wp-temporary-login-without-password-public.php
public function init_wtlwp() {
if ( ! empty( $_GET['wtlwp_token'] ) ) {
$wtlwp_token = sanitize_key( $_GET['wtlwp_token'] ); // Input var okay.
$users = Wp_Temporary_Login_Without_Password_Common::get_valid_user_based_on_wtlwp_token( $wtlwp_token );
$temporary_user = '';
if ( ! empty( $users ) ) {
$temporary_user = $users[0];
}
if ( ! empty( $temporary_user ) ) {
$temporary_user_id = $temporary_user->ID;
That's a really bad ideea. Consider this:
You send an email to user A and B which contains the following link:
http://wordpressblog.exp/fromemail?user_id=A;
http://wordpressblog.exp/fromemail?user_id=B;
If user B replaces his user id with A's user_id then he has access to User A's account.
Youd be better of constructing a hash for logging a user that way

Categories