Backup #246
| ID | 246 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Controller/ProtokollController.php |
| Version | 4 |
| Typ |
modified |
| Größe | 5.2 KB |
| Hash | 8a1aee6edc7740648280ac14a5baea0136ff4643646454d2a42a82c79d722c12 |
| Datum | 2025-12-22 01:46:44 |
| 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;
/**
* ProtokollController - KI-Protokoll Ansicht
*
* Zeigt KI-Interaktionen aus ki_dev.protokoll.
* Nur Lesen, kein Erstellen/Bearbeiten.
*/
class ProtokollController extends Controller
{
private \PDO $db;
public function __construct()
{
$this->db = DatabaseFactory::dev();
}
/**
* 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
$page = max(1, (int) ($_GET['page'] ?? 1));
$limit = 50;
$offset = ($page - 1) * $limit;
$search = $_GET['search'] ?? '';
$status = $_GET['status'] ?? '';
$model = $_GET['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 = [];
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();
// 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', $limit, \PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, \PDO::PARAM_INT);
$stmt->execute();
$entries = $stmt->fetchAll();
// 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,
'entries' => $entries,
'models' => $models,
'currentSearch' => $search,
'currentStatus' => $status,
'currentModel' => $model,
'currentPage' => $page,
'totalCount' => $totalCount,
'totalPages' => ceil($totalCount / $limit),
]);
}
/**
* 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) {
http_response_code(404);
echo '404 - Protokoll-Eintrag nicht gefunden';
return;
}
// 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();
$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,
]);
}
/**
* JSON formatieren für Anzeige
*/
private function formatJson(?string $json): string
{
if ($json === null || $json === '') {
return '-';
}
$decoded = json_decode($json, true);
if ($decoded === null) {
return htmlspecialchars($json);
}
return json_encode($decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
}
}
Vollständig herunterladen
Aktionen
Andere Versionen dieser Datei
| ID |
Version |
Typ |
Größe |
Datum |
| 699 |
15 |
modified |
2.1 KB |
2025-12-23 07:53 |
| 643 |
14 |
modified |
2.1 KB |
2025-12-23 04:47 |
| 469 |
13 |
modified |
2.1 KB |
2025-12-22 10:32 |
| 468 |
12 |
modified |
2.1 KB |
2025-12-22 10:32 |
| 453 |
11 |
modified |
2.9 KB |
2025-12-22 10:27 |
| 448 |
10 |
modified |
5.3 KB |
2025-12-22 10:19 |
| 407 |
9 |
modified |
5.2 KB |
2025-12-22 08:55 |
| 345 |
8 |
modified |
5.1 KB |
2025-12-22 08:12 |
| 344 |
7 |
modified |
5.1 KB |
2025-12-22 08:12 |
| 343 |
6 |
modified |
5.1 KB |
2025-12-22 08:12 |
| 306 |
5 |
modified |
5.1 KB |
2025-12-22 08:05 |
| 246 |
4 |
modified |
5.2 KB |
2025-12-22 01:46 |
| 135 |
3 |
modified |
4.9 KB |
2025-12-20 19:56 |
| 34 |
2 |
modified |
5.7 KB |
2025-12-20 17:23 |
| 3 |
1 |
modified |
5.7 KB |
2025-12-20 16:08 |
← Zurück zur Übersicht