EnhancedSearchUseCase.php
- Pfad:
src/UseCases/Search/EnhancedSearchUseCase.php - Namespace: UseCases\Search
- Zeilen: 237 | Größe: 7,677 Bytes
- Geändert: 2025-12-28 23:32:20 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 91
- Dependencies: 100 (25%)
- LOC: 56 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 6
- constructor Domain\Service\SearchServiceInterface
- constructor Domain\Repository\ChunkTaxonomyRepositoryInterface
- constructor Domain\Repository\TaxonomyRepositoryInterface
- use Domain\Repository\ChunkTaxonomyRepositoryInterface
- use Domain\Repository\TaxonomyRepositoryInterface
- use Domain\Service\SearchServiceInterface
Klassen 1
-
EnhancedSearchUseCaseclass Zeile 13
Funktionen 6
-
__construct()public Zeile 15 -
execute()public Zeile 38 -
searchInTaxonomy()public Zeile 105 -
getSuggestionsForQuery()public Zeile 122 -
expandWithChildTerms()private Zeile 180 -
getChunkIdsForTerms()private Zeile 220
Versionen 6
-
v6
2025-12-28 23:32 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v5
2025-12-28 23:32 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v4
2025-12-28 23:32 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-25 20:19 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-25 20:19 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-25 20:17 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
Code
<?php
declare(strict_types=1);
namespace UseCases\Search;
// @responsibility: Erweiterte Suche mit Taxonomie-Term-ID-Filterung
use Domain\Repository\ChunkTaxonomyRepositoryInterface;
use Domain\Repository\TaxonomyRepositoryInterface;
use Domain\Service\SearchServiceInterface;
final class EnhancedSearchUseCase
{
public function __construct(
private SearchServiceInterface $searchService,
private ChunkTaxonomyRepositoryInterface $chunkTaxonomyRepository,
private TaxonomyRepositoryInterface $taxonomyRepository
) {
}
/**
* Enhanced search with taxonomy term ID filtering.
*
* @param string $query Search query
* @param array<int> $taxonomyTermIds Filter by these taxonomy term IDs
* @param bool $includeChildTerms Include child terms in filter (recursive)
* @param int $limit Maximum results
* @return array{
* results: array<array<string, mixed>>,
* taxonomy_filter: array{term_ids: array<int>, chunk_ids: array<int>},
* total_before_filter: int,
* total_after_filter: int
* }
*
* @throws \RuntimeException When search service or repository operations fail
*/
public function execute(
string $query,
array $taxonomyTermIds = [],
bool $includeChildTerms = false,
int $limit = 10
): array {
// If no taxonomy filter, delegate directly to search service
if (empty($taxonomyTermIds)) {
$results = $this->searchService->search($query, [], $limit);
return [
'results' => $results,
'taxonomy_filter' => ['term_ids' => [], 'chunk_ids' => []],
'total_before_filter' => count($results),
'total_after_filter' => count($results),
];
}
// Expand term IDs if includeChildTerms is true
$effectiveTermIds = $includeChildTerms
? $this->expandWithChildTerms($taxonomyTermIds)
: $taxonomyTermIds;
// Get chunk IDs that match the taxonomy filter
$filteredChunkIds = $this->getChunkIdsForTerms($effectiveTermIds);
if (empty($filteredChunkIds)) {
return [
'results' => [],
'taxonomy_filter' => ['term_ids' => $effectiveTermIds, 'chunk_ids' => []],
'total_before_filter' => 0,
'total_after_filter' => 0,
];
}
// Perform search with higher limit to allow for filtering
$searchResults = $this->searchService->search($query, [], $limit * 5);
$totalBeforeFilter = count($searchResults);
// Filter results to only include chunks matching taxonomy
$filteredResults = array_filter(
$searchResults,
static fn (array $result): bool => in_array($result['chunk_id'] ?? 0, $filteredChunkIds, true)
);
// Re-index and limit
$filteredResults = array_values($filteredResults);
$limitedResults = array_slice($filteredResults, 0, $limit);
return [
'results' => $limitedResults,
'taxonomy_filter' => [
'term_ids' => $effectiveTermIds,
'chunk_ids' => $filteredChunkIds,
],
'total_before_filter' => $totalBeforeFilter,
'total_after_filter' => count($filteredResults),
];
}
/**
* Search within a specific taxonomy term and its children.
*
* @return array<array<string, mixed>>
*
* @throws \RuntimeException When search service or repository operations fail
*/
public function searchInTaxonomy(string $query, int $termId, int $limit = 10): array
{
$result = $this->execute($query, [$termId], true, $limit);
return $result['results'];
}
/**
* Get search suggestions based on taxonomy structure.
*
* @return array{
* terms: array<array{id: int, name: string, chunk_count: int}>,
* suggested_filters: array<int>
* }
*
* @throws \RuntimeException When search service or repository operations fail
*/
public function getSuggestionsForQuery(string $query): array
{
// First, get search results without filter
$results = $this->searchService->search($query, [], 20);
if (empty($results)) {
return ['terms' => [], 'suggested_filters' => []];
}
// Extract chunk IDs from results
$chunkIds = array_map(
static fn (array $r): int => (int) ($r['chunk_id'] ?? 0),
$results
);
$chunkIds = array_filter($chunkIds);
// Find common taxonomy terms for these chunks
$termCounts = [];
foreach ($chunkIds as $chunkId) {
$mappings = $this->chunkTaxonomyRepository->findByChunkId($chunkId);
foreach ($mappings as $mapping) {
$termId = $mapping->getTaxonomyTermId();
if (!isset($termCounts[$termId])) {
$termCounts[$termId] = 0;
}
$termCounts[$termId]++;
}
}
// Sort by count and get top terms
arsort($termCounts);
$topTermIds = array_slice(array_keys($termCounts), 0, 5);
// Get term details
$terms = [];
foreach ($topTermIds as $termId) {
$term = $this->taxonomyRepository->find($termId);
if ($term !== null) {
$terms[] = [
'id' => $termId,
'name' => $term['name'],
'chunk_count' => $termCounts[$termId],
];
}
}
return [
'terms' => $terms,
'suggested_filters' => $topTermIds,
];
}
/**
* Expand term IDs to include all child terms.
*
* @param array<int> $termIds
* @return array<int>
*/
private function expandWithChildTerms(array $termIds): array
{
$allTerms = $this->taxonomyRepository->findAll();
$expanded = $termIds;
// Build parent-child map
$childrenMap = [];
foreach ($allTerms as $term) {
$parentId = $term['parent_id'];
if ($parentId !== null) {
if (!isset($childrenMap[$parentId])) {
$childrenMap[$parentId] = [];
}
$childrenMap[$parentId][] = $term['id'];
}
}
// Recursively add children
$queue = $termIds;
while (!empty($queue)) {
$currentId = array_shift($queue);
if (isset($childrenMap[$currentId])) {
foreach ($childrenMap[$currentId] as $childId) {
if (!in_array($childId, $expanded, true)) {
$expanded[] = $childId;
$queue[] = $childId;
}
}
}
}
return $expanded;
}
/**
* Get chunk IDs that have mappings to any of the given taxonomy terms.
*
* @param array<int> $termIds
* @return array<int>
*/
private function getChunkIdsForTerms(array $termIds): array
{
$chunkIds = [];
foreach ($termIds as $termId) {
$mappings = $this->chunkTaxonomyRepository->findByTaxonomyTermId($termId);
foreach ($mappings as $mapping) {
$chunkId = $mapping['chunk_id'];
if ($chunkId > 0 && !in_array($chunkId, $chunkIds, true)) {
$chunkIds[] = $chunkId;
}
}
}
return $chunkIds;
}
}