public static function handle_import_members() { if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Not allowed.' ); check_admin_referer( 'cryogen_import', 'cryogen_import_nonce' ); if ( empty( $_FILES['cg_import_file']['tmp_name'] ) ) { wp_redirect( admin_url( 'admin.php?page=cryogen-import&cg_import_msg=' . urlencode( 'No file uploaded.' ) ) ); exit; } global $wpdb; $handle = fopen( $_FILES['cg_import_file']['tmp_name'], 'r' ); $header = fgetcsv( $handle ); $added = 0; $skipped = 0; while ( ( $row = fgetcsv( $handle ) ) !== false ) { $data = array_combine( $header, $row ); $email = sanitize_email( $data['email'] ?? '' ); $zwift = sanitize_text_field( $data['zwift_id'] ?? '' ); if ( ! $email || ! $zwift ) { $skipped++; continue; } $exists = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}cryogen_members WHERE email=%s OR zwift_id=%s", $email, $zwift ) ); if ( $exists ) { $skipped++; continue; } self::do_add_member( [ 'name' => $data['name'] ?? '', 'email' => $email, 'zwift_id' => $zwift, 'discord_handle' => $data['discord_handle'] ?? '', 'facebook' => $data['facebook'] ?? '', 'tier' => ( isset( $data['tier'] ) && trim( strtolower( $data['tier'] ) ) === 'full' ) ? 'full' : 'half', ] ); $added++; } fclose( $handle ); $msg = "Import complete: {$added} added, {$skipped} skipped (already existed or missing data)."; wp_redirect( admin_url( 'admin.php?page=cryogen-import&cg_import_msg=' . urlencode( $msg ) ) ); exit; } public static function add_zwift_data_columns() { global $wpdb; $table = "{$wpdb->prefix}cryogen_members"; $existing = $wpdb->get_col( "DESCRIBE {$table}", 0 ); $new_columns = [ 'zp_category' => "VARCHAR(5) DEFAULT ''", 'ftp' => "SMALLINT DEFAULT 0", 'critical_power' => "SMALLINT DEFAULT 0", 'compound_score' => "DECIMAL(10,2) DEFAULT 0", 'velo_rating' => "DECIMAL(10,2) DEFAULT 0", 'phenotype' => "VARCHAR(20) DEFAULT ''", 'club_match' => "VARCHAR(120) DEFAULT ''", 'zwift_data_updated_at' => "DATETIME NULL", ]; foreach ( $new_columns as $col => $definition ) { if ( ! in_array( $col, $existing, true ) ) { $wpdb->query( "ALTER TABLE {$table} ADD COLUMN {$col} {$definition}" ); } } } public static function handle_upgrade_schema() { if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Not allowed.' ); self::add_zwift_data_columns(); wp_redirect( admin_url( 'admin.php?page=cryogen-members&cg_msg=' . urlencode( 'Database columns updated.' ) ) ); exit; }