Backup #2040
| ID | 2040 |
| Dateipfad | /var/www/dev.campus.systemische-tools.de/src/Controller/Api/DocsController.php |
| Version | 16 |
| Typ |
modified |
| Größe | 9.6 KB |
| Hash | d248c7bf1b19d08c2bdfa4c885fc72ea019fcbb9e9b08d4abd8a8d607154ecd8 |
| Datum | 2025-12-28 23:25:36 |
| Geändert von | claude-code-hook |
| Grund | Claude 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) {
error_log(sprintf('[API.Docs.index] %s: %s', get_class($e), $e->getMessage()));
$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) {
error_log(sprintf('[API.Docs.show] %s: %s', get_class($e), $e->getMessage()));
$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) {
error_log(sprintf('[API.Docs.showByPath] %s: %s', get_class($e), $e->getMessage()));
$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) {
error_log(sprintf('[API.Docs.store] %s: %s', get_class($e), $e->getMessage()));
$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
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