* * @throws FulltextException */ #[Query] #[Module(\Modules::PRODUCTS_SECTIONS, \Modules::SUB_ELASTICSEARCH)] public function autocomplete(string $term, array $types): \Generator { $invalidTypes = array_diff($types, $this->fulltext->getIndexTypes()); if ($invalidTypes) { throw new \Exception('Invalid types:'.implode(', ', $invalidTypes)); } $multiSearch = $this->searchClientFactory->createMultiSearch(); foreach ($types as $searchTopic) { $pager = new \Pager(); $pager->setOnPage(self::RESULTS_COUNT); $pager->setPageNumber(1); $search = $this->elasticQueryClient->createGenericSearch( searchTerm: $term, index: $searchTopic, pager: $pager, ); $multiSearch->addSearch($search, $searchTopic); } $response = $multiSearch->search(); foreach ($response->getResultSets() as $type => $result) { $items = array_map( static fn (Result $r) => array_merge($r->getSource(), ['id' => $r->getId()]), $result->getResults(), ); $items = $this->processFulltextItems($type, $items); yield new AutocompleteResult($type, $items, $result->getTotalHits()); } } /** * @param string[] $types * * @return \Generator * * @throws BadRequestHttpException */ #[Query] #[Module(\Modules::PRODUCTS_SECTIONS, \Modules::SUB_ELASTICSEARCH)] public function presearch(array $types): \Generator { $dbcfg = \Settings::getDefault(); $config = $dbcfg->fulltext['preload'] ?? []; if ($invalidTypes = array_diff($types, static::ALLOWED_PRESEARCH_TYPES)) { throw new BadRequestHttpException('Invalid types: '.implode(', ', $invalidTypes)); } $multiSearch = $this->searchClientFactory->createMultiSearch(); foreach ($types as $type) { if (empty($config[$type])) { continue; } $query = new \KupShop\CatalogElasticBundle\Elastica\Query(); $query->setQuery(new Ids($config[$type])); $search = $this->searchClientFactory->createSearch($type)->setQuery($query); $multiSearch->addSearch($search, $type); } if (empty($multiSearch->getSearches())) { return yield from []; } $resultSet = $multiSearch->search(); foreach ($resultSet->getResultSets() as $type => $result) { $items = $this->processFulltextItems($type, array_map(fn (Result $x) => ['id' => $x->getId(), ...$x->getSource()], $result->getResults())); yield new AutocompleteResult($type, $items, 0); } } protected function processFulltextItems(string $type, array $items) { $cfg = \Settings::getDefault(); $lang = Contexts::get(LanguageContext::class)->getActiveId(); $defaultImagePath = $this->systemImageUtils->getSystemImagePlaceholderPath(); if (!str_starts_with($defaultImagePath, '/')) { $defaultImagePath = '/'.$defaultImagePath; } if (!is_array($cfg['Photo']['placeholder'] ?? null)) { $placeholder = getVal('placeholder', $cfg['Photo'], $defaultImagePath); } if (empty($placeholder)) { $placeholder = $cfg['Photo']['placeholder']['lang'][$lang] ?? $cfg['Photo']['placeholder']['default'] ?? $defaultImagePath; } if ($type == FulltextElastic::INDEX_PRODUCTS) { foreach ($items as $item) { yield new AutocompleteProductResultItem($type, $item, $placeholder, $this->currencyContext, $this->priceConverter); } return; } foreach ($items as $item) { yield new AutocompleteResultItem($type, $item, $placeholder); } } }