Backup #231

ID231
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/ConfigController.php
Version4
Typ modified
Größe10.4 KB
Hash4e02e70122468a46c80243870019bd3479798ac31552984c42f08f3f83d0aa20
Datum2025-12-22 01:45:25
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

namespace Controller;

use Framework\Controller;
use Infrastructure\Config\DatabaseFactory;

class ConfigController extends Controller
{
    private \PDO $db;

    private const TYPES = ['author_profile', 'structure', 'organization', 'contract', 'rule', 'system_prompt'];
    private const TYPE_LABELS = [
        'author_profile' => 'Autorenprofil',
        'structure' => 'Struktur',
        'organization' => 'Organisation',
        'contract' => 'Contract',
        'rule' => 'Regel',
        'system_prompt' => 'System-Prompt',
    ];

    public function __construct()
    {
        $this->db = DatabaseFactory::content();
    }

    /**
     * GET /config
     */
    public function index(): void
    {
        $typeFilter = $_GET['type'] ?? '';
        $statusFilter = $_GET['status'] ?? '';

        $sql = 'SELECT c.*, p.name as parent_name
                FROM content_config c
                LEFT JOIN content_config p ON c.parent_id = p.id
                WHERE 1=1';
        $params = [];

        if ($typeFilter !== '' && in_array($typeFilter, self::TYPES, true)) {
            $sql .= ' AND c.type = ?';
            $params[] = $typeFilter;
        }

        if ($statusFilter !== '' && in_array($statusFilter, ['draft', 'active', 'deprecated'], true)) {
            $sql .= ' AND c.status = ?';
            $params[] = $statusFilter;
        }

        $sql .= ' ORDER BY c.type, c.name';

        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        $configs = $stmt->fetchAll(\PDO::FETCH_ASSOC);

        $stats = $this->getStatistics();

        $this->view('config.index', [
            'title' => 'Content-Konfiguration',
            'configs' => $configs,
            'stats' => $stats,
            'types' => self::TYPES,
            'typeLabels' => self::TYPE_LABELS,
            'currentType' => $typeFilter,
            'currentStatus' => $statusFilter,
        ]);
    }

    /**
     * GET /config/new
     */
    public function configNew(): void
    {
        $parents = $this->getParentOptions();

        $this->view('config.form', [
            'title' => 'Neue Konfiguration',
            'config' => null,
            'types' => self::TYPES,
            'typeLabels' => self::TYPE_LABELS,
            'parents' => $parents,
            'isEdit' => false,
        ]);
    }

    /**
     * POST /config
     */
    public function store(): void
    {
        $this->requireCsrf();

        $type = $_POST['type'] ?? '';
        $name = trim($_POST['name'] ?? '');
        $slug = trim($_POST['slug'] ?? '');
        $description = trim($_POST['description'] ?? '');
        $content = $_POST['content'] ?? '{}';
        $version = trim($_POST['version'] ?? '1.0');
        $status = $_POST['status'] ?? 'draft';
        $parentId = !empty($_POST['parent_id']) ? (int) $_POST['parent_id'] : null;

        if (!in_array($type, self::TYPES, true) || $name === '' || $slug === '') {
            $_SESSION['error'] = 'Typ, Name und Slug sind erforderlich.';
            header('Location: /config/new');
            exit;
        }

        // JSON validieren
        $decoded = json_decode($content, true);
        if ($decoded === null && $content !== 'null') {
            $_SESSION['error'] = 'Ungültiges JSON-Format.';
            header('Location: /config/new');
            exit;
        }

        $stmt = $this->db->prepare(
            'INSERT INTO content_config (type, name, slug, description, content, version, status, parent_id)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
        );
        $stmt->execute([$type, $name, $slug, $description ?: null, $content, $version, $status, $parentId]);
        $id = $this->db->lastInsertId();

        $_SESSION['success'] = 'Konfiguration erfolgreich erstellt.';
        header('Location: /config/' . $id);
        exit;
    }

    /**
     * GET /config/{id}
     */
    public function show(string $id): void
    {
        $config = $this->findById((int) $id);

        if ($config === null) {
            $this->notFound('Konfiguration nicht gefunden');
        }

        $children = $this->getChildren((int) $id);
        $history = $this->getHistory((int) $id);

        $this->view('config.show', [
            'title' => $config['name'],
            'config' => $config,
            'children' => $children,
            'history' => $history,
            'typeLabels' => self::TYPE_LABELS,
        ]);
    }

    /**
     * GET /config/{id}/edit
     */
    public function edit(string $id): void
    {
        $config = $this->findById((int) $id);

        if ($config === null) {
            $this->notFound('Konfiguration nicht gefunden');
        }

        $parents = $this->getParentOptions((int) $id);

        $this->view('config.form', [
            'title' => 'Bearbeiten: ' . $config['name'],
            'config' => $config,
            'types' => self::TYPES,
            'typeLabels' => self::TYPE_LABELS,
            'parents' => $parents,
            'isEdit' => true,
        ]);
    }

    /**
     * POST /config/{id}
     */
    public function update(string $id): void
    {
        $this->requireCsrf();

        $config = $this->findById((int) $id);

        if ($config === null) {
            http_response_code(404);
            echo 'Konfiguration nicht gefunden';

            return;
        }

        $name = trim($_POST['name'] ?? '');
        $slug = trim($_POST['slug'] ?? '');
        $description = trim($_POST['description'] ?? '');
        $content = $_POST['content'] ?? '{}';
        $newVersion = trim($_POST['new_version'] ?? '');
        $changeDescription = trim($_POST['change_description'] ?? '');
        $status = $_POST['status'] ?? $config['status'];
        $parentId = !empty($_POST['parent_id']) ? (int) $_POST['parent_id'] : null;

        if ($name === '' || $slug === '' || $newVersion === '') {
            $_SESSION['error'] = 'Name, Slug und neue Version sind erforderlich.';
            header('Location: /config/' . $id . '/edit');
            exit;
        }

        // JSON validieren
        $decoded = json_decode($content, true);
        if ($decoded === null && $content !== 'null') {
            $_SESSION['error'] = 'Ungültiges JSON-Format.';
            header('Location: /config/' . $id . '/edit');
            exit;
        }

        // Alte Version in History speichern
        $stmt = $this->db->prepare(
            'INSERT INTO content_config_history (config_id, content, version, changed_by, change_description)
             VALUES (?, ?, ?, ?, ?)'
        );
        $stmt->execute([
            $id,
            $config['content'],
            $config['version'],
            'web-ui',
            $changeDescription ?: 'Update auf Version ' . $newVersion,
        ]);

        // Config aktualisieren
        $stmt = $this->db->prepare(
            'UPDATE content_config
             SET name = ?, slug = ?, description = ?, content = ?, version = ?, status = ?, parent_id = ?
             WHERE id = ?'
        );
        $stmt->execute([$name, $slug, $description ?: null, $content, $newVersion, $status, $parentId, $id]);

        $_SESSION['success'] = 'Konfiguration auf Version ' . $newVersion . ' aktualisiert.';
        header('Location: /config/' . $id);
        exit;
    }

    /**
     * POST /config/{id}/delete
     */
    public function delete(string $id): void
    {
        $this->requireCsrf();

        $config = $this->findById((int) $id);

        if ($config === null) {
            http_response_code(404);
            echo 'Konfiguration nicht gefunden';

            return;
        }

        // Prüfen ob Children existieren
        $stmt = $this->db->prepare('SELECT COUNT(*) FROM content_config WHERE parent_id = ?');
        $stmt->execute([$id]);
        if ($stmt->fetchColumn() > 0) {
            $_SESSION['error'] = 'Kann nicht gelöscht werden: Es existieren verknüpfte Einträge.';
            header('Location: /config/' . $id);
            exit;
        }

        // History löschen
        $stmt = $this->db->prepare('DELETE FROM content_config_history WHERE config_id = ?');
        $stmt->execute([$id]);

        // Config löschen
        $stmt = $this->db->prepare('DELETE FROM content_config WHERE id = ?');
        $stmt->execute([$id]);

        $_SESSION['success'] = 'Konfiguration gelöscht.';
        header('Location: /config');
        exit;
    }

    // ========== Private Helpers ==========

    private function findById(int $id): ?array
    {
        $stmt = $this->db->prepare(
            'SELECT c.*, p.name as parent_name
             FROM content_config c
             LEFT JOIN content_config p ON c.parent_id = p.id
             WHERE c.id = ?'
        );
        $stmt->execute([$id]);
        $result = $stmt->fetch(\PDO::FETCH_ASSOC);

        return $result !== false ? $result : null;
    }

    private function getStatistics(): array
    {
        $stats = ['total' => 0, 'by_type' => [], 'by_status' => []];

        $stmt = $this->db->query('SELECT type, COUNT(*) as cnt FROM content_config GROUP BY type');
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
            $stats['by_type'][$row['type']] = (int) $row['cnt'];
            $stats['total'] += (int) $row['cnt'];
        }

        $stmt = $this->db->query('SELECT status, COUNT(*) as cnt FROM content_config GROUP BY status');
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
            $stats['by_status'][$row['status']] = (int) $row['cnt'];
        }

        return $stats;
    }

    private function getParentOptions(?int $excludeId = null): array
    {
        $sql = 'SELECT id, type, name FROM content_config WHERE type IN ("contract", "organization") ORDER BY type, name';
        $stmt = $this->db->query($sql);
        $parents = [];
        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
            if ($excludeId !== null && (int) $row['id'] === $excludeId) {
                continue;
            }
            $parents[] = $row;
        }

        return $parents;
    }

    private function getChildren(int $parentId): array
    {
        $stmt = $this->db->prepare('SELECT * FROM content_config WHERE parent_id = ? ORDER BY name');
        $stmt->execute([$parentId]);

        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }

    private function getHistory(int $configId): array
    {
        $stmt = $this->db->prepare(
            'SELECT * FROM content_config_history WHERE config_id = ? ORDER BY created_at DESC LIMIT 10'
        );
        $stmt->execute([$configId]);

        return $stmt->fetchAll(\PDO::FETCH_ASSOC);
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
2139 22 modified 6.1 KB 2025-12-30 20:32
2138 21 modified 6.1 KB 2025-12-30 20:32
2137 20 modified 5.9 KB 2025-12-30 20:32
2136 19 modified 5.7 KB 2025-12-30 20:31
2135 18 modified 5.6 KB 2025-12-30 20:31
2129 17 modified 5.6 KB 2025-12-30 20:28
1763 16 modified 5.3 KB 2025-12-27 12:53
1762 15 modified 5.1 KB 2025-12-27 12:53
1761 14 modified 4.9 KB 2025-12-27 12:52
864 13 modified 4.9 KB 2025-12-23 08:50
687 12 modified 4.8 KB 2025-12-23 07:52
466 11 modified 4.8 KB 2025-12-22 10:31
465 10 modified 4.8 KB 2025-12-22 10:31
464 9 modified 4.8 KB 2025-12-22 10:31
452 8 modified 6.7 KB 2025-12-22 10:26
446 7 modified 10.3 KB 2025-12-22 10:18
307 6 modified 10.3 KB 2025-12-22 08:05
232 5 modified 10.4 KB 2025-12-22 01:45
231 4 modified 10.4 KB 2025-12-22 01:45
230 3 modified 10.4 KB 2025-12-22 01:45
229 2 modified 10.5 KB 2025-12-22 01:45
149 1 modified 10.4 KB 2025-12-21 02:30

← Zurück zur Übersicht