Backup #3

ID3
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/ProtokollController.php
Version1
Typ modified
Größe5.7 KB
Hash532576e9de78c630d0ce9b367073792505bd3cb204ff4caba58ab9fe8f2357c7
Datum2025-12-20 16:08:07
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

namespace Controller;

use Framework\Controller;

/**
 * ProtokollController - KI-Protokoll Ansicht
 *
 * Zeigt KI-Interaktionen aus ki_protokoll.protokoll.
 * Nur Lesen, kein Erstellen/Bearbeiten.
 */
class ProtokollController extends Controller
{
    private \PDO $db;

    public function __construct()
    {
        $this->db = new \PDO(
            'mysql:host=localhost;dbname=ki_protokoll;charset=utf8mb4',
            'root',
            $this->getPassword(),
            [
                \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
                \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
            ]
        );
    }

    private function getPassword(): string
    {
        $file = '/var/www/docs/credentials/credentials.md';
        $content = file_get_contents($file);
        foreach (explode("\n", $content) as $line) {
            if (str_contains($line, 'MariaDB') && str_contains($line, 'root')) {
                $parts = explode('|', $line);
                if (count($parts) >= 4) {
                    return trim($parts[3]);
                }
            }
        }

        return '';
    }

    /**
     * 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);
        $stmt->execute($params);
        $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

Herunterladen

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