232 lines
12 KiB
PHP
232 lines
12 KiB
PHP
<?php
|
||
if (session_status() === PHP_SESSION_NONE) {
|
||
session_start();
|
||
}
|
||
|
||
$all_results = $_SESSION["search_results"] ?? [];
|
||
$query = $_SESSION["search_query"] ?? "";
|
||
|
||
// ---------------------------------------------------------------
|
||
// Parameter aus der URL lesen & validieren
|
||
// ---------------------------------------------------------------
|
||
$allowedCategories = [
|
||
'all', 'Deutsch', 'Englisch', 'Franzoesisch', 'Latein', 'Literatur',
|
||
'Mathematik', 'Biologie', 'Informatik', 'Chemie', 'Physik', 'Astronomie',
|
||
'Geschichte', 'Erdkunde', 'Sozialkunde', 'Wirtschaftskunde', 'Religion',
|
||
'Ethikunterricht', 'Philosophie', 'Psychologie', 'Kunst', 'Musik',
|
||
'Theater', 'Technik', 'Werken', 'Hauswirtschaft', 'Sport',
|
||
];
|
||
|
||
$category = $_GET['category'] ?? 'all';
|
||
if (!in_array($category, $allowedCategories, true)) {
|
||
$category = 'all';
|
||
}
|
||
|
||
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
||
if (!in_array($limit, [10, 20, 50, 100], true)) {
|
||
$limit = 10;
|
||
}
|
||
|
||
$currentSort = $_SESSION['search_sort'] ?? 'alphabet';
|
||
|
||
// ---------------------------------------------------------------
|
||
// Diese Berechnung ist der Server-seitige Fallback für Nutzer ohne
|
||
// JavaScript. Sobald JS aktiv ist, übernimmt js/search-results.js
|
||
// Filterung, Sortierung und Pagination komplett im Browser (auf
|
||
// Basis des unten eingebetteten JSON-Datensatzes) und überschreibt
|
||
// diese Ausgabe live, ohne dass eine neue Seite geladen wird.
|
||
// ---------------------------------------------------------------
|
||
$filteredResults = $all_results;
|
||
if ($category !== 'all') {
|
||
$filteredResults = array_values(array_filter($filteredResults, function ($item) use ($category) {
|
||
return ($item['category'] ?? '') === $category;
|
||
}));
|
||
}
|
||
|
||
$totalResultsCount = count($filteredResults);
|
||
$totalPages = max(1, (int)ceil($totalResultsCount / $limit));
|
||
|
||
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||
if ($currentPage < 1) {
|
||
$currentPage = 1;
|
||
} elseif ($currentPage > $totalPages) {
|
||
$currentPage = $totalPages;
|
||
}
|
||
|
||
$offset = ($currentPage - 1) * $limit;
|
||
$results = array_slice($filteredResults, $offset, $limit);
|
||
$resultCount = count($results);
|
||
|
||
// Hilfsfunktion, um Pagination-Links zu bauen, die alle aktuellen
|
||
// Parameter (q, sort, limit, category) beibehalten.
|
||
function buildPageUrl(int $page, string $query, string $sort, int $limit, string $category): string
|
||
{
|
||
$params = [
|
||
'pfad' => 'search-results',
|
||
'q' => $query,
|
||
'sort' => $sort,
|
||
'limit' => $limit,
|
||
'category' => $category,
|
||
'page' => $page,
|
||
];
|
||
return 'index.php?' . http_build_query($params);
|
||
}
|
||
|
||
// ---------------------------------------------------------------
|
||
// JSON-Datensatz für die clientseitige Aufbereitung (Filter,
|
||
// Sortierung, Pagination) durch js/search-results.js. Enthält ALLE
|
||
// Treffer der Suche (unabhängig von Kategorie/Sortierung/Seite),
|
||
// damit im Browser ohne weitere Serveranfragen gearbeitet werden kann.
|
||
// ---------------------------------------------------------------
|
||
$jsonItems = array_map(function ($item) {
|
||
$likes = isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : ($item['likes'] ?? 0);
|
||
return [
|
||
'id' => $item['id'] ?? null,
|
||
'title' => $item['title'] ?? '',
|
||
'author' => $item['author'] ?? '',
|
||
'category' => $item['category'] ?? '',
|
||
'likes' => $likes,
|
||
'creationDate'=> $item['creationDate'] ?? '',
|
||
];
|
||
}, $all_results);
|
||
?>
|
||
<noscript>
|
||
Bitte JavaScript aktivieren, um die volle Funktionalität (Live-Filterung ohne Neuladen) zu nutzen. Die Seite funktioniert auch ohne JavaScript – Sortierung, Filterung und Seitenwechsel erfolgen dann über die Formular- bzw. Link-Auswahl.
|
||
</noscript>
|
||
<!--
|
||
Seite: Suchergebnisse
|
||
Inhalt: Zeigt die Ergebnisse einer Suche an
|
||
-->
|
||
<div class="s-res-layout-grid">
|
||
<?php include_once "includes/alertMessages.php" ?>
|
||
<!-- Links: Seitenleiste für Filter und Suche -->
|
||
<aside class="s-res-sidebar">
|
||
<!-- Sortierfuntion Box und Such Box -->
|
||
<form action="php/controller/search-results-controller.php" method="GET" id="searchform-id" class="s-res-sidebar-form">
|
||
|
||
<input type="hidden" id="s-res-page-input" name="page" value="<?php echo (int)$currentPage; ?>">
|
||
|
||
<div class="s-res-sidebar-box">
|
||
<h3 class="s-res-sidebar-title">Suche anpassen</h3>
|
||
<input type="search" id="site-search" name="q" placeholder="Suchen..."
|
||
class="nav__search" value="<?php echo htmlspecialchars($query); ?>" maxlength="50" required>
|
||
<button type="submit" class="nav__search-button">Suchen</button>
|
||
</div>
|
||
|
||
<div class="s-res-sidebar-box">
|
||
<h3 class="s-res-sidebar-title">Sortierung</h3>
|
||
<div class="s-res-filter-group">
|
||
<label class="s-res-filter-option">
|
||
<input type="radio" name="sort" value="alphabet" class="sort-radio" <?php echo $currentSort === 'alphabet' ? 'checked' : ''; ?>>
|
||
<span>Alphabetisch</span>
|
||
</label>
|
||
<label class="s-res-filter-option">
|
||
<input type="radio" name="sort" value="likes" class="sort-radio" <?php echo $currentSort === 'likes' ? 'checked' : ''; ?>>
|
||
<span>Beliebtheit (Likes)</span>
|
||
</label>
|
||
<label class="s-res-filter-option">
|
||
<input type="radio" name="sort" value="newest" class="sort-radio" <?php echo $currentSort === 'newest' ? 'checked' : ''; ?>>
|
||
<span>Neueste Beiträge</span>
|
||
</label>
|
||
<label class="s-res-filter-option">
|
||
<input type="radio" name="sort" value="oldest" class="sort-radio" <?php echo $currentSort === 'oldest' ? 'checked' : ''; ?>>
|
||
<span>Älteste Beiträge</span>
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="s-res-sidebar-box">
|
||
<h3 class="s-res-sidebar-title">Kategorie filtern</h3>
|
||
<select id="category-filter" name="category" class="s-res-limit-select" style="width: 100%; padding: 8px; border-radius: 6px; border: 1px solid #cbd5e1;">
|
||
<?php foreach ($allowedCategories as $catValue):
|
||
$label = $catValue === 'all' ? 'Alle Kategorien' : ($catValue === 'Franzoesisch' ? 'Französisch' : $catValue);
|
||
?>
|
||
<option value="<?php echo htmlspecialchars($catValue); ?>" <?php echo $category === $catValue ? 'selected' : ''; ?>>
|
||
<?php echo htmlspecialchars($label); ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Für Nutzer ohne JavaScript: expliziter Button, um Sortierung/Kategorie anzuwenden -->
|
||
<noscript>
|
||
<button type="submit" class="nav__search-button">Filter anwenden</button>
|
||
</noscript>
|
||
</form>
|
||
</aside>
|
||
|
||
<main class="s-res-main-content">
|
||
<div class="s-res-header">
|
||
<h1 class="s-res-main-title">Suchergebnisse</h1>
|
||
<p class="s-res-meta" data-query="<?php echo htmlspecialchars($query); ?>">
|
||
<?php echo $totalResultsCount; ?> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Ergebnisliste: serverseitig gerendert (No-JS-Fallback). Wird bei aktivem JS durch js/search-results.js live ersetzt. -->
|
||
<div class="s-res-list">
|
||
<?php if (!empty($results)): ?>
|
||
<?php foreach ($results as $item):
|
||
$likesCount = isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : ($item['likes'] ?? 0);
|
||
?>
|
||
<div class="s-res-item" data-likes="<?php echo $likesCount; ?>" data-category="<?php echo strtolower($item['category'] ?? ''); ?>">
|
||
<div class="s-res-content">
|
||
<h2 class="s-res-item-title">
|
||
<a href="index.php?pfad=showArticle&id=<?php echo $item['id']; ?>" class="s-res-link">
|
||
<?php echo htmlspecialchars($item['title']); ?>
|
||
</a>
|
||
</h2>
|
||
<div class="s-res-meta-row">
|
||
<p class="s-res-author">Von: <span class="s-res-author-name"><?php echo htmlspecialchars($item['author']); ?></span></p>
|
||
<span class="s-res-likes"> ❤️ <?php echo $likesCount; ?></span>
|
||
</div>
|
||
</div>
|
||
<div class="s-res-arrow">→</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
|
||
<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>
|
||
<?php elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?>
|
||
<p>Unzulässige Suchanfrage</p>
|
||
<?php endif; ?>
|
||
<?php unset($_SESSION["message"]); ?>
|
||
</div>
|
||
|
||
<div class="s-res-pagination-footer">
|
||
<!-- Auswahl der Ergebnisse pro Seite -->
|
||
<div class="s-res-limit-selector">
|
||
<label for="s-res-per-page" class="s-res-limit-label">Ergebnisse pro Seite:</label>
|
||
<select id="s-res-per-page" name="limit" form="searchform-id" class="s-res-limit-select">
|
||
<option value="10" <?php echo $limit === 10 ? 'selected' : ''; ?>>10</option>
|
||
<option value="20" <?php echo $limit === 20 ? 'selected' : ''; ?>>20</option>
|
||
<option value="50" <?php echo $limit === 50 ? 'selected' : ''; ?>>50</option>
|
||
<option value="100" <?php echo $limit === 100 ? 'selected' : ''; ?>>100</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- No-JS-Fallback: echte Links, die serverseitig neu paginieren -->
|
||
<div class="s-res-page-navigation">
|
||
<?php if ($currentPage > 1): ?>
|
||
<a class="s-res-page-btn" href="<?php echo htmlspecialchars(buildPageUrl($currentPage - 1, $query, $currentSort, $limit, $category)); ?>">«</a>
|
||
<?php else: ?>
|
||
<span class="s-res-page-btn" aria-disabled="true">«</span>
|
||
<?php endif; ?>
|
||
|
||
<span id="dynamic-page-numbers">Seite <?php echo $currentPage; ?> von <?php echo $totalPages; ?></span>
|
||
|
||
<?php if ($currentPage < $totalPages): ?>
|
||
<a class="s-res-page-btn" href="<?php echo htmlspecialchars(buildPageUrl($currentPage + 1, $query, $currentSort, $limit, $category)); ?>">»</a>
|
||
<?php else: ?>
|
||
<span class="s-res-page-btn" aria-disabled="true">»</span>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
|
||
<!-- Vollständiger, ungefilterter Ergebnis-Datensatz für die clientseitige
|
||
Filterung/Sortierung/Pagination (siehe js/search-results.js).
|
||
JSON_HEX_* verhindert das Ausbrechen aus dem <script>-Tag bzw. XSS. -->
|
||
<script type="application/json" id="s-res-data">
|
||
<?php echo json_encode($jsonItems, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP); ?>
|
||
</script>
|