Create custom registration form for Wordpress Multisite - wordpress

I have Multisite Wordpress website and I've seen the default registration form but it did not meet all of my requirements because I want to add more additional fields like Password field.

To add custom fields in the registration form of a WordPress Multisite you need to do several things:
To show extra fields to sign up form.
To validate the fields when form is submitted.
To store the fields while user is pending activation.
To attach the fields to the user profile when the user is activated.
The file that controls the sign up process is wp-signup.php, where you can find useful filters and hooks to attach almost all the actions you need:
To show extra fields you can use the action hook signup_extra_fields.
To store the fields while user is pending activation you can use add_signup_meta.
To attach the fields to the user profile when the user is activated you can use wpmu_activate_user.
The validation step
For the fields validation step I haven't found a filter or an action hook to run the necessary code. So I have added one to wp-signup.php that I call signup_validate_extra_fields. You can call it as you want. I've added it inside the function validate_user_signup(). This function calls the function validate_user_form() that validates only username and user mail. The idea is to add the other fields validation at this point filtering this function. We can do this by replacing just one line (line 648):
$result = validate_user_form();
With this modification:
$result = apply_filters('signup_validate_extra_fields',validate_user_form());
With the new line, the beginning of the validate_user_signup() funcion would be:
/**
* Validate the new user signup
*
* #since MU (3.0.0)
*
* #return bool True if new user signup was validated, false if error
*/
function validate_user_signup() {
// $result = validate_user_form();
$result = apply_filters('signup_validate_extra_fields',validate_user_form());
$user_name = $result['user_name'];
$user_email = $result['user_email'];
$errors = $result['errors'];
It is not a good practice to modify WordPress core files, of course. To avoid it and not to loose the modifications after every WordPress update, I use the plugin Network Subsite User Registration that uses a local copy of wp-signup.php, so I can add the new filter there and not in the core file.
The whole code
The whole code using the hooks and filters I mention could be included in the file functions.php of a theme or in a plugin (probably better):
// add validation for extra fields
add_action( 'signup_extra_fields', 'prefix_signup_extra_fields',10,1 );
function prefix_signup_extra_fields($errors) {
$first_name = ( ! empty( $_POST['first_name'] ) ) ? sanitize_text_field( $_POST['first_name'] ) : '';
$last_name = ( ! empty( $_POST['last_name'] ) ) ? sanitize_text_field( $_POST['last_name'] ) : '';
// extra fields error handle
$fields = array(
'first_name',
'last_name'
);
$e = '';
if ( isset( $errors ) ) {
foreach ( $fields as $f )
$e[$f] = ( $errors->get_error_message( $f ) ) ? '<p class="error">'.$errors->get_error_message( $f ).'</p>' : '';
}
else {
foreach ( $fields as $f )
$e[$f] = '';
}
$signup_out = '
<hr>
<p>
<label for="first_name">'.__( 'First name' ).
$e['first_name']
.'<input type="text" name="first_name" id="first_name" class="signup-input" value="'.esc_attr( $first_name ).'" required />
</p>
<p>
<label for="last_name">'.__( 'Last name' ).
$e['last_name']
.'<input type="text" name="last_name" id="last_name" class="signup-input" value="'.esc_attr( $last_name ).'" required />
</p>
';
echo $signup_out;
return;
}
// add validation for extra fields
// I added a new filter to wp-singup.php
add_filter('signup_validate_extra_fields', 'prefix_signup_validation', 10, 1);
function pdigital_signup_validation( $arguments ) {
if ( ! isset( $_POST['signup_for'] ) )
return;
$fields = array(
'first_name' => __('You must include a first name.','pdigital'),
'last_name' => __('You must include a last name.','pdigital')
);
$errors = $arguments['errors'];
foreach( $fields as $f => $e )
if ( empty( $_POST[$f] ) || ! empty( $_POST[$f] ) && trim( $_POST[$f] ) == '' )
$errors->add( $f, $e );
return $arguments;
}
// store extra fields in wp_signups table while activating user
add_filter('add_signup_meta', 'prefix_add_signup_meta');
function prefix_add_signup_meta($meta) {
$fields = array(
'first_name',
'last_name',
);
foreach ( $fields as $f )
if( isset( $_POST[$f] ) )
$meta[$f] = sanitize_text_field( $_POST[$f] );
return $meta;
}
// add extra fields to user profile when user is activated
add_action('wpmu_activate_user','prefix_activate_user',10,3);
function prefix_activate_user( $user_id, $password, $meta ) {
$fields = array(
'first_name',
'last_name'
);
foreach ( $fields as $f )
if ( isset( $meta[$f] ) )
update_user_meta( $user_id, $f, $meta[$f] );
return;
}
Conclusion
Customize the sign up form of a WordPress Multisite is trickier than doing it in a one-site WordPress.
Finally it is worth to read the documentation about user system in WordPress Multisite and understand that it is common to all the sites of the network, before adding additional fields to the registration form.

Related

How to retrieve all users from the logged in user role? - Wordpress

I am trying to retrieve all users from the active user role. I have successfully fetched all the users, but I only want to fetch the users from the currently logged-in user role.
Have the following code in functions to retrieve all users:
// Get users by role
function userLooping( $role ) {
$user_query = new WP_User_Query( array( 'role' => $role ) );
// UserLoop
if ( ! empty( $user_query->results ) ) :
echo '<div id="divuser">';
foreach ( $user_query->results as $user ) :
echo '<option value="zo">';
echo $user->display_name; // display user name
echo '</option>';
endforeach;
echo '</div>';
endif;
}
add_shortcode( 'users_role', 'userLooping' );
Note: I only added <options> because I'm importing the result into a dropdown.
Any suggestions?
The code below works for me. A couple of notes:
You should check to see if the user is logged into WordPress (added in the snippet below)
Unless you have a good reason to separate it, it makes sense to grab the current user's role in your shortcode function (added in the snippet below)
A WordPress user can have more than one role, so this uses role__in to check an array of roles.
<option> elements need to be nested inside a select, outgroup, or datalist elements
function userLooping() {
if ( is_user_logged_in() ) {
$user = wp_get_current_user();
$roles = $user->roles;
$user_query = new WP_User_Query( [ 'role__in' => $roles ] );
$users = [];
if ( !empty ( $user_query->results ) ) {
$users = '<select id="divuser">';
foreach ( $user_query->results as $user ):
$users .= "<option value='$user->user_login'>";
$users .= $user->display_name; // display user name
$users .= '</option>';
endforeach;
$users .= '</select>';
}
return $users;
}
}
add_shortcode( 'users_role', 'userLooping' );

Wordpress single profile page with acf gallery sharing images

Good afternoon devs, I develop a project that consists of users profiles with a record created with fields from the ACF, including the image gallery field, my problem is ... as I only use one page to display this profile, the image gallery is makes it shared even with the option of "attached to the post", as I only use one page for this, example "/profile?userid=userid".
Is there any other good practice for doing this?
I would like suggestions.
one part profile edit
function acf_profile_edit( $atts ) {
$a = shortcode_atts( array(
'field_group' => ''
), $atts );
$uid = get_current_user_id();
if ( ! empty ( $a['field_group'] ) && ! empty ( $uid ) ) {
$options = array(
'post_id' => 'user_'.$uid,
'field_groups' => array( intval( $a['field_group'] ) ),
'return' => add_query_arg( 'updated', 'true', get_permalink() )
);
ob_start();
acf_form( $options );
$form = ob_get_contents();
ob_end_clean();
}
return $form;
}
add_shortcode( 'profile_edit', 'acf_profile_edit' );
Edit...
This code resolved my problem
add_filter('ajax_query_attachments_args', 'restrict_images_to_user');
function restrict_images_to_user($query) {
$gallery_images = 'field_5e4d799b34145';
$gallery_videos = 'field_5e5597e37f2c7';
if ( isset($_POST['query']['_acfuploader'] )
&& ( isset($_POST['query']['_acfuploader']) == $gallery_images || isset($_POST['query']['_acfuploader']) == $gallery_videos ) ) {
$author = get_current_user_id();
$query['author'] = $author;
}
return $query;
}
If you are using one page, use a page template called page-profile.php, the bit after page- must match the name of the page you have assigned.
Then use the WordPress Post Loop:
if (have_posts()) :
while (have_posts()) :
the_post();
the_content();
endwhile;
endif;
You can assign a username to the posts and the posts loop will only return the stuff associate with that username.
Another way would be to get the current username, then can you make an extra acf field with the username in and then do a check.
This is an example and will be exactly correct, but may be able to help you with suggestions.
If(content && username == currentuser)
{
$content = acf content;
}
then later in your page you can echo the content where you need it and will only be the content for the current username, or you can also do it with the user id.

Woocommerce: Override login required for existing email. Add order to user account

Woocommerce Settings:
Guest checkout disabled.
Create account during checkout enabled (user and passowrd auto generated)
If user is REGISTERED. But NOT logged in.
Checkout errors with
"An account is already registered with your email address. Please log in."
How do I override this to
COMPLETE order, and tie order to existing account.
Give a prompt to user to login next time for a faster checkout
Can't find any snippet or module that can do it
none yet. Happy to reward.
There is no hook for this. You may need to modify process_customer function in WC core (plugins/woocommerce/includes/class-wc-checkout.php) Line#935 - Keep in mind, it's not encouraged to edit core ( when updated, your changes will loose)
protected function process_customer( $data ) {
$customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );
if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
$username = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
$password = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
if(email_exists($data['billing_email'])){
$creds = array();
$creds['user_login'] = $user_login;
$creds['user_password'] = $user_password;
$creds['remember'] = true;
$user = wp_signon($creds, false);
$customer_id = $user->ID;
wp_set_current_user($customer_id, $user_login);
wp_set_auth_cookie($customer_id, true, false);
do_action('wp_login', $user_login);
}else{
$customer_id = wc_create_new_customer( $data['billing_email'], $username, $password );
}
if ( is_wp_error( $customer_id ) ) {
throw new Exception( $customer_id->get_error_message() );
}
wp_set_current_user( $customer_id );
wc_set_customer_auth_cookie( $customer_id );
// As we are now logged in, checkout will need to refresh to show logged in data.
WC()->session->set( 'reload_checkout', true );
// Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering.
WC()->cart->calculate_totals();
}
// On multisite, ensure user exists on current site, if not add them before allowing login.
if ( $customer_id && is_multisite() && is_user_logged_in() && ! is_user_member_of_blog() ) {
add_user_to_blog( get_current_blog_id(), $customer_id, 'customer' );
}
// Add customer info from other fields.
if ( $customer_id && apply_filters( 'woocommerce_checkout_update_customer_data', true, $this ) ) {
$customer = new WC_Customer( $customer_id );
if ( ! empty( $data['billing_first_name'] ) ) {
$customer->set_first_name( $data['billing_first_name'] );
}
if ( ! empty( $data['billing_last_name'] ) ) {
$customer->set_last_name( $data['billing_last_name'] );
}
// If the display name is an email, update to the user's full name.
if ( is_email( $customer->get_display_name() ) ) {
$customer->set_display_name( $data['billing_first_name'] . ' ' . $data['billing_last_name'] );
}
foreach ( $data as $key => $value ) {
// Use setters where available.
if ( is_callable( array( $customer, "set_{$key}" ) ) ) {
$customer->{"set_{$key}"}( $value );
// Store custom fields prefixed with wither shipping_ or billing_.
} elseif ( 0 === stripos( $key, 'billing_' ) || 0 === stripos( $key, 'shipping_' ) ) {
$customer->update_meta_data( $key, $value );
}
}
/**
* Action hook to adjust customer before save.
*
* #since 3.0.0
*/
do_action( 'woocommerce_checkout_update_customer', $customer, $data );
$customer->save();
}
do_action( 'woocommerce_checkout_update_user_meta', $customer_id, $data );
}
If you have enabled allow customers to login on checkout, the option login from checkout page will be coming.

I want to create two new user type in WordPress

In WordPress, I want to create two register user type: 1.teacher and 2. student.. means register as teacher and register as a student.
teacher registration is free and it posts his video, text etc..
student registration is not free but it's 6-month and 12-month subscription when a student is subscribed for this then student show the teacher's all post.
Can you please suggest me in this how to create this type of registration and membership...
thanks in advance
I think you can do it using add_role function.
There are three parameters in add_role function.
add_role( $role, $display_name, $capabilities );
$role: Unique name of the role.
$display_name: The name to be displayed in WordPress Admin Panel.
$capabilities: Privileges that one can access.
Complete list of all capabilities can be found here.
Step 2 : add user roles dropdown in registration form
//1. Add a new form element...
add_action( 'register_form', 'myplugin_register_form' );
function myplugin_register_form() {
global $wp_roles;
echo '<select name="role" class="input">';
foreach ( $wp_roles->roles as $key=>$value ) {
// Exclude default roles such as administrator etc. Add your own
if ( ! in_array( $value['name'], [ 'Administrator', 'Contributor', ] ) {
echo '<option value="'.$key.'">'.$value['name'].'</option>';
}
}
echo '</select>';
}
//2. Add validation.
add_filter( 'registration_errors', 'myplugin_registration_errors', 10, 3 );
function myplugin_registration_errors( $errors, $sanitized_user_login, $user_email ) {
if ( empty( $_POST['role'] ) || ! empty( $_POST['role'] ) && trim( $_POST['role'] ) == '' ) {
$errors->add( 'role_error', __( '<strong>ERROR</strong>: You must include a role.', 'mydomain' ) );
}
return $errors;
}
//3. Finally, save our extra registration user meta.
add_action( 'user_register', 'myplugin_user_register' );
function myplugin_user_register( $user_id ) {
$user_id = wp_update_user( array( 'ID' => $user_id, 'role' => $_POST['role'] ) );
}
Finally How to check if a user is in a specific role ?
$user = wp_get_current_user();
if ( in_array( 'author', (array) $user->roles ) ) {
//The user has the "author" role
}

Display role of administrator next to the username in WordPress

Is there a way to display an extra text next to the Username if the person has the administrator role?
I just want to display the extra text for this role only, what hook could I use for that?
Yes, you can use the filter the_author, like so:
add_filter( 'the_author', 'author_admin_so_14367149' );
function author_admin_so_14367149( $display_name )
{
// Block the filter in the dashboard (admin area)
if( is_admin() )
return $display_name;
global $authordata;
// User has administrator role, add string to display name
if( in_array( 'administrator', $authordata->roles ) )
$display_name = $display_name . ' (admin)';
return $display_name;
}
For the comments section, there's another filter and the checks are different:
add_filter( 'get_comment_author', 'comment_author_admin_so_14367149' );
function comment_author_admin_so_14367149( $author )
{
// Block the filter in the dashboard (admin area)
if( is_admin() )
return $author;
$user = get_user_by( 'login', $author );
// User has administrator role, add string to display name
if( in_array( 'administrator', $user->roles ) )
$author = $author . ' (admin)';
return $author;
}

Resources