Backup #974

ID974
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/ContentController.php
Version57
Typ modified
Größe9.2 KB
Hash896f08b73a46cd333e46916dba870ca67df37a43a0706fa1a02b91c47df68999
Datum2025-12-24 00:12:13
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace Controller;

// @responsibility: HTTP-Endpunkte für Content Studio (Aufträge, Generierung, Kritik)

use Application\ContentCollectionService;
use Framework\Controller;
use Infrastructure\AI\ModelConfig;
use Infrastructure\Persistence\ContentRepository;
use UseCases\Command\CreateContentOrderCommand;
use UseCases\Command\GenerateContentCommand;
use UseCases\Content\GenerateContentUseCase;

class ContentController extends Controller
{
    private ContentRepository $repository;
    private ContentCollectionService $collectionService;
    private GenerateContentUseCase $generateUseCase;

    public function __construct(
        ContentRepository $repository,
        ContentCollectionService $collectionService,
        GenerateContentUseCase $generateUseCase
    ) {
        $this->repository = $repository;
        $this->collectionService = $collectionService;
        $this->generateUseCase = $generateUseCase;
    }

    /**
     * GET /content - List all content orders
     */
    public function index(): void
    {
        $status = $this->getString('status');

        $this->view('content.index', [
            'title' => 'Content Studio',
            'orders' => $this->repository->findAllOrders($status !== '' ? ['status' => $status] : []),
            'stats' => $this->repository->getStatistics(),
            'currentStatus' => $status,
        ]);
    }

    /**
     * GET /content/new - Show create form
     */
    public function contentNew(): void
    {
        $lastSettings = $this->repository->getLastOrderSettings();

        $this->view('content.new', [
            'title' => 'Neuer Content-Auftrag',
            'profiles' => $this->repository->findAllProfiles(),
            'contracts' => $this->repository->findAllContracts(),
            'structures' => $this->repository->findAllStructures(),
            'models' => ModelConfig::getAll(),
            'collections' => $this->collectionService->getAvailable(),
            'defaultModel' => $lastSettings['model'],
            'defaultCollections' => $lastSettings['collections'],
            'defaultContextLimit' => $lastSettings['context_limit'],
            'defaultProfileId' => $lastSettings['author_profile_id'],
            'defaultContractId' => $lastSettings['contract_id'],
            'defaultStructureId' => $lastSettings['structure_id'],
        ]);
    }

    /**
     * POST /content - Store new order
     */
    public function store(): void
    {
        $this->requireCsrf();

        $command = CreateContentOrderCommand::fromRequest($_POST);
        $errors = $command->validate();

        if ($errors !== []) {
            $_SESSION['error'] = implode(' ', $errors);
            $this->redirect('/content/new');
        }

        // Validate collections
        $result = $this->collectionService->validateWithCompatibility($command->collections);
        if (!$result['valid']) {
            $_SESSION['error'] = 'Collection-Fehler: ' . $result['error'];
            $this->redirect('/content/new');
        }

        $orderId = $this->repository->createOrder([
            'title' => $command->title,
            'briefing' => $command->briefing,
            'author_profile_id' => $command->authorProfileId,
            'contract_id' => $command->contractId ?? $this->getFirstContractId(),
            'structure_id' => $command->structureId,
            'model' => ModelConfig::validate($command->model),
            'collections' => json_encode($result['collections']),
            'context_limit' => $command->contextLimit,
        ]);

        if ($command->shouldGenerate()) {
            $genResult = $this->generateUseCase->generate(
                $orderId,
                ModelConfig::validate($command->model),
                $result['collections'][0] ?? 'documents',
                $command->contextLimit
            );
            $_SESSION[$genResult->hasError() ? 'error' : 'success'] =
                $genResult->hasError() ? 'Generierung fehlgeschlagen: ' . $genResult->getError() : 'Content wurde generiert.';
        }

        $this->redirect('/content/' . $orderId);
    }

    /**
     * GET /content/{id} - Show order details
     */
    public function show(int $id): void
    {
        $order = $this->repository->findOrder($id);
        if ($order === null) {
            $this->notFound('Auftrag nicht gefunden');
        }

        $versions = $this->repository->findVersionsByOrder($id);
        $latestVersion = $versions[0] ?? null;

        $this->view('content.show', [
            'title' => $order['title'],
            'order' => $order,
            'versions' => $versions,
            'latestVersion' => $latestVersion,
            'critiques' => $latestVersion ? $this->repository->findCritiquesByVersion($latestVersion['id']) : [],
            'sources' => $this->repository->findSourcesByOrder($id),
            'models' => ModelConfig::getAll(),
            'availableCollections' => $this->collectionService->getAvailable(),
        ]);
    }

    /**
     * GET /content/{id}/edit - Show edit form
     */
    public function edit(int $id): void
    {
        $order = $this->repository->findOrder($id);
        if ($order === null) {
            $this->notFound('Auftrag nicht gefunden');
        }

        $this->view('content.edit', [
            'title' => 'Auftrag bearbeiten',
            'order' => $order,
            'profiles' => $this->repository->findAllProfiles(),
            'contracts' => $this->repository->findAllContracts(),
            'structures' => $this->repository->findAllStructures(),
        ]);
    }

    /**
     * POST /content/{id}/generate - Generate content (HTMX)
     */
    public function generate(int $id): void
    {
        $this->requireCsrf();

        $command = GenerateContentCommand::fromRequest($id, $_POST);
        if (($errors = $command->validate()) !== []) {
            $this->htmxError(implode(' ', $errors));

            return;
        }

        $result = $this->collectionService->validateWithCompatibility([$command->collection]);
        if (!$result['valid']) {
            $this->htmxError($result['error'] ?? 'Collection-Fehler');

            return;
        }

        $genResult = $this->generateUseCase->generate($id, $command->model, $result['collections'][0], $command->contextLimit);
        if ($genResult->hasError()) {
            $this->htmxError('Fehler: ' . $genResult->getError());

            return;
        }

        $this->renderVersionPartial($genResult->toArray());
    }

    /**
     * POST /content/{id}/critique - Run critique round (HTMX)
     */
    public function critique(int $id): void
    {
        $this->requireCsrf();

        $version = $this->repository->findLatestVersion($id);
        if ($version === null) {
            $this->htmxError('Keine Version vorhanden.');

            return;
        }

        $result = $this->generateUseCase->critique($version['id'], $_POST['model'] ?? 'claude-opus-4-5-20251101');
        if ($result->hasError()) {
            $this->htmxError('Fehler: ' . $result->getError());

            return;
        }

        $this->renderCritiquePartial($result->toArray());
    }

    /**
     * POST /content/{id}/revise - Create revision (HTMX)
     */
    public function revise(int $id): void
    {
        $this->requireCsrf();

        $version = $this->repository->findLatestVersion($id);
        if ($version === null) {
            $this->htmxError('Keine Version vorhanden.');

            return;
        }

        $result = $this->generateUseCase->revise($version['id'], $_POST['model'] ?? 'claude-opus-4-5-20251101');
        if ($result->hasError()) {
            $this->htmxError('Fehler: ' . $result->getError());

            return;
        }

        $this->renderVersionPartial($result->toArray());
    }

    /**
     * POST /content/{id}/approve - Approve content
     */
    public function approve(int $id): void
    {
        $this->requireCsrf();
        $this->repository->updateOrderStatus($id, 'approve');
        $this->htmxSuccess('Content genehmigt!');
        $this->html('<script>setTimeout(() => window.location.reload(), 1000);</script>');
    }

    /**
     * POST /content/{id}/decline - Decline content
     */
    public function decline(int $id): void
    {
        $this->requireCsrf();
        $this->repository->updateOrderStatus($id, 'draft');
        $this->htmxAlert('warning', 'Content abgelehnt. Zurück zu Entwurf.');
        $this->html('<script>setTimeout(() => window.location.reload(), 1000);</script>');
    }

    private function getFirstContractId(): ?int
    {
        $contracts = $this->repository->findAllContracts();

        return $contracts !== [] ? (int) $contracts[0]['id'] : null;
    }

    private function renderVersionPartial(array $result): void
    {
        $this->view('content.partials.version', [
            'content' => $result['content'] ?? '',
            'sources' => $result['sources'] ?? [],
            'versionNumber' => $result['version_number'] ?? '?',
        ]);
    }

    private function renderCritiquePartial(array $result): void
    {
        $this->view('content.partials.critique', [
            'critiques' => $result['critiques'] ?? [],
            'allPassed' => $result['all_passed'] ?? false,
            'round' => $result['round'] ?? '?',
        ]);
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
2162 71 modified 14.5 KB 2025-12-30 22:24
2161 70 modified 14.3 KB 2025-12-30 22:24
2160 69 modified 14.1 KB 2025-12-30 22:24
2159 68 modified 13.6 KB 2025-12-30 22:23
1768 67 modified 13.2 KB 2025-12-27 12:55
1297 66 modified 13.1 KB 2025-12-25 13:27
1296 65 modified 13.0 KB 2025-12-25 13:27
1295 64 modified 13.0 KB 2025-12-25 13:27
1294 63 modified 13.2 KB 2025-12-25 13:27
1276 62 modified 13.2 KB 2025-12-25 12:52
1015 61 modified 10.9 KB 2025-12-24 01:29
986 60 modified 10.7 KB 2025-12-24 00:41
985 59 modified 10.8 KB 2025-12-24 00:31
984 58 modified 10.4 KB 2025-12-24 00:18
974 57 modified 9.2 KB 2025-12-24 00:12
686 56 modified 9.1 KB 2025-12-23 07:51
633 55 modified 9.2 KB 2025-12-23 04:45
618 54 modified 9.5 KB 2025-12-23 04:42
590 53 modified 9.2 KB 2025-12-23 04:24
530 52 modified 11.8 KB 2025-12-22 21:19
509 51 modified 11.9 KB 2025-12-22 15:42
508 50 modified 11.9 KB 2025-12-22 15:42
501 49 modified 11.9 KB 2025-12-22 15:40
500 48 modified 11.9 KB 2025-12-22 15:40
499 47 modified 12.0 KB 2025-12-22 15:40
498 46 modified 12.0 KB 2025-12-22 15:40
497 45 modified 12.2 KB 2025-12-22 15:38
489 44 modified 12.1 KB 2025-12-22 15:27
488 43 modified 12.4 KB 2025-12-22 15:27
487 42 modified 12.3 KB 2025-12-22 15:27
320 41 modified 12.3 KB 2025-12-22 08:06
280 40 modified 14.1 KB 2025-12-22 02:18
279 39 modified 14.1 KB 2025-12-22 02:17
278 38 modified 14.1 KB 2025-12-22 02:17
277 37 modified 14.1 KB 2025-12-22 02:17
276 36 modified 14.1 KB 2025-12-22 02:17
275 35 modified 14.1 KB 2025-12-22 02:17
267 34 modified 15.4 KB 2025-12-22 02:10
266 33 modified 16.0 KB 2025-12-22 02:10
234 32 modified 16.0 KB 2025-12-22 01:46
233 31 modified 16.1 KB 2025-12-22 01:46
207 30 modified 15.6 KB 2025-12-21 17:01
198 29 modified 15.9 KB 2025-12-21 14:39
190 28 modified 14.4 KB 2025-12-21 14:36
189 27 modified 13.8 KB 2025-12-21 14:35
188 26 modified 13.4 KB 2025-12-21 14:35
187 25 modified 13.5 KB 2025-12-21 14:35
186 24 modified 13.6 KB 2025-12-21 14:35
185 23 modified 13.2 KB 2025-12-21 14:35
178 22 modified 13.4 KB 2025-12-21 09:14
177 21 modified 13.0 KB 2025-12-21 09:14
173 20 modified 12.8 KB 2025-12-21 04:13
172 19 modified 12.6 KB 2025-12-21 04:13
166 18 modified 12.6 KB 2025-12-21 04:11
165 17 modified 12.6 KB 2025-12-21 04:11
164 16 modified 12.6 KB 2025-12-21 04:11
163 15 modified 12.8 KB 2025-12-21 04:11
160 14 modified 12.5 KB 2025-12-21 03:00
157 13 modified 12.1 KB 2025-12-21 02:59
156 12 modified 11.8 KB 2025-12-21 02:59
155 11 modified 11.4 KB 2025-12-21 02:59
139 10 modified 11.4 KB 2025-12-20 19:58
138 9 modified 11.3 KB 2025-12-20 19:57
137 8 modified 10.8 KB 2025-12-20 19:57
134 7 modified 10.4 KB 2025-12-20 19:55
113 6 modified 10.4 KB 2025-12-20 19:20
112 5 modified 10.3 KB 2025-12-20 19:20
111 4 modified 10.3 KB 2025-12-20 19:20
110 3 modified 10.3 KB 2025-12-20 19:20
109 2 modified 10.2 KB 2025-12-20 19:19
108 1 modified 10.2 KB 2025-12-20 19:19

← Zurück zur Übersicht