Systematic audit and implementation of missing Master Trainer functionality with comprehensive WordPress best practices and security implementation. ## Features Implemented - Master Events Overview (/master-trainer/events/) - KPI dashboard with filtering - Import/Export Data Management (/master-trainer/import-export/) - CSV operations - Communication Templates (/trainer/communication-templates/) - Professional templates - Enhanced Announcements (/master-trainer/announcements/) - Dynamic shortcode integration - Pending Approvals System (/master-trainer/pending-approvals/) - Workflow management ## Navigation & UX Improvements - Removed redundant Events link from top-level navigation menu - Reorganized administrative functions under Tools dropdown - Enhanced navigation clarity and professional appearance - Full responsive design with accessibility compliance ## Architecture & Security - 5 new singleton manager classes following WordPress patterns - Comprehensive role-based access control (hvac_master_trainer) - Complete security implementation (nonces, sanitization, escaping) - Performance optimizations with transient caching and conditional loading - Professional error handling and user feedback systems ## Files Added (16 new files) - 4 manager classes: Import/Export, Events Overview, Pending Approvals, Communication Templates - 4 CSS files with responsive design and accessibility features - 4 JavaScript files with AJAX functionality and error handling - 2 new templates: Import/Export, Pending Approvals - 2 enhanced templates: Events Overview, Communication Templates ## Files Modified (14 files) - Core system integration in Plugin, Page Manager, Scripts/Styles classes - Navigation system cleanup in Master Menu System - Enhanced access control and role management - Template updates for dynamic content integration ## Testing & Deployment - Comprehensive testing with Playwright automation - Successful staging deployment and verification - All 5 missing pages now fully functional - Navigation improvements verified working Resolves master trainer area audit requirements with production-ready implementation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
866 lines
No EOL
27 KiB
PHP
866 lines
No EOL
27 KiB
PHP
<?php
|
|
/**
|
|
* HVAC Import Export Manager
|
|
*
|
|
* Manages data import/export functionality for master trainers
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @since 1.0.0
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* HVAC_Import_Export_Manager class
|
|
*/
|
|
class HVAC_Import_Export_Manager {
|
|
|
|
/**
|
|
* Instance
|
|
*
|
|
* @var HVAC_Import_Export_Manager
|
|
*/
|
|
private static $instance = null;
|
|
|
|
/**
|
|
* Script version for cache busting
|
|
*
|
|
* @var string
|
|
*/
|
|
private $version;
|
|
|
|
/**
|
|
* Get instance
|
|
*
|
|
* @return HVAC_Import_Export_Manager
|
|
*/
|
|
public static function instance() {
|
|
if (null === self::$instance) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
private function __construct() {
|
|
$this->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(); |