refactor solution to PHP through AI
This commit is contained in:
@@ -0,0 +1,610 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ElixForms\Common;
|
||||
|
||||
require_once __DIR__ . '/QueryParamHelper.php';
|
||||
require_once __DIR__ . '/ElixFormsElement.php';
|
||||
|
||||
/**
|
||||
* Classe astratta base per le custom page PHP di elixForms.
|
||||
* Equivalente PHP di ElixFormsComponentAbstract.tsx nel progetto React.
|
||||
*
|
||||
* Ogni pagina custom deve:
|
||||
* 1. Estendere questa classe
|
||||
* 2. Sovrascrivere createCustomFormFields() per definire i campi del form
|
||||
* 3. Opzionalmente sovrascrivere renderExtraContentPre() / renderExtraContentPost()
|
||||
* 4. Chiamare render() per generare l'HTML completo della pagina
|
||||
*
|
||||
* Uso tipico:
|
||||
* ```php
|
||||
* $page = new MiaPaginaCustom([
|
||||
* 'moduleName' => 'Nome Modulo',
|
||||
* 'cardTitle' => 'Titolo Card',
|
||||
* // ...altre proprietà...
|
||||
* ]);
|
||||
* echo $page->render();
|
||||
* ```
|
||||
*/
|
||||
abstract class ElixFormsComponent
|
||||
{
|
||||
/**
|
||||
* Proprietà della pagina (equivalente a IElixFormsComponentProperties).
|
||||
*
|
||||
* Chiavi supportate:
|
||||
* - isDarkTheme: bool (opzionale)
|
||||
* - userDisplayName: string (opzionale)
|
||||
* - additionalFieldsJson: string (opzionale, JSON schema per campi dinamici)
|
||||
* - moduleName: string (obbligatorio)
|
||||
* - headerTitle: string (opzionale)
|
||||
* - headerHeroImageSrc: string (opzionale)
|
||||
* - cardTitle: string (obbligatorio)
|
||||
* - cardDescription: string (opzionale)
|
||||
* - alertInfoTitle: string (opzionale)
|
||||
* - alertInfoMessage: string (opzionale)
|
||||
* - instructionsTitle: string (opzionale)
|
||||
* - instructionsMessage: string (opzionale)
|
||||
* - submitText: string (opzionale, default 'INVIA')
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected array $properties;
|
||||
|
||||
/**
|
||||
* Nomi dei parametri obbligatori che elixForms passa in query string.
|
||||
* Se mancano, la pagina mostra un errore di autenticazione.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $mandatoryFormFieldNames = [
|
||||
'RWE2_MODULE_ID',
|
||||
'RWE2_REQUEST_ID',
|
||||
'custom-workflow-back-url',
|
||||
'custom-workflow-generic-id',
|
||||
'custom-workflow-current-tabrel-genid',
|
||||
'custom-workflow-source-field',
|
||||
'crc',
|
||||
'MODULE_TESTMODE_KEY',
|
||||
'ELANG',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $properties Proprietà della pagina
|
||||
*/
|
||||
public function __construct(array $properties)
|
||||
{
|
||||
$this->properties = $properties;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Metodi estensibili (da sovrascrivere nelle pagine figlie)
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Genera i campi custom del form.
|
||||
* Da sovrascrivere nelle pagine figlie per definire i campi specifici.
|
||||
*
|
||||
* @return string HTML dei campi custom
|
||||
*/
|
||||
protected function createCustomFormFields(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Contenuto extra da renderizzare PRIMA del form.
|
||||
* Sovrascrivere per aggiungere contenuto personalizzato.
|
||||
*
|
||||
* @return string HTML del contenuto extra
|
||||
*/
|
||||
protected function renderExtraContentPre(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Contenuto extra da renderizzare DOPO il form.
|
||||
* Sovrascrivere per aggiungere contenuto personalizzato.
|
||||
*
|
||||
* @return string HTML del contenuto extra
|
||||
*/
|
||||
protected function renderExtraContentPost(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Metodi factory per campi form
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Crea un campo di testo (input type="text").
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo (corrisponde alla colonna elixForms)
|
||||
* @param string $label Etichetta del campo
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createTextInput(string $paramName, string $label, bool $required = false): string
|
||||
{
|
||||
$currentValue = htmlspecialchars(QueryParamHelper::getDecodedTextFromQuery($paramName) ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
|
||||
$labelHtml = '<label class="form-label fw-semibold" for="' . htmlspecialchars($paramName) . '">' . htmlspecialchars($label) . '</label>';
|
||||
$inputHtml = '<input id="' . htmlspecialchars($paramName) . '" name="' . htmlspecialchars($paramName) . '" class="form-control" type="text" value="' . $currentValue . '"' . $requiredAttr . ' />';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo textarea.
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo
|
||||
* @param string $label Etichetta del campo
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createTextAreaInput(string $paramName, string $label, bool $required = false): string
|
||||
{
|
||||
$currentValue = htmlspecialchars(QueryParamHelper::getDecodedTextFromQuery($paramName) ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
|
||||
$labelHtml = '<label class="form-label fw-semibold" for="' . htmlspecialchars($paramName) . '">' . htmlspecialchars($label) . '</label>';
|
||||
$inputHtml = '<textarea id="' . htmlspecialchars($paramName) . '" name="' . htmlspecialchars($paramName) . '" class="form-control" rows="4"' . $requiredAttr . '>' . $currentValue . '</textarea>';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo numerico (input type="number").
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo
|
||||
* @param string $label Etichetta del campo
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createNumberInput(string $paramName, string $label, bool $required = false): string
|
||||
{
|
||||
$currentValue = htmlspecialchars(QueryParamHelper::getDecodedTextFromQuery($paramName) ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
|
||||
$labelHtml = '<label class="form-label fw-semibold" for="' . htmlspecialchars($paramName) . '">' . htmlspecialchars($label) . '</label>';
|
||||
$inputHtml = '<input id="' . htmlspecialchars($paramName) . '" name="' . htmlspecialchars($paramName) . '" class="form-control" type="number" value="' . $currentValue . '"' . $requiredAttr . ' />';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo booleano (radio Sì/No).
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo
|
||||
* @param string $label Etichetta del campo
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createBooleanInput(string $paramName, string $label, bool $required = false): string
|
||||
{
|
||||
$currentValue = QueryParamHelper::getDecodedTextFromQuery($paramName) ?? '';
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
$escapedName = htmlspecialchars($paramName);
|
||||
$escapedLabel = htmlspecialchars($label);
|
||||
|
||||
$labelHtml = '<span class="form-label fw-semibold">' . $escapedLabel . '</span>';
|
||||
|
||||
$options = [
|
||||
['value' => 'true', 'label' => 'Sì'],
|
||||
['value' => 'false', 'label' => 'No'],
|
||||
];
|
||||
|
||||
$inputHtml = '<div class="d-flex flex-column gap-2" role="radiogroup" aria-label="' . $escapedLabel . '">';
|
||||
foreach ($options as $option) {
|
||||
$id = $escapedName . '_' . $option['value'];
|
||||
$checked = $currentValue === $option['value'] ? ' checked' : '';
|
||||
$inputHtml .= <<<HTML
|
||||
<div class="form-check">
|
||||
<input id="{$id}" class="form-check-input" type="radio" name="{$escapedName}" value="{$option['value']}"{$checked}{$requiredAttr} />
|
||||
<label class="form-check-label" for="{$id}">{$option['label']}</label>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
$inputHtml .= '</div>';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo radio con opzioni personalizzate.
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo
|
||||
* @param string $label Etichetta del campo
|
||||
* @param array<array{value: int, label: string}> $options Opzioni radio
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createRadioInput(string $paramName, string $label, array $options, bool $required = false): string
|
||||
{
|
||||
$currentValue = (string)(QueryParamHelper::getOptionFromQuery($paramName) ?? '');
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
$escapedName = htmlspecialchars($paramName);
|
||||
$escapedLabel = htmlspecialchars($label);
|
||||
|
||||
$labelHtml = '<span class="form-label fw-semibold">' . $escapedLabel . '</span>';
|
||||
|
||||
$inputHtml = '<div class="d-flex flex-column gap-2" role="radiogroup" aria-label="' . $escapedLabel . '">';
|
||||
foreach ($options as $option) {
|
||||
$id = $escapedName . '_' . $option['value'];
|
||||
$checked = $currentValue === (string)$option['value'] ? ' checked' : '';
|
||||
$optionLabel = htmlspecialchars($option['label']);
|
||||
$inputHtml .= <<<HTML
|
||||
<div class="form-check">
|
||||
<input id="{$id}" class="form-check-input" type="radio" name="{$escapedName}" value="{$option['value']}"{$checked}{$requiredAttr} />
|
||||
<label class="form-check-label" for="{$id}">{$optionLabel}</label>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
$inputHtml .= '</div>';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo checkbox con opzioni multiple.
|
||||
* I valori selezionati vengono inviati come stringa separata da virgola in un input hidden.
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo (usato per l'hidden input)
|
||||
* @param string $label Etichetta del campo
|
||||
* @param array<array{value: int, label: string, required?: bool}> $options Opzioni checkbox
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createCheckboxInput(string $paramName, string $label, array $options): string
|
||||
{
|
||||
$checkedValues = QueryParamHelper::getCheckedFromQuery($paramName);
|
||||
$currentValue = implode(',', $checkedValues);
|
||||
$escapedName = htmlspecialchars($paramName);
|
||||
$escapedLabel = htmlspecialchars($label);
|
||||
|
||||
$labelHtml = '<label class="form-label fw-semibold" for="' . $escapedName . '">' . $escapedLabel . '</label>';
|
||||
|
||||
$inputHtml = '<div class="d-flex flex-column gap-2" role="group" aria-label="' . $escapedLabel . '">';
|
||||
foreach ($options as $entryIndex => $entry) {
|
||||
$id = $escapedName . '_' . $entryIndex;
|
||||
$isChecked = in_array($entryIndex, $checkedValues) ? ' checked' : '';
|
||||
$optionLabel = htmlspecialchars($entry['label']);
|
||||
$inputHtml .= <<<HTML
|
||||
<div class="form-check">
|
||||
<input id="{$id}" class="form-check-input" type="checkbox" value="{$entryIndex}" data-param="{$escapedName}"{$isChecked} />
|
||||
<label class="form-check-label" for="{$id}">{$optionLabel}</label>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
$inputHtml .= '</div>';
|
||||
// Hidden input che contiene il valore aggregato (aggiornato via JS client-side)
|
||||
$inputHtml .= '<input type="hidden" id="' . $escapedName . '" name="' . $escapedName . '" value="' . htmlspecialchars($currentValue) . '" />';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo dropdown (select).
|
||||
*
|
||||
* @param string $paramName Nome/ID del campo
|
||||
* @param string $label Etichetta del campo
|
||||
* @param array<array{value: int, label: string}> $options Opzioni dropdown
|
||||
* @param bool $required Se il campo è obbligatorio
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
protected function createDropdownInput(string $paramName, string $label, array $options, bool $required = false): string
|
||||
{
|
||||
$queryValue = QueryParamHelper::getOptionFromQuery($paramName);
|
||||
$currentValue = $queryValue !== null ? (string)$queryValue : '';
|
||||
$requiredAttr = $required ? ' required' : '';
|
||||
$escapedName = htmlspecialchars($paramName);
|
||||
$escapedLabel = htmlspecialchars($label);
|
||||
|
||||
$labelHtml = '<label class="form-label fw-semibold" for="' . $escapedName . '">' . $escapedLabel . '</label>';
|
||||
|
||||
$inputHtml = '<select id="' . $escapedName . '" name="' . $escapedName . '" class="form-select"' . $requiredAttr . '>';
|
||||
$inputHtml .= '<option value="">Seleziona...</option>';
|
||||
foreach ($options as $option) {
|
||||
$selected = $currentValue === (string)$option['value'] ? ' selected' : '';
|
||||
$optionLabel = htmlspecialchars($option['label']);
|
||||
$inputHtml .= '<option value="' . $option['value'] . '"' . $selected . '>' . $optionLabel . '</option>';
|
||||
}
|
||||
$inputHtml .= '</select>';
|
||||
|
||||
return (new ElixFormsElement($labelHtml, $inputHtml))->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un campo nascosto (hidden input).
|
||||
* L'ID dell'hidden ha il suffisso _hidden per evitare conflitti.
|
||||
*
|
||||
* @param string $paramName Nome del campo
|
||||
* @return string HTML dell'input hidden
|
||||
*/
|
||||
protected function createHiddenInput(string $paramName): string
|
||||
{
|
||||
$value = htmlspecialchars(QueryParamHelper::getDecodedTextFromQuery($paramName) ?? '', ENT_QUOTES, 'UTF-8');
|
||||
$escapedName = htmlspecialchars($paramName);
|
||||
|
||||
return '<input type="hidden" id="' . $escapedName . '_hidden" name="' . $escapedName . '" value="' . $value . '" />';
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Metodi interni di rendering
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Genera gli hidden input per tutti i parametri obbligatori elixForms.
|
||||
*
|
||||
* @return string HTML degli hidden input
|
||||
*/
|
||||
private function createMandatoryFormFields(): string
|
||||
{
|
||||
$html = '';
|
||||
foreach ($this->mandatoryFormFieldNames as $paramName) {
|
||||
$html .= $this->createHiddenInput($paramName);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera i campi form da uno schema JSON (additionalFieldsJson).
|
||||
*
|
||||
* @return string HTML dei campi aggiuntivi
|
||||
*/
|
||||
private function createAdditionalFormFields(): string
|
||||
{
|
||||
$json = $this->properties['additionalFieldsJson'] ?? '[]';
|
||||
$schema = json_decode($json, true);
|
||||
|
||||
if (!is_array($schema)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
foreach ($schema as $field) {
|
||||
$html .= $this->renderField($field);
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderizza un singolo campo form in base al tipo specificato nello schema.
|
||||
*
|
||||
* @param array<string, mixed> $field Definizione del campo
|
||||
* @return string HTML del campo
|
||||
*/
|
||||
private function renderField(array $field): string
|
||||
{
|
||||
$key = $field['key'] ?? '';
|
||||
$fieldLabel = $field['label'] ?? '';
|
||||
$required = $field['required'] ?? false;
|
||||
$fieldOptions = $field['options'] ?? [];
|
||||
|
||||
return match ($field['type'] ?? '') {
|
||||
'text' => $this->createTextInput($key, $fieldLabel, $required),
|
||||
'textarea' => $this->createTextAreaInput($key, $fieldLabel, $required),
|
||||
'number' => $this->createNumberInput($key, $fieldLabel, $required),
|
||||
'boolean' => $this->createBooleanInput($key, $fieldLabel, $required),
|
||||
'radio' => $this->createRadioInput($key, $fieldLabel, $fieldOptions, $required),
|
||||
'checkbox' => $this->createCheckboxInput($key, $fieldLabel, $fieldOptions),
|
||||
'dropdown' => $this->createDropdownInput($key, $fieldLabel, $fieldOptions, $required),
|
||||
default => '',
|
||||
};
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Render principale
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Genera l'HTML completo della pagina.
|
||||
* Include: head con CSS, header Bootstrap Italia, breadcrumb, card con form, footer.
|
||||
*
|
||||
* @return string HTML completo della pagina
|
||||
*/
|
||||
public function render(): string
|
||||
{
|
||||
$userDisplayName = $this->properties['userDisplayName'] ?? '';
|
||||
$moduleName = htmlspecialchars($this->properties['moduleName'] ?? '');
|
||||
$headerTitle = $this->properties['headerTitle'] ?? '';
|
||||
$headerHeroImageSrc = $this->properties['headerHeroImageSrc'] ?? '';
|
||||
$cardTitle = $this->properties['cardTitle'] ?? '';
|
||||
$cardDescription = $this->properties['cardDescription'] ?? '';
|
||||
$alertInfoTitle = $this->properties['alertInfoTitle'] ?? '';
|
||||
$alertInfoMessage = $this->properties['alertInfoMessage'] ?? '';
|
||||
$instructionsTitle = $this->properties['instructionsTitle'] ?? '';
|
||||
$instructionsMessage = $this->properties['instructionsMessage'] ?? '';
|
||||
$submitText = $this->properties['submitText'] ?? 'INVIA';
|
||||
|
||||
// Verifica parametri obbligatori
|
||||
$missingParams = array_filter($this->mandatoryFormFieldNames, fn($p) => !isset($_GET[$p]));
|
||||
$hasAuthenticationError = count($missingParams) > 0;
|
||||
|
||||
// Contenuti del form
|
||||
$mandatoryFields = $this->createMandatoryFormFields();
|
||||
$additionalFields = $this->createAdditionalFormFields();
|
||||
$customFields = $this->createCustomFormFields();
|
||||
$extraContentPre = $this->renderExtraContentPre();
|
||||
$extraContentPost = $this->renderExtraContentPost();
|
||||
|
||||
// Costruisci l'HTML della pagina
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= htmlspecialchars($cardTitle) ?> — elixForms</title>
|
||||
<meta name="description" content="<?= htmlspecialchars($cardDescription) ?>">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Titillium+Web:wght@300;400;600;700&display=swap">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-italia@2.18.2/dist/css/bootstrap-italia.min.css">
|
||||
<link rel="stylesheet" href="https://console-unipr.elixforms.it/rwe2/css/design-bs/util.css">
|
||||
<link rel="stylesheet" href="https://console-unipr.elixforms.it/rwe2/css/themes/blu-italia.css">
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<header class="it-header-wrapper text-white">
|
||||
<?php if ($userDisplayName): ?>
|
||||
<div class="it-header-slim-wrapper">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="it-header-slim-wrapper-content">
|
||||
<div class="nav-mobile"></div>
|
||||
<div class="it-header-slim-right-zone">
|
||||
<div class="it-access-top-wrapper">
|
||||
<?= htmlspecialchars($userDisplayName) ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="it-header-center-wrapper">
|
||||
<div class="container">
|
||||
<div class="it-header-center-content-wrapper">
|
||||
<div class="it-brand-wrapper">
|
||||
<a href="https://www.unipr.it/" title="Torna alla homepage dell'Università di Parma">
|
||||
<img class="icon" src="https://procedure.unipr.it/UploadImgs/12_marchio_UNIPR_neg_b1_squareLogo.png" alt="Università di Parma" />
|
||||
<div class="it-brand-text">
|
||||
<p class="h2 no_toc">Università di Parma</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="it-right-zone"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="container my-2 mx-4">
|
||||
<div class="cmp-breadcrumb" role="navigation">
|
||||
<nav class="breadcrumb-container" aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">Procedure Online<span class="separator">></span></li>
|
||||
<li class="breadcrumb-item active" aria-current="page"><?= $moduleName ?></li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<?php if ($headerHeroImageSrc): ?>
|
||||
<img src="<?= htmlspecialchars($headerHeroImageSrc) ?>" alt="Hero Image" class="hero-image img-fluid mb-3" />
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($headerTitle): ?>
|
||||
<p class="h2"><?= htmlspecialchars($headerTitle) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<?php if ($cardTitle): ?>
|
||||
<p class="h3 mb-3"><?= htmlspecialchars($cardTitle) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($cardDescription): ?>
|
||||
<p class="lead text-secondary"><?= htmlspecialchars($cardDescription) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($alertInfoTitle || $alertInfoMessage): ?>
|
||||
<div class="custom-alert custom-alert-warning" role="status">
|
||||
<?php if ($alertInfoTitle): ?><div><b><?= htmlspecialchars($alertInfoTitle) ?></b></div><?php endif; ?>
|
||||
<?php if ($alertInfoMessage): ?><div class="small"><?= htmlspecialchars($alertInfoMessage) ?></div><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($hasAuthenticationError): ?>
|
||||
<div class="alert alert-danger" role="alert">Accesso non autorizzato!</div>
|
||||
<?php else: ?>
|
||||
|
||||
<?= $extraContentPre ?>
|
||||
|
||||
<?php if ($instructionsTitle || $instructionsMessage): ?>
|
||||
<div class="custom-alert custom-alert-info" role="status">
|
||||
<?php if ($instructionsTitle): ?><div><b><?= htmlspecialchars($instructionsTitle) ?></b></div><?php endif; ?>
|
||||
<?php if ($instructionsMessage): ?><div class="small"><?= htmlspecialchars($instructionsMessage) ?></div><?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="https://procedure.unipr.it/rwe2/ComeBackToElixAndSave" method="post" accept-charset="ISO-8859-1" class="mt-3">
|
||||
<?= $mandatoryFields ?>
|
||||
<?= $additionalFields ?>
|
||||
<?= $customFields ?>
|
||||
<div class="mt-4 d-flex justify-content-end">
|
||||
<button type="submit" class="btn btn-primary"><?= htmlspecialchars($submitText) ?> <span class="it-arrow-right text-white ms-2"></span></button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?= $extraContentPost ?>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="it-footer text-white">
|
||||
<div class="it-footer-small-prints clearfix">
|
||||
<div class="container">
|
||||
<section>
|
||||
<div class="row clearfix">
|
||||
<div class="col-sm-12">
|
||||
<div class="footer-content text-center p-2">
|
||||
<div class="subfooter-top">powered by <span class="highlight">elixForms</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<?= $this->renderCheckboxScript() ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Genera il JavaScript per la gestione client-side dei checkbox.
|
||||
* Aggiorna l'hidden input con i valori selezionati separati da virgola.
|
||||
*
|
||||
* @return string Tag <script> con il codice JS
|
||||
*/
|
||||
private function renderCheckboxScript(): string
|
||||
{
|
||||
return <<<'SCRIPT'
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('input[type="checkbox"][data-param]').forEach(function(checkbox) {
|
||||
checkbox.addEventListener('change', function() {
|
||||
var paramName = this.getAttribute('data-param');
|
||||
var hiddenInput = document.getElementById(paramName);
|
||||
if (!hiddenInput) return;
|
||||
|
||||
var checkboxes = document.querySelectorAll('input[type="checkbox"][data-param="' + paramName + '"]');
|
||||
var values = [];
|
||||
checkboxes.forEach(function(cb) {
|
||||
if (cb.checked) {
|
||||
values.push(cb.value);
|
||||
}
|
||||
});
|
||||
hiddenInput.value = values.join(',');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
SCRIPT;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user