mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
* **Unified Format + Fichiers into a single HTMX fragment**
* Introduced `app/public/partage/fichiers-fragment.php` as shared dynamic block returning both format checkboxes and adaptive “Fichiers” fieldset
* Logic adapts inputs based on selected formats:
* no selection / upload formats → standard file inputs
* “Site web” → URL fields only
* “Site web + upload” → file inputs + URL sub-fieldset
* Added admin wrapper: `app/public/admin/fichiers-fragment.php` (gated via `admin_mode=1`)
* Added `app/public/admin/format-website-fragment.php` for edit-mode website URL toggling
* Wired route `/partage/fichiers-fragment` in `app/public/partage/index.php`
* Refactored `form.php` (add/edit partage) to use single `#format-fichiers-block` instead of separate fragments
* Edit mode format checkboxes now target `format-website-fragment.php` → `#edit-website-url-fieldset`
* Added `$hxInclude` support in `checkbox-list.php` for configurable HTMX includes
* **Format system migration + ordering**
* Migration `020_format_types_sort_and_rename.sql`:
* added `sort_order` column to `format_types`
* inserted new format **Image**
* defined ordering: Écriture · Image · Audio · Vidéo · Site web · Performance · Objet éditorial · Installation · Autre
* `Database.php`: format queries now use `ORDER BY sort_order, id`
* `fichiers-fragment.php`:
* uses ordered format list
* resolves Image/Vidéo/Audio by name
* introduces `$hasImage` flag
* preserves `admin_mode` across HTMX requests
* **File constraints and UX updates**
* Enforced **100 MB PDF limit**
* `ThesisCreateController`: `MAX_PDF_SIZE = 100MB` for PDFs only
* `ThesisEditController`: same PDF-specific constraint applied
* Other file types remain capped at 500 MB
* Updated UI hints in `fichiers-fragment.php` and edit form:
* explicitly mention 100 MB PDF limit
* added reference to `bentopdf.com` for compression guidance
* `file-field.php`: added `$hintRaw` to allow HTML rendering in hints
* **Admin authentication fix**
* Fixed missing auth in admin fragments
* Added `require_once AdminAuth.php`
* Replaced direct usage with `AdminAuth::requireLogin()`
* Applied consistent pattern with existing fragment authentication approach
* **Migrations included**
* `019_add_ecriture_format.sql`
* `020_format_types_sort_and_rename.sql`
* **Files affected**
* Controllers: `ThesisCreateController`, `ThesisEditController`
* DB layer: `Database.php`
* Public fragments: `partage/fichiers-fragment.php`, `admin/fichiers-fragment.php`, `admin/format-website-fragment.php`
* Templates: `form.php`, `checkbox-list.php`, `file-field.php`
* Routing: `partage/index.php`
* Misc: `TODO.md`
This consolidates format normalization, HTMX UI simplification, file validation rules, and admin stability fixes into a single coherent system update.
606 lines
29 KiB
PHP
606 lines
29 KiB
PHP
<?php
|
||
/**
|
||
* Shared TFE form partial — single source of truth for add, edit, and partage forms.
|
||
*
|
||
* Required variables (set by the including page):
|
||
* string $mode — 'add' | 'edit' | 'partage'
|
||
* string $formAction — form action URL
|
||
* string $hiddenFields — raw HTML for hidden inputs (csrf, thesis_id, etc.)
|
||
*
|
||
* old/value callables:
|
||
* callable $oldFn — fn(string $key, string $default=''): string (with escaping)
|
||
* callable $withAutofocusFn — fn(string $field, array $attrs=[]): array
|
||
*
|
||
* Data shared across fieldsets:
|
||
* array $formData — raw form repopulation data (not pre-escaped)
|
||
* array $orientations, $apPrograms, $finalityTypes, $languages, $formatTypes, $licenseTypes
|
||
*
|
||
* Jury data:
|
||
* ?string $juryPromoteur, $juryPromoteurUlb, $juryPresident
|
||
* array $lecteursInternes, $lecteursExternes
|
||
* bool $showPresident, $showPromoteurUlb, $promoteurUlbConditional
|
||
*
|
||
* Licence / access:
|
||
* bool $libreEnabled, $interneEnabled, $interditEnabled
|
||
* string $generalitiesHtml
|
||
* int $defaultAccessTypeId
|
||
*
|
||
* Optional flags (all default to false):
|
||
* bool $showIntroHelp — render partage intro help block
|
||
* bool $showFlash — render flash banners (error/warning/success)
|
||
* bool $showContact — Contact checkbox fieldset
|
||
* bool $showCoverPreview — cover image preview + remove checkbox
|
||
* bool $showExistingFiles — existing thesis files list (sortable, deletable)
|
||
* bool $showContextNote — Note contextuelle fieldset
|
||
* bool $showBackoffice — Backoffice fieldset (jury_points, remarks, contact_interne, exemplaires)
|
||
* bool $showEmailConfirmation — E-mail de confirmation fieldset
|
||
* bool $showPublish — Publication checkbox fieldset
|
||
* string $helpFn — fn(string $key): string (for help blocks)
|
||
* string $helpContent — current help block content (for help-block renders)
|
||
* array $helpBlocks — all help blocks (for intro)
|
||
*
|
||
* Files mode variables:
|
||
* string $filesMode — 'add' | 'edit' (determines which file inputs to show)
|
||
* ?string $currentCover — existing cover file info for edit mode
|
||
* array $currentFiles — existing thesis files for edit mode
|
||
* ?string $currentContextNote — existing context note for edit mode
|
||
* array $currentRaw — raw thesis row for edit mode
|
||
* ?string $currentAuthorShowContact — author show_contact flag for edit mode
|
||
* ?string $currentAuthorEmail — author email for edit mode
|
||
*
|
||
* Website:
|
||
* string $existingWebsiteUrl
|
||
* string $existingWebsiteLabel
|
||
* array $checkedFormatsForSiteWeb
|
||
*/
|
||
|
||
// ── Defaults ──────────────────────────────────────────────────────────────────
|
||
$mode = $mode ?? 'add';
|
||
// In admin add/edit, no field is required (admins can save partial records)
|
||
$adminMode = ($mode === 'add' || $mode === 'edit');
|
||
$formAction = $formAction ?? '';
|
||
$hiddenFields = $hiddenFields ?? '';
|
||
$formData = $formData ?? [];
|
||
$synopsisExtra = $synopsisExtra ?? "";
|
||
|
||
$juryPromoteur = $juryPromoteur ?? null;
|
||
$juryPromoteurUlb = $juryPromoteurUlb ?? null;
|
||
$lecteursInternes = $lecteursInternes ?? [];
|
||
$lecteursExternes = $lecteursExternes ?? [];
|
||
$juryPresident = $juryPresident ?? null;
|
||
$showPresident = $showPresident ?? false;
|
||
$showPromoteurUlb = $showPromoteurUlb ?? true;
|
||
$promoteurUlbConditional = $promoteurUlbConditional ?? false;
|
||
|
||
$libreEnabled = $libreEnabled ?? true;
|
||
$interneEnabled = $interneEnabled ?? true;
|
||
$interditEnabled = $interditEnabled ?? true;
|
||
$generalitiesHtml = $generalitiesHtml ?? "";
|
||
$defaultAccessTypeId = $defaultAccessTypeId ?? 2;
|
||
|
||
// Optional flags
|
||
$showIntroHelp = $showIntroHelp ?? false;
|
||
$showFlash = $showFlash ?? false;
|
||
$showContact = $showContact ?? false;
|
||
$showCoverPreview = $showCoverPreview ?? false;
|
||
$showExistingFiles = $showExistingFiles ?? false;
|
||
$showBannerPreview = false; // Banners merged into covers — field removed
|
||
$showContextNote = $showContextNote ?? false;
|
||
$showBackoffice = $showBackoffice ?? false;
|
||
$showEmailConfirmation = $showEmailConfirmation ?? false;
|
||
$showPublish = $showPublish ?? false;
|
||
|
||
$oldFn = $oldFn ?? (function_exists('old') ? 'old' : fn($k, $d = '') => $d);
|
||
$withAutofocusFn = $withAutofocusFn ?? fn($field, $attrs = []) => $attrs;
|
||
$filesMode = $filesMode ?? 'add';
|
||
$existingWebsiteUrl = $existingWebsiteUrl ?? '';
|
||
$existingWebsiteLabel = $existingWebsiteLabel ?? '';
|
||
$checkedFormatsForSiteWeb = $checkedFormatsForSiteWeb ?? [];
|
||
?>
|
||
|
||
<?php if ($showIntroHelp && isset($helpFn)): ?>
|
||
<?php
|
||
$helpContent = $helpFn("partage_intro");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
?>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($showFlash): ?>
|
||
<?php
|
||
$flashError = $_SESSION["_flash_error"] ?? null;
|
||
$flashWarning = $_SESSION["_flash_warning"] ?? null;
|
||
$flashSuccess = $_SESSION["_flash_success"] ?? null;
|
||
unset(
|
||
$_SESSION["_flash_error"],
|
||
$_SESSION["_flash_warning"],
|
||
$_SESSION["_flash_success"],
|
||
);
|
||
?>
|
||
<?php if ($flashError): ?>
|
||
<div class="flash-error" role="alert"><?= htmlspecialchars(
|
||
$flashError,
|
||
) ?></div>
|
||
<?php endif; ?>
|
||
<?php if ($flashWarning): ?>
|
||
<div class="flash-warning" id="flash-warning" role="alert" tabindex="-1"><?= htmlspecialchars(
|
||
$flashWarning,
|
||
) ?></div>
|
||
<script>document.addEventListener('DOMContentLoaded',function(){var el=document.getElementById('flash-warning');if(el){el.scrollIntoView({behavior:'smooth',block:'center'});el.focus();}});</script>
|
||
<?php endif; ?>
|
||
<?php if ($flashSuccess): ?>
|
||
<div class="flash-success" role="alert"><?= htmlspecialchars(
|
||
$flashSuccess,
|
||
) ?></div>
|
||
<?php endif; ?>
|
||
<?php endif; ?>
|
||
|
||
<form action="<?= $formAction ?>" method="post" enctype="multipart/form-data" class="admin-form" data-beforeunload-guard>
|
||
<?= $hiddenFields ?>
|
||
|
||
<?php if (!$adminMode): ?>
|
||
<p class="required-note"><span class="asterisk">*</span> Champs obligatoires</p>
|
||
<?php endif; ?>
|
||
|
||
<!-- ═══════════════════ Informations du TFE ═══════════════════ -->
|
||
<?php
|
||
if ($mode === "partage" && isset($helpFn)) {
|
||
$helpContent = $helpFn("fieldset_tfe_info");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
}
|
||
include APP_ROOT . "/templates/partials/form/fieldset-tfe-info.php";
|
||
?>
|
||
|
||
<?php if ($showContact): ?>
|
||
<!-- ═══════════════════ Contact ═══════════════════ -->
|
||
<fieldset>
|
||
<legend>Contact</legend>
|
||
<div class="admin-form-group">
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="contact_public" value="1"
|
||
<?= !empty($formData["contact_public"]) ||
|
||
($currentAuthorShowContact ?? false)
|
||
? "checked"
|
||
: "" ?>>
|
||
Rendre le contact visible publiquement sur la fiche du TFE
|
||
</label>
|
||
<small>L'adresse est toujours conservée en interne comme contact de référence.</small>
|
||
</div>
|
||
</fieldset>
|
||
<?php endif; ?>
|
||
|
||
<!-- ═══════════════════ Langue(s) ═══════════════════ -->
|
||
<fieldset id="languages-fieldset">
|
||
<legend>Langue(s)</legend>
|
||
<?php
|
||
$name = "languages";
|
||
$label = "Langue(s) du TFE :";
|
||
$options = $languages;
|
||
$checked = $formData["languages"] ?? [];
|
||
$required = !$adminMode;
|
||
$hxPost = $mode === 'partage' ? "/partage/language-autre-fragment" : "/admin/language-autre-fragment.php";
|
||
$hxTarget = "#language-autre-row";
|
||
$hxSwap = "outerHTML";
|
||
include APP_ROOT . "/templates/partials/form/checkbox-list.php";
|
||
unset($hxSwap);
|
||
?>
|
||
<?php
|
||
$_langAutreRequired = empty($formData["languages"]);
|
||
$_langAutreValue = $oldFn("language_autre");
|
||
?>
|
||
<div id="language-autre-row">
|
||
<div>
|
||
<label for="language_autre">Autre(s) langue(s) :<?= $_langAutreRequired ? ' <span class="asterisk">*</span>' : '' ?></label>
|
||
<div>
|
||
<input type="text"
|
||
id="language_autre"
|
||
name="language_autre"
|
||
value="<?= $_langAutreValue ?>"
|
||
<?= (!$adminMode && $_langAutreRequired) ? 'required' : '' ?>>
|
||
<small>Si votre TFE contient une langue absente de la liste, précisez-la ici.</small>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<?php unset($_langAutreRequired, $_langAutreValue); ?>
|
||
</fieldset>
|
||
|
||
<!-- ═══════════════════ Mots-clés ═══════════════════ -->
|
||
<fieldset>
|
||
<legend>Mots-clés</legend>
|
||
<?php
|
||
$name = "tag";
|
||
$label = "Mots-clés (max 10) :";
|
||
$value = $oldFn("tag");
|
||
$placeholder = "sociologie, anthropologie, ...";
|
||
$hint = "Séparez par des virgules. Max 10 mots-clés.";
|
||
$attrs = $withAutofocusFn("tag");
|
||
include APP_ROOT . "/templates/partials/form/text-field.php";
|
||
?>
|
||
</fieldset>
|
||
|
||
<!-- ═══════════════════ Cadre académique ═══════════════════ -->
|
||
<?php include APP_ROOT .
|
||
"/templates/partials/form/fieldset-academic.php"; ?>
|
||
|
||
<!-- ═══════════════════ Composition du jury ═══════════════════ -->
|
||
<?php
|
||
if ($mode === "partage" && isset($helpFn)) {
|
||
$helpContent = $helpFn("fieldset_jury");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
}
|
||
require APP_ROOT . "/templates/partials/form/jury-fieldset.php";
|
||
?>
|
||
|
||
<!-- ═══════════════════ Format(s) + Fichiers ═══════════════════ -->
|
||
<?php if ($filesMode === 'add'): ?>
|
||
<?php
|
||
// Add / partage mode: Format + Fichiers rendered as one HTMX-swappable block.
|
||
// Synthesise POST-like data so fichiers-fragment.php can render the initial state.
|
||
if ($mode === "partage" && isset($helpFn)) {
|
||
$helpContent = $helpFn("fieldset_files");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
}
|
||
// Temporarily populate $_POST so the fragment can read formats/website values.
|
||
$_savedPost = $_POST;
|
||
$_POST['formats'] = $checkedFormatsForSiteWeb;
|
||
$_POST['website_url'] = $existingWebsiteUrl;
|
||
$_POST['website_label'] = $existingWebsiteLabel;
|
||
$_POST['admin_mode'] = $adminMode ? '1' : '0';
|
||
include APP_ROOT . '/public/partage/fichiers-fragment.php';
|
||
$_POST = $_savedPost;
|
||
unset($_savedPost);
|
||
?>
|
||
<?php else: ?>
|
||
<!-- Edit mode: Format checkboxes (old website fragment) + existing files management -->
|
||
<fieldset>
|
||
<legend>Format(s)</legend>
|
||
<?php
|
||
$name = "formats";
|
||
$label = "Format(s) du TFE :";
|
||
$options = $formatTypes;
|
||
$checked = $formData["formats"] ?? [];
|
||
$required = !$adminMode;
|
||
$hxPost = "/admin/format-website-fragment.php";
|
||
$hxTarget = "#edit-website-url-fieldset";
|
||
$hxSwap = "outerHTML";
|
||
$hxInclude = "this, #edit-website-url-fieldset";
|
||
include APP_ROOT . "/templates/partials/form/checkbox-list.php";
|
||
?>
|
||
</fieldset>
|
||
|
||
<!-- ═══════════════════ Fichiers (edit mode) ═══════════════════ -->
|
||
<fieldset>
|
||
<legend>Fichiers</legend>
|
||
|
||
<!-- Cover image -->
|
||
<div class="admin-form-group">
|
||
<label>Image de couverture :</label>
|
||
<div class="admin-file-input">
|
||
<?php if (!empty($currentCover)): ?>
|
||
<div class="admin-banner-preview">
|
||
<img src="/media?path=<?= urlencode(
|
||
$currentCover["file_path"],
|
||
) ?>"
|
||
alt="Couverture actuelle" style="max-height:180px;">
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="remove_cover" value="1"> Supprimer la couverture
|
||
</label>
|
||
</div>
|
||
<?php endif; ?>
|
||
<input type="file" id="couverture" name="couverture" accept="image/jpeg,image/png,image/webp" data-preview="fp-couverture">
|
||
<div id="fp-couverture" class="file-preview-list" aria-live="polite"></div>
|
||
<small><?= empty($currentCover)
|
||
? "JPG, PNG ou WEBP. Format 4:3 recommandé. Max 20 MB."
|
||
: "Laisser vide pour conserver la couverture actuelle. JPG, PNG ou WEBP. Max 20 MB." ?></small>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Existing thesis files — sortable, with labels -->
|
||
<?php $thesisFilesList = array_values(
|
||
array_filter(
|
||
$currentFiles,
|
||
fn($f) => $f["file_type"] !== "cover",
|
||
),
|
||
); ?>
|
||
<?php if (!empty($thesisFilesList)): ?>
|
||
<div class="admin-form-group">
|
||
<label>Fichiers du TFE existants :</label>
|
||
<small style="display:block;margin-bottom:var(--space-2xs);color:var(--text-tertiary)">
|
||
Glissez-déposez les lignes pour réordonner les fichiers sur la page publique.
|
||
</small>
|
||
<ul id="existing-files-sortable" class="admin-file-list sortable-list">
|
||
<?php foreach ($thesisFilesList as $f):
|
||
|
||
$fExt = strtolower(
|
||
pathinfo($f["file_path"] ?? "", PATHINFO_EXTENSION),
|
||
);
|
||
$fType = $f["file_type"] ?? "other";
|
||
$fIcon = match (true) {
|
||
$fType === "main" || $fExt === "pdf" => "📄",
|
||
in_array($fExt, [
|
||
"jpg",
|
||
"jpeg",
|
||
"png",
|
||
"gif",
|
||
"webp",
|
||
])
|
||
=> "🖼️",
|
||
$fType === "video" ||
|
||
in_array($fExt, ["mp4", "webm", "mov", "ogv"])
|
||
=> "🎬",
|
||
$fType === "audio" ||
|
||
in_array($fExt, [
|
||
"mp3",
|
||
"ogg",
|
||
"wav",
|
||
"flac",
|
||
"aac",
|
||
"m4a",
|
||
])
|
||
=> "🔊",
|
||
$fType === "caption" || $fExt === "vtt" => "💬",
|
||
$fType === "website" => "🌐",
|
||
default => "📎",
|
||
};
|
||
$isExternalUrl =
|
||
str_starts_with($f["file_path"] ?? "", "http://") ||
|
||
str_starts_with($f["file_path"] ?? "", "https://");
|
||
$fLinkHref = $isExternalUrl
|
||
? htmlspecialchars($f["file_path"])
|
||
: "/media?path=" . urlencode($f["file_path"]);
|
||
?>
|
||
<li class="admin-file-list-item" data-file-id="<?= (int) $f[
|
||
"id"
|
||
] ?>">
|
||
<input type="hidden" name="file_sort_order[]" value="<?= (int) $f[
|
||
"id"
|
||
] ?>">
|
||
<span class="admin-file-drag-handle" title="Réordonner">⠿</span>
|
||
<span class="admin-file-icon-col"><?= $fIcon ?></span>
|
||
<span class="admin-file-info">
|
||
<a href="<?= $fLinkHref ?>" target="_blank" rel="noopener" class="admin-file-name">
|
||
<?= htmlspecialchars(
|
||
$f["file_name"] ??
|
||
basename($f["file_path"]),
|
||
) ?>
|
||
</a>
|
||
<span class="admin-file-meta-row">
|
||
<span class="admin-file-type-badge"><?= htmlspecialchars(
|
||
$fType,
|
||
) ?></span>
|
||
<?php if (
|
||
!empty($f["file_size"]) &&
|
||
$f["file_size"] > 0
|
||
): ?>
|
||
<span class="admin-file-size"><?= number_format(
|
||
$f["file_size"] / 1024 / 1024,
|
||
2,
|
||
) ?> MB</span>
|
||
<?php endif; ?>
|
||
</span>
|
||
<input type="text" name="file_label[<?= (int) $f[
|
||
"id"
|
||
] ?>]"
|
||
value="<?= htmlspecialchars(
|
||
$f["display_label"] ?? "",
|
||
) ?>"
|
||
placeholder="Légende / description (optionnel)"
|
||
class="admin-file-label-input">
|
||
</span>
|
||
<label class="admin-checkbox-label admin-file-delete">
|
||
<input type="checkbox" name="delete_files[]" value="<?= (int) $f[
|
||
"id"
|
||
] ?>"> Supprimer
|
||
</label>
|
||
</li>
|
||
<?php
|
||
endforeach; ?>
|
||
</ul>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<!-- New thesis files -->
|
||
<div class="admin-form-group admin-files-fieldgroup">
|
||
<label>Ajouter des fichiers du TFE :</label>
|
||
<div class="admin-file-input">
|
||
<input type="file" id="tfe-files-input"
|
||
name="files[]" multiple
|
||
accept=".pdf,.jpg,.jpeg,.png,.gif,.webp,.mp4,.webm,.mov,.ogv,.mp3,.ogg,.oga,.wav,.flac,.aac,.m4a,.zip,.tar,.gz,.vtt"
|
||
class="tfe-file-picker">
|
||
<small class="admin-file-hint">
|
||
PDF (max 100 MB) · Images (JPG/PNG/GIF/WEBP) · ZIP/TAR (max 500 MB) · autres fichiers.
|
||
PDFs trop lourds ? <a href="https://www.bentopdf.com" target="_blank" rel="noopener">bentopdf.com</a>
|
||
</small>
|
||
<ul id="tfe-file-queue" class="tfe-file-queue sortable-list" aria-label="Nouveaux fichiers (réordonnable)"></ul>
|
||
<p id="tfe-file-queue-empty" class="tfe-queue-empty">Aucun nouveau fichier sélectionné.</p>
|
||
</div>
|
||
</div>
|
||
</fieldset>
|
||
|
||
<!-- Website URL fieldset for edit mode — shown/hidden via HTMX -->
|
||
<fieldset id="edit-website-url-fieldset" style="display:none">
|
||
<legend>Site web</legend>
|
||
<div class="admin-form-group">
|
||
<label for="website_url">URL du site :</label>
|
||
<div class="admin-file-input">
|
||
<input type="url" id="website_url" name="website_url"
|
||
value="<?= htmlspecialchars($existingWebsiteUrl) ?>"
|
||
placeholder="https://mon-tfe.erg.be">
|
||
<small>Si le TFE est un site web, entrez son URL ici. Il sera affiché comme un site embarqué sur la page du TFE.</small>
|
||
</div>
|
||
</div>
|
||
<div class="admin-form-group">
|
||
<label for="website_label">Légende :</label>
|
||
<input type="text" id="website_label" name="website_label"
|
||
value="<?= htmlspecialchars($existingWebsiteLabel) ?>"
|
||
placeholder="Description du site (optionnel)"
|
||
class="admin-file-label-input"
|
||
style="max-width:400px;">
|
||
</div>
|
||
</fieldset>
|
||
<?php
|
||
// Server-side: show website fieldset if Site web already checked
|
||
$_stmt = Database::getInstance()
|
||
->getConnection()
|
||
->prepare("SELECT id FROM format_types WHERE name = ? LIMIT 1");
|
||
$_stmt->execute(["Site web"]);
|
||
$_siteWebId = $_stmt->fetchColumn();
|
||
if (
|
||
$_siteWebId &&
|
||
in_array(
|
||
(string) $_siteWebId,
|
||
array_map("strval", $checkedFormatsForSiteWeb),
|
||
true,
|
||
)
|
||
) {
|
||
echo '<script>document.getElementById("edit-website-url-fieldset").style.display=""</script>';
|
||
}
|
||
?>
|
||
<?php endif; ?>
|
||
|
||
<!-- ═══════════════════ Métadonnées complémentaires ═══════════════════ -->
|
||
<?php include APP_ROOT .
|
||
"/templates/partials/form/fieldset-metadata.php"; ?>
|
||
|
||
<!-- ═══════════════════ Degrés d'ouverture et licences ═══════════════════ -->
|
||
<?php
|
||
if ($mode === "partage" && isset($helpFn)) {
|
||
$helpContent = $helpFn("fieldset_access");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
}
|
||
include APP_ROOT .
|
||
"/templates/partials/form/fieldset-licence-explanation.php";
|
||
?>
|
||
|
||
<?php if ($showContextNote): ?>
|
||
<!-- ═══════════════════ Note contextuelle ═══════════════════ -->
|
||
<fieldset>
|
||
<legend>Note contextuelle</legend>
|
||
<div>
|
||
<label for="context_note">Note contextuelle :</label>
|
||
<div>
|
||
<textarea id="context_note" name="context_note"
|
||
rows="4" maxlength="1500"><?= htmlspecialchars(
|
||
$currentContextNote ??
|
||
($formData["context_note"] ?? ""),
|
||
) ?></textarea>
|
||
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
|
||
</div>
|
||
</div>
|
||
</fieldset>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($showBackoffice): ?>
|
||
<!-- ═══════════════════ Backoffice ═══════════════════ -->
|
||
<fieldset>
|
||
<legend>Backoffice</legend>
|
||
|
||
<div class="admin-form-group">
|
||
<label for="jury_points">Points :</label>
|
||
<input type="number" id="jury_points" name="jury_points"
|
||
value="<?= htmlspecialchars(
|
||
$currentRaw["jury_points"] ??
|
||
($formData["jury_points"] ?? ""),
|
||
) ?>"
|
||
step="0.01" min="0" max="20" placeholder="sur 20">
|
||
<small>Note du jury (interne, non visible publiquement).</small>
|
||
</div>
|
||
|
||
<div class="admin-form-group">
|
||
<label for="remarks">Remarques :</label>
|
||
<textarea id="remarks" name="remarks" rows="4"><?= htmlspecialchars(
|
||
$currentRaw["remarks"] ?? ($formData["remarks"] ?? ""),
|
||
) ?></textarea>
|
||
<small>Notes internes (non visibles publiquement).</small>
|
||
</div>
|
||
|
||
<div class="admin-form-group">
|
||
<label for="contact_interne">Contact interne :</label>
|
||
<input type="email" id="contact_interne" name="contact_interne"
|
||
value="<?= htmlspecialchars(
|
||
$currentRaw["contact_interne"] ??
|
||
($formData["contact_interne"] ??
|
||
($currentAuthorEmail ?? "")),
|
||
) ?>"
|
||
placeholder="ton.email@exemple.be">
|
||
<small>Adresse de contact interne (non visible publiquement).</small>
|
||
</div>
|
||
|
||
<div class="admin-form-group">
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="exemplaire_baiu" value="1"
|
||
<?= !empty(
|
||
$currentRaw["exemplaire_baiu"] ??
|
||
($formData["exemplaire_baiu"] ?? false)
|
||
)
|
||
? "checked"
|
||
: "" ?>>
|
||
Exemplaire physique BAIU
|
||
</label>
|
||
<small>Case logistique : cocher si un exemplaire physique est disponible à la BAIU.</small>
|
||
</div>
|
||
|
||
<div class="admin-form-group">
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="exemplaire_erg" value="1"
|
||
<?= !empty(
|
||
$currentRaw["exemplaire_erg"] ??
|
||
($formData["exemplaire_erg"] ?? false)
|
||
)
|
||
? "checked"
|
||
: "" ?>>
|
||
Exemplaire physique ERG
|
||
</label>
|
||
<small>Case logistique : cocher si un exemplaire physique est disponible à l'ERG.</small>
|
||
</div>
|
||
</fieldset>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($showEmailConfirmation): ?>
|
||
<!-- ═══════════════════ E-mail de confirmation ═══════════ -->
|
||
<fieldset>
|
||
<legend>E-mail de confirmation</legend>
|
||
<?php if ($mode === "partage" && isset($helpFn)): ?>
|
||
<?php
|
||
$helpContent = $helpFn("fieldset_email");
|
||
include APP_ROOT . "/templates/partials/form/form-help-block.php";
|
||
?>
|
||
<?php endif; ?>
|
||
<?php
|
||
$name = "confirmation_email";
|
||
$label = "Adresse e-mail :";
|
||
$value = $oldFn("confirmation_email");
|
||
$type = "email";
|
||
$required = !$adminMode;
|
||
$placeholder = "ton.email@exemple.be";
|
||
$hint =
|
||
"Nécessaire pour recevoir le récapitulatif de ta soumission.";
|
||
include APP_ROOT . "/templates/partials/form/text-field.php";
|
||
?>
|
||
</fieldset>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($showPublish): ?>
|
||
<!-- ═══════════════════ Publication ════════════════════════ -->
|
||
<fieldset>
|
||
<legend>Publication</legend>
|
||
<div>
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="is_published" value="1"
|
||
<?= !empty($currentRaw["is_published"] ?? false)
|
||
? "checked"
|
||
: "" ?>>
|
||
Publier ce TFE sur le site public
|
||
</label>
|
||
</div>
|
||
</fieldset>
|
||
<?php endif; ?>
|
||
|
||
<div class="form-footer admin-form-footer">
|
||
<button type="submit" name="go" class="btn btn--primary"><?= $mode === 'edit' ? 'Enregistrer' : 'Soumettre' ?></button>
|
||
<?php if ($mode === 'add' || $mode === 'edit'): ?>
|
||
<a href="/admin/" class="btn btn--secondary">Annuler</a>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
</form>
|