v1.0.0.6
Publisium
- <?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/article-card.php';
-
- UserAuth::boot();
-
- $db = Database::site();
- $settings = SiteFront::settings();
-
- if ($settings['search_enabled'] !== '1') {
- http_response_code(404);
- $pageTitle = Language::get('not_found_title', 'Not found') . ' - ' . $settings['site_name'];
- $showBanner = false;
- require __DIR__ . '/includes/front-header.php';
- echo '<p>' . htmlspecialchars(Language::get('search_not_available', 'Search is not available.')) . '</p>';
- require __DIR__ . '/includes/front-footer.php';
- exit;
- }
-
- $query = trim((string) ($_GET['q'] ?? ''));
-
- $matchTitle = $settings['search_match_title'] === '1';
- $matchExcerpt = $settings['search_match_excerpt'] === '1';
- $matchContent = $settings['search_match_content'] === '1';
-
- if (!$matchTitle && !$matchExcerpt && !$matchContent) {
- $matchTitle = true;
- }
-
- $articles = [];
- $totalArticles = 0;
- $totalPages = 0;
- $currentPage = Pagination::currentPage();
- $perPage = max(1, (int) $settings['articles_per_page_home']);
- $offset = Pagination::offset($currentPage, $perPage);
-
- if ($query !== '') {
- $conditions = [];
- if ($matchTitle) {
- $conditions[] = 'a.title LIKE :q_title';
- }
- if ($matchExcerpt) {
- $conditions[] = 'a.excerpt LIKE :q_excerpt';
- }
- if ($matchContent) {
- $conditions[] = 'a.content_blocks LIKE :q_content';
- }
-
- $whereClause = "a.status = 'published' AND (" . implode(' OR ', $conditions) . ')' . Languages::articleFilterSql('a');
- $likeValue = '%' . str_replace(['%', '_'], ['\\%', '\\_'], $query) . '%';
-
- $bindings = [];
- if ($matchTitle) {
- $bindings['q_title'] = $likeValue;
- }
- if ($matchExcerpt) {
- $bindings['q_excerpt'] = $likeValue;
- }
- if ($matchContent) {
- $bindings['q_content'] = $likeValue;
- }
-
- $countStatement = $db->prepare("SELECT COUNT(*) AS c FROM articles a WHERE {$whereClause}");
- $countStatement->execute($bindings);
- $totalArticles = (int) $countStatement->fetch()['c'];
- $isStaticArticleLoading = ($settings['article_loading_mode'] ?? 'scroll') === 'static';
- if ($isStaticArticleLoading) {
- $perPage = max(1, $totalArticles);
- $currentPage = 1;
- $offset = 0;
- }
- $totalPages = Pagination::totalPages($totalArticles, $perPage);
-
- $searchStatement = $db->prepare(
- "SELECT a.*, c.name AS category_name, c.slug AS category_slug
- FROM articles a
- LEFT JOIN categories c ON c.id = a.category_id
- WHERE {$whereClause}
- ORDER BY a.published_at DESC
- LIMIT :limit OFFSET :offset"
- );
- foreach ($bindings as $bindKey => $bindValue) {
- $searchStatement->bindValue($bindKey, $bindValue, PDO::PARAM_STR);
- }
- $searchStatement->bindValue('limit', $perPage, PDO::PARAM_INT);
- $searchStatement->bindValue('offset', $offset, PDO::PARAM_INT);
- $searchStatement->execute();
- $articles = Languages::articles($searchStatement->fetchAll());
- }
-
- $pageTitle = Language::get('nav_search', 'Search') . ' - ' . $settings['site_name'];
- $pageDescription = '';
- $showBanner = false;
-
- require __DIR__ . '/includes/front-header.php';
-
- ?>
- <h1 class="category-title"><?= htmlspecialchars(Language::get('nav_search', 'Search')) ?></h1>
-
- <form action="search.php" method="get" class="site-search-form site-search-form-page" role="search">
- <span class="site-search-form-icon">
- <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">
- <circle cx="11" cy="11" r="7"></circle>
- <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
- </svg>
- </span>
- <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>
- <button type="submit" class="site-search-submit"><?= htmlspecialchars(Language::get('search_button', 'Search')) ?></button>
- </form>
- <script>
- (function() {
- var input = document.querySelector('.site-search-form-page .site-search-input');
- if (!input) {
- return;
- }
- var end = input.value.length;
- input.focus();
- input.setSelectionRange(end, end);
- })();
- </script>
-
- <?= SiteFront::renderAds('search-top') ?>
-
- <?php if ($query === ''): ?>
- <p class="search-hint"><?= htmlspecialchars(Language::get('search_hint_empty', 'Type something above to search articles.')) ?></p>
- <?php else: ?>
- <p class="search-hint">
- <?php
- $resultsTemplate = $totalArticles === 1
- ? Language::get('search_results_count_one', '%d result for "%s"')
- : Language::get('search_results_count_other', '%d results for "%s"');
- echo htmlspecialchars(sprintf($resultsTemplate, $totalArticles, $query));
- ?>
- </p>
-
- <div class="article-grid" id="article-list" data-pagination-source="search" data-search-query="<?= htmlspecialchars($query, ENT_QUOTES) ?>">
- <?php foreach ($articles as $article): ?>
- <?= renderArticleCard($article) ?>
- <?php endforeach; ?>
- <?php if (empty($articles)): ?>
- <p><?= htmlspecialchars(Language::get('search_no_results', 'No articles matched your search.')) ?></p>
- <?php endif; ?>
- </div>
-
- <div id="pagination-container">
- <?= ($settings['article_loading_mode'] ?? 'scroll') === 'static' ? '' : Pagination::render($settings['pagination_style'], 'search.php', $currentPage, $totalPages, ['q' => $query], 'article-list') ?>
- </div>
- <?php endif; ?>
-
- <?php require __DIR__ . '/includes/front-footer.php'; ?>
-