fix CSV importer AP/orientation name resolution + seed missing AP programs

- migration 014: adds Récits et expérimentation (RE), PACS, sets code NS
  on Narration Spéculative; applied to both posterg.db and test.db

- importer (admin/index.php): replaced the code-only ap_programs lookup
  (SELECT WHERE code=?) and the orientationMap short-code translation with
  two resolver closures that handle the real CSV format (full names):

  resolveAP(): alias map for L.I.E.N.S., case variants → exact name
  match → code match (legacy) → case-insensitive name match

  resolveOrientation(): legacy 2-letter code map → alias map for
  Installation/Performance, Arts numériques, Design numérique →
  exact name match → case-insensitive name match

  All 5 AP values and 13 orientation values from the real CSV now
  resolve to correct DB IDs. Legacy short-code CSVs (test.db format)
  continue to work unchanged.
This commit is contained in:
Pontoporeia
2026-04-21 19:16:52 +02:00
parent 73fdda4a7f
commit 19ef2a11dc
6 changed files with 104 additions and 15 deletions

View File

@@ -38,7 +38,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
fgetcsv($handle, 0, ',', '"', '');
fgetcsv($handle, 0, ',', '"', ''); // skip 4 header rows
$orientationMap = [
// Code → canonical name (legacy short-code CSV format)
$orientationCodeMap = [
'SC'=>'Sculpture','VI'=>'Vidéographie','CA'=>"Cinéma d'animation",
'IP'=>'Installation-Performance','PE'=>'Peinture','PH'=>'Photographie',
'DE'=>'Dessin','AN'=>'Arts Numériques','GR'=>'Graphisme',
@@ -46,6 +47,91 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
'BD'=>'Bande-Dessinée','SE'=>'Sérigraphie','GV'=>'Gravure',
];
// Alias map: normalise known variant spellings → canonical DB name.
// Keys are lowercased+stripped for comparison.
$orientationAliases = [
'arts numériques' => 'Arts Numériques',
'design numérique' => 'Design Numérique',
'installation/performance' => 'Installation-Performance',
'installation performance' => 'Installation-Performance',
'cinema d\'animation' => "Cinéma d'animation",
'cinéma d\'animation' => "Cinéma d'animation",
'bande dessinée' => 'Bande-Dessinée',
];
// Resolve an orientation string (code or full name) → canonical DB name.
$resolveOrientation = function(string $raw) use ($orientationCodeMap, $orientationAliases, $importPdo): ?int {
$raw = trim($raw);
if ($raw === '') return null;
// 1. Try legacy short code
if (isset($orientationCodeMap[$raw])) {
$raw = $orientationCodeMap[$raw];
}
// 2. Try alias map (lowercase key)
$key = mb_strtolower($raw, 'UTF-8');
if (isset($orientationAliases[$key])) {
$raw = $orientationAliases[$key];
}
// 3. Exact DB match
$s = $importPdo->prepare("SELECT id FROM orientations WHERE name = ?");
$s->execute([$raw]);
$r = $s->fetch();
if ($r) return (int)$r['id'];
// 4. Case-insensitive DB match
$s = $importPdo->prepare("SELECT id FROM orientations WHERE LOWER(name) = LOWER(?)");
$s->execute([$raw]);
$r = $s->fetch();
return $r ? (int)$r['id'] : null;
};
// AP alias map: variant spellings → canonical DB name.
$apAliases = [
'l.i.e.n.s.' => 'Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes',
'liens' => 'Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes',
'lieux, interdisciplinarités, écologie, nécessité, systèmes'
=> 'Lieux, Interdisciplinarités, Écologie, Nécessité, Systèmes',
'récits et expérimentation' => 'Récits et expérimentation',
'recits et experimentation' => 'Récits et expérimentation',
'atelier pratiques situées' => 'Atelier Pratiques Situées',
'design et politique du multiple' => 'Design et Politique du Multiple',
'narration spéculative' => 'Narration Spéculative',
'pacs' => 'PACS',
];
// Resolve an AP string (code or full name) → ap_program id.
$resolveAP = function(string $raw) use ($apAliases, $importPdo): ?int {
$raw = trim($raw);
if ($raw === '') return null;
// 1. Try alias map (lowercase key)
$key = mb_strtolower($raw, 'UTF-8');
if (isset($apAliases[$key])) {
$raw = $apAliases[$key];
}
// 2. Exact name match
$s = $importPdo->prepare("SELECT id FROM ap_programs WHERE name = ?");
$s->execute([$raw]);
$r = $s->fetch();
if ($r) return (int)$r['id'];
// 3. Code match (legacy)
$s = $importPdo->prepare("SELECT id FROM ap_programs WHERE code = ?");
$s->execute([$raw]);
$r = $s->fetch();
if ($r) return (int)$r['id'];
// 4. Case-insensitive name match
$s = $importPdo->prepare("SELECT id FROM ap_programs WHERE LOWER(name) = LOWER(?)");
$s->execute([$raw]);
$r = $s->fetch();
return $r ? (int)$r['id'] : null;
};
$lineNumber = 5;
while (($row = fgetcsv($handle, 0, ',', '"', '')) !== false) {
$lineNumber++;
@@ -77,20 +163,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['csv_file'])) {
if (empty($title) || empty($year)) throw new Exception("Titre et année requis.");
$orientationName = $orientationMap[$orientationCode] ?? null;
$orientationId = null;
if ($orientationName) {
$s = $importPdo->prepare("SELECT id FROM orientations WHERE name = ?");
$s->execute([$orientationName]);
$r = $s->fetch(); $orientationId = $r ? $r['id'] : null;
}
$apProgramId = null;
if (!empty($apCode)) {
$s = $importPdo->prepare("SELECT id FROM ap_programs WHERE code = ?");
$s->execute([$apCode]);
$r = $s->fetch(); $apProgramId = $r ? $r['id'] : null;
}
$orientationId = $resolveOrientation($orientationCode);
$apProgramId = $resolveAP($apCode);
$finalityId = null;
if (!empty($finalityName)) {

View File

@@ -0,0 +1 @@
,padlock,archlinux,21.04.2026 19:12,file:///home/padlock/.config/libreoffice/4;

View File

@@ -0,0 +1,9 @@
-- Migration 014: seed missing AP programs and fix codes
-- Adds programs present in real CSV data but absent from the initial seed.
-- Fill in missing code for Narration Spéculative
UPDATE ap_programs SET code = 'NS' WHERE name = 'Narration Spéculative' AND (code IS NULL OR code = '');
-- Add missing AP programs (INSERT OR IGNORE is safe to re-run)
INSERT OR IGNORE INTO ap_programs (name, code) VALUES ('Récits et expérimentation', 'RE');
INSERT OR IGNORE INTO ap_programs (name, code) VALUES ('PACS', 'PACS');

Binary file not shown.

Binary file not shown.