version = defined('HVAC_PLUGIN_VERSION') ? HVAC_PLUGIN_VERSION : '1.0.0'; $this->init_hooks(); } /** * Initialize hooks * * @return void */ private function init_hooks() { // AJAX handlers for import/export operations add_action('wp_ajax_hvac_export_trainers', array($this, 'export_trainers')); add_action('wp_ajax_hvac_export_events', array($this, 'export_events')); add_action('wp_ajax_hvac_export_user_profiles', array($this, 'export_user_profiles')); add_action('wp_ajax_hvac_import_trainer_profiles', array($this, 'import_trainer_profiles')); add_action('wp_ajax_hvac_import_events', array($this, 'import_events')); add_action('wp_ajax_hvac_bulk_update_users', array($this, 'bulk_update_users')); // Asset loading for import-export page add_action('wp_enqueue_scripts', array($this, 'enqueue_assets')); } /** * Check if current page is import-export page * * @return bool */ private function is_import_export_page() { $current_url = $_SERVER['REQUEST_URI']; return (strpos($current_url, '/master-trainer/import-export/') !== false); } /** * Enqueue assets for import-export page * * @return void */ public function enqueue_assets() { if (!$this->is_import_export_page()) { return; } // Enqueue CSS wp_enqueue_style( 'hvac-import-export', HVAC_PLUGIN_URL . 'assets/css/hvac-import-export.css', array(), $this->version ); // Enqueue JavaScript wp_enqueue_script( 'hvac-import-export', HVAC_PLUGIN_URL . 'assets/js/hvac-import-export.js', array('jquery'), $this->version, true ); // Localize script wp_localize_script('hvac-import-export', 'hvac_import_export', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('hvac_import_export_nonce'), 'strings' => array( 'processing' => __('Processing...', 'hvac-community-events'), 'export_complete' => __('Export completed successfully!', 'hvac-community-events'), 'import_complete' => __('Import completed successfully!', 'hvac-community-events'), 'error' => __('An error occurred. Please try again.', 'hvac-community-events'), 'confirm_import' => __('Are you sure you want to import this data? This action cannot be undone.', 'hvac-community-events'), 'select_file' => __('Please select a file to import.', 'hvac-community-events'), 'invalid_file' => __('Invalid file type. Please select a CSV file.', 'hvac-community-events'), ), )); } /** * Export trainers to CSV * * @return void */ public function export_trainers() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } try { $trainers = $this->get_all_trainers(); // Create CSV data $csv_data = $this->create_trainers_csv($trainers); // Generate filename with timestamp $filename = 'hvac_trainers_export_' . date('Y-m-d_H-i-s') . '.csv'; wp_send_json_success(array( 'data' => $csv_data, 'filename' => $filename, 'count' => count($trainers), 'message' => sprintf(__('%d trainers exported successfully', 'hvac-community-events'), count($trainers)) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Export failed: ' . $e->getMessage())); } } /** * Export events to CSV * * @return void */ public function export_events() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } try { $events = $this->get_all_events(); // Create CSV data $csv_data = $this->create_events_csv($events); // Generate filename with timestamp $filename = 'hvac_events_export_' . date('Y-m-d_H-i-s') . '.csv'; wp_send_json_success(array( 'data' => $csv_data, 'filename' => $filename, 'count' => count($events), 'message' => sprintf(__('%d events exported successfully', 'hvac-community-events'), count($events)) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Export failed: ' . $e->getMessage())); } } /** * Export user profiles with metadata to CSV * * @return void */ public function export_user_profiles() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } try { $users = $this->get_all_users_with_metadata(); // Create CSV data $csv_data = $this->create_user_profiles_csv($users); // Generate filename with timestamp $filename = 'hvac_user_profiles_export_' . date('Y-m-d_H-i-s') . '.csv'; wp_send_json_success(array( 'data' => $csv_data, 'filename' => $filename, 'count' => count($users), 'message' => sprintf(__('%d user profiles exported successfully', 'hvac-community-events'), count($users)) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Export failed: ' . $e->getMessage())); } } /** * Import trainer profiles from CSV * * @return void */ public function import_trainer_profiles() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } // Check if file was uploaded if (!isset($_FILES['import_file']) || $_FILES['import_file']['error'] !== UPLOAD_ERR_OK) { wp_send_json_error(array('message' => 'No file uploaded or upload error')); } // Validate file type if (!$this->validate_csv_file($_FILES['import_file'])) { wp_send_json_error(array('message' => 'Invalid file type. Please upload a CSV file.')); } try { $results = $this->process_trainer_profiles_import($_FILES['import_file']['tmp_name']); wp_send_json_success(array( 'results' => $results, 'message' => sprintf( __('Import completed: %d created, %d updated, %d errors', 'hvac-community-events'), $results['created'], $results['updated'], $results['errors'] ) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Import failed: ' . $e->getMessage())); } } /** * Import events from CSV * * @return void */ public function import_events() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } // Check if file was uploaded if (!isset($_FILES['import_file']) || $_FILES['import_file']['error'] !== UPLOAD_ERR_OK) { wp_send_json_error(array('message' => 'No file uploaded or upload error')); } // Validate file type if (!$this->validate_csv_file($_FILES['import_file'])) { wp_send_json_error(array('message' => 'Invalid file type. Please upload a CSV file.')); } try { $results = $this->process_events_import($_FILES['import_file']['tmp_name']); wp_send_json_success(array( 'results' => $results, 'message' => sprintf( __('Import completed: %d created, %d updated, %d errors', 'hvac-community-events'), $results['created'], $results['updated'], $results['errors'] ) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Import failed: ' . $e->getMessage())); } } /** * Bulk update users * * @return void */ public function bulk_update_users() { // Security checks if (!check_ajax_referer('hvac_import_export_nonce', 'nonce', false)) { wp_send_json_error(array('message' => 'Security check failed')); } if (!$this->check_master_trainer_permission()) { wp_send_json_error(array('message' => 'Insufficient permissions')); } // Check if file was uploaded if (!isset($_FILES['import_file']) || $_FILES['import_file']['error'] !== UPLOAD_ERR_OK) { wp_send_json_error(array('message' => 'No file uploaded or upload error')); } // Validate file type if (!$this->validate_csv_file($_FILES['import_file'])) { wp_send_json_error(array('message' => 'Invalid file type. Please upload a CSV file.')); } try { $results = $this->process_bulk_user_updates($_FILES['import_file']['tmp_name']); wp_send_json_success(array( 'results' => $results, 'message' => sprintf( __('Bulk update completed: %d updated, %d errors', 'hvac-community-events'), $results['updated'], $results['errors'] ) )); } catch (Exception $e) { wp_send_json_error(array('message' => 'Bulk update failed: ' . $e->getMessage())); } } /** * Check if user has master trainer permission * * @return bool */ private function check_master_trainer_permission() { $user = wp_get_current_user(); return (in_array('hvac_master_trainer', $user->roles) || current_user_can('manage_options')); } /** * Get all trainers * * @return array */ private function get_all_trainers() { $users = get_users(array( 'role__in' => array('hvac_trainer', 'hvac_master_trainer'), 'meta_query' => array( array( 'key' => 'hvac_trainer_status', 'value' => array('approved', 'active'), 'compare' => 'IN' ) ) )); $trainers = array(); foreach ($users as $user) { $trainers[] = array( 'id' => $user->ID, 'username' => $user->user_login, 'email' => $user->user_email, 'first_name' => get_user_meta($user->ID, 'first_name', true), 'last_name' => get_user_meta($user->ID, 'last_name', true), 'business_name' => get_user_meta($user->ID, 'business_name', true), 'business_email' => get_user_meta($user->ID, 'business_email', true), 'phone' => get_user_meta($user->ID, 'phone', true), 'website' => get_user_meta($user->ID, 'website', true), 'status' => get_user_meta($user->ID, 'hvac_trainer_status', true), 'certification_type' => get_user_meta($user->ID, 'certification_type', true), 'certification_status' => get_user_meta($user->ID, 'certification_status', true), 'date_certified' => get_user_meta($user->ID, 'date_certified', true), 'business_type' => get_user_meta($user->ID, 'business_type', true), 'training_audience' => get_user_meta($user->ID, 'training_audience', true), 'registered_date' => $user->user_registered, 'roles' => implode(',', $user->roles) ); } return $trainers; } /** * Get all events * * @return array */ private function get_all_events() { $events_query = new WP_Query(array( 'post_type' => 'tribe_events', 'post_status' => 'any', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => '_hvac_trainer_event', 'value' => '1', 'compare' => '=' ) ) )); $events = array(); if ($events_query->have_posts()) { while ($events_query->have_posts()) { $events_query->the_post(); $post_id = get_the_ID(); $events[] = array( 'id' => $post_id, 'title' => get_the_title(), 'description' => get_the_content(), 'start_date' => get_post_meta($post_id, '_EventStartDate', true), 'end_date' => get_post_meta($post_id, '_EventEndDate', true), 'venue' => get_post_meta($post_id, '_EventVenueID', true), 'organizer' => get_post_meta($post_id, '_EventOrganizerID', true), 'trainer_id' => get_post_meta($post_id, '_hvac_trainer_id', true), 'cost' => get_post_meta($post_id, '_EventCost', true), 'url' => get_post_meta($post_id, '_EventURL', true), 'status' => get_post_status($post_id), 'created_date' => get_the_date('Y-m-d H:i:s'), 'modified_date' => get_the_modified_date('Y-m-d H:i:s') ); } } wp_reset_postdata(); return $events; } /** * Get all users with metadata * * @return array */ private function get_all_users_with_metadata() { $users = get_users(array( 'role__in' => array('hvac_trainer', 'hvac_master_trainer', 'subscriber'), 'number' => -1 )); $user_profiles = array(); foreach ($users as $user) { $all_meta = get_user_meta($user->ID); $user_profile = array( 'id' => $user->ID, 'username' => $user->user_login, 'email' => $user->user_email, 'display_name' => $user->display_name, 'registered_date' => $user->user_registered, 'roles' => implode(',', $user->roles) ); // Add all user meta foreach ($all_meta as $key => $values) { if (is_array($values) && count($values) === 1) { $user_profile[$key] = $values[0]; } else { $user_profile[$key] = maybe_serialize($values); } } $user_profiles[] = $user_profile; } return $user_profiles; } /** * Create trainers CSV data * * @param array $trainers * @return string */ private function create_trainers_csv($trainers) { if (empty($trainers)) { return ''; } // Create CSV content $output = fopen('php://temp', 'r+'); // Headers $headers = array_keys($trainers[0]); fputcsv($output, $headers); // Data rows foreach ($trainers as $trainer) { fputcsv($output, $trainer); } // Get CSV content rewind($output); $csv_data = stream_get_contents($output); fclose($output); return $csv_data; } /** * Create events CSV data * * @param array $events * @return string */ private function create_events_csv($events) { if (empty($events)) { return ''; } // Create CSV content $output = fopen('php://temp', 'r+'); // Headers $headers = array_keys($events[0]); fputcsv($output, $headers); // Data rows foreach ($events as $event) { fputcsv($output, $event); } // Get CSV content rewind($output); $csv_data = stream_get_contents($output); fclose($output); return $csv_data; } /** * Create user profiles CSV data * * @param array $users * @return string */ private function create_user_profiles_csv($users) { if (empty($users)) { return ''; } // Create CSV content $output = fopen('php://temp', 'r+'); // Headers $headers = array_keys($users[0]); fputcsv($output, $headers); // Data rows foreach ($users as $user) { fputcsv($output, $user); } // Get CSV content rewind($output); $csv_data = stream_get_contents($output); fclose($output); return $csv_data; } /** * Validate CSV file * * @param array $file * @return bool */ private function validate_csv_file($file) { // Check file extension $file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); if ($file_extension !== 'csv') { return false; } // Check MIME type $allowed_mime_types = array('text/csv', 'text/plain', 'application/csv'); if (!in_array($file['type'], $allowed_mime_types)) { return false; } // Check file size (max 10MB) if ($file['size'] > 10 * 1024 * 1024) { return false; } return true; } /** * Process trainer profiles import * * @param string $file_path * @return array */ private function process_trainer_profiles_import($file_path) { $results = array( 'created' => 0, 'updated' => 0, 'errors' => 0, 'details' => array() ); $handle = fopen($file_path, 'r'); if (!$handle) { throw new Exception('Cannot open CSV file'); } // Get headers $headers = fgetcsv($handle); if (!$headers) { fclose($handle); throw new Exception('Cannot read CSV headers'); } $row_number = 1; while (($row = fgetcsv($handle)) !== FALSE) { $row_number++; try { $data = array_combine($headers, $row); $this->import_single_trainer_profile($data); $results['updated']++; } catch (Exception $e) { $results['errors']++; $results['details'][] = "Row $row_number: " . $e->getMessage(); } } fclose($handle); return $results; } /** * Process events import * * @param string $file_path * @return array */ private function process_events_import($file_path) { $results = array( 'created' => 0, 'updated' => 0, 'errors' => 0, 'details' => array() ); $handle = fopen($file_path, 'r'); if (!$handle) { throw new Exception('Cannot open CSV file'); } // Get headers $headers = fgetcsv($handle); if (!$headers) { fclose($handle); throw new Exception('Cannot read CSV headers'); } $row_number = 1; while (($row = fgetcsv($handle)) !== FALSE) { $row_number++; try { $data = array_combine($headers, $row); $result = $this->import_single_event($data); if ($result === 'created') { $results['created']++; } else { $results['updated']++; } } catch (Exception $e) { $results['errors']++; $results['details'][] = "Row $row_number: " . $e->getMessage(); } } fclose($handle); return $results; } /** * Process bulk user updates * * @param string $file_path * @return array */ private function process_bulk_user_updates($file_path) { $results = array( 'updated' => 0, 'errors' => 0, 'details' => array() ); $handle = fopen($file_path, 'r'); if (!$handle) { throw new Exception('Cannot open CSV file'); } // Get headers $headers = fgetcsv($handle); if (!$headers) { fclose($handle); throw new Exception('Cannot read CSV headers'); } $row_number = 1; while (($row = fgetcsv($handle)) !== FALSE) { $row_number++; try { $data = array_combine($headers, $row); $this->update_single_user($data); $results['updated']++; } catch (Exception $e) { $results['errors']++; $results['details'][] = "Row $row_number: " . $e->getMessage(); } } fclose($handle); return $results; } /** * Import single trainer profile * * @param array $data * @return void */ private function import_single_trainer_profile($data) { // Find user by email or username $user = null; if (!empty($data['email'])) { $user = get_user_by('email', sanitize_email($data['email'])); } if (!$user && !empty($data['username'])) { $user = get_user_by('login', sanitize_user($data['username'])); } if (!$user) { throw new Exception('User not found'); } // Update user meta $meta_fields = array( 'first_name', 'last_name', 'business_name', 'business_email', 'phone', 'website', 'certification_type', 'certification_status', 'date_certified', 'business_type', 'training_audience' ); foreach ($meta_fields as $field) { if (isset($data[$field]) && $data[$field] !== '') { update_user_meta($user->ID, $field, sanitize_text_field($data[$field])); } } } /** * Import single event * * @param array $data * @return string */ private function import_single_event($data) { // Check if event exists by title $existing_event = get_page_by_title($data['title'], OBJECT, 'tribe_events'); $event_data = array( 'post_title' => sanitize_text_field($data['title']), 'post_content' => wp_kses_post($data['description']), 'post_type' => 'tribe_events', 'post_status' => 'publish' ); if ($existing_event) { $event_data['ID'] = $existing_event->ID; wp_update_post($event_data); return 'updated'; } else { $event_id = wp_insert_post($event_data); if ($event_id && !is_wp_error($event_id)) { // Add event metadata if (!empty($data['start_date'])) { update_post_meta($event_id, '_EventStartDate', sanitize_text_field($data['start_date'])); } if (!empty($data['end_date'])) { update_post_meta($event_id, '_EventEndDate', sanitize_text_field($data['end_date'])); } update_post_meta($event_id, '_hvac_trainer_event', '1'); return 'created'; } } throw new Exception('Failed to import event'); } /** * Update single user * * @param array $data * @return void */ private function update_single_user($data) { // Find user $user = null; if (!empty($data['id'])) { $user = get_user_by('id', intval($data['id'])); } elseif (!empty($data['email'])) { $user = get_user_by('email', sanitize_email($data['email'])); } if (!$user) { throw new Exception('User not found'); } // Update user data $user_data = array('ID' => $user->ID); if (!empty($data['display_name'])) { $user_data['display_name'] = sanitize_text_field($data['display_name']); } if (count($user_data) > 1) { wp_update_user($user_data); } // Update meta fields foreach ($data as $key => $value) { if (!in_array($key, array('id', 'username', 'email', 'display_name', 'registered_date', 'roles')) && $value !== '') { update_user_meta($user->ID, $key, sanitize_text_field($value)); } } } } // Initialize the class HVAC_Import_Export_Manager::instance();