285 lines
9.2 KiB
PHP
285 lines
9.2 KiB
PHP
<?php
|
||
$moduleName = (string)($_GET['module'] ?? '');
|
||
$module = modules()->get($moduleName);
|
||
$error = null;
|
||
$notice = null;
|
||
|
||
require_admin();
|
||
|
||
if (!$module) {
|
||
http_response_code(404);
|
||
echo '<div class="card">Modul nicht gefunden.</div>';
|
||
return;
|
||
}
|
||
|
||
$fields = (array)($module['setup']['fields'] ?? []);
|
||
$fieldTypes = [];
|
||
$fieldMeta = [];
|
||
foreach ($fields as $field) {
|
||
$fname = (string)($field['name'] ?? '');
|
||
if ($fname === '') {
|
||
continue;
|
||
}
|
||
$fieldTypes[$fname] = (string)($field['type'] ?? 'text');
|
||
$fieldMeta[$fname] = $field;
|
||
}
|
||
$current = modules()->settings($moduleName);
|
||
$defaults = $module['db_defaults'] ?? [];
|
||
if (empty($current['db']) && is_array($defaults)) {
|
||
$current['db'] = $defaults;
|
||
}
|
||
$metadataDefaults = $module['metadata_db_defaults'] ?? [];
|
||
if (empty($current['metadata_db']) && is_array($metadataDefaults)) {
|
||
$current['metadata_db'] = $metadataDefaults;
|
||
}
|
||
|
||
$setNested = function (array &$target, string $path, mixed $value): void {
|
||
$parts = explode('.', $path);
|
||
$last = array_pop($parts);
|
||
$node = &$target;
|
||
foreach ($parts as $part) {
|
||
if (!isset($node[$part]) || !is_array($node[$part])) {
|
||
$node[$part] = [];
|
||
}
|
||
$node = &$node[$part];
|
||
}
|
||
if ($last !== null && $last !== '') {
|
||
$node[$last] = $value;
|
||
}
|
||
};
|
||
|
||
$getNested = function (array $source, string $path): mixed {
|
||
$node = $source;
|
||
foreach (explode('.', $path) as $part) {
|
||
if (!is_array($node) || !array_key_exists($part, $node)) {
|
||
return null;
|
||
}
|
||
$node = $node[$part];
|
||
}
|
||
return $node;
|
||
};
|
||
|
||
$dbGroups = [];
|
||
$fieldsByDbGroup = [];
|
||
$generalFields = [];
|
||
foreach ($fields as $field) {
|
||
$name = (string)($field['name'] ?? '');
|
||
if (!str_contains($name, '.')) {
|
||
continue;
|
||
}
|
||
|
||
[$group, $key] = explode('.', $name, 2);
|
||
if ($key !== 'driver') {
|
||
continue;
|
||
}
|
||
|
||
$label = (string)($field['label'] ?? $group);
|
||
$label = trim(preg_replace('/\s+DB\s+Driver$/i', ' DB', $label) ?? $label);
|
||
$label = $label !== '' ? $label : $group;
|
||
$dbGroups[$group] = $label;
|
||
}
|
||
|
||
foreach ($fields as $field) {
|
||
$name = (string)($field['name'] ?? '');
|
||
if (str_contains($name, '.')) {
|
||
[$group] = explode('.', $name, 2);
|
||
if (array_key_exists($group, $dbGroups)) {
|
||
$fieldsByDbGroup[$group][] = $field;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
$generalFields[] = $field;
|
||
}
|
||
|
||
$driverOptions = [
|
||
'pgsql' => 'PostgreSQL',
|
||
'mysql' => 'MySQL / MariaDB',
|
||
'sqlite' => 'SQLite',
|
||
];
|
||
|
||
$renderField = function (array $field) use ($current, $getNested, $driverOptions): void {
|
||
$name = (string)($field['name'] ?? '');
|
||
if ($name === '') {
|
||
return;
|
||
}
|
||
$label = (string)($field['label'] ?? $name);
|
||
$type = (string)($field['type'] ?? 'text');
|
||
$required = !empty($field['required']);
|
||
$help = (string)($field['help'] ?? $field['description'] ?? '');
|
||
$postKey = str_replace('.', '_', $name);
|
||
|
||
$value = '';
|
||
if ($name === 'kea_auto_init') {
|
||
$value = !empty($current[$name]) ? '1' : '0';
|
||
} elseif (str_contains($name, '.')) {
|
||
$value = (string)($getNested($current, $name) ?? '');
|
||
} else {
|
||
$value = (string)($current[$name] ?? '');
|
||
}
|
||
?>
|
||
<label class="setup-field muted">
|
||
<span><?= e($label) ?></span>
|
||
<?php if (str_ends_with($name, '.driver')): ?>
|
||
<select name="<?= e($postKey) ?>" <?= $required ? 'required' : '' ?>>
|
||
<option value="">Bitte waehlen</option>
|
||
<?php foreach ($driverOptions as $driver => $driverLabel): ?>
|
||
<option value="<?= e($driver) ?>" <?= $value === $driver ? 'selected' : '' ?>><?= e($driverLabel) ?></option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
<?php elseif ($type === 'textarea'): ?>
|
||
<textarea name="<?= e($postKey) ?>" rows="3" <?= $required ? 'required' : '' ?>><?= e($value) ?></textarea>
|
||
<?php elseif ($type === 'checkbox'): ?>
|
||
<input type="checkbox" name="<?= e($postKey) ?>" value="1" <?= $value === '1' ? 'checked' : '' ?>>
|
||
<?php else: ?>
|
||
<input type="<?= e($type) ?>" name="<?= e($postKey) ?>" value="<?= e($value) ?>" <?= $required ? 'required' : '' ?>>
|
||
<?php endif; ?>
|
||
<?php if ($help !== ''): ?>
|
||
<small class="muted"><?= e($help) ?></small>
|
||
<?php endif; ?>
|
||
</label>
|
||
<?php
|
||
};
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
$payload = [];
|
||
|
||
foreach ($fields as $field) {
|
||
$name = (string)($field['name'] ?? '');
|
||
if ($name === '') {
|
||
continue;
|
||
}
|
||
$type = (string)($field['type'] ?? 'text');
|
||
$postKey = str_replace('.', '_', $name);
|
||
$value = $_POST[$postKey] ?? null;
|
||
|
||
if ($type === 'checkbox') {
|
||
$value = isset($_POST[$postKey]) ? '1' : '0';
|
||
}
|
||
if (is_array($value)) {
|
||
continue;
|
||
}
|
||
$value = is_string($value) ? trim($value) : $value;
|
||
|
||
if ($name === 'kea_auto_init') {
|
||
$payload[$name] = $value === '1';
|
||
continue;
|
||
}
|
||
|
||
if (str_contains($name, '.')) {
|
||
$setNested($payload, $name, $value);
|
||
continue;
|
||
}
|
||
|
||
$payload[$name] = $value;
|
||
}
|
||
|
||
$current = array_replace_recursive($current, $payload);
|
||
|
||
$testGroup = (string)($_POST['test_db'] ?? '');
|
||
if ($testGroup !== '') {
|
||
if (!array_key_exists($testGroup, $dbGroups)) {
|
||
$error = 'Unbekannte Datenbank-Konfiguration.';
|
||
} else {
|
||
$dbConfig = $getNested($current, $testGroup);
|
||
if (!is_array($dbConfig)) {
|
||
$error = 'Datenbank-Konfiguration ist unvollstaendig.';
|
||
} else {
|
||
try {
|
||
$dbConfig['options'] = array_replace([
|
||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
||
], (array)($dbConfig['options'] ?? []));
|
||
|
||
$testPdo = \App\Database::createFromArray($dbConfig);
|
||
$testPdo->query('SELECT 1')->fetchColumn();
|
||
$notice = $dbGroups[$testGroup] . ': Verbindung erfolgreich.';
|
||
} catch (\Throwable $e) {
|
||
$error = $dbGroups[$testGroup] . ': Verbindung fehlgeschlagen. ' . $e->getMessage();
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
modules()->saveSettings($moduleName, $payload);
|
||
$notice = 'Setup gespeichert.';
|
||
$module = modules()->get($moduleName) ?: $module;
|
||
}
|
||
}
|
||
?>
|
||
<div class="setup-shell">
|
||
<div class="pill">Setup</div>
|
||
<h1 class="setup-title"><?= e($module['title']) ?> – Einrichtung</h1>
|
||
<p class="muted">Trage die benötigten Informationen für das Modul ein.</p>
|
||
|
||
<?php if ($error): ?>
|
||
<div class="bg-red-900 border-l-4 border-red-500 text-red-100 p-4 mb-6" role="alert">
|
||
<?= e($error) ?>
|
||
</div>
|
||
<?php elseif ($notice): ?>
|
||
<div class="setup-notice">
|
||
<?= e($notice) ?>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<form method="post" class="setup-form">
|
||
<?php if ($generalFields !== []): ?>
|
||
<section class="setup-panel">
|
||
<div class="setup-panel__head">
|
||
<div>
|
||
<span class="pill">Allgemein</span>
|
||
<h2>Moduleinstellungen</h2>
|
||
</div>
|
||
</div>
|
||
<div class="setup-grid">
|
||
<?php foreach ($generalFields as $field): ?>
|
||
<?php $renderField($field); ?>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<?php if ($dbGroups !== []): ?>
|
||
<section class="setup-panel setup-panel--flat">
|
||
<div class="setup-panel__head">
|
||
<div>
|
||
<span class="pill">Datenbanken</span>
|
||
<h2>Verbindungen</h2>
|
||
<p class="muted">Jede Verbindung kann getrennt konfiguriert und getestet werden.</p>
|
||
</div>
|
||
</div>
|
||
<div class="setup-tabs" aria-label="Datenbankbereiche">
|
||
<?php foreach ($dbGroups as $group => $label): ?>
|
||
<a class="nav-link" href="#setup-db-<?= e($group) ?>"><?= e($label) ?></a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
<div class="setup-db-panels">
|
||
<?php foreach ($dbGroups as $group => $label): ?>
|
||
<section class="setup-db-panel" id="setup-db-<?= e($group) ?>">
|
||
<div class="setup-panel__head">
|
||
<div>
|
||
<span class="pill"><?= e($label) ?></span>
|
||
<h3><?= e($label) ?> konfigurieren</h3>
|
||
</div>
|
||
<button class="nav-link" type="submit" name="test_db" value="<?= e($group) ?>" formnovalidate>
|
||
Verbindung testen
|
||
</button>
|
||
</div>
|
||
<div class="setup-grid">
|
||
<?php foreach (($fieldsByDbGroup[$group] ?? []) as $field): ?>
|
||
<?php $renderField($field); ?>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</section>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<div class="setup-actions">
|
||
<button class="cta-button" type="submit">Speichern</button>
|
||
<a class="nav-link" href="/modules/access/<?= e($moduleName) ?>">Zugriff verwalten</a>
|
||
<a class="nav-link" href="/modules">Zurück</a>
|
||
</div>
|
||
</form>
|
||
</div>
|