['/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', '/assets/js/app/autosave-handler.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|array { 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; // ── Autosave draft wiring (add / edit only) ─────────────────────┐ $autosaveUrl = '/admin/actions/draft.php'; $formExtraAttrs = ''; $showAutosaveStatus = false; $extraHidden = ''; if ($mode === 'add') { // Reuse draft token from session so drafts survive page reloads if (empty($_SESSION['admin_draft_add_token'])) { $_SESSION['admin_draft_add_token'] = bin2hex(random_bytes(8)); } $draftToken = $_SESSION['admin_draft_add_token']; $draftKey = 'admin_draft_' . $draftToken; $extraHidden = ''; // Hydrate from any previous session (survives accidental navigations) $draft = $_SESSION[$draftKey] ?? []; $formData = array_merge($draft, $formData); $showAutosaveStatus = true; } elseif ($mode === 'edit') { $thesisId = (int)($options['thesisId'] ?? 0); if ($thesisId > 0) { $draftKey = 'admin_draft_edit_' . $thesisId; $extraHidden = ''; $draft = $_SESSION[$draftKey] ?? []; $formData = array_merge($draft, $formData); $showAutosaveStatus = true; } } if ($showAutosaveStatus) { $formExtraAttrs = 'hx-post="' . htmlspecialchars($autosaveUrl) . '"'; } return array_merge([ // Base 'mode' => $mode, 'formAction' => $formAction, 'hiddenFields' => $hiddenFields . $extraHidden, 'errorFieldName' => $autofocusField, 'synopsisExtra' => $options['synopsisExtra'] ?? '', 'formExtraAttrs' => $formExtraAttrs, 'showAutosaveStatus' => $showAutosaveStatus, 'autosaveUrl' => $autosaveUrl, // 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, 'currentDurationValue' => null, 'currentDurationUnit' => 'pages', // Files (edit mode) 'currentCover' => null, 'currentFiles' => [], ], $options); } }