WebOrbiton
v1.0.0.1

StocketBase

170 lines · 8.0 KB
  1. <?php
  2. ​
  3. declare(strict_types=1);
  4. ​
  5. require_once __DIR__ . '/includes/config.php';
  6. require_once __DIR__ . '/includes/database.php';
  7. require_once __DIR__ . '/includes/user-auth.php';
  8. require_once __DIR__ . '/includes/language.php';
  9. require_once __DIR__ . '/includes/site-front.php';
  10. require_once __DIR__ . '/includes/pagination.php';
  11. require_once __DIR__ . '/includes/product-card.php';
  12. require_once __DIR__ . '/includes/product-search.php';
  13. require_once __DIR__ . '/includes/tags.php';
  14. ​
  15. UserAuth::boot();
  16. ​
  17. $db = Database::site();
  18. $settings = SiteFront::settings();
  19. ​
  20. if ($settings['search_enabled'] !== '1') {
  21. http_response_code(404);
  22. $pageTitle = Language::get('page_title_not_found', 'Not found') . ' - ' . $settings['site_name'];
  23. require __DIR__ . '/includes/front-header.php';
  24. echo '<p>' . htmlspecialchars(Language::get('search_not_available', 'Search is not available.')) . '</p>';
  25. require __DIR__ . '/includes/front-footer.php';
  26. exit;
  27. }
  28. ​
  29. $query = trim((string) ($_GET['q'] ?? ''));
  30. $categoryId = (int) ($_GET['category'] ?? 0);
  31. $tagId = (int) ($_GET['tag'] ?? 0);
  32. $sort = ProductSearch::sanitizeSort((string) ($_GET['sort'] ?? 'newest'));
  33. $tagsEnabled = ProductTags::isEnabled();
  34. if (!$tagsEnabled) {
  35. $tagId = 0;
  36. }
  37. ​
  38. $categories = $db->query('SELECT id, name FROM categories ORDER BY name ASC')->fetchAll();
  39. $tags = $tagsEnabled ? $db->query('SELECT id, name FROM tags ORDER BY name ASC')->fetchAll() : [];
  40. ​
  41. $hasFilters = $categoryId > 0 || $tagId > 0 || $sort !== 'newest';
  42. ​
  43. $products = [];
  44. $totalProducts = 0;
  45. $totalPages = 0;
  46. $currentPage = Pagination::currentPage();
  47. $perPage = max(1, (int) $settings['products_per_page_home']);
  48. ​
  49. if ($query !== '' || $hasFilters) {
  50. $result = ProductSearch::run(
  51. $settings,
  52. ['q' => $query, 'category' => $categoryId, 'tag' => $tagId, 'sort' => $sort],
  53. $currentPage,
  54. $perPage
  55. );
  56. $products = $result['products'];
  57. $totalProducts = $result['total'];
  58. $totalPages = $result['totalPages'];
  59. $currentPage = $result['page'];
  60. $perPage = $result['perPage'];
  61. }
  62. ​
  63. $isStaticProductLoading = ($settings['product_loading_mode'] ?? 'scroll') === 'static';
  64. ​
  65. $paginationExtraParams = ['q' => $query];
  66. if ($categoryId > 0) {
  67. $paginationExtraParams['category'] = $categoryId;
  68. }
  69. if ($tagId > 0) {
  70. $paginationExtraParams['tag'] = $tagId;
  71. }
  72. if ($sort !== 'newest') {
  73. $paginationExtraParams['sort'] = $sort;
  74. }
  75. ​
  76. $pageTitle = Language::get('nav_search', 'Search') . ' - ' . $settings['site_name'];
  77. $pageDescription = '';
  78. ​
  79. require __DIR__ . '/includes/front-header.php';
  80. ​
  81. ?>
  82. <h1 class="category-title"><?= htmlspecialchars(Language::get('nav_search', 'Search')) ?></h1>
  83. ​
  84. <form action="search.php" method="get" class="site-search-form site-search-form-page" role="search">
  85. <span class="site-search-form-icon">
  86. <svg class="icon icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
  87. <circle cx="11" cy="11" r="7"></circle>
  88. <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
  89. </svg>
  90. </span>
  91. <input type="text" name="q" class="site-search-input" value="<?= htmlspecialchars($query) ?>" placeholder="<?= htmlspecialchars(Language::get('search_placeholder', 'Search')) ?>" aria-label="<?= htmlspecialchars(Language::get('search_placeholder', 'Search')) ?>" autofocus>
  92. <button type="submit" class="site-search-submit"><?= htmlspecialchars(Language::get('search_button', 'Search')) ?></button>
  93. </form>
  94. ​
  95. <form action="search.php" method="get" class="search-filters">
  96. <input type="hidden" name="q" value="<?= htmlspecialchars($query, ENT_QUOTES) ?>">
  97. ​
  98. <label class="search-filter-field">
  99. <span><?= htmlspecialchars(Language::get('search_filter_category', 'Category')) ?></span>
  100. <select name="category" onchange="this.form.submit()">
  101. <option value="0"><?= htmlspecialchars(Language::get('search_filter_all_categories', 'All categories')) ?></option>
  102. <?php foreach ($categories as $categoryOption): ?>
  103. <option value="<?= (int) $categoryOption['id'] ?>" <?= $categoryId === (int) $categoryOption['id'] ? 'selected' : '' ?>><?= htmlspecialchars($categoryOption['name']) ?></option>
  104. <?php endforeach; ?>
  105. </select>
  106. </label>
  107. ​
  108. <?php if ($tagsEnabled && !empty($tags)): ?>
  109. <label class="search-filter-field">
  110. <span><?= htmlspecialchars(Language::get('search_filter_tag', 'Tag')) ?></span>
  111. <select name="tag" onchange="this.form.submit()">
  112. <option value="0"><?= htmlspecialchars(Language::get('search_filter_all_tags', 'All tags')) ?></option>
  113. <?php foreach ($tags as $tagOption): ?>
  114. <option value="<?= (int) $tagOption['id'] ?>" <?= $tagId === (int) $tagOption['id'] ? 'selected' : '' ?>><?= htmlspecialchars($tagOption['name']) ?></option>
  115. <?php endforeach; ?>
  116. </select>
  117. </label>
  118. <?php endif; ?>
  119. ​
  120. <label class="search-filter-field">
  121. <span><?= htmlspecialchars(Language::get('search_filter_sort', 'Sort by')) ?></span>
  122. <select name="sort" onchange="this.form.submit()">
  123. <option value="newest" <?= $sort === 'newest' ? 'selected' : '' ?>><?= htmlspecialchars(Language::get('search_sort_newest', 'Publish date (newest)')) ?></option>
  124. <option value="oldest" <?= $sort === 'oldest' ? 'selected' : '' ?>><?= htmlspecialchars(Language::get('search_sort_oldest', 'Publish date (oldest)')) ?></option>
  125. <option value="price_asc" <?= $sort === 'price_asc' ? 'selected' : '' ?>><?= htmlspecialchars(Language::get('search_sort_price_asc', 'Price: low to high')) ?></option>
  126. <option value="price_desc" <?= $sort === 'price_desc' ? 'selected' : '' ?>><?= htmlspecialchars(Language::get('search_sort_price_desc', 'Price: high to low')) ?></option>
  127. <option value="rating" <?= $sort === 'rating' ? 'selected' : '' ?>><?= htmlspecialchars(Language::get('search_sort_rating', 'Highest rated')) ?></option>
  128. </select>
  129. </label>
  130. ​
  131. <noscript><button type="submit" class="dash-btn-small"><?= htmlspecialchars(Language::get('search_filter_apply', 'Apply')) ?></button></noscript>
  132. </form>
  133. ​
  134. <?php if ($query === '' && !$hasFilters): ?>
  135. <p class="search-hint"><?= htmlspecialchars(Language::get('search_hint_empty', 'Type something above to search products.')) ?></p>
  136. <?php else: ?>
  137. <p class="search-hint">
  138. <?php if ($query !== ''): ?>
  139. <?php
  140. $resultsTemplate = $totalProducts === 1
  141. ? Language::get('search_results_count_one', '%d result for "%s"')
  142. : Language::get('search_results_count_other', '%d results for "%s"');
  143. echo htmlspecialchars(sprintf($resultsTemplate, $totalProducts, $query));
  144. ?>
  145. <?php else: ?>
  146. <?php
  147. $resultsTemplate = $totalProducts === 1
  148. ? Language::get('search_results_count_one_nolabel', '%d result')
  149. : Language::get('search_results_count_other_nolabel', '%d results');
  150. echo htmlspecialchars(sprintf($resultsTemplate, $totalProducts));
  151. ?>
  152. <?php endif; ?>
  153. </p>
  154. ​
  155. <div class="article-grid" id="article-list" data-pagination-source="search" data-search-query="<?= htmlspecialchars($query, ENT_QUOTES) ?>" data-search-category="<?= $categoryId ?>" data-search-tag="<?= $tagId ?>" data-search-sort="<?= htmlspecialchars($sort, ENT_QUOTES) ?>">
  156. <?php foreach ($products as $product): ?>
  157. <?= renderProductCard($product) ?>
  158. <?php endforeach; ?>
  159. <?php if (empty($products)): ?>
  160. <p><?= htmlspecialchars(Language::get('search_no_results', 'No products matched your search.')) ?></p>
  161. <?php endif; ?>
  162. </div>
  163. ​
  164. <div id="pagination-container">
  165. <?= $isStaticProductLoading ? '' : Pagination::render($settings['pagination_style'], 'search.php', $currentPage, $totalPages, $paginationExtraParams, 'article-list') ?>
  166. </div>
  167. <?php endif; ?>
  168. ​
  169. <?php require __DIR__ . '/includes/front-footer.php'; ?>
  170. ​