v1.0.0.0
StocketBase
- <?php
-
- declare(strict_types=1);
-
- require_once __DIR__ . '/includes/config.php';
- require_once __DIR__ . '/includes/database.php';
- require_once __DIR__ . '/includes/user-auth.php';
- require_once __DIR__ . '/includes/language.php';
- require_once __DIR__ . '/includes/site-front.php';
- require_once __DIR__ . '/includes/pagination.php';
- require_once __DIR__ . '/includes/product-card.php';
-
- UserAuth::boot();
-
- $db = Database::site();
- $settings = SiteFront::settings();
-
- function resolveFeaturedProducts(PDO $db, array $settings): array
- {
- if (($settings['featured_banner_enabled'] ?? '0') !== '1') {
- return [];
- }
-
- if (($settings['featured_banner_mode'] ?? 'static') === 'static') {
- $featuredIds = [];
- for ($i = 1; $i <= 5; $i++) {
- $id = (int) ($settings['featured_banner_product_' . $i] ?? 0);
- if ($id > 0 && !in_array($id, $featuredIds, true)) {
- $featuredIds[] = $id;
- }
- }
-
- if (empty($featuredIds)) {
- return [];
- }
-
- $placeholders = implode(',', array_fill(0, count($featuredIds), '?'));
- $statement = $db->prepare(
- "SELECT p.*, c.name AS category_name FROM products p LEFT JOIN categories c ON c.id = p.category_id WHERE p.status = 'published' AND p.id IN ($placeholders)"
- );
- $statement->execute($featuredIds);
- $byId = [];
- foreach ($statement->fetchAll() as $row) {
- $byId[(int) $row['id']] = $row;
- }
-
- $result = [];
- foreach ($featuredIds as $id) {
- if (isset($byId[$id])) {
- $result[] = $byId[$id];
- }
- }
-
- return $result;
- }
-
- $windowValue = max(1, min(720, (int) ($settings['featured_banner_auto_window_value'] ?? 24)));
- $windowUnit = ($settings['featured_banner_auto_window_unit'] ?? 'hours') === 'minutes' ? 'minutes' : 'hours';
- $windowMinutes = $windowUnit === 'hours' ? $windowValue * 60 : $windowValue;
- $cutoff = (new DateTimeImmutable('now', new DateTimeZone('UTC')))->modify('-' . $windowMinutes . ' minutes')->format('Y-m-d H:i:s');
-
- $statement = $db->prepare(
- "SELECT p.*, c.name AS category_name FROM products p LEFT JOIN categories c ON c.id = p.category_id
- WHERE p.status = 'published' AND p.published_at >= :cutoff
- ORDER BY p.views_count DESC, p.published_at DESC, p.id DESC"
- );
- $statement->execute(['cutoff' => $cutoff]);
- $candidates = $statement->fetchAll();
- $categoryMode = $settings['featured_banner_auto_category_mode'] ?? 'mixed';
-
- $result = [];
- if ($categoryMode === 'one_per_category') {
- $used = [];
- foreach ($candidates as $row) {
- $key = (string) ($row['category_id'] ?? 'none');
- if (isset($used[$key])) {
- continue;
- }
- $used[$key] = true;
- $result[] = $row;
- if (count($result) === 5) {
- break;
- }
- }
- } elseif ($categoryMode === 'mixed') {
- $byCategory = [];
- foreach ($candidates as $row) {
- $key = (string) ($row['category_id'] ?? 'none');
- $byCategory[$key][] = $row;
- }
- while (count($result) < 5 && !empty($byCategory)) {
- foreach ($byCategory as $key => $rows) {
- if (!empty($rows)) {
- $result[] = array_shift($byCategory[$key]);
- }
- if (empty($byCategory[$key])) {
- unset($byCategory[$key]);
- }
- if (count($result) === 5) {
- break;
- }
- }
- }
- } else {
- $result = array_slice($candidates, 0, 5);
- }
-
- return $result;
- }
-
- function resolveFeaturedExcludedIds(array $settings, array $featuredProducts): array
- {
- if (($settings['featured_banner_enabled'] ?? '0') !== '1' || ($settings['featured_banner_hide_duplicates'] ?? '0') !== '1') {
- return [];
- }
-
- return array_values(array_map(static fn (array $product): int => (int) $product['id'], $featuredProducts));
- }
-
- $featuredProducts = resolveFeaturedProducts($db, $settings);
- $excludedIds = resolveFeaturedExcludedIds($settings, $featuredProducts);
- $excludeSql = empty($excludedIds) ? '' : ' AND p.id NOT IN (' . implode(',', $excludedIds) . ')';
-
- $currentPage = Pagination::currentPage();
- $totalProducts = (int) $db->query("SELECT COUNT(*) AS c FROM products p WHERE p.status = 'published'" . $excludeSql)->fetch()['c'];
- $isStaticProductLoading = ($settings['product_loading_mode'] ?? 'scroll') === 'static';
- $perPage = $isStaticProductLoading
- ? max(1, $totalProducts)
- : max(1, (int) $settings['products_per_page_home']);
- $currentPage = $isStaticProductLoading ? 1 : $currentPage;
- $offset = Pagination::offset($currentPage, $perPage);
- $totalPages = Pagination::totalPages($totalProducts, $perPage);
-
- $productsStatement = $db->prepare(
- "SELECT p.*, c.name AS category_name, c.slug AS category_slug FROM products p LEFT JOIN categories c ON c.id = p.category_id WHERE p.status = 'published'" . $excludeSql . " ORDER BY p.published_at DESC LIMIT :limit OFFSET :offset"
- );
- $productsStatement->bindValue('limit', $perPage, PDO::PARAM_INT);
- $productsStatement->bindValue('offset', $offset, PDO::PARAM_INT);
- $productsStatement->execute();
- $products = $productsStatement->fetchAll();
-
- $pageTitle = $settings['seo_title'] !== '' ? $settings['seo_title'] : $settings['site_name'];
- $pageDescription = $settings['seo_description'] !== '' ? $settings['seo_description'] : $settings['site_description'];
- $pageType = 'index';
-
- require __DIR__ . '/includes/front-header.php';
-
- ?>
- <?php if (!empty($settings['site_description'])): ?>
- <section class="hero-section">
- <div class="hero-eyebrow"><?= htmlspecialchars(Language::get('nav_home', 'Home')) ?></div>
- <h1 class="hero-title"><?= htmlspecialchars($settings['site_name']) ?></h1>
- <p class="hero-subtitle"><?= htmlspecialchars($settings['site_description']) ?></p>
- </section>
- <?php endif; ?>
-
- <?php foreach (SiteFront::activeAds('homepage-top') as $homepageTopAd): ?>
- <?= SiteFront::renderAd($homepageTopAd) ?>
- <?php endforeach; ?>
-
- <?php if (($settings['featured_banner_enabled'] ?? '0') === '1'): ?>
- <div class="section-heading-row">
- <h2 class="section-heading"><?= htmlspecialchars(Language::get('home_featured', 'Featured')) ?></h2>
- </div>
-
- <?php if (!empty($featuredProducts)): ?>
- <?= renderFeaturedBanner($featuredProducts) ?>
- <?php endif; ?>
- <?php endif; ?>
-
- <div class="article-grid" id="article-list" data-pagination-source="home">
- <?php $catalogTopAds = SiteFront::activeAds('catalog-top'); ?>
- <?php foreach ($products as $inFeedIndex => $product): ?>
- <?= renderProductCard($product) ?>
- <?php if ($inFeedIndex === 2 && !empty($catalogTopAds)): ?>
- <?php foreach ($catalogTopAds as $catalogTopAd): ?>
- <?= SiteFront::renderAd($catalogTopAd) ?>
- <?php endforeach; ?>
- <?php endif; ?>
- <?php endforeach; ?>
- <?php if (empty($products)): ?>
- <p><?= htmlspecialchars(Language::get('home_no_products', 'No products published yet.')) ?></p>
- <?php endif; ?>
- </div>
-
- <div id="pagination-container">
- <?= $isStaticProductLoading ? '' : Pagination::render($settings['pagination_style'], 'index.php', $currentPage, $totalPages, [], 'article-list') ?>
- </div>
-
- <?php require __DIR__ . '/includes/front-footer.php'; ?>
-