fix: spurious HTMX console warnings from checkbox-list default hx-include

The checkbox-list partial defaulted hx-include to 'this, #website-url-fieldset',
but #website-url-fieldset only exists when `Site web` is checked in the
format list.  Every language checkbox click triggered a no-match warning
and a cascade triggering the known HTMX internal-data crash.
This commit is contained in:
Pontoporeia
2026-05-10 19:23:43 +02:00
parent d5fee1acfb
commit f28a20d642
4 changed files with 73 additions and 5 deletions

View File

@@ -755,16 +755,40 @@ class Database
/**
* Return only the predefined / hardcoded languages used as checkboxes
* in the form. All other languages go into the "Autre langue" input.
*
* De-duplicates accent variants (e.g. 'francais' + 'français') by
* returning the accented row. No REGEXP in SQLite, so we use a
* priority-window approach.
*/
public function getPredefinedLanguages(): array
{
$stmt = $this->pdo->query(
"SELECT id, UPPER(SUBSTR(name,1,1)) || SUBSTR(name,2) as name, created_at
$langs = $this->pdo->query(
"SELECT id, name, created_at,
CASE
WHEN LOWER(name) IN ('français', 'francais') THEN 1
WHEN LOWER(name) = 'anglais' THEN 2
WHEN LOWER(name) IN ('néerlandais', 'neerlandais') THEN 3
END AS grp,
CASE WHEN name GLOB '*[À-ÿ]*' THEN 0 ELSE 1 END AS is_ascii
FROM languages
WHERE LOWER(name) IN ('français', 'anglais', 'néerlandais', 'francais', 'neerlandais')
ORDER BY name"
);
return $stmt->fetchAll();
ORDER BY grp, is_ascii"
)->fetchAll();
// De-duplicate: keep first row per grp (accented variant wins due to ORDER BY)
$seen = [];
$dedup = [];
foreach ($langs as $l) {
$g = $l['grp'];
if (isset($seen[$g])) continue;
$seen[$g] = true;
$dedup[] = [
'id' => $l['id'],
'name' => $l['name'],
'created_at' => $l['created_at'],
];
}
return $dedup;
}
// ========================================================================
@@ -1681,15 +1705,41 @@ class Database
* Return the ID of an existing language by name, inserting it if absent.
* Name is stored lowercase and displayed with first letter capitalized.
*/
/**
* Find or create a language by name (case-insensitive, accent-tolerant).
*
* Normalises the name to lowercase. Before creating a new row, checks
* whether the name differs from an existing row only by accents (e.g.
* 'francais' → matches existing 'français') and returns the existing ID.
*/
public function getOrCreateLanguage(string $name): int
{
$name = strtolower(trim($name));
if ($name === '') {
throw new \InvalidArgumentException('Language name must not be empty.');
}
// 1. Exact lowercase match
$stmt = $this->pdo->prepare('SELECT id FROM languages WHERE LOWER(name) = LOWER(?) LIMIT 1');
$stmt->execute([$name]);
$id = $stmt->fetchColumn();
if ($id !== false) {
return (int)$id;
}
// 2. Accent-tolerant fallback: strip accents and re-compare.
// iconv 'ASCII//TRANSLIT' turns é→e, ç→c, etc.
$asciiName = @iconv('UTF-8', 'ASCII//TRANSLIT', $name);
if ($asciiName !== false && $asciiName !== $name) {
$all = $this->pdo->query('SELECT id, name FROM languages')->fetchAll();
foreach ($all as $row) {
$rowAscii = @iconv('UTF-8', 'ASCII//TRANSLIT', strtolower($row['name']));
if ($rowAscii !== false && $rowAscii === $asciiName) {
return (int)$row['id'];
}
}
}
$this->pdo->prepare('INSERT INTO languages (name) VALUES (?)')->execute([$name]);
return (int)$this->pdo->lastInsertId();
}