{
"tool_response": [
{
"type": "text",
"text": "{\n \"status\": \"success\",\n \"data\": [\n {\n \"id\": 7593,\n \"scan_id\": \"107a7119-7bcf-4ea9-8514-386c0c47fa04\",\n \"file_path\": \"\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/Api\/ExplorerController.php\",\n \"file_name\": \"ExplorerController.php\",\n \"extension\": \"php\",\n \"directory\": \"\/var\/www\/dev.campus.systemische-tools.de\/src\/Controller\/Api\",\n \"file_size\": 8799,\n \"line_count\": 290,\n \"file_content\": \"<?php\\n\\ndeclare(strict_types=1);\\n\\nnamespace Controller\\\\Api;\\n\\n\/\/ @responsibility: REST-API für Doc2Vector Explorer (Dokumente, Chunks, Suche)\\n\\nuse Domain\\\\Repository\\\\ChunkExplorerRepositoryInterface;\\nuse Domain\\\\Repository\\\\DokumentExplorerRepositoryInterface;\\nuse Domain\\\\Repository\\\\SeiteExplorerRepositoryInterface;\\nuse Framework\\\\Controller;\\nuse Infrastructure\\\\Docs\\\\HybridSearchService;\\nuse Infrastructure\\\\Traits\\\\JsonDecodeTrait;\\n\\nclass ExplorerController extends Controller\\n{\\n use JsonDecodeTrait;\\n\\n private DokumentExplorerRepositoryInterface $dokumentRepository;\\n private SeiteExplorerRepositoryInterface $seiteRepository;\\n private ChunkExplorerRepositoryInterface $chunkRepository;\\n private HybridSearchService $searchService;\\n\\n public function __construct(\\n DokumentExplorerRepositoryInterface $dokumentRepository,\\n SeiteExplorerRepositoryInterface $seiteRepository,\\n ChunkExplorerRepositoryInterface $chunkRepository,\\n HybridSearchService $searchService\\n ) {\\n $this->dokumentRepository = $dokumentRepository;\\n $this->seiteRepository = $seiteRepository;\\n $this->chunkRepository = $chunkRepository;\\n $this->searchService = $searchService;\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/stats\\n *\/\\n public function stats(): void\\n {\\n try {\\n $this->json([\\n 'success' => true,\\n 'data' => [\\n 'dokumente' => $this->dokumentRepository->countDokumente(),\\n 'seiten' => $this->seiteRepository->countSeiten(),\\n 'chunks' => $this->chunkRepository->getChunkStats(),\\n 'taxonomy_categories' => $this->chunkRepository->getTopTaxonomyCategories(100),\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/dokumente\\n *\/\\n public function listDokumente(): void\\n {\\n try {\\n $dokumente = $this->dokumentRepository->getDokumenteWithFullStats();\\n\\n $this->json([\\n 'success' => true,\\n 'data' => $dokumente,\\n 'meta' => ['total' => count($dokumente)],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/dokumente\/{id}\\n *\/\\n public function getDokument(string $id): void\\n {\\n try {\\n $dokument = $this->dokumentRepository->getDokumentRoot((int) $id);\\n\\n if ($dokument === null) {\\n $this->json(['success' => false, 'error' => 'Dokument nicht gefunden'], 404);\\n\\n return;\\n }\\n\\n $this->json([\\n 'success' => true,\\n 'data' => [\\n 'dokument' => $dokument,\\n 'seiten' => $this->seiteRepository->getSeitenWithStatsForParent((int) $id),\\n 'taxonomy' => $this->seiteRepository->getTaxonomyForDokumentTree((int) $id),\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/seiten\\n *\/\\n public function listSeiten(): void\\n {\\n try {\\n $search = $this->getString('search');\\n $parentId = $this->getString('parent_id');\\n $limit = $this->getLimit(100, 50);\\n $offset = $this->getInt('offset');\\n\\n $total = $this->seiteRepository->countSeitenFiltered($search, $parentId);\\n $seiten = $this->seiteRepository->getSeitenPaginated($search, $parentId, $limit, $offset);\\n\\n $this->json([\\n 'success' => true,\\n 'data' => $seiten,\\n 'meta' => [\\n 'total' => $total,\\n 'limit' => $limit,\\n 'offset' => $offset,\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/seiten\/{id}\\n *\/\\n public function getSeite(string $id): void\\n {\\n try {\\n $seite = $this->seiteRepository->getSeiteWithParent((int) $id);\\n\\n if ($seite === null) {\\n $this->json(['success' => false, 'error' => 'Seite nicht gefunden'], 404);\\n\\n return;\\n }\\n\\n $chunks = $this->chunkRepository->getChunksDetailedForDokument((int) $id);\\n\\n \/\/ Decode JSON fields in chunks\\n foreach ($chunks as &$c) {\\n $c['entities'] = $this->decodeJsonArray($c['entities'] ?? null);\\n $c['keywords'] = $this->decodeJsonArray($c['keywords'] ?? null);\\n $c['taxonomy_path'] = $this->decodeJsonArray($c['taxonomy_path'] ?? null);\\n }\\n\\n $this->json([\\n 'success' => true,\\n 'data' => [\\n 'seite' => $seite,\\n 'chunks' => $chunks,\\n 'unterseiten' => $this->seiteRepository->getUnterseiten((int) $id),\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/chunks\\n *\/\\n public function listChunks(): void\\n {\\n try {\\n $category = $this->getString('category');\\n $status = $this->getString('status');\\n $search = $this->getString('search');\\n $limit = $this->getLimit(100, 50);\\n $offset = $this->getInt('offset');\\n\\n $total = $this->chunkRepository->countChunksFiltered($category, $status, $search);\\n $chunks = $this->chunkRepository->getChunksFilteredPaginated($category, $status, $search, $limit, $offset);\\n\\n $this->json([\\n 'success' => true,\\n 'data' => $chunks,\\n 'meta' => [\\n 'total' => $total,\\n 'limit' => $limit,\\n 'offset' => $offset,\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/chunks\/{id}\\n *\/\\n public function getChunk(string $id): void\\n {\\n try {\\n $chunk = $this->chunkRepository->getChunk((int) $id);\\n\\n if ($chunk === null) {\\n $this->json(['success' => false, 'error' => 'Chunk nicht gefunden'], 404);\\n\\n return;\\n }\\n\\n $this->json([\\n 'success' => true,\\n 'data' => $chunk,\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/taxonomie\\n *\/\\n public function taxonomie(): void\\n {\\n try {\\n $this->json([\\n 'success' => true,\\n 'data' => [\\n 'categories' => $this->chunkRepository->getTopTaxonomyCategories(100),\\n 'top_keywords' => $this->chunkRepository->getTopKeywords(50),\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * GET \/api\/v1\/explorer\/entities\\n *\/\\n public function entities(): void\\n {\\n try {\\n $this->json([\\n 'success' => true,\\n 'data' => $this->chunkRepository->getEntitiesGrouped(100),\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n\\n \/**\\n * POST \/api\/v1\/explorer\/suche\\n *\/\\n public function suche(): void\\n {\\n try {\\n $input = $this->getJsonInput();\\n\\n $query = trim($input['query'] ?? '');\\n if ($query === '') {\\n $this->json(['success' => false, 'error' => 'Query ist erforderlich'], 400);\\n\\n return;\\n }\\n\\n $filters = [];\\n if (!empty($input['category'])) {\\n $filters['taxonomy_category'] = $input['category'];\\n }\\n\\n $limit = min((int) ($input['limit'] ?? 10), 50);\\n\\n $results = $this->searchService->search($query, $filters, $limit);\\n $suggestions = $this->searchService->suggestRelatedSearches($results);\\n\\n $this->json([\\n 'success' => true,\\n 'data' => [\\n 'query' => $query,\\n 'results' => $results,\\n 'suggestions' => $suggestions,\\n 'count' => count($results),\\n ],\\n ]);\\n } catch (\\\\Exception $e) {\\n $this->jsonError($e->getMessage());\\n }\\n }\\n}\\n\",\n \"modified_at\": \"2025-12-25T12:34:35\",\n \"namespace\": \"Controller\\\\Api\",\n \"classes\": \"[{\\\"name\\\":\\\"ExplorerController\\\",\\\"type\\\":\\\"class\\\",\\\"line\\\":16}]\",\n \"functions\": \"[{\\\"name\\\":\\\"__construct\\\",\\\"visibility\\\":\\\"public\\\",\\\"line\\\":25},{\\\"name\\\":\\\"stats\\\",\\\"visibility\\\":\\\"public\\\",\\\"line\\\":40},{\\\"name\\\":\\\"listDokumente\\\",\\\"visibility\\\":\\\"public\\\",\\\"line\\\":60},{\\\"name\\\":\\\"getDokument\\\",\\\"visibility\\\":\\\"public\\\",\\\"line... [TRUNCATED-78364bd2440fb522]"
}
]
}