mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Extract FormBootstrap helper to eliminate bootstrap duplication across add/edit form pages
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../../bootstrap.php";
|
require_once __DIR__ . '/../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../src/AdminAuth.php';
|
||||||
|
require_once __DIR__ . '/../../src/Form/FormBootstrap.php';
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (empty($_SESSION["csrf_token"])) {
|
if (empty($_SESSION['csrf_token'])) {
|
||||||
$_SESSION["csrf_token"] = bin2hex(random_bytes(32));
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
$pageTitle = "Ajouter un TFE";
|
$pageTitle = 'Ajouter un TFE';
|
||||||
|
|
||||||
require_once __DIR__ . '/../../src/Controllers/ThesisCreateController.php';
|
require_once __DIR__ . '/../../src/Controllers/ThesisCreateController.php';
|
||||||
|
|
||||||
@@ -19,44 +20,32 @@ try {
|
|||||||
die('Erreur lors du chargement du formulaire.');
|
die('Erreur lors du chargement du formulaire.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Form data (flash repopulation)
|
||||||
$formData = $_SESSION['form_data'] ?? [];
|
$formData = $_SESSION['form_data'] ?? [];
|
||||||
unset($_SESSION['form_data']);
|
unset($_SESSION['form_data']);
|
||||||
$autofocusField = App::consumeAutofocus();
|
|
||||||
|
|
||||||
// Site settings for licence / access type toggles
|
|
||||||
$siteSettings = Database::getInstance()->getAllSettings();
|
$siteSettings = Database::getInstance()->getAllSettings();
|
||||||
// Form help blocks
|
|
||||||
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
|
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
|
||||||
$helpFn = fn(string $key) => empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
|
|
||||||
|
|
||||||
function withAutofocus(string $fieldName, array $attrs = []): array {
|
// Shared form variables from the bootstrap helper
|
||||||
global $autofocusField;
|
extract(FormBootstrap::adminFormVariables(
|
||||||
if ($autofocusField === $fieldName) {
|
mode: 'add',
|
||||||
$attrs['autofocus'] = true;
|
formAction: 'actions/formulaire.php',
|
||||||
}
|
hiddenFields: '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($_SESSION['csrf_token']) . '">',
|
||||||
return $attrs;
|
formData: $formData,
|
||||||
}
|
siteSettings: $siteSettings,
|
||||||
|
helpBlocks: $helpBlocks,
|
||||||
function old($key, $default = "") {
|
options: [
|
||||||
global $formData;
|
'existingWebsiteUrl' => $formData['website_url'] ?? '',
|
||||||
if (!isset($formData[$key])) return $default;
|
'existingWebsiteLabel' => $formData['website_label'] ?? '',
|
||||||
if (is_array($formData[$key])) return $formData[$key]; // Return raw array for callers that handle it
|
'checkedFormats' => $formData['formats'] ?? [],
|
||||||
if ($formData[$key] === null) return $default;
|
],
|
||||||
return htmlspecialchars((string)$formData[$key]);
|
));
|
||||||
}
|
|
||||||
|
|
||||||
function wasSelected($key, $value) {
|
|
||||||
global $formData;
|
|
||||||
if (!isset($formData[$key])) return false;
|
|
||||||
if (is_array($formData[$key])) return in_array($value, $formData[$key]);
|
|
||||||
return $formData[$key] == $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Asset arrays and page chrome
|
||||||
$isAdmin = true;
|
$isAdmin = true;
|
||||||
$bodyClass = 'admin-body';
|
$bodyClass = 'admin-body';
|
||||||
$extraCss = ['/assets/css/form-base.css'];
|
extract(FormBootstrap::adminAssetArrays());
|
||||||
$extraCssAdmin = ['/assets/css/form-admin.css', '/assets/css/filepond.min.css', '/assets/css/filepond-plugin-image-preview.min.css'];
|
|
||||||
$extraJs = ['/assets/js/vendor/filepond.min.js', '/assets/js/vendor/filepond-plugin-file-validate-type.min.js', '/assets/js/vendor/filepond-plugin-file-validate-size.min.js', '/assets/js/vendor/filepond-plugin-image-preview.min.js', '/assets/js/vendor/filepond-plugin-image-exif-orientation.min.js', '/assets/js/app/file-upload-filepond.js', '/assets/js/app/beforeunload-guard.js', '/assets/js/app/pill-search.js', '/assets/js/app/jury-autocomplete.js'];
|
|
||||||
require_once APP_ROOT . '/templates/head.php';
|
require_once APP_ROOT . '/templates/head.php';
|
||||||
include APP_ROOT . '/templates/header.php';
|
include APP_ROOT . '/templates/header.php';
|
||||||
include APP_ROOT . '/templates/admin/add.php';
|
include APP_ROOT . '/templates/admin/add.php';
|
||||||
|
|||||||
@@ -1,47 +1,167 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../../bootstrap.php";
|
require_once __DIR__ . '/../../bootstrap.php';
|
||||||
require_once __DIR__ . '/../../src/AdminAuth.php';
|
require_once __DIR__ . '/../../src/AdminAuth.php';
|
||||||
|
require_once __DIR__ . '/../../src/Form/FormBootstrap.php';
|
||||||
AdminAuth::requireLogin();
|
AdminAuth::requireLogin();
|
||||||
|
|
||||||
if (empty($_SESSION['csrf_token'])) {
|
if (empty($_SESSION['csrf_token'])) {
|
||||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once APP_ROOT . '/src/Controllers/ThesisEditController.php';
|
|
||||||
|
|
||||||
$thesisId = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
$thesisId = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||||||
|
|
||||||
if ($thesisId <= 0) {
|
if ($thesisId <= 0) {
|
||||||
die("ID invalide");
|
die('ID invalide');
|
||||||
}
|
}
|
||||||
|
|
||||||
$autofocusField = App::consumeAutofocus();
|
require_once __DIR__ . '/../../src/Controllers/ThesisEditController.php';
|
||||||
|
|
||||||
// Form help blocks for editable généralités
|
$formData = [];
|
||||||
|
$siteSettings = Database::getInstance()->getAllSettings();
|
||||||
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
|
$helpBlocks = Database::getInstance()->getAllFormHelpBlocks();
|
||||||
$helpFn = fn(string $key) => empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
|
|
||||||
|
|
||||||
function old($key, $default = "") {
|
|
||||||
global $formData;
|
|
||||||
if (!isset($formData[$key])) return $default;
|
|
||||||
if (is_array($formData[$key])) return $formData[$key]; // Return raw array for callers that handle it
|
|
||||||
if ($formData[$key] === null) return $default;
|
|
||||||
return htmlspecialchars((string)$formData[$key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$ctrl = ThesisEditController::create();
|
$ctrl = ThesisEditController::create();
|
||||||
$view = $ctrl->load($thesisId);
|
$view = $ctrl->load($thesisId);
|
||||||
extract($view);
|
extract($view);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
error_log("Error loading edit page: " . $e->getMessage());
|
error_log('Error loading edit page: ' . $e->getMessage());
|
||||||
die("Erreur lors du chargement: " . $e->getMessage());
|
die('Erreur lors du chargement: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
$isAdmin = true; $bodyClass = 'admin-body';
|
// Merge flash repopulation data (from redirects after validation errors)
|
||||||
$extraCss = ['/assets/css/form-base.css'];
|
// with current thesis data so old() can fall back to DB values.
|
||||||
$extraCssAdmin = ['/assets/css/form-admin.css', '/assets/css/filepond.min.css', '/assets/css/filepond-plugin-image-preview.min.css'];
|
$formData = array_merge($formData, [
|
||||||
$extraJs = ['/assets/js/vendor/filepond.min.js', '/assets/js/vendor/filepond-plugin-file-validate-type.min.js', '/assets/js/vendor/filepond-plugin-file-validate-size.min.js', '/assets/js/vendor/filepond-plugin-image-preview.min.js', '/assets/js/vendor/filepond-plugin-image-exif-orientation.min.js', '/assets/js/app/file-upload-filepond.js', '/assets/js/app/beforeunload-guard.js', '/assets/js/app/pill-search.js', '/assets/js/app/jury-autocomplete.js'];
|
'titre' => $thesis['title'],
|
||||||
|
'subtitle' => $thesis['subtitle'] ?? '',
|
||||||
|
'auteurice' => $thesis['authors'] ?? '',
|
||||||
|
'mail' => $contactInterne ?? '',
|
||||||
|
'contact_visible' => $currentContactVisible ?? '',
|
||||||
|
'synopsis' => $thesis['synopsis'] ?? '',
|
||||||
|
'tag' => $thesis['keywords'] ?? '',
|
||||||
|
'année' => $thesis['year'],
|
||||||
|
'orientation' => $thesis['orientation'],
|
||||||
|
'ap' => $thesis['ap_program'],
|
||||||
|
'finality' => $thesis['finality_type'],
|
||||||
|
'lien' => $thesis['baiu_link'] ?? '',
|
||||||
|
'contact_public' => $contactPublic ?? false,
|
||||||
|
'contact_interne' => $contactInterne ?? '',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Build jury arrays
|
||||||
|
$juryPromoteurs = [];
|
||||||
|
$juryPromoteursUlb = [];
|
||||||
|
$lecteursInternes = [];
|
||||||
|
$lecteursExternes = [];
|
||||||
|
$juryPromoteur = null;
|
||||||
|
$juryPromoteurUlb = null;
|
||||||
|
|
||||||
|
foreach ($jury as $jm) {
|
||||||
|
if ($jm['role'] === 'president') continue;
|
||||||
|
if ($jm['role'] === 'promoteur') {
|
||||||
|
if (($jm['is_ulb'] ?? 0) == 1) {
|
||||||
|
$juryPromoteursUlb[] = $jm;
|
||||||
|
} else {
|
||||||
|
$juryPromoteurs[] = $jm;
|
||||||
|
}
|
||||||
|
} elseif ($jm['role'] === 'lecteur') {
|
||||||
|
if (($jm['is_external'] ?? 0) == 1) {
|
||||||
|
$lecteursExternes[] = $jm;
|
||||||
|
} else {
|
||||||
|
$lecteursInternes[] = $jm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($juryPromoteurs) && $juryPromoteur === null) $juryPromoteur = $juryPromoteurs[0]['name'];
|
||||||
|
if (!empty($juryPromoteursUlb) && $juryPromoteurUlb === null) $juryPromoteurUlb = $juryPromoteursUlb[0]['name'];
|
||||||
|
|
||||||
|
// Build existing website URL / label from current files
|
||||||
|
$existingWebsiteUrl = '';
|
||||||
|
$existingWebsiteLabel = '';
|
||||||
|
foreach ($currentFiles as $f) {
|
||||||
|
if ($f['file_type'] === 'website') {
|
||||||
|
$existingWebsiteUrl = $f['file_path'] ?? '';
|
||||||
|
$existingWebsiteLabel = $f['display_label'] ?? '';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Languages — either from flash repopulation or current thesis data
|
||||||
|
$formData['languages'] = $formData['languages'] ?? $currentLanguages ?? [];
|
||||||
|
|
||||||
|
// Compute "other" languages (not in the predefined checkbox list)
|
||||||
|
$predefinedLangIds = array_column($languages, 'id');
|
||||||
|
$otherLangIds = array_diff($currentLanguages ?? [], $predefinedLangIds);
|
||||||
|
$selectedOtherLanguages = [];
|
||||||
|
if (!empty($otherLangIds)) {
|
||||||
|
$allLangs = Database::getInstance()->getAllLanguages();
|
||||||
|
$allLangMap = [];
|
||||||
|
foreach ($allLangs as $al) {
|
||||||
|
$allLangMap[(int)$al['id']] = $al['name'];
|
||||||
|
}
|
||||||
|
foreach ($otherLangIds as $lid) {
|
||||||
|
$lid = (int)$lid;
|
||||||
|
if (isset($allLangMap[$lid])) {
|
||||||
|
$selectedOtherLanguages[] = $allLangMap[$lid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort($selectedOtherLanguages, SORT_NATURAL | SORT_FLAG_CASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tags — either from flash repopulation or current thesis data
|
||||||
|
$keywordsStr = $thesis['keywords'] ?? '';
|
||||||
|
$currentTags = $keywordsStr !== '' ? array_map('trim', explode(',', $keywordsStr)) : [];
|
||||||
|
if (!empty($formData['tag']) && is_array($formData['tag'])) {
|
||||||
|
$currentTags = $formData['tag'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats — either from flash repopulation or current thesis data
|
||||||
|
$checkedFormats = $formData['formats'] ?? $currentFormats ?? [];
|
||||||
|
$formData['formats'] = $checkedFormats;
|
||||||
|
|
||||||
|
// Shared form variables from the bootstrap helper
|
||||||
|
extract(FormBootstrap::adminFormVariables(
|
||||||
|
mode: 'edit',
|
||||||
|
formAction: '/admin/actions/edit.php',
|
||||||
|
hiddenFields:
|
||||||
|
'<input type="hidden" name="csrf_token" value="' . htmlspecialchars($_SESSION['csrf_token']) . '">'
|
||||||
|
. '<input type="hidden" name="thesis_id" value="' . $thesisId . '">',
|
||||||
|
formData: $formData,
|
||||||
|
siteSettings: $siteSettings,
|
||||||
|
helpBlocks: $helpBlocks,
|
||||||
|
options: [
|
||||||
|
'filesMode' => 'edit',
|
||||||
|
'existingWebsiteUrl' => $existingWebsiteUrl,
|
||||||
|
'existingWebsiteLabel' => $existingWebsiteLabel,
|
||||||
|
'checkedFormats' => $checkedFormats,
|
||||||
|
'juryPromoteurs' => $juryPromoteurs,
|
||||||
|
'juryPromoteursUlb' => $juryPromoteursUlb,
|
||||||
|
'lecteursInternes' => $lecteursInternes,
|
||||||
|
'lecteursExternes' => $lecteursExternes,
|
||||||
|
'juryPromoteur' => $juryPromoteur,
|
||||||
|
'juryPromoteurUlb' => $juryPromoteurUlb,
|
||||||
|
'currentRaw' => $currentRaw ?? [],
|
||||||
|
'currentCover' => $currentCover ?? null,
|
||||||
|
'currentFiles' => $currentFiles ?? [],
|
||||||
|
'currentContextNote' => $currentContextNote ?? null,
|
||||||
|
'currentContactVisible' => $currentContactVisible ?? null,
|
||||||
|
'contactInterne' => $contactInterne ?? null,
|
||||||
|
'contactPublic' => $contactPublic ?? false,
|
||||||
|
'showCoverPreview' => true,
|
||||||
|
'showExistingFiles' => true,
|
||||||
|
'defaultAccessTypeId' => $currentAccessTypeId ?? 2,
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
|
// Inject thesis-derived values into formData for the template
|
||||||
|
$formData['access_type_id'] = $currentAccessTypeId;
|
||||||
|
$formData['license_id'] = $currentLicenseId;
|
||||||
|
$formData['license_custom'] = $currentRaw['license_custom'] ?? '';
|
||||||
|
$formData['cc2r'] = $currentRaw['cc2r'] ?? false;
|
||||||
|
|
||||||
|
// Asset arrays and page chrome
|
||||||
|
$isAdmin = true;
|
||||||
|
$bodyClass = 'admin-body';
|
||||||
|
extract(FormBootstrap::adminAssetArrays());
|
||||||
require_once APP_ROOT . '/templates/head.php';
|
require_once APP_ROOT . '/templates/head.php';
|
||||||
include APP_ROOT . '/templates/header.php';
|
include APP_ROOT . '/templates/header.php';
|
||||||
include APP_ROOT . '/templates/admin/edit.php';
|
include APP_ROOT . '/templates/admin/edit.php';
|
||||||
|
|||||||
183
app/src/Form/FormBootstrap.php
Normal file
183
app/src/Form/FormBootstrap.php
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FormBootstrap — shared bootstrap logic for TFE form pages.
|
||||||
|
*
|
||||||
|
* Provides factory methods and helper closures used by add, edit, and partage
|
||||||
|
* form scripts, eliminating copy-pasted preamble across the three entry points.
|
||||||
|
*
|
||||||
|
* Each public static method returns an associative array of variables to be
|
||||||
|
* extracted in the caller's scope.
|
||||||
|
*/
|
||||||
|
class FormBootstrap
|
||||||
|
{
|
||||||
|
// ── Asset arrays (identical for all admin form pages) ────────────────────
|
||||||
|
|
||||||
|
public static function adminAssetArrays(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'extraCss' => ['/assets/css/form-base.css'],
|
||||||
|
'extraCssAdmin' => [
|
||||||
|
'/assets/css/form-admin.css',
|
||||||
|
'/assets/css/filepond.min.css',
|
||||||
|
'/assets/css/filepond-plugin-image-preview.min.css',
|
||||||
|
],
|
||||||
|
'extraJs' => [
|
||||||
|
'/assets/js/vendor/filepond.min.js',
|
||||||
|
'/assets/js/vendor/filepond-plugin-file-validate-type.min.js',
|
||||||
|
'/assets/js/vendor/filepond-plugin-file-validate-size.min.js',
|
||||||
|
'/assets/js/vendor/filepond-plugin-image-preview.min.js',
|
||||||
|
'/assets/js/vendor/filepond-plugin-image-exif-orientation.min.js',
|
||||||
|
'/assets/js/app/file-upload-filepond.js',
|
||||||
|
'/assets/js/app/beforeunload-guard.js',
|
||||||
|
'/assets/js/app/pill-search.js',
|
||||||
|
'/assets/js/app/jury-autocomplete.js',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Helpers ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an `old()` callable for admin forms (add/edit).
|
||||||
|
*
|
||||||
|
* Returns `htmlspecialchars`-escaped string values, or the raw array for
|
||||||
|
* array-typed keys. Uses the $formData array from the caller's scope
|
||||||
|
* (which may be $_SESSION['form_data'] with an edit-data overlay).
|
||||||
|
*/
|
||||||
|
public static function adminOld(array &$formData): callable
|
||||||
|
{
|
||||||
|
return function (string $key, string $default = '') use (&$formData): string {
|
||||||
|
if (!isset($formData[$key])) return $default;
|
||||||
|
if (is_array($formData[$key])) return $formData[$key];
|
||||||
|
if ($formData[$key] === null) return $default;
|
||||||
|
return htmlspecialchars((string)$formData[$key]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an `old()` callable for share/partage forms.
|
||||||
|
*
|
||||||
|
* Returns raw values (no escaping) — callers must apply htmlspecialchars()
|
||||||
|
* when rendering. Supports colon-delimited keys (e.g. "key:0").
|
||||||
|
*/
|
||||||
|
public static function shareOld(array &$formData): callable
|
||||||
|
{
|
||||||
|
return function (string $key, string $default = '') use (&$formData) {
|
||||||
|
$parts = explode(':', $key);
|
||||||
|
$value = $formData;
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if (is_array($value) && array_key_exists($part, $value)) {
|
||||||
|
$value = $value[$part];
|
||||||
|
} else {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Common form variables ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the standard variable set needed by form partials for an admin
|
||||||
|
* add/edit page. Returns an array suitable for extract().
|
||||||
|
*
|
||||||
|
* @param string $mode 'add' | 'edit'
|
||||||
|
* @param string $formAction URL string
|
||||||
|
* @param string $hiddenFields Raw HTML for hidden inputs
|
||||||
|
* @param array $formData Merged form data for repopulation
|
||||||
|
* @param array $siteSettings from getAllSettings()
|
||||||
|
* @param array $helpBlocks from getAllFormHelpBlocks()
|
||||||
|
* @param array $options Overrides for individual keys (juryPromoteur, etc.)
|
||||||
|
*/
|
||||||
|
public static function adminFormVariables(
|
||||||
|
string $mode,
|
||||||
|
string $formAction,
|
||||||
|
string $hiddenFields,
|
||||||
|
array &$formData,
|
||||||
|
array $siteSettings,
|
||||||
|
array $helpBlocks,
|
||||||
|
array $options = []
|
||||||
|
): array {
|
||||||
|
$helpFn = function (string $key) use ($helpBlocks): string {
|
||||||
|
return empty($helpBlocks[$key]['enabled']) ? '' : ($helpBlocks[$key]['content'] ?? '');
|
||||||
|
};
|
||||||
|
|
||||||
|
$autofocusField = App::consumeAutofocus();
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
$showContact = false;
|
||||||
|
$showBackoffice = ($mode === 'add' || $mode === 'edit');
|
||||||
|
|
||||||
|
// Licence / access toggles: admin always enables all three
|
||||||
|
$libreEnabled = true;
|
||||||
|
$interneEnabled = true;
|
||||||
|
$interditEnabled = true;
|
||||||
|
$generalitiesHtml = $helpFn('fieldset_generalites');
|
||||||
|
$defaultAccessTypeId = $options['defaultAccessTypeId'] ?? 2;
|
||||||
|
|
||||||
|
return array_merge([
|
||||||
|
// Base
|
||||||
|
'mode' => $mode,
|
||||||
|
'formAction' => $formAction,
|
||||||
|
'hiddenFields' => $hiddenFields,
|
||||||
|
'errorFieldName' => $autofocusField,
|
||||||
|
'synopsisExtra' => $options['synopsisExtra'] ?? '',
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
'helpFn' => $helpFn,
|
||||||
|
'helpBlocks' => $helpBlocks,
|
||||||
|
'oldFn' => self::adminOld($formData),
|
||||||
|
'withAutofocusFn' => function (string $field, array $attrs = []) use ($autofocusField): array {
|
||||||
|
if ($autofocusField === $field) $attrs['autofocus'] = true;
|
||||||
|
return $attrs;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Jury
|
||||||
|
'juryPromoteur' => null,
|
||||||
|
'juryPromoteurs' => [],
|
||||||
|
'juryPromoteurUlb' => null,
|
||||||
|
'juryPromoteursUlb' => [],
|
||||||
|
'lecteursInternes' => [],
|
||||||
|
'lecteursExternes' => [],
|
||||||
|
'showPromoteurUlb' => true,
|
||||||
|
'promoteurUlbConditional' => false,
|
||||||
|
|
||||||
|
// Licence / access
|
||||||
|
'libreEnabled' => $libreEnabled,
|
||||||
|
'interneEnabled' => $interneEnabled,
|
||||||
|
'interditEnabled' => $interditEnabled,
|
||||||
|
'generalitiesHtml' => $generalitiesHtml,
|
||||||
|
'defaultAccessTypeId' => $defaultAccessTypeId,
|
||||||
|
|
||||||
|
// Optional sections
|
||||||
|
'showContact' => $showContact,
|
||||||
|
'showBackoffice' => $showBackoffice,
|
||||||
|
'showCoverPreview' => false,
|
||||||
|
'showExistingFiles' => false,
|
||||||
|
'showEmailConfirmation' => false,
|
||||||
|
'showFlash' => false,
|
||||||
|
'showIntroHelp' => false,
|
||||||
|
|
||||||
|
// Files
|
||||||
|
'filesMode' => $options['filesMode'] ?? 'add',
|
||||||
|
|
||||||
|
// Website
|
||||||
|
'existingWebsiteUrl' => $options['existingWebsiteUrl'] ?? '',
|
||||||
|
'existingWebsiteLabel' => $options['existingWebsiteLabel'] ?? '',
|
||||||
|
'checkedFormatsForSiteWeb' => $options['checkedFormats'] ?? [],
|
||||||
|
|
||||||
|
// Backoffice (empty for add, populated for edit by caller)
|
||||||
|
'currentRaw' => [],
|
||||||
|
'contactInterne' => null,
|
||||||
|
'contactPublic' => false,
|
||||||
|
'currentContextNote' => null,
|
||||||
|
'currentContactVisible' => null,
|
||||||
|
|
||||||
|
// Files (edit mode)
|
||||||
|
'currentCover' => null,
|
||||||
|
'currentFiles' => [],
|
||||||
|
], $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,53 +2,7 @@
|
|||||||
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H107.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L107.31,120H168A8,8,0,0,1,176,128Z"></path></svg></a> Ajouter un TFE</h1>
|
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H107.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L107.31,120H168A8,8,0,0,1,176,128Z"></path></svg></a> Ajouter un TFE</h1>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// ── Variables for the shared form partial ─────────────────────────────────
|
// All form variables are already in scope from FormBootstrap::adminFormVariables().
|
||||||
$mode = 'add';
|
|
||||||
$formAction = 'actions/formulaire.php';
|
|
||||||
$hiddenFields = '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($_SESSION["csrf_token"]) . '">';
|
|
||||||
$errorFieldName = $autofocusField ?? null;
|
|
||||||
$withAutofocusFn = function (string $field, array $attrs = []) use ($autofocusField) {
|
|
||||||
if ($autofocusField === $field) $attrs['autofocus'] = true;
|
|
||||||
return $attrs;
|
|
||||||
};
|
|
||||||
|
|
||||||
$synopsisExtra = '';
|
|
||||||
|
|
||||||
// Jury: fresh add (all empty)
|
|
||||||
$juryPromoteur = null;
|
|
||||||
$juryPromoteurs = [];
|
|
||||||
$juryPromoteurUlb = null;
|
|
||||||
$juryPromoteursUlb = [];
|
|
||||||
$lecteursInternes = [];
|
|
||||||
$lecteursExternes = [];
|
|
||||||
$showPromoteurUlb = true;
|
|
||||||
$promoteurUlbConditional = false;
|
|
||||||
|
|
||||||
// Licence / access
|
|
||||||
$libreEnabled = ($siteSettings['access_type_libre_enabled'] ?? '0') === '1';
|
|
||||||
$interneEnabled = ($siteSettings['access_type_interne_enabled'] ?? '1') === '1';
|
|
||||||
$interditEnabled = ($siteSettings['access_type_interdit_enabled'] ?? '1') === '1';
|
|
||||||
$generalitiesHtml = $helpFn('fieldset_generalites');
|
|
||||||
$defaultAccessTypeId = 2;
|
|
||||||
|
|
||||||
// Optional sections
|
|
||||||
$showContact = false; // Admin: contact visibility controlled by filling 'mail' field in fieldset-tfe-info
|
|
||||||
$showBackoffice = true;
|
|
||||||
|
|
||||||
// Files: add mode
|
|
||||||
$filesMode = 'add';
|
|
||||||
|
|
||||||
// Website URL (repopulation)
|
|
||||||
$existingWebsiteUrl = $formData['website_url'] ?? '';
|
|
||||||
$existingWebsiteLabel = $formData['website_label'] ?? '';
|
|
||||||
|
|
||||||
// Backoffice (add mode: null → falls back to formData)
|
|
||||||
$currentRaw = [];
|
|
||||||
$contactInterne = null;
|
|
||||||
$contactPublic = false;
|
|
||||||
$currentContextNote = null;
|
|
||||||
$currentContactVisible = null;
|
|
||||||
|
|
||||||
include APP_ROOT . '/templates/partials/form/form.php';
|
include APP_ROOT . '/templates/partials/form/form.php';
|
||||||
?>
|
?>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -2,146 +2,7 @@
|
|||||||
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H107.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L107.31,120H168A8,8,0,0,1,176,128Z"></path></svg></a> Modifier un TFE</h1>
|
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H107.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L107.31,120H168A8,8,0,0,1,176,128Z"></path></svg></a> Modifier un TFE</h1>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// ── Build a unified old() callable for the entire edit form ────────────────
|
// All form variables are already in scope from FormBootstrap::adminFormVariables().
|
||||||
$editFormData = array_merge($formData ?? [], [
|
|
||||||
'titre' => $thesis['title'],
|
|
||||||
'subtitle' => $thesis['subtitle'] ?? '',
|
|
||||||
'auteurice' => $thesis['authors'] ?? '',
|
|
||||||
'mail' => $contactInterne ?? '',
|
|
||||||
'contact_visible' => $currentContactVisible ?? '',
|
|
||||||
'synopsis' => $thesis['synopsis'] ?? '',
|
|
||||||
'tag' => $thesis['keywords'] ?? '',
|
|
||||||
'année' => $thesis['year'],
|
|
||||||
'orientation' => $thesis['orientation'],
|
|
||||||
'ap' => $thesis['ap_program'],
|
|
||||||
'finality' => $thesis['finality_type'],
|
|
||||||
'lien' => $thesis['baiu_link'] ?? '',
|
|
||||||
'contact_public' => $contactPublic ?? false,
|
|
||||||
'contact_interne' => $contactInterne ?? '',
|
|
||||||
]);
|
|
||||||
$oldFn = fn(string $key, string $default = '') =>
|
|
||||||
isset($editFormData[$key]) && !is_array($editFormData[$key])
|
|
||||||
? htmlspecialchars((string)$editFormData[$key]) : $default;
|
|
||||||
|
|
||||||
$withAutofocusFn = function (string $field, array $attrs = []) use ($autofocusField) {
|
|
||||||
if ($autofocusField === $field) $attrs['autofocus'] = true;
|
|
||||||
return $attrs;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ── Shared form variables ──────────────────────────────────────────────────
|
|
||||||
$mode = 'edit';
|
|
||||||
$formAction = '/admin/actions/edit.php';
|
|
||||||
$hiddenFields = '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($_SESSION['csrf_token']) . '">'
|
|
||||||
. '<input type="hidden" name="thesis_id" value="' . $thesisId . '">';
|
|
||||||
$errorFieldName = $autofocusField ?? null;
|
|
||||||
|
|
||||||
$synopsisExtra = '';
|
|
||||||
$formData = $editFormData;
|
|
||||||
|
|
||||||
// Jury data
|
|
||||||
$juryPromoteur = null;
|
|
||||||
$juryPromoteurs = [];
|
|
||||||
$juryPromoteurUlb = null;
|
|
||||||
$juryPromoteursUlb = [];
|
|
||||||
$lecteursInternes = [];
|
|
||||||
$lecteursExternes = [];
|
|
||||||
foreach ($jury as $jm) {
|
|
||||||
if ($jm['role'] === 'president') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($jm['role'] === 'promoteur') {
|
|
||||||
if (($jm['is_ulb'] ?? 0) == 1) {
|
|
||||||
$juryPromoteursUlb[] = $jm;
|
|
||||||
} else {
|
|
||||||
$juryPromoteurs[] = $jm;
|
|
||||||
}
|
|
||||||
} elseif ($jm['role'] === 'lecteur') {
|
|
||||||
if (($jm['is_external'] ?? 0) == 1) {
|
|
||||||
$lecteursExternes[] = $jm;
|
|
||||||
} else {
|
|
||||||
$lecteursInternes[] = $jm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Backwards compat: if only one, also set the scalar for simple templates
|
|
||||||
if (!empty($juryPromoteurs) && $juryPromoteur === null) {
|
|
||||||
$juryPromoteur = $juryPromoteurs[0]['name'];
|
|
||||||
}
|
|
||||||
if (!empty($juryPromoteursUlb) && $juryPromoteurUlb === null) {
|
|
||||||
$juryPromoteurUlb = $juryPromoteursUlb[0]['name'];
|
|
||||||
}
|
|
||||||
$showPromoteurUlb = true;
|
|
||||||
$promoteurUlbConditional = false;
|
|
||||||
|
|
||||||
// Licence / access — always all enabled for admin
|
|
||||||
$libreEnabled = true;
|
|
||||||
$interneEnabled = true;
|
|
||||||
$interditEnabled = true;
|
|
||||||
$generalitiesHtml = $helpFn('fieldset_generalites');
|
|
||||||
$defaultAccessTypeId = $currentAccessTypeId ?? 2;
|
|
||||||
$formData['access_type_id'] = $currentAccessTypeId;
|
|
||||||
$formData['license_id'] = $currentLicenseId;
|
|
||||||
$formData['license_custom'] = $currentRaw['license_custom'] ?? '';
|
|
||||||
$formData['cc2r'] = $currentRaw['cc2r'] ?? false;
|
|
||||||
|
|
||||||
// Optional sections
|
|
||||||
$showContact = false; // Admin: contact visibility controlled by filling 'mail' field in fieldset-tfe-info
|
|
||||||
$showBackoffice = true;
|
|
||||||
|
|
||||||
// Files: edit mode
|
|
||||||
$filesMode = 'edit';
|
|
||||||
$currentCover = $currentCover ?? null;
|
|
||||||
$currentFiles = $currentFiles ?? [];
|
|
||||||
$currentContextNote = $currentContextNote ?? null;
|
|
||||||
|
|
||||||
// Website URL from existing files
|
|
||||||
$existingWebsiteUrl = '';
|
|
||||||
$existingWebsiteLabel = '';
|
|
||||||
foreach ($currentFiles as $f) {
|
|
||||||
if ($f['file_type'] === 'website') {
|
|
||||||
$existingWebsiteUrl = $f['file_path'] ?? '';
|
|
||||||
$existingWebsiteLabel = $f['display_label'] ?? '';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Languages — either from flash repopulation or current thesis data
|
|
||||||
$formData['languages'] = $formData['languages'] ?? $currentLanguages ?? [];
|
|
||||||
|
|
||||||
// Compute "other" languages (those not in the predefined checkbox list)
|
|
||||||
$predefinedLangIds = array_column($languages, 'id');
|
|
||||||
$otherLangIds = array_diff($currentLanguages ?? [], $predefinedLangIds);
|
|
||||||
$selectedOtherLanguages = [];
|
|
||||||
if (!empty($otherLangIds)) {
|
|
||||||
$allLangs = Database::getInstance()->getAllLanguages();
|
|
||||||
$allLangMap = [];
|
|
||||||
foreach ($allLangs as $al) {
|
|
||||||
$allLangMap[(int)$al['id']] = $al['name'];
|
|
||||||
}
|
|
||||||
foreach ($otherLangIds as $lid) {
|
|
||||||
$lid = (int)$lid;
|
|
||||||
if (isset($allLangMap[$lid])) {
|
|
||||||
$selectedOtherLanguages[] = $allLangMap[$lid];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sort alphabetically
|
|
||||||
sort($selectedOtherLanguages, SORT_NATURAL | SORT_FLAG_CASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tags — either from flash repopulation or current thesis data
|
|
||||||
$keywordsStr = $thesis['keywords'] ?? '';
|
|
||||||
$currentTags = $keywordsStr !== '' ? array_map('trim', explode(',', $keywordsStr)) : [];
|
|
||||||
// If formData has tag[], use that instead
|
|
||||||
if (!empty($formData['tag']) && is_array($formData['tag'])) {
|
|
||||||
$currentTags = $formData['tag'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Formats — either from flash repopulation or current thesis data
|
|
||||||
$checkedFormats = $formData['formats'] ?? $currentFormats ?? [];
|
|
||||||
// Populate formData.formats for checkbox-list partial
|
|
||||||
$formData['formats'] = $checkedFormats;
|
|
||||||
$checkedFormatsForSiteWeb = $checkedFormats;
|
|
||||||
|
|
||||||
include APP_ROOT . '/templates/partials/form/form.php';
|
include APP_ROOT . '/templates/partials/form/form.php';
|
||||||
?>
|
?>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Reference in New Issue
Block a user