mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 08:09:18 +02:00
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:
5
TODO.md
5
TODO.md
@@ -6,3 +6,8 @@
|
||||
- [x] Add `console.log` tracing on JS submit interception
|
||||
- [x] Add `error_log` entry-point logging to all 16 PHP action files
|
||||
- [x] Add double-submit guard (`_xamxamActiveSubmit`)
|
||||
- [x] Fix spurious HTMX console warnings from checkbox-list default hx-include
|
||||
- [x] Fix duplicate language entries (accented vs non-accented variants)
|
||||
- [x] Deduplicate getPredefinedLanguages() query
|
||||
- [x] Accent-tolerant getOrCreateLanguage() to prevent future duplicates
|
||||
- [x] Delete orphan non-accented language rows from DB
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
0
app/storage/xamxam.sqlite
Normal file
0
app/storage/xamxam.sqlite
Normal file
@@ -272,6 +272,19 @@
|
||||
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||
+\\\\\\\ to: muzswpkw dbe1ac28 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
|
||||
++ $linkName = $link['name'] ?? '';
|
||||
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: muzswpkw dbe1ac28 "fix: repair form submission with queued files + add comprehensive debug logging" (rebased revision)
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||
- $linkName = $link['name'] ?? '';
|
||||
- $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: somsyvxz 14a3cd10 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebase destination)
|
||||
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ to: ymrzpvln f17c59a8 "fix: spurious HTMX console warnings from checkbox-list default hx-include" (rebased revision)
|
||||
$linkName = $link['name'] ?? '';
|
||||
$linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||
$linkLockedYear = $link['locked_year'] ?? null;
|
||||
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
|
||||
+\\\\\\\ to: ymrzpvln 01fd03c9 "fix: spurious HTMX console warnings from checkbox-list default hx-include" (rebased revision)
|
||||
++ $linkName = $link['name'] ?? '';
|
||||
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
|
||||
?>
|
||||
<tr class="admin-table-row" onclick="event.stopPropagation(); window.open('/partage/<?= urlencode($link['slug']) ?>', '_blank')" style="cursor:pointer">
|
||||
|
||||
Reference in New Issue
Block a user