Backup #231
| ID | 231 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Controller/ConfigController.php |
| Version | 4 |
| Typ |
modified |
| Größe | 10.4 KB |
| Hash | 4e02e70122468a46c80243870019bd3479798ac31552984c42f08f3f83d0aa20 |
| Datum | 2025-12-22 01:45:25 |
| Geändert von | claude-code-hook |
| Grund | Claude Code Pre-Hook Backup vor Edit-Operation |
| Datei existiert |
Ja
|
Dateiinhalt
<?php
namespace Controller;
use Framework\Controller;
use Infrastructure\Config\DatabaseFactory;
class ConfigController extends Controller
{
private \PDO $db;
private const TYPES = ['author_profile', 'structure', 'organization', 'contract', 'rule', 'system_prompt'];
private const TYPE_LABELS = [
'author_profile' => 'Autorenprofil',
'structure' => 'Struktur',
'organization' => 'Organisation',
'contract' => 'Contract',
'rule' => 'Regel',
'system_prompt' => 'System-Prompt',
];
public function __construct()
{
$this->db = DatabaseFactory::content();
}
/**
* GET /config
*/
public function index(): void
{
$typeFilter = $_GET['type'] ?? '';
$statusFilter = $_GET['status'] ?? '';
$sql = 'SELECT c.*, p.name as parent_name
FROM content_config c
LEFT JOIN content_config p ON c.parent_id = p.id
WHERE 1=1';
$params = [];
if ($typeFilter !== '' && in_array($typeFilter, self::TYPES, true)) {
$sql .= ' AND c.type = ?';
$params[] = $typeFilter;
}
if ($statusFilter !== '' && in_array($statusFilter, ['draft', 'active', 'deprecated'], true)) {
$sql .= ' AND c.status = ?';
$params[] = $statusFilter;
}
$sql .= ' ORDER BY c.type, c.name';
$stmt = $this->db->prepare($sql);
$stmt->execute($params);
$configs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stats = $this->getStatistics();
$this->view('config.index', [
'title' => 'Content-Konfiguration',
'configs' => $configs,
'stats' => $stats,
'types' => self::TYPES,
'typeLabels' => self::TYPE_LABELS,
'currentType' => $typeFilter,
'currentStatus' => $statusFilter,
]);
}
/**
* GET /config/new
*/
public function configNew(): void
{
$parents = $this->getParentOptions();
$this->view('config.form', [
'title' => 'Neue Konfiguration',
'config' => null,
'types' => self::TYPES,
'typeLabels' => self::TYPE_LABELS,
'parents' => $parents,
'isEdit' => false,
]);
}
/**
* POST /config
*/
public function store(): void
{
$this->requireCsrf();
$type = $_POST['type'] ?? '';
$name = trim($_POST['name'] ?? '');
$slug = trim($_POST['slug'] ?? '');
$description = trim($_POST['description'] ?? '');
$content = $_POST['content'] ?? '{}';
$version = trim($_POST['version'] ?? '1.0');
$status = $_POST['status'] ?? 'draft';
$parentId = !empty($_POST['parent_id']) ? (int) $_POST['parent_id'] : null;
if (!in_array($type, self::TYPES, true) || $name === '' || $slug === '') {
$_SESSION['error'] = 'Typ, Name und Slug sind erforderlich.';
header('Location: /config/new');
exit;
}
// JSON validieren
$decoded = json_decode($content, true);
if ($decoded === null && $content !== 'null') {
$_SESSION['error'] = 'Ungültiges JSON-Format.';
header('Location: /config/new');
exit;
}
$stmt = $this->db->prepare(
'INSERT INTO content_config (type, name, slug, description, content, version, status, parent_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
);
$stmt->execute([$type, $name, $slug, $description ?: null, $content, $version, $status, $parentId]);
$id = $this->db->lastInsertId();
$_SESSION['success'] = 'Konfiguration erfolgreich erstellt.';
header('Location: /config/' . $id);
exit;
}
/**
* GET /config/{id}
*/
public function show(string $id): void
{
$config = $this->findById((int) $id);
if ($config === null) {
$this->notFound('Konfiguration nicht gefunden');
}
$children = $this->getChildren((int) $id);
$history = $this->getHistory((int) $id);
$this->view('config.show', [
'title' => $config['name'],
'config' => $config,
'children' => $children,
'history' => $history,
'typeLabels' => self::TYPE_LABELS,
]);
}
/**
* GET /config/{id}/edit
*/
public function edit(string $id): void
{
$config = $this->findById((int) $id);
if ($config === null) {
$this->notFound('Konfiguration nicht gefunden');
}
$parents = $this->getParentOptions((int) $id);
$this->view('config.form', [
'title' => 'Bearbeiten: ' . $config['name'],
'config' => $config,
'types' => self::TYPES,
'typeLabels' => self::TYPE_LABELS,
'parents' => $parents,
'isEdit' => true,
]);
}
/**
* POST /config/{id}
*/
public function update(string $id): void
{
$this->requireCsrf();
$config = $this->findById((int) $id);
if ($config === null) {
http_response_code(404);
echo 'Konfiguration nicht gefunden';
return;
}
$name = trim($_POST['name'] ?? '');
$slug = trim($_POST['slug'] ?? '');
$description = trim($_POST['description'] ?? '');
$content = $_POST['content'] ?? '{}';
$newVersion = trim($_POST['new_version'] ?? '');
$changeDescription = trim($_POST['change_description'] ?? '');
$status = $_POST['status'] ?? $config['status'];
$parentId = !empty($_POST['parent_id']) ? (int) $_POST['parent_id'] : null;
if ($name === '' || $slug === '' || $newVersion === '') {
$_SESSION['error'] = 'Name, Slug und neue Version sind erforderlich.';
header('Location: /config/' . $id . '/edit');
exit;
}
// JSON validieren
$decoded = json_decode($content, true);
if ($decoded === null && $content !== 'null') {
$_SESSION['error'] = 'Ungültiges JSON-Format.';
header('Location: /config/' . $id . '/edit');
exit;
}
// Alte Version in History speichern
$stmt = $this->db->prepare(
'INSERT INTO content_config_history (config_id, content, version, changed_by, change_description)
VALUES (?, ?, ?, ?, ?)'
);
$stmt->execute([
$id,
$config['content'],
$config['version'],
'web-ui',
$changeDescription ?: 'Update auf Version ' . $newVersion,
]);
// Config aktualisieren
$stmt = $this->db->prepare(
'UPDATE content_config
SET name = ?, slug = ?, description = ?, content = ?, version = ?, status = ?, parent_id = ?
WHERE id = ?'
);
$stmt->execute([$name, $slug, $description ?: null, $content, $newVersion, $status, $parentId, $id]);
$_SESSION['success'] = 'Konfiguration auf Version ' . $newVersion . ' aktualisiert.';
header('Location: /config/' . $id);
exit;
}
/**
* POST /config/{id}/delete
*/
public function delete(string $id): void
{
$this->requireCsrf();
$config = $this->findById((int) $id);
if ($config === null) {
http_response_code(404);
echo 'Konfiguration nicht gefunden';
return;
}
// Prüfen ob Children existieren
$stmt = $this->db->prepare('SELECT COUNT(*) FROM content_config WHERE parent_id = ?');
$stmt->execute([$id]);
if ($stmt->fetchColumn() > 0) {
$_SESSION['error'] = 'Kann nicht gelöscht werden: Es existieren verknüpfte Einträge.';
header('Location: /config/' . $id);
exit;
}
// History löschen
$stmt = $this->db->prepare('DELETE FROM content_config_history WHERE config_id = ?');
$stmt->execute([$id]);
// Config löschen
$stmt = $this->db->prepare('DELETE FROM content_config WHERE id = ?');
$stmt->execute([$id]);
$_SESSION['success'] = 'Konfiguration gelöscht.';
header('Location: /config');
exit;
}
// ========== Private Helpers ==========
private function findById(int $id): ?array
{
$stmt = $this->db->prepare(
'SELECT c.*, p.name as parent_name
FROM content_config c
LEFT JOIN content_config p ON c.parent_id = p.id
WHERE c.id = ?'
);
$stmt->execute([$id]);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
return $result !== false ? $result : null;
}
private function getStatistics(): array
{
$stats = ['total' => 0, 'by_type' => [], 'by_status' => []];
$stmt = $this->db->query('SELECT type, COUNT(*) as cnt FROM content_config GROUP BY type');
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
$stats['by_type'][$row['type']] = (int) $row['cnt'];
$stats['total'] += (int) $row['cnt'];
}
$stmt = $this->db->query('SELECT status, COUNT(*) as cnt FROM content_config GROUP BY status');
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
$stats['by_status'][$row['status']] = (int) $row['cnt'];
}
return $stats;
}
private function getParentOptions(?int $excludeId = null): array
{
$sql = 'SELECT id, type, name FROM content_config WHERE type IN ("contract", "organization") ORDER BY type, name';
$stmt = $this->db->query($sql);
$parents = [];
foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
if ($excludeId !== null && (int) $row['id'] === $excludeId) {
continue;
}
$parents[] = $row;
}
return $parents;
}
private function getChildren(int $parentId): array
{
$stmt = $this->db->prepare('SELECT * FROM content_config WHERE parent_id = ? ORDER BY name');
$stmt->execute([$parentId]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
private function getHistory(int $configId): array
{
$stmt = $this->db->prepare(
'SELECT * FROM content_config_history WHERE config_id = ? ORDER BY created_at DESC LIMIT 10'
);
$stmt->execute([$configId]);
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
Vollständig herunterladen
Aktionen
Andere Versionen dieser Datei
| ID |
Version |
Typ |
Größe |
Datum |
| 2139 |
22 |
modified |
6.1 KB |
2025-12-30 20:32 |
| 2138 |
21 |
modified |
6.1 KB |
2025-12-30 20:32 |
| 2137 |
20 |
modified |
5.9 KB |
2025-12-30 20:32 |
| 2136 |
19 |
modified |
5.7 KB |
2025-12-30 20:31 |
| 2135 |
18 |
modified |
5.6 KB |
2025-12-30 20:31 |
| 2129 |
17 |
modified |
5.6 KB |
2025-12-30 20:28 |
| 1763 |
16 |
modified |
5.3 KB |
2025-12-27 12:53 |
| 1762 |
15 |
modified |
5.1 KB |
2025-12-27 12:53 |
| 1761 |
14 |
modified |
4.9 KB |
2025-12-27 12:52 |
| 864 |
13 |
modified |
4.9 KB |
2025-12-23 08:50 |
| 687 |
12 |
modified |
4.8 KB |
2025-12-23 07:52 |
| 466 |
11 |
modified |
4.8 KB |
2025-12-22 10:31 |
| 465 |
10 |
modified |
4.8 KB |
2025-12-22 10:31 |
| 464 |
9 |
modified |
4.8 KB |
2025-12-22 10:31 |
| 452 |
8 |
modified |
6.7 KB |
2025-12-22 10:26 |
| 446 |
7 |
modified |
10.3 KB |
2025-12-22 10:18 |
| 307 |
6 |
modified |
10.3 KB |
2025-12-22 08:05 |
| 232 |
5 |
modified |
10.4 KB |
2025-12-22 01:45 |
| 231 |
4 |
modified |
10.4 KB |
2025-12-22 01:45 |
| 230 |
3 |
modified |
10.4 KB |
2025-12-22 01:45 |
| 229 |
2 |
modified |
10.5 KB |
2025-12-22 01:45 |
| 149 |
1 |
modified |
10.4 KB |
2025-12-21 02:30 |
← Zurück zur Übersicht