{
"event": "PostToolUse",
"raw_data": {
"session_id": "18ef5bf3-e872-4052-897e-53d6dc45b0b9",
"transcript_path": "\/root\/.claude\/projects\/-var-www\/18ef5bf3-e872-4052-897e-53d6dc45b0b9.jsonl",
"cwd": "\/var\/www",
"permission_mode": "acceptEdits",
"hook_event_name": "PostToolUse",
"tool_name": "Read",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/CriticsController.php"
},
"tool_response": {
"type": "text",
"file": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/CriticsController.php",
"content": "<?php\n\nnamespace Controller;\n\nuse Framework\\Controller;\nuse Infrastructure\\Config\\DatabaseFactory;\n\nclass CriticsController extends Controller\n{\n private \\PDO $db;\n\n public function __construct()\n {\n $this->db = DatabaseFactory::content();\n }\n\n \/**\n * GET \/critics\n *\/\n public function index(): void\n {\n $stmt = $this->db->query('\n SELECT c.*, p.name as prompt_name\n FROM critics c\n LEFT JOIN prompts p ON c.prompt_id = p.id\n ORDER BY c.sort_order, c.name\n ');\n $critics = $stmt->fetchAll(\\PDO::FETCH_ASSOC);\n\n $stats = $this->getStatistics();\n\n $this->view('critics.index', [\n 'title' => 'Critics verwalten',\n 'critics' => $critics,\n 'stats' => $stats,\n ]);\n }\n\n \/**\n * GET \/critics\/new\n *\/\n public function criticsNew(): void\n {\n $prompts = $this->getAvailablePrompts();\n\n $this->view('critics.form', [\n 'title' => 'Neuer Critic',\n 'critic' => null,\n 'prompts' => $prompts,\n 'isEdit' => false,\n ]);\n }\n\n \/**\n * POST \/critics\n *\/\n public function store(): void\n {\n $this->requireCsrf();\n\n $name = trim($_POST['name'] ?? '');\n $fokus = $_POST['fokus'] ?? '';\n $promptId = !empty($_POST['prompt_id']) ? (int) $_POST['prompt_id'] : null;\n $sortOrder = (int) ($_POST['sort_order'] ?? 0);\n $isActive = isset($_POST['is_active']) ? 1 : 0;\n\n if ($name === '') {\n $_SESSION['error'] = 'Name ist erforderlich.';\n header('Location: \/critics\/new');\n exit;\n }\n\n \/\/ Fokus als JSON Array speichern\n $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));\n $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);\n\n $stmt = $this->db->prepare('\n INSERT INTO critics (name, fokus, prompt_id, sort_order, is_active)\n VALUES (?, ?, ?, ?, ?)\n ');\n $stmt->execute([$name, $fokusJson, $promptId, $sortOrder, $isActive]);\n $id = $this->db->lastInsertId();\n\n $_SESSION['success'] = 'Critic erfolgreich erstellt.';\n header('Location: \/critics\/' . $id);\n exit;\n }\n\n \/**\n * GET \/critics\/{id}\n *\/\n public function show(string $id): void\n {\n $critic = $this->findById((int) $id);\n\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n \/\/ Prompt-Details laden\n $prompt = null;\n if ($critic['prompt_id']) {\n $stmt = $this->db->prepare('SELECT * FROM prompts WHERE id = ?');\n $stmt->execute([$critic['prompt_id']]);\n $prompt = $stmt->fetch(\\PDO::FETCH_ASSOC);\n }\n\n \/\/ Letzte Critiques anzeigen\n $stmt = $this->db->prepare('\n SELECT cc.*, cv.version_number, co.title as order_title\n FROM content_critiques cc\n JOIN content_versions cv ON cc.version_id = cv.id\n JOIN content_orders co ON cv.order_id = co.id\n WHERE cc.critic_id = ?\n ORDER BY cc.created_at DESC\n LIMIT 10\n ');\n $stmt->execute([$id]);\n $recentCritiques = $stmt->fetchAll(\\PDO::FETCH_ASSOC);\n\n $this->view('critics.show', [\n 'title' => $critic['name'],\n 'critic' => $critic,\n 'prompt' => $prompt,\n 'recentCritiques' => $recentCritiques,\n ]);\n }\n\n \/**\n * GET \/critics\/{id}\/edit\n *\/\n public function edit(string $id): void\n {\n $critic = $this->findById((int) $id);\n\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $prompts = $this->getAvailablePrompts();\n\n $this->view('critics.form', [\n 'title' => 'Bearbeiten: ' . $critic['name'],\n 'critic' => $critic,\n 'prompts' => $prompts,\n 'isEdit' => true,\n ]);\n }\n\n \/**\n * POST \/critics\/{id}\n *\/\n public function update(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->findById((int) $id);\n\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $name = trim($_POST['name'] ?? '');\n $fokus = $_POST['fokus'] ?? '';\n $promptId = !empty($_POST['prompt_id']) ? (int) $_POST['prompt_id'] : null;\n $sortOrder = (int) ($_POST['sort_order'] ?? 0);\n $isActive = isset($_POST['is_active']) ? 1 : 0;\n\n if ($name === '') {\n $_SESSION['error'] = 'Name ist erforderlich.';\n header('Location: \/critics\/' . $id . '\/edit');\n exit;\n }\n\n \/\/ Fokus als JSON Array speichern\n $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));\n $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);\n\n $stmt = $this->db->prepare('\n UPDATE critics\n SET name = ?, fokus = ?, prompt_id = ?, sort_order = ?, is_active = ?\n WHERE id = ?\n ');\n $stmt->execute([$name, $fokusJson, $promptId, $sortOrder, $isActive, $id]);\n\n $_SESSION['success'] = 'Critic aktualisiert.';\n header('Location: \/critics\/' . $id);\n exit;\n }\n\n \/**\n * POST \/critics\/{id}\/delete\n *\/\n public function delete(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->findById((int) $id);\n\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n \/\/ Prüfen ob Critiques existieren\n $stmt = $this->db->prepare('SELECT COUNT(*) FROM content_critiques WHERE critic_id = ?');\n $stmt->execute([$id]);\n $critiqueCount = (int) $stmt->fetchColumn();\n\n if ($critiqueCount > 0) {\n $_SESSION['error'] = \"Kann nicht gelöscht werden: {$critiqueCount} Critiques verknüpft.\";\n header('Location: \/critics\/' . $id);\n exit;\n }\n\n $stmt = $this->db->prepare('DELETE FROM critics WHERE id = ?');\n $stmt->execute([$id]);\n\n $_SESSION['success'] = 'Critic gelöscht.';\n header('Location: \/critics');\n exit;\n }\n\n \/**\n * POST \/critics\/{id}\/toggle\n *\/\n public function toggle(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->findById((int) $id);\n\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $newStatus = $critic['is_active'] ? 0 : 1;\n $stmt = $this->db->prepare('UPDATE critics SET is_active = ? WHERE id = ?');\n $stmt->execute([$newStatus, $id]);\n\n $statusText = $newStatus ? 'aktiviert' : 'deaktiviert';\n $_SESSION['success'] = \"Critic {$statusText}.\";\n header('Location: \/critics');\n exit;\n }\n\n \/\/ ========== Private Helpers ==========\n\n private function findById(int $id): ?array\n {\n $stmt = $this->db->prepare('\n SELECT c.*, p.name as prompt_name\n FROM critics c\n LEFT JOIN prompts p ON c.prompt_id = p.id\n WHERE c.id = ?\n ');\n $stmt->execute([$id]);\n $result = $stmt->fetch(\\PDO::FETCH_ASSOC);\n\n return $result !== false ? $result : null;\n }\n\n private function getAvailablePrompts(): array\n {\n $stmt = $this->db->query('\n SELECT id, name, version\n FROM prompts\n WHERE is_active = 1\n ORDER BY name\n ');\n\n return $stmt->fetchAll(\\PDO::FETCH_ASSOC);\n }\n\n private function getStatistics(): array\n {\n $stats = ['total' => 0, 'active' => 0, 'inactive' => 0, 'total_critiques' => 0];\n\n $stmt = $this->db->query('SELECT COUNT(*) as cnt, SUM(is_active) as active FROM critics');\n $row = $stmt->fetch(\\PDO::FETCH_ASSOC);\n $stats['total'] = (int) $row['cnt'];\n $stats['active'] = (int) $row['active'];\n $stats['inactive'] = $stats['total'] - $stats['active'];\n\n $stmt = $this->db->query('SELECT COUNT(*) FROM content_critiques');\n $stats['total_critiques'] = (int) $stmt->fetchColumn();\n\n return $stats;\n }\n}\n",
"numLines": 290,
"startLine": 1,
"totalLines": 290
}
},
"tool_use_id": "toolu_01YMXx45DAddG5i15nXCNYyf"
}
}