';
if (!empty($errors['transient'])) echo '
' . esc_html($errors['transient']) . '
';
// Nonce errors should ideally be caught in admin-post, but display if somehow set
if (!empty($errors['nonce'])) echo '' . esc_html($errors['nonce']) . '
';
error_log('[HVAC REG DEBUG] render_registration_form: Errors before display_form_html: ' . print_r($errors, true));
if (!empty($errors['account'])) echo '' . esc_html($errors['account']) . '
';
echo '';
}
// Display the form HTML, passing retrieved errors and submitted data
// No success message here anymore, success leads to redirect
$this->display_form_html($submitted_data, $errors);
return ob_get_clean();
// --- End Render Form ---
}
/**
* Processes the registration form submission via admin-post.
* Handles validation, user creation, notifications, and redirects.
*/
public function process_registration_submission() {
error_log('[HVAC REG DEBUG] process_registration_submission fired.');
$errors = [];
$submitted_data = $_POST; // Capture submitted data early for potential repopulation
$registration_page_url = home_url('/trainer-registration/'); // Adjust if slug changes
// --- Verify Nonce ---
if (!isset($_POST['hvac_registration_nonce']) || !wp_verify_nonce($_POST['hvac_registration_nonce'], 'hvac_trainer_registration')) {
$errors['nonce'] = 'Security check failed. Please try submitting the form again.';
error_log('[HVAC REG DEBUG] Nonce check failed in admin-post.');
$this->redirect_with_errors($errors, $submitted_data, $registration_page_url);
// No need for return/exit here, redirect_with_errors exits.
}
error_log('[HVAC REG DEBUG] Nonce check passed in admin-post.');
// --- File Upload Handling ---
$profile_image_data = null;
if (isset($_FILES['profile_image']) && $_FILES['profile_image']['error'] !== UPLOAD_ERR_NO_FILE) {
if ($_FILES['profile_image']['error'] === UPLOAD_ERR_OK) {
// Check if it's actually an uploaded file
if (!is_uploaded_file($_FILES['profile_image']['tmp_name'])) {
$errors['profile_image'] = 'File upload error (invalid temp file).';
error_log('[HVAC REG DEBUG] Profile image upload error: Not an uploaded file.');
} else {
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
// Use wp_check_filetype on the actual file name for extension check
// Use finfo_file or getimagesize on tmp_name for actual MIME type check for better security
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $_FILES['profile_image']['tmp_name']);
finfo_close($finfo);
if (!in_array($mime_type, $allowed_types)) {
$errors['profile_image'] = 'Invalid file type detected (' . esc_html($mime_type) . '). Please upload a JPG, PNG, or GIF.';
error_log('[HVAC REG DEBUG] Profile image upload error: Invalid MIME type - ' . $mime_type);
} else {
$profile_image_data = $_FILES['profile_image']; // Store the whole $_FILES entry
error_log('[HVAC REG DEBUG] Profile image seems valid.');
}
}
error_log('[HVAC REG DEBUG] process_registration_submission: Errors after validation merge: ' . print_r($errors, true));
} else {
$errors['profile_image'] = 'There was an error uploading the profile image. Code: ' . $_FILES['profile_image']['error'];
error_log('[HVAC REG DEBUG] Profile image upload error code: ' . $_FILES['profile_image']['error']);
error_log('[HVAC REG DEBUG] process_registration_submission: Checking if errors is empty. Result: ' . (empty($errors) ? 'Yes' : 'No'));
}
}
// --- End File Upload Handling ---
// Validate the rest of the form data
$validation_errors = $this->validate_registration($submitted_data);
$errors = array_merge($errors, $validation_errors); // Combine file errors and validation errors
// --- Process if No Errors ---
if (empty($errors)) {
error_log('[HVAC REG DEBUG] Validation passed in admin-post. Attempting account creation...');
$user_id = $this->create_trainer_account($submitted_data, $profile_image_data);
if (is_wp_error($user_id)) {
$errors['account'] = $user_id->get_error_message();
error_log('[HVAC REG DEBUG] Account creation WP_Error in admin-post: ' . $user_id->get_error_message());
$this->redirect_with_errors($errors, $submitted_data, $registration_page_url);
// No need for return/exit here
} elseif ($user_id) {
error_log('[HVAC REG DEBUG] Account creation SUCCESS in admin-post. User ID: ' . $user_id);
error_log('[HVAC REG DEBUG] Sending admin notification...');
$this->send_admin_notification($user_id, $submitted_data);
// $this->send_user_pending_notification($user_id); // TODO
// --- Success Redirect ---
$success_redirect_url = home_url('/registration-pending/'); // URL from E2E test
error_log('[HVAC REG DEBUG] Redirecting to success page: ' . $success_redirect_url);
wp_safe_redirect($success_redirect_url);
exit; // Important after redirect
} else {
// This case should ideally not happen if wp_insert_user works correctly
$errors['account'] = 'An unknown error occurred during registration. Please contact support.';
error_log('[HVAC REG DEBUG] Account creation failed silently in admin-post (returned false/0).');
$this->redirect_with_errors($errors, $submitted_data, $registration_page_url);
// No need for return/exit here
}
} else {
error_log('[HVAC REG DEBUG] Validation errors found in admin-post: ' . print_r($errors, true));
$this->redirect_with_errors($errors, $submitted_data, $registration_page_url);
// No need for return/exit here
}
}
/**
* Helper function to store errors/data in transient and redirect back to the form page.
error_log('[HVAC REG DEBUG] redirect_with_errors: Preparing transient. Key: ' . $transient_key . ' Data: ' . print_r($transient_data, true));
*
* @param array $errors Array of error messages.
* @param array $data Submitted form data.
* @param string $redirect_url The URL to redirect back to.
*/
private function redirect_with_errors($errors, $data, $redirect_url) {
$transient_id = uniqid(); // Generate unique ID for transient key
$transient_key = self::TRANSIENT_PREFIX . $transient_id;
$transient_data = [
'errors' => $errors,
'data' => $data, // Store submitted data to repopulate form
];
// Store for 5 minutes
set_transient($transient_key, $transient_data, MINUTE_IN_SECONDS * 5);
// Add query arguments to the redirect URL
$redirect_url = add_query_arg([
'reg_error' => '1',
'tid' => $transient_id,
], $redirect_url);
error_log('[HVAC REG DEBUG] Redirecting back with errors. URL: ' . $redirect_url . ' Transient Key: ' . $transient_key);
wp_safe_redirect($redirect_url);
exit; // Stop execution after redirect
}
/**
* Displays the actual form HTML.
* Receives submitted data and errors as arguments (potentially retrieved from transient).
*/
private function display_form_html($data = [], $errors = []) {
// Ensure $data and $errors are arrays, even if transient failed
$data = is_array($data) ? $data : [];
$errors = is_array($errors) ? $errors : [];
?>
post_content, 'hvac_trainer_registration')) {
wp_enqueue_style(
'hvac-registration-style',
HVAC_CE_PLUGIN_URL . 'assets/css/hvac-registration.css', // Ensure this CSS file exists and is styled
array(),
HVAC_CE_VERSION
);
wp_enqueue_script(
'hvac-registration-js',
HVAC_CE_PLUGIN_URL . 'assets/js/hvac-registration.js', // Ensure this JS file exists
array('jquery'),
HVAC_CE_VERSION,
true
);
// Localize script to pass states/provinces data and AJAX URL
wp_localize_script('hvac-registration-js', 'hvacRegistrationData', array(
'ajax_url' => admin_url('admin-ajax.php'), // Needed if JS fetches states/provinces via AJAX
'states' => $this->get_us_states(), // Pass US states
'provinces' => $this->get_canadian_provinces(), // Pass CA provinces
// Pass other country data if needed, or handle via AJAX
));
}
}
/**
* Handle profile image upload after user is created.
* Should be called from within create_trainer_account or similar context.
*
* @param int $user_id The ID of the user to attach the image to.
* @param array $file_data The $_FILES array entry for the uploaded image.
* @return int|false Attachment ID on success, false on failure.
*/
private function handle_profile_image_upload($user_id, $file_data) {
// Basic validation already done in process_registration_submission
if (!$user_id || empty($file_data) || !isset($file_data['tmp_name']) || $file_data['error'] !== UPLOAD_ERR_OK) {
error_log('[HVAC REG DEBUG] handle_profile_image_upload called with invalid args or file error.');
return false;
}
// These files need to be included as dependencies when on the front-end.
require_once(ABSPATH . 'wp-admin/includes/image.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
// Let WordPress handle the upload. It moves the file and creates attachment post.
// Pass the $_FILES array key ('profile_image' in this case)
$attachment_id = media_handle_upload('profile_image', 0); // 0 means don't attach to a post
if (is_wp_error($attachment_id)) {
// Handle upload error
error_log('[HVAC REG DEBUG] Profile image upload error for user ' . $user_id . ': ' . $attachment_id->get_error_message());
// Optionally add this error to be displayed to the user via transient?
// For now, just fail silently in terms of user feedback, but log it.
return false;
} else {
// Store the attachment ID as user meta
update_user_meta($user_id, 'profile_image_id', $attachment_id);
error_log('[HVAC REG DEBUG] Profile image uploaded successfully for user ' . $user_id . '. Attachment ID: ' . $attachment_id);
return $attachment_id;
}
}
/**
* Validate registration form data
*
* @param array $data Submitted form data ($_POST).
* @return array Array of errors, empty if valid.
*/
public function validate_registration($data) {
error_log('[HVAC REG DEBUG] validate_registration: Received data: ' . print_r($data, true));
$errors = array();
// Required field validation
$required_fields = [
'user_email' => 'Email',
'user_pass' => 'Password',
'confirm_password' => 'Confirm Password',
'first_name' => 'First Name',
'last_name' => 'Last Name',
'display_name' => 'Display Name',
'description' => 'Biographical Info',
'business_name' => 'Business Name',
'business_phone' => 'Business Phone',
'business_email' => 'Business Email',
'business_description' => 'Business Description',
'user_country' => 'Country',
'user_state' => 'State/Province',
'user_city' => 'City',
'user_zip' => 'Zip/Postal Code',
'create_venue' => 'Create Training Venue Profile selection',
'business_type' => 'Business Type',
'application_details' => 'Application Details',
];
foreach ($required_fields as $field => $label) {
// Use trim to catch spaces-only input
if (empty($data[$field]) || trim($data[$field]) === '') {
$errors[$field] = $label . ' is required.';
}
}
// Required checkbox groups
$required_checkboxes = [
'training_audience' => 'Training Audience',
'training_formats' => 'Training Formats',
'training_locations' => 'Training Locations',
'training_resources' => 'Training Resources',
];
foreach ($required_checkboxes as $field => $label) {
// Check if the key exists and is a non-empty array
if (empty($data[$field]) || !is_array($data[$field])) {
$errors[$field] = 'Please select at least one option for ' . $label . '.';
}
}
// Email validation
if (!empty($data['user_email']) && !is_email($data['user_email'])) {
$errors['user_email'] = 'Please enter a valid email address.';
}
if (!empty($data['business_email']) && !is_email($data['business_email'])) {
$errors['business_email'] = 'Please enter a valid business email address.';
}
// Email exists validation (only if email is valid)
if (empty($errors['user_email']) && !empty($data['user_email']) && email_exists($data['user_email'])) {
$errors['user_email'] = 'This email address is already registered.';
}
// Password validation
if (!empty($data['user_pass'])) {
if (strlen($data['user_pass']) < 8) {
$errors['user_pass'] = 'Password must be at least 8 characters long.';
} elseif (!preg_match('/[A-Z]/', $data['user_pass'])) {
$errors['user_pass'] = 'Password must contain at least one uppercase letter.';
} elseif (!preg_match('/[a-z]/', $data['user_pass'])) {
$errors['user_pass'] = 'Password must contain at least one lowercase letter.';
} elseif (!preg_match('/[0-9]/', $data['user_pass'])) {
$errors['user_pass'] = 'Password must contain at least one number.';
}
// Consider adding special character requirement if needed: !preg_match('/[\W_]/', $data['user_pass'])
}
// Confirm password validation (only if password itself is not empty)
if (!empty($data['user_pass']) && empty($errors['user_pass'])) {
if (empty($data['confirm_password'])) {
$errors['confirm_password'] = 'Please confirm your password.';
} elseif ($data['user_pass'] !== $data['confirm_password']) {
$errors['confirm_password'] = 'Passwords do not match.';
}
}
// URL validation (optional fields)
if (!empty($data['user_url']) && !filter_var($data['user_url'], FILTER_VALIDATE_URL)) {
$errors['user_url'] = 'Please enter a valid URL for your personal website.';
}
if (!empty($data['user_linkedin']) && !filter_var($data['user_linkedin'], FILTER_VALIDATE_URL)) {
$errors['user_linkedin'] = 'Please enter a valid URL for your LinkedIn profile.';
}
if (!empty($data['business_website']) && !filter_var($data['business_website'], FILTER_VALIDATE_URL)) {
$errors['business_website'] = 'Please enter a valid URL for your business website.';
}
// State/Province 'Other' validation
if (!empty($data['user_country'])) {
if ($data['user_country'] !== 'United States' && $data['user_country'] !== 'Canada') {
// If country is not US/CA, state *must* be 'Other'
if (empty($data['user_state']) || $data['user_state'] !== 'Other') {
$errors['user_state'] = 'Please select "Other" for State/Province if your country is not US or Canada.';
} elseif (empty($data['user_state_other']) || trim($data['user_state_other']) === '') {
// If state is 'Other', the text input must not be empty
$errors['user_state_other'] = 'Please enter your state/province.';
}
} elseif (!empty($data['user_state'])) {
// If country is US/CA
if ($data['user_state'] === 'Other') {
// State cannot be 'Other' if country is US/CA
$errors['user_state'] = 'Please select your state/province from the list.';
} elseif (empty($errors['user_state'])) { // Only check 'Other' field if state itself is valid
// Ensure 'Other' text input is cleared if a valid state is selected
// This might be better handled by JS, but add server-side check just in case
if (!empty($data['user_state_other'])) {
// Maybe log a warning? Or just ignore it. Let's ignore for now.
// error_log("[HVAC REG DEBUG] 'Other State' field had data but a valid US/CA state was selected.");
}
}
}
}
error_log('[HVAC REG DEBUG] validate_registration: FINAL errors before return: ' . print_r($errors, true));
return $errors;
}
/**
* Create trainer account and associated data
*
* @param array $data Sanitized form data.
* @param array|null $profile_image_data The $_FILES entry for the profile image, if provided.
* @return int|WP_Error User ID on success, WP_Error on failure.
*/
private function create_trainer_account($data, $profile_image_data = null) {
// Assume data is already somewhat validated by validate_registration
// Perform final sanitization here before insertion
$user_email = sanitize_email($data['user_email']);
$user_pass = $data['user_pass']; // wp_insert_user handles hashing
$first_name = sanitize_text_field($data['first_name']);
$last_name = sanitize_text_field($data['last_name']);
$display_name = sanitize_text_field($data['display_name']);
$user_url = !empty($data['user_url']) ? esc_url_raw($data['user_url']) : '';
$description = wp_kses_post($data['description']); // Allow some HTML
// Generate username from email (ensure uniqueness)
$username_base = sanitize_user(substr($user_email, 0, strpos($user_email, '@')), true);
if (empty($username_base)) { // Handle cases where email might be weird
$username_base = 'trainer';
}
$username = $username_base;
$counter = 1;
while (username_exists($username)) {
$username = $username_base . $counter;
$counter++;
if ($counter > 100) { // Safety break
return new WP_Error('username_generation', 'Could not generate a unique username.');
}
}
// User data array
$user_data = array(
'user_login' => $username,
'user_email' => $user_email,
'user_pass' => $user_pass,
'first_name' => $first_name,
'last_name' => $last_name,
'display_name' => $display_name,
'user_url' => $user_url,
'description' => $description,
'role' => 'hvac_trainer' // Assign custom role
);
// Insert the user
$user_id = wp_insert_user($user_data);
// Check for errors
if (is_wp_error($user_id)) {
error_log('[HVAC REG DEBUG] wp_insert_user failed: ' . $user_id->get_error_message());
return $user_id; // Return the WP_Error object
}
error_log('[HVAC REG DEBUG] wp_insert_user success. User ID: ' . $user_id);
// --- Update User Meta ---
// Sanitize all meta values before updating
$meta_fields = [
'user_linkedin' => !empty($data['user_linkedin']) ? esc_url_raw($data['user_linkedin']) : '',
'personal_accreditation' => !empty($data['personal_accreditation']) ? sanitize_text_field($data['personal_accreditation']) : '',
'business_name' => sanitize_text_field($data['business_name']),
'business_phone' => sanitize_text_field($data['business_phone']),
'business_email' => sanitize_email($data['business_email']),
'business_website' => !empty($data['business_website']) ? esc_url_raw($data['business_website']) : '',
'business_description' => wp_kses_post($data['business_description']),
'user_country' => sanitize_text_field($data['user_country']),
// Use the 'Other' field value if state was 'Other', otherwise use the selected state
'user_state' => ($data['user_state'] === 'Other' && isset($data['user_state_other'])) ? sanitize_text_field($data['user_state_other']) : sanitize_text_field($data['user_state']),
'user_city' => sanitize_text_field($data['user_city']),
'user_zip' => sanitize_text_field($data['user_zip']),
'create_venue' => sanitize_text_field($data['create_venue']), // Should be 'Yes' or 'No'
'business_type' => sanitize_text_field($data['business_type']),
'training_audience' => (!empty($data['training_audience']) && is_array($data['training_audience'])) ? array_map('sanitize_text_field', $data['training_audience']) : [],
'training_formats' => (!empty($data['training_formats']) && is_array($data['training_formats'])) ? array_map('sanitize_text_field', $data['training_formats']) : [],
'training_locations' => (!empty($data['training_locations']) && is_array($data['training_locations'])) ? array_map('sanitize_text_field', $data['training_locations']) : [],
'training_resources' => (!empty($data['training_resources']) && is_array($data['training_resources'])) ? array_map('sanitize_text_field', $data['training_resources']) : [],
'application_details' => wp_kses_post($data['application_details']),
'annual_revenue_target' => !empty($data['annual_revenue_target']) ? intval($data['annual_revenue_target']) : '',
'account_status' => 'pending' // Set initial status
];
foreach ($meta_fields as $key => $value) {
update_user_meta($user_id, $key, $value);
}
error_log('[HVAC REG DEBUG] User meta updated for user ID: ' . $user_id);
// --- Handle Profile Image Upload ---
// Note: handle_profile_image_upload uses media_handle_upload which expects the key from $_FILES
if ($profile_image_data) {
error_log('[HVAC REG DEBUG] Attempting profile image upload for user ID: ' . $user_id);
// We don't need the return value here unless we want to report specific upload errors
$this->handle_profile_image_upload($user_id, $profile_image_data); // Pass the $_FILES entry
}
// --- Create Organizer Profile ---
error_log('[HVAC REG DEBUG] Attempting organizer profile creation for user ID: ' . $user_id);
$organizer_id = $this->create_organizer_profile($user_id, $meta_fields); // Pass sanitized meta fields
if ($organizer_id) {
error_log('[HVAC REG DEBUG] Organizer profile created/updated. ID: ' . $organizer_id);
update_user_meta($user_id, 'hvac_organizer_id', $organizer_id);
} else {
error_log('[HVAC REG DEBUG] Organizer profile creation failed for user ID: ' . $user_id);
// Consider returning an error if this is critical
// return new WP_Error('organizer_creation', 'Failed to create the associated organizer profile.');
}
// --- Create Training Venue (if requested) ---
if (isset($meta_fields['create_venue']) && $meta_fields['create_venue'] === 'Yes') {
error_log('[HVAC REG DEBUG] Attempting venue creation for user ID: ' . $user_id);
$venue_id = $this->create_training_venue($user_id, $meta_fields); // Pass sanitized meta fields
if ($venue_id) {
error_log('[HVAC REG DEBUG] Venue created/updated. ID: ' . $venue_id);
update_user_meta($user_id, 'hvac_venue_id', $venue_id);
} else {
error_log('[HVAC REG DEBUG] Venue creation failed for user ID: ' . $user_id);
// Consider returning an error if this is critical
// return new WP_Error('venue_creation', 'Failed to create the associated training venue.');
}
}
// --- Set Account Status to Pending ---
// This is already done via user meta, but could also involve custom capabilities or flags
// update_user_meta($user_id, 'account_status', 'pending'); // Redundant if set above
return $user_id; // Return user ID on success
}
/**
* Create or update an Organizer profile linked to the user using sanitized data.
*
* @param int $user_id The user ID.
* @param array $meta_data Array of sanitized user meta data.
* @return int|false Organizer Post ID on success, false on failure.
*/
private function create_organizer_profile($user_id, $meta_data) {
if (!class_exists('Tribe__Events__Main') || !function_exists('tribe_create_organizer')) {
error_log('[HVAC REG DEBUG] The Events Calendar function tribe_create_organizer not found.');
return false;
}
$organizer_data = array(
'Organizer' => $meta_data['business_name'], // Use sanitized business name
'Phone' => $meta_data['business_phone'],
'Website' => $meta_data['business_website'],
'Email' => $meta_data['business_email'],
'Description' => $meta_data['business_description'],
'post_status' => 'publish', // Publish organizer immediately
'post_author' => $user_id // Associate with the new user
);
// Check if an organizer already exists for this user
$existing_organizer_id = get_user_meta($user_id, 'hvac_organizer_id', true);
if ($existing_organizer_id && get_post_type($existing_organizer_id) === Tribe__Events__Main::ORGANIZER_POST_TYPE) {
// Update existing organizer
$organizer_data['ID'] = $existing_organizer_id;
$organizer_id = tribe_update_organizer($existing_organizer_id, $organizer_data);
error_log('[HVAC REG DEBUG] Updated existing organizer ID: ' . $existing_organizer_id);
} else {
// Create new organizer
$organizer_id = tribe_create_organizer($organizer_data);
error_log('[HVAC REG DEBUG] Created new organizer.');
}
if (is_wp_error($organizer_id)) {
error_log('[HVAC REG DEBUG] Error creating/updating organizer: ' . $organizer_id->get_error_message());
return false;
} elseif (!$organizer_id || $organizer_id === 0) { // Check for 0 as well
error_log('[HVAC REG DEBUG] tribe_create/update_organizer returned false or 0.');
return false;
}
return (int) $organizer_id;
}
/**
* Create or update a Venue profile linked to the user using sanitized data.
*
* @param int $user_id The user ID.
* @param array $meta_data Array of sanitized user meta data.
* @return int|false Venue Post ID on success, false on failure.
*/
private function create_training_venue($user_id, $meta_data) {
if (!class_exists('Tribe__Events__Main') || !function_exists('tribe_create_venue')) {
error_log('[HVAC REG DEBUG] The Events Calendar function tribe_create_venue not found.');
return false;
}
// Use the already processed state/province from meta
$state_province = $meta_data['user_state'];
$venue_data = array(
'Venue' => $meta_data['business_name'] . ' Training Venue', // Venue name from sanitized meta
'Country' => $meta_data['user_country'],
'Address' => '', // TEC doesn't have a single address line, use City/State/Zip
'City' => $meta_data['user_city'],
'StateProvince' => $state_province,
'State' => $state_province, // Also set State field
'Province' => $state_province, // Also set Province field
'Zip' => $meta_data['user_zip'],
'Phone' => $meta_data['business_phone'],
'Website' => $meta_data['business_website'],
'post_status' => 'publish', // Publish venue immediately
'post_author' => $user_id // Associate with the new user
);
// Check if a venue already exists for this user
$existing_venue_id = get_user_meta($user_id, 'hvac_venue_id', true);
if ($existing_venue_id && get_post_type($existing_venue_id) === Tribe__Events__Main::VENUE_POST_TYPE) {
// Update existing venue
$venue_data['ID'] = $existing_venue_id;
$venue_id = tribe_update_venue($existing_venue_id, $venue_data);
error_log('[HVAC REG DEBUG] Updated existing venue ID: ' . $existing_venue_id);
} else {
// Create new venue
$venue_id = tribe_create_venue($venue_data);
error_log('[HVAC REG DEBUG] Created new venue.');
}
if (is_wp_error($venue_id)) {
error_log('[HVAC REG DEBUG] Error creating/updating venue: ' . $venue_id->get_error_message());
return false;
} elseif (!$venue_id || $venue_id === 0) { // Check for 0 as well
error_log('[HVAC REG DEBUG] tribe_create/update_venue returned false or 0.');
return false;
}
return (int) $venue_id;
}
/**
* Send notification email to admin about new registration
*
* @param int $user_id The ID of the newly registered user.
* @param array $data The raw submitted form data (used for notification content).
*/
private function send_admin_notification($user_id, $data) {
$admin_email = get_option('admin_email');
if (!$admin_email) {
error_log('[HVAC REG DEBUG] Admin email not configured. Cannot send notification.');
return;
}
$user_info = get_userdata($user_id);
if (!$user_info) {
error_log('[HVAC REG DEBUG] Could not get user data for notification. User ID: ' . $user_id);
return;
}
$subject = sprintf('%s - New HVAC Trainer Registration Pending Approval', get_bloginfo('name'));
// Use sanitized data for the email body where appropriate
$message = "A new HVAC trainer has registered and is awaiting approval.\n\n";
$message .= "Details:\n";
$message .= "Username: " . $user_info->user_login . "\n";
$message .= "Email: " . $user_info->user_email . "\n";
// Use the sanitized first/last name from user_info if available, fallback to data
$first_name = $user_info->first_name ?: sanitize_text_field($data['first_name']);
$last_name = $user_info->last_name ?: sanitize_text_field($data['last_name']);
$message .= "Name: " . $first_name . " " . $last_name . "\n";
$message .= "Business Name: " . sanitize_text_field($data['business_name']) . "\n"; // Use raw data as meta might not be fully updated yet? Safer to use raw.
$message .= "Application Details:\n" . wp_kses_post($data['application_details']) . "\n\n"; // Use wp_kses_post for safety
// Add link to user profile in admin
$profile_link = admin_url('user-edit.php?user_id=' . $user_id);
$message .= "Approve/Deny User: " . $profile_link . "\n";
$headers = array('Content-Type: text/plain; charset=UTF-8');
if (wp_mail($admin_email, $subject, $message, $headers)) {
error_log('[HVAC REG DEBUG] Admin notification email sent successfully to ' . $admin_email);
} else {
error_log('[HVAC REG DEBUG] Failed to send admin notification email to ' . $admin_email);
// Consider adding an error to the transient if email failure is critical?
// $errors['notification'] = 'Admin notification failed. Registration complete but please contact support.';
}
}
// TODO: Add send_user_pending_notification()
// TODO: Add send_user_approved_notification()
// TODO: Add send_user_denied_notification()
/**
* Get list of countries (simplified)
*/
private function get_country_list() {
// In a real application, use a more comprehensive list or library
return array(
'US' => 'United States',
'CA' => 'Canada',
// Add more countries as needed
'GB' => 'United Kingdom',
'AU' => 'Australia',
// ...
);
}
/**
* Get list of US states
*/
private function get_us_states() {
// Use state abbreviations as keys if preferred by JS/validation
return array(
'AL' => 'Alabama', 'AK' => 'Alaska', 'AZ' => 'Arizona', 'AR' => 'Arkansas', 'CA' => 'California',
'CO' => 'Colorado', 'CT' => 'Connecticut', 'DE' => 'Delaware', 'DC' => 'District of Columbia', 'FL' => 'Florida',
'GA' => 'Georgia', 'HI' => 'Hawaii', 'ID' => 'Idaho', 'IL' => 'Illinois', 'IN' => 'Indiana',
'IA' => 'Iowa', 'KS' => 'Kansas', 'KY' => 'Kentucky', 'LA' => 'Louisiana', 'ME' => 'Maine',
'MD' => 'Maryland', 'MA' => 'Massachusetts', 'MI' => 'Michigan', 'MN' => 'Minnesota', 'MS' => 'Mississippi',
'MO' => 'Missouri', 'MT' => 'Montana', 'NE' => 'Nebraska', 'NV' => 'Nevada', 'NH' => 'New Hampshire',
'NJ' => 'New Jersey', 'NM' => 'New Mexico', 'NY' => 'New York', 'NC' => 'North Carolina', 'ND' => 'North Dakota',
'OH' => 'Ohio', 'OK' => 'Oklahoma', 'OR' => 'Oregon', 'PA' => 'Pennsylvania', 'RI' => 'Rhode Island',
'SC' => 'South Carolina', 'SD' => 'South Dakota', 'TN' => 'Tennessee', 'TX' => 'Texas', 'UT' => 'Utah',
'VT' => 'Vermont', 'VA' => 'Virginia', 'WA' => 'Washington', 'WV' => 'West Virginia', 'WI' => 'Wisconsin',
'WY' => 'Wyoming'
);
}
/**
* Get list of Canadian provinces
*/
private function get_canadian_provinces() {
// Use province abbreviations as keys if preferred by JS/validation
return array(
'AB' => 'Alberta', 'BC' => 'British Columbia', 'MB' => 'Manitoba', 'NB' => 'New Brunswick',
'NL' => 'Newfoundland and Labrador', 'NS' => 'Nova Scotia', 'ON' => 'Ontario', 'PE' => 'Prince Edward Island',
'QC' => 'Quebec', 'SK' => 'Saskatchewan', 'NT' => 'Northwest Territories', 'NU' => 'Nunavut', 'YT' => 'Yukon'
);
}
} // End class HVAC_Registration