Files
new.rybstock.ru/app/Controllers/CatalogController.php
T
2026-06-05 19:57:23 +03:00

166 lines
7.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Repositories\CategoryRepository;
use App\Repositories\ProductRepository;
final class CatalogController
{
public function index(): void
{
$categoryRepository = new CategoryRepository();
$productRepository = new ProductRepository();
$pagination = $this->paginationInput();
$totalProducts = $productRepository->catalogTotal(true);
$products = $productRepository->catalogPreview($pagination['limit'], $pagination['offset'], true);
view('catalog/index', [
'title' => 'Каталог Рыбсток - рыба, морепродукты, мясо, сыры и продукты',
'metaDescription' => 'Полный каталог Рыбсток: рыба, морепродукты, икра, мясо, сыры, полуфабрикаты, овощи, ягоды и бакалея по стоковым ценам с доставкой по Москве и Московской области.',
'metaKeywords' => 'каталог Рыбсток, купить рыбу Москва, морепродукты Москва, мясо доставка Москва, сыры доставка, икра, полуфабрикаты, овощи ягоды заморозка, бакалея, продукты по стоковым ценам',
'breadcrumbs' => [
['title' => 'Главная', 'url' => '/'],
['title' => 'Каталог'],
],
'categories' => $categoryRepository->tree(),
'currentCategory' => null,
'products' => $products,
'pagination' => $this->paginationData('/catalog', $totalProducts, count($products), $pagination),
]);
}
public function category(string $slug): void
{
$categoryRepository = new CategoryRepository();
$productRepository = new ProductRepository();
$category = $categoryRepository->findBySlug($slug);
if ($category === null) {
http_response_code(404);
view('pages/404', [
'title' => 'Категория не найдена - Рыбсток',
'breadcrumbs' => [
['title' => 'Главная', 'url' => '/'],
['title' => 'Каталог', 'url' => '/catalog'],
['title' => 'Категория не найдена'],
],
]);
return;
}
$categoryName = (string) $category['name'];
$pagination = $this->paginationInput();
$totalProducts = $productRepository->categoryTotal((int) $category['id'], true);
$products = $productRepository->forCategory((int) $category['id'], $pagination['limit'], $pagination['offset'], true);
view('catalog/index', [
'title' => $category['seo_title'] ?: $categoryName . ' - купить в Рыбсток с доставкой по Москве',
'metaDescription' => $category['seo_description'] ?: $categoryName . ' в интернет-складе Рыбсток: качественная продукция по стоковым ценам, фасовки для дома и бизнеса, доставка по Москве и Московской области.',
'metaKeywords' => $category['seo_keywords'] ?: $categoryName . ', купить ' . $categoryName . ' Москва, ' . $categoryName . ' доставка, Рыбсток, продукты по стоковым ценам',
'breadcrumbs' => $categoryRepository->breadcrumbs((int) $category['id']),
'categories' => $categoryRepository->tree(),
'currentCategory' => $category,
'products' => $products,
'pagination' => $this->paginationData('/catalog/' . (string) $category['slug'], $totalProducts, count($products), $pagination),
]);
}
public function product(string $slug): void
{
$categoryRepository = new CategoryRepository();
$productRepository = new ProductRepository();
$product = $productRepository->findBySlug($slug);
if ($product === null) {
http_response_code(404);
view('pages/404', [
'title' => 'Товар не найден - Рыбсток',
'breadcrumbs' => [
['title' => 'Главная', 'url' => '/'],
['title' => 'Каталог', 'url' => '/catalog'],
['title' => 'Товар не найден'],
],
]);
return;
}
$breadcrumbs = [
['title' => 'Главная', 'url' => '/'],
['title' => 'Каталог', 'url' => '/catalog'],
];
if (!empty($product['display_category_id'] ?? $product['category_id'] ?? null)) {
$breadcrumbs = $categoryRepository->breadcrumbs((int) ($product['display_category_id'] ?? $product['category_id']));
}
$breadcrumbs[] = ['title' => (string) $product['name']];
view('catalog/product', [
'title' => $product['seo_title'] ?: $product['name'] . ' - купить в Рыбсток',
'metaDescription' => $product['seo_description'] ?: $product['short_description'] ?: '',
'metaKeywords' => $product['seo_keywords'] ?: '',
'breadcrumbs' => $breadcrumbs,
'product' => $product,
'variants' => $productRepository->variantsForProduct((int) $product['id']),
'images' => $productRepository->imagesForProduct((int) $product['id']),
]);
}
/**
* @return array{page:int, limit:int, offset:int, per_page:int, cumulative:bool}
*/
private function paginationInput(): array
{
$perPage = 48;
$cumulativeLimit = isset($_GET['limit']) ? (int) $_GET['limit'] : 0;
if ($cumulativeLimit > 0) {
$limit = max($perPage, min($cumulativeLimit, 5000));
return [
'page' => 1,
'limit' => $limit,
'offset' => 0,
'per_page' => $perPage,
'cumulative' => true,
];
}
$page = max(1, (int) ($_GET['page'] ?? 1));
return [
'page' => $page,
'limit' => $perPage,
'offset' => ($page - 1) * $perPage,
'per_page' => $perPage,
'cumulative' => false,
];
}
/**
* @param array{page:int, limit:int, offset:int, per_page:int, cumulative:bool} $input
* @return array<string, mixed>
*/
private function paginationData(string $basePath, int $total, int $currentCount, array $input): array
{
$shown = min($total, $input['offset'] + $currentCount);
$nextLimit = min($total, max($shown, $input['limit']) + $input['per_page']);
return [
'base_path' => $basePath,
'total' => $total,
'shown' => $shown,
'page' => $input['page'],
'pages' => max(1, (int) ceil($total / $input['per_page'])),
'per_page' => $input['per_page'],
'limit' => $input['limit'],
'has_more' => $shown < $total,
'next_limit' => $nextLimit,
'cumulative' => $input['cumulative'],
];
}
}