Backup #2034

ID2034
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/Api/DocsController.php
Version12
Typ modified
Größe9.2 KB
Hash354167489f64d479e5424c89a8c39ce93f266c53e744f43f9550b20ae306f207
Datum2025-12-28 23:25:03
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;

// @responsibility: REST-API für Dokumentations-CRUD und Semantic Search

use Domain\Constants;
use Domain\Repository\DokumentationRepositoryInterface;
use Framework\Controller;
use Infrastructure\Docs\ChunkSearchService;
use UseCases\Docs\DocumentationChatUseCase;

class DocsController extends Controller
{
    private DokumentationRepositoryInterface $repository;
    private ChunkSearchService $searchService;
    private DocumentationChatUseCase $chatUseCase;

    public function __construct(
        DokumentationRepositoryInterface $repository,
        ChunkSearchService $searchService,
        DocumentationChatUseCase $chatUseCase
    ) {
        $this->repository = $repository;
        $this->searchService = $searchService;
        $this->chatUseCase = $chatUseCase;
    }

    /**
     * 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(Constants::DEFAULT_LIMIT, 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->searchService->searchByTaxonomy($query, $category, $limit);
            } else {
                $results = $this->searchService->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