src/Service/SearchService.php line 35
<?phpnamespace App\Service;use App\Dto\SearchResult;use App\Entity\Coleccion;use App\Entity\Composicion;use App\Entity\Destacada;use App\Entity\Modelo;use App\Entity\Programa;use App\Repository\ColeccionRepository;use App\Repository\ComposicionRepository;use App\Repository\DestacadaRepository;use App\Repository\ModeloRepository;use App\Repository\ProgramaRepository;class SearchService{public function __construct(private ModeloRepository $modeloRepository,private ColeccionRepository $coleccionRepository,private ComposicionRepository $composicionRepository,private ProgramaRepository $programaRepository,private DestacadaRepository $destacadaRepository) {}/*** Realiza una búsqueda global en todas las entidades** @param string $term Término de búsqueda* @param int $finalLimit Límite de resultados finales* @param int $perEntityLimit Límite de resultados por entidad (para ordenar después)* @return SearchResult[]*/public function globalSearch(string $term, int $finalLimit = 10, int $perEntityLimit = null): array{// Si no se especifica límite por entidad, usar el triple del límite final$perEntityLimit = $perEntityLimit ?? ($finalLimit * 3);$results = [];// Buscar en Modelos$modelos = $this->modeloRepository->searchByTerm($term, $perEntityLimit);foreach ($modelos as $modelo) {$results[] = $this->createSearchResultFromModelo($modelo);}// Buscar en Colecciones$colecciones = $this->coleccionRepository->searchByTerm($term, $perEntityLimit);foreach ($colecciones as $coleccion) {$results[] = $this->createSearchResultFromColeccion($coleccion);}// Buscar en Composiciones$composiciones = $this->composicionRepository->searchByTerm($term, $perEntityLimit);foreach ($composiciones as $composicion) {$results[] = $this->createSearchResultFromComposicion($composicion);}// Buscar en Programas$programas = $this->programaRepository->searchByTerm($term, $perEntityLimit);foreach ($programas as $programa) {$results[] = $this->createSearchResultFromPrograma($programa);}// Buscar en Destacadas$destacadas = $this->destacadaRepository->searchByTerm($term, $perEntityLimit);foreach ($destacadas as $destacada) {$results[] = $this->createSearchResultFromDestacada($destacada);}// Ordenar resultados por relevanciausort($results, function (SearchResult $a, SearchResult $b) use ($term) {$termLower = strtolower($term);$aNameLower = strtolower($a->getNombre());$bNameLower = strtolower($b->getNombre());$aDescLower = strtolower($a->getDescripcion() ?? '');$bDescLower = strtolower($b->getDescripcion() ?? '');// 1. Coincidencia exacta en el nombre$aExact = ($aNameLower === $termLower) ? 1 : 0;$bExact = ($bNameLower === $termLower) ? 1 : 0;if ($aExact !== $bExact) {return $bExact - $aExact;}// 2. Comienza con el término en el nombre$aStarts = str_starts_with($aNameLower, $termLower) ? 1 : 0;$bStarts = str_starts_with($bNameLower, $termLower) ? 1 : 0;if ($aStarts !== $bStarts) {return $bStarts - $aStarts;}// 3. Contiene el término en el nombre (antes que en descripción)$aInName = str_contains($aNameLower, $termLower) ? 1 : 0;$bInName = str_contains($bNameLower, $termLower) ? 1 : 0;if ($aInName !== $bInName) {return $bInName - $aInName;}// 4. Contiene el término en la descripción (menor prioridad)$aInDesc = str_contains($aDescLower, $termLower) ? 1 : 0;$bInDesc = str_contains($bDescLower, $termLower) ? 1 : 0;if ($aInDesc !== $bInDesc) {return $bInDesc - $aInDesc;}// 5. Orden alfabéticoreturn strcmp($aNameLower, $bNameLower);});// Limitar los resultados finalesreturn array_slice($results, 0, $finalLimit);}private function createSearchResultFromModelo(Modelo $modelo): SearchResult{return new SearchResult(type: 'modelo',id: $modelo->getId(),nombre: $modelo->getNombre(),descripcion: $modelo->getDescripcion(),metadata: ['coleccion' => $modelo->getColeccion()?->getNombre(),'ancho' => $modelo->getAncho(),'alto' => $modelo->getAlto(),'fondo' => $modelo->getFondo(),]);}private function createSearchResultFromColeccion(Coleccion $coleccion): SearchResult{return new SearchResult(type: 'coleccion',id: $coleccion->getId(),nombre: $coleccion->getNombre(),descripcion: $coleccion->getDescripcion(),metadata: ['programa' => $coleccion->getPrograma()?->getNombre(),]);}private function createSearchResultFromComposicion(Composicion $composicion): SearchResult{return new SearchResult(type: 'composicion',id: $composicion->getId(),nombre: $composicion->getNombre(),descripcion: null,metadata: ['modelo' => $composicion->getModelo()?->getNombre(),'precio' => $composicion->getPrecio(),]);}private function createSearchResultFromPrograma(Programa $programa): SearchResult{return new SearchResult(type: 'programa',id: $programa->getId(),nombre: $programa->getNombre(),descripcion: $programa->getDescripcion(),metadata: []);}private function createSearchResultFromDestacada(Destacada $destacada): SearchResult{return new SearchResult(type: 'destacada',id: $destacada->getId(),nombre: $destacada->getNombre(),descripcion: null,metadata: ['activo' => $destacada->getActivo(),]);}}