upskill-event-manager/admin-import-trainers.php
bengizmo e608a15c74 fix: Ensure import script sets correct hvac_trainer role for all users
- Add explicit role setting in update_user() method for existing users
- Fix issue where existing users kept their old roles during import
- Update both CLI and web-based import scripts
- Update documentation to reflect role handling improvement

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-18 12:26:06 -03:00

415 lines
No EOL
15 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* HVAC Trainer Import - WordPress Admin Page
*
* Upload this file to your WordPress root directory and access via:
* https://yoursite.com/admin-import-trainers.php
*
* IMPORTANT: Remove this file after import is complete for security!
*/
// WordPress environment setup
if (!defined('ABSPATH')) {
require_once __DIR__ . '/wp-load.php';
}
// Security check - only allow admin users
if (!current_user_can('manage_options')) {
wp_die('You do not have sufficient permissions to access this page.');
}
// Handle CSV upload and processing
if ($_POST && isset($_POST['action']) && $_POST['action'] === 'import_csv') {
if (!wp_verify_nonce($_POST['import_nonce'], 'trainer_import')) {
wp_die('Security check failed');
}
$dry_run = isset($_POST['dry_run']) && $_POST['dry_run'] === '1';
if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] === 0) {
$csv_file = $_FILES['csv_file']['tmp_name'];
$importer = new TrainerCSVImporter($dry_run);
// Capture output
ob_start();
$importer->import_csv($csv_file);
$output = ob_get_clean();
echo '<div class="notice notice-success"><p>Import completed!</p></div>';
echo '<pre>' . esc_html($output) . '</pre>';
} else {
echo '<div class="notice notice-error"><p>Error uploading file.</p></div>';
}
}
class TrainerCSVImporter {
private $dry_run = false;
private $stats = [
'processed' => 0,
'created' => 0,
'updated' => 0,
'skipped' => 0,
'errors' => 0
];
public function __construct($dry_run = false) {
$this->dry_run = $dry_run;
}
public function import_csv($csv_file) {
echo "Starting import from uploaded CSV\n";
if ($this->dry_run) {
echo "DRY RUN MODE - No data will be modified\n";
}
echo "----------------------------------------\n";
$handle = fopen($csv_file, 'r');
if (!$handle) {
die("Could not open CSV file\n");
}
// Read header row
$headers = fgetcsv($handle);
if (!$headers) {
die("Could not read CSV headers\n");
}
// Process each row
while (($row = fgetcsv($handle)) !== false) {
$data = array_combine($headers, $row);
$this->process_trainer_record($data);
$this->stats['processed']++;
}
fclose($handle);
$this->print_stats();
}
private function process_trainer_record($data) {
// Skip if no email
if (empty($data['Work Email'])) {
echo "Skipping record with no email\n";
$this->stats['skipped']++;
return;
}
$email = sanitize_email($data['Work Email']);
$existing_user = get_user_by('email', $email);
if ($existing_user) {
echo "Updating existing user: $email\n";
$this->update_user($existing_user, $data);
$this->stats['updated']++;
} else {
echo "Creating new user: $email\n";
$this->create_user($data);
$this->stats['created']++;
}
}
private function create_user($data) {
if ($this->dry_run) return;
$email = sanitize_email($data['Work Email']);
$username = $this->generate_username($email);
// Generate random password - user will need to reset
$password = wp_generate_password(12, true, true);
$user_data = [
'user_login' => $username,
'user_email' => $email,
'user_pass' => $password,
'first_name' => sanitize_text_field($data['Name'] ?? ''),
'last_name' => sanitize_text_field($data['Last Name'] ?? ''),
'display_name' => trim(($data['Name'] ?? '') . ' ' . ($data['Last Name'] ?? '')),
'role' => 'hvac_trainer'
];
$user_id = wp_insert_user($user_data);
if (is_wp_error($user_id)) {
echo "Error creating user $email: " . $user_id->get_error_message() . "\n";
$this->stats['errors']++;
return;
}
$this->set_user_meta($user_id, $data);
// Send password reset email
$this->send_welcome_email($user_id);
}
private function update_user($user, $data) {
if ($this->dry_run) return;
// Update basic user data
$user_data = [
'ID' => $user->ID,
'first_name' => sanitize_text_field($data['Name'] ?? ''),
'last_name' => sanitize_text_field($data['Last Name'] ?? ''),
'display_name' => trim(($data['Name'] ?? '') . ' ' . ($data['Last Name'] ?? ''))
];
wp_update_user($user_data);
// Ensure user has correct role
$user_obj = new WP_User($user->ID);
$user_obj->set_role('hvac_trainer');
$this->set_user_meta($user->ID, $data);
}
private function set_user_meta($user_id, $data) {
// Personal Information
update_user_meta($user_id, 'personal_accreditation', sanitize_textarea_field($data['Personal Accreditations'] ?? ''));
// Business Information
update_user_meta($user_id, 'business_name', sanitize_text_field($data['Company Name'] ?? ''));
update_user_meta($user_id, 'business_phone', sanitize_text_field($data['Phone Number'] ?? ''));
update_user_meta($user_id, 'business_email', sanitize_email($data['Work Email'] ?? ''));
update_user_meta($user_id, 'business_website', esc_url_raw($data['Company Website'] ?? ''));
update_user_meta($user_id, 'business_type', $this->map_organization_type($data['Organization Type'] ?? ''));
// Address Information
update_user_meta($user_id, 'user_country', sanitize_text_field($data['Country'] ?? ''));
update_user_meta($user_id, 'user_state', sanitize_text_field($data['State'] ?? ''));
// Training Information
$training_audience = $this->map_training_audience($data['Training Target'] ?? '');
update_user_meta($user_id, 'training_audience', $training_audience);
// Application Data
update_user_meta($user_id, 'application_details', sanitize_textarea_field($data['Trainer Details'] ?? ''));
// Profile Image - Map staging URL to production
$profile_image_id = $this->map_profile_image($data['Profile Picture'] ?? '');
if ($profile_image_id) {
update_user_meta($user_id, 'profile_image_id', $profile_image_id);
}
// Default settings for imported users
update_user_meta($user_id, 'account_status', 'approved'); // Pre-approved users
update_user_meta($user_id, 'create_venue', 'Yes');
// Create organizer and venue profiles
$this->create_organizer_venue($user_id, $data);
}
private function map_organization_type($org_type) {
$mapping = [
'Training Organization' => 'Manufacturer',
'Service Company' => 'Contractor',
'' => 'Other'
];
return $mapping[$org_type] ?? 'Other';
}
private function map_training_audience($target) {
if (empty($target)) {
return ['Anyone'];
}
// Convert single string to array format expected by system
$mapping = [
'Industry professionals' => ['Industry professionals'],
'Internal staff' => ['Internal staff'],
'Anyone' => ['Anyone']
];
return $mapping[$target] ?? ['Anyone'];
}
private function map_profile_image($staging_url) {
if (empty($staging_url)) {
return null;
}
// Convert staging URL to production URL pattern
$production_url = str_replace(
'upskill-staging.measurequick.com',
$_SERVER['HTTP_HOST'], // Use current domain
$staging_url
);
// Try to find existing attachment by URL
$attachment_id = attachment_url_to_postid($production_url);
if (!$attachment_id) {
// Try with staging URL in case it's already in the system
$attachment_id = attachment_url_to_postid($staging_url);
}
if (!$attachment_id) {
echo "Warning: Could not find attachment for URL: $staging_url\n";
return null;
}
return $attachment_id;
}
private function create_organizer_venue($user_id, $data) {
if ($this->dry_run) return;
// Check if organizer already exists
$existing_organizer = get_user_meta($user_id, 'hvac_organizer_id', true);
if ($existing_organizer) {
return; // Already has organizer
}
// Only create if Events Calendar is active
if (!class_exists('Tribe__Events__Main')) {
return;
}
// Create Events Calendar organizer
$organizer_data = [
'post_title' => trim(($data['Name'] ?? '') . ' ' . ($data['Last Name'] ?? '')),
'post_type' => 'tribe_organizer',
'post_status' => 'publish',
'meta_input' => [
'_OrganizerEmail' => sanitize_email($data['Work Email'] ?? ''),
'_OrganizerPhone' => sanitize_text_field($data['Phone Number'] ?? ''),
'_OrganizerWebsite' => esc_url_raw($data['Company Website'] ?? '')
]
];
$organizer_id = wp_insert_post($organizer_data);
if ($organizer_id) {
update_user_meta($user_id, 'hvac_organizer_id', $organizer_id);
}
// Create venue if business name exists
if (!empty($data['Company Name'])) {
$venue_data = [
'post_title' => sanitize_text_field($data['Company Name']),
'post_type' => 'tribe_venue',
'post_status' => 'publish',
'meta_input' => [
'_VenueCountry' => sanitize_text_field($data['Country'] ?? ''),
'_VenueStateProvince' => sanitize_text_field($data['State'] ?? ''),
'_VenueURL' => esc_url_raw($data['Company Website'] ?? '')
]
];
$venue_id = wp_insert_post($venue_data);
if ($venue_id) {
update_user_meta($user_id, 'hvac_venue_id', $venue_id);
}
}
}
private function generate_username($email) {
$username = sanitize_user(substr($email, 0, strpos($email, '@')));
// Ensure username is unique
$base_username = $username;
$counter = 1;
while (username_exists($username)) {
$username = $base_username . $counter;
$counter++;
}
return $username;
}
private function send_welcome_email($user_id) {
$user = get_user_by('id', $user_id);
if (!$user) return;
// Send password reset email
$reset_key = get_password_reset_key($user);
if (!is_wp_error($reset_key)) {
$reset_url = network_site_url("wp-login.php?action=rp&key=$reset_key&login=" . rawurlencode($user->user_login), 'login');
$subject = 'Welcome to HVAC Upskill Platform';
$message = "Hello {$user->first_name},\n\n";
$message .= "Your trainer account has been created on the HVAC Upskill Platform.\n\n";
$message .= "Please set your password by clicking this link:\n";
$message .= $reset_url . "\n\n";
$message .= "After setting your password, you can login at: " . wp_login_url() . "\n\n";
$message .= "Welcome to the platform!\n";
wp_mail($user->user_email, $subject, $message);
}
}
private function print_stats() {
echo "\n========================================\n";
echo "Import Complete!\n";
echo "========================================\n";
echo "Processed: {$this->stats['processed']}\n";
echo "Created: {$this->stats['created']}\n";
echo "Updated: {$this->stats['updated']}\n";
echo "Skipped: {$this->stats['skipped']}\n";
echo "Errors: {$this->stats['errors']}\n";
}
}
// Only show form if not processing
if (!$_POST || !isset($_POST['action']) || $_POST['action'] !== 'import_csv') {
?>
<!DOCTYPE html>
<html>
<head>
<title>HVAC Trainer Import</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 20px; }
.container { max-width: 600px; margin: 0 auto; }
.form-group { margin-bottom: 20px; }
label { display: block; margin-bottom: 5px; font-weight: bold; }
input[type="file"] { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
input[type="checkbox"] { margin-right: 10px; }
input[type="submit"] { background: #0073aa; color: white; padding: 12px 24px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; }
input[type="submit"]:hover { background: #005a87; }
.warning { background: #fff3cd; border: 1px solid #ffeaa7; color: #856404; padding: 15px; border-radius: 4px; margin-bottom: 20px; }
.info { background: #d1ecf1; border: 1px solid #bee5eb; color: #0c5460; padding: 15px; border-radius: 4px; margin-bottom: 20px; }
</style>
</head>
<body>
<div class="container">
<h1>HVAC Trainer CSV Import</h1>
<div class="warning">
<strong>⚠️ IMPORTANT:</strong> This tool imports trainer data into your WordPress database.
Always run a dry-run first and backup your database before importing.
<strong>Remove this file after import for security!</strong>
</div>
<div class="info">
<strong> Instructions:</strong><br>
1. Download the CSV file: <a href="https://upskill-staging.measurequick.com/wp-content/uploads/2025/06/250618120131_user-registration_formidable_entries.csv" target="_blank">Trainer Registration CSV</a><br>
2. Upload the CSV file below<br>
3. Run a dry-run first to preview changes<br>
4. Run actual import if dry-run looks good
</div>
<form method="post" enctype="multipart/form-data">
<?php wp_nonce_field('trainer_import', 'import_nonce'); ?>
<input type="hidden" name="action" value="import_csv">
<div class="form-group">
<label for="csv_file">Select CSV File:</label>
<input type="file" name="csv_file" id="csv_file" accept=".csv" required>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="dry_run" value="1" checked>
Dry Run (preview changes without importing)
</label>
</div>
<div class="form-group">
<input type="submit" value="Import Trainers">
</div>
</form>
</div>
</body>
</html>
<?php
}
?>