jsonFactory = $jsonFactory; $this->productCollectionFactory = $productCollectionFactory; $this->categoryCollectionFactory = $categoryCollectionFactory; $this->queryCollectionFactory = $queryCollectionFactory; $this->storeManager = $storeManager; $this->productVisibility = $productVisibility; $this->imageFactory = $imageFactory; $this->priceCurrency = $priceCurrency; $this->stockRegistry = $stockRegistry; } public function execute(): Json { $result = $this->jsonFactory->create(); $term = trim((string)$this->getRequest()->getParam('q')); if (mb_strlen($term) < 2) { return $result->setData(['suggestions' => [], 'products' => [], 'total' => 0]); } $store = $this->storeManager->getStore(); $like = '%' . addcslashes($term, '%_') . '%'; $products = $this->productCollectionFactory->create(); $products->setStore($store) ->addStoreFilter($store) ->setVisibility($this->productVisibility->getVisibleInSiteIds()) ->addAttributeToSelect(['name', 'sku', 'small_image', 'thumbnail', 'price', 'special_price']) ->addAttributeToFilter([ ['attribute' => 'name', 'like' => $like], ['attribute' => 'sku', 'like' => $like] ], null, 'left') ->addAttributeToSort('name', 'ASC') ->setPageSize(5) ->setCurPage(1); $total = (int)$products->getSize(); $productData = []; foreach ($products as $product) { try { $inStock = (bool)$this->stockRegistry->getStockItem((int)$product->getId())->getIsInStock(); } catch (\Throwable $exception) { $inStock = true; } $imageHelper = $this->imageFactory->create()->init($product, 'product_small_image'); $connection = $products->getConnection(); $galleryTable = $products->getTable('catalog_product_entity_media_gallery'); $linkTable = $products->getTable('catalog_product_entity_media_gallery_value_to_entity'); $imageFile = $connection->fetchOne( $connection->select() ->from(['gallery' => $galleryTable], ['value']) ->joinInner(['link' => $linkTable], 'link.value_id = gallery.value_id', []) ->where('link.entity_id = ?', (int)$product->getId()) ->order('gallery.value_id ASC') ->limit(1) ); $imageUrl = ''; if ($imageFile) { $localImage = BP . '/pub/media/catalog/product' . $imageFile; if (is_file($localImage)) { $imageHelper->setImageFile((string)$imageFile); } else { $imageUrl = 'https://ltsecurityinc.com/media/catalog/product' . $imageFile; } } $productData[] = [ 'id' => (int)$product->getId(), 'name' => (string)$product->getName(), 'sku' => (string)$product->getSku(), 'url' => (string)$product->getProductUrl(), 'image' => $imageUrl ?: $imageHelper->resize(86, 86)->getUrl(), 'price' => $this->priceCurrency->format((float)$product->getFinalPrice(), false), 'in_stock' => $inStock, 'add_url' => $this->_url->getUrl('checkout/cart/add', ['product' => (int)$product->getId()]) ]; } return $result->setData([ 'suggestions' => $this->getSuggestions($term, (int)$store->getId(), $productData), 'products' => $productData, 'total' => $total, 'search_url' => $this->_url->getUrl('catalogsearch/result', ['q' => $term]) ]); } private function getSuggestions(string $term, int $storeId, array $products): array { $suggestions = []; $this->appendSuggestion($suggestions, $term); $queries = $this->queryCollectionFactory->create(); $queries->setStoreId($storeId)->setQueryFilter($term)->setPageSize(8); foreach ($queries as $query) { $this->appendSuggestion($suggestions, (string)$query->getQueryText()); } $matchedCategories = $this->categoryCollectionFactory->create(); $matchedCategories->setStoreId($storeId) ->addAttributeToSelect(['name', 'path', 'level']) ->addAttributeToFilter('is_active', 1) ->addAttributeToFilter('name', ['like' => '%' . addcslashes($term, '%_') . '%']) ->setPageSize(5); foreach ($matchedCategories as $category) { $this->appendSuggestion($suggestions, (string)$category->getName()); if (count($suggestions) >= 8) { break; } $children = $this->categoryCollectionFactory->create(); $children->setStoreId($storeId) ->addAttributeToSelect(['name', 'level']) ->addAttributeToFilter('is_active', 1) ->addFieldToFilter('path', ['like' => '%/' . (int)$category->getId() . '/%']) ->addFieldToFilter('level', ['lteq' => (int)$category->getLevel() + 2]) ->setPageSize(8); foreach ($children as $child) { $name = (string)$child->getName(); $label = stripos($name, $term) === false ? $term . ' ' . $name : $name; $this->appendSuggestion($suggestions, $label); if (count($suggestions) >= 8) { break 2; } } } foreach ($products as $product) { $this->appendSuggestion($suggestions, (string)$product['name']); if (count($suggestions) >= 8) { break; } } return array_slice(array_values($suggestions), 0, 8); } private function appendSuggestion(array &$suggestions, string $label): void { $label = trim(preg_replace('/\s+/', ' ', $label) ?: ''); if ($label === '') { return; } $key = mb_strtolower($label); if (!isset($suggestions[$key])) { $suggestions[$key] = ['title' => $label]; } } }