3
\$\begingroup\$

I work on plugin for custom auth pages for WordPress and I try to create a custom registration form with additional fields. it has a shortcode in Beaver Builder. Is this the correct approach, and what can be improved here?

<?php

if (!defined('ABSPATH')) {
    exit;
}
function intercept_wp_registration_errors($errors, $sanitized_user_login, $user_email) {
    
    if (is_user_logged_in()) {
        wp_redirect(home_url('/already-logged-in/'));
        exit;
    }
    if (!session_id()) {
        session_start();
    }
    if (isset($_POST['first_name'])) {
        $first_name = sanitize_text_field($_POST['first_name']);
        if (empty($first_name)) {
            $errors->add('invalid_first_name', __('<strong>Error:</strong> First Name is required.'));
        } else {
            $_SESSION['registration_form_data']['first_name'] = $first_name;
        }
    } else {
        $errors->add('invalid_first_name', __('<strong>Error:</strong> First Name is required.'));
    }
    if (isset($_POST['last_name'])) {
        $last_name = sanitize_text_field($_POST['last_name']);
        if (empty($last_name)) {
            $errors->add('invalid_last_name', __('<strong>Error:</strong> Last Name is required.'));
        } else {
            $_SESSION['registration_form_data']['last_name'] = $last_name;
        }
    } else {
        $errors->add('invalid_last_name', __('<strong>Error:</strong> Last Name is required.'));
    }
    if (isset($_POST['phone'])) {
        $phone = sanitize_text_field($_POST['phone']);
        if (empty($phone)) {
            $errors->add('invalid_phone', __('<strong>Error:</strong> Phone Number is required.'));
        } else {
            $_SESSION['registration_form_data']['phone'] = $phone;
        }
    } else {
        $errors->add('invalid_phone', __('<strong>Error:</strong> Phone Number is required.'));
    }
    if (empty($sanitized_user_login)) {
        $errors->add('invalid_username', __('<strong>Error:</strong> Username is required.'));
    } else {
        if (username_exists($sanitized_user_login)) {
            $errors->add('username_exists', __('<strong>Error:</strong> Username already exists.'));
        } else {
            $_SESSION['registration_form_data']['user_login'] = $sanitized_user_login;
        }
    }
    if (empty($user_email)) {
        $errors->add('invalid_email', __('<strong>Error:</strong> Email is required.'));
    } else {
        if (email_exists($user_email)) {
            $errors->add('email_exists', __('<strong>Error:</strong> Email already exists.'));
        } else {
            $_SESSION['registration_form_data']['user_email'] = $user_email;
        }
    }
    if (!empty($errors->errors)) {
        $_SESSION['registration_errors'] = $errors;
        wp_redirect(home_url('/sign-up'));
        exit;
    }
    
    return $errors;
}

add_filter('registration_errors', 'intercept_wp_registration_errors', 10, 3);
function custom_registration_form() {
    
    if (!session_id()) {
        session_start();
    }
    $errors = isset($_SESSION['registration_errors']) ? $_SESSION['registration_errors'] : new WP_Error();
    $form_data = isset($_SESSION['registration_form_data']) ? $_SESSION['registration_form_data'] : [];
    unset($_SESSION['registration_errors'], $_SESSION['registration_form_data']);
    ob_start();
    ?>

  <form method="post" action="<?php echo esc_url(site_url('wp-login.php?action=register', 'login_post')); ?>"
        id="registration_form">
    <div class="form-item">

      <label for="user_login"><?php _e('Username', 'textdomain'); ?></label>
      <input type="text" name="user_login" id="user_login"
             value="<?php echo esc_attr($form_data['user_login'] ?? ''); ?>" required>
        <?php if (isset($errors->errors['invalid_username'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['invalid_username'][0]); ?></p>
        <?php elseif (isset($errors->errors['username_exists'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['username_exists'][0]); ?></p>
        <?php endif; ?>
    </div>
    <div class="form-item">

      <label for="user_email"><?php _e('Email', 'textdomain'); ?></label>
      <input type="email" name="user_email" id="user_email"
             value="<?php echo esc_attr($form_data['user_email'] ?? ''); ?>" required>
        <?php if (isset($errors->errors['invalid_email'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['invalid_email'][0]); ?></p>
        <?php elseif (isset($errors->errors['email_exists'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['email_exists'][0]); ?></p>
        <?php endif; ?>
    </div>
    <div class="form-item">

      <label for="first_name"><?php _e('First Name', 'textdomain'); ?></label>
      <input type="text" name="first_name" id="first_name"
             value="<?php echo esc_attr($form_data['first_name'] ?? ''); ?>" required>
        <?php if (isset($errors->errors['invalid_first_name'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['invalid_first_name'][0]); ?></p>
        <?php endif; ?>
    </div>
    <div class="form-item">

      <label for="last_name"><?php _e('Last Name', 'textdomain'); ?></label>
      <input type="text" name="last_name" id="last_name"
             value="<?php echo esc_attr($form_data['last_name'] ?? ''); ?>" required>
        <?php if (isset($errors->errors['invalid_last_name'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['invalid_last_name'][0]); ?></p>
        <?php endif; ?>
    </div>
    <div class="form-item">

      <label for="phone"><?php _e('Phone Number', 'textdomain'); ?></label>
      <input type="tel" name="phone" id="phone" value="<?php echo esc_attr($form_data['phone'] ?? ''); ?>"
             required>
        <?php if (isset($errors->errors['invalid_phone'])) : ?>
          <p class="error"><?php echo wp_kses_post($errors->errors['invalid_phone'][0]); ?></p>
        
        <?php endif; ?>
      
      <span id="valid-msg" class="valid hide">✓ Valid</span>
      <span id="error-msg" class="error hide"></span>
    </div>
      <?php wp_nonce_field('custom_register_action', 'custom_register_nonce'); ?>

    <button id="btn" class="button" type="submit"><?php _e('Register', 'textdomain'); ?></button>
  </form>
    
    <?php
    return ob_get_clean();
}

add_shortcode('custom_registration_form', 'custom_registration_form');
function custom_user_register($user_id) {
    
    if (!session_id()) {
        session_start();
    }
    $first_name = sanitize_text_field($_POST['first_name'] ?? '');
    $last_name = sanitize_text_field($_POST['last_name'] ?? '');
    $phone = sanitize_text_field($_POST['phone'] ?? '');
    if (!empty($first_name)) {
        update_user_meta($user_id, 'first_name', $first_name);
    }
    if (!empty($last_name)) {
        update_user_meta($user_id, 'last_name', $last_name);
    }
    if (!empty($phone)) {
        update_user_meta($user_id, 'billing_phone', $phone);
    }
}

add_action('user_register', 'custom_user_register');
function redirect_wp_register() {
    
    if (strpos($_SERVER['REQUEST_URI'], 'wp-login.php?action=register') !== false) {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            add_action('registration_errors', 'custom_registration_redirect_on_error', 10, 3);
        } else {
            wp_redirect(home_url('/sign-up/'));
            exit;
        }
    }
    if (strpos($_SERVER['REQUEST_URI'], 'wp-login.php?checkemail=registered') !== false) {
        wp_redirect(home_url('/registred-checkemail'));
        exit;
    }
}

add_action('init', 'redirect_wp_register');
function custom_registration_redirect_on_error($errors, $sanitized_user_login, $user_email) {
    
    if (!empty($errors->errors)) {
        wp_redirect(home_url('/sign-up/?registration=failed'));
        exit;
    }
    
    return $errors;
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

what can be improved here?

Abstract common blocks to a loop or function

There is a bit of redundancy - e.g. in function intercept_wp_registration_errors():

if (isset($_POST['first_name'])) {
    $first_name = sanitize_text_field($_POST['first_name']);
    if (empty($first_name)) {
        $errors->add('invalid_first_name', __('<strong>Error:</strong> First Name is required.'));
     } else {
         $_SESSION['registration_form_data']['first_name'] = $first_name;
     }
 } else {
     $errors->add('invalid_first_name', __('<strong>Error:</strong> First Name is required.'));
 }
 if (isset($_POST['last_name'])) {
     $last_name = sanitize_text_field($_POST['last_name']);
     if (empty($last_name)) {
         $errors->add('invalid_last_name', __('<strong>Error:</strong> Last Name is required.'));
     } else {
         $_SESSION['registration_form_data']['last_name'] = $last_name;
     }
 } else {
     $errors->add('invalid_last_name', __('<strong>Error:</strong> Last Name is required.'));
 }
 if (isset($_POST['phone'])) {
     $phone = sanitize_text_field($_POST['phone']);
     if (empty($phone)) {
         $errors->add('invalid_phone', __('<strong>Error:</strong> Phone Number is required.'));
     } else {
         $_SESSION['registration_form_data']['phone'] = $phone;
     }
 } else {
     $errors->add('invalid_phone', __('<strong>Error:</strong> Phone Number is required.'));
}

This goes against the Don't repeat yourself (i.e. DRY) principle. One could abstract the field names into an array - e.g.

$fields = ['first_name', 'last_name', 'phone'];

and then iterate over those in a loop to either add an invalid value to the list of errors or set the value in the session.

The same applies to this block within function custom_user_register():

$first_name = sanitize_text_field($_POST['first_name'] ?? '');
$last_name = sanitize_text_field($_POST['last_name'] ?? '');
$phone = sanitize_text_field($_POST['phone'] ?? '');
if (!empty($first_name)) {
    update_user_meta($user_id, 'first_name', $first_name);
}
if (!empty($last_name)) {
    update_user_meta($user_id, 'last_name', $last_name);
}
if (!empty($phone)) {
    update_user_meta($user_id, 'billing_phone', $phone);
}

Use null-coalescing operator

In the function custom_user_register() the null-coalescing operator is used:

$first_name = sanitize_text_field($_POST['first_name'] ?? '');
$last_name = sanitize_text_field($_POST['last_name'] ?? '');
$phone = sanitize_text_field($_POST['phone'] ?? '');

That could be used in other places - e.g.:

in custom_registration_form():

$errors = isset($_SESSION['registration_errors']) ? $_SESSION['registration_errors'] : new WP_Error();
$form_data = isset($_SESSION['registration_form_data']) ? $_SESSION['registration_form_data'] : [];
\$\endgroup\$
0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.