195 lines
7.8 KiB
PHP
195 lines
7.8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Controllers;
|
||
|
||
use App\Core\Database;
|
||
use App\Repositories\CategoryRepository;
|
||
use App\Repositories\ProductRepository;
|
||
use App\Repositories\SettingRepository;
|
||
use Throwable;
|
||
|
||
final class HomeController
|
||
{
|
||
public function index(): void
|
||
{
|
||
$dbStatus = 'not_checked';
|
||
$categories = [];
|
||
$catalogProducts = [];
|
||
$popularProducts = [];
|
||
$homeCatalogSections = [];
|
||
$settings = [];
|
||
$notice = null;
|
||
|
||
try {
|
||
Database::pdo()->query('SELECT 1');
|
||
$dbStatus = 'connected';
|
||
|
||
$categoryRepository = new CategoryRepository();
|
||
$categories = $categoryRepository->tree();
|
||
$productRepository = new ProductRepository();
|
||
$catalogProducts = $productRepository->catalogPreview(24);
|
||
$popularProducts = $productRepository->popularPreview(10);
|
||
$homeCatalogSections[] = [
|
||
'key' => 'promos',
|
||
'title' => 'Акции',
|
||
'url' => '/catalog',
|
||
'count' => 10,
|
||
'kind' => 'promo',
|
||
'products' => $productRepository->promoPreview(10),
|
||
];
|
||
$homeCatalogSections[] = [
|
||
'key' => 'new',
|
||
'title' => 'Новинки',
|
||
'url' => '/catalog',
|
||
'count' => 50,
|
||
'kind' => 'new',
|
||
'products' => $productRepository->newPreview(10),
|
||
];
|
||
|
||
foreach ([
|
||
['slugs' => ['ikra'], 'title' => 'Икра'],
|
||
['slugs' => ['ryba'], 'title' => 'Рыба'],
|
||
['slugs' => ['moreprodukty'], 'title' => 'Морепродукты'],
|
||
['slugs' => ['myaso'], 'title' => 'Мясо'],
|
||
['slugs' => ['polufabrikaty'], 'title' => 'Полуфабрикаты'],
|
||
['slugs' => ['syry'], 'title' => 'Сыры'],
|
||
['slugs' => ['frukty-ovoschi-yagody-griby'], 'title' => 'Фрукты, овощи, ягоды, грибы'],
|
||
['slugs' => ['mramornaya-govyadina'], 'title' => 'Мраморная говядина'],
|
||
['slugs' => ['kopchenaya-ryba', 'kopchenaya-riba-1'], 'title' => 'Копченая рыба'],
|
||
['slugs' => ['vyalenaya-ryba', 'vylaenaya-riba'], 'title' => 'Вяленая рыба'],
|
||
['slugs' => ['malosolnaya-ryba', 'malosolnaya-riba'], 'title' => 'Малосольная рыба'],
|
||
] as $sectionConfig) {
|
||
$categoryMatch = $this->homeCategoryShowcase(
|
||
$categoryRepository,
|
||
$productRepository,
|
||
$categories,
|
||
$sectionConfig['slugs'],
|
||
$sectionConfig['title']
|
||
);
|
||
|
||
if ($categoryMatch === null) {
|
||
continue;
|
||
}
|
||
|
||
$category = $categoryMatch['category'];
|
||
$showcase = $categoryMatch['showcase'];
|
||
$slug = (string) ($sectionConfig['slugs'][0] ?? $category['slug']);
|
||
$homeCatalogSections[] = [
|
||
'key' => $slug,
|
||
'title' => $sectionConfig['title'],
|
||
'url' => '/catalog/' . $category['slug'],
|
||
'count' => $showcase['total'],
|
||
'kind' => 'category',
|
||
'products' => $showcase['products'],
|
||
];
|
||
}
|
||
$settings = (new SettingRepository())->allKeyed();
|
||
} catch (Throwable $exception) {
|
||
$dbStatus = app_env('APP_DEBUG', 'false') === 'true'
|
||
? 'error: ' . $exception->getMessage()
|
||
: 'error';
|
||
$notice = 'Если таблицы еще не созданы, откройте страницу установки базы.';
|
||
}
|
||
|
||
view('pages/home', [
|
||
'title' => 'Рыбсток - качественные продукты по стоковым ценам с доставкой',
|
||
'metaDescription' => 'Рыбсток - интернет-склад качественной рыбы, морепродуктов, мяса, сыров, овощей, ягод и бакалеи по стоковым ценам. Бесплатная доставка по Москве и Московской области, самовывоз с ул. Привольная.',
|
||
'metaKeywords' => 'Рыбсток, рыба доставка Москва, морепродукты доставка Москва, мясо доставка Москва, сыры доставка, икра доставка Москва, овощи ягоды заморозка, бакалея с доставкой, продукты по стоковым ценам, интернет склад продуктов, бесплатная доставка продуктов Москва, доставка продуктов Московская область',
|
||
'breadcrumbs' => [
|
||
['title' => 'Главная'],
|
||
],
|
||
'showBackButton' => false,
|
||
'dbStatus' => $dbStatus,
|
||
'categories' => $categories,
|
||
'catalogProducts' => $catalogProducts,
|
||
'popularProducts' => $popularProducts,
|
||
'homeCatalogSections' => $homeCatalogSections,
|
||
'settings' => $settings,
|
||
'notice' => $notice,
|
||
'buildVersion' => '2026-06-04-02',
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* @param array<int, array<string, mixed>> $categoryTree
|
||
* @param array<int, string> $slugs
|
||
* @return array{category: array<string, mixed>, showcase: array{products: array<int, array<string, mixed>>, total: int}}|null
|
||
*/
|
||
private function homeCategoryShowcase(
|
||
CategoryRepository $categoryRepository,
|
||
ProductRepository $productRepository,
|
||
array $categoryTree,
|
||
array $slugs,
|
||
string $title
|
||
): ?array {
|
||
$candidates = [];
|
||
$seenIds = [];
|
||
|
||
foreach ($slugs as $slug) {
|
||
$category = $categoryRepository->findBySlug($slug);
|
||
if ($category !== null) {
|
||
$categoryId = (int) $category['id'];
|
||
$seenIds[$categoryId] = true;
|
||
$candidates[] = $category;
|
||
}
|
||
}
|
||
|
||
foreach ($this->findCategoriesByName($categoryTree, $title) as $category) {
|
||
$categoryId = (int) $category['id'];
|
||
if (isset($seenIds[$categoryId])) {
|
||
continue;
|
||
}
|
||
|
||
$seenIds[$categoryId] = true;
|
||
$candidates[] = $category;
|
||
}
|
||
|
||
$fallback = null;
|
||
foreach ($candidates as $category) {
|
||
$showcase = $productRepository->categoryRetailShowcase((int) $category['id'], 10);
|
||
$match = [
|
||
'category' => $category,
|
||
'showcase' => $showcase,
|
||
];
|
||
|
||
if ($showcase['products'] !== []) {
|
||
return $match;
|
||
}
|
||
|
||
$fallback ??= $match;
|
||
}
|
||
|
||
return $fallback;
|
||
}
|
||
|
||
/**
|
||
* @param array<int, array<string, mixed>> $categories
|
||
* @return array<int, array<string, mixed>>
|
||
*/
|
||
private function findCategoriesByName(array $categories, string $name): array
|
||
{
|
||
$matches = [];
|
||
$normalizedName = $this->normalizeCategoryName($name);
|
||
|
||
foreach ($categories as $category) {
|
||
if ($this->normalizeCategoryName((string) ($category['name'] ?? '')) === $normalizedName) {
|
||
$matches[] = $category;
|
||
}
|
||
|
||
$matches = array_merge(
|
||
$matches,
|
||
$this->findCategoriesByName($category['children'] ?? [], $name)
|
||
);
|
||
}
|
||
|
||
return $matches;
|
||
}
|
||
|
||
private function normalizeCategoryName(string $name): string
|
||
{
|
||
return trim(str_replace('ё', 'е', mb_strtolower($name)));
|
||
}
|
||
}
|