Import en masse depuis CSV

Uploader le couple hal-to-import.csv + hal-to-import-context.json (généré par php scripts/prepare-csv-context.php) pour importer les publications legacy. Chaque batch traite publications — cliquer plusieurs fois jusqu'à terminaison.

Fichier CSV
Fichier contexte (JSON)

Généré par scripts/prepare-csv-context.php.

Statut des posts
Date du post WP

render_csv_progress($queue); ?>
0 ? round(100 * $done / $total, 1) : 0; $report_ct = count($queue['report'] ?? []); ?>

File d'attente active — statut cible : — backdate :

/ publications traitées (%) — restantes

Dernière mise à jour :

Erreur dernier batch :

0): ?>
message = ['error', 'CSV ou fichier contexte manquant.']; return; } // Parse CSV -> list of hal_ids $fh = fopen($_FILES['csv_file']['tmp_name'], 'r'); if (!$fh) { $this->message = ['error', 'Impossible de lire le CSV.']; return; } $header = fgetcsv($fh); $hal_col = array_search('hal_id', $header); $spip_col = array_search('spip_id', $header); if ($hal_col === false) { fclose($fh); $this->message = ['error', 'Header CSV : colonne hal_id manquante.']; return; } $hal_ids = []; $spip_map = []; // hal_id => spip_id while (($row = fgetcsv($fh)) !== false) { $hid = trim($row[$hal_col] ?? ''); if ($hid === '') continue; $hal_ids[] = $hid; if ($spip_col !== false) $spip_map[$hid] = trim($row[$spip_col] ?? ''); } fclose($fh); $hal_ids = array_values(array_unique($hal_ids)); // Parse JSON context $ctx_raw = file_get_contents($_FILES['ctx_file']['tmp_name']); $ctx_data = json_decode($ctx_raw, true); if (!is_array($ctx_data) || !isset($ctx_data['ctx'])) { $this->message = ['error', 'Fichier contexte JSON invalide.']; return; } $status = ($_POST['post_status'] ?? 'publish') === 'pending' ? 'pending' : 'publish'; $backdate = !empty($_POST['backdate_post']); $queue = [ 'hal_ids' => $hal_ids, 'spip_map' => $spip_map, 'status' => $status, 'backdate' => $backdate, 'total' => count($hal_ids), 'done' => 0, 'spip_ctx' => $ctx_data['ctx'], 'wp_users_by_hal_id' => $ctx_data['wp_users_by_hal_id'] ?? [], 'report' => [], 'last_error' => '', 'updated_at' => current_time('mysql'), ]; update_option(self::CSV_QUEUE_OPTION, $queue, false); $this->message = ['success', sprintf( 'CSV chargé : %d publications prêtes. Statut cible : %s. Cliquer "Traiter le prochain batch" pour lancer.', count($hal_ids), $status )]; } private function handle_csv_batch(): void { $queue = get_option(self::CSV_QUEUE_OPTION, null); if (!$queue) { $this->message = ['error', 'Aucune queue active.']; return; } $batch = array_slice($queue['hal_ids'], $queue['done'], self::CSV_BATCH_SIZE); if (empty($batch)) { $this->message = ['success', 'Import terminé — tous les batches ont été traités.']; return; } $docs = $this->api->fetch_by_hal_ids($batch, self::CSV_BATCH_SIZE); if (is_wp_error($docs)) { $queue['last_error'] = $docs->get_error_message(); $queue['updated_at'] = current_time('mysql'); update_option(self::CSV_QUEUE_OPTION, $queue, false); $this->message = ['error', 'Erreur HAL API : ' . $docs->get_error_message()]; return; } // Normalize wp_users_by_hal_id keys to lowercase for the importer $users_map = []; foreach ($queue['wp_users_by_hal_id'] as $hid => $u) { $users_map[strtolower(trim((string) $hid))] = $u; } $importer = new Thalim_HAL_Importer_Logic(); $batch_imported = 0; $batch_skipped = 0; $batch_errors = 0; foreach ($batch as $hal_id) { $spip_id = $queue['spip_map'][$hal_id] ?? ''; $doc = $docs[$hal_id] ?? null; $ctx = $queue['spip_ctx'][$hal_id] ?? []; if (!$doc) { $queue['report'][] = [$hal_id, $spip_id, '', 'not_found_in_hal', 'false', 'none', 'HAL API did not return this hal_id']; $batch_errors++; continue; } $post_id = $importer->import($doc, $users_map, $queue['status'], (bool) $queue['backdate'], $ctx); if (is_wp_error($post_id)) { $code = $post_id->get_error_code(); $queue['report'][] = [$hal_id, $spip_id, '', $code, 'false', 'none', $post_id->get_error_message()]; if ($code === 'exists') $batch_skipped++; else $batch_errors++; } else { $source = $importer->last_axes_source; $has_axe = $source !== 'none' ? 'true' : 'false'; $queue['report'][] = [$hal_id, $spip_id, (string) $post_id, 'imported', $has_axe, $source, '']; $batch_imported++; } } $queue['done'] += count($batch); $queue['last_error'] = ''; $queue['updated_at'] = current_time('mysql'); update_option(self::CSV_QUEUE_OPTION, $queue, false); $this->message = ['success', sprintf( 'Batch traité : %d importé(s), %d déjà importé(s), %d erreur(s). Progression : %d / %d.', $batch_imported, $batch_skipped, $batch_errors, $queue['done'], $queue['total'] )]; } private function handle_csv_cancel(): void { delete_option(self::CSV_QUEUE_OPTION); $this->message = ['success', 'Queue CSV annulée.']; } private function handle_csv_download_report(): void { $queue = get_option(self::CSV_QUEUE_OPTION, null); if (!$queue || empty($queue['report'])) { $this->message = ['warning', 'Aucun rapport à télécharger.']; return; } $filename = 'hal-import-report-' . date('Ymd-His') . '.csv'; header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="' . $filename . '"'); $out = fopen('php://output', 'w'); fputcsv($out, ['hal_id', 'spip_id', 'post_id', 'status', 'has_axe', 'axes_source', 'error']); foreach ($queue['report'] as $row) fputcsv($out, $row); fclose($out); exit; } }