979 lines
56 KiB
PHP
979 lines
56 KiB
PHP
<?php
|
|
/**
|
|
* Handles the HVAC trainer profile editing functionality.
|
|
*
|
|
* @package HVAC Community Events
|
|
* @subpackage Includes/Community
|
|
* @author Roo
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
class HVAC_Profile {
|
|
|
|
const PROFILE_ACTION = 'hvac_update_profile'; // Action name for admin-post
|
|
const TRANSIENT_PREFIX = 'hvac_profile_'; // Prefix for transients
|
|
|
|
private static $instance = null; // Singleton instance
|
|
|
|
/**
|
|
* Get Singleton instance.
|
|
*
|
|
* @return HVAC_Profile
|
|
*/
|
|
public static function instance() {
|
|
if (is_null(self::$instance)) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Private constructor to prevent direct instantiation.
|
|
*/
|
|
private function __construct() { // Make constructor private
|
|
// Register shortcode for profile form
|
|
add_shortcode('hvac_trainer_profile', array($this, 'render_profile_form'));
|
|
|
|
// Enqueue styles and scripts (reuse registration styles for now)
|
|
add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts'));
|
|
|
|
// Hook to a later action and check for our specific POST action
|
|
add_action('wp_loaded', array($this, 'maybe_process_profile_submission'));
|
|
|
|
// <<< ADDED: Prevent canonical redirect from stripping our success param
|
|
add_filter('redirect_canonical', array($this, 'prevent_canonical_redirect_on_success'), 10, 2); // Restore filter
|
|
}
|
|
|
|
/**
|
|
* Prevents canonical redirects on the profile page if our success query var is present.
|
|
*
|
|
* @param string $redirect_url The redirect URL.
|
|
* @param string $requested_url The requested URL.
|
|
* @return string|false The redirect URL or false to prevent redirect.
|
|
*/
|
|
public function prevent_canonical_redirect_on_success($redirect_url, $requested_url) {
|
|
// Only interfere if it's the profile page and our success flag is set
|
|
// Use get_queried_object_id() to be more robust than is_page('slug')
|
|
$profile_page_id = get_page_by_path('trainer-profile', OBJECT, 'page') ? get_page_by_path('trainer-profile', OBJECT, 'page')->ID : null;
|
|
|
|
if ($profile_page_id && is_page($profile_page_id) && isset($_GET['profile_updated'])) {
|
|
// Check if the redirect is simply adding/removing a trailing slash to our success URL
|
|
// Allow this specific type of canonical redirect to proceed.
|
|
$success_url_base = home_url('/trainer-profile/');
|
|
$success_url_with_flag = add_query_arg('profile_updated', '1', $success_url_base);
|
|
|
|
// Compare URLs ignoring the trailing slash
|
|
if (untrailingslashit($redirect_url) === untrailingslashit($success_url_with_flag)) {
|
|
return $redirect_url; // Allow this specific redirect
|
|
}
|
|
// Otherwise, prevent any other canonical redirect on this specific request
|
|
// error_log("[DEBUG CANONICAL] Preventing redirect from {$requested_url} to {$redirect_url}"); // Optional debug
|
|
return false;
|
|
}
|
|
return $redirect_url; // Allow all other canonical redirects
|
|
}
|
|
|
|
|
|
/**
|
|
* Checks if the profile form was submitted and processes it.
|
|
* Hooked to wp_loaded.
|
|
*/
|
|
public function maybe_process_profile_submission() {
|
|
if (isset($_POST['action']) && $_POST['action'] === self::PROFILE_ACTION) {
|
|
$this->process_profile_submission();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Enqueues styles and scripts. Reuses registration form styles.
|
|
*/
|
|
public function enqueue_scripts() {
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] Method called.'); // Log method entry
|
|
// Only enqueue on pages where the shortcode might be present
|
|
// A more robust check might involve checking post content or using a flag
|
|
$profile_page_object = get_page_by_path('trainer-profile', OBJECT, 'page');
|
|
$profile_page_id = $profile_page_object ? $profile_page_object->ID : null;
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] Profile Page ID found: ' . print_r($profile_page_id, true)); // Log page ID result
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] is_page check result: ' . (is_page($profile_page_id) ? 'true' : 'false')); // Log is_page result
|
|
|
|
// More robust check: See if the current post content contains our shortcode
|
|
global $post;
|
|
$should_enqueue = false;
|
|
if (is_a($post, 'WP_Post') && has_shortcode($post->post_content, 'hvac_trainer_profile')) {
|
|
$should_enqueue = true;
|
|
}
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] Shortcode check result: ' . ($should_enqueue ? 'true' : 'false')); // Log shortcode check
|
|
|
|
// if ($profile_page_id && is_page($profile_page_id)) { // Original check
|
|
if ($should_enqueue) { // Use shortcode check instead
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] Condition met, enqueuing scripts/styles.'); // Log condition met
|
|
wp_enqueue_style(
|
|
'hvac-registration-style',
|
|
HVAC_CE_PLUGIN_URL . 'assets/css/hvac-registration.css',
|
|
array(), // Dependencies
|
|
HVAC_CE_VERSION
|
|
);
|
|
wp_enqueue_script(
|
|
'hvac-registration-script',
|
|
HVAC_CE_PLUGIN_URL . 'assets/js/hvac-registration.js',
|
|
array('jquery'), // Dependencies
|
|
HVAC_CE_VERSION,
|
|
true // Load in footer
|
|
);
|
|
// Pass country/state data to JS (same as registration)
|
|
$countries = $this->get_country_list();
|
|
$us_states = $this->get_us_states();
|
|
$ca_provinces = $this->get_canadian_provinces();
|
|
// Add debug logging
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] Countries: ' . print_r($countries, true));
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] US States: ' . print_r($us_states, true));
|
|
error_log('[DEBUG HVAC_Profile::enqueue_scripts] CA Provinces: ' . print_r($ca_provinces, true));
|
|
|
|
wp_localize_script('hvac-registration-script', 'hvac_reg_vars', array(
|
|
'ajax_url' => admin_url('admin-ajax.php'), // If needed for future AJAX
|
|
'countries' => $countries,
|
|
'us_states' => $us_states,
|
|
'ca_provinces' => $ca_provinces,
|
|
'selected_country' => '', // Will be populated dynamically if needed
|
|
'selected_state' => '' // Will be populated dynamically if needed
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders the profile form shortcode.
|
|
* Handles security checks and retrieves messages from transients.
|
|
*/
|
|
public function render_profile_form() {
|
|
error_log('[DEBUG PROFILE RENDER] Entering render_profile_form'); // Log entry
|
|
// Ensure instance exists (runs constructor and adds hooks) when shortcode is rendered
|
|
self::instance(); // Restore instantiation via shortcode render
|
|
|
|
// --- Security Check ---
|
|
if (!is_user_logged_in() || !current_user_can('edit_hvac_profile')) { // Use appropriate capability
|
|
return '<p>You must be logged in as a trainer to view this page.</p>';
|
|
}
|
|
|
|
$user_id = get_current_user_id();
|
|
$errors = [];
|
|
$success_message = '';
|
|
$submitted_data = [];
|
|
|
|
$output = ''; // Build output string
|
|
|
|
// Check for messages/errors from redirect
|
|
if (isset($_GET['profile_updated']) && $_GET['profile_updated'] === '1') {
|
|
$success_message = 'Profile updated successfully.';
|
|
$output .= '<!-- DEBUG_SUCCESS_FLAG_DETECTED -->'; // Keep debug marker
|
|
$output .= '<div class="hvac-notice hvac-success"><p>' . esc_html($success_message) . '</p></div>'; // Append to output
|
|
} elseif (isset($_GET['profile_error']) && $_GET['profile_error'] === '1' && isset($_GET['tid'])) {
|
|
$transient_id_from_url = sanitize_key($_GET['tid']);
|
|
$transient_key = self::TRANSIENT_PREFIX . $transient_id_from_url;
|
|
|
|
$transient_data = get_transient($transient_key);
|
|
|
|
if ($transient_data && is_array($transient_data)) {
|
|
$errors = $transient_data['errors'] ?? [];
|
|
$submitted_data = $transient_data['data'] ?? [];
|
|
delete_transient($transient_key);
|
|
} else {
|
|
$errors['transient'] = 'Could not retrieve submission details. Please try again.';
|
|
}
|
|
if (!empty($errors)) {
|
|
$output .= '<div class="hvac-errors">'; // Append to output
|
|
foreach ($errors as $error_key => $error_message) {
|
|
$output .= '<p class="error-message"><strong>Error:</strong> ' . esc_html($error_message) . '</p>'; // Append to output
|
|
}
|
|
$output .= '</div>'; // Append to output
|
|
}
|
|
}
|
|
|
|
// Display the form HTML (needs to return instead of echo now)
|
|
$output .= $this->display_profile_form_html($user_id, $errors, $submitted_data); // <<< Pass submitted_data, append output
|
|
|
|
error_log('[DEBUG PROFILE RENDER] Exiting render_profile_form'); // Log exit
|
|
return $output; // Return the built string
|
|
}
|
|
|
|
/**
|
|
* Displays the actual profile form HTML.
|
|
* NOW RETURNS HTML STRING INSTEAD OF ECHOING.
|
|
*
|
|
* @param int $user_id The ID of the current user.
|
|
* @param array $errors Array of validation errors.
|
|
* @param array $submitted_data Array of submitted form data (used for repopulation on error).
|
|
* @return string Form HTML.
|
|
*/
|
|
private function display_profile_form_html($user_id, $errors = [], $submitted_data = []) { // <<< Added $submitted_data param
|
|
error_log('[DEBUG PROFILE RENDER] Entering display_profile_form_html for user ID: ' . $user_id); // Log entry
|
|
$current_user = get_userdata($user_id);
|
|
if (!$current_user) {
|
|
return '<p>Error: Could not load user data.</p>'; // Return instead of echo
|
|
}
|
|
|
|
// Fetch user meta data - adapt keys from registration logic
|
|
$meta_keys = [
|
|
'first_name', 'last_name', 'description', // Core WP fields
|
|
'user_url', // Core WP field
|
|
'user_linkedin', 'personal_accreditation', 'business_name',
|
|
'business_phone', 'business_email', 'business_website', 'business_description',
|
|
'user_country', 'user_state', 'user_city', 'user_zip',
|
|
'business_type', 'training_audience', 'training_formats',
|
|
'training_locations', 'training_resources',
|
|
'profile_image_id', // Store attachment ID instead of URL
|
|
'linked_venue_id' // Store linked venue post ID
|
|
];
|
|
$user_meta = [];
|
|
foreach ($meta_keys as $key) {
|
|
// Core WP fields are directly on the user object
|
|
if (isset($current_user->$key)) {
|
|
$user_meta[$key] = $current_user->$key;
|
|
} else {
|
|
$user_meta[$key] = get_user_meta($user_id, $key, true);
|
|
}
|
|
}
|
|
// Special handling for user_email and display_name from user object
|
|
$user_meta['user_email'] = $current_user->user_email;
|
|
$user_meta['display_name'] = $current_user->display_name;
|
|
|
|
// Prioritize submitted data (if available, e.g., after error) over stored meta for repopulation
|
|
$form_data = !empty($submitted_data) ? $submitted_data : $user_meta; // <<< Use submitted data if present
|
|
|
|
// Ensure array types for checkboxes/multiselects using the correct data source
|
|
$array_keys = ['training_audience', 'training_formats', 'training_locations', 'training_resources'];
|
|
foreach($array_keys as $key) {
|
|
if (!isset($form_data[$key]) || !is_array($form_data[$key])) { // Check form_data
|
|
$form_data[$key] = []; // Default to empty array if not set or not array
|
|
}
|
|
}
|
|
|
|
// Get profile image URL (still based on stored meta)
|
|
$profile_image_url = '';
|
|
if (!empty($user_meta['profile_image_id']) && is_numeric($user_meta['profile_image_id'])) {
|
|
$profile_image_url = wp_get_attachment_image_url((int)$user_meta['profile_image_id'], 'thumbnail'); // Or another appropriate size
|
|
}
|
|
|
|
// Get linked venue info (still based on stored meta)
|
|
$linked_venue_id = $user_meta['linked_venue_id'] ?? null;
|
|
$venue_info = '';
|
|
if ($linked_venue_id && get_post_status($linked_venue_id) === 'publish') {
|
|
$venue_title = get_the_title($linked_venue_id);
|
|
$venue_url = get_permalink($linked_venue_id); // Or admin edit link if preferred
|
|
$venue_info = 'Linked Training Venue: <a href="' . esc_url($venue_url) . '" target="_blank">' . esc_html($venue_title) . '</a>';
|
|
// TODO: Add more venue details if needed (address etc.)
|
|
} elseif ($linked_venue_id) {
|
|
$venue_info = 'Linked Training Venue: (Venue not published or found)';
|
|
} else {
|
|
$venue_info = 'No Training Venue linked to this profile.';
|
|
}
|
|
|
|
// Start building HTML string
|
|
$html = '<div class="hvac-profile-form hvac-registration-form">'; // Reuse registration form class
|
|
$html .= '<h2>Edit Trainer Profile</h2>';
|
|
|
|
$html .= '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" id="hvac-trainer-profile-form" enctype="multipart/form-data" novalidate>';
|
|
$html .= '<input type="hidden" name="action" value="' . esc_attr(self::PROFILE_ACTION) . '">';
|
|
$html .= wp_nonce_field(self::PROFILE_ACTION, 'hvac_profile_nonce', true, false); // Return nonce field instead of echoing
|
|
|
|
// Account Information
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Account Information</h3>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="user_email"><strong>Email *</strong></label>';
|
|
$html .= '<input type="email" name="user_email" id="user_email" value="' . esc_attr($form_data['user_email'] ?? '') . '" required aria-describedby="user_email_error">';
|
|
if (isset($errors['user_email'])) $html .= '<p class="error-message" id="user_email_error">' . esc_html($errors['user_email']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row form-row-half">';
|
|
$html .= '<div>';
|
|
$html .= '<label for="user_pass">New Password</label>';
|
|
$html .= '<input type="password" name="user_pass" id="user_pass" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" title="Password must be at least 8 characters long, and include at least one uppercase letter, one lowercase letter, and one number." aria-describedby="user_pass_hint user_pass_error">';
|
|
$html .= '<small id="user_pass_hint">Leave blank to keep current password. Must be 8+ chars, upper, lower, number.</small>';
|
|
if (isset($errors['user_pass'])) $html .= '<p class="error-message" id="user_pass_error">' . esc_html($errors['user_pass']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div>';
|
|
$html .= '<label for="confirm_password">Confirm New Password</label>';
|
|
$html .= '<input type="password" name="confirm_password" id="confirm_password" aria-describedby="confirm_password_error">';
|
|
if (isset($errors['confirm_password'])) $html .= '<p class="error-message" id="confirm_password_error">' . esc_html($errors['confirm_password']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="current_password"><strong>Current Password *</strong></label>';
|
|
$html .= '<input type="password" name="current_password" id="current_password" required aria-describedby="current_password_hint current_password_error">';
|
|
$html .= '<small id="current_password_hint">Required to update email or password.</small>';
|
|
if (isset($errors['current_password'])) $html .= '<p class="error-message" id="current_password_error">' . esc_html($errors['current_password']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Account Info
|
|
|
|
// Personal Information Section
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Personal Information</h3>';
|
|
$html .= '<div class="form-row form-row-half">';
|
|
$html .= '<div>';
|
|
$html .= '<label for="first_name"><strong>First Name *</strong></label>';
|
|
$html .= '<input type="text" name="first_name" id="first_name" value="' . esc_attr($form_data['first_name'] ?? '') . '" required aria-describedby="first_name_error">';
|
|
if (isset($errors['first_name'])) $html .= '<p class="error-message" id="first_name_error">' . esc_html($errors['first_name']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div>';
|
|
$html .= '<label for="last_name"><strong>Last Name *</strong></label>';
|
|
$html .= '<input type="text" name="last_name" id="last_name" value="' . esc_attr($form_data['last_name'] ?? '') . '" required aria-describedby="last_name_error">';
|
|
if (isset($errors['last_name'])) $html .= '<p class="error-message" id="last_name_error">' . esc_html($errors['last_name']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="display_name"><strong>Display Name *</strong></label>';
|
|
$html .= '<input type="text" name="display_name" id="display_name" value="' . esc_attr($form_data['display_name'] ?? '') . '" required aria-describedby="display_name_hint display_name_error">';
|
|
$html .= '<small id="display_name_hint">This will be the name displayed to other users on the site.</small>';
|
|
if (isset($errors['display_name'])) $html .= '<p class="error-message" id="display_name_error">' . esc_html($errors['display_name']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row form-row-half">';
|
|
$html .= '<div>';
|
|
$html .= '<label for="user_url">Personal Website (optional)</label>';
|
|
$html .= '<input type="url" name="user_url" id="user_url" value="' . esc_attr($form_data['user_url'] ?? '') . '" aria-describedby="user_url_error">';
|
|
if (isset($errors['user_url'])) $html .= '<p class="error-message" id="user_url_error">' . esc_html($errors['user_url']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div>';
|
|
$html .= '<label for="user_linkedin">LinkedIn Profile URL (optional)</label>';
|
|
$html .= '<input type="url" name="user_linkedin" id="user_linkedin" value="' . esc_attr($form_data['user_linkedin'] ?? '') . '" aria-describedby="user_linkedin_error">';
|
|
if (isset($errors['user_linkedin'])) $html .= '<p class="error-message" id="user_linkedin_error">' . esc_html($errors['user_linkedin']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="personal_accreditation">Personal Accreditation (optional)</label>';
|
|
$html .= '<input type="text" name="personal_accreditation" id="personal_accreditation" value="' . esc_attr($form_data['personal_accreditation'] ?? '') . '" aria-describedby="personal_accreditation_hint">';
|
|
$html .= '<small id="personal_accreditation_hint">Enter your abbreviated accreditations separated by commas.</small>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="description"><strong>Biographical Info *</strong></label>';
|
|
$html .= '<textarea name="description" id="description" rows="4" required aria-describedby="description_hint description_error">' . esc_textarea($form_data['description'] ?? '') . '</textarea>';
|
|
$html .= '<small id="description_hint">A short bio about yourself. This will be displayed on your profile page.</small>';
|
|
if (isset($errors['description'])) $html .= '<p class="error-message" id="description_error">' . esc_html($errors['description']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="profile_image">Profile Image (optional)</label>';
|
|
if ($profile_image_url) {
|
|
$html .= '<div class="current-profile-image">';
|
|
$html .= '<img src="' . esc_url($profile_image_url) . '" alt="Current Profile Image" style="max-width: 100px; height: auto; margin-bottom: 10px;">';
|
|
$html .= '<label style="display: block; margin-bottom: 5px;">';
|
|
$html .= '<input type="checkbox" name="delete_profile_image" value="1"> Delete current image';
|
|
$html .= '</label>';
|
|
$html .= '</div>';
|
|
}
|
|
$html .= '<input type="file" name="profile_image" id="profile_image" accept="image/jpeg,image/png,image/gif" aria-describedby="profile_image_hint profile_image_error">';
|
|
$html .= '<small id="profile_image_hint">Upload a new image to replace the current one (.jpg, .png, .gif).</small>';
|
|
if (isset($errors['profile_image'])) $html .= '<p class="error-message" id="profile_image_error">' . esc_html($errors['profile_image']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Personal Info
|
|
|
|
// Business Information Section
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Business Information</h3>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="business_name"><strong>Business Name *</strong></label>';
|
|
$html .= '<input type="text" name="business_name" id="business_name" value="' . esc_attr($form_data['business_name'] ?? '') . '" required aria-describedby="business_name_error">';
|
|
if (isset($errors['business_name'])) $html .= '<p class="error-message" id="business_name_error">' . esc_html($errors['business_name']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row form-row-half">';
|
|
$html .= '<div>';
|
|
$html .= '<label for="business_phone"><strong>Business Phone *</strong></label>';
|
|
$html .= '<input type="tel" name="business_phone" id="business_phone" value="' . esc_attr($form_data['business_phone'] ?? '') . '" required aria-describedby="business_phone_error">';
|
|
if (isset($errors['business_phone'])) $html .= '<p class="error-message" id="business_phone_error">' . esc_html($errors['business_phone']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div>';
|
|
$html .= '<label for="business_email"><strong>Business Email *</strong></label>';
|
|
$html .= '<input type="email" name="business_email" id="business_email" value="' . esc_attr($form_data['business_email'] ?? '') . '" required aria-describedby="business_email_error">';
|
|
if (isset($errors['business_email'])) $html .= '<p class="error-message" id="business_email_error">' . esc_html($errors['business_email']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="business_website">Business Website (optional)</label>';
|
|
$html .= '<input type="url" name="business_website" id="business_website" value="' . esc_attr($form_data['business_website'] ?? '') . '" aria-describedby="business_website_error">';
|
|
if (isset($errors['business_website'])) $html .= '<p class="error-message" id="business_website_error">' . esc_html($errors['business_website']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="business_description"><strong>Business Description *</strong></label>';
|
|
$html .= '<textarea name="business_description" id="business_description" rows="4" required aria-describedby="business_description_error">' . esc_textarea($form_data['business_description'] ?? '') . '</textarea>';
|
|
if (isset($errors['business_description'])) $html .= '<p class="error-message" id="business_description_error">' . esc_html($errors['business_description']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Business Info
|
|
|
|
// Address Information Section
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Address Information</h3>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="user_country"><strong>Country *</strong></label>';
|
|
$html .= '<select name="user_country" id="user_country" required aria-describedby="user_country_error">';
|
|
$html .= '<option value="">Select Country</option>';
|
|
$html .= '<option value="United States" ' . selected($form_data['user_country'] ?? '', 'United States', false) . '>United States</option>';
|
|
$html .= '<option value="Canada" ' . selected($form_data['user_country'] ?? '', 'Canada', false) . '>Canada</option>';
|
|
$html .= '<option value="" disabled>---</option>';
|
|
$countries = $this->get_country_list();
|
|
foreach ($countries as $code => $name) {
|
|
if ($code !== 'US' && $code !== 'CA') {
|
|
$html .= '<option value="' . esc_attr($name) . '" ' . selected($form_data['user_country'] ?? '', $name, false) . '>' . esc_html($name) . '</option>';
|
|
}
|
|
}
|
|
$html .= '</select>';
|
|
if (isset($errors['user_country'])) $html .= '<p class="error-message" id="user_country_error">' . esc_html($errors['user_country']) . '</p>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row form-row-half">';
|
|
$html .= '<div>';
|
|
$html .= '<label for="user_state"><strong>State/Province *</strong></label>';
|
|
$html .= '<select name="user_state" id="user_state" required aria-describedby="user_state_error">';
|
|
$html .= '<option value="">Select State/Province</option>';
|
|
$html .= '<option value="Other" ' . selected($form_data['user_state'] ?? '', 'Other', false) . '>Other</option>';
|
|
$selected_state = $form_data['user_state'] ?? ''; // Use form_data
|
|
if (!empty($selected_state) && $selected_state !== 'Other') {
|
|
$html .= '<option value="' . esc_attr($selected_state) . '" selected>' . esc_html($selected_state) . '</option>';
|
|
}
|
|
$html .= '</select>';
|
|
$other_style = (($form_data['user_state'] ?? '') === 'Other' && ($form_data['user_country'] ?? '') !== 'United States' && ($form_data['user_country'] ?? '') !== 'Canada') ? '' : 'display:none;';
|
|
$html .= '<input type="text" name="user_state_other" id="user_state_other" value="' . esc_attr($form_data['user_state_other'] ?? '') . '" style="' . $other_style . ' margin-top: 0.5rem;" placeholder="Enter your state/province" aria-describedby="user_state_other_error">';
|
|
if (isset($errors['user_state'])) $html .= '<p class="error-message" id="user_state_error">' . esc_html($errors['user_state']) . '</p>';
|
|
if (isset($errors['user_state_other'])) $html .= '<p class="error-message" id="user_state_other_error">' . esc_html($errors['user_state_other']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '<div>';
|
|
$html .= '<label for="user_city"><strong>City *</strong></label>';
|
|
$html .= '<input type="text" name="user_city" id="user_city" value="' . esc_attr($form_data['user_city'] ?? '') . '" required aria-describedby="user_city_error">';
|
|
if (isset($errors['user_city'])) $html .= '<p class="error-message" id="user_city_error">' . esc_html($errors['user_city']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label for="user_zip"><strong>Zip/Postal Code *</strong></label>';
|
|
$html .= '<input type="text" name="user_zip" id="user_zip" value="' . esc_attr($form_data['user_zip'] ?? '') . '" required aria-describedby="user_zip_error">';
|
|
if (isset($errors['user_zip'])) $html .= '<p class="error-message" id="user_zip_error">' . esc_html($errors['user_zip']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Address Info
|
|
|
|
// Training Venue Section
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Training Venue</h3>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<p>' . wp_kses_post($venue_info) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Training Venue
|
|
|
|
// Training Information Section
|
|
$html .= '<div class="form-section">';
|
|
$html .= '<h3>Training Information</h3>';
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label id="business_type_label"><strong>Business Type *</strong></label>';
|
|
$html .= '<small>What type of business are you?</small>';
|
|
$html .= '<div class="radio-group" role="radiogroup" aria-labelledby="business_type_label">';
|
|
$business_types = ["Manufacturer", "Distributor", "Contractor", "Consultant", "Educator", "Government", "Other"];
|
|
foreach ($business_types as $type) {
|
|
$html .= '<label><input type="radio" name="business_type" value="' . esc_attr($type) . '" ' . checked($form_data['business_type'] ?? '', $type, false) . ' required> ' . esc_html($type) . '</label>';
|
|
}
|
|
$html .= '</div>';
|
|
if (isset($errors['business_type'])) $html .= '<p class="error-message">' . esc_html($errors['business_type']) . '</p>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label id="training_audience_label"><strong>Training Audience *</strong></label>';
|
|
$html .= '<small>Who do you offer training to? (Select all that apply)</small>';
|
|
$html .= '<div class="checkbox-group" role="group" aria-labelledby="training_audience_label">';
|
|
$audience_options = [
|
|
"Anyone" => "Anyone (open to the public)",
|
|
"Industry professionals" => "Industry professionals",
|
|
"Internal staff" => "Internal staff in my company",
|
|
"Registered students" => "Registered students/members of my org/institution"
|
|
];
|
|
$selected_audience = $form_data['training_audience'] ?? []; // Use form_data
|
|
foreach ($audience_options as $value => $label) {
|
|
$html .= '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($value) . '" ' . checked(in_array($value, $selected_audience), true, false) . '> ' . esc_html($label) . '</label>';
|
|
}
|
|
$html .= '</div>';
|
|
if (isset($errors['training_audience'])) $html .= '<p class="error-message">' . esc_html($errors['training_audience']) . '</p>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label id="training_formats_label"><strong>Training Formats *</strong></label>';
|
|
$html .= '<small>What formats of training do you offer?</small>';
|
|
$html .= '<div class="checkbox-group" role="group" aria-labelledby="training_formats_label">';
|
|
$format_options = ["In-person", "Virtual", "Hybrid", "On-demand"];
|
|
$selected_formats = $form_data['training_formats'] ?? []; // Use form_data
|
|
foreach ($format_options as $option) {
|
|
$html .= '<label><input type="checkbox" name="training_formats[]" value="' . esc_attr($option) . '" ' . checked(in_array($option, $selected_formats), true, false) . '> ' . esc_html($option) . '</label>';
|
|
}
|
|
$html .= '</div>';
|
|
if (isset($errors['training_formats'])) $html .= '<p class="error-message">' . esc_html($errors['training_formats']) . '</p>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label id="training_locations_label"><strong>Training Locations *</strong></label>';
|
|
$html .= '<small>Where are you willing to provide training? (Select all that apply)</small>';
|
|
$html .= '<div class="checkbox-group" role="group" aria-labelledby="training_locations_label">';
|
|
$location_options = ["Online", "Local", "Regional", "Travel National", "Travel International"];
|
|
$selected_locations = $form_data['training_locations'] ?? []; // Use form_data
|
|
foreach ($location_options as $option) {
|
|
$html .= '<label><input type="checkbox" name="training_locations[]" value="' . esc_attr($option) . '" ' . checked(in_array($option, $selected_locations), true, false) . '> ' . esc_html($option) . '</label>';
|
|
}
|
|
$html .= '</div>';
|
|
if (isset($errors['training_locations'])) $html .= '<p class="error-message">' . esc_html($errors['training_locations']) . '</p>';
|
|
$html .= '</div>';
|
|
|
|
$html .= '<div class="form-row">';
|
|
$html .= '<label id="training_resources_label"><strong>Training Resources *</strong></label>';
|
|
$html .= '<small>What training resources do you have access to? (Select all that apply)</small>';
|
|
$html .= '<div class="checkbox-group" role="group" aria-labelledby="training_resources_label">';
|
|
$resource_options = [
|
|
"Classroom" => "Classroom",
|
|
"Training Lab" => "Training Lab",
|
|
"Ducted Furnace(s)" => "Ducted Furnace(s)",
|
|
"Ducted Air Handler(s)" => "Ducted Air Handler(s)",
|
|
"Ducted Air Conditioner(s)" => "Ducted Air Conditioner(s)",
|
|
"Ducted Heat Pump(s)" => "Ducted Heat Pump(s)",
|
|
"Ductless Heat Pump(s)" => "Ductless Heat Pump(s)",
|
|
"Training Manuals" => "Training Manuals",
|
|
"Presentation Slides" => "Presentation Slides",
|
|
"LMS Platform / SCORM Files" => "LMS Platform / SCORM Files",
|
|
"Custom Curriculum" => "Custom Curriculum",
|
|
"Other" => "Other"
|
|
];
|
|
$selected_resources = $form_data['training_resources'] ?? []; // Use form_data
|
|
foreach ($resource_options as $value => $label) {
|
|
$html .= '<label><input type="checkbox" name="training_resources[]" value="' . esc_attr($value) . '" ' . checked(in_array($value, $selected_resources), true, false) . '> ' . esc_html($label) . '</label>';
|
|
}
|
|
$html .= '</div>';
|
|
if (isset($errors['training_resources'])) $html .= '<p class="error-message">' . esc_html($errors['training_resources']) . '</p>';
|
|
$html .= '</div>';
|
|
$html .= '</div>'; // End Training Info
|
|
|
|
$html .= '<div class="form-row submit-row">';
|
|
$html .= '<input type="submit" value="Update Profile">';
|
|
$html .= '</div>';
|
|
|
|
$html .= '</form>';
|
|
$html .= '</div>'; // End .hvac-profile-form
|
|
|
|
error_log('[DEBUG PROFILE RENDER] Exiting display_profile_form_html'); // Log exit
|
|
return $html; // Return the built string
|
|
}
|
|
|
|
|
|
/**
|
|
* Processes the profile form submission.
|
|
* Handles validation, user update, and redirects.
|
|
*/
|
|
public function process_profile_submission() {
|
|
// Verify nonce
|
|
if (!isset($_POST['hvac_profile_nonce']) || !wp_verify_nonce($_POST['hvac_profile_nonce'], self::PROFILE_ACTION)) {
|
|
wp_die('Security check failed.');
|
|
}
|
|
|
|
// Check user logged in
|
|
if (!is_user_logged_in()) {
|
|
wp_die('You must be logged in to update your profile.');
|
|
}
|
|
$user_id = get_current_user_id();
|
|
|
|
// Check capability
|
|
if (!current_user_can('edit_hvac_profile', $user_id)) { // Check capability for the specific user
|
|
wp_die('You do not have permission to edit this profile.');
|
|
}
|
|
|
|
// Sanitize POST data (basic sanitization, more specific in validation/update)
|
|
$submitted_data = stripslashes_deep($_POST);
|
|
|
|
// Validate data
|
|
$errors = $this->validate_profile_data($submitted_data, $user_id);
|
|
|
|
// Redirect back with errors if validation fails
|
|
if (!empty($errors)) {
|
|
$redirect_url = home_url('/trainer-profile/'); // Redirect back to profile page
|
|
$this->redirect_with_errors($errors, $redirect_url, $submitted_data); // <<< Pass submitted data
|
|
exit; // Stop execution after redirect
|
|
}
|
|
|
|
// Handle image upload/deletion
|
|
$image_data = $_FILES['profile_image'] ?? null;
|
|
$delete_image = isset($submitted_data['delete_profile_image']) && $submitted_data['delete_profile_image'] === '1';
|
|
|
|
// Attempt to update the user account
|
|
$update_result = $this->update_trainer_account($user_id, $submitted_data, $image_data, $delete_image);
|
|
|
|
// Handle update result
|
|
if (is_wp_error($update_result)) {
|
|
// Update failed, redirect back with error message(s)
|
|
$errors = $update_result->get_error_messages(); // Get all error messages
|
|
$error_codes = $update_result->get_error_codes();
|
|
$error_map = [];
|
|
foreach($error_codes as $index => $code) {
|
|
$error_map[$code] = $errors[$index]; // Map code to message
|
|
}
|
|
$redirect_url = home_url('/trainer-profile/');
|
|
$this->redirect_with_errors($error_map, $redirect_url, $submitted_data); // Pass error map and submitted data
|
|
exit;
|
|
} elseif ($update_result === true) {
|
|
// Success! Redirect with success flag
|
|
$redirect_url = add_query_arg('profile_updated', '1', home_url('/trainer-profile/'));
|
|
wp_safe_redirect($redirect_url);
|
|
exit;
|
|
} else {
|
|
// Should not happen if update_trainer_account always returns true or WP_Error
|
|
$errors['general'] = 'An unexpected error occurred during profile update.';
|
|
$redirect_url = home_url('/trainer-profile/');
|
|
$this->redirect_with_errors($errors, $redirect_url, $submitted_data); // Pass submitted data
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Redirects back to a URL with errors stored in a transient.
|
|
* NOW ACCEPTS SUBMITTED DATA TO STORE IN TRANSIENT.
|
|
*
|
|
* @param array $errors Array of errors (key => message).
|
|
* @param string $redirect_url URL to redirect back to.
|
|
* @param array $submitted_data The submitted form data.
|
|
*/
|
|
private function redirect_with_errors($errors, $redirect_url, $submitted_data) { // <<< Added $submitted_data param
|
|
$transient_id = wp_generate_password(12, false); // Generate a unique ID for the transient
|
|
$transient_key = self::TRANSIENT_PREFIX . $transient_id;
|
|
|
|
// Store both errors and submitted data in the transient
|
|
$transient_data = [
|
|
'errors' => $errors,
|
|
'data' => $submitted_data, // <<< Store submitted data
|
|
];
|
|
|
|
set_transient($transient_key, $transient_data, MINUTE_IN_SECONDS * 5); // Store for 5 minutes
|
|
|
|
// Add error flag and transient ID to the redirect URL
|
|
$redirect_url = add_query_arg(array(
|
|
'profile_error' => '1',
|
|
'tid' => $transient_id
|
|
), $redirect_url);
|
|
|
|
wp_safe_redirect($redirect_url);
|
|
exit;
|
|
}
|
|
|
|
|
|
/**
|
|
* Validates the submitted profile data.
|
|
* Changed from private to public for unit testing.
|
|
*
|
|
* @param array $data Submitted form data.
|
|
* @param int $user_id The ID of the user being updated.
|
|
* @return array Array of errors (empty if valid).
|
|
*/
|
|
public function validate_profile_data($data, $user_id) { // Changed from private to public
|
|
$errors = [];
|
|
$current_user = get_userdata($user_id);
|
|
|
|
// --- Account Information ---
|
|
// Email
|
|
if (empty($data['user_email'])) {
|
|
$errors['user_email'] = 'Email address is required.';
|
|
} elseif (!is_email($data['user_email'])) {
|
|
$errors['user_email'] = 'Invalid email address format.';
|
|
} elseif ($data['user_email'] !== $current_user->user_email && email_exists($data['user_email'])) {
|
|
$errors['user_email'] = 'This email address is already in use by another account.';
|
|
}
|
|
|
|
// Password (only validate if a new password is provided)
|
|
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.';
|
|
} elseif (empty($data['confirm_password'])) {
|
|
$errors['confirm_password'] = 'Please confirm your new password.';
|
|
} elseif ($data['user_pass'] !== $data['confirm_password']) {
|
|
$errors['confirm_password'] = 'Passwords do not match.';
|
|
}
|
|
}
|
|
|
|
// Current Password (required only if email or password changes)
|
|
$email_changed = isset($data['user_email']) && $data['user_email'] !== $current_user->user_email;
|
|
$password_changed = !empty($data['user_pass']);
|
|
if (($email_changed || $password_changed) && empty($data['current_password'])) {
|
|
$errors['current_password'] = 'Current password is required to update email or password.';
|
|
}
|
|
// Note: Actual check if current password is correct happens in update_trainer_account
|
|
|
|
// --- Personal Information ---
|
|
if (empty($data['first_name'])) $errors['first_name'] = 'First Name is required.';
|
|
if (empty($data['last_name'])) $errors['last_name'] = 'Last Name is required.';
|
|
if (empty($data['display_name'])) $errors['display_name'] = 'Display Name is required.';
|
|
if (!empty($data['user_url']) && !filter_var($data['user_url'], FILTER_VALIDATE_URL)) $errors['user_url'] = 'Invalid Personal Website URL format.';
|
|
if (!empty($data['user_linkedin']) && !filter_var($data['user_linkedin'], FILTER_VALIDATE_URL)) $errors['user_linkedin'] = 'Invalid LinkedIn Profile URL format.';
|
|
if (empty($data['description'])) $errors['description'] = 'Biographical Info is required.';
|
|
|
|
// Profile Image Validation (basic)
|
|
if (isset($_FILES['profile_image']) && $_FILES['profile_image']['error'] === UPLOAD_ERR_OK) {
|
|
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
|
|
$file_info = wp_check_filetype_and_ext($_FILES['profile_image']['tmp_name'], $_FILES['profile_image']['name']);
|
|
if (empty($file_info['type']) || !in_array($file_info['type'], $allowed_types)) {
|
|
$errors['profile_image'] = 'Invalid file type. Please upload a JPG, PNG, or GIF image.';
|
|
}
|
|
// Add size check if needed:
|
|
// if ($_FILES['profile_image']['size'] > MAX_UPLOAD_SIZE) {
|
|
// $errors['profile_image'] = 'File size exceeds limit.';
|
|
// }
|
|
} elseif (isset($_FILES['profile_image']) && $_FILES['profile_image']['error'] !== UPLOAD_ERR_NO_FILE && $_FILES['profile_image']['error'] !== UPLOAD_ERR_OK) {
|
|
$errors['profile_image'] = 'Error uploading profile image. Code: ' . $_FILES['profile_image']['error'];
|
|
}
|
|
|
|
|
|
// --- Business Information ---
|
|
if (empty($data['business_name'])) $errors['business_name'] = 'Business Name is required.';
|
|
if (empty($data['business_phone'])) $errors['business_phone'] = 'Business Phone is required.';
|
|
if (empty($data['business_email'])) {
|
|
$errors['business_email'] = 'Business Email is required.';
|
|
} elseif (!is_email($data['business_email'])) {
|
|
$errors['business_email'] = 'Invalid Business Email format.';
|
|
}
|
|
if (!empty($data['business_website']) && !filter_var($data['business_website'], FILTER_VALIDATE_URL)) $errors['business_website'] = 'Invalid Business Website URL format.';
|
|
if (empty($data['business_description'])) $errors['business_description'] = 'Business Description is required.';
|
|
|
|
// --- Address Information ---
|
|
if (empty($data['user_country'])) $errors['user_country'] = 'Country is required.';
|
|
if (empty($data['user_state'])) {
|
|
$errors['user_state'] = 'State/Province is required.';
|
|
} elseif ($data['user_state'] === 'Other' && empty($data['user_state_other'])) {
|
|
$errors['user_state_other'] = 'Please specify your state/province.';
|
|
}
|
|
if (empty($data['user_city'])) $errors['user_city'] = 'City is required.';
|
|
if (empty($data['user_zip'])) $errors['user_zip'] = 'Zip/Postal Code is required.';
|
|
|
|
// --- Training Information ---
|
|
if (empty($data['business_type'])) $errors['business_type'] = 'Business Type is required.';
|
|
if (empty($data['training_audience'])) $errors['training_audience'] = 'Please select at least one option for Training Audience.';
|
|
if (empty($data['training_formats'])) $errors['training_formats'] = 'Please select at least one option for Training Formats.';
|
|
if (empty($data['training_locations'])) $errors['training_locations'] = 'Please select at least one option for Training Locations.';
|
|
if (empty($data['training_resources'])) $errors['training_resources'] = 'Please select at least one option for Training Resources.';
|
|
|
|
// Ensure checkbox/multiselect data is arrays if submitted (even if empty)
|
|
$array_keys = ['training_audience', 'training_formats', 'training_locations', 'training_resources'];
|
|
foreach($array_keys as $key) {
|
|
if (isset($data[$key]) && !is_array($data[$key])) {
|
|
$errors[$key] = 'Invalid data format for ' . $key . '.';
|
|
} elseif (!isset($data[$key])) {
|
|
// If the field is required and not submitted at all (e.g., disabled JS)
|
|
if (in_array($key, ['training_audience', 'training_formats', 'training_locations', 'training_resources'])) { // Add other required array fields if any
|
|
$errors[$key] = 'Please select at least one option for ' . str_replace('_', ' ', ucfirst($key)) . '.';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return $errors;
|
|
}
|
|
|
|
|
|
/**
|
|
* Updates the user account and meta data.
|
|
*
|
|
* @param int $user_id The ID of the user to update.
|
|
* @param array $data Sanitized submitted form data.
|
|
* @param array|null $image_data Uploaded file data from $_FILES['profile_image'].
|
|
* @param bool $delete_image Whether to delete the current profile image.
|
|
* @return bool|WP_Error True on success, WP_Error on failure.
|
|
*/
|
|
private function update_trainer_account($user_id, $data, $image_data, $delete_image) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Entering function for user ID: ' . $user_id);
|
|
$update_args = array(
|
|
'ID' => $user_id,
|
|
);
|
|
|
|
// Sanitize and prepare data for wp_update_user
|
|
if (isset($data['user_email'])) {
|
|
$update_args['user_email'] = sanitize_email($data['user_email']);
|
|
}
|
|
if (!empty($data['user_pass'])) {
|
|
$update_args['user_pass'] = $data['user_pass']; // wp_update_user handles hashing
|
|
}
|
|
if (isset($data['user_url'])) {
|
|
$update_args['user_url'] = esc_url_raw($data['user_url']);
|
|
}
|
|
if (isset($data['display_name'])) {
|
|
$update_args['display_name'] = sanitize_text_field($data['display_name']);
|
|
}
|
|
if (isset($data['first_name'])) {
|
|
$update_args['first_name'] = sanitize_text_field($data['first_name']);
|
|
}
|
|
if (isset($data['last_name'])) {
|
|
$update_args['last_name'] = sanitize_text_field($data['last_name']);
|
|
}
|
|
if (isset($data['description'])) {
|
|
$update_args['description'] = sanitize_textarea_field($data['description']);
|
|
}
|
|
|
|
// Check current password if email or password is being changed
|
|
$current_user = get_userdata($user_id);
|
|
$needs_current_password_check = false;
|
|
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Checking if password or email update is needed.');
|
|
// Check if password needs updating
|
|
if (!empty($data['user_pass'])) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] New password provided.');
|
|
$needs_current_password_check = true;
|
|
}
|
|
// Check if email needs updating
|
|
if (isset($data['user_email']) && $data['user_email'] !== $current_user->user_email) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Email change detected: ' . $current_user->user_email . ' -> ' . $data['user_email']);
|
|
$needs_current_password_check = true;
|
|
}
|
|
|
|
// Check current password if needed
|
|
if ($needs_current_password_check) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Current password check required.');
|
|
if (empty($data['current_password'])) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Error: Current password missing for email/password update.');
|
|
$error = new WP_Error('missing_current_password', 'Current password is required to update email or password.');
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Returning WP_Error: ' . $error->get_error_code());
|
|
return $error;
|
|
}
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Checking current password...');
|
|
if (!wp_check_password($data['current_password'], $current_user->user_pass, $user_id)) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Error: Current password check failed for user ID: ' . $user_id);
|
|
$error = new WP_Error('incorrect_current_password', 'The current password you entered is incorrect.');
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Returning WP_Error: ' . $error->get_error_code());
|
|
return $error;
|
|
}
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Current password check successful.');
|
|
}
|
|
|
|
// Update the user core data
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Calling wp_update_user with args: ' . print_r($update_args, true));
|
|
$result = wp_update_user($update_args);
|
|
|
|
if (is_wp_error($result)) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] wp_update_user failed: ' . $result->get_error_message());
|
|
$error = new WP_Error('user_update_failed', 'Could not update user information: ' . $result->get_error_message());
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Returning WP_Error: ' . $error->get_error_code());
|
|
return $error; // Return the modified error object
|
|
}
|
|
error_log('[DEBUG UPDATE_ACCOUNT] wp_update_user successful for user ID: ' . $user_id);
|
|
|
|
// Update user meta data
|
|
$meta_to_update = [
|
|
'user_linkedin' => sanitize_text_field($data['user_linkedin'] ?? ''),
|
|
'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' => esc_url_raw($data['business_website'] ?? ''),
|
|
'business_description' => sanitize_textarea_field($data['business_description'] ?? ''),
|
|
'user_country' => sanitize_text_field($data['user_country'] ?? ''),
|
|
'user_state' => sanitize_text_field($data['user_state'] ?? ''), // Includes 'Other' or selected state
|
|
'user_state_other' => ($data['user_state'] ?? '') === 'Other' ? sanitize_text_field($data['user_state_other'] ?? '') : '', // Only save if 'Other' is selected
|
|
'user_city' => sanitize_text_field($data['user_city'] ?? ''),
|
|
'user_zip' => sanitize_text_field($data['user_zip'] ?? ''),
|
|
'business_type' => sanitize_text_field($data['business_type'] ?? ''),
|
|
'training_audience' => $data['training_audience'] ?? [], // Already validated as array or empty
|
|
'training_formats' => $data['training_formats'] ?? [],
|
|
'training_locations' => $data['training_locations'] ?? [],
|
|
'training_resources' => $data['training_resources'] ?? [],
|
|
];
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Updating user meta: ' . print_r($meta_to_update, true));
|
|
foreach ($meta_to_update as $key => $value) {
|
|
update_user_meta($user_id, $key, $value);
|
|
}
|
|
|
|
// Handle profile image upload/deletion
|
|
if ($delete_image) {
|
|
$current_image_id = get_user_meta($user_id, 'profile_image_id', true);
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Deleting profile image. Current ID: ' . $current_image_id);
|
|
if ($current_image_id) {
|
|
wp_delete_attachment($current_image_id, true);
|
|
delete_user_meta($user_id, 'profile_image_id');
|
|
}
|
|
} elseif (!empty($image_data['tmp_name'])) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Processing profile image upload: ' . print_r($image_data, true));
|
|
// Need wp-admin/includes/file.php, wp-admin/includes/image.php, wp-admin/includes/media.php
|
|
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
|
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
|
require_once(ABSPATH . 'wp-admin/includes/media.php');
|
|
|
|
// Handle the upload
|
|
// Note: media_handle_upload() expects the file input name ('profile_image' in this case)
|
|
$attachment_id = media_handle_upload('profile_image', 0); // 0 means no parent post
|
|
|
|
if (is_wp_error($attachment_id)) {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Profile image upload failed: ' . $attachment_id->get_error_message());
|
|
// Optionally return error, or just log it and continue
|
|
// return new WP_Error('image_upload_failed', 'Could not upload profile image: ' . $attachment_id->get_error_message());
|
|
} else {
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Profile image uploaded successfully. Attachment ID: ' . $attachment_id);
|
|
// Delete old image if exists
|
|
$current_image_id = get_user_meta($user_id, 'profile_image_id', true);
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Deleting old profile image. Current ID: ' . $current_image_id);
|
|
if ($current_image_id && $current_image_id != $attachment_id) {
|
|
wp_delete_attachment($current_image_id, true);
|
|
}
|
|
// Store new attachment ID
|
|
update_user_meta($user_id, 'profile_image_id', $attachment_id);
|
|
}
|
|
}
|
|
|
|
// TODO: Implement logic to update linked TEC Organizer/Venue posts if necessary
|
|
// This might involve fetching the linked venue ID and updating its details based on profile changes.
|
|
|
|
error_log('[DEBUG UPDATE_ACCOUNT] Update process completed successfully for user ID: ' . $user_id . '. Returning true.');
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns a list of countries.
|
|
* Could be expanded or loaded from a config/API.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_country_list() {
|
|
return array(
|
|
'US' => 'United States',
|
|
'CA' => 'Canada',
|
|
'GB' => 'United Kingdom',
|
|
'AU' => 'Australia',
|
|
// Add more countries as needed
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of US states.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_us_states() {
|
|
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'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of Canadian provinces.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_canadian_provinces() {
|
|
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_Profile
|