index(); return; } $_GET['q'] = $query; $perPage = 48; $limit = isset($_GET['limit']) ? max($perPage, min((int) $_GET['limit'], 5000)) : $perPage; $page = max(1, (int) ($_GET['page'] ?? 1)); $offset = isset($_GET['limit']) ? 0 : (($page - 1) * $perPage); $categoryRepository = new CategoryRepository(); $productRepository = new ProductRepository(); if (method_exists($productRepository, 'searchCatalog')) { $searchResult = $productRepository->searchCatalog($query, $limit, $offset, true); $products = $searchResult['products']; $total = $searchResult['total']; } else { $allProducts = $productRepository->catalogPreview(5000, 0, true); $needle = function_exists('mb_strtolower') ? mb_strtolower($query, 'UTF-8') : strtolower($query); $words = array_values(array_filter(preg_split('/\s+/u', $needle) ?: [])); $ranked = []; foreach ($allProducts as $product) { $haystack = implode(' ', [ (string) ($product['name'] ?? ''), (string) ($product['short_description'] ?? ''), (string) ($product['category_name'] ?? ''), (string) ($product['display_category_name'] ?? ''), (string) ($product['categories_path'] ?? ''), ]); $haystack = function_exists('mb_strtolower') ? mb_strtolower($haystack, 'UTF-8') : strtolower($haystack); $score = 0; if ($needle !== '' && str_contains($haystack, $needle)) { $score += 100; } foreach ($words as $word) { if ($word !== '' && str_contains($haystack, $word)) { $score += 20; } } if ($score > 0) { $product['_search_score'] = $score; $ranked[] = $product; } } usort($ranked, static fn (array $a, array $b): int => ($b['_search_score'] ?? 0) <=> ($a['_search_score'] ?? 0)); $total = count($ranked); $products = array_slice($ranked, $offset, $limit); } $shown = min($total, $offset + count($products)); $basePath = '/search/' . rawurlencode($query); view('catalog/index', [ 'title' => 'Поиск по каталогу Рыбсток - ' . $query, 'metaDescription' => 'Результаты поиска по каталогу Рыбсток: ' . $query, 'metaKeywords' => $query . ', Рыбсток, каталог продуктов', 'breadcrumbs' => [ ['title' => 'Главная', 'url' => '/'], ['title' => 'Каталог', 'url' => '/catalog'], ['title' => 'Поиск'], ], 'categories' => $categoryRepository->tree(), 'currentCategory' => null, 'products' => $products, 'searchQuery' => $query, 'pagination' => [ 'base_path' => $basePath, 'total' => $total, 'shown' => $shown, 'page' => $page, 'pages' => max(1, (int) ceil($total / $perPage)), 'per_page' => $perPage, 'limit' => $limit, 'has_more' => $shown < $total, 'next_limit' => min($total, max($shown, $limit) + $perPage), 'cumulative' => isset($_GET['limit']), ], ]); }; $router->get('/', static fn () => (new HomeController())->index()); $router->post('/price-request', static fn () => (new PriceRequestController())->store()); $router->get('/search', static fn () => $catalogSearchHandler()); $router->get('/search/{query}', static fn (string $query) => $catalogSearchHandler($query)); $router->get('/catalog', static fn () => trim((string) ($_GET['q'] ?? '')) !== '' ? $catalogSearchHandler() : (new CatalogController())->index()); $router->get('/delivery', static fn () => (new PageController())->delivery()); $router->get('/payment', static fn () => (new PageController())->payment()); $router->get('/contacts', static fn () => (new PageController())->contacts()); $router->get('/returns', static fn () => (new PageController())->returns()); $router->get('/cart', static fn () => (new PageController())->cart()); $router->get('/product/{slug}', static fn (string $slug) => (new CatalogController())->product($slug)); $router->get('/catalog/{slug}', static fn (string $slug) => (new CatalogController())->category($slug)); $router->dispatch($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);