diff --git a/TODO.md b/TODO.md
index be7fb0e..0779163 100644
--- a/TODO.md
+++ b/TODO.md
@@ -3,6 +3,9 @@
- [x] Fix email addresses in about.php contacts section not using EmailObfuscator for link text
- [x] Raise rate limits: SearchController 30→300, request-access 3→30, partage 5→50
- [x] Make Libre option toggleable in Degré d'ouverture fieldset, move to top, remove temporary note
+- [x] Mots-clés required (min 3) in partage form: red count < 3, accent ≥ 3
+- [x] Language checkbox-list no longer required when language_autre pill is present
+- [x] Admin contenus: auto-save checkboxes via HTMX (Restrictions, Degré d'ouverture, Types de travaux), remove Enregistrer buttons
- [x] Improve recapitulatif.php (partage): bottom margin/padding, center .thanks-success
- [x] Display ALL submitted info in recapitulatif page + email recap
- [x] Add "validate your info / contact xamxam@erg.be" note on recap page
diff --git a/app/public/admin/actions/settings.php b/app/public/admin/actions/settings.php
index 759501b..2906c6d 100644
--- a/app/public/admin/actions/settings.php
+++ b/app/public/admin/actions/settings.php
@@ -18,6 +18,7 @@ require_once APP_ROOT . '/src/AdminLogger.php';
$db = new Database();
$logger = AdminLogger::make();
+$isHxRequest = (isset($_SERVER['HTTP_HX_REQUEST']) && $_SERVER['HTTP_HX_REQUEST'] === 'true');
$section = $_POST['section'] ?? '';
if ($section === 'formulaire') {
@@ -34,7 +35,9 @@ if ($section === 'formulaire') {
$newValues[$key] = $value;
}
$logger->logFormSettingsUpdate($newValues);
- App::flash('success', "Paramètres du formulaire mis à jour.");
+ if (!$isHxRequest) {
+ App::flash('success', "Paramètres du formulaire mis à jour.");
+ }
} elseif ($section === 'objet_types') {
$newValues = [
'objet_these_enabled' => isset($_POST['objet_these_enabled']) ? '1' : '0',
@@ -43,7 +46,9 @@ if ($section === 'formulaire') {
$db->setSetting('objet_these_enabled', $newValues['objet_these_enabled']);
$db->setSetting('objet_frart_enabled', $newValues['objet_frart_enabled']);
$logger->logObjetTypesUpdate($newValues);
- App::flash('success', "Types de travaux mis à jour.");
+ if (!$isHxRequest) {
+ App::flash('success', "Types de travaux mis à jour.");
+ }
} elseif ($section === 'smtp') {
$smtpData = [
'host' => $_POST['smtp_host'] ?? '',
@@ -96,5 +101,15 @@ if ($section === 'formulaire') {
}
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
+
+if ($isHxRequest) {
+ // Return updated CSRF tokens for all three hidden inputs on the page
+ $newToken = htmlspecialchars($_SESSION['csrf_token']);
+ echo '';
+ echo '';
+ echo '';
+ exit;
+}
+
header('Location: /admin/parametres.php');
exit;
diff --git a/app/public/partage/language-autre-fragment.php b/app/public/partage/language-autre-fragment.php
index 26f6e84..5e0e82a 100644
--- a/app/public/partage/language-autre-fragment.php
+++ b/app/public/partage/language-autre-fragment.php
@@ -18,5 +18,16 @@ $selectedIds = isset($_POST['languages']) && is_array($_POST['languages'])
? $_POST['languages']
: [];
$anyChecked = !empty($selectedIds);
+
+// Also check if any "autre" language pills are present (posted as language_autre[])
+$hasLangAutre = isset($_POST['language_autre']) && is_array($_POST['language_autre'])
+ && count(array_filter($_POST['language_autre'], fn($l) => is_string($l) && trim($l) !== '')) > 0;
+
+// The "Autre(s) langue(s)" label is required if no standard language is checked.
+// The "Langue(s) du TFE" checkbox list is required if neither standard languages
+// nor "autre" languages are set.
+$langAutreRequired = !$anyChecked;
+$checkboxesRequired = !$anyChecked && !$hasLangAutre;
?>
-= !$anyChecked ? ' *' : '' ?>
+= $langAutreRequired ? ' *' : '' ?>
+= $checkboxesRequired ? ' *' : '' ?>
diff --git a/app/templates/admin/acces.php b/app/templates/admin/acces.php
index 5e5d743..da7f14f 100644
--- a/app/templates/admin/acces.php
+++ b/app/templates/admin/acces.php
@@ -545,6 +545,19 @@
+%%%%%%% diff from: somsyvxz 249f7943 "Bulk bar anti-shift, tags icons, AP no-wrap, credits reorder" (rebased revision)
+\\\\\\\ to: nqmqrqmo dd511b0d "fix: obfuscate email in contact links, raise rate limits, make Libre toggleable" (rebased revision)
++ $linkName = $link['name'] ?? '';
+++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff from: nqmqrqmo dd511b0d "fix: obfuscate email in contact links, raise rate limits, make Libre toggleable" (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: olzzwmwr 277c8ce4 "feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes" (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: olzzwmwr 82533c5a "feat: require 3 mots-clés in partage, language asterisk toggle, admin auto-save checkboxes" (rebased revision)
+++ $linkName = $link['name'] ?? '';
++ $linkExpiresVal = $link['expires_at'] ? date('Y-m-d\TH:i', strtotime($link['expires_at'])) : '';
?>
diff --git a/app/templates/admin/contenus.php b/app/templates/admin/contenus.php
index 0bd3c59..14ffe9c 100644
--- a/app/templates/admin/contenus.php
+++ b/app/templates/admin/contenus.php
@@ -88,34 +88,40 @@