Forum implementiert #34

Merged
niklas.ortmann merged 20 commits from Forum into dev 2026-06-17 10:24:25 +02:00
4 changed files with 105 additions and 213 deletions
Showing only changes of commit f4f6960b9d - Show all commits
+36 -3
View File
@@ -93,7 +93,7 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
<div class="container">
<?php include_once "includes/alertMessages.php"?>
<?php include_once "includes/alertMessages.php" ?>
<h2 class="section-title">Meine Beiträge</h2>
@@ -157,7 +157,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 +167,6 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
Löschen
</button>
</form>
</div>
<?php endforeach; ?>
@@ -180,9 +181,41 @@ $isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
</button>
<?php endif; ?>
</div>
<br>
<h2 class="section-title">Meine Kommentare</h2>
<div class="articles-list">
caroline.slt marked this conversation as resolved
Review

Würde ich in ein eigenes Div packen, nicht in das gleiche Div wie die Beiträge

Würde ich in ein eigenes Div packen, nicht in das gleiche Div wie die Beiträge
<?php if (isset($userComments) && count($userComments) > 0): ?>
<?php foreach ($userComments as $comment): ?>
<div class="article-item">
<div class="article-meta">
<span class="article-date">
<?php echo htmlspecialchars($comment->getCreated()); ?>
</span>
</div>
<p>
<?php echo nl2br(htmlspecialchars($comment->getContent())); ?>
</p>
Outdated
Review

Müssen Kommentare auch wieder gelöscht werden dürfen?
Ich weiß, dass das schwierig für den Kommentar-Baum ist...
Sonst lassen wir das erst so, wenn es zu umständlich ist.

Müssen Kommentare auch wieder gelöscht werden dürfen? Ich weiß, dass das schwierig für den Kommentar-Baum ist... Sonst lassen wir das erst so, wenn es zu umständlich ist.
Outdated
Review

Schaffe ich heute nicht mehr

Schaffe ich heute nicht mehr
<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; ?>
<?php unset($_SESSION["message"]); ?>
</div>
</div>
</div>
+4
View File
@@ -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;
@@ -76,6 +77,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";
}
+9
View File
@@ -42,4 +42,13 @@ interface CommentManagerDAO
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);
}
+56 -210
View File
@@ -1,222 +1,68 @@
<?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
* Lädt alle Kommentare eines Autors.
*
* @param string $author E-Mail-Adresse des Autors
*
* @return Comment[]
*/
public function getCommentsByAuthor($author)
{
private static $instance = null;
try {
$db = $this->getConnection();
/**
* Erstellt die Kommentartabelle,
* falls diese noch nicht existiert.
*
* Zusätzlich wird geprüft, ob die Spalte parent_comment_id existiert.
*/
public function __construct()
{
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
";
$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
);
");
$command = $db->prepare($sql);
$columns = $db->query("PRAGMA table_info(comments);")->fetchAll(PDO::FETCH_ASSOC);
$hasParentColumn = false;
$command->execute([
":author" => $author
]);
foreach ($columns as $column) {
if ($column["name"] === "parent_comment_id") {
$hasParentColumn = true;
break;
}
}
$comments = [];
if (!$hasParentColumn) {
$db->exec("ALTER TABLE comments ADD COLUMN parent_comment_id INTEGER NULL;");
}
while ($row = $command->fetch(PDO::FETCH_ASSOC)) {
$parentCommentId = null;
unset($db);
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"]);
}
caroline.slt marked this conversation as resolved Outdated
Outdated
Review

Die genaue Formulierung der Fehlernachrichten wird ja in den views übernommen. Hier könnte man Fehlerkürzel wie
RuntimeException("internal_error") verwenden. In der view wird aus der Exception dann gelesen, was in dieser Stand. Wenn dort dann internal_error stand, dann wird eine bestimmte Fehlernachricht angezeigt.

Die genaue Formulierung der Fehlernachrichten wird ja in den views übernommen. Hier könnte man Fehlerkürzel wie RuntimeException("internal_error") verwenden. In der view wird aus der Exception dann gelesen, was in dieser Stand. Wenn dort dann internal_error stand, dann wird eine bestimmte Fehlernachricht angezeigt.
} catch (PDOException $e) {
throw new RuntimeException(
"Kommentardatenbank konnte nicht erstellt werden."
);
}
}
$comments[] = new Comment(
intval($row["id"]),
intval($row["article_id"]),
$parentCommentId,
$row["author"],
$row["content"],
$row["created"]
);
}
/**
* Baut die Verbindung zur SQLite-Datenbank auf.
*
* @return PDO Datenbankverbindung
*/
private function getConnection()
{
try {
$dsn = 'sqlite:' . __DIR__ . '/../../db/comments.db';
return $comments;
$db = new PDO($dsn, null, null);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $db;
} catch (PDOException $e) {
throw new RuntimeException(
"Verbindung zur Kommentardatenbank fehlgeschlagen."
);
}
}
/**
* 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(
"Kommentar konnte nicht gespeichert werden."
);
}
}
/**
* 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
]);
$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;
} catch (PDOException $e) {
throw new RuntimeException(
"Kommentare konnten nicht geladen werden."
);
}
}
} catch (PDOException $e) {
throw new RuntimeException(
"Kommentare konnten nicht geladen werden."
);
}
}