{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/ProtokollController.php",
"old_string": "<?php\n\nnamespace Controller;\n\nuse Domain\\ValueObject\\Pagination;\nuse Framework\\Controller;\nuse Infrastructure\\Config\\DatabaseFactory;\n\n\/**\n * ProtokollController - KI-Protokoll Ansicht\n *\n * Zeigt KI-Interaktionen aus ki_dev.protokoll.\n * Nur Lesen, kein Erstellen\/Bearbeiten.\n *\/\nclass ProtokollController extends Controller\n{\n private \\PDO $db;\n\n public function __construct()\n {\n $this->db = DatabaseFactory::dev();\n }\n\n \/**\n * GET \/protokoll\n * Liste aller Protokoll-Einträge\n *\/\n public function index(): void\n {\n \/\/ Statistiken\n $stats = $this->db->query(\n 'SELECT\n COUNT(*) as total,\n SUM(CASE WHEN status = \"completed\" THEN 1 ELSE 0 END) as completed,\n SUM(CASE WHEN status = \"error\" THEN 1 ELSE 0 END) as errors,\n COALESCE(SUM(tokens_total), 0) as tokens_total,\n COALESCE(SUM(duration_ms), 0) as duration_total\n FROM protokoll'\n )->fetch();\n\n \/\/ Einträge mit Pagination\n $pagination = Pagination::fromRequest(50);\n\n $search = $this->getString('search');\n $status = $this->getString('status');\n $model = $this->getString('model');\n\n $sql = 'SELECT id, timestamp, client_name, model_name, status, tokens_total, duration_ms,\n LEFT(request, 200) as request_preview\n FROM protokoll WHERE 1=1';\n $countSql = 'SELECT COUNT(*) FROM protokoll WHERE 1=1';\n $params = [];\n\n if ($search !== '') {\n $sql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $countSql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $params['search'] = '%' . $search . '%';\n $params['search2'] = '%' . $search . '%';\n $params['search3'] = '%' . $search . '%';\n }\n\n if ($status !== '') {\n $sql .= ' AND status = :status';\n $countSql .= ' AND status = :status';\n $params['status'] = $status;\n }\n\n if ($model !== '') {\n $sql .= ' AND model_name = :model';\n $countSql .= ' AND model_name = :model';\n $params['model'] = $model;\n }\n\n \/\/ Total count\n $countStmt = $this->db->prepare($countSql);\n $countStmt->execute($params);\n $totalCount = (int) $countStmt->fetchColumn();\n $pagination = $pagination->withTotal($totalCount);\n\n \/\/ Fetch entries\n $sql .= ' ORDER BY timestamp DESC LIMIT :limit OFFSET :offset';\n $stmt = $this->db->prepare($sql);\n foreach ($params as $key => $value) {\n $stmt->bindValue(':' . $key, $value);\n }\n $stmt->bindValue(':limit', $pagination->limit, \\PDO::PARAM_INT);\n $stmt->bindValue(':offset', $pagination->offset, \\PDO::PARAM_INT);\n $stmt->execute();\n $entries = $stmt->fetchAll();\n\n \/\/ Modelle für Filter\n $models = $this->db->query(\n 'SELECT DISTINCT model_name FROM protokoll WHERE model_name IS NOT NULL ORDER BY model_name'\n )->fetchAll(\\PDO::FETCH_COLUMN);\n\n $this->view('protokoll.index', [\n 'title' => 'KI-Protokoll',\n 'stats' => $stats,\n 'entries' => $entries,\n 'models' => $models,\n 'currentSearch' => $search,\n 'currentStatus' => $status,\n 'currentModel' => $model,\n 'currentPage' => $pagination->page,\n 'totalCount' => $pagination->totalCount,\n 'totalPages' => $pagination->totalPages(),\n ]);\n }\n\n \/**\n * GET \/protokoll\/{id}\n * Detail-Ansicht eines Eintrags\n *\/\n public function show(string $id): void\n {\n $stmt = $this->db->prepare('SELECT * FROM protokoll WHERE id = :id');\n $stmt->execute(['id' => (int) $id]);\n $entry = $stmt->fetch();\n\n if ($entry === false) {\n $this->notFound('Protokoll-Eintrag nicht gefunden');\n }\n\n \/\/ Request\/Response als formatiertes JSON\n $entry['request_formatted'] = $this->formatJson($entry['request']);\n $entry['response_formatted'] = $this->formatJson($entry['response']);\n\n \/\/ Nachbar-Einträge für Navigation\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id < :id ORDER BY id DESC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $prevEntry = $stmt->fetch();\n\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id > :id ORDER BY id ASC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $nextEntry = $stmt->fetch();\n\n $this->view('protokoll.show', [\n 'title' => 'Protokoll #' . $id,\n 'entry' => $entry,\n 'prevEntry' => $prevEntry,\n 'nextEntry' => $nextEntry,\n ]);\n }\n\n \/**\n * JSON formatieren für Anzeige\n *\/\n private function formatJson(?string $json): string\n {\n if ($json === null || $json === '') {\n return '-';\n }\n\n $decoded = json_decode($json, true);\n if ($decoded === null) {\n return htmlspecialchars($json);\n }\n\n $formatted = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n\n return $formatted !== false ? $formatted : htmlspecialchars($json);\n }\n}",
"new_string": "<?php\n\nnamespace Controller;\n\nuse Domain\\ValueObject\\Pagination;\nuse Framework\\Controller;\nuse Infrastructure\\Persistence\\KiProtokollRepository;\n\nclass ProtokollController extends Controller\n{\n private KiProtokollRepository $protokollRepo;\n\n public function __construct(?KiProtokollRepository $protokollRepo = null)\n {\n $this->protokollRepo = $protokollRepo ?? new KiProtokollRepository();\n }\n\n public function index(): void\n {\n $pagination = Pagination::fromRequest(50);\n\n $search = $this->getString('search');\n $status = $this->getString('status');\n $model = $this->getString('model');\n\n $searchVal = $search !== '' ? $search : null;\n $statusVal = $status !== '' ? $status : null;\n $modelVal = $model !== '' ? $model : null;\n\n $totalCount = $this->protokollRepo->countFiltered($searchVal, $statusVal, $modelVal);\n $pagination = $pagination->withTotal($totalCount);\n\n $entries = $this->protokollRepo->findPaginated(\n $searchVal,\n $statusVal,\n $modelVal,\n $pagination->limit,\n $pagination->offset\n );\n\n $this->view('protokoll.index', [\n 'title' => 'KI-Protokoll',\n 'stats' => $this->protokollRepo->getStatistics(),\n 'entries' => $entries,\n 'models' => $this->protokollRepo->getDistinctModels(),\n 'currentSearch' => $search,\n 'currentStatus' => $status,\n 'currentModel' => $model,\n 'currentPage' => $pagination->page,\n 'totalCount' => $pagination->totalCount,\n 'totalPages' => $pagination->totalPages(),\n ]);\n }\n\n public function show(string $id): void\n {\n $entry = $this->protokollRepo->findById((int) $id);\n if ($entry === null) {\n $this->notFound('Protokoll-Eintrag nicht gefunden');\n }\n\n $entry['request_formatted'] = $this->formatJson($entry['request']);\n $entry['response_formatted'] = $this->formatJson($entry['response']);\n\n $prevId = $this->protokollRepo->findPreviousId((int) $id);\n $nextId = $this->protokollRepo->findNextId((int) $id);\n\n $this->view('protokoll.show', [\n 'title' => 'Protokoll #' . $id,\n 'entry' => $entry,\n 'prevEntry' => $prevId !== null ? ['id' => $prevId] : false,\n 'nextEntry' => $nextId !== null ? ['id' => $nextId] : false,\n ]);\n }\n\n private function formatJson(?string $json): string\n {\n if ($json === null || $json === '') {\n return '-';\n }\n\n $decoded = json_decode($json, true);\n if ($decoded === null) {\n return htmlspecialchars($json);\n }\n\n $formatted = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n\n return $formatted !== false ? $formatted : htmlspecialchars($json);\n }\n}"
}
}
{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/ProtokollController.php",
"oldString": "<?php\n\nnamespace Controller;\n\nuse Domain\\ValueObject\\Pagination;\nuse Framework\\Controller;\nuse Infrastructure\\Config\\DatabaseFactory;\n\n\/**\n * ProtokollController - KI-Protokoll Ansicht\n *\n * Zeigt KI-Interaktionen aus ki_dev.protokoll.\n * Nur Lesen, kein Erstellen\/Bearbeiten.\n *\/\nclass ProtokollController extends Controller\n{\n private \\PDO $db;\n\n public function __construct()\n {\n $this->db = DatabaseFactory::dev();\n }\n\n \/**\n * GET \/protokoll\n * Liste aller Protokoll-Einträge\n *\/\n public function index(): void\n {\n \/\/ Statistiken\n $stats = $this->db->query(\n 'SELECT\n COUNT(*) as total,\n SUM(CASE WHEN status = \"completed\" THEN 1 ELSE 0 END) as completed,\n SUM(CASE WHEN status = \"error\" THEN 1 ELSE 0 END) as errors,\n COALESCE(SUM(tokens_total), 0) as tokens_total,\n COALESCE(SUM(duration_ms), 0) as duration_total\n FROM protokoll'\n )->fetch();\n\n \/\/ Einträge mit Pagination\n $pagination = Pagination::fromRequest(50);\n\n $search = $this->getString('search');\n $status = $this->getString('status');\n $model = $this->getString('model');\n\n $sql = 'SELECT id, timestamp, client_name, model_name, status, tokens_total, duration_ms,\n LEFT(request, 200) as request_preview\n FROM protokoll WHERE 1=1';\n $countSql = 'SELECT COUNT(*) FROM protokoll WHERE 1=1';\n $params = [];\n\n if ($search !== '') {\n $sql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $countSql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $params['search'] = '%' . $search . '%';\n $params['search2'] = '%' . $search . '%';\n $params['search3'] = '%' . $search . '%';\n }\n\n if ($status !== '') {\n $sql .= ' AND status = :status';\n $countSql .= ' AND status = :status';\n $params['status'] = $status;\n }\n\n if ($model !== '') {\n $sql .= ' AND model_name = :model';\n $countSql .= ' AND model_name = :model';\n $params['model'] = $model;\n }\n\n \/\/ Total count\n $countStmt = $this->db->prepare($countSql);\n $countStmt->execute($params);\n $totalCount = (int) $countStmt->fetchColumn();\n $pagination = $pagination->withTotal($totalCount);\n\n \/\/ Fetch entries\n $sql .= ' ORDER BY timestamp DESC LIMIT :limit OFFSET :offset';\n $stmt = $this->db->prepare($sql);\n foreach ($params as $key => $value) {\n $stmt->bindValue(':' . $key, $value);\n }\n $stmt->bindValue(':limit', $pagination->limit, \\PDO::PARAM_INT);\n $stmt->bindValue(':offset', $pagination->offset, \\PDO::PARAM_INT);\n $stmt->execute();\n $entries = $stmt->fetchAll();\n\n \/\/ Modelle für Filter\n $models = $this->db->query(\n 'SELECT DISTINCT model_name FROM protokoll WHERE model_name IS NOT NULL ORDER BY model_name'\n )->fetchAll(\\PDO::FETCH_COLUMN);\n\n $this->view('protokoll.index', [\n 'title' => 'KI-Protokoll',\n 'stats' => $stats,\n 'entries' => $entries,\n 'models' => $models,\n 'currentSearch' => $search,\n 'currentStatus' => $status,\n 'currentModel' => $model,\n 'currentPage' => $pagination->page,\n 'totalCount' => $pagination->totalCount,\n 'totalPages' => $pagination->totalPages(),\n ]);\n }\n\n \/**\n * GET \/protokoll\/{id}\n * Detail-Ansicht eines Eintrags\n *\/\n public function show(string $id): void\n {\n $stmt = $this->db->prepare('SELECT * FROM protokoll WHERE id = :id');\n $stmt->execute(['id' => (int) $id]);\n $entry = $stmt->fetch();\n\n if ($entry === false) {\n $this->notFound('Protokoll-Eintrag nicht gefunden');\n }\n\n \/\/ Request\/Response als formatiertes JSON\n $entry['request_formatted'] = $this->formatJson($entry['request']);\n $entry['response_formatted'] = $this->formatJson($entry['response']);\n\n \/\/ Nachbar-Einträge für Navigation\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id < :id ORDER BY id DESC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $prevEntry = $stmt->fetch();\n\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id > :id ORDER BY id ASC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $nextEntry = $stmt->fetch();\n\n $this->view('protokoll.show', [\n 'title' => 'Protokoll #' . $id,\n 'entry' => $entry,\n 'prevEntry' => $prevEntry,\n 'nextEntry' => $nextEntry,\n ]);\n }\n\n \/**\n * JSON formatieren für Anzeige\n *\/\n private function formatJson(?string $json): string\n {\n if ($json === null || $json === '') {\n return '-';\n }\n\n $decoded = json_decode($json, true);\n if ($decoded === null) {\n return htmlspecialchars($json);\n }\n\n $formatted = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n\n return $formatted !== false ? $formatted : htmlspecialchars($json);\n }\n}",
"newString": "<?php\n\nnamespace Controller;\n\nuse Domain\\ValueObject\\Pagination;\nuse Framework\\Controller;\nuse Infrastructure\\Persistence\\KiProtokollRepository;\n\nclass ProtokollController extends Controller\n{\n private KiProtokollRepository $protokollRepo;\n\n public function __construct(?KiProtokollRepository $protokollRepo = null)\n {\n $this->protokollRepo = $protokollRepo ?? new KiProtokollRepository();\n }\n\n public function index(): void\n {\n $pagination = Pagination::fromRequest(50);\n\n $search = $this->getString('search');\n $status = $this->getString('status');\n $model = $this->getString('model');\n\n $searchVal = $search !== '' ? $search : null;\n $statusVal = $status !== '' ? $status : null;\n $modelVal = $model !== '' ? $model : null;\n\n $totalCount = $this->protokollRepo->countFiltered($searchVal, $statusVal, $modelVal);\n $pagination = $pagination->withTotal($totalCount);\n\n $entries = $this->protokollRepo->findPaginated(\n $searchVal,\n $statusVal,\n $modelVal,\n $pagination->limit,\n $pagination->offset\n );\n\n $this->view('protokoll.index', [\n 'title' => 'KI-Protokoll',\n 'stats' => $this->protokollRepo->getStatistics(),\n 'entries' => $entries,\n 'models' => $this->protokollRepo->getDistinctModels(),\n 'currentSearch' => $search,\n 'currentStatus' => $status,\n 'currentModel' => $model,\n 'currentPage' => $pagination->page,\n 'totalCount' => $pagination->totalCount,\n 'totalPages' => $pagination->totalPages(),\n ]);\n }\n\n public function show(string $id): void\n {\n $entry = $this->protokollRepo->findById((int) $id);\n if ($entry === null) {\n $this->notFound('Protokoll-Eintrag nicht gefunden');\n }\n\n $entry['request_formatted'] = $this->formatJson($entry['request']);\n $entry['response_formatted'] = $this->formatJson($entry['response']);\n\n $prevId = $this->protokollRepo->findPreviousId((int) $id);\n $nextId = $this->protokollRepo->findNextId((int) $id);\n\n $this->view('protokoll.show', [\n 'title' => 'Protokoll #' . $id,\n 'entry' => $entry,\n 'prevEntry' => $prevId !== null ? ['id' => $prevId] : false,\n 'nextEntry' => $nextId !== null ? ['id' => $nextId] : false,\n ]);\n }\n\n private function formatJson(?string $json): string\n {\n if ($json === null || $json === '') {\n return '-';\n }\n\n $decoded = json_decode($json, true);\n if ($decoded === null) {\n return htmlspecialchars($json);\n }\n\n $formatted = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n\n return $formatted !== false ? $formatted : htmlspecialchars($json);\n }\n}",
"originalFile": "<?php\n\nnamespace Controller;\n\nuse Domain\\ValueObject\\Pagination;\nuse Framework\\Controller;\nuse Infrastructure\\Config\\DatabaseFactory;\n\n\/**\n * ProtokollController - KI-Protokoll Ansicht\n *\n * Zeigt KI-Interaktionen aus ki_dev.protokoll.\n * Nur Lesen, kein Erstellen\/Bearbeiten.\n *\/\nclass ProtokollController extends Controller\n{\n private \\PDO $db;\n\n public function __construct()\n {\n $this->db = DatabaseFactory::dev();\n }\n\n \/**\n * GET \/protokoll\n * Liste aller Protokoll-Einträge\n *\/\n public function index(): void\n {\n \/\/ Statistiken\n $stats = $this->db->query(\n 'SELECT\n COUNT(*) as total,\n SUM(CASE WHEN status = \"completed\" THEN 1 ELSE 0 END) as completed,\n SUM(CASE WHEN status = \"error\" THEN 1 ELSE 0 END) as errors,\n COALESCE(SUM(tokens_total), 0) as tokens_total,\n COALESCE(SUM(duration_ms), 0) as duration_total\n FROM protokoll'\n )->fetch();\n\n \/\/ Einträge mit Pagination\n $pagination = Pagination::fromRequest(50);\n\n $search = $this->getString('search');\n $status = $this->getString('status');\n $model = $this->getString('model');\n\n $sql = 'SELECT id, timestamp, client_name, model_name, status, tokens_total, duration_ms,\n LEFT(request, 200) as request_preview\n FROM protokoll WHERE 1=1';\n $countSql = 'SELECT COUNT(*) FROM protokoll WHERE 1=1';\n $params = [];\n\n if ($search !== '') {\n $sql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $countSql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';\n $params['search'] = '%' . $search . '%';\n $params['search2'] = '%' . $search . '%';\n $params['search3'] = '%' . $search . '%';\n }\n\n if ($status !== '') {\n $sql .= ' AND status = :status';\n $countSql .= ' AND status = :status';\n $params['status'] = $status;\n }\n\n if ($model !== '') {\n $sql .= ' AND model_name = :model';\n $countSql .= ' AND model_name = :model';\n $params['model'] = $model;\n }\n\n \/\/ Total count\n $countStmt = $this->db->prepare($countSql);\n $countStmt->execute($params);\n $totalCount = (int) $countStmt->fetchColumn();\n $pagination = $pagination->withTotal($totalCount);\n\n \/\/ Fetch entries\n $sql .= ' ORDER BY timestamp DESC LIMIT :limit OFFSET :offset';\n $stmt = $this->db->prepare($sql);\n foreach ($params as $key => $value) {\n $stmt->bindValue(':' . $key, $value);\n }\n $stmt->bindValue(':limit', $pagination->limit, \\PDO::PARAM_INT);\n $stmt->bindValue(':offset', $pagination->offset, \\PDO::PARAM_INT);\n $stmt->execute();\n $entries = $stmt->fetchAll();\n\n \/\/ Modelle für Filter\n $models = $this->db->query(\n 'SELECT DISTINCT model_name FROM protokoll WHERE model_name IS NOT NULL ORDER BY model_name'\n )->fetchAll(\\PDO::FETCH_COLUMN);\n\n $this->view('protokoll.index', [\n 'title' => 'KI-Protokoll',\n 'stats' => $stats,\n 'entries' => $entries,\n 'models' => $models,\n 'currentSearch' => $search,\n 'currentStatus' => $status,\n 'currentModel' => $model,\n 'currentPage' => $pagination->page,\n 'totalCount' => $pagination->totalCount,\n 'totalPages' => $pagination->totalPages(),\n ]);\n }\n\n \/**\n * GET \/protokoll\/{id}\n * Detail-Ansicht eines Eintrags\n *\/\n public function show(string $id): void\n {\n $stmt = $this->db->prepare('SELECT * FROM protokoll WHERE id = :id');\n $stmt->execute(['id' => (int) $id]);\n $entry = $stmt->fetch();\n\n if ($entry === false) {\n $this->notFound('Protokoll-Eintrag nicht gefunden');\n }\n\n \/\/ Request\/Response als formatiertes JSON\n $entry['request_formatted'] = $this->formatJson($entry['request']);\n $entry['response_formatted'] = $this->formatJson($entry['response']);\n\n \/\/ Nachbar-Einträge für Navigation\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id < :id ORDER BY id DESC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $prevEntry = $stmt->fetch();\n\n $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id > :id ORDER BY id ASC LIMIT 1');\n $stmt->execute(['id' => (int) $id]);\n $nextEntry = $stmt->fetch();\n\n $this->view('protokoll.show', [\n 'title' => 'Protokoll #' . $id,\n 'entry' => $entry,\n 'prevEntry' => $prevEntry,\n 'nextEntry' => $nextEntry,\n ]);\n }\n\n \/**\n * JSON formatieren für Anzeige\n *\/\n private function formatJson(?string $json): string\n {\n if ($json === null || $json === '') {\n return '-';\n }\n\n $decoded = json_decode($json, true);\n if ($decoded === null) {\n return htmlspecialchars($json);\n }\n\n $formatted = json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n\n return $formatted !== false ? $formatted : htmlspecialchars($json);\n }\n}\n",
"structuredPatch": [
{
"oldStart": 4,
"oldLines": 100,
"newStart": 4,
"newLines": 45,
"lines": [
" ",
" use Domain\\ValueObject\\Pagination;",
" use Framework\\Controller;",
"-use Infrastructure\\Config\\DatabaseFactory;",
"+use Infrastructure\\Persistence\\KiProtokollRepository;",
" ",
"-\/**",
"- * ProtokollController - KI-Protokoll Ansicht",
"- *",
"- * Zeigt KI-Interaktionen aus ki_dev.protokoll.",
"- * Nur Lesen, kein Erstellen\/Bearbeiten.",
"- *\/",
" class ProtokollController extends Controller",
" {",
"- private \\PDO $db;",
"+ private KiProtokollRepository $protokollRepo;",
" ",
"- public function __construct()",
"+ public function __construct(?KiProtokollRepository $protokollRepo = null)",
" {",
"- $this->db = DatabaseFactory::dev();",
"+ $this->protokollRepo = $protokollRepo ?? new KiProtokollRepository();",
" }",
" ",
"- \/**",
"- * GET \/protokoll",
"- * Liste aller Protokoll-Einträge",
"- *\/",
" public function index(): void",
" {",
"- \/\/ Statistiken",
"- $stats = $this->db->query(",
"- 'SELECT",
"- COUNT(*) as total,",
"- SUM(CASE WHEN status = \"completed\" THEN 1 ELSE 0 END) as completed,",
"- SUM(CASE WHEN status = \"error\" THEN 1 ELSE 0 END) as errors,",
"- COALESCE(SUM(tokens_total), 0) as tokens_total,",
"- COALESCE(SUM(duration_ms), 0) as duration_total",
"- FROM protokoll'",
"- )->fetch();",
"-",
"- \/\/ Einträge mit Pagination",
" $pagination = Pagination::fromRequest(50);",
" ",
" $search = $this->getString('search');",
" $status = $this->getString('status');",
" $model = $this->getString('model');",
" ",
"- $sql = 'SELECT id, timestamp, client_name, model_name, status, tokens_total, duration_ms,",
"- LEFT(request, 200) as request_preview",
"- FROM protokoll WHERE 1=1';",
"- $countSql = 'SELECT COUNT(*) FROM protokoll WHERE 1=1';",
"- $params = [];",
"+ $searchVal = $search !== '' ? $search : null;",
"+ $statusVal = $status !== '' ? $status : null;",
"+ $modelVal = $model !== '' ? $model : null;",
" ",
"- if ($search !== '') {",
"- $sql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';",
"- $countSql .= ' AND (request LIKE :search OR response LIKE :search2 OR client_name LIKE :search3)';",
"- $params['search'] = '%' . $search . '%';",
"- $params['search2'] = '%' . $search . '%';",
"- $params['search3'] = '%' . $search . '%';",
"- }",
"-",
"- if ($status !== '') {",
"- $sql .= ' AND status = :status';",
"- $countSql .= ' AND status = :status';",
"- $params['status'] = $status;",
"- }",
"-",
"- if ($model !== '') {",
"- $sql .= ' AND model_name = :model';",
"- $countSql .= ' AND model_name = :model';",
"- $params['model'] = $model;",
"- }",
"-",
"- \/\/ Total count",
"- $countStmt = $this->db->prepare($countSql);",
"- $countStmt->execute($params);",
"- $totalCount = (int) $countStmt->fetchColumn();",
"+ $totalCount = $this->protokollRepo->countFiltered($searchVal, $statusVal, $modelVal);",
" $pagination = $pagination->withTotal($totalCount);",
" ",
"- \/\/ Fetch entries",
"- $sql .= ' ORDER BY timestamp DESC LIMIT :limit OFFSET :offset';",
"- $stmt = $this->db->prepare($sql);",
"- foreach ($params as $key => $value) {",
"- $stmt->bindValue(':' . $key, $value);",
"- }",
"- $stmt->bindValue(':limit', $pagination->limit, \\PDO::PARAM_INT);",
"- $stmt->bindValue(':offset', $pagination->offset, \\PDO::PARAM_INT);",
"- $stmt->execute();",
"- $entries = $stmt->fetchAll();",
"+ $entries = $this->protokollRepo->findPaginated(",
"+ $searchVal,",
"+ $statusVal,",
"+ $modelVal,",
"+ $pagination->limit,",
"+ $pagination->offset",
"+ );",
" ",
"- \/\/ Modelle für Filter",
"- $models = $this->db->query(",
"- 'SELECT DISTINCT model_name FROM protokoll WHERE model_name IS NOT NULL ORDER BY model_name'",
"- )->fetchAll(\\PDO::FETCH_COLUMN);",
"-",
" $this->view('protokoll.index', [",
" 'title' => 'KI-Protokoll',",
"- 'stats' => $stats,",
"+ 'stats' => $this->protokollRepo->getStatistics(),",
" 'entries' => $entries,",
"- 'models' => $models,",
"+ 'models' => $this->protokollRepo->getDistinctModels(),",
" 'currentSearch' => $search,",
" 'currentStatus' => $status,",
" 'currentModel' => $model,"
]
},
{
"oldStart": 107,
"oldLines": 44,
"newStart": 52,
"newLines": 27,
"lines": [
" ]);",
" }",
" ",
"- \/**",
"- * GET \/protokoll\/{id}",
"- * Detail-Ansicht eines Eintrags",
"- *\/",
" public function show(string $id): void",
" {",
"- $stmt = $this->db->prepare('SELECT * FROM protokoll WHERE id = :id');",
"- $stmt->execute(['id' => (int) $id]);",
"- $entry = $stmt->fetch();",
"-",
"- if ($entry === false) {",
"+ $entry = $this->protokollRepo->findById((int) $id);",
"+ if ($entry === null) {",
" $this->notFound('Protokoll-Eintrag nicht gefunden');",
" }",
" ",
"- \/\/ Request\/Response als formatiertes JSON",
" $entry['request_formatted'] = $this->formatJson($entry['request']);",
" $entry['response_formatted'] = $this->formatJson($entry['response']);",
" ",
"- \/\/ Nachbar-Einträge für Navigation",
"- $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id < :id ORDER BY id DESC LIMIT 1');",
"- $stmt->execute(['id' => (int) $id]);",
"- $prevEntry = $stmt->fetch();",
"+ $prevId = $this->protokollRepo->findPreviousId((int) $id);",
"+ $nextId = $this->protokollRepo->findNextId((int) $id);",
" ",
"- $stmt = $this->db->prepare('SELECT id FROM protokoll WHERE id > :id ORDER BY id ASC LIMIT 1');",
"- $stmt->execute(['id' => (int) $id]);",
"- $nextEntry = $stmt->fetch();",
"-",
" $this->view('protokoll.show', [",
" 'title' => 'Protokoll #' . $id,",
" 'entry' => $entry,",
"- 'prevEntry' => $prevEntry,",
"- 'nextEntry' => $nextEntry,",
"+ 'prevEntry' => $prevId !== null ? ['id' => $prevId] : false,",
"+ 'nextEntry' => $nextId !== null ? ['id' => $nextId] : false,",
" ]);",
" }",
" ",
"- \/**",
"- * JSON formatieren für Anzeige",
"- *\/",
" private function formatJson(?string $json): string",
" {",
" if ($json === null || $json === '') {"
]
}
],
"userModified": false,
"replaceAll": false
}
}