Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca643dd298 | |||
| e19225e49e | |||
| 9ffbca679e | |||
| d90a10e462 | |||
| b6f25d041b | |||
| d1b3641754 | |||
| 5281c1bc7d | |||
| af17764346 | |||
| a8d321609d | |||
| 23ccbe2d02 | |||
| 47239016c5 | |||
| f4f6960b9d | |||
| c4c299eed6 | |||
| e20b59b43d | |||
| 901232b683 | |||
| 40c5fa69f5 | |||
| 7694396454 | |||
| dafc149bba | |||
| f23ec27247 | |||
| efb179dec2 | |||
| 86222aa92e | |||
| a5fb5cd360 | |||
| 6f6e53a483 | |||
| f13a2c6f1e | |||
| 59012cacfb | |||
| 21c5471d73 | |||
| e1ee70b46f | |||
| eb56b8d6a0 | |||
| d597046f41 | |||
| ae1c873536 | |||
| 95251d23ad | |||
| c16bf574ce | |||
| 0e44d92baa | |||
| f2ef3c08a7 | |||
| 8a66e8af3f | |||
| 41d1cc6013 | |||
| c9c6a4ae81 |
@@ -19,6 +19,8 @@
|
||||
- Die Suchseite und Kategorieseite packen momentan alle passenden Beiträge untereinander. Später sollen zunächst 10
|
||||
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.
|
||||
- id in showArticle-controller.php und updateArticle-controller.php wird nicht als gültige numerische ID geprüft.
|
||||
- sort in search-results-controller.php wird nicht gegen erlaubte Werte validiert.
|
||||
|
||||
## Besonderheiten des Projektes
|
||||
- Es wurde ein einfacher Beitrags-Editor erstellt. Mit diesem können Beiträge erstellt oder bearbeitet werden.
|
||||
|
||||
+193
-27
@@ -51,45 +51,211 @@ if (!isset($_SESSION["user"])) {
|
||||
<div class="sidebar-block">
|
||||
<label for="category">Kategorie <span class="required">*</span></label>
|
||||
<select id="category" name="category" required>
|
||||
<option value="" disabled selected>Kategorie wählen...</option>
|
||||
<option disabled <?php
|
||||
if ((!isset($_SESSION['old_category']) || empty($_SESSION['old_category'])) && (!isset($category) || empty($category))) {
|
||||
echo 'selected';
|
||||
}
|
||||
?>>Kategorie wählen...</option>
|
||||
|
||||
<optgroup label="Sprachen">
|
||||
<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="deutsch" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'deutsch') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'deutsch') { echo 'selected'; }
|
||||
}
|
||||
?>>Deutsch</option>
|
||||
<option value="englisch" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'englisch') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'englisch') { echo 'selected'; }
|
||||
}
|
||||
?>>Englisch</option>
|
||||
<option value="franzoesisch" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'franzoesisch') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'franzoesisch') { echo 'selected'; }
|
||||
}
|
||||
?>>Französisch</option>
|
||||
<option value="latein" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'latein') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'latein') { echo 'selected'; }
|
||||
}
|
||||
?>>Latein</option>
|
||||
<option value="literatur" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'literatur') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'literatur') { echo 'selected'; }
|
||||
}
|
||||
?>>Literatur</option>
|
||||
</optgroup>
|
||||
|
||||
<optgroup label="MINT">
|
||||
<option value="mathe">Mathematik</option>
|
||||
<option value="biologie">Biologie</option>
|
||||
<option value="chemie">Chemie</option>
|
||||
<option value="physik">Physik</option>
|
||||
<option value="informatik">Informatik</option>
|
||||
<option value="astronomie">Astronomie</option>
|
||||
<option value="mathe" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'mathe') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'mathe') { echo 'selected'; }
|
||||
}
|
||||
?>>Mathematik</option>
|
||||
<option value="biologie" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'biologie') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'biologie') { echo 'selected'; }
|
||||
}
|
||||
?>>Biologie</option>
|
||||
<option value="chemie" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'chemie') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'chemie') { echo 'selected'; }
|
||||
}
|
||||
?>>Chemie</option>
|
||||
<option value="physik" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'physik') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'physik') { echo 'selected'; }
|
||||
}
|
||||
?>>Physik</option>
|
||||
<option value="informatik" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'informatik') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'informatik') { echo 'selected'; }
|
||||
}
|
||||
?>>Informatik</option>
|
||||
<option value="astronomie" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'astronomie') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'astronomie') { echo 'selected'; }
|
||||
}
|
||||
?>>Astronomie</option>
|
||||
</optgroup>
|
||||
|
||||
<optgroup label="Gesellschaft & Werte">
|
||||
<option value="geschichte">Geschichte</option>
|
||||
<option value="erdkunde">Erdkunde</option>
|
||||
<option value="sozialkunde">Sozialkunde</option>
|
||||
<option value="wirtschaft">Wirtschaftskunde</option>
|
||||
<option value="religion">Religion</option>
|
||||
<option value="ethik">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="geschichte" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'geschichte') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'geschichte') { echo 'selected'; }
|
||||
}
|
||||
?>>Geschichte</option>
|
||||
<option value="erdkunde" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'erdkunde') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'erdkunde') { echo 'selected'; }
|
||||
}
|
||||
?>>Erdkunde</option>
|
||||
<option value="sozialkunde" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'sozialkunde') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'sozialkunde') { echo 'selected'; }
|
||||
}
|
||||
?>>Sozialkunde</option>
|
||||
<option value="wirtschaft" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'wirtschaft') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'wirtschaft') { echo 'selected'; }
|
||||
}
|
||||
?>>Wirtschaftskunde</option>
|
||||
<option value="religion" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'religion') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'religion') { echo 'selected'; }
|
||||
}
|
||||
?>>Religion</option>
|
||||
<option value="ethik" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'ethik') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'ethik') { echo 'selected'; }
|
||||
}
|
||||
?>>Ethikunterricht</option>
|
||||
<option value="philosophie" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'philosophie') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'philosophie') { echo 'selected'; }
|
||||
}
|
||||
?>>Philosophie</option>
|
||||
<option value="psychologie" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'psychologie') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'psychologie') { echo 'selected'; }
|
||||
}
|
||||
?>>Psychologie</option>
|
||||
<option value="kunst" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'kunst') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'kunst') { echo 'selected'; }
|
||||
}
|
||||
?>>Kunst</option>
|
||||
<option value="musik" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'musik') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'musik') { echo 'selected'; }
|
||||
}
|
||||
?>>Musik</option>
|
||||
<option value="theater" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'theater') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'theater') { echo 'selected'; }
|
||||
}
|
||||
?>>Theater</option>
|
||||
</optgroup>
|
||||
|
||||
<optgroup label="Technik & Praxis">
|
||||
<option value="technik">Technik</option>
|
||||
<option value="werken">Werken</option>
|
||||
<option value="hauswirtschaft">Hauswirtschaft</option>
|
||||
<option value="sport">Sport</option>
|
||||
<option value="technik" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'technik') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'technik') { echo 'selected'; }
|
||||
}
|
||||
?>>Technik</option>
|
||||
<option value="werken" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'werken') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'werken') { echo 'selected'; }
|
||||
}
|
||||
?>>Werken</option>
|
||||
<option value="hauswirtschaft" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'hauswirtschaft') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'hauswirtschaft') { echo 'selected'; }
|
||||
}
|
||||
?>>Hauswirtschaft</option>
|
||||
<option value="sport" <?php
|
||||
if (isset($_SESSION['old_category']) && !empty($_SESSION['old_category'])) {
|
||||
if ($_SESSION['old_category'] === 'sport') { echo 'selected'; }
|
||||
} elseif (isset($category) && !empty($category)) {
|
||||
if ($category === 'sport') { echo 'selected'; }
|
||||
}
|
||||
?>>Sport</option>
|
||||
</optgroup>
|
||||
|
||||
<?php
|
||||
if (isset($_SESSION['old_category'])) {
|
||||
unset($_SESSION['old_category']);
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
+54
-8
@@ -6,8 +6,8 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||
?>
|
||||
|
||||
<main class="form-page">
|
||||
<?php include_once "includes/alertMessages.php" ?>
|
||||
<div class="flexbox">
|
||||
|
||||
<div class="container">
|
||||
|
||||
<?php if (!empty($error)): ?>
|
||||
@@ -93,8 +93,6 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||
|
||||
<div class="container">
|
||||
|
||||
<?php include_once "includes/alertMessages.php"?>
|
||||
|
||||
<h2 class="section-title">Meine Beiträge</h2>
|
||||
|
||||
<div class="articles-list">
|
||||
@@ -157,7 +155,9 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||
</a>
|
||||
|
||||
<form action="php/controller/deleteArticle-controller.php" method="POST">
|
||||
<input type="hidden" name="id" value="<?php echo htmlspecialchars($userArticle->getID()); ?>">
|
||||
<input type="hidden"
|
||||
name="id"
|
||||
value="<?php echo htmlspecialchars($userArticle->getID()); ?>">
|
||||
|
||||
<button type="submit"
|
||||
class="button"
|
||||
@@ -165,7 +165,6 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||
Löschen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
@@ -180,10 +179,57 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||
</button>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php unset($_SESSION["message"]); ?>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<!-- Eigener Bereich für die Kommentare des Nutzers -->
|
||||
<div class="comments-section">
|
||||
|
||||
<h2 class="section-title">Meine Kommentare</h2>
|
||||
|
||||
<!-- Liste aller Kommentare des Nutzers -->
|
||||
<div class="comments-list">
|
||||
|
||||
<?php if (isset($userComments) && count($userComments) > 0): ?>
|
||||
|
||||
<?php foreach ($userComments as $comment): ?>
|
||||
<div class="article-item">
|
||||
|
||||
<!-- Erstellungsdatum des Kommentars -->
|
||||
<div class="article-meta">
|
||||
<span class="article-date">
|
||||
<?php echo htmlspecialchars($comment->getCreated()); ?>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Inhalt des Kommentars -->
|
||||
<p>
|
||||
<?php echo nl2br(htmlspecialchars($comment->getContent())); ?>
|
||||
</p>
|
||||
|
||||
<!-- Link zum Beitrag, unter dem der Kommentar geschrieben wurde -->
|
||||
<a href="index.php?pfad=showArticle&id=<?php echo htmlspecialchars($comment->getArticleId()); ?>"
|
||||
class="edit-link-button">
|
||||
Zum Beitrag
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<p>Du hast noch keine Kommentare geschrieben.</p>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php unset($_SESSION["message"]); ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
@@ -2,19 +2,38 @@
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
$results = $_SESSION["search_results"] ?? [];
|
||||
|
||||
$all_results = $_SESSION["search_results"] ?? [];
|
||||
$query = $_SESSION["search_query"] ?? "";
|
||||
$totalResultsCount = count($all_results);
|
||||
|
||||
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
||||
if (!in_array($limit, [10, 20, 50, 100])) {
|
||||
$limit = 10;
|
||||
}
|
||||
$results = array_slice($results, 0, $limit);
|
||||
|
||||
// Gesamtseitenzahl
|
||||
$totalPages = max(1, ceil($totalResultsCount / $limit));
|
||||
|
||||
// Aktuelle Seite auslesen und validieren
|
||||
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
|
||||
if ($currentPage < 1) {
|
||||
$currentPage = 1;
|
||||
} elseif ($currentPage > $totalPages) {
|
||||
$currentPage = $totalPages;
|
||||
}
|
||||
|
||||
// Startpunkt im Array berechnen (Offset)
|
||||
$offset = ($currentPage - 1) * $limit;
|
||||
|
||||
// Nur die Ergebnisse für die aktuelle Seite ausschneiden
|
||||
$results = array_slice($all_results, $offset, $limit);
|
||||
$resultCount = count($results);
|
||||
|
||||
?>
|
||||
<noscript>
|
||||
Bitte JavaScript aktivieren!
|
||||
</noscript>
|
||||
<!--
|
||||
Seite: Suchergebnisse
|
||||
Inhalt: Zeigt die Ergebnisse einer Suche an
|
||||
@@ -27,8 +46,10 @@ $resultCount = count($results);
|
||||
|
||||
<!-- Sortierfuntion Box und Such Box-->
|
||||
<form id="search-form-id" action="php/controller/search-results-controller.php" method="GET" class="s-res-sidebar-form">
|
||||
|
||||
<div class="s-res-sidebar-box">
|
||||
<!-- Dieses Feld hält die aktuelle Seitenzahl für den Submit bereit -->
|
||||
<input type="hidden" name="page" id="s-res-page-input" value="<?php echo $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>
|
||||
@@ -66,7 +87,7 @@ $resultCount = count($results);
|
||||
|
||||
<div class="s-res-header">
|
||||
<h1 class="s-res-main-title">Suchergebnisse</h1>
|
||||
<p class="s-res-meta"><?php echo $resultCount; ?> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"</p>
|
||||
<p class="s-res-meta"><?php echo $totalResultsCount; ?> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"</p>
|
||||
</div>
|
||||
|
||||
<!-- Ergebnisliste -->
|
||||
@@ -115,9 +136,20 @@ $resultCount = count($results);
|
||||
</div>
|
||||
|
||||
<div class="s-res-page-navigation">
|
||||
<button type="button" class="s-res-page-btn" disabled>«</button>
|
||||
<button type="button" class="s-res-page-btn s-res-page-btn-active">1</button>
|
||||
<button type="button" class="s-res-page-btn">»</button>
|
||||
<button type="button" class="s-res-page-btn" data-page="<?php echo $currentPage - 1; ?>" <?php echo $currentPage <= 1 ? 'disabled' : ''; ?>>
|
||||
«
|
||||
</button>
|
||||
<!-- Dynamische Seitenzahlen -->
|
||||
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
|
||||
<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>
|
||||
|
||||
+102
-5
@@ -1,11 +1,33 @@
|
||||
<?php
|
||||
include_once 'php/controller/showArticle-controller.php';
|
||||
require_once 'php/model/CommentManager.php';
|
||||
|
||||
$comments = [];
|
||||
$mainComments = [];
|
||||
$repliesByParent = [];
|
||||
|
||||
if (isset($_GET["id"])) {
|
||||
try {
|
||||
$commentManager = CommentManager::getInstance();
|
||||
$comments = $commentManager->getCommentsByArticle($_GET["id"]);
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
if ($comment->isReply()) {
|
||||
$parentId = $comment->getParentCommentId();
|
||||
$repliesByParent[$parentId][] = $comment;
|
||||
} else {
|
||||
$mainComments[] = $comment;
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$_SESSION["message"] = "internal_error";
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!--
|
||||
Seite: Anzeige für Beiträge
|
||||
Funktion: Stellt einen übergebenen Beitrag dar.
|
||||
-->
|
||||
|
||||
Seite: Anzeige für Beiträge
|
||||
Funktion: Stellt einen übergebenen Beitrag dar.
|
||||
-->
|
||||
<!-- Hauptcontainer für die Beitragsansicht (Ausschließlich der Content-Bereich) -->
|
||||
<main class="article-view-container">
|
||||
<?php include_once "includes/alertMessages.php"?>
|
||||
@@ -16,6 +38,7 @@ include_once 'php/controller/showArticle-controller.php';
|
||||
<?php if (isset($category) && !empty($category)): ?>
|
||||
<span class="article-view-category"><?php echo htmlspecialchars($category); ?></span>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1 class="article-view-title">
|
||||
<?php if (isset($title)) { echo htmlspecialchars($title); } ?>
|
||||
</h1>
|
||||
@@ -82,5 +105,79 @@ include_once 'php/controller/showArticle-controller.php';
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</main>
|
||||
<section class="article-comments-section">
|
||||
<h2>Kommentare</h2>
|
||||
|
||||
<div id="comments-list">
|
||||
<?php if (!empty($mainComments)): ?>
|
||||
<?php foreach ($mainComments as $comment): ?>
|
||||
<div class="comment-item" data-comment-id="<?php echo htmlspecialchars($comment->getId()); ?>">
|
||||
<p>
|
||||
<strong><?php echo htmlspecialchars($comment->getAuthor()); ?></strong>
|
||||
<span><?php echo htmlspecialchars($comment->getCreated()); ?></span>
|
||||
</p>
|
||||
|
||||
<p><?php echo nl2br(htmlspecialchars($comment->getContent())); ?></p>
|
||||
|
||||
<?php if (isset($_SESSION["user_email"])): ?>
|
||||
<button type="button"
|
||||
class="reply-button"
|
||||
data-comment-id="<?php echo htmlspecialchars($comment->getId()); ?>"
|
||||
data-author="<?php echo htmlspecialchars($comment->getAuthor()); ?>">
|
||||
Antworten
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="comment-replies">
|
||||
<?php if (isset($repliesByParent[$comment->getId()])): ?>
|
||||
<?php foreach ($repliesByParent[$comment->getId()] as $reply): ?>
|
||||
<div class="comment-item comment-reply">
|
||||
<p>
|
||||
<strong><?php echo htmlspecialchars($reply->getAuthor()); ?></strong>
|
||||
<span><?php echo htmlspecialchars($reply->getCreated()); ?></span>
|
||||
</p>
|
||||
|
||||
<p><?php echo nl2br(htmlspecialchars($reply->getContent())); ?></p>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<p class="no-comments-message">
|
||||
Noch keine Kommentare vorhanden.
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_SESSION["user_email"])): ?>
|
||||
<form id="comment-form">
|
||||
<input type="hidden"
|
||||
name="article_id"
|
||||
value="<?php echo htmlspecialchars($_GET["id"] ?? ""); ?>">
|
||||
|
||||
<input type="hidden"
|
||||
name="parent_comment_id"
|
||||
id="parent-comment-id"
|
||||
value="">
|
||||
|
||||
<p id="reply-info" class="reply-info" style="display: none;"></p>
|
||||
|
||||
<textarea name="content"
|
||||
id="comment-content"
|
||||
placeholder="Schreibe einen Kommentar..."
|
||||
required></textarea>
|
||||
|
||||
<button type="submit" class="button">
|
||||
Kommentar senden
|
||||
</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<div class="comment-login-hint">
|
||||
<p>Melde dich an, um einen Kommentar zu schreiben.</p>
|
||||
<a href="index.php?pfad=login" class="button">Jetzt anmelden</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</main>
|
||||
@@ -147,3 +147,96 @@
|
||||
font-size: 1.85rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* --- KOMMENTARE --- */
|
||||
|
||||
.article-comments-section {
|
||||
margin-top: 3rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.article-comments-section h2 {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
#comments-list {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.comment-item {
|
||||
background-color: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
padding: 1rem 1.25rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#comment-form {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#comment-content {
|
||||
width: 100%;
|
||||
min-height: 130px;
|
||||
padding: 1rem;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
#comment-form .button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.reply-button {
|
||||
display: inline-block;
|
||||
margin-top: 0.75rem;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #2563eb;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.reply-button:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.comment-replies {
|
||||
margin-top: 1rem;
|
||||
margin-left: 2rem;
|
||||
padding-left: 1rem;
|
||||
border-left: 3px solid #cbd5e1;
|
||||
}
|
||||
|
||||
.comment-reply {
|
||||
background-color: #eef6ff;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.reply-info {
|
||||
margin: 0.5rem 0;
|
||||
color: #475569;
|
||||
font-weight: 600;
|
||||
}
|
||||
.comment-login-hint {
|
||||
margin-top: 2rem;
|
||||
padding: 1.5rem;
|
||||
background-color: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.comment-login-hint p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -63,6 +63,16 @@
|
||||
Dein Beitrag wurde erfolgreich veröffentlicht!
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "article_updated"): ?>
|
||||
<p class="alert-message is-success">
|
||||
Der Beitrag wurde erfolgreich bearbeitet und gespeichert.
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "profile_updated"): ?>
|
||||
<p class="alert-message is-success">
|
||||
Das Profil wurde erfolgreich bearbeitet.
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($_SESSION["message"]) && $_SESSION["message"] == "image_upload_error"): ?>
|
||||
<p class="alert-message is-error">
|
||||
Das Bild konnte nicht hochgeladen werden. Bitte versuche es erneut oder verwende ein anderes Bildformat.
|
||||
|
||||
@@ -52,7 +52,10 @@ if ($pfad === "deleteAccount") {
|
||||
<link rel="stylesheet" href="css/showArticle.css">
|
||||
<link rel="stylesheet" href="css/message.css">
|
||||
|
||||
<script src="js/paginator.js" async></script>
|
||||
<script src="js/comments.js" defer></script>
|
||||
<script src="js/editor.js" async></script>
|
||||
|
||||
<title>EduForge</title>
|
||||
</head>
|
||||
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* Initialisiert die Kommentarfunktion.
|
||||
*
|
||||
* Kommentare werden per AJAX gespeichert,
|
||||
* ohne dass die Seite neu geladen werden muss.
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const form = document.getElementById("comment-form");
|
||||
const commentsList = document.getElementById("comments-list");
|
||||
const commentContent = document.getElementById("comment-content");
|
||||
const parentCommentInput = document.getElementById("parent-comment-id");
|
||||
const replyInfo = document.getElementById("reply-info");
|
||||
|
||||
if (!form || !commentsList || !commentContent || !parentCommentInput || !replyInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktiviert einen einzelnen Antworten-Button.
|
||||
*
|
||||
* @param {HTMLButtonElement} button Antworten-Button
|
||||
*/
|
||||
function registerReplyButton(button) {
|
||||
button.addEventListener("click", function () {
|
||||
parentCommentInput.value = button.dataset.commentId;
|
||||
replyInfo.textContent = "Antwort auf " + button.dataset.author;
|
||||
replyInfo.style.display = "block";
|
||||
commentContent.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registriert alle bereits vorhandenen Antwort-Buttons.
|
||||
*/
|
||||
document.querySelectorAll(".reply-button").forEach(function (button) {
|
||||
registerReplyButton(button);
|
||||
});
|
||||
|
||||
/**
|
||||
* Sendet Kommentare per AJAX an den Server.
|
||||
*/
|
||||
form.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
const formData = new FormData(form);
|
||||
const parentCommentId = parentCommentInput.value;
|
||||
|
||||
fetch("php/ajax/add-comment.php", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.success) {
|
||||
alert(data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const emptyMessage = commentsList.querySelector(".no-comments-message");
|
||||
|
||||
if (emptyMessage) {
|
||||
emptyMessage.remove();
|
||||
}
|
||||
|
||||
const commentElement = document.createElement("div");
|
||||
commentElement.classList.add("comment-item");
|
||||
|
||||
if (parentCommentId) {
|
||||
commentElement.classList.add("comment-reply");
|
||||
|
||||
commentElement.innerHTML = `
|
||||
<p>
|
||||
<strong>${escapeHtml(data.author)}</strong>
|
||||
<span>${escapeHtml(data.created)}</span>
|
||||
</p>
|
||||
<p>${escapeHtml(data.content).replace(/\n/g, "<br>")}</p>
|
||||
`;
|
||||
|
||||
const parentReplies = document.querySelector(
|
||||
`.comment-item[data-comment-id="${parentCommentId}"] .comment-replies`
|
||||
);
|
||||
|
||||
if (parentReplies) {
|
||||
parentReplies.appendChild(commentElement);
|
||||
}
|
||||
|
||||
} else {
|
||||
commentElement.dataset.commentId = data.commentId;
|
||||
|
||||
commentElement.innerHTML = `
|
||||
<p>
|
||||
<strong>${escapeHtml(data.author)}</strong>
|
||||
<span>${escapeHtml(data.created)}</span>
|
||||
</p>
|
||||
<p>${escapeHtml(data.content).replace(/\n/g, "<br>")}</p>
|
||||
|
||||
<button type="button"
|
||||
class="reply-button"
|
||||
data-comment-id="${escapeHtml(data.commentId)}"
|
||||
data-author="${escapeHtml(data.author)}">
|
||||
Antworten
|
||||
</button>
|
||||
|
||||
<div class="comment-replies"></div>
|
||||
`;
|
||||
|
||||
commentsList.prepend(commentElement);
|
||||
|
||||
const newReplyButton = commentElement.querySelector(".reply-button");
|
||||
|
||||
if (newReplyButton) {
|
||||
registerReplyButton(newReplyButton);
|
||||
}
|
||||
}
|
||||
|
||||
commentContent.value = "";
|
||||
parentCommentInput.value = "";
|
||||
replyInfo.textContent = "";
|
||||
replyInfo.style.display = "none";
|
||||
})
|
||||
.catch(() => {
|
||||
alert("Kommentar konnte nicht gesendet werden.");
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Entfernt HTML-Sonderzeichen aus Nutzereingaben.
|
||||
*
|
||||
* @param {string} text Zu bereinigender Text
|
||||
* @returns {string} Sicherer Text
|
||||
*/
|
||||
function escapeHtml(text) {
|
||||
const div = document.createElement("div");
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
function initPaginator() {
|
||||
const form = document.getElementById('search-form-id');
|
||||
const pageInput = document.getElementById('s-res-page-input');
|
||||
const pageButtons = document.querySelectorAll('.s-res-page-navigation .s-res-page-btn');
|
||||
|
||||
pageButtons.forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
if (this.disabled) return;
|
||||
|
||||
const targetPage = this.getAttribute('data-page');
|
||||
|
||||
if (targetPage && form && pageInput) {
|
||||
pageInput.value = targetPage;
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ist das DOM bereits vollständig aufgebaut?
|
||||
if (document.readyState === 'loading') {
|
||||
// Falls noch geladen wird, auf das Event warten
|
||||
document.addEventListener('DOMContentLoaded', initPaginator);
|
||||
} else {
|
||||
// Falls das HTML bereits komplett da ist, sofort ausführen
|
||||
initPaginator();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
header("Content-Type: application/json");
|
||||
|
||||
require_once "../model/CommentManager.php";
|
||||
|
||||
if (!isset($_SESSION["user_email"])) {
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Du musst angemeldet sein, um zu kommentieren."
|
||||
]);
|
||||
exit();
|
||||
}
|
||||
|
||||
$articleId = $_POST["article_id"] ?? null;
|
||||
$content = trim($_POST["content"] ?? "");
|
||||
$parentCommentId = $_POST["parent_comment_id"] ?? null;
|
||||
|
||||
if ($parentCommentId === "" || $parentCommentId === "0") {
|
||||
$parentCommentId = null;
|
||||
}
|
||||
|
||||
if (empty($articleId) || empty($content)) {
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Kommentar darf nicht leer sein."
|
||||
]);
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
$commentManager = CommentManager::getInstance();
|
||||
|
||||
$commentId = $commentManager->addComment(
|
||||
$articleId,
|
||||
$_SESSION["user_email"],
|
||||
$content,
|
||||
$parentCommentId
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
"success" => true,
|
||||
"commentId" => $commentId,
|
||||
"author" => $_SESSION["user_email"],
|
||||
"content" => $content,
|
||||
"created" => date("Y-m-d H:i:s"),
|
||||
"parentCommentId" => $parentCommentId
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
"success" => false,
|
||||
"message" => "Kommentar konnte nicht gespeichert werden."
|
||||
]);
|
||||
}
|
||||
@@ -6,6 +6,10 @@ require_once '../model/LocalArticleManager.php';
|
||||
require_once '../model/ArticleManager.php';
|
||||
require_once '../validator/article-validator.php';
|
||||
|
||||
if (!isset($_SESSION["user"])) {
|
||||
header("Location: index.php?pfad=login");
|
||||
exit();
|
||||
}
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$_SESSION["old_title"] = $_POST["title"] ?? '';
|
||||
$_SESSION["old_content"] = $_POST["content"] ?? '';
|
||||
|
||||
@@ -6,6 +6,11 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
require_once __DIR__ . "/../model/UserManager.php";
|
||||
require_once __DIR__ . "/../model/ArticleManager.php";
|
||||
|
||||
if (!isset($_SESSION["user"])) {
|
||||
header("Location: index.php?pfad=login");
|
||||
exit();
|
||||
}
|
||||
|
||||
/*
|
||||
Deregistrierung
|
||||
Funktion: Entfernt User aus der Datenbank und beendet die Session
|
||||
|
||||
@@ -5,6 +5,11 @@ if (session_status() === PHP_SESSION_NONE) {
|
||||
|
||||
require_once __DIR__ . "/../model/ArticleManager.php";
|
||||
|
||||
if (!isset($_SESSION["user"])) {
|
||||
header("Location: index.php?pfad=login");
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
|
||||
if (isset($_SESSION["user_email"])) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
require_once "php/model/UserManager.php";
|
||||
require_once "php/model/Article.php";
|
||||
require_once "php/model/ArticleManager.php";
|
||||
require_once "php/model/CommentManager.php";
|
||||
require_once "php/validator/user-validator.php";
|
||||
|
||||
$error = null;
|
||||
@@ -62,6 +63,7 @@ try {
|
||||
$_SESSION["user"] = $vorname . " " . $nachname;
|
||||
$_SESSION["user_email"] = $newEmail;
|
||||
|
||||
$_SESSION["message"] = "profile_updated";
|
||||
header("Location: index.php?pfad=profile");
|
||||
exit();
|
||||
} else {
|
||||
@@ -76,6 +78,9 @@ try {
|
||||
$articleManager = ArticleManager::getInstance();
|
||||
$userArticles = $articleManager->getArticlesByAuthor($_SESSION["user_email"]);
|
||||
|
||||
$commentManager = CommentManager::getInstance();
|
||||
$userComments = $commentManager->getCommentsByAuthor($_SESSION["user_email"]);
|
||||
|
||||
if (!isset($userArticles)) {
|
||||
$_SESSION["message"] = "user_has_no_articles";
|
||||
}
|
||||
|
||||
@@ -62,7 +62,11 @@ if ($_SERVER["REQUEST_METHOD"] === "GET" && isset($_GET["q"])) {
|
||||
$_SESSION["message"] = "internal_error";
|
||||
}
|
||||
}
|
||||
header("Location: ../../index.php?pfad=search-results");
|
||||
|
||||
$sort = $_GET['sort'] ?? 'alphabet';
|
||||
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 10;
|
||||
$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);
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,11 @@ require_once '../model/ArticleManager.php';
|
||||
require_once '../model/Article.php';
|
||||
require_once '../validator/article-validator.php';
|
||||
|
||||
if (!isset($_SESSION["user"])) {
|
||||
header("Location: index.php?pfad=login");
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
$_SESSION["old_title"] = $_POST["title"] ?? '';
|
||||
$_SESSION["old_content"] = $_POST["content"] ?? '';
|
||||
@@ -22,6 +27,20 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||
exit();
|
||||
}
|
||||
|
||||
try {
|
||||
$articleManager = ArticleManager::getInstance();
|
||||
$article = $articleManager->getArticle($id);
|
||||
if ($article->getAuthor() != $_SESSION["user"]->getUsername()) {
|
||||
$_SESSION["message"] = "unauthorized_access";
|
||||
header("location: ../../index.php");
|
||||
exit();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$_SESSION["message"] = $e->getMessage();
|
||||
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!isset($_POST["title"]) ||!isset($_POST["content"]) || !isset($_POST["category"])){
|
||||
$_SESSION["message"] = "missing_parameters";
|
||||
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Repräsentiert einen Kommentar unter einem Beitrag.
|
||||
*
|
||||
* Ein Kommentar kann entweder ein Hauptkommentar sein
|
||||
* oder eine Antwort auf einen anderen Kommentar.
|
||||
*
|
||||
* @author Caroline Schulte
|
||||
*/
|
||||
class Comment
|
||||
{
|
||||
private int $id;
|
||||
private int $articleId;
|
||||
private ?int $parentCommentId;
|
||||
private string $author;
|
||||
private string $content;
|
||||
private string $created;
|
||||
|
||||
/**
|
||||
* Erstellt einen neuen Kommentar.
|
||||
*
|
||||
* @param int $id Eindeutige ID des Kommentars
|
||||
* @param int $articleId ID des zugehörigen Beitrags
|
||||
* @param int|null $parentCommentId ID des Eltern-Kommentars oder null
|
||||
* @param string $author Autor des Kommentars
|
||||
* @param string $content Inhalt des Kommentars
|
||||
* @param string $created Erstellungsdatum des Kommentars
|
||||
*/
|
||||
public function __construct(
|
||||
int $id,
|
||||
int $articleId,
|
||||
?int $parentCommentId,
|
||||
string $author,
|
||||
string $content,
|
||||
string $created
|
||||
) {
|
||||
$this->id = $id;
|
||||
$this->articleId = $articleId;
|
||||
$this->parentCommentId = $parentCommentId;
|
||||
$this->author = $author;
|
||||
$this->content = $content;
|
||||
$this->created = $created;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die ID des Kommentars zurück.
|
||||
*
|
||||
* @return int Kommentar-ID
|
||||
*/
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die ID des zugehörigen Beitrags zurück.
|
||||
*
|
||||
* @return int Beitrags-ID
|
||||
*/
|
||||
public function getArticleId(): int
|
||||
{
|
||||
return $this->articleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die ID des Eltern-Kommentars zurück.
|
||||
*
|
||||
* @return int|null ID des Eltern-Kommentars oder null
|
||||
*/
|
||||
public function getParentCommentId(): ?int
|
||||
{
|
||||
return $this->parentCommentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt zurück, ob der Kommentar eine Antwort ist.
|
||||
*
|
||||
* @return bool true wenn der Kommentar eine Antwort ist, sonst false
|
||||
*/
|
||||
public function isReply(): bool
|
||||
{
|
||||
return $this->parentCommentId !== null && $this->parentCommentId !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Autor des Kommentars zurück.
|
||||
*
|
||||
* @return string Autor
|
||||
*/
|
||||
public function getAuthor(): string
|
||||
{
|
||||
return $this->author;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den Inhalt des Kommentars zurück.
|
||||
*
|
||||
* @return string Kommentarinhalt
|
||||
*/
|
||||
public function getContent(): string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt das Erstellungsdatum des Kommentars zurück.
|
||||
*
|
||||
* @return string Erstellungsdatum
|
||||
*/
|
||||
public function getCreated(): string
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
require_once "DatabaseCommentManager.php";
|
||||
|
||||
/**
|
||||
* Zentrale Zugriffsschicht für Kommentare.
|
||||
*
|
||||
* Die Anwendung arbeitet ausschließlich
|
||||
* mit dem CommentManager und kennt die
|
||||
* konkrete Speicherimplementierung nicht.
|
||||
*
|
||||
* @author Caroline Schulte
|
||||
*/
|
||||
class CommentManager
|
||||
{
|
||||
/**
|
||||
* Gibt die aktive Kommentarverwaltung zurück.
|
||||
*
|
||||
* @return CommentManagerDAO
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
return DatabaseCommentManager::getInstance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
require_once "Comment.php";
|
||||
|
||||
/**
|
||||
* Schnittstelle für die Verwaltung von Kommentaren.
|
||||
*
|
||||
* Definiert die grundlegenden Methoden zum
|
||||
* Speichern und Laden von Kommentaren.
|
||||
*
|
||||
* @author Caroline Schulte
|
||||
*/
|
||||
interface CommentManagerDAO
|
||||
{
|
||||
/**
|
||||
* Speichert einen neuen Kommentar zu einem Beitrag.
|
||||
*
|
||||
* Optional kann eine parentCommentId übergeben werden,
|
||||
* wenn der Kommentar eine Antwort auf einen anderen Kommentar ist.
|
||||
*
|
||||
* @param int $articleId ID des Beitrags
|
||||
* @param string $author Autor des Kommentars
|
||||
* @param string $content Inhalt des Kommentars
|
||||
* @param int|null $parentCommentId ID des Eltern-Kommentars oder null
|
||||
*
|
||||
* @return int ID des neu gespeicherten Kommentars
|
||||
*/
|
||||
public function addComment(
|
||||
$articleId,
|
||||
$author,
|
||||
$content,
|
||||
$parentCommentId = null
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Kommentare eines Beitrags zurück.
|
||||
*
|
||||
* @param int $articleId ID des Beitrags
|
||||
*
|
||||
* @return Comment[] Liste der Kommentare
|
||||
*/
|
||||
public function getCommentsByArticle(
|
||||
$articleId
|
||||
);
|
||||
|
||||
/**
|
||||
* Gibt alle Kommentare eines Autors zurück.
|
||||
*
|
||||
* @param string $author E-Mail-Adresse des Autors
|
||||
*
|
||||
* @return Comment[] Liste der Kommentare
|
||||
*/
|
||||
public function getCommentsByAuthor($author);
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
require_once "CommentManagerDAO.php";
|
||||
require_once "Comment.php";
|
||||
|
||||
/**
|
||||
* Verwaltet die Speicherung und das Laden von Kommentaren
|
||||
* über eine SQLite-Datenbank.
|
||||
*
|
||||
* @author Caroline Schulte
|
||||
*/
|
||||
class DatabaseCommentManager implements CommentManagerDAO
|
||||
{
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Erstellt die Kommentartabelle, falls diese noch nicht existiert.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
try {
|
||||
$db = $this->getConnection();
|
||||
|
||||
$db->exec("
|
||||
CREATE TABLE IF NOT EXISTS comments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
article_id INTEGER NOT NULL,
|
||||
parent_comment_id INTEGER NULL,
|
||||
author TEXT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
");
|
||||
|
||||
$columns = $db->query("PRAGMA table_info(comments);")->fetchAll(PDO::FETCH_ASSOC);
|
||||
$hasParentColumn = false;
|
||||
|
||||
foreach ($columns as $column) {
|
||||
if ($column["name"] === "parent_comment_id") {
|
||||
$hasParentColumn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$hasParentColumn) {
|
||||
$db->exec("ALTER TABLE comments ADD COLUMN parent_comment_id INTEGER NULL;");
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException("internal_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Baut die Verbindung zur SQLite-Datenbank auf.
|
||||
*
|
||||
* @return PDO Datenbankverbindung
|
||||
*/
|
||||
private function getConnection()
|
||||
{
|
||||
try {
|
||||
$dsn = 'sqlite:' . __DIR__ . '/../../db/comments.db';
|
||||
|
||||
$db = new PDO($dsn, null, null);
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
return $db;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException("internal_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Singleton-Instanz zurück.
|
||||
*
|
||||
* @return DatabaseCommentManager
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new DatabaseCommentManager();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert einen neuen Kommentar oder eine Antwort.
|
||||
*
|
||||
* @param int $articleId ID des Beitrags
|
||||
* @param string $author Autor des Kommentars
|
||||
* @param string $content Inhalt des Kommentars
|
||||
* @param int|null $parentCommentId ID des Eltern-Kommentars oder null
|
||||
*
|
||||
* @return int ID des neu gespeicherten Kommentars
|
||||
*/
|
||||
public function addComment(
|
||||
$articleId,
|
||||
$author,
|
||||
$content,
|
||||
$parentCommentId = null
|
||||
) {
|
||||
try {
|
||||
$db = $this->getConnection();
|
||||
|
||||
if ($parentCommentId === "" || $parentCommentId === 0 || $parentCommentId === "0") {
|
||||
$parentCommentId = null;
|
||||
}
|
||||
|
||||
$sql = "
|
||||
INSERT INTO comments (
|
||||
article_id,
|
||||
parent_comment_id,
|
||||
author,
|
||||
content
|
||||
)
|
||||
VALUES (
|
||||
:articleId,
|
||||
:parentCommentId,
|
||||
:author,
|
||||
:content
|
||||
)
|
||||
";
|
||||
|
||||
$command = $db->prepare($sql);
|
||||
|
||||
$command->execute([
|
||||
":articleId" => $articleId,
|
||||
":parentCommentId" => $parentCommentId,
|
||||
":author" => $author,
|
||||
":content" => $content
|
||||
]);
|
||||
|
||||
return intval($db->lastInsertId());
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException("internal_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Kommentare eines Beitrags.
|
||||
*
|
||||
* @param int $articleId ID des Beitrags
|
||||
*
|
||||
* @return Comment[]
|
||||
*/
|
||||
public function getCommentsByArticle($articleId)
|
||||
{
|
||||
try {
|
||||
$db = $this->getConnection();
|
||||
|
||||
$sql = "
|
||||
SELECT
|
||||
id,
|
||||
article_id,
|
||||
CASE
|
||||
WHEN parent_comment_id IS NULL THEN NULL
|
||||
WHEN parent_comment_id = '' THEN NULL
|
||||
WHEN parent_comment_id = 0 THEN NULL
|
||||
ELSE parent_comment_id
|
||||
END AS parent_comment_id,
|
||||
author,
|
||||
content,
|
||||
created
|
||||
FROM comments
|
||||
WHERE article_id = :articleId
|
||||
ORDER BY created ASC
|
||||
";
|
||||
|
||||
$command = $db->prepare($sql);
|
||||
$command->execute([":articleId" => $articleId]);
|
||||
|
||||
return $this->mapRowsToComments($command);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException("internal_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt alle Kommentare eines Autors.
|
||||
*
|
||||
* @param string $author E-Mail-Adresse des Autors
|
||||
*
|
||||
* @return Comment[]
|
||||
*/
|
||||
public function getCommentsByAuthor($author)
|
||||
{
|
||||
try {
|
||||
$db = $this->getConnection();
|
||||
|
||||
$sql = "
|
||||
SELECT
|
||||
id,
|
||||
article_id,
|
||||
CASE
|
||||
WHEN parent_comment_id IS NULL THEN NULL
|
||||
WHEN parent_comment_id = '' THEN NULL
|
||||
WHEN parent_comment_id = 0 THEN NULL
|
||||
ELSE parent_comment_id
|
||||
END AS parent_comment_id,
|
||||
author,
|
||||
content,
|
||||
created
|
||||
FROM comments
|
||||
WHERE author = :author
|
||||
ORDER BY created DESC
|
||||
";
|
||||
|
||||
$command = $db->prepare($sql);
|
||||
$command->execute([":author" => $author]);
|
||||
|
||||
return $this->mapRowsToComments($command);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
throw new RuntimeException("internal_error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wandelt Datenbankzeilen in Comment-Objekte um.
|
||||
*
|
||||
* @param PDOStatement $command Ausgeführtes Statement
|
||||
*
|
||||
* @return Comment[]
|
||||
*/
|
||||
private function mapRowsToComments($command)
|
||||
{
|
||||
$comments = [];
|
||||
|
||||
while ($row = $command->fetch(PDO::FETCH_ASSOC)) {
|
||||
$parentCommentId = null;
|
||||
|
||||
if (
|
||||
isset($row["parent_comment_id"])
|
||||
&& $row["parent_comment_id"] !== null
|
||||
&& $row["parent_comment_id"] !== ""
|
||||
&& intval($row["parent_comment_id"]) !== 0
|
||||
) {
|
||||
$parentCommentId = intval($row["parent_comment_id"]);
|
||||
}
|
||||
|
||||
$comments[] = new Comment(
|
||||
intval($row["id"]),
|
||||
intval($row["article_id"]),
|
||||
$parentCommentId,
|
||||
$row["author"],
|
||||
$row["content"],
|
||||
$row["created"]
|
||||
);
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user