mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
Add admin form field partials and apply to add/edit forms
Four reusable PHP partials extracted to templates/partials/form/:
- text-field.php — single-line input (text/number/url); wraps input+hint in div,
skips the inner wrapper when no hint is present. Supports $type,
$placeholder, $required, $attrs, $hint, $id overrides.
- select-field.php — <select> with leading empty option; matches $selected against
option id OR option name string (handles view-sourced data where
orientation/ap/finality come back as name strings, not FK ids).
- checkbox-list.php — checkbox group (languages, formats); renders .admin-checkbox-list
with typed-string comparison so int ids from DB match string values.
- file-field.php — file input with accept/multiple/hint; appends [] to name when
$multiple is true.
Both add.php and edit.php rewritten to use the partials:
- ~15 repeated text-field divs collapsed to single-line include calls
- ~6 repeated select divs collapsed to single-line include calls
- 4 checkbox-list blocks collapsed to 2 calls each
- 3 file input blocks collapsed to single-line include calls
- Textarea fields (synopsis, context_note) kept inline — no partial for <textarea>
- Banner preview block in edit.php kept inline — conditional UI not generalised
Line count: add.php 251→93 (-158), edit.php 289→171 (-118)
This commit is contained in:
8
TODO.md
8
TODO.md
@@ -36,10 +36,10 @@
|
||||
PHP has no component system, but `include`/`require` with variable scoping works as partials. These are already used (`head.php`, `header.php`, `footer.php`, `flash-messages.php`). New partials to extract:
|
||||
|
||||
### Form field partials — `templates/partials/form/`
|
||||
- [ ] **`text-field.php`** — accepts `$name`, `$label`, `$value`, `$required`, `$placeholder`, `$hint`; renders the `<div>…<label>…<input>…<small>` pattern used ~15 times across `add.php` and `edit.php`
|
||||
- [ ] **`select-field.php`** — accepts `$name`, `$label`, `$options[]`, `$selected`, `$required`; renders `<div>…<label>…<select>…</div>` pattern used ~6 times
|
||||
- [ ] **`checkbox-list.php`** — accepts `$name`, `$label`, `$options[]`, `$checked[]`; renders the checkbox group pattern (languages, formats) used ~4 times across `add.php` and `edit.php`
|
||||
- [ ] **`file-field.php`** — accepts `$name`, `$label`, `$accept`, `$hint`, `$multiple`; renders file input pattern used 3 times
|
||||
- [x] **`text-field.php`** — accepts `$name`, `$label`, `$value`, `$required`, `$placeholder`, `$hint`; renders the `<div>…<label>…<input>…<small>` pattern used ~15 times across `add.php` and `edit.php`
|
||||
- [x] **`select-field.php`** — accepts `$name`, `$label`, `$options[]`, `$selected`, `$required`; renders `<div>…<label>…<select>…</div>` pattern used ~6 times; supports match by id or by name string for compatibility with view-sourced data
|
||||
- [x] **`checkbox-list.php`** — accepts `$name`, `$label`, `$options[]`, `$checked[]`; renders the checkbox group pattern (languages, formats) used ~4 times across `add.php` and `edit.php`
|
||||
- [x] **`file-field.php`** — accepts `$name`, `$label`, `$accept`, `$hint`, `$multiple`; renders file input pattern used 3 times
|
||||
- [x] **`jury-fieldset.php`** — the entire jury composition fieldset + JS is duplicated verbatim between `add.php` and `edit.php`; extract into one partial accepting `$juryPresident`, `$juryPromoteur`, `$juryPromoteurExt`, `$juryLecteurs[]`
|
||||
|
||||
### Shared UI partials — `templates/partials/`
|
||||
|
||||
@@ -13,19 +13,19 @@ require_once __DIR__ . '/../../src/Database.php';
|
||||
|
||||
try {
|
||||
$db = new Database();
|
||||
$orientations = $db->getAllOrientations();
|
||||
$apPrograms = $db->getAllAPPrograms();
|
||||
$orientations = $db->getAllOrientations();
|
||||
$apPrograms = $db->getAllAPPrograms();
|
||||
$finalityTypes = $db->getAllFinalityTypes();
|
||||
$languages = $db->getAllLanguages();
|
||||
$formatTypes = $db->getAllFormatTypes();
|
||||
$licenseTypes = $db->getAllLicenseTypes();
|
||||
$languages = $db->getAllLanguages();
|
||||
$formatTypes = $db->getAllFormatTypes();
|
||||
$licenseTypes = $db->getAllLicenseTypes();
|
||||
} catch (Exception $e) {
|
||||
error_log("Failed to load form data: " . $e->getMessage());
|
||||
die("Erreur lors du chargement du formulaire.");
|
||||
}
|
||||
|
||||
$error = $_SESSION["form_error"] ?? null;
|
||||
$formData = $_SESSION["form_data"] ?? [];
|
||||
$error = $_SESSION["form_error"] ?? null;
|
||||
$formData = $_SESSION["form_data"] ?? [];
|
||||
unset($_SESSION["form_error"], $_SESSION["form_data"]);
|
||||
|
||||
function old($key, $default = "") {
|
||||
@@ -52,127 +52,32 @@ function wasSelected($key, $value) {
|
||||
<form action="actions/formulaire.php" method="post" enctype="multipart/form-data" class="admin-form">
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION["csrf_token"]) ?>">
|
||||
|
||||
<!-- Titre -->
|
||||
<div>
|
||||
<label for="titre">Titre :</label>
|
||||
<input type="text" id="titre" name="titre"
|
||||
value="<?= old('titre') ?>" required>
|
||||
</div>
|
||||
|
||||
<!-- Sous-titre -->
|
||||
<div>
|
||||
<label for="subtitle">Sous-titre (si applicable) :</label>
|
||||
<input type="text" id="subtitle" name="subtitle"
|
||||
value="<?= old('subtitle') ?>">
|
||||
</div>
|
||||
|
||||
<!-- Auteur·ice -->
|
||||
<div>
|
||||
<label for="auteurice">Auteur·ice(s) :</label>
|
||||
<input type="text" id="auteurice" name="auteurice"
|
||||
value="<?= old('auteurice') ?>" required>
|
||||
</div>
|
||||
|
||||
<!-- Contact -->
|
||||
<div>
|
||||
<label for="mail">Contact(s) (optionnel) [mail/site/insta/etc.] :</label>
|
||||
<input type="text" id="mail" name="mail"
|
||||
value="<?= old('mail') ?>">
|
||||
</div>
|
||||
<?php $name = 'titre'; $label = 'Titre :'; $value = old('titre'); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'subtitle'; $label = 'Sous-titre (si applicable) :'; $value = old('subtitle'); $required = false; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = old('auteurice'); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact(s) (optionnel) [mail/site/insta/etc.] :'; $value = old('mail'); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<?php require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?>
|
||||
|
||||
<!-- Année -->
|
||||
<div>
|
||||
<label for="année">Année :</label>
|
||||
<input type="number" id="année" name="année"
|
||||
min="2000" max="<?= date('Y') + 1 ?>"
|
||||
placeholder="<?= date('Y') ?>"
|
||||
value="<?= old('année') ?>" required>
|
||||
</div>
|
||||
<?php
|
||||
$name = 'année'; $label = 'Année :'; $value = old('année'); $required = true;
|
||||
$type = 'number';
|
||||
$placeholder = date('Y');
|
||||
$attrs = ['min' => 2000, 'max' => date('Y') + 1];
|
||||
include APP_ROOT . '/templates/partials/form/text-field.php';
|
||||
?>
|
||||
|
||||
<!-- Orientation -->
|
||||
<div>
|
||||
<label for="orientation">Orientation :</label>
|
||||
<select id="orientation" name="orientation" required>
|
||||
<option value=""></option>
|
||||
<?php foreach ($orientations as $o): ?>
|
||||
<option value="<?= htmlspecialchars($o['id']) ?>"
|
||||
<?= wasSelected('orientation', $o['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($o['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'orientation'; $label = 'Orientation :'; $options = $orientations; $selected = $formData['orientation'] ?? ''; $required = true; $placeholder = ''; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<!-- AP -->
|
||||
<div>
|
||||
<label for="ap">Atelier pluridisciplinaire :</label>
|
||||
<select id="ap" name="ap" required>
|
||||
<option value=""></option>
|
||||
<?php foreach ($apPrograms as $ap): ?>
|
||||
<option value="<?= htmlspecialchars($ap['id']) ?>"
|
||||
<?= wasSelected('ap', $ap['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($ap['name']) ?><?php if ($ap['code']): ?> (<?= htmlspecialchars($ap['code']) ?>)<?php endif; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'ap'; $label = 'Atelier pluridisciplinaire :'; $options = $apPrograms; $selected = $formData['ap'] ?? ''; $required = true; $placeholder = ''; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<!-- Finalité -->
|
||||
<div>
|
||||
<label for="finality">Finalité du master :</label>
|
||||
<select id="finality" name="finality" required>
|
||||
<option value=""></option>
|
||||
<?php foreach ($finalityTypes as $f): ?>
|
||||
<option value="<?= htmlspecialchars($f['id']) ?>"
|
||||
<?= wasSelected('finality', $f['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($f['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'finality'; $label = 'Finalité du master :'; $options = $finalityTypes; $selected = $formData['finality'] ?? ''; $required = true; $placeholder = ''; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<!-- Langue(s) -->
|
||||
<div>
|
||||
<label>Langue(s) :</label>
|
||||
<div class="admin-checkbox-list">
|
||||
<?php foreach ($languages as $lang): ?>
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="languages[]"
|
||||
value="<?= htmlspecialchars($lang['id']) ?>"
|
||||
<?= wasSelected('languages', $lang['id']) ? 'checked' : '' ?>>
|
||||
<?= htmlspecialchars($lang['name']) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $formData['languages'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
|
||||
|
||||
<!-- Format(s) -->
|
||||
<div>
|
||||
<label>Format(s) :</label>
|
||||
<div class="admin-checkbox-list">
|
||||
<?php foreach ($formatTypes as $fmt): ?>
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="formats[]"
|
||||
value="<?= htmlspecialchars($fmt['id']) ?>"
|
||||
<?= wasSelected('formats', $fmt['id']) ? 'checked' : '' ?>>
|
||||
<?= htmlspecialchars($fmt['name']) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'formats'; $label = 'Format(s) :'; $options = $formatTypes; $checked = $formData['formats'] ?? []; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
|
||||
|
||||
<!-- Mots-clés -->
|
||||
<div>
|
||||
<label for="tag">Mots-clés :</label>
|
||||
<div>
|
||||
<input type="text" id="tag" name="tag"
|
||||
placeholder="sociologie, anthropologie, ..."
|
||||
value="<?= old('tag') ?>">
|
||||
<small>Séparez par des virgules. Max 10 mots-clés.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'tag'; $label = 'Mots-clés :'; $value = old('tag'); $placeholder = 'sociologie, anthropologie, ...'; $hint = 'Séparez par des virgules. Max 10 mots-clés.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<!-- Synopsis -->
|
||||
<div>
|
||||
@@ -181,66 +86,17 @@ function wasSelected($key, $value) {
|
||||
rows="7" required><?= old('synopsis') ?></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Licence -->
|
||||
<div>
|
||||
<label for="license_id">Licence :</label>
|
||||
<select id="license_id" name="license_id">
|
||||
<option value="">— Inconnue —</option>
|
||||
<?php foreach ($licenseTypes as $lt): ?>
|
||||
<option value="<?= htmlspecialchars($lt['id']) ?>"
|
||||
<?= wasSelected('license_id', $lt['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($lt['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes; $selected = $formData['license_id'] ?? ''; $placeholder = '— Inconnue —'; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<!-- Durée/Taille -->
|
||||
<div>
|
||||
<label for="duration_info">Durée / Taille :</label>
|
||||
<div>
|
||||
<input type="text" id="duration_info" name="duration_info"
|
||||
placeholder="Ex : 84 pages"
|
||||
value="<?= old('duration_info') ?>">
|
||||
<small>Durée (minutes) ou nombre de pages.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'duration_info'; $label = 'Durée / Taille :'; $value = old('duration_info'); $placeholder = 'Ex : 84 pages'; $hint = 'Durée (minutes) ou nombre de pages.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<!-- Lien -->
|
||||
<div>
|
||||
<label for="lien">Lien (site / ressource) :</label>
|
||||
<input type="url" id="lien" name="lien"
|
||||
placeholder="https://..."
|
||||
value="<?= old('lien') ?>">
|
||||
</div>
|
||||
<?php $name = 'lien'; $label = 'Lien (site / ressource) :'; $value = old('lien'); $type = 'url'; $placeholder = 'https://...'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<!-- Image couverture -->
|
||||
<div>
|
||||
<label>Image de couverture :</label>
|
||||
<div class="admin-file-input">
|
||||
<input type="file" id="couverture" name="couverture" accept="image/jpeg,image/png">
|
||||
<small>JPG, PNG. Taille max : 10 MB.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'couverture'; $label = 'Image de couverture :'; $accept = 'image/jpeg,image/png'; $hint = 'JPG, PNG. Taille max : 10 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
|
||||
|
||||
<!-- Image bannière -->
|
||||
<div>
|
||||
<label>Image bannière (accueil) :</label>
|
||||
<div class="admin-file-input">
|
||||
<input type="file" id="banner" name="banner" accept="image/jpeg,image/png,image/webp">
|
||||
<small>JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'banner'; $label = 'Image bannière (accueil) :'; $accept = 'image/jpeg,image/png,image/webp'; $hint = 'JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.'; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
|
||||
|
||||
<!-- Fichiers -->
|
||||
<div>
|
||||
<label>Fichiers du TFE :</label>
|
||||
<div class="admin-file-input">
|
||||
<input type="file" id="files" name="files[]" multiple
|
||||
accept=".pdf,.jpg,.jpeg,.png,.mp4,.zip">
|
||||
<small>PDF, JPG, PNG, MP4, ZIP. Max 50 MB par fichier.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'files'; $label = 'Fichiers du TFE :'; $accept = '.pdf,.jpg,.jpeg,.png,.mp4,.zip'; $hint = 'PDF, JPG, PNG, MP4, ZIP. Max 50 MB par fichier.'; $multiple = true; include APP_ROOT . '/templates/partials/form/file-field.php'; ?>
|
||||
|
||||
<div class="admin-submit-wrap">
|
||||
<button type="submit" name="go" class="admin-btn">Soumettre</button>
|
||||
|
||||
@@ -78,58 +78,20 @@ try {
|
||||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||||
<input type="hidden" name="thesis_id" value="<?= $thesisId ?>">
|
||||
|
||||
<div>
|
||||
<label for="auteurice">Auteur·ice(s) :</label>
|
||||
<input type="text" id="auteurice" name="auteurice"
|
||||
value="<?= htmlspecialchars($thesis['authors']) ?>" required>
|
||||
</div>
|
||||
<?php $name = 'auteurice'; $label = 'Auteur·ice(s) :'; $value = htmlspecialchars($thesis['authors']); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'mail'; $label = 'Contact :'; $value = ''; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="mail">Contact :</label>
|
||||
<input type="text" id="mail" name="mail" value="">
|
||||
</div>
|
||||
<?php
|
||||
$name = 'année'; $label = 'Année :'; $value = htmlspecialchars((string)$thesis['year']); $required = true;
|
||||
$type = 'number';
|
||||
include APP_ROOT . '/templates/partials/form/text-field.php';
|
||||
?>
|
||||
|
||||
<div>
|
||||
<label for="année">Année :</label>
|
||||
<input type="number" id="année" name="année"
|
||||
value="<?= $thesis['year'] ?>" required>
|
||||
</div>
|
||||
<?php $name = 'orientation'; $label = 'Orientation :'; $options = $orientations; $selected = $thesis['orientation']; $required = true; $placeholder = null; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="orientation">Orientation :</label>
|
||||
<select id="orientation" name="orientation" required>
|
||||
<?php foreach ($orientations as $o): ?>
|
||||
<option value="<?= $o['id'] ?>"
|
||||
<?= ($thesis['orientation'] == $o['name']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($o['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'ap'; $label = 'Atelier pluridisciplinaire :'; $options = $apPrograms; $selected = $thesis['ap_program']; $required = true; $placeholder = null; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="ap">Atelier pluridisciplinaire :</label>
|
||||
<select id="ap" name="ap" required>
|
||||
<?php foreach ($apPrograms as $ap): ?>
|
||||
<option value="<?= $ap['id'] ?>"
|
||||
<?= ($thesis['ap_program'] == $ap['name']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($ap['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="finality">Finalité du master :</label>
|
||||
<select id="finality" name="finality" required>
|
||||
<?php foreach ($finalityTypes as $f): ?>
|
||||
<option value="<?= $f['id'] ?>"
|
||||
<?= ($thesis['finality_type'] == $f['name']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($f['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'finality'; $label = 'Finalité du master :'; $options = $finalityTypes; $selected = $thesis['finality_type']; $required = true; $placeholder = null; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<!-- Composition du jury -->
|
||||
<?php
|
||||
@@ -150,109 +112,51 @@ try {
|
||||
?>
|
||||
<?php require APP_ROOT . '/templates/partials/form/jury-fieldset.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="access_type_id">Visibilité / Accès :</label>
|
||||
<select id="access_type_id" name="access_type_id">
|
||||
<option value="">- Non défini -</option>
|
||||
<?php foreach ($accessTypes as $at): ?>
|
||||
<option value="<?= (int)$at['id'] ?>"
|
||||
<?= ($currentAccessTypeId == $at['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($at['name']) ?>
|
||||
<?php if (!empty($at['description'])): ?>
|
||||
- <?= htmlspecialchars(mb_strimwidth($at['description'], 0, 60, '...')) ?>
|
||||
<?php endif; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php
|
||||
// Access type select: options need 'id'+'name'; description appended inline
|
||||
$accessOptions = array_map(function($at) {
|
||||
$label = $at['name'];
|
||||
if (!empty($at['description'])) {
|
||||
$label .= ' - ' . mb_strimwidth($at['description'], 0, 60, '...');
|
||||
}
|
||||
return ['id' => $at['id'], 'name' => $label];
|
||||
}, $accessTypes);
|
||||
$name = 'access_type_id'; $label = 'Visibilité / Accès :'; $options = $accessOptions; $selected = $currentAccessTypeId; $placeholder = '- Non défini -';
|
||||
include APP_ROOT . '/templates/partials/form/select-field.php';
|
||||
?>
|
||||
|
||||
<!-- Context note (textarea — no text-field partial for textarea) -->
|
||||
<div>
|
||||
<label for="context_note">Note contextuelle :</label>
|
||||
<div>
|
||||
<textarea id="context_note" name="context_note"
|
||||
rows="4" maxlength="1500"><?= htmlspecialchars($currentContextNote ?? '') ?></textarea>
|
||||
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
|
||||
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="license_id">Licence :</label>
|
||||
<select id="license_id" name="license_id">
|
||||
<option value="">- Inconnue -</option>
|
||||
<?php foreach ($licenseTypes as $lt): ?>
|
||||
<option value="<?= $lt['id'] ?>"
|
||||
<?= ($currentLicenseId == $lt['id']) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($lt['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php $name = 'license_id'; $label = 'Licence :'; $options = $licenseTypes; $selected = $currentLicenseId; $placeholder = '- Inconnue -'; include APP_ROOT . '/templates/partials/form/select-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="titre">Titre :</label>
|
||||
<input type="text" id="titre" name="titre"
|
||||
value="<?= htmlspecialchars($thesis['title']) ?>" required>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="subtitle">Sous-titre :</label>
|
||||
<input type="text" id="subtitle" name="subtitle"
|
||||
value="<?= htmlspecialchars($thesis['subtitle'] ?? '') ?>">
|
||||
</div>
|
||||
<?php $name = 'titre'; $label = 'Titre :'; $value = htmlspecialchars($thesis['title']); $required = true; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
<?php $name = 'subtitle'; $label = 'Sous-titre :'; $value = htmlspecialchars($thesis['subtitle'] ?? ''); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<!-- Synopsis (textarea — not covered by text-field partial) -->
|
||||
<div>
|
||||
<label for="synopsis">Synopsis :</label>
|
||||
<textarea id="synopsis" name="synopsis" rows="7" required><?= htmlspecialchars($thesis['synopsis'] ?? '') ?></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Langue(s) :</label>
|
||||
<div class="admin-checkbox-list">
|
||||
<?php foreach ($languages as $lang): ?>
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="languages[]" value="<?= $lang['id'] ?>"
|
||||
<?= in_array($lang['id'], $currentLanguages) ? 'checked' : '' ?>>
|
||||
<?= htmlspecialchars($lang['name']) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'languages'; $label = 'Langue(s) :'; $options = $languages; $checked = $currentLanguages; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
|
||||
|
||||
<div>
|
||||
<label>Format(s) :</label>
|
||||
<div class="admin-checkbox-list">
|
||||
<?php foreach ($formatTypes as $fmt): ?>
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox" name="formats[]" value="<?= $fmt['id'] ?>"
|
||||
<?= in_array($fmt['id'], $currentFormats) ? 'checked' : '' ?>>
|
||||
<?= htmlspecialchars($fmt['name']) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'formats'; $label = 'Format(s) :'; $options = $formatTypes; $checked = $currentFormats; include APP_ROOT . '/templates/partials/form/checkbox-list.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="tag">Mots-clés :</label>
|
||||
<div>
|
||||
<input type="text" id="tag" name="tag"
|
||||
value="<?= htmlspecialchars($thesis['keywords'] ?? '') ?>">
|
||||
<small>Séparer par des virgules. Max 10.</small>
|
||||
</div>
|
||||
</div>
|
||||
<?php $name = 'tag'; $label = 'Mots-clés :'; $value = htmlspecialchars($thesis['keywords'] ?? ''); $hint = 'Séparer par des virgules. Max 10.'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="duration_info">Durée / Taille :</label>
|
||||
<input type="text" id="duration_info" name="duration_info"
|
||||
value="<?= htmlspecialchars($thesis['file_size_info'] ?? '') ?>">
|
||||
</div>
|
||||
<?php $name = 'duration_info'; $label = 'Durée / Taille :'; $value = htmlspecialchars($thesis['file_size_info'] ?? ''); include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<div>
|
||||
<label for="lien">Lien externe :</label>
|
||||
<input type="url" id="lien" name="lien"
|
||||
value="<?= htmlspecialchars($thesis['baiu_link'] ?? '') ?>">
|
||||
</div>
|
||||
<?php $name = 'lien'; $label = 'Lien externe :'; $value = htmlspecialchars($thesis['baiu_link'] ?? ''); $type = 'url'; include APP_ROOT . '/templates/partials/form/text-field.php'; ?>
|
||||
|
||||
<!-- Image bannière -->
|
||||
<!-- Image bannière (custom: includes current banner preview + remove checkbox) -->
|
||||
<div>
|
||||
<label>Image bannière (accueil) :</label>
|
||||
<div>
|
||||
@@ -270,6 +174,7 @@ try {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Publication toggle -->
|
||||
<div>
|
||||
<label>Publication :</label>
|
||||
<label class="admin-checkbox-label">
|
||||
|
||||
29
templates/partials/form/checkbox-list.php
Normal file
29
templates/partials/form/checkbox-list.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Checkbox list partial — renders a group of checkboxes (e.g. languages, formats).
|
||||
*
|
||||
* Variables consumed:
|
||||
* string $name — input name attribute (will be posted as array: name[])
|
||||
* string $label — group label (rendered as plain <label>, not associated with any single input)
|
||||
* array $options — each element must have 'id' and 'name' keys
|
||||
* array $checked — array of 'id' values that are currently checked
|
||||
*/
|
||||
|
||||
$checked = $checked ?? [];
|
||||
?>
|
||||
<div>
|
||||
<label><?= htmlspecialchars($label) ?></label>
|
||||
<div class="admin-checkbox-list">
|
||||
<?php foreach ($options as $opt): ?>
|
||||
<label class="admin-checkbox-label">
|
||||
<input type="checkbox"
|
||||
name="<?= htmlspecialchars($name) ?>[]"
|
||||
value="<?= htmlspecialchars((string)$opt['id']) ?>"
|
||||
<?= in_array((string)$opt['id'], array_map('strval', $checked)) ? 'checked' : '' ?>>
|
||||
<?= htmlspecialchars($opt['name']) ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
unset($checked);
|
||||
33
templates/partials/form/file-field.php
Normal file
33
templates/partials/form/file-field.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* File input partial.
|
||||
*
|
||||
* Variables consumed:
|
||||
* string $name — input name attribute (used for id too unless $id set)
|
||||
* string $label — visible label text
|
||||
* string $accept — MIME types / extensions for the accept attribute (e.g. 'image/jpeg,image/png')
|
||||
* string|null $hint — optional hint shown in <small> below the input
|
||||
* bool $multiple — whether to allow multiple file selection; default false
|
||||
* string|null $id — override the id attribute (defaults to $name)
|
||||
*/
|
||||
|
||||
$accept = $accept ?? '';
|
||||
$hint = $hint ?? null;
|
||||
$multiple = $multiple ?? false;
|
||||
$id = $id ?? $name;
|
||||
?>
|
||||
<div>
|
||||
<label for="<?= htmlspecialchars($id) ?>"><?= htmlspecialchars($label) ?></label>
|
||||
<div class="admin-file-input">
|
||||
<input type="file"
|
||||
id="<?= htmlspecialchars($id) ?>"
|
||||
name="<?= htmlspecialchars($name) ?><?= $multiple ? '[]' : '' ?>"
|
||||
<?= $accept ? 'accept="' . htmlspecialchars($accept) . '"' : '' ?>
|
||||
<?= $multiple ? 'multiple' : '' ?>>
|
||||
<?php if ($hint): ?>
|
||||
<small><?= htmlspecialchars($hint) ?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
unset($accept, $hint, $multiple, $id);
|
||||
49
templates/partials/form/select-field.php
Normal file
49
templates/partials/form/select-field.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Select field partial.
|
||||
*
|
||||
* Variables consumed:
|
||||
* string $name — select name attribute (also used for id)
|
||||
* string $label — visible label text
|
||||
* array $options — each element must have 'id' and 'name' keys;
|
||||
* may optionally have 'code' for display suffix
|
||||
* mixed $selected — currently selected value (compared to option 'id');
|
||||
* pass null or '' for no selection
|
||||
* bool $required — whether the field is required; default false
|
||||
* string $placeholder — text for the leading empty <option>; default ''
|
||||
* set to null to suppress the empty option entirely
|
||||
* string|null $id — override the id attribute (defaults to $name)
|
||||
* string|null $hint — optional hint shown in <small> below the select
|
||||
*/
|
||||
|
||||
$required = $required ?? false;
|
||||
$placeholder = array_key_exists('placeholder', get_defined_vars()) ? $placeholder : '';
|
||||
$id = $id ?? $name;
|
||||
$hint = $hint ?? null;
|
||||
?>
|
||||
<div>
|
||||
<label for="<?= htmlspecialchars($id) ?>"><?= htmlspecialchars($label) ?></label>
|
||||
<select id="<?= htmlspecialchars($id) ?>"
|
||||
name="<?= htmlspecialchars($name) ?>"
|
||||
<?= $required ? 'required' : '' ?>>
|
||||
<?php if ($placeholder !== null): ?>
|
||||
<option value=""><?= htmlspecialchars($placeholder) ?></option>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($options as $opt): ?>
|
||||
<?php
|
||||
// Match by id (numeric FK) or by name string (when the view returns the name).
|
||||
$isSelected = ((string)$selected === (string)$opt['id'])
|
||||
|| ($selected !== null && $selected !== '' && isset($opt['name']) && (string)$selected === (string)$opt['name']);
|
||||
?>
|
||||
<option value="<?= htmlspecialchars((string)$opt['id']) ?>"
|
||||
<?= $isSelected ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($opt['name']) ?><?php if (!empty($opt['code'])): ?> (<?= htmlspecialchars($opt['code']) ?>)<?php endif; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php if ($hint): ?>
|
||||
<small><?= htmlspecialchars($hint) ?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
unset($required, $placeholder, $id, $hint);
|
||||
56
templates/partials/form/text-field.php
Normal file
56
templates/partials/form/text-field.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Text field partial — single-line text / number / url / email input.
|
||||
*
|
||||
* Variables consumed:
|
||||
* string $name — input name attribute (also used for id)
|
||||
* string $label — visible label text
|
||||
* string $value — current value (already htmlspecialchars'd by caller, or raw)
|
||||
* string $type — input type; default 'text'
|
||||
* bool $required — whether the field is required; default false
|
||||
* string $placeholder — placeholder text; default ''
|
||||
* string|null $hint — optional hint shown in <small> below the input
|
||||
* string|null $id — override the id attribute (defaults to $name)
|
||||
* array $attrs — extra HTML attributes as key=>value pairs (e.g. min/max for number)
|
||||
*
|
||||
* The partial does NOT call htmlspecialchars on $value — the caller is responsible.
|
||||
*/
|
||||
|
||||
$type = $type ?? 'text';
|
||||
$required = $required ?? false;
|
||||
$placeholder = $placeholder ?? '';
|
||||
$hint = $hint ?? null;
|
||||
$id = $id ?? $name;
|
||||
$attrs = $attrs ?? [];
|
||||
|
||||
$attrStr = '';
|
||||
foreach ($attrs as $k => $v) {
|
||||
$attrStr .= ' ' . htmlspecialchars($k) . '="' . htmlspecialchars((string)$v) . '"';
|
||||
}
|
||||
?>
|
||||
<div>
|
||||
<label for="<?= htmlspecialchars($id) ?>"><?= htmlspecialchars($label) ?></label>
|
||||
<?php if ($hint): ?>
|
||||
<div>
|
||||
<input type="<?= htmlspecialchars($type) ?>"
|
||||
id="<?= htmlspecialchars($id) ?>"
|
||||
name="<?= htmlspecialchars($name) ?>"
|
||||
value="<?= $value ?>"
|
||||
<?= $required ? 'required' : '' ?>
|
||||
<?= $placeholder ? 'placeholder="' . htmlspecialchars($placeholder) . '"' : '' ?>
|
||||
<?= $attrStr ?>>
|
||||
<small><?= htmlspecialchars($hint) ?></small>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<input type="<?= htmlspecialchars($type) ?>"
|
||||
id="<?= htmlspecialchars($id) ?>"
|
||||
name="<?= htmlspecialchars($name) ?>"
|
||||
value="<?= $value ?>"
|
||||
<?= $required ? 'required' : '' ?>
|
||||
<?= $placeholder ? 'placeholder="' . htmlspecialchars($placeholder) . '"' : '' ?>
|
||||
<?= $attrStr ?>>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
// Reset consumed variables so includes in a loop don't bleed state.
|
||||
unset($type, $required, $placeholder, $hint, $id, $attrs, $attrStr, $k, $v);
|
||||
Reference in New Issue
Block a user