'Critic-Prompt', 'generate' => 'Generierungs-Prompt', 'revise' => 'Revisions-Prompt', 'system' => 'System-Prompt', 'other' => 'Sonstiges', ]; public function __construct() { $this->db = DatabaseFactory::content(); } /** * GET /prompts */ public function index(): void { $stmt = $this->db->query(' SELECT p.*, (SELECT COUNT(*) FROM critics c WHERE c.prompt_id = p.id) as critic_count FROM prompts p ORDER BY p.name '); $prompts = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stats = $this->getStatistics(); $this->view('prompts.index', [ 'title' => 'Prompts verwalten', 'prompts' => $prompts, 'stats' => $stats, 'promptTypes' => self::PROMPT_TYPES, ]); } /** * GET /prompts/new */ public function promptsNew(): void { $this->view('prompts.form', [ 'title' => 'Neuer Prompt', 'prompt' => null, 'promptTypes' => self::PROMPT_TYPES, 'isEdit' => false, ]); } /** * POST /prompts */ public function store(): void { $this->requireCsrf(); $name = trim($_POST['name'] ?? ''); $version = trim($_POST['version'] ?? '1.0'); $content = $_POST['content'] ?? ''; $isActive = isset($_POST['is_active']) ? 1 : 0; if ($name === '' || $content === '') { $_SESSION['error'] = 'Name und Inhalt sind erforderlich.'; header('Location: /prompts/new'); exit; } $stmt = $this->db->prepare(' INSERT INTO prompts (name, version, content, is_active) VALUES (?, ?, ?, ?) '); $stmt->execute([$name, $version, $content, $isActive]); $id = $this->db->lastInsertId(); $_SESSION['success'] = 'Prompt erfolgreich erstellt.'; header('Location: /prompts/' . $id); exit; } /** * GET /prompts/{id} */ public function show(string $id): void { $prompt = $this->findById((int) $id); if ($prompt === null) { $this->notFound('Prompt nicht gefunden'); } // Verknüpfte Critics laden $stmt = $this->db->prepare('SELECT * FROM critics WHERE prompt_id = ? ORDER BY name'); $stmt->execute([$id]); $linkedCritics = $stmt->fetchAll(\PDO::FETCH_ASSOC); $this->view('prompts.show', [ 'title' => $prompt['name'], 'prompt' => $prompt, 'linkedCritics' => $linkedCritics, 'promptTypes' => self::PROMPT_TYPES, ]); } /** * GET /prompts/{id}/edit */ public function edit(string $id): void { $prompt = $this->findById((int) $id); if ($prompt === null) { $this->notFound('Prompt nicht gefunden'); } $this->view('prompts.form', [ 'title' => 'Bearbeiten: ' . $prompt['name'], 'prompt' => $prompt, 'promptTypes' => self::PROMPT_TYPES, 'isEdit' => true, ]); } /** * POST /prompts/{id} */ public function update(string $id): void { $this->requireCsrf(); $prompt = $this->findById((int) $id); if ($prompt === null) { $this->notFound('Prompt nicht gefunden'); } $name = trim($_POST['name'] ?? ''); $version = trim($_POST['version'] ?? $prompt['version']); $content = $_POST['content'] ?? ''; $isActive = isset($_POST['is_active']) ? 1 : 0; if ($name === '' || $content === '') { $_SESSION['error'] = 'Name und Inhalt sind erforderlich.'; header('Location: /prompts/' . $id . '/edit'); exit; } $stmt = $this->db->prepare(' UPDATE prompts SET name = ?, version = ?, content = ?, is_active = ? WHERE id = ? '); $stmt->execute([$name, $version, $content, $isActive, $id]); $_SESSION['success'] = 'Prompt aktualisiert.'; header('Location: /prompts/' . $id); exit; } /** * POST /prompts/{id}/delete */ public function delete(string $id): void { $this->requireCsrf(); $prompt = $this->findById((int) $id); if ($prompt === null) { $this->notFound('Prompt nicht gefunden'); } // Prüfen ob Critics verknüpft sind $stmt = $this->db->prepare('SELECT COUNT(*) FROM critics WHERE prompt_id = ?'); $stmt->execute([$id]); $criticCount = (int) $stmt->fetchColumn(); if ($criticCount > 0) { $_SESSION['error'] = "Kann nicht gelöscht werden: {$criticCount} Critics verknüpft."; header('Location: /prompts/' . $id); exit; } $stmt = $this->db->prepare('DELETE FROM prompts WHERE id = ?'); $stmt->execute([$id]); $_SESSION['success'] = 'Prompt gelöscht.'; header('Location: /prompts'); exit; } /** * POST /prompts/{id}/duplicate */ public function duplicate(string $id): void { $this->requireCsrf(); $prompt = $this->findById((int) $id); if ($prompt === null) { $this->notFound('Prompt nicht gefunden'); } $newName = $prompt['name'] . ' (Kopie)'; $newVersion = '1.0'; $stmt = $this->db->prepare(' INSERT INTO prompts (name, version, content, is_active) VALUES (?, ?, ?, 0) '); $stmt->execute([$newName, $newVersion, $prompt['content']]); $newId = $this->db->lastInsertId(); $_SESSION['success'] = 'Prompt dupliziert.'; header('Location: /prompts/' . $newId . '/edit'); exit; } // ========== Private Helpers ========== private function findById(int $id): ?array { $stmt = $this->db->prepare('SELECT * FROM prompts WHERE id = ?'); $stmt->execute([$id]); $result = $stmt->fetch(\PDO::FETCH_ASSOC); return $result !== false ? $result : null; } private function getStatistics(): array { $stats = ['total' => 0, 'active' => 0, 'inactive' => 0, 'linked_to_critics' => 0]; $stmt = $this->db->query('SELECT COUNT(*) as cnt, SUM(is_active) as active FROM prompts'); $row = $stmt->fetch(\PDO::FETCH_ASSOC); $stats['total'] = (int) $row['cnt']; $stats['active'] = (int) $row['active']; $stats['inactive'] = $stats['total'] - $stats['active']; $stmt = $this->db->query('SELECT COUNT(DISTINCT prompt_id) FROM critics WHERE prompt_id IS NOT NULL'); $stats['linked_to_critics'] = (int) $stmt->fetchColumn(); return $stats; } }