fix: author name casing not updating — use ID lookup priority

Root cause: SQLite uses BINARY collation, so WHERE name = ? is
case-sensitive. When changing 'john doe' to 'John Doe', the name
lookup failed and fell through to the email path which didn't update
the name. The previous fix only added UPDATE in the name-match branch.

Fixes in findOrCreateAuthor:
1. Accept optional $idHint parameter — when known (edit flow), update
   directly by ID (fastest, zero ambiguity)
2. Add COLLATE NOCASE to the name lookup (fallback path)
3. Add UPDATE in the email fallback path too

setThesisAuthors now fetches existing author_ids before deletion and
passes them as position-based hints, so identity is always preserved.
This commit is contained in:
Pontoporeia
2026-06-09 12:33:26 +02:00
parent 3016c199bd
commit 3df1456781
12 changed files with 62 additions and 16 deletions

View File

@@ -1014,7 +1014,7 @@ class Database
/**
* Find or create an author
*/
public function findOrCreateAuthor($name, $email = null, bool $showContact = false)
public function findOrCreateAuthor($name, $email = null, bool $showContact = false, ?int $idHint = null)
{
// Normalise CSV artefacts: OUI/NON strings in email column → null
if ($email !== null && in_array(strtoupper(trim($email)), ['NON', 'OUI'], true)) {
@@ -1023,8 +1023,19 @@ class Database
$cleanEmail = ($email !== null && $email !== '') ? $email : null;
// Try to find by name first
$stmt = $this->pdo->prepare('SELECT id, email FROM authors WHERE name = ?');
// 1. If we have a known ID (edit flow), update directly by ID
if ($idHint !== null) {
$stmt = $this->pdo->prepare('SELECT id FROM authors WHERE id = ?');
$stmt->execute([$idHint]);
if ($stmt->fetch()) {
$updateStmt = $this->pdo->prepare('UPDATE authors SET name = ?, email = ?, show_contact = ? WHERE id = ?');
$updateStmt->execute([$name, $cleanEmail, $showContact ? 1 : 0, $idHint]);
return $idHint;
}
}
// 2. Try to find by name (case-insensitive — SQLite BINARY collation otherwise)
$stmt = $this->pdo->prepare('SELECT id, email FROM authors WHERE name = ? COLLATE NOCASE');
$stmt->execute([$name]);
$author = $stmt->fetch();
@@ -1042,16 +1053,19 @@ class Database
return $author['id'];
}
// If an author with this email already exists (different name), reuse that record.
// 3. If an author with this email already exists (different name), reuse that record.
if ($cleanEmail !== null) {
$byEmail = $this->pdo->prepare('SELECT id FROM authors WHERE email = ?');
$byEmail = $this->pdo->prepare('SELECT id, name FROM authors WHERE email = ?');
$byEmail->execute([$cleanEmail]);
$existing = $byEmail->fetch();
if ($existing) {
$updateStmt = $this->pdo->prepare('UPDATE authors SET name = ?, show_contact = ? WHERE id = ?');
$updateStmt->execute([$name, $showContact ? 1 : 0, $existing['id']]);
return $existing['id'];
}
}
// 4. Create new author
$stmt = $this->pdo->prepare('INSERT INTO authors (name, email, show_contact) VALUES (?, ?, ?)');
$stmt->execute([$name, $cleanEmail, $showContact ? 1 : 0]);
return $this->pdo->lastInsertId();
@@ -2194,6 +2208,11 @@ class Database
*/
public function setThesisAuthors(int $thesisId, array $authors): void
{
// Fetch existing author IDs before deletion (preserves identity for edit)
$existingStmt = $this->pdo->prepare('SELECT author_id FROM thesis_authors WHERE thesis_id = ? ORDER BY author_order');
$existingStmt->execute([$thesisId]);
$existingIds = $existingStmt->fetchAll(\PDO::FETCH_COLUMN);
$this->pdo->prepare('DELETE FROM thesis_authors WHERE thesis_id = ?')->execute([$thesisId]);
$stmt = $this->pdo->prepare(
'INSERT INTO thesis_authors (thesis_id, author_id, author_order) VALUES (?, ?, ?)'
@@ -2204,7 +2223,9 @@ class Database
continue;
}
$showContact = !empty($author['show_contact']);
$authorId = $this->findOrCreateAuthor($name, $author['email'] ?? null, $showContact);
// Pass existing ID by position so findOrCreateAuthor can update directly
$hintId = isset($existingIds[$index]) ? (int)$existingIds[$index] : null;
$authorId = $this->findOrCreateAuthor($name, $author['email'] ?? null, $showContact, $hintId);
$stmt->execute([$thesisId, $authorId, (int)$index + 1]);
}
}