Extract FormBootstrap helper to eliminate bootstrap duplication across add/edit form pages

This commit is contained in:
Pontoporeia
2026-06-11 12:11:37 +02:00
parent f4a3e26901
commit a19e9e1454
5 changed files with 354 additions and 247 deletions

View 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);
}
}