admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('hvac_attendee_nonce') )); } /** * Render attendee profile */ public function render_attendee_profile($atts) { // Check permissions - trainers and admins only if (!current_user_can('manage_hvac_events') && !current_user_can('manage_options')) { return '

You do not have permission to view attendee profiles.

'; } // Get attendee ID from URL parameter $attendee_id = isset($_GET['attendee_id']) ? intval($_GET['attendee_id']) : 0; if (!$attendee_id) { return '

No attendee specified. Please provide an attendee ID.

'; } // Get attendee data $attendee_data = $this->get_attendee_data($attendee_id); if (!$attendee_data) { return '

Attendee not found.

'; } ob_start(); include HVAC_CE_PLUGIN_DIR . 'templates/attendee/template-attendee-profile.php'; return ob_get_clean(); } /** * Get comprehensive attendee data */ public function get_attendee_data($attendee_id) { global $wpdb; // First, try to get attendee as a user $user = null; $attendee_email = ''; // Check if this is an attendee post ID $attendee_post = get_post($attendee_id); if ($attendee_post && in_array($attendee_post->post_type, array('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees'))) { // Get email from attendee meta $email_keys = array( '_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email', '_tribe_tpp_attendee_email' ); foreach ($email_keys as $key) { $email = get_post_meta($attendee_id, $key, true); if ($email && is_email($email)) { $attendee_email = $email; break; } } // Try to find user by email if ($attendee_email) { $user = get_user_by('email', $attendee_email); } } else { // Maybe this is a user ID $user = get_user_by('id', $attendee_id); if ($user) { $attendee_email = $user->user_email; } } if (!$attendee_email) { return false; } // Get profile information $profile_data = $this->get_profile_info($attendee_email, $user); // Get statistics $stats = $this->get_attendee_statistics($attendee_email); // Get timeline data $timeline = $this->get_attendee_timeline($attendee_email); return array( 'profile' => $profile_data, 'stats' => $stats, 'timeline' => $timeline, 'attendee_id' => $attendee_id, 'user_id' => $user ? $user->ID : 0 ); } /** * Get profile information */ private function get_profile_info($email, $user = null) { global $wpdb; $profile = array( 'name' => '', 'email' => $email, 'phone' => '', 'company' => '', 'state' => '', 'avatar_url' => '' ); // If we have a user, get their data if ($user) { $profile['name'] = $user->display_name; $profile['phone'] = get_user_meta($user->ID, 'phone', true); $profile['company'] = get_user_meta($user->ID, 'company', true); $profile['state'] = get_user_meta($user->ID, 'state', true); $profile['avatar_url'] = get_avatar_url($user->ID, array('size' => 150)); } // Try to get name from attendee records if not set if (empty($profile['name'])) { $name = $wpdb->get_var($wpdb->prepare(" SELECT COALESCE( MAX(CASE WHEN pm.meta_key = '_tec_tickets_commerce_full_name' THEN pm.meta_value END), MAX(CASE WHEN pm.meta_key = '_tribe_tpp_full_name' THEN pm.meta_value END), MAX(CASE WHEN pm.meta_key = '_tribe_tickets_full_name' THEN pm.meta_value END) ) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm_email ON p.ID = pm_email.post_id JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type IN ('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees') AND pm_email.meta_value = %s AND pm_email.meta_key IN ('_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email') AND pm.meta_key IN ('_tec_tickets_commerce_full_name', '_tribe_tpp_full_name', '_tribe_tickets_full_name') LIMIT 1 ", $email)); if ($name) { $profile['name'] = $name; } } // If still no name, use email prefix if (empty($profile['name'])) { $email_parts = explode('@', $email); $profile['name'] = ucwords(str_replace(array('.', '_', '-'), ' ', $email_parts[0])); } return $profile; } /** * Get attendee statistics */ private function get_attendee_statistics($email) { global $wpdb; // Get total purchases (unique events registered) $total_purchases = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT p.post_parent) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type IN ('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees') AND pm.meta_key IN ('_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email', '_tribe_tpp_attendee_email') AND pm.meta_value = %s AND p.post_status = 'publish' ", $email)); // Get events registered for $events_registered = $total_purchases; // Same as purchases for now // Get events checked in $events_checked_in = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(DISTINCT p.post_parent) FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm_email ON p.ID = pm_email.post_id JOIN {$wpdb->postmeta} pm_checkin ON p.ID = pm_checkin.post_id WHERE p.post_type IN ('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees') AND pm_email.meta_key IN ('_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email', '_tribe_tpp_attendee_email') AND pm_email.meta_value = %s AND pm_checkin.meta_key = '_tribe_tickets_attendee_checked_in' AND pm_checkin.meta_value = '1' AND p.post_status = 'publish' ", $email)); // Get certificates earned $certificates_earned = 0; if (class_exists('HVAC_Certificate_Manager')) { $certificate_manager = HVAC_Certificate_Manager::instance(); // Get all attendee IDs for this email $attendee_ids = $wpdb->get_col($wpdb->prepare(" SELECT p.ID FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type IN ('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees') AND pm.meta_key IN ('_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email', '_tribe_tpp_attendee_email') AND pm.meta_value = %s AND p.post_status = 'publish' ", $email)); // Count certificates for these attendees foreach ($attendee_ids as $att_id) { $certs = $wpdb->get_var($wpdb->prepare(" SELECT COUNT(*) FROM {$wpdb->prefix}hvac_certificates WHERE attendee_id = %d ", $att_id)); $certificates_earned += $certs; } } return array( 'total_purchases' => intval($total_purchases), 'events_registered' => intval($events_registered), 'events_checked_in' => intval($events_checked_in), 'certificates_earned' => intval($certificates_earned) ); } /** * Get attendee timeline data */ private function get_attendee_timeline($email) { global $wpdb; $timeline_events = array(); // Get all attendee records for this email $attendee_records = $wpdb->get_results($wpdb->prepare(" SELECT p.ID as attendee_id, p.post_parent as event_id, p.post_date as registration_date, event.post_title as event_title, event_date.meta_value as event_date, checkin.meta_value as checked_in FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id JOIN {$wpdb->posts} event ON p.post_parent = event.ID LEFT JOIN {$wpdb->postmeta} event_date ON event.ID = event_date.post_id AND event_date.meta_key = '_EventStartDate' LEFT JOIN {$wpdb->postmeta} checkin ON p.ID = checkin.post_id AND checkin.meta_key = '_tribe_tickets_attendee_checked_in' WHERE p.post_type IN ('tribe_tpp_attendees', 'tec_tc_attendee', 'tribe_rsvp_attendees') AND pm.meta_key IN ('_tec_tickets_commerce_email', '_tribe_tpp_email', '_tribe_tickets_email', '_tribe_tpp_attendee_email') AND pm.meta_value = %s AND p.post_status = 'publish' ORDER BY p.post_date DESC ", $email)); foreach ($attendee_records as $record) { // Registration event $timeline_events[] = array( 'type' => 'registration', 'title' => 'Registered for ' . $record->event_title, 'date' => $record->registration_date, 'event_id' => $record->event_id, 'icon' => 'fas fa-ticket-alt', 'color' => '#007cba' ); // Event attendance (if event date has passed) if ($record->event_date && strtotime($record->event_date) < current_time('timestamp')) { $timeline_events[] = array( 'type' => 'event', 'title' => 'Attended ' . $record->event_title, 'date' => $record->event_date, 'event_id' => $record->event_id, 'checked_in' => $record->checked_in == '1', 'icon' => 'fas fa-calendar-check', 'color' => $record->checked_in == '1' ? '#28a745' : '#6c757d' ); } // Certificate earned if (class_exists('HVAC_Certificate_Manager')) { $cert = $wpdb->get_row($wpdb->prepare(" SELECT certificate_number, date_generated FROM {$wpdb->prefix}hvac_certificates WHERE attendee_id = %d LIMIT 1 ", $record->attendee_id)); if ($cert) { $timeline_events[] = array( 'type' => 'certificate', 'title' => 'Certificate earned for ' . $record->event_title, 'date' => $cert->date_generated, 'event_id' => $record->event_id, 'certificate_number' => $cert->certificate_number, 'icon' => 'fas fa-certificate', 'color' => '#ffc107' ); } } } // Sort timeline by date usort($timeline_events, function($a, $b) { return strtotime($b['date']) - strtotime($a['date']); }); return $timeline_events; } /** * AJAX handler for timeline data */ public function ajax_get_timeline() { check_ajax_referer('hvac_attendee_nonce', 'nonce'); if (!current_user_can('manage_hvac_events') && !current_user_can('manage_options')) { wp_die('Unauthorized'); } $attendee_id = isset($_POST['attendee_id']) ? intval($_POST['attendee_id']) : 0; if (!$attendee_id) { wp_send_json_error('Invalid attendee ID'); } $attendee_data = $this->get_attendee_data($attendee_id); if (!$attendee_data) { wp_send_json_error('Attendee not found'); } wp_send_json_success(array( 'timeline' => $attendee_data['timeline'] )); } } // Initialize HVAC_Attendee_Profile::instance();