[ 'ds' => 'fr-en-ips-ecoles-ap2022', 'select' => 'rentree_scolaire,uai,ips,ips_departemental', 'ips' => ['ips'], 'dep' => 'ips_departemental', 'file' => 'ips_ecoles.csv', ], 'colleges' => [ 'ds' => 'fr-en-ips-colleges-ap2022', 'select' => 'rentree_scolaire,uai,ips', 'ips' => ['ips'], 'dep' => null, 'file' => 'ips_colleges.csv', ], 'lycees' => [ 'ds' => 'fr-en-ips-lycees-ap2022', 'select' => 'rentree_scolaire,uai,ips_ensemble_gt_pro,ips_voie_gt', 'ips' => ['ips_ensemble_gt_pro', 'ips_voie_gt'], // ensemble, sinon voie GT 'dep' => null, 'file' => 'ips_lycees.csv', ], ]; /** Télécharge l'export CSV d'un dataset vers $path s'il est absent. */ function ips_download(string $ds, string $select, string $path): void { if (is_file($path)) { return; } @mkdir(dirname($path), 0777, true); $url = 'https://data.education.gouv.fr/api/explore/v2.1/catalog/datasets/' . $ds . '/exports/csv?select=' . rawurlencode($select) . '&delimiter=%3B'; say("… Téléchargement de $ds …"); $fp = fopen($path, 'w'); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_FILE => $fp, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 600, CURLOPT_USERAGENT => 'ecoles-import/1.0', ]); $ok = curl_exec($ch); $err = curl_error($ch); curl_close($ch); fclose($fp); if (!$ok) { @unlink($path); throw new RuntimeException("Téléchargement échoué ($ds) : $err"); } } /** Importe un dataset IPS dans la table « ips ». Renvoie le nombre de lignes. */ function ips_import_one(PDO $pdo, array $cfg): int { $path = __DIR__ . '/data/insee/' . $cfg['file']; ips_download($cfg['ds'], $cfg['select'], $path); $fh = fopen($path, 'r'); $header = fgetcsv($fh, 0, ';'); $header[0] = preg_replace('/^\xEF\xBB\xBF/', '', (string) $header[0]); // retire un éventuel BOM $idx = static fn(string $name) => array_search($name, $header, true); $iY = $idx('rentree_scolaire'); $iU = $idx('uai'); $ipsCols = array_values(array_filter(array_map($idx, $cfg['ips']), static fn($v) => $v !== false)); $iD = $cfg['dep'] !== null ? $idx($cfg['dep']) : false; if ($iY === false || $iU === false || !$ipsCols) { fclose($fh); throw new RuntimeException("Colonnes attendues introuvables dans {$cfg['file']}."); } $ins = $pdo->prepare('REPLACE INTO ips (uai, annee, ips, ips_dep) VALUES (?, ?, ?, ?)'); $dec = static fn($v) => ($v === null || $v === '') ? null : (float) str_replace(',', '.', (string) $v); $pdo->beginTransaction(); $n = 0; while (($row = fgetcsv($fh, 0, ';')) !== false) { $uai = $row[$iU] ?? ''; $annee = (int) ($row[$iY] ?? 0); // Première colonne IPS non vide (ensemble, sinon repli). $ips = null; foreach ($ipsCols as $c) { $ips = $dec($row[$c] ?? null); if ($ips !== null) { break; } } if ($uai === '' || $annee === 0 || $ips === null) { continue; } $ins->execute([$uai, $annee, $ips, $iD !== false ? $dec($row[$iD] ?? null) : null]); if (++$n % 5000 === 0) { $pdo->commit(); $pdo->beginTransaction(); } } $pdo->commit(); fclose($fh); return $n; } try { $pdo = db(); $pdo->exec( 'CREATE TABLE IF NOT EXISTS ips ( uai VARCHAR(12) NOT NULL, annee SMALLINT NOT NULL, ips DECIMAL(5,1) NOT NULL, ips_dep DECIMAL(5,1) NULL, PRIMARY KEY (uai, annee), INDEX idx_uai (uai) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4' ); // Filtre éventuel sur un niveau. $only = null; foreach ($argv ?? [] as $a) { if (preg_match('/^--niveau=(ecoles|colleges|lycees)$/', $a, $m)) { $only = $m[1]; } } $total = 0; foreach (IPS_DATASETS as $niveau => $cfg) { if ($only !== null && $only !== $niveau) { continue; } $n = ips_import_one($pdo, $cfg); say("✔ $niveau : $n lignes importées."); $total += $n; } $ecoles = (int) $pdo->query('SELECT COUNT(DISTINCT uai) FROM ips')->fetchColumn(); say("✔ ips : $total lignes au total ($ecoles établissements distincts)."); say('🎉 Terminé.'); } catch (Throwable $e) { if (isset($pdo) && $pdo->inTransaction()) { $pdo->rollBack(); } http_response_code(500); say('!! ERREUR : ' . $e->getMessage()); exit(1); }