Skip Navigation

[Resolved] Bypass Cred email verification

This support ticket is created 3 years, 10 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 10:00 – 13:00 10:00 – 13:00 10:00 – 13:00 10:00 – 13:00 10:00 – 13:00 -
- 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 -

Supporter timezone: Asia/Kolkata (GMT+05:30)

This topic contains 26 replies, has 3 voices.

Last updated by Puntorosso 3 years, 9 months ago.

Assisted by: Minesh.

Author
Posts
#1967443

Hi,
When a user form is submitted, I have a php function in place, which create a post and assign the new created user as author of the post.
If this user form is submitted a second time, with the same email address, it generates an error, because the email already exist in the database.

While the error it's correct, I would still need that the php function create anyway a new post, and assign that post to the same author.

User X submit form -> create user X - create post with author X
User Y submit form -> create user Y - create post with author Y
User X submit form -> create post with author X

How to achieve this? Thanks

#1968013

Hello and thank you for contacting the Toolset support.

I assume that the custom code to create the user's post is hooked to cred_save_data or cred_submit_complete actions, right?

Now, to create a post for the user even if the user creation fails, you will have to hook into the cred_form_validate check the errors to verify that the user creation failed because of the existing email address, and create the post at that point. Does it make sense?
https://toolset.com/documentation/programmer-reference/cred-api/#cred_form_validate

#1968043

It makes perfectly sense.
But if I use the cred_form_validate hook, how I catch the "existing user" error and let other error pass?

#1968073

The hooked function will take an array of errors and fields in the first argument '$error_fields'. You can get the errors and the fields with the following line:

list($fields,$errors)=$error_fields;

Then you can check for $errors['user_email'].

#1968135

Sorry, I still miss which parameter I should check.
There's a specific error code I can compare, to see if the user/email already exist?

Something like

add_filter('cred_form_validate','user_exist_already',10,2);
function user_exist_already($error_fields, $form_data)
{
    list($fields,$errors)=$error_fields;
	
	// if ($errors['user_email'] = XXXXX){do something;}
    
    }
#1968209

You are right. XXX should be the error message when an email already exists.

#1968219

Ok, but which value has to have XXX, if the error it's a duplicated email?
Sorry, maybe I take the principle from the wrong side.

#1968301

You can also directly search for the email if it exists without altering the validation at all. If the email exists, create the post. Does it make sense?

add_filter('cred_form_validate','user_exist_already',10,2);
function user_exist_already($error_fields, $form_data)
{
    $user = get_user_by( 'email', $_POST['user_email'] );
    if ( $user ) {
        // Create the post and make the user the author ($user->ID) 
    }
    return $error_fields;
}

Use the wp_insert_post and set the author to $user->ID
https://developer.wordpress.org/reference/functions/wp_insert_post/

#1968617

Can I chain 2 functions?

add_filter('cred_form_validate','user_exist_already',10,2);
function user_exist_already($error_fields, $form_data)
{
	if ($form_data['id']==1574) {
    	$user = get_user_by( 'email', $_POST['user_email'] );
		if ( $user ) {
			add_action('cred_save_data', 'add_customer_inquiry',20,4);
			function add_customer_inquiry($user_id, $form_data) {
			// create post and set author
		} else {
				return $error_fields;
				}
		}
	}
}
#1968787

Yes, you can. But, in this case, the second function you add to the "cred_save_data" action will never be executed because the validation of the email will fail and the process will not reach the "cred_save_data" action.

"return $error_fields;" has to be the last thing in the code and it should not be inside a condition. Because the other hook that should fire expect $error_fields. Does it make sense?

#1969037

The problem is that I have already a really "weird" coding on this form, due to the problem that Toolset require an email to save the form, but we want to be able to submit the form without it.

I have already a long thread open
https://toolset.com/forums/topic/email-not-required/

Finally, I was able to achieve what we wanted, and it works.
User can submit the form with/without email, and we automatically fill in the missing details.

// make the email field in a user form not required
add_filter('cred_filter_field_before_add_to_form', 'tssupp_not_required_email_func', 10, 1);
function tssupp_not_required_email_func($field){
    if(isset($field['id']) && in_array($field['id'], array('user_email'))){
        // in some cases $fields['data'] is an empty string, so you'll need to first set it's expected format for PHP 7.1 compatibility
        if (!is_array($field['data'])) {
            $field['data'] = array();
        }
        unset($field['data']['validate']['required']);
    }
    return $field;
}

// create a new user, so add a timestamp as login name, to avoid form errors
add_action('cred_before_save_data', 'contact_autogen_username',10,1);
function contact_autogen_username($form_data) {
    // if a specific form
    $forms = array( 5466,1574 );
    if ( in_array( $form_data['id'], $forms ) )
    {
        $_POST['user_login'] = date('YmdHms'); // generate unique username based on current timestamp        
    }
}

// now set a proper username
add_action('cred_save_data','func_proper_username',12,2);
function func_proper_username ($user_id,$form_data) {
	    $forms = array( 5466, 1574 );
		if ( in_array( $form_data['id'], $forms ) ) {		
 		global $wpdb;
	    $username = strtolower($_REQUEST['first_name'] . $_REQUEST['last_name']) . $user_id ;
	    $wpdb->update($wpdb->users, array('user_login' => $username), array('ID' => $user_id));
}
}


// update the other names and add a customer number.
add_action('cred_submit_complete','func_create_new_customer',12,2);
function func_create_new_customer($user_id,$form_data) {
		
	// if is a new created user
	$forms = array( 5466, 1574 );
    if ( in_array( $form_data['id'], $forms ) ) {
	    $first_name = ucwords(strtolower(sanitize_text_field($_REQUEST['first_name'])));
	    $last_name = ucwords(strtolower(sanitize_text_field($_REQUEST['last_name'])));
	    $username = strtolower( $first_name . $last_name ) . $user_id ;

		$userdata = array (
			'ID' => $user_id,
			'first_name' => $first_name,
			'last_name' => $last_name,
			'nickname' => $first_name . " " . $last_name,
			'user_nicename' => $username,
			'display_name' => $first_name . " " . $last_name
			);
	    wp_update_user($userdata);      
	    update_user_meta( $user_id, 'wpcf-user-number', "KV-" . $user_id);    
	} 
	
	// change role
	$forms = array( 5466, 1574, 9077 );
    if ( in_array( $form_data['id'], $forms ) ) {
	    if ( isset ($_REQUEST['customer_select_role'])) {
			$role = $_REQUEST['customer_select_role'];	
		}else{
			$role = 'customer';
		}	
   		$user_meta = get_userdata($user_id);
   		$user_role = $user_meta->roles;
   		$u = new WP_User( $user_id );
   		$u->remove_role( $user_role ); //cred form roles field
   		$u->set_role( $role );

	}
}

As you see, I need the form to go through the full process before I create the new user.

Now I need to find a way to use the "cred_form_validate" hook, as you suggested, to fire the function that create the custom post:

User X submit form -> create user X with the above code -> start function "add_customer_inquiry" to create post with author X
User Y submit form -> create user Y with the above code -> start function "add_customer_inquiry" to create post with author Y
User X submit again the form -> bypass the above code but -> start function "add_customer_inquiry" to create post with author X

#1969467

As I explained in my reply https://toolset.com/forums/topic/bypass-cred-email-verification/#post-1968301

add_filter('cred_form_validate','user_exist_already',10,2);
function user_exist_already($error_fields, $form_data)
{
  if ($form_data['id']==1574) {
    $user = get_user_by( 'email', $_POST['user_email'] );
    if ( $user ) {
        // Create the post and make the user the author ($user->ID) 
        $my_post = array(
          'post_title'    => 'Post title',
          'post_content'  => 'Post content',
          'post_status'   => 'publish',
          'post_author'   => $user->ID,  // set the author of the post
        );
 
        // Insert the post into the database
        wp_insert_post( $my_post );
    }
  }
    return $error_fields; // return the $error_fields object to let Toolset complete the validation and process further.
}
#1969475

I understood that, but you are missing the point.
The post should be created if the user already exist but also if the user DOESN'T exist.

Possible scenarios:

1) the user doesn't exist.
In this case all my above mentioned routines should be executed, a new user would be created, and then the function to create a post executed.

2) the user exist.
In this case the above mentioned routines should NOT generate an "existing user" error but, instead, ONLY the function to create the post should be executed.

The way you are suggesting now, would still generate an error on the form, if a user already exist.

#1970427

Right, if the user exists, the post will be created at the validation stage. But then, the validation will fail and an error will be displayed for the user.

There is no way to bypass the default validation and display to the user that the post has created successfully when the user already exists. What I can think of, is to perform a redirection. So:
1) the user doesn't exist.
This code will not be executed. The validation will complete successfully, then the post will be created using the function hooked to cred_submit_complete.
https://toolset.com/forums/topic/bypass-cred-email-verification/#post-1969467

2) the user exist.
This code will run and create the post for the user. And if the validation completes, he will get an error. To work around it, you need to perform a redirect to somewhere and exit. Something like:

add_filter('cred_form_validate','user_exist_already',10,2);
function user_exist_already($error_fields, $form_data)
{
  if ($form_data['id']==1574) {
    $user = get_user_by( 'email', $_POST['user_email'] );
    if ( $user ) {
        // Create the post and make the user the author ($user->ID) 
        $my_post = array(
          'post_title'    => 'Post title',
          'post_content'  => 'Post content',
          'post_status'   => 'publish',
          'post_author'   => $user->ID,  // set the author of the post
        );
  
        // Insert the post into the database
        wp_insert_post( $my_post );
        
        // Decide here where to redirect
        $redirect_url = site_url();
        wp_redirect( $redirect_url );
        exit;
    }
  }
    return $error_fields; // return the $error_fields object to let Toolset complete the validation and process further.
}

But here again, the success message is not displayed, unless you will redirect to a page that has a hardcoded message or you want to handle it with URL params. Does it make sense?

#1970641

Could be a solution.
There's a way to read the redirection url from the form?
hidden link