SemanticExplorerController.php
- Pfad:
src/Controller/SemanticExplorerController.php - Namespace: Controller
- Zeilen: 300 | Größe: 9,817 Bytes
- Geändert: 2025-12-28 03:05:08 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 95
- Dependencies: 80 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 14
- extends Framework\Controller
- constructor Domain\Repository\DocumentRepositoryInterface
- constructor Domain\Repository\ChunkRepositoryInterface
- constructor Domain\Repository\EntityRepositoryInterface
- constructor Domain\Repository\RelationRepositoryInterface
- constructor Domain\Repository\SemanticSearchRepositoryInterface
- constructor Infrastructure\AI\VectorSearchService
- use Domain\Repository\ChunkRepositoryInterface
- use Domain\Repository\DocumentRepositoryInterface
- use Domain\Repository\EntityRepositoryInterface
- use Domain\Repository\RelationRepositoryInterface
- use Domain\Repository\SemanticSearchRepositoryInterface
- use Framework\Controller
- use Infrastructure\AI\VectorSearchService
Klassen 1
-
SemanticExplorerControllerclass Zeile 17
Funktionen 11
-
__construct()public Zeile 26 -
index()public Zeile 46 -
dokumente()public Zeile 72 -
dokumentShow()public Zeile 91 -
chunks()public Zeile 118 -
chunkShow()public Zeile 143 -
suche()public Zeile 181 -
vectorSearch()private Zeile 215 -
semantik()public Zeile 248 -
graph()public Zeile 278 -
graphData()public Zeile 294
Versionen 56
-
v56
2025-12-28 03:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v55
2025-12-28 02:54 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v54
2025-12-27 12:18 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v53
2025-12-25 09:22 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v52
2025-12-25 09:22 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v51
2025-12-25 09:22 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v50
2025-12-25 09:22 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v49
2025-12-25 09:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v48
2025-12-25 09:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v47
2025-12-25 09:20 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v46
2025-12-25 02:29 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v45
2025-12-25 02:29 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v44
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v43
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v42
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v41
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v40
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v39
2025-12-25 02:26 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v38
2025-12-25 02:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v37
2025-12-25 02:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v36
2025-12-25 02:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v35
2025-12-23 16:41 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v34
2025-12-23 16:40 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v33
2025-12-23 07:53 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v32
2025-12-23 07:00 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v31
2025-12-23 04:47 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v30
2025-12-23 04:42 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v29
2025-12-23 04:24 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v28
2025-12-22 08:11 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v27
2025-12-22 08:11 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v26
2025-12-22 08:11 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v25
2025-12-22 08:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v24
2025-12-22 08:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v23
2025-12-22 08:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v22
2025-12-22 08:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v21
2025-12-22 08:00 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v20
2025-12-22 08:00 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v19
2025-12-22 08:00 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v18
2025-12-22 08:00 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v17
2025-12-22 02:07 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v16
2025-12-22 02:07 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v15
2025-12-22 02:06 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v14
2025-12-22 02:05 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v13
2025-12-22 02:04 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v12
2025-12-22 02:04 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v11
2025-12-22 02:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v10
2025-12-22 02:02 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v9
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v8
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v7
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v6
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v5
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v4
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-22 01:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-20 17:44 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-20 16:35 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Write-Operation
Code
<?php
declare(strict_types=1);
namespace Controller;
// @responsibility: HTTP-Endpunkte für Semantic Explorer (Nutzdaten, Vektor-Suche)
use Domain\Repository\ChunkRepositoryInterface;
use Domain\Repository\DocumentRepositoryInterface;
use Domain\Repository\EntityRepositoryInterface;
use Domain\Repository\RelationRepositoryInterface;
use Domain\Repository\SemanticSearchRepositoryInterface;
use Framework\Controller;
use Infrastructure\AI\VectorSearchService;
class SemanticExplorerController extends Controller
{
private DocumentRepositoryInterface $documentRepository;
private ChunkRepositoryInterface $chunkRepository;
private EntityRepositoryInterface $entityRepository;
private RelationRepositoryInterface $relationRepository;
private SemanticSearchRepositoryInterface $semanticSearchRepository;
private VectorSearchService $vectorSearchService;
public function __construct(
DocumentRepositoryInterface $documentRepository,
ChunkRepositoryInterface $chunkRepository,
EntityRepositoryInterface $entityRepository,
RelationRepositoryInterface $relationRepository,
SemanticSearchRepositoryInterface $semanticSearchRepository,
VectorSearchService $vectorSearchService
) {
$this->documentRepository = $documentRepository;
$this->chunkRepository = $chunkRepository;
$this->entityRepository = $entityRepository;
$this->relationRepository = $relationRepository;
$this->semanticSearchRepository = $semanticSearchRepository;
$this->vectorSearchService = $vectorSearchService;
}
/**
* GET /semantic-explorer
* Dashboard mit Statistiken
*/
public function index(): void
{
$docStats = $this->documentRepository->getStats();
$chunkStats = $this->chunkRepository->getStats();
$semanticStats = $this->semanticSearchRepository->getSemanticStats();
$textSemanticStats = $this->semanticSearchRepository->getTextSemanticStats();
$knowledgeSemanticStats = $this->semanticSearchRepository->getKnowledgeSemanticStats();
$documents = $this->documentRepository->findAll();
$recentChunks = $this->chunkRepository->findRecent(5);
$this->view('semantic-explorer.index', [
'title' => 'Semantic Explorer',
'docStats' => $docStats,
'chunkStats' => $chunkStats,
'semanticStats' => $semanticStats,
'textSemanticStats' => $textSemanticStats,
'knowledgeSemanticStats' => $knowledgeSemanticStats,
'documents' => $documents,
'recentChunks' => $recentChunks,
]);
}
/**
* GET /semantic-explorer/dokumente
* Liste aller Dokumente
*/
public function dokumente(): void
{
$status = $this->getString('status');
$search = $this->getString('search');
$documents = $this->documentRepository->findFiltered($status, $search);
$this->view('semantic-explorer.dokumente.index', [
'title' => 'Dokumente',
'documents' => $documents,
'currentStatus' => $status,
'currentSearch' => $search,
]);
}
/**
* GET /semantic-explorer/dokumente/{id}
* Dokument-Details mit Chunks
*/
public function dokumentShow(int $id): void
{
$document = $this->documentRepository->find($id);
if ($document === null) {
$this->notFound('Dokument nicht gefunden');
}
$chunks = $this->chunkRepository->findByDocument($id);
// Heading-Paths dekodieren
foreach ($chunks as &$chunk) {
$chunk['heading_path_decoded'] = $this->decodeJson($chunk['heading_path'] ?? null);
$chunk['metadata_decoded'] = $this->decodeJson($chunk['metadata'] ?? null);
}
$this->view('semantic-explorer.dokumente.show', [
'title' => $document['filename'],
'document' => $document,
'chunks' => $chunks,
]);
}
/**
* GET /semantic-explorer/chunks
* Liste aller Chunks
*/
public function chunks(): void
{
$search = $this->getString('search');
$embedded = $this->getString('embedded');
$pagination = $this->getPagination(50);
$totalCount = $this->chunkRepository->count($search, $embedded);
$chunks = $this->chunkRepository->findFiltered($search, $embedded, $pagination->limit, $pagination->offset);
$pagination = $pagination->withTotal($totalCount);
$this->view('semantic-explorer.chunks.index', [
'title' => 'Chunks',
'chunks' => $chunks,
'currentSearch' => $search,
'currentEmbedded' => $embedded,
'currentPage' => $pagination->page,
'totalCount' => $pagination->totalCount,
'totalPages' => $pagination->totalPages(),
]);
}
/**
* GET /semantic-explorer/chunks/{id}
* Chunk-Details
*/
public function chunkShow(int $id): void
{
$chunk = $this->chunkRepository->find($id);
if ($chunk === null) {
$this->notFound('Chunk nicht gefunden');
}
// JSON-Felder dekodieren
$chunk['heading_path_decoded'] = $this->decodeJson($chunk['heading_path'] ?? null);
$chunk['metadata_decoded'] = $this->decodeJson($chunk['metadata'] ?? null);
// Nachbar-Chunks
$prevChunk = $this->chunkRepository->findByDocumentAndIndex(
$chunk['document_id'],
$chunk['chunk_index'] - 1
);
$nextChunk = $this->chunkRepository->findByDocumentAndIndex(
$chunk['document_id'],
$chunk['chunk_index'] + 1
);
// Text-Semantik laden
$textSemantics = $this->chunkRepository->getTextSemantics($id);
$this->view('semantic-explorer.chunks.show', [
'title' => 'Chunk #' . $chunk['id'],
'chunk' => $chunk,
'prevChunk' => $prevChunk,
'nextChunk' => $nextChunk,
'textSemantics' => $textSemantics,
]);
}
/**
* GET /semantic-explorer/suche
* Semantische Suche in Nutzdaten
*/
public function suche(): void
{
$query = $this->getString('q');
$limit = $this->getLimit(20, 10);
$results = [];
if ($query !== '') {
// Vektor-Suche via Qdrant
$results = $this->vectorSearch($query, $limit);
}
// HTMX: Return only search results partial
if ($this->isHtmxRequest()) {
$this->partial('semantic-explorer.partials.search-results', [
'query' => $query,
'results' => $results,
'limit' => $limit,
]);
return;
}
$this->view('semantic-explorer.suche', [
'title' => 'Semantische Suche',
'query' => $query,
'results' => $results,
'limit' => $limit,
]);
}
/**
* Vektor-Suche in documents Collection using VectorSearchService
*/
private function vectorSearch(string $query, int $limit): array
{
// Search via service
$response = $this->vectorSearchService->search($query, 'documents', $limit);
if (empty($response)) {
return [];
}
// Chunk-Details aus DB laden
$results = [];
foreach ($response as $point) {
$chunkId = $point['payload']['chunk_id'] ?? null;
if ($chunkId === null) {
continue;
}
$chunk = $this->chunkRepository->find($chunkId);
if ($chunk !== null) {
$chunk['score'] = $point['score'];
$chunk['heading_path_decoded'] = $this->decodeJson($chunk['heading_path'] ?? null);
$results[] = $chunk;
}
}
return $results;
}
/**
* GET /semantic-explorer/semantik
* Begriffe mit Bedeutungen
*/
public function semantik(): void
{
$search = $this->getString('search');
$type = $this->getString('type');
$pagination = $this->getPagination(50);
$totalCount = $this->semanticSearchRepository->countEntitySemantics($search, $type);
$semantics = $this->semanticSearchRepository->findEntitySemantics($search, $type, $pagination->limit, $pagination->offset);
$pagination = $pagination->withTotal($totalCount);
$stats = $this->semanticSearchRepository->getSemanticStats();
$entityTypes = $this->entityRepository->getStats();
$this->view('semantic-explorer.semantik', [
'title' => 'Semantik',
'semantics' => $semantics,
'stats' => $stats,
'entityTypes' => $entityTypes,
'currentSearch' => $search,
'currentType' => $type,
'currentPage' => $pagination->page,
'totalCount' => $pagination->totalCount,
'totalPages' => $pagination->totalPages(),
]);
}
/**
* GET /semantic-explorer/graph
* Entity-Relations Graph Visualisierung
*/
public function graph(): void
{
$entityTypes = $this->entityRepository->getStats();
$relationTypes = $this->relationRepository->getTypes();
$this->view('semantic-explorer.graph', [
'title' => 'Entity Graph',
'entityTypes' => $entityTypes,
'relationTypes' => $relationTypes,
]);
}
/**
* GET /semantic-explorer/graph-data
* JSON-Daten für Graph-Visualisierung
*/
public function graphData(): void
{
$data = $this->semanticSearchRepository->getGraphData();
$this->json($data);
}
}