Backup #621

ID621
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/Api/DocsController.php
Version5
Typ modified
Größe9.8 KB
Hash3b6c0abb5c8d58ad3ebabe4f4f1273dfa2a026da56b3f2284317fae29af121fe
Datum2025-12-23 04:43: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\Api;

use Framework\Controller;
use Infrastructure\Docs\ChunkSyncService;
use Infrastructure\Persistence\DokumentationRepository;
use UseCases\Docs\DocumentationChatUseCase;

/**
 * DocsController - REST API für Dokumentationsverwaltung
 *
 * Endpoints:
 * - GET    /api/v1/docs              - Liste aller Dokumente
 * - GET    /api/v1/docs/{id}         - Einzelnes Dokument
 * - GET    /api/v1/docs/path/{path}  - Dokument nach Pfad
 * - POST   /api/v1/docs              - Dokument erstellen
 * - PUT    /api/v1/docs/{id}         - Dokument aktualisieren
 * - DELETE /api/v1/docs/{id}         - Dokument löschen
 * - GET    /api/v1/docs/search       - Semantic Search
 * - GET    /api/v1/docs/hierarchy    - Dokumentbaum
 * - POST   /api/v1/docs/chat         - Chat mit Dokumentation
 */
class DocsController extends Controller
{
    private DokumentationRepository $repository;
    private ChunkSyncService $syncService;
    private DocumentationChatUseCase $chatUseCase;

    public function __construct(
        ?DokumentationRepository $repository = null,
        ?ChunkSyncService $syncService = null,
        ?DocumentationChatUseCase $chatUseCase = null
    ) {
        $this->repository = $repository ?? new DokumentationRepository();
        $this->syncService = $syncService ?? new ChunkSyncService();
        $this->chatUseCase = $chatUseCase ?? new DocumentationChatUseCase();
    }

    /**
     * GET /api/v1/docs
     * Liste aller Dokumente mit optionalen Filtern.
     */
    public function index(): void
    {
        try {
            $status = $this->getString('status');
            $parentId = $this->getInt('parent_id');
            $search = $this->getString('search');
            $limit = $this->getLimit(100, 50);
            $offset = $this->getInt('offset');

            $docs = $this->repository->findAll(
                status: $status ?: null,
                parentId: $parentId > 0 ? $parentId : null,
                search: $search ?: null,
                limit: $limit,
                offset: $offset
            );

            $total = $this->repository->count(
                status: $status ?: null,
                parentId: $parentId > 0 ? $parentId : null,
                search: $search ?: null
            );

            $this->json([
                'success' => true,
                'data' => $docs,
                'meta' => [
                    'total' => $total,
                    'limit' => $limit,
                    'offset' => $offset,
                ],
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * GET /api/v1/docs/{id}
     * Einzelnes Dokument mit optionalen Kindern und Breadcrumb.
     */
    public function show(string $id): void
    {
        try {
            $includeChildren = $this->getString('include_children') === '1';
            $includeBreadcrumb = $this->getString('include_breadcrumb') === '1';

            $doc = $this->repository->findById((int) $id);

            if ($doc === null) {
                $this->json(['success' => false, 'error' => 'Dokument nicht gefunden'], 404);

                return;
            }

            $response = [
                'success' => true,
                'data' => $doc,
            ];

            if ($includeChildren) {
                $response['children'] = $this->repository->findChildren((int) $id);
            }

            if ($includeBreadcrumb) {
                $response['breadcrumb'] = $this->repository->getBreadcrumb((int) $id);
            }

            $this->json($response);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * GET /api/v1/docs/path/{path}
     * Dokument nach Pfad.
     */
    public function showByPath(string $path): void
    {
        try {
            $fullPath = '/' . ltrim($path, '/');
            $doc = $this->repository->findByPath($fullPath);

            if ($doc === null) {
                $this->json(['success' => false, 'error' => 'Dokument nicht gefunden'], 404);

                return;
            }

            $this->json([
                'success' => true,
                'data' => $doc,
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * POST /api/v1/docs
     * Neues Dokument erstellen.
     */
    public function store(): void
    {
        try {
            $input = $this->getJsonInput();

            $required = ['title', 'slug'];
            foreach ($required as $field) {
                if (empty($input[$field])) {
                    $this->json(['success' => false, 'error' => "Feld '$field' ist erforderlich"], 400);

                    return;
                }
            }

            $docId = $this->repository->create([
                'title' => trim($input['title']),
                'slug' => trim($input['slug']),
                'content' => $input['content'] ?? '',
                'description' => $input['description'] ?? null,
                'parent_id' => $input['parent_id'] ?? null,
                'status' => $input['status'] ?? 'draft',
                'sort_order' => $input['sort_order'] ?? 0,
            ]);

            $doc = $this->repository->findById($docId);

            $this->json([
                'success' => true,
                'data' => $doc,
                'message' => 'Dokument erstellt',
            ], 201);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * PUT /api/v1/docs/{id}
     * Dokument aktualisieren.
     */
    public function update(string $id): void
    {
        try {
            $doc = $this->repository->findById((int) $id);

            if ($doc === null) {
                $this->json(['success' => false, 'error' => 'Dokument nicht gefunden'], 404);

                return;
            }

            $input = $this->getJsonInput();

            $this->repository->update((int) $id, [
                'title' => $input['title'] ?? $doc['title'],
                'content' => $input['content'] ?? $doc['content'],
                'description' => $input['description'] ?? $doc['description'],
                'status' => $input['status'] ?? $doc['status'],
            ]);

            $updated = $this->repository->findById((int) $id);

            $this->json([
                'success' => true,
                'data' => $updated,
                'message' => 'Dokument aktualisiert',
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * DELETE /api/v1/docs/{id}
     * Dokument löschen.
     */
    public function destroy(string $id): void
    {
        try {
            $doc = $this->repository->findById((int) $id);

            if ($doc === null) {
                $this->json(['success' => false, 'error' => 'Dokument nicht gefunden'], 404);

                return;
            }

            // Check for children
            $children = $this->repository->findChildren((int) $id);
            if (!empty($children)) {
                $this->json([
                    'success' => false,
                    'error' => 'Dokument hat Unterdokumente. Lösche diese zuerst.',
                ], 400);

                return;
            }

            $this->repository->delete((int) $id);

            $this->json([
                'success' => true,
                'message' => 'Dokument gelöscht',
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * GET /api/v1/docs/search
     * Semantic search über Dokumentation.
     */
    public function search(): void
    {
        try {
            $query = $this->getString('q');
            $limit = $this->getInt('limit', 5);
            $category = $this->getString('category');

            if ($query === '') {
                $this->json(['success' => false, 'error' => 'Keine Suchanfrage'], 400);

                return;
            }

            if ($category !== '') {
                $results = $this->syncService->searchByTaxonomy($query, $category, $limit);
            } else {
                $results = $this->syncService->search($query, $limit);
            }

            $this->json([
                'success' => true,
                'data' => $results,
                'meta' => [
                    'query' => $query,
                    'limit' => $limit,
                    'count' => count($results),
                ],
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * GET /api/v1/docs/hierarchy
     * Vollständiger Dokumentationsbaum.
     */
    public function hierarchy(): void
    {
        try {
            $tree = $this->repository->getTree();

            $this->json([
                'success' => true,
                'data' => $tree,
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }

    /**
     * POST /api/v1/docs/chat
     * Chat mit Dokumentation (RAG).
     */
    public function chat(): void
    {
        try {
            $input = $this->getJsonInput();
            $question = trim($input['question'] ?? '');
            $model = $input['model'] ?? 'mistral';
            $limit = (int) ($input['limit'] ?? 5);

            if ($question === '') {
                $this->json(['success' => false, 'error' => 'Keine Frage angegeben'], 400);

                return;
            }

            $result = $this->chatUseCase->execute($question, $model, $limit);

            $this->json([
                'success' => true,
                'data' => $result,
            ]);
        } catch (\Exception $e) {
            $this->jsonError($e->getMessage());
        }
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
2045 20 modified 10.0 KB 2025-12-28 23:26
2044 19 modified 9.9 KB 2025-12-28 23:26
2043 18 modified 9.8 KB 2025-12-28 23:25
2042 17 modified 9.7 KB 2025-12-28 23:25
2040 16 modified 9.6 KB 2025-12-28 23:25
2038 15 modified 9.5 KB 2025-12-28 23:25
2037 14 modified 9.4 KB 2025-12-28 23:25
2036 13 modified 9.3 KB 2025-12-28 23:25
2034 12 modified 9.2 KB 2025-12-28 23:25
1888 11 modified 9.2 KB 2025-12-28 01:01
1884 10 modified 9.2 KB 2025-12-28 01:00
1283 9 modified 9.2 KB 2025-12-25 13:01
1282 8 modified 9.2 KB 2025-12-25 13:01
1273 7 modified 9.1 KB 2025-12-25 12:52
700 6 modified 9.7 KB 2025-12-23 07:53
621 5 modified 9.8 KB 2025-12-23 04:43
596 4 modified 11.9 KB 2025-12-23 04:27
595 3 modified 11.7 KB 2025-12-23 04:26
594 2 modified 11.5 KB 2025-12-23 04:25
570 1 modified 11.6 KB 2025-12-23 03:41

← Zurück zur Übersicht