v1.0.0.1
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_once __DIR__ . '/includes/block-editor.php';
-
- try {
- $homePage = SiteFront::homePage();
- } catch (Throwable $exception) {
- $homePage = null;
- }
-
- if ($homePage !== null) {
- $homePage = Languages::pages([$homePage])[0];
- $homeBlocksJson = (string) $homePage['content_blocks'];
- } else {
- $homeBlocksJson = BlockEditor::defaultHomepageBlocks(trim((string) ($settings['site_description'] ?? '')) !== '');
- }
-
- $renderHomeFeatured = static function () use ($settings, $featuredProducts): string {
- ob_start();
- foreach (SiteFront::activeAds('homepage-top') as $homepageTopAd) {
- echo SiteFront::renderAd($homepageTopAd);
- }
- if (($settings['featured_banner_enabled'] ?? '0') === '1') {
- echo '<div class="section-heading-row"><h2 class="section-heading">' . htmlspecialchars(Language::get('home_featured', 'Featured')) . '</h2></div>';
- if (!empty($featuredProducts)) {
- echo renderFeaturedBanner($featuredProducts);
- }
- }
-
- return (string) ob_get_clean();
- };
-
- $renderHomeProducts = static function () use ($settings, $products, $isStaticProductLoading, $currentPage, $totalPages): string {
- ob_start();
- $catalogTopAds = SiteFront::activeAds('catalog-top');
- echo '<div class="article-grid" id="article-list" data-pagination-source="home">';
- foreach ($products as $inFeedIndex => $product) {
- echo renderProductCard($product);
- if ($inFeedIndex === 2 && !empty($catalogTopAds)) {
- foreach ($catalogTopAds as $catalogTopAd) {
- echo SiteFront::renderAd($catalogTopAd);
- }
- }
- }
- if (empty($products)) {
- echo '<p>' . htmlspecialchars(Language::get('home_no_products', 'No products published yet.')) . '</p>';
- }
- echo '</div>';
- echo '<div id="pagination-container">';
- echo $isStaticProductLoading ? '' : Pagination::render($settings['pagination_style'], 'index.php', $currentPage, $totalPages, [], 'article-list');
- echo '</div>';
-
- return (string) ob_get_clean();
- };
-
- require __DIR__ . '/includes/front-header.php';
-
- echo BlockEditor::renderHomepage($homeBlocksJson, $settings, [
- 'home_featured' => $renderHomeFeatured,
- 'home_products' => $renderHomeProducts,
- ]);
-
- require __DIR__ . '/includes/front-footer.php';
-