Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17034c928b | |||
| 395041fd44 | |||
| c117c7e641 | |||
| 12ad9759cf | |||
| 057639be7c | |||
| 87e7be1c10 | |||
| 1db77346d0 | |||
| 1e6ac0fcd9 | |||
| b3c74c2172 | |||
| 0805958033 | |||
| 5c0e978c93 | |||
| 520298bae4 | |||
| 969adc4836 | |||
| d9eca06197 | |||
| 48f2e90e49 | |||
| 358247a2a1 | |||
| de4d2fe5c0 | |||
| e1102eb7db | |||
| a8df9590fd | |||
| 3e453e22ec | |||
| beeab0ec90 | |||
| 9353a7eaaa | |||
| cac8f3046d | |||
| 66eeac372c |
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="dataSourceStorageLocal" created-in="IU-253.32098.101">
|
<component name="dataSourceStorageLocal" created-in="IU-261.25134.95">
|
||||||
<data-source name="articles" uuid="315cb5c9-2b0f-435b-b602-59823b160908">
|
<data-source name="articles" uuid="315cb5c9-2b0f-435b-b602-59823b160908">
|
||||||
<database-info product="SQLite" version="3.51.1" jdbc-version="4.2" driver-name="SQLite JDBC" driver-version="3.51.1.0" dbms="SQLITE" exact-version="3.51.1" exact-driver-version="3.51">
|
<database-info product="SQLite" version="3.51.1" jdbc-version="4.2" driver-name="SQLite JDBC" driver-version="3.51.1.0" dbms="SQLITE" exact-version="3.51.1" exact-driver-version="3.51">
|
||||||
<identifier-quote-string>"</identifier-quote-string>
|
<identifier-quote-string>"</identifier-quote-string>
|
||||||
|
|||||||
@@ -16,21 +16,18 @@
|
|||||||
|
|
||||||
## Bekannte Fehler und Mängel
|
## Bekannte Fehler und Mängel
|
||||||
- Bitte auf die gesetzten TODO's achten. Wenn Inhalte fehlen, sind sie i.d.R. als TODO kommentiert.
|
- Bitte auf die gesetzten TODO's achten. Wenn Inhalte fehlen, sind sie i.d.R. als TODO kommentiert.
|
||||||
- Die Kategorieseite listet momentan alle passenden Beiträge untereinander. Später sollen mit einem Paginator die neusten
|
- Die Suchseite und Kategorieseite packen momentan alle passenden Beiträge untereinander. Später sollen zunächst 10
|
||||||
Beiträge nacheinander aufgelistet werden (ähnlich wie bei der Suche, wenn nach Fach gefiltert wird).
|
Ergebnisse auf einer Seite angezeigt werden.
|
||||||
- Wenn ein Bild aus einem Beitrag entfernt wird, dann wird noch nicht die Datei im Pfad /uploads gelöscht.
|
- Wenn ein Bild aus einem Beitrag entfernt wird, dann wird noch nicht die Datei im Pfad /uploads gelöscht.
|
||||||
- id in showArticle-controller.php und updateArticle-controller.php wird nicht als gültige numerische ID geprüft.
|
- id in showArticle-controller.php und updateArticle-controller.php wird nicht als gültige numerische ID geprüft.
|
||||||
- Bilder im Beitragseditor sollen zukünftig eine Bildunterschrift bekommen und größenverstellbar sein.
|
- sort in search-results-controller.php wird nicht gegen erlaubte Werte validiert.
|
||||||
- Die Elemente eines Contents im Beitrag werden momentan stumpf untereinander aufgelistet. Soll später
|
|
||||||
sich responisve auch nebeneinander orientieren usw.
|
|
||||||
|
|
||||||
## Besonderheiten des Projektes
|
## Besonderheiten des Projektes
|
||||||
- Es wurde AJAX verwendet, um asynchrone Erstellung von Kommentaren zu implementieren. Es ermöglicht dem Nutzer, einen
|
- Es wurde ein einfacher Beitrags-Editor erstellt. Mit diesem können Beiträge erstellt oder bearbeitet werden.
|
||||||
Kommentar abzusenden, ohne dass die gesamte Webseite neu geladen werden muss.
|
Es handelt es sich um eine einfache Version. Später sollen z.B. Bilder und die Positionierung der Elemente folgen.
|
||||||
- Mit JavaScript werden auch clientseitig die Kommentare visuell hinzugefügt und die Kommentarbäume aufgebaut.
|
- Es sind drei Dummy-Beiträge für den Nutzer max.mustermann hinterlegt.
|
||||||
- JavaScript wird verwendet, um im erweitertem Beitragseditor clientseitig einzelne Content-Boxen erstellen und löschen
|
- Die Such-Seite umfasst eine Such- und Sortierfunktion. Jedoch fehlt noch eine
|
||||||
zu können.
|
Filterfunktion (z.B. nur Mathe anzeigen).
|
||||||
- JavaScript wird ebenfalls verwendet, um in die Suchergebnisse clientseitig zu sortieren.
|
|
||||||
|
|
||||||
## Sonstiges
|
## Sonstiges
|
||||||
- Das Datenschema befindet sich unter /planung/Datenschema.pdf
|
- Das Datenschema befindet sich unter /planung/Datenschema.pdf
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once "php/model/UserManager.php";
|
|
||||||
|
|
||||||
$token = basename($_GET["token"] ?? "");
|
|
||||||
$file = "data/pending-password/" . $token . ".json";
|
|
||||||
|
|
||||||
$title = "Passwort zurücksetzen";
|
|
||||||
$message = "";
|
|
||||||
$link = "";
|
|
||||||
$isSuccess = false;
|
|
||||||
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
$message = "Der Bestätigungslink ist ungültig oder bereits abgelaufen.";
|
|
||||||
} else {
|
|
||||||
$data = json_decode(file_get_contents($file), true);
|
|
||||||
|
|
||||||
if ($data === null || empty($data["email"]) || empty($data["password"])) {
|
|
||||||
$message = "Die Daten zur Passwortänderung konnten nicht gelesen werden.";
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
$dao = UserManager::getInstance();
|
|
||||||
$user = $dao->findUser($data["email"]);
|
|
||||||
|
|
||||||
if ($user !== null) {
|
|
||||||
$dao->updateUser(
|
|
||||||
$user["email"],
|
|
||||||
$user["email"],
|
|
||||||
$user["vorname"],
|
|
||||||
$user["nachname"],
|
|
||||||
$data["password"]
|
|
||||||
);
|
|
||||||
|
|
||||||
unlink($file);
|
|
||||||
|
|
||||||
$title = "Passwort geändert";
|
|
||||||
$message = "Ihr Passwort wurde erfolgreich geändert. Sie können sich jetzt anmelden.";
|
|
||||||
$link = '<a class="button confirm-button" href="index.php?pfad=login">Zum Login</a>';
|
|
||||||
$isSuccess = true;
|
|
||||||
} else {
|
|
||||||
unlink($file);
|
|
||||||
|
|
||||||
$message = "Der Benutzer konnte nicht gefunden werden.";
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$message = "Das Passwort konnte nicht geändert werden.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<main class="login-page">
|
|
||||||
<div class="login-container">
|
|
||||||
|
|
||||||
<h1><?php echo htmlspecialchars($title); ?></h1>
|
|
||||||
|
|
||||||
<p class="alert-message <?php echo $isSuccess ? 'is-success' : 'is-error'; ?> confirm-message">
|
|
||||||
<?php echo htmlspecialchars($message); ?>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php echo $link; ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once "php/model/UserManager.php";
|
|
||||||
|
|
||||||
$token = basename($_GET["token"] ?? "");
|
|
||||||
$file = "data/pending/" . $token . ".json";
|
|
||||||
|
|
||||||
$title = "Registrierung";
|
|
||||||
$message = "";
|
|
||||||
$link = "";
|
|
||||||
$isSuccess = false;
|
|
||||||
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
$message = "Der Registrierungslink ist ungültig oder bereits abgelaufen.";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
$data = json_decode(file_get_contents($file), true);
|
|
||||||
|
|
||||||
if ($data === null) {
|
|
||||||
$message = "Die Registrierungsdaten konnten nicht gelesen werden.";
|
|
||||||
} elseif (
|
|
||||||
empty($data["email"]) ||
|
|
||||||
empty($data["vorname"]) ||
|
|
||||||
empty($data["nachname"]) ||
|
|
||||||
empty($data["password"])
|
|
||||||
) {
|
|
||||||
$message = "Die Registrierungsdaten sind unvollständig.";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
try {
|
|
||||||
$dao = UserManager::getInstance();
|
|
||||||
|
|
||||||
if ($dao->findUser($data["email"]) === null) {
|
|
||||||
$dao->addUser(
|
|
||||||
$data["email"],
|
|
||||||
$data["vorname"],
|
|
||||||
$data["nachname"],
|
|
||||||
$data["password"]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink($file);
|
|
||||||
|
|
||||||
$title = "Registrierung erfolgreich";
|
|
||||||
$message = "Ihre Registrierung wurde erfolgreich abgeschlossen. Sie können sich jetzt anmelden.";
|
|
||||||
$link = '<a class="button confirm-button" href="index.php?pfad=login">Zum Login</a>';
|
|
||||||
$isSuccess = true;
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$message = "Die Registrierung konnte nicht abgeschlossen werden.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<main class="login-page">
|
|
||||||
<div class="login-container">
|
|
||||||
|
|
||||||
<h1><?php echo htmlspecialchars($title); ?></h1>
|
|
||||||
|
|
||||||
<p class="alert-message <?php echo $isSuccess ? 'is-success' : 'is-error'; ?> confirm-message">
|
|
||||||
<?php echo htmlspecialchars($message); ?>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<?php echo $link; ?>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
+2
-8
@@ -11,8 +11,8 @@ $error = $error ?? null;
|
|||||||
|
|
||||||
<h1>Bitte anmelden</h1>
|
<h1>Bitte anmelden</h1>
|
||||||
|
|
||||||
<?php if (!empty($error)): ?>
|
<?php if ($error): ?>
|
||||||
<p class="alert-message is-error">
|
<p style="color:red;">
|
||||||
<?php echo htmlspecialchars($error); ?>
|
<?php echo htmlspecialchars($error); ?>
|
||||||
</p>
|
</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@@ -41,12 +41,6 @@ $error = $error ?? null;
|
|||||||
anmelden
|
anmelden
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="register-link">
|
|
||||||
<a href="index.php?pfad=password-forgotten">
|
|
||||||
Passwort vergessen?
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="register-link">
|
<div class="register-link">
|
||||||
<a href="index.php?pfad=register">
|
<a href="index.php?pfad=register">
|
||||||
Noch keinen Account? Jetzt hier registrieren!
|
Noch keinen Account? Jetzt hier registrieren!
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
$error = $error ?? null;
|
|
||||||
$success = $success ?? null;
|
|
||||||
?>
|
|
||||||
|
|
||||||
<main class="login-page">
|
|
||||||
<div class="login-container">
|
|
||||||
|
|
||||||
<h1>Passwort vergessen</h1>
|
|
||||||
|
|
||||||
<?php if (!empty($error)): ?>
|
|
||||||
<p class="alert-message is-error">
|
|
||||||
<?php echo htmlspecialchars($error); ?>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if (!empty($success)): ?>
|
|
||||||
<p class="alert-message is-success">
|
|
||||||
<?php echo $success; ?>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="post" action="index.php?pfad=password-forgotten">
|
|
||||||
|
|
||||||
<p class="input-label">E-Mail-Adresse:</p>
|
|
||||||
<input type="email"
|
|
||||||
name="email"
|
|
||||||
class="login-input"
|
|
||||||
placeholder="E-Mail-Adresse"
|
|
||||||
required>
|
|
||||||
|
|
||||||
<p class="input-label">Neues Passwort:</p>
|
|
||||||
<input type="password"
|
|
||||||
name="password"
|
|
||||||
class="login-input"
|
|
||||||
placeholder="Neues Passwort"
|
|
||||||
required>
|
|
||||||
|
|
||||||
<button type="submit"
|
|
||||||
name="passwordForgottenSubmit"
|
|
||||||
class="button">
|
|
||||||
Passwort zurücksetzen
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="register-link">
|
|
||||||
<a href="index.php?pfad=login">
|
|
||||||
Zurück zum Login
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
$error = $error ?? null;
|
$error = $error ?? null;
|
||||||
$success = $success ?? null;
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -13,17 +12,11 @@ $success = $success ?? null;
|
|||||||
<h1>Jetzt Registrieren!</h1>
|
<h1>Jetzt Registrieren!</h1>
|
||||||
|
|
||||||
<?php if (!empty($error)): ?>
|
<?php if (!empty($error)): ?>
|
||||||
<p class="alert-message is-error">
|
<p class="alert-message is-error" style="color:red;">
|
||||||
<?php echo htmlspecialchars($error); ?>
|
<?php echo htmlspecialchars($error); ?>
|
||||||
</p>
|
</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (!empty($success)): ?>
|
|
||||||
<p class="alert-message is-success">
|
|
||||||
<?php echo $success; ?>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form method="post" action="index.php?pfad=register">
|
<form method="post" action="index.php?pfad=register">
|
||||||
|
|
||||||
<p class="input-label">Email:</p>
|
<p class="input-label">Email:</p>
|
||||||
|
|||||||
+57
-32
@@ -27,7 +27,8 @@ if ($currentPage < 1) {
|
|||||||
$offset = ($currentPage - 1) * $limit;
|
$offset = ($currentPage - 1) * $limit;
|
||||||
|
|
||||||
// Nur die Ergebnisse für die aktuelle Seite ausschneiden
|
// Nur die Ergebnisse für die aktuelle Seite ausschneiden
|
||||||
$results = array_slice($all_results, $offset, $limit);
|
//$results = array_slice($all_results, $offset, $limit);
|
||||||
|
$results = $all_results;
|
||||||
$resultCount = count($results);
|
$resultCount = count($results);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -44,12 +45,11 @@ $resultCount = count($results);
|
|||||||
<!-- Links: Seitenleiste für Filter und Suche -->
|
<!-- Links: Seitenleiste für Filter und Suche -->
|
||||||
<aside class="s-res-sidebar">
|
<aside class="s-res-sidebar">
|
||||||
|
|
||||||
<!-- Sortierfuntion Box und Such Box-->
|
<form action="php/controller/search-results-controller.php" method="GET" id="search-form-id" class="s-res-sidebar-form">
|
||||||
<form id="search-form-id" action="php/controller/search-results-controller.php" method="GET" class="s-res-sidebar-form">
|
|
||||||
<!-- Dieses Feld hält die aktuelle Seitenzahl für den Submit bereit -->
|
<input type="hidden" id="s-res-page-input" name="page" value="<?php echo $_GET['page'] ?? 1; ?>">
|
||||||
<input type="hidden" name="page" id="s-res-page-input" value="<?php echo $currentPage; ?>">
|
|
||||||
|
|
||||||
<div class="s-res-sidebar-box">
|
<div class="s-res-sidebar-box">
|
||||||
<h3 class="s-res-sidebar-title">Suche anpassen</h3>
|
<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>
|
<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>
|
<button type="submit" class="nav__search-button">Suchen</button>
|
||||||
@@ -60,25 +60,57 @@ $resultCount = count($results);
|
|||||||
<?php $currentSort = $_SESSION['search_sort'] ?? 'alphabet'; ?>
|
<?php $currentSort = $_SESSION['search_sort'] ?? 'alphabet'; ?>
|
||||||
<div class="s-res-filter-group">
|
<div class="s-res-filter-group">
|
||||||
<label class="s-res-filter-option">
|
<label class="s-res-filter-option">
|
||||||
<input type="radio" name="sort" value="alphabet" <?php echo $currentSort === 'alphabet' ? 'checked' : ''; ?> onchange="this.form.submit()">
|
<input type="radio" name="sort" value="alphabet" class="sort-radio" <?php echo $currentSort === 'alphabet' ? 'checked' : ''; ?>>
|
||||||
<span>Alphabetisch</span>
|
<span>Alphabetisch</span>
|
||||||
</label>
|
</label>
|
||||||
<!-- Noch disabled, da likes noch nicht implementiert-->
|
|
||||||
<label class="s-res-filter-option">
|
<label class="s-res-filter-option">
|
||||||
<input type="radio" name="sort" value="likes" <?php echo $currentSort === 'likes' ? 'checked' : ''; ?> onchange="this.form.submit()">
|
<input type="radio" name="sort" value="likes" class="sort-radio" <?php echo $currentSort === 'likes' ? 'checked' : ''; ?>>
|
||||||
<span>Beliebtheit (Likes)</span>
|
<span>Beliebtheit (Likes)</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="s-res-filter-option">
|
<label class="s-res-filter-option">
|
||||||
<input type="radio" name="sort" value="newest" <?php echo $currentSort === 'newest' ? 'checked' : ''; ?> onchange="this.form.submit()">
|
<input type="radio" name="sort" value="newest" class="sort-radio" <?php echo $currentSort === 'newest' ? 'checked' : ''; ?>>
|
||||||
<span>Neueste Beiträge</span>
|
<span>Neueste Beiträge</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="s-res-filter-option">
|
<label class="s-res-filter-option">
|
||||||
<input type="radio" name="sort" value="oldest" <?php echo $currentSort === 'oldest' ? 'checked' : ''; ?> onchange="this.form.submit()">
|
<input type="radio" name="sort" value="oldest" class="sort-radio" <?php echo $currentSort === 'oldest' ? 'checked' : ''; ?>>
|
||||||
<span>Älteste Beiträge</span>
|
<span>Älteste Beiträge</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="s-res-sidebar-box">
|
||||||
|
<h3 class="s-res-sidebar-title">Kategorie filtern</h3>
|
||||||
|
<select id="category-filter" class="s-res-limit-select" style="width: 100%; padding: 8px; border-radius: 6px; border: 1px solid #cbd5e1;">
|
||||||
|
<option value="all">Alle Kategorien</option>
|
||||||
|
<option value="Deutsch">Deutsch</option>
|
||||||
|
<option value="Englisch">Englisch</option>
|
||||||
|
<option value="Franzoesisch">Französisch</option>
|
||||||
|
<option value="Latein">Latein</option>
|
||||||
|
<option value="Literatur">Literatur</option>
|
||||||
|
<option value="Mathematik">Mathematik</option>
|
||||||
|
<option value="Biologie">Biologie</option>
|
||||||
|
<option value="Informatik">Informatik</option>
|
||||||
|
<option value="Chemie">Chemie</option>
|
||||||
|
<option value="Physik">Physik</option>
|
||||||
|
<option value="Astronomie">Astronomie</option>
|
||||||
|
<option value="Geschichte">Geschichte</option>
|
||||||
|
<option value="Erdkunde">Erdkunde</option>
|
||||||
|
<option value="Sozialkunde">Sozialkunde</option>
|
||||||
|
<option value="Wirtschaftskunde">Wirtschaftskunde</option>
|
||||||
|
<option value="Religion">Religion</option>
|
||||||
|
<option value="Ethikunterricht">Ethikunterricht</option>
|
||||||
|
<option value="Philosophie">Philosophie</option>
|
||||||
|
<option value="Psychologie">Psychologie</option>
|
||||||
|
<option value="Kunst">Kunst</option>
|
||||||
|
<option value="Musik">Musik</option>
|
||||||
|
<option value="Theater">Theater</option>
|
||||||
|
<option value="Technik">Technik</option>
|
||||||
|
<option value="Werken">Werken</option>
|
||||||
|
<option value="Hauswirtschaft">Hauswirtschaft</option>
|
||||||
|
<option value="Sport">Sport</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
@@ -95,8 +127,11 @@ $resultCount = count($results);
|
|||||||
<?php
|
<?php
|
||||||
if (!empty($results)): ?>
|
if (!empty($results)): ?>
|
||||||
|
|
||||||
<?php foreach ($results as $item): ?>
|
<?php foreach ($results as $item):
|
||||||
<div class="s-res-item">
|
// Anzahl der Likes ermitteln (falls es ein Array ist, zählen; falls Zahl, direkt nutzen)
|
||||||
|
$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">
|
<div class="s-res-content">
|
||||||
<h2 class="s-res-item-title">
|
<h2 class="s-res-item-title">
|
||||||
<a href="index.php?pfad=showArticle&id=<?php echo $item['id']; ?>" class="s-res-link">
|
<a href="index.php?pfad=showArticle&id=<?php echo $item['id']; ?>" class="s-res-link">
|
||||||
@@ -107,10 +142,9 @@ $resultCount = count($results);
|
|||||||
<p class="s-res-author">Von: <span class="s-res-author-name"><?php echo htmlspecialchars($item['author']); ?></span></p>
|
<p class="s-res-author">Von: <span class="s-res-author-name"><?php echo htmlspecialchars($item['author']); ?></span></p>
|
||||||
|
|
||||||
<span class="s-res-likes">
|
<span class="s-res-likes">
|
||||||
❤️ <?php echo isset($item['likes']) && is_array($item['likes']) ? count($item['likes']) : 0; ?>
|
❤️ <?php echo $likesCount; ?>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="s-res-arrow">→</div>
|
<div class="s-res-arrow">→</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,8 +154,8 @@ $resultCount = count($results);
|
|||||||
elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
|
elseif (isset($_SESSION["search_query"]) && $_SESSION["search_query"] !== "" && $resultCount === 0): ?>
|
||||||
<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>
|
<p>Keine Beiträge zu diesem Suchbegriff gefunden.</p>
|
||||||
<?php
|
<?php
|
||||||
elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "missing_parameters"): ?>
|
elseif (isset($_SESSION["message"]) && $_SESSION["message"] == "invalid_search_query"): ?>
|
||||||
<p>Bitte überprüfe deine Sucheingabe und versuche es erneut!</p>
|
<p>Unzulässige Suchanfrage</p>
|
||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php
|
<?php
|
||||||
@@ -143,23 +177,14 @@ $resultCount = count($results);
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="s-res-page-navigation">
|
<div class="s-res-page-navigation">
|
||||||
<button type="button" class="s-res-page-btn" data-page="<?php echo $currentPage - 1; ?>" <?php echo $currentPage <= 1 ? 'disabled' : ''; ?>>
|
<button type="button" class="s-res-page-btn" id="prev-page-btn" data-page="0">«</button>
|
||||||
«
|
|
||||||
</button>
|
<span id="dynamic-page-numbers"></span>
|
||||||
<!-- Dynamische Seitenzahlen -->
|
|
||||||
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
|
<button type="button" class="s-res-page-btn" id="next-page-btn" data-page="2">»</button>
|
||||||
<button type="button"
|
|
||||||
class="s-res-page-btn <?php echo $i === $currentPage ? 's-res-page-btn-active' : ''; ?>"
|
|
||||||
data-page="<?php echo $i; ?>">
|
|
||||||
<?php echo $i; ?>
|
|
||||||
</button>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<button type="button" class="s-res-page-btn" data-page="<?php echo $currentPage + 1; ?>" <?php echo $currentPage >= $totalPages ? 'disabled' : ''; ?>>
|
|
||||||
»
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Zeigt den Inhalt einer simulierten E-Mail an.
|
|
||||||
* Die Datei wird über einen zufällig erzeugten Token geladen.
|
|
||||||
*/
|
|
||||||
|
|
||||||
$token = basename($_GET["token"] ?? "");
|
|
||||||
$file = __DIR__ . "/../data/mails/" . $token . ".html";
|
|
||||||
|
|
||||||
if (!file_exists($file)) {
|
|
||||||
echo "<p>Datei nicht gefunden.</p>";
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
<main class="login-page">
|
|
||||||
<div class="login-container">
|
|
||||||
<h1>Simulierte E-Mail</h1>
|
|
||||||
|
|
||||||
<?php include $file; ?>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
+15
-15
@@ -130,6 +130,13 @@ h1 {
|
|||||||
color: #1f2937;
|
color: #1f2937;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input-label {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
color: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
.login-input {
|
.login-input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
@@ -203,6 +210,14 @@ h1 {
|
|||||||
.form-container {
|
.form-container {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
padding: 30px;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #dbe3ec;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-container {
|
||||||
flex: 1 1 450px;
|
flex: 1 1 450px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@@ -210,19 +225,4 @@ h1 {
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
|
box-shadow: 0 6px 20px rgba(0,0,0,0.1);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
|
||||||
|
|
||||||
/* Darstellung der Registrierungsbestätigung */
|
|
||||||
.confirm-message {
|
|
||||||
text-align: center;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Anpassung des Login-Buttons auf der Bestätigungsseite */
|
|
||||||
.confirm-button {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
text-decoration: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
<?php
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<?php
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<?php
|
|
||||||
@@ -17,9 +17,6 @@ if ($pfad === "login") {
|
|||||||
if ($pfad === "register") {
|
if ($pfad === "register") {
|
||||||
include_once "php/controller/register-controller.php";
|
include_once "php/controller/register-controller.php";
|
||||||
}
|
}
|
||||||
if ($pfad === "password-forgotten") {
|
|
||||||
include_once "php/controller/password-forgotten-controller.php";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pfad === "logout") {
|
if ($pfad === "logout") {
|
||||||
include_once "php/controller/logout-controller.php";
|
include_once "php/controller/logout-controller.php";
|
||||||
@@ -56,8 +53,10 @@ if ($pfad === "deleteAccount") {
|
|||||||
<link rel="stylesheet" href="css/message.css">
|
<link rel="stylesheet" href="css/message.css">
|
||||||
|
|
||||||
<script src="js/paginator.js" async></script>
|
<script src="js/paginator.js" async></script>
|
||||||
|
<script src="js/sorter.js" async></script>
|
||||||
<script src="js/comments.js" defer></script>
|
<script src="js/comments.js" defer></script>
|
||||||
<script src="js/editor.js" async></script>
|
<script src="js/editor.js" async></script>
|
||||||
|
<script src="js/filter.js" async></script>
|
||||||
|
|
||||||
<title>EduForge</title>
|
<title>EduForge</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
let currentClientPage = 1;
|
||||||
|
const itemsPerPage = 10;
|
||||||
|
|
||||||
|
function initFilter() {
|
||||||
|
const filterSelect = document.getElementById('category-filter');
|
||||||
|
const listContainer = document.querySelector('.s-res-list');
|
||||||
|
|
||||||
|
if (!filterSelect || !listContainer) return;
|
||||||
|
|
||||||
|
updateVisibility();
|
||||||
|
|
||||||
|
filterSelect.addEventListener('change', function() {
|
||||||
|
currentClientPage = 1;
|
||||||
|
updateVisibility();
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigationContainer = document.querySelector('.s-res-page-navigation');
|
||||||
|
if (navigationContainer) {
|
||||||
|
navigationContainer.addEventListener('click', function(e) {
|
||||||
|
const button = e.target.closest('.s-res-page-btn');
|
||||||
|
if (!button || button.disabled) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const targetPage = button.getAttribute('data-page');
|
||||||
|
if (targetPage) {
|
||||||
|
currentClientPage = parseInt(targetPage, 10);
|
||||||
|
updateVisibility();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateVisibility() {
|
||||||
|
const filterSelect = document.getElementById('category-filter');
|
||||||
|
const listContainer = document.querySelector('.s-res-list');
|
||||||
|
const selectedCategory = filterSelect.value.toLowerCase().trim();
|
||||||
|
const cards = listContainer.querySelectorAll('.s-res-item');
|
||||||
|
|
||||||
|
let visibleCards = [];
|
||||||
|
cards.forEach(card => {
|
||||||
|
const cardCategory = (card.getAttribute('data-category') || '').toLowerCase().trim();
|
||||||
|
if (selectedCategory === 'all' || cardCategory.includes(selectedCategory) || selectedCategory.includes(cardCategory)) {
|
||||||
|
visibleCards.push(card);
|
||||||
|
} else {
|
||||||
|
card.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalVisible = visibleCards.length;
|
||||||
|
const totalPages = Math.max(1, Math.ceil(totalVisible / itemsPerPage));
|
||||||
|
|
||||||
|
if (currentClientPage < 1) currentClientPage = 1;
|
||||||
|
if (currentClientPage > totalPages) currentClientPage = totalPages;
|
||||||
|
|
||||||
|
const startOffset = (currentClientPage - 1) * itemsPerPage;
|
||||||
|
const endOffset = startOffset + itemsPerPage;
|
||||||
|
|
||||||
|
visibleCards.forEach((card, index) => {
|
||||||
|
if (index >= startOffset && index < endOffset) {
|
||||||
|
card.style.display = 'flex';
|
||||||
|
} else {
|
||||||
|
card.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updatePaginatorUI(currentClientPage, totalPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePaginatorUI(currentPage, totalPages) {
|
||||||
|
const prevBtn = document.getElementById('prev-page-btn');
|
||||||
|
const nextBtn = document.getElementById('next-page-btn');
|
||||||
|
const numbersContainer = document.getElementById('dynamic-page-numbers');
|
||||||
|
|
||||||
|
if (!prevBtn || !nextBtn || !numbersContainer) return;
|
||||||
|
|
||||||
|
prevBtn.setAttribute('data-page', currentPage - 1);
|
||||||
|
prevBtn.disabled = (currentPage <= 1);
|
||||||
|
|
||||||
|
nextBtn.setAttribute('data-page', currentPage + 1);
|
||||||
|
nextBtn.disabled = (currentPage >= totalPages);
|
||||||
|
|
||||||
|
let buttonsHTML = '';
|
||||||
|
for (let i = 1; i <= totalPages; i++) {
|
||||||
|
const activeClass = (i === currentPage) ? 's-res-page-btn-active' : '';
|
||||||
|
buttonsHTML += `<button type="button" class="s-res-page-btn ${activeClass}" data-page="${i}">${i}</button> `;
|
||||||
|
}
|
||||||
|
numbersContainer.innerHTML = buttonsHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hilfsfunktion für Math.ceil in JS
|
||||||
|
function ceil(val) { return Math.ceil(val); }
|
||||||
|
|
||||||
|
// ist das DOM bereits vollständig aufgebaut?
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
// Falls noch geladen wird, auf das Event warten
|
||||||
|
document.addEventListener('DOMContentLoaded', initFilter);
|
||||||
|
} else {
|
||||||
|
// Falls das HTML bereits komplett da ist, sofort ausführen
|
||||||
|
initFilter();
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
function initSorter() {
|
||||||
|
const listContainer = document.querySelector('.s-res-list');
|
||||||
|
const sortRadios = document.querySelectorAll('.sort-radio');
|
||||||
|
|
||||||
|
// wenn keine liste vorhanden, abbrechen
|
||||||
|
if (!listContainer || sortRadios.length === 0) return;
|
||||||
|
|
||||||
|
sortRadios.forEach(radio => {
|
||||||
|
radio.addEventListener('change', function() {
|
||||||
|
const cards = Array.from(listContainer.querySelectorAll('.s-res-item'));
|
||||||
|
const sortValue = this.value;
|
||||||
|
|
||||||
|
cards.sort((a, b) => {
|
||||||
|
if (sortValue === 'likes') {
|
||||||
|
const likesA = parseInt(a.getAttribute('data-likes') || '0', 10);
|
||||||
|
const likesB = parseInt(b.getAttribute('data-likes') || '0', 10);
|
||||||
|
return likesB - likesA;
|
||||||
|
}
|
||||||
|
else if (sortValue === 'alphabet') {
|
||||||
|
// alphabetische sortierung
|
||||||
|
const titleA = a.querySelector('.s-res-link').textContent.trim().toLowerCase();
|
||||||
|
const titleB = b.querySelector('.s-res-link').textContent.trim().toLowerCase();
|
||||||
|
return titleA.localeCompare(titleB);
|
||||||
|
}
|
||||||
|
else if (sortValue === 'newest' || sortValue === 'oldest') {
|
||||||
|
// hoehere ID wird als neuer gesehen
|
||||||
|
const urlA = a.querySelector('.s-res-link').getAttribute('href');
|
||||||
|
const urlB = b.querySelector('.s-res-link').getAttribute('href');
|
||||||
|
|
||||||
|
const idA = parseInt(urlA.match(/id=(\d+)/)[1], 10);
|
||||||
|
const idB = parseInt(urlB.match(/id=(\d+)/)[1], 10);
|
||||||
|
|
||||||
|
return sortValue === 'newest' ? idB - idA : idA - idB;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
listContainer.innerHTML = '';
|
||||||
|
cards.forEach(card => listContainer.appendChild(card));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ist das DOM bereits vollständig aufgebaut?
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initSorter);
|
||||||
|
} else {
|
||||||
|
initSorter();
|
||||||
|
}
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once "php/model/UserManager.php";
|
|
||||||
require_once "php/validator/user-validator.php";
|
|
||||||
|
|
||||||
$error = null;
|
|
||||||
$success = null;
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
||||||
|
|
||||||
$email = trim($_POST["email"] ?? "");
|
|
||||||
$plainPassword = $_POST["password"] ?? "";
|
|
||||||
|
|
||||||
if (!userEmailValidator($email)) {
|
|
||||||
$error = "Bitte gib eine gültige E-Mail-Adresse ein.";
|
|
||||||
} elseif (!userPasswordValidator($plainPassword)) {
|
|
||||||
$error = "Das Passwort muss 5 bis 12 Zeichen lang sein.";
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
$dao = UserManager::getInstance();
|
|
||||||
|
|
||||||
$token = bin2hex(random_bytes(16));
|
|
||||||
$existingUser = $dao->findUser($email);
|
|
||||||
|
|
||||||
if (!is_dir("data/mails") && !mkdir("data/mails", 0777, true)) {
|
|
||||||
throw new RuntimeException("Ordner data/mails konnte nicht erstellt werden.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_dir("data/pending-password") && !mkdir("data/pending-password", 0777, true)) {
|
|
||||||
throw new RuntimeException("Ordner data/pending-password konnte nicht erstellt werden.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_writable("data/mails") || !is_writable("data/pending-password")) {
|
|
||||||
throw new RuntimeException("Ordner sind nicht beschreibbar.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($existingUser !== null) {
|
|
||||||
$pendingData = [
|
|
||||||
"email" => $email,
|
|
||||||
"password" => $plainPassword
|
|
||||||
];
|
|
||||||
|
|
||||||
file_put_contents(
|
|
||||||
"data/pending-password/" . $token . ".json",
|
|
||||||
json_encode($pendingData, JSON_PRETTY_PRINT)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($existingUser !== null) {
|
|
||||||
$mailContent = "
|
|
||||||
<h2>Passwort zurücksetzen</h2>
|
|
||||||
<p>Falls Sie diese Anfrage nicht gestellt haben, können Sie diese Nachricht ignorieren.</p>
|
|
||||||
<p>
|
|
||||||
<a href='index.php?pfad=confirm-password&token=$token'>
|
|
||||||
Passwortänderung bestätigen
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
";
|
|
||||||
} else {
|
|
||||||
$mailContent = "
|
|
||||||
<h2>Passwort zurücksetzen</h2>
|
|
||||||
<p>Falls Sie diese Anfrage nicht gestellt haben, können Sie diese Nachricht ignorieren.</p>
|
|
||||||
<p>Für diese E-Mail-Adresse wurde kein Konto gefunden.</p>
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents("data/mails/" . $token . ".html", $mailContent);
|
|
||||||
|
|
||||||
$success = 'Weitere Infos finden Sie in der Datei
|
|
||||||
<a href="index.php?pfad=show-mail&token=' . htmlspecialchars($token) . '" target="_blank">xy</a>.';
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$error = "Die Passwortänderung konnte nicht verarbeitet werden.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,6 @@ require_once "php/model/UserManager.php";
|
|||||||
require_once "php/validator/user-validator.php";
|
require_once "php/validator/user-validator.php";
|
||||||
|
|
||||||
$error = null;
|
$error = null;
|
||||||
$success = null;
|
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
|
|
||||||
@@ -25,71 +24,20 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|||||||
try {
|
try {
|
||||||
$dao = UserManager::getInstance();
|
$dao = UserManager::getInstance();
|
||||||
|
|
||||||
// Token für die simulierte E-Mail und die spätere Bestätigung erzeugen.
|
$password = password_hash($plainPassword, PASSWORD_DEFAULT);
|
||||||
$token = bin2hex(random_bytes(16));
|
|
||||||
$existingUser = $dao->findUser($email);
|
|
||||||
|
|
||||||
if (!is_dir("data/mails") && !mkdir("data/mails", 0777, true)) {
|
$dao->addUser($email, $vorname, $nachname, $password);
|
||||||
throw new RuntimeException("Ordner data/mails konnte nicht erstellt werden.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_dir("data/pending") && !mkdir("data/pending", 0777, true)) {
|
$_SESSION["user"] = $vorname . " " . $nachname;
|
||||||
throw new RuntimeException("Ordner data/pending konnte nicht erstellt werden.");
|
$_SESSION["user_email"] = $email;
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_writable("data/mails")) {
|
header("Location: index.php");
|
||||||
throw new RuntimeException("Ordner data/mails ist nicht beschreibbar.");
|
exit();
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_writable("data/pending")) {
|
|
||||||
throw new RuntimeException("Ordner data/pending ist nicht beschreibbar.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($existingUser === null) {
|
|
||||||
$password = password_hash($plainPassword, PASSWORD_DEFAULT);
|
|
||||||
|
|
||||||
$pendingData = [
|
|
||||||
"email" => $email,
|
|
||||||
"vorname" => $vorname,
|
|
||||||
"nachname" => $nachname,
|
|
||||||
"password" => $password
|
|
||||||
];
|
|
||||||
|
|
||||||
file_put_contents(
|
|
||||||
"data/pending/" . $token . ".json",
|
|
||||||
json_encode($pendingData, JSON_PRETTY_PRINT)
|
|
||||||
);
|
|
||||||
|
|
||||||
$mailContent = "
|
|
||||||
<h2>Registrierung bestätigen</h2>
|
|
||||||
<p>Bitte ignorieren Sie diese Nachricht, wenn Sie sich nicht registrieren wollten.</p>
|
|
||||||
<p>
|
|
||||||
<a href='index.php?pfad=confirm-register&token=$token'>
|
|
||||||
Registrierung bestätigen
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
";
|
|
||||||
} else {
|
|
||||||
$mailContent = "
|
|
||||||
<h2>Registrierung</h2>
|
|
||||||
<p>Bitte ignorieren Sie diese Nachricht, wenn Sie sich nicht registrieren wollten.</p>
|
|
||||||
<p>Sie sind bereits registriert.</p>
|
|
||||||
<p>
|
|
||||||
<a href='index.php?pfad=password-forgotten'>
|
|
||||||
Passwort vergessen
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
";
|
|
||||||
}
|
|
||||||
|
|
||||||
file_put_contents("data/mails/" . $token . ".html", $mailContent);
|
|
||||||
|
|
||||||
// Neutrale Meldung, damit nicht sichtbar wird, ob die E-Mail bereits registriert ist.
|
|
||||||
$success = 'Weitere Infos finden Sie in der Datei
|
|
||||||
<a href="index.php?pfad=show-mail&token=' . htmlspecialchars($token) . '" target="_blank">xy</a>.';
|
|
||||||
|
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
$error = $e->getMessage();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
$error = "Die Registrierung konnte nicht verarbeitet werden.";
|
$error = "Die Registrierung konnte nicht gespeichert werden.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,15 @@ if (session_status() === PHP_SESSION_NONE) {
|
|||||||
require_once '../model/LocalArticleManager.php';
|
require_once '../model/LocalArticleManager.php';
|
||||||
require_once '../model/ArticleManager.php';
|
require_once '../model/ArticleManager.php';
|
||||||
require_once '../model/Article.php';
|
require_once '../model/Article.php';
|
||||||
|
require_once '../validator/search-validator.php';
|
||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
||||||
|
|
||||||
$search = trim($_GET["q"]);
|
$search = trim($_GET["q"]);
|
||||||
if (empty($search)) {
|
if (!searchQueryValidator($search)) {
|
||||||
$_SESSION["search_results"] = [];
|
$_SESSION["search_results"] = [];
|
||||||
$_SESSION["search_query"] = "";
|
$_SESSION["search_query"] = "";
|
||||||
$_SESSION["message"] = "missing_parameters";
|
$_SESSION["message"] = "invalid_search_query";
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -70,6 +71,9 @@ if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
|||||||
|
|
||||||
$sort = $_GET['sort'] ?? 'alphabet';
|
$sort = $_GET['sort'] ?? 'alphabet';
|
||||||
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
||||||
|
if (!searchLimitValidator($limit)) {
|
||||||
|
$limit = 10;
|
||||||
|
}
|
||||||
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||||
header("Location: ../../index.php?pfad=search-results&q=" . urlencode($search) . "&sort=" . urlencode($sort) . "&limit=" . $limit . "&page=" . $page);
|
header("Location: ../../index.php?pfad=search-results&q=" . urlencode($search) . "&sort=" . urlencode($sort) . "&limit=" . $limit . "&page=" . $page);
|
||||||
exit();
|
exit();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ require_once '../model/ArticleManager.php';
|
|||||||
require_once '../model/Article.php';
|
require_once '../model/Article.php';
|
||||||
require_once '../validator/article-validator.php';
|
require_once '../validator/article-validator.php';
|
||||||
|
|
||||||
if (!isset($_SESSION["user_email"])) {
|
if (!isset($_SESSION["user"])) {
|
||||||
header("Location: index.php?pfad=login");
|
header("Location: index.php?pfad=login");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ if (!isset($_SESSION["user_email"])) {
|
|||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
$_SESSION["old_title"] = $_POST["title"] ?? '';
|
$_SESSION["old_title"] = $_POST["title"] ?? '';
|
||||||
$_SESSION["old_content"] = $_POST["content"] ?? '';
|
$_SESSION["old_content"] = $_POST["content"] ?? '';
|
||||||
$_SESSION["old_category"] = $_POST["category"] ?? '';
|
$_SESSION["old_category"] = $_POST["category"] ?? ''; // TODO: die Kategorie im Dropdown setzen, wenn der Editor erneut geöffnet wird.
|
||||||
$_SESSION["old_tags"] = $_POST["tags"] ?? '';
|
$_SESSION["old_tags"] = $_POST["tags"] ?? '';
|
||||||
|
|
||||||
if (isset($_GET["id"]) && !empty($_GET["id"])) {
|
if (isset($_GET["id"]) && !empty($_GET["id"])) {
|
||||||
@@ -30,7 +30,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|||||||
try {
|
try {
|
||||||
$articleManager = ArticleManager::getInstance();
|
$articleManager = ArticleManager::getInstance();
|
||||||
$article = $articleManager->getArticle($id);
|
$article = $articleManager->getArticle($id);
|
||||||
if ($article->getAuthor() != $_SESSION["user_email"]) {
|
if ($article->getAuthor() != $_SESSION["user"]->getUsername()) {
|
||||||
$_SESSION["message"] = "unauthorized_access";
|
$_SESSION["message"] = "unauthorized_access";
|
||||||
header("location: ../../index.php");
|
header("location: ../../index.php");
|
||||||
exit();
|
exit();
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft, ob eine Suchanfrage gültig ist.
|
||||||
|
*
|
||||||
|
* Erlaubt werden Buchstaben, Zahlen, Umlaute, typische Satzzeichen und Leerzeichen.
|
||||||
|
* Die Länge muss zwischen 1 und 50 Zeichen liegen.
|
||||||
|
*
|
||||||
|
* @param string $query Zu prüfender Suchbegriff
|
||||||
|
*
|
||||||
|
* @return bool true wenn die Suche gültig ist, sonst false
|
||||||
|
*/
|
||||||
|
function searchQueryValidator($query)
|
||||||
|
{
|
||||||
|
$query = trim($query);
|
||||||
|
|
||||||
|
// Mindestens 1 Zeichen, maximal 50 Zeichen
|
||||||
|
$length = mb_strlen($query);
|
||||||
|
if ($length < 1 || $length > 50) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Erlaubt Buchstaben (inkl. Umlaut/ß), Zahlen, Leerzeichen sowie ?, !, ., -, _
|
||||||
|
$searchPattern = '/^[a-zA-Z0-9äöüÄÖÜß\s?!.,\-_]+$/u';
|
||||||
|
|
||||||
|
return preg_match($searchPattern, $query) === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft, ob das gewählte Treffer-Limit erlaubt ist.
|
||||||
|
*
|
||||||
|
* @param int|string $limit Das zu prüfende Limit
|
||||||
|
*
|
||||||
|
* @return bool true wenn das Limit 10, 20, 50 oder 100 ist, sonst false
|
||||||
|
*/
|
||||||
|
function searchLimitValidator($limit)
|
||||||
|
{
|
||||||
|
$allowedLimits = [10, 20, 50, 100];
|
||||||
|
return in_array((int)$limit, $allowedLimits, true);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user