OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

_field_renderer.php

6 KB
<?php
/**
 * Gemeinsamer Feld-Renderer für externe Antrags-Formulare (öffentliches
 * Formular und Self-Service-Portal). Erwartet im Scope:
 *   $view    – View-Instanz (für e())
 *   $lookups – Vorschlagslisten je field_key
 *   $dirOn   – Verzeichnis-Auswahl erlaubt?
 * Definiert die Closure $renderField(array $f): void.
 */
// Feld-Renderer: respektiert den Verzeichnis-Schalter (person/user/lookup → Freitext, wenn aus).
$renderField = function (array $f) use ($view, $lookups, $dirOn) {
    $name = 'field_' . $f['field_key'];
    $req  = (int)$f['is_required'] === 1;
    $opts = !empty($f['options_json']) ? (json_decode($f['options_json'], true) ?: []) : [];
    $type = $f['field_type'];
    $attrs = $req ? ' required' : '';
    if (!empty($f['max_length'])) { $attrs .= ' maxlength="' . (int)$f['max_length'] . '"'; }
    if (in_array($type, ['number','date','currency'], true)) {
        if (($f['min_value'] ?? '') !== '') { $attrs .= ' min="' . $view->e($f['min_value']) . '"'; }
        if (($f['max_value'] ?? '') !== '') { $attrs .= ' max="' . $view->e($f['max_value']) . '"'; }
    }
    // Bei deaktiviertem Verzeichnis verhalten sich diese Typen wie Freitext.
    $hasList = isset($lookups[$f['field_key']]);
    if (in_array($type, ['person','user','lookup'], true) && (!$dirOn || !$hasList)) {
        $type = 'text';
    }
    // Reine Anzeige-Typen: Überschrift, HTML-Block, Zustimmung. Der Anzeige-
    // Inhalt (options_json.html) stammt aus der Formularverwaltung, wird aber
    // auf öffentlichen und Portal-Seiten gerendert – daher über eine
    // Positivliste bereinigt statt roh ausgegeben.
    $contentHtml = is_array($opts) && isset($opts['html'])
        ? \OpenNIT\Security\XSS::purifyHtml((string)$opts['html'])
        : '';
    if ($type === 'heading') { ?>
        <div style="font-size:.78rem;font-weight:700;color:var(--gray-500);text-transform:uppercase;letter-spacing:.05em;margin:1rem 0 .5rem;border-bottom:1px solid var(--gray-200);padding-bottom:.3rem;">
            <?= $view->e($f['label']) ?>
        </div>
        <?php if (!empty($f['help_text'])): ?><p class="text-muted" style="font-size:.8rem;margin:0 0 .5rem;"><?= $view->e($f['help_text']) ?></p><?php endif; ?>
        <?php return;
    }
    if ($type === 'html') { ?>
        <div class="form-group"><?= $contentHtml ?></div>
        <?php return;
    }
    if ($type === 'consent') { ?>
        <div class="form-group">
            <label class="checkbox-inline" style="display:flex;gap:.55rem;align-items:flex-start;font-weight:400;cursor:pointer;">
                <input type="checkbox" name="<?= $view->e($name) ?>" value="1" style="margin-top:.22rem;flex:0 0 auto;"<?= $req ? ' required' : '' ?>>
                <span><?= $contentHtml !== '' ? $contentHtml : $view->e($f['label']) ?><?php if ($req): ?> <span class="text-danger">*</span><?php endif; ?></span>
            </label>
        </div>
        <?php return;
    }
    ?>
    <div class="form-group">
        <label for="f-fc6b-----------------------"><?= $view->e($f['label']) ?><?php if ($req): ?> <span class="text-danger">*</span><?php endif; ?></label>
        <?php if ($type === 'textarea'): ?>
            <textarea id="f-fc6b-----------------------" class="form-control form-control-sm" name="<?= $view->e($name) ?>" rows="4"<?= $attrs ?>></textarea>
        <?php elseif ($type === 'dropdown'): ?>
            <select class="form-control form-control-sm" name="<?= $view->e($name) ?>"<?= $req ? ' required' : '' ?>>
                <option value=""><?= $this->te('– bitte wählen –') ?></option>
                <?php foreach ($opts as $o): ?><option value="<?= $view->e($o) ?>"><?= $view->e($o) ?></option><?php endforeach; ?>
            </select>
        <?php elseif ($type === 'checkbox'): ?>
            <label class="checkbox-inline"><input type="checkbox" name="<?= $view->e($name) ?>" value="1"> Ja</label>
        <?php elseif ($type === 'number'): ?>
            <input class="form-control form-control-sm" type="number" name="<?= $view->e($name) ?>"<?= $attrs ?>>
        <?php elseif ($type === 'currency'): ?>
            <input class="form-control form-control-sm" type="number" step="0.01" name="<?= $view->e($name) ?>"<?= $attrs ?>> <?= $view->e($view->currency()) ?>
        <?php elseif ($type === 'date'): ?>
            <input class="form-control form-control-sm" type="date" name="<?= $view->e($name) ?>"<?= $attrs ?>>
        <?php elseif (in_array($type, ['person','user','lookup'], true)): ?>
            <input class="form-control form-control-sm" list="lk-<?= $view->e($f['field_key']) ?>" name="<?= $view->e($name) ?>"<?= $attrs ?> autocomplete="off">
            <datalist id="lk-<?= $view->e($f['field_key']) ?>">
                <?php foreach (($lookups[$f['field_key']] ?? []) as $lv): ?><option value="<?= $view->e($lv) ?>"></option><?php endforeach; ?>
            </datalist>
        <?php elseif ($type === 'file'): ?>
            <input class="form-control form-control-sm" type="file" name="<?= $view->e($name) ?>"<?= $req ? ' required' : '' ?><?= !empty($f['accept']) ? ' accept="' . $view->e($f['accept']) . '"' : '' ?>>
        <?php elseif ($type === 'email'): ?>
            <input class="form-control form-control-sm" type="email" name="<?= $view->e($name) ?>"<?= $attrs ?>>
        <?php elseif ($type === 'repeater'): ?>
            <div class="wf-repeater">
                <div class="wf-rep-rows">
                    <div class="wf-rep-row" style="display:flex;gap:.4rem;margin-bottom:.35rem;">
                        <input class="form-control form-control-sm" type="text" name="<?= $view->e($name) ?>[]"<?= $req ? ' required' : '' ?>>
                        <button aria-label="<?= $this->te('Entfernen') ?>" type="button" class="btn btn-xs btn-secondary wf-rep-del"><i class="fas fa-minus"></i></button>
                    </div>
                </div>
                <button type="button" class="btn btn-xs btn-secondary wf-rep-add"><i class="fas fa-plus"></i> <?= $this->te('Zeile hinzufügen') ?></button>
            </div>
        <?php else: ?>
            <input class="form-control form-control-sm" type="text" name="<?= $view->e($name) ?>"<?= $attrs ?>>
        <?php endif; ?>
        <?php if (!empty($f['help_text'])): ?><small class="text-muted"><?= $view->e($f['help_text']) ?></small><?php endif; ?>
    </div>
    <?php
};