// File: wp-content/mu-plugins/mp-csv-assign.php if( defined('WP_CLI') && WP_CLI ) { WP_CLI::add_command('mp assign_free_from_csv', function($args, $assoc_args) { $csv_path = $assoc_args['csv'] ?? ''; $membership_id = intval($assoc_args['membership'] ?? 0); $dry_run = isset($assoc_args['dry-run']); $limit = intval($assoc_args['limit'] ?? 50); $offset = intval($assoc_args['offset'] ?? 0); if($csv_path === '' || $membership_id <= 0) { WP_CLI::error('Usage: wp mp assign_free_from_csv --csv=/abs/path/file.csv --membership=78248 [--dry-run] [--limit=50] [--offset=0]'); } if(!file_exists($csv_path) || !is_readable($csv_path)) { WP_CLI::error('CSV not found or not readable: ' . $csv_path); } // Read CSV header and locate email column $h = fopen($csv_path, 'r'); if(!$h) { WP_CLI::error('Failed to open CSV.'); } $header = fgetcsv($h); if($header === false) { fclose($h); WP_CLI::error('CSV empty.'); } $email_col = null; foreach($header as $i => $name) { if(strtolower(trim($name)) === 'email') { $email_col = $i; break; } } if($email_col === null) { $email_col = 0; } // fallback: first col // Skip to offset $i = 0; while($i < $offset && ($row = fgetcsv($h)) !== false) { $i++; } global $wpdb; $subs_table = $wpdb->prefix . 'mepr_subscriptions'; $processed = $assigned = $skipped_no_user = $skipped_already = $skipped_bad_email = 0; while($processed < $limit && ($row = fgetcsv($h)) !== false) { $processed++; $email = isset($row[$email_col]) ? strtolower(trim($row[$email_col])) : ''; if($email === '' || !is_email($email)) { $skipped_bad_email++; WP_CLI::log("SKIP bad email: " . ($email ?: '[empty]')); continue; } $user = get_user_by('email', $email); if(!$user) { $skipped_no_user++; WP_CLI::log("SKIP no WP user: {$email}"); continue; } $existing = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$subs_table} WHERE user_id=%d AND product_id=%d AND status=%s LIMIT 1", $user->ID, $membership_id, MeprSubscription::$active_str )); if($existing) { $skipped_already++; WP_CLI::log("SKIP already active: {$email} (user_id {$user->ID})"); continue; } if($dry_run) { WP_CLI::log("DRY RUN would assign: {$email} (user_id {$user->ID})"); continue; } $txn = new MeprTransaction(); $txn->user_id = $user->ID; $txn->product_id = $membership_id; $txn->amount = 0.00; $txn->total = 0.00; $txn->tax_amount = 0.00; $txn->status = MeprTransaction::$complete_str; $txn->gateway = 'free'; $txn->expires_at = null; $txn->store(); $sub = new MeprSubscription(); $sub->user_id = $user->ID; $sub->product_id = $membership_id; $sub->price = 0.00; $sub->total = 0.00; $sub->status = MeprSubscription::$active_str; $sub->gateway = 'free'; $sub->store(); $assigned++; WP_CLI::log("ASSIGNED: {$email} (user_id {$user->ID})"); } fclose($h); WP_CLI::success("Batch done. processed={$processed} assigned={$assigned} skipped_no_user={$skipped_no_user} skipped_already={$skipped_already} skipped_bad_email={$skipped_bad_email} next_offset=" . ($offset + $processed)); }); }