{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/CriticsController.php",
"oldString": "<?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}",
"newString": "<?php\n\nnamespace Controller;\n\nuse Framework\\Controller;\nuse Infrastructure\\Persistence\\CriticsRepository;\nuse Infrastructure\\Persistence\\PromptsRepository;\n\nclass CriticsController extends Controller\n{\n private CriticsRepository $criticsRepo;\n private PromptsRepository $promptsRepo;\n\n public function __construct(\n ?CriticsRepository $criticsRepo = null,\n ?PromptsRepository $promptsRepo = null\n ) {\n $this->criticsRepo = $criticsRepo ?? new CriticsRepository();\n $this->promptsRepo = $promptsRepo ?? new PromptsRepository();\n }\n\n public function index(): void\n {\n $this->view('critics.index', [\n 'title' => 'Critics verwalten',\n 'critics' => $this->criticsRepo->findAll(),\n 'stats' => $this->criticsRepo->getStatistics(),\n ]);\n }\n\n public function criticsNew(): void\n {\n $this->view('critics.form', [\n 'title' => 'Neuer Critic',\n 'critic' => null,\n 'prompts' => $this->promptsRepo->findActivePrompts(),\n 'isEdit' => false,\n ]);\n }\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 $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));\n $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);\n\n $id = $this->criticsRepo->create($name, $fokusJson, $promptId, $sortOrder, $isActive);\n\n $_SESSION['success'] = 'Critic erfolgreich erstellt.';\n header('Location: \/critics\/' . $id);\n exit;\n }\n\n public function show(string $id): void\n {\n $critic = $this->criticsRepo->findById((int) $id);\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $prompt = null;\n if ($critic['prompt_id']) {\n $prompt = $this->promptsRepo->findById($critic['prompt_id']);\n }\n\n $this->view('critics.show', [\n 'title' => $critic['name'],\n 'critic' => $critic,\n 'prompt' => $prompt,\n 'recentCritiques' => $this->criticsRepo->findRecentCritiques((int) $id, 10),\n ]);\n }\n\n public function edit(string $id): void\n {\n $critic = $this->criticsRepo->findById((int) $id);\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $this->view('critics.form', [\n 'title' => 'Bearbeiten: ' . $critic['name'],\n 'critic' => $critic,\n 'prompts' => $this->promptsRepo->findActivePrompts(),\n 'isEdit' => true,\n ]);\n }\n\n public function update(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->criticsRepo->findById((int) $id);\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 $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));\n $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);\n\n $this->criticsRepo->update((int) $id, $name, $fokusJson, $promptId, $sortOrder, $isActive);\n\n $_SESSION['success'] = 'Critic aktualisiert.';\n header('Location: \/critics\/' . $id);\n exit;\n }\n\n public function delete(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->criticsRepo->findById((int) $id);\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $critiqueCount = $this->criticsRepo->countCritiques((int) $id);\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 $this->criticsRepo->delete((int) $id);\n\n $_SESSION['success'] = 'Critic gelöscht.';\n header('Location: \/critics');\n exit;\n }\n\n public function toggle(string $id): void\n {\n $this->requireCsrf();\n\n $critic = $this->criticsRepo->findById((int) $id);\n if ($critic === null) {\n $this->notFound('Critic nicht gefunden');\n }\n\n $newStatus = $critic['is_active'] ? 0 : 1;\n $this->criticsRepo->toggleActive((int) $id, $newStatus);\n\n $statusText = $newStatus ? 'aktiviert' : 'deaktiviert';\n $_SESSION['success'] = \"Critic {$statusText}.\";\n header('Location: \/critics');\n exit;\n }\n}",
"originalFile": "<?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",
"structuredPatch": [
{
"oldStart": 3,
"oldLines": 57,
"newStart": 3,
"newLines": 41,
"lines": [
" namespace Controller;",
" ",
" use Framework\\Controller;",
"-use Infrastructure\\Config\\DatabaseFactory;",
"+use Infrastructure\\Persistence\\CriticsRepository;",
"+use Infrastructure\\Persistence\\PromptsRepository;",
" ",
" class CriticsController extends Controller",
" {",
"- private \\PDO $db;",
"+ private CriticsRepository $criticsRepo;",
"+ private PromptsRepository $promptsRepo;",
" ",
"- public function __construct()",
"- {",
"- $this->db = DatabaseFactory::content();",
"+ public function __construct(",
"+ ?CriticsRepository $criticsRepo = null,",
"+ ?PromptsRepository $promptsRepo = null",
"+ ) {",
"+ $this->criticsRepo = $criticsRepo ?? new CriticsRepository();",
"+ $this->promptsRepo = $promptsRepo ?? new PromptsRepository();",
" }",
" ",
"- \/**",
"- * GET \/critics",
"- *\/",
" public function index(): void",
" {",
"- $stmt = $this->db->query('",
"- SELECT c.*, p.name as prompt_name",
"- FROM critics c",
"- LEFT JOIN prompts p ON c.prompt_id = p.id",
"- ORDER BY c.sort_order, c.name",
"- ');",
"- $critics = $stmt->fetchAll(\\PDO::FETCH_ASSOC);",
"-",
"- $stats = $this->getStatistics();",
"-",
" $this->view('critics.index', [",
" 'title' => 'Critics verwalten',",
"- 'critics' => $critics,",
"- 'stats' => $stats,",
"+ 'critics' => $this->criticsRepo->findAll(),",
"+ 'stats' => $this->criticsRepo->getStatistics(),",
" ]);",
" }",
" ",
"- \/**",
"- * GET \/critics\/new",
"- *\/",
" public function criticsNew(): void",
" {",
"- $prompts = $this->getAvailablePrompts();",
"-",
" $this->view('critics.form', [",
" 'title' => 'Neuer Critic',",
" 'critic' => null,",
"- 'prompts' => $prompts,",
"+ 'prompts' => $this->promptsRepo->findActivePrompts(),",
" 'isEdit' => false,",
" ]);",
" }",
" ",
"- \/**",
"- * POST \/critics",
"- *\/",
" public function store(): void",
" {",
" $this->requireCsrf();"
]
},
{
"oldStart": 70,
"oldLines": 92,
"newStart": 54,
"newLines": 56,
"lines": [
" exit;",
" }",
" ",
"- \/\/ Fokus als JSON Array speichern",
" $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));",
" $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);",
" ",
"- $stmt = $this->db->prepare('",
"- INSERT INTO critics (name, fokus, prompt_id, sort_order, is_active)",
"- VALUES (?, ?, ?, ?, ?)",
"- ');",
"- $stmt->execute([$name, $fokusJson, $promptId, $sortOrder, $isActive]);",
"- $id = $this->db->lastInsertId();",
"+ $id = $this->criticsRepo->create($name, $fokusJson, $promptId, $sortOrder, $isActive);",
" ",
" $_SESSION['success'] = 'Critic erfolgreich erstellt.';",
" header('Location: \/critics\/' . $id);",
" exit;",
" }",
" ",
"- \/**",
"- * GET \/critics\/{id}",
"- *\/",
" public function show(string $id): void",
" {",
"- $critic = $this->findById((int) $id);",
"-",
"+ $critic = $this->criticsRepo->findById((int) $id);",
" if ($critic === null) {",
" $this->notFound('Critic nicht gefunden');",
" }",
" ",
"- \/\/ Prompt-Details laden",
" $prompt = null;",
" if ($critic['prompt_id']) {",
"- $stmt = $this->db->prepare('SELECT * FROM prompts WHERE id = ?');",
"- $stmt->execute([$critic['prompt_id']]);",
"- $prompt = $stmt->fetch(\\PDO::FETCH_ASSOC);",
"+ $prompt = $this->promptsRepo->findById($critic['prompt_id']);",
" }",
" ",
"- \/\/ Letzte Critiques anzeigen",
"- $stmt = $this->db->prepare('",
"- SELECT cc.*, cv.version_number, co.title as order_title",
"- FROM content_critiques cc",
"- JOIN content_versions cv ON cc.version_id = cv.id",
"- JOIN content_orders co ON cv.order_id = co.id",
"- WHERE cc.critic_id = ?",
"- ORDER BY cc.created_at DESC",
"- LIMIT 10",
"- ');",
"- $stmt->execute([$id]);",
"- $recentCritiques = $stmt->fetchAll(\\PDO::FETCH_ASSOC);",
"-",
" $this->view('critics.show', [",
" 'title' => $critic['name'],",
" 'critic' => $critic,",
" 'prompt' => $prompt,",
"- 'recentCritiques' => $recentCritiques,",
"+ 'recentCritiques' => $this->criticsRepo->findRecentCritiques((int) $id, 10),",
" ]);",
" }",
" ",
"- \/**",
"- * GET \/critics\/{id}\/edit",
"- *\/",
" public function edit(string $id): void",
" {",
"- $critic = $this->findById((int) $id);",
"-",
"+ $critic = $this->criticsRepo->findById((int) $id);",
" if ($critic === null) {",
" $this->notFound('Critic nicht gefunden');",
" }",
" ",
"- $prompts = $this->getAvailablePrompts();",
"-",
" $this->view('critics.form', [",
" 'title' => 'Bearbeiten: ' . $critic['name'],",
" 'critic' => $critic,",
"- 'prompts' => $prompts,",
"+ 'prompts' => $this->promptsRepo->findActivePrompts(),",
" 'isEdit' => true,",
" ]);",
" }",
" ",
"- \/**",
"- * POST \/critics\/{id}",
"- *\/",
" public function update(string $id): void",
" {",
" $this->requireCsrf();",
" ",
"- $critic = $this->findById((int) $id);",
"-",
"+ $critic = $this->criticsRepo->findById((int) $id);",
" if ($critic === null) {",
" $this->notFound('Critic nicht gefunden');",
" }"
]
},
{
"oldStart": 172,
"oldLines": 118,
"newStart": 120,
"newLines": 54,
"lines": [
" exit;",
" }",
" ",
"- \/\/ Fokus als JSON Array speichern",
" $fokusArray = array_filter(array_map('trim', explode(\"\\n\", $fokus)));",
" $fokusJson = json_encode(array_values($fokusArray), JSON_UNESCAPED_UNICODE);",
" ",
"- $stmt = $this->db->prepare('",
"- UPDATE critics",
"- SET name = ?, fokus = ?, prompt_id = ?, sort_order = ?, is_active = ?",
"- WHERE id = ?",
"- ');",
"- $stmt->execute([$name, $fokusJson, $promptId, $sortOrder, $isActive, $id]);",
"+ $this->criticsRepo->update((int) $id, $name, $fokusJson, $promptId, $sortOrder, $isActive);",
" ",
" $_SESSION['success'] = 'Critic aktualisiert.';",
" header('Location: \/critics\/' . $id);",
" exit;",
" }",
" ",
"- \/**",
"- * POST \/critics\/{id}\/delete",
"- *\/",
" public function delete(string $id): void",
" {",
" $this->requireCsrf();",
" ",
"- $critic = $this->findById((int) $id);",
"-",
"+ $critic = $this->criticsRepo->findById((int) $id);",
" if ($critic === null) {",
" $this->notFound('Critic nicht gefunden');",
" }",
" ",
"- \/\/ Prüfen ob Critiques existieren",
"- $stmt = $this->db->prepare('SELECT COUNT(*) FROM content_critiques WHERE critic_id = ?');",
"- $stmt->execute([$id]);",
"- $critiqueCount = (int) $stmt->fetchColumn();",
"-",
"+ $critiqueCount = $this->criticsRepo->countCritiques((int) $id);",
" if ($critiqueCount > 0) {",
" $_SESSION['error'] = \"Kann nicht gelöscht werden: {$critiqueCount} Critiques verknüpft.\";",
" header('Location: \/critics\/' . $id);",
" exit;",
" }",
" ",
"- $stmt = $this->db->prepare('DELETE FROM critics WHERE id = ?');",
"- $stmt->execute([$id]);",
"+ $this->criticsRepo->delete((int) $id);",
" ",
" $_SESSION['success'] = 'Critic gelöscht.';",
" header('Location: \/critics');",
" exit;",
" }",
" ",
"- \/**",
"- * POST \/critics\/{id}\/toggle",
"- *\/",
" public function toggle(string $id): void",
" {",
" $this->requireCsrf();",
" ",
"- $critic = $this->findById((int) $id);",
"-",
"+ $critic = $this->criticsRepo->findById((int) $id);",
" if ($critic === null) {",
" $this->notFound('Critic nicht gefunden');",
" }",
" ",
" $newStatus = $critic['is_active'] ? 0 : 1;",
"- $stmt = $this->db->prepare('UPDATE critics SET is_active = ? WHERE id = ?');",
"- $stmt->execute([$newStatus, $id]);",
"+ $this->criticsRepo->toggleActive((int) $id, $newStatus);",
" ",
" $statusText = $newStatus ? 'aktiviert' : 'deaktiviert';",
" $_SESSION['success'] = \"Critic {$statusText}.\";",
" header('Location: \/critics');",
" exit;",
" }",
"-",
"- \/\/ ========== Private Helpers ==========",
"-",
"- private function findById(int $id): ?array",
"- {",
"- $stmt = $this->db->prepare('",
"- SELECT c.*, p.name as prompt_name",
"- FROM critics c",
"- LEFT JOIN prompts p ON c.prompt_id = p.id",
"- WHERE c.id = ?",
"- ');",
"- $stmt->execute([$id]);",
"- $result = $stmt->fetch(\\PDO::FETCH_ASSOC);",
"-",
"- return $result !== false ? $result : null;",
"- }",
"-",
"- private function getAvailablePrompts(): array",
"- {",
"- $stmt = $this->db->query('",
"- SELECT id, name, version",
"- FROM prompts",
"- WHERE is_active = 1",
"- ORDER BY name",
"- ');",
"-",
"- return $stmt->fetchAll(\\PDO::FETCH_ASSOC);",
"- }",
"-",
"- private function getStatistics(): array",
"- {",
"- $stats = ['total' => 0, 'active' => 0, 'inactive' => 0, 'total_critiques' => 0];",
"-",
"- $stmt = $this->db->query('SELECT COUNT(*) as cnt, SUM(is_active) as active FROM critics');",
"- $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(*) FROM content_critiques');",
"- $stats['total_critiques'] = (int) $stmt->fetchColumn();",
"-",
"- return $stats;",
"- }",
" }"
]
}
],
"userModified": false,
"replaceAll": false
}
}