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;
}
1 Answer 1
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'] : [];