From 7b7208ad6b393f37755488a2174b4d28d13d7896 Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Sat, 18 Jul 2026 16:44:05 +0200 Subject: [PATCH] =?UTF-8?q?Kommentare=20l=C3=B6schen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/showArticle.php | 177 ++++++++++++++++---- php/controller/deleteComment-controller.php | 105 ++++++++++++ php/model/CommentManagerDAO.php | 21 +++ php/model/DatabaseCommentManager.php | 154 ++++++++++++++++- php/model/DatabaseInitializer.php | 22 +-- 5 files changed, 439 insertions(+), 40 deletions(-) create mode 100644 php/controller/deleteComment-controller.php diff --git a/content/showArticle.php b/content/showArticle.php index 10c09f0..9ea6287 100644 --- a/content/showArticle.php +++ b/content/showArticle.php @@ -153,43 +153,164 @@ if ($replyAuthor === null) {
-
-

- getAuthor()); ?> - getCreated()); ?> -

+
-

getContent())); ?>

+ getContent() + === "Dieser Kommentar wurde gelöscht."; + ?> + + + +

+ Dieser Kommentar wurde gelöscht. +

+ + + +

+ + getAuthor()); ?> + + + + getCreated()); ?> + +

+ +

+ getContent()) + ); + ?> +

+ + getAuthor() + ): ?> + +
+ + + + + + +
+ + + + + + &id=getArticleId()); + ?>&reply_to=getId()); + ?>#comment-form" + class="reply-button" + data-comment-id="getId() + ); ?>" + data-author="getAuthor() + ); ?>"> + + Antworten + + + - - &id=&reply_to=getId()); - ?>#comment-form" - class="reply-button" - data-comment-id="getId() - ); ?>" - data-author="getAuthor() - ); ?>"> - Antworten -
getId()])): ?> getId()] as $reply): ?>
-

- getAuthor()); ?> - getCreated()); ?> -

-

getContent())); ?>

+ getContent() + === "Dieser Kommentar wurde gelöscht."; + ?> + + + +

+ Dieser Kommentar wurde gelöscht. +

+ + + +

+ + getAuthor()); ?> + + + + getCreated()); ?> + +

+ +

+ getContent()) + ); + ?> +

+ + getAuthor() + ): ?> + +
+ + + + + + +
+ + + + +
diff --git a/php/controller/deleteComment-controller.php b/php/controller/deleteComment-controller.php new file mode 100644 index 0000000..0b12158 --- /dev/null +++ b/php/controller/deleteComment-controller.php @@ -0,0 +1,105 @@ +deleteComment( + $commentId, + $_SESSION["user_email"] + ); + + if ($deleted) { + $_SESSION["comment_message"] = + "Der Kommentar wurde gelöscht."; + + $_SESSION["comment_message_type"] = "success"; + } else { + $_SESSION["comment_message"] = + "Der Kommentar wurde nicht gefunden oder gehört nicht dir."; + + $_SESSION["comment_message_type"] = "error"; + } + +} catch (Throwable $e) { + $_SESSION["comment_message"] = + "Der Kommentar konnte nicht gelöscht werden."; + + $_SESSION["comment_message_type"] = "error"; +} + +/* + * Anschließend wird wieder zum Beitrag und zu den Kommentaren geleitet. + */ +header( + "Location: ../../index.php?pfad=showArticle&id=" + . urlencode((string) $articleId) + . "#comments" +); + +exit(); diff --git a/php/model/CommentManagerDAO.php b/php/model/CommentManagerDAO.php index 348126e..1390815 100644 --- a/php/model/CommentManagerDAO.php +++ b/php/model/CommentManagerDAO.php @@ -51,4 +51,25 @@ interface CommentManagerDAO * @return Comment[] Liste der Kommentare */ public function getCommentsByAuthor($author); + /** + * Löscht einen einzelnen Kommentar des angemeldeten Nutzers. + * + * Kommentare ohne Antworten werden vollständig entfernt. + * Kommentare mit Antworten bleiben als anonymer Platzhalter erhalten. + * + * @param int $commentId ID des Kommentars + * @param string $author E-Mail-Adresse des Autors + * @return bool true, wenn der Kommentar gefunden und gelöscht wurde + */ + public function deleteComment(int $commentId, string $author): bool; + + /** + * Löscht beziehungsweise anonymisiert alle Kommentare eines Nutzers. + * + * Diese Methode wird bei der Löschung eines Benutzerkontos verwendet. + * + * @param string $author E-Mail-Adresse des Nutzers + * @return void + */ + public function deleteCommentsByAuthor(string $author): void; } \ No newline at end of file diff --git a/php/model/DatabaseCommentManager.php b/php/model/DatabaseCommentManager.php index aebe73c..31bea09 100644 --- a/php/model/DatabaseCommentManager.php +++ b/php/model/DatabaseCommentManager.php @@ -17,7 +17,7 @@ class DatabaseCommentManager implements CommentManagerDAO /** * Erstellt die Kommentartabelle, falls diese noch nicht existiert. */ - public function __construct() + private function __construct() { $this->dbPath = __DIR__ . '/../../db/eduforgeDB.db'; DatabaseInitializer::initialize($this->dbPath); @@ -223,4 +223,156 @@ class DatabaseCommentManager implements CommentManagerDAO return $comments; } + /** + * Löscht einen eigenen Kommentar. + * + * Hat der Kommentar Antworten, wird er anonymisiert. + * Hat er keine Antworten, wird er vollständig gelöscht. + * + * @param int $commentId ID des Kommentars + * @param string $author E-Mail-Adresse des Autors + * @return bool true, wenn der Kommentar gelöscht wurde + */ + public function deleteComment(int $commentId, string $author): bool + { + try { + $db = $this->getConnection(); + + /* + * Zuerst wird geprüft, ob der Kommentar existiert + * und wirklich dem angemeldeten Nutzer gehört. + */ + $checkCommand = $db->prepare(" + SELECT id + FROM comments + WHERE id = :commentId + AND author = :author + "); + + $checkCommand->execute([ + ":commentId" => $commentId, + ":author" => $author + ]); + + if ($checkCommand->fetch() === false) { + return false; + } + + /* + * Danach wird geprüft, ob Antworten auf den Kommentar existieren. + */ + $replyCommand = $db->prepare(" + SELECT COUNT(*) + FROM comments + WHERE parent_comment_id = :commentId + "); + + $replyCommand->execute([ + ":commentId" => $commentId + ]); + + $hasReplies = (int) $replyCommand->fetchColumn() > 0; + + if ($hasReplies) { + /* + * Der Kommentar wird für den Kommentarbaum benötigt. + * Deshalb bleibt er als anonymer Platzhalter erhalten. + */ + $deleteCommand = $db->prepare(" + UPDATE comments + SET author = NULL, + content = 'Dieser Kommentar wurde gelöscht.' + WHERE id = :commentId + AND author = :author + "); + } else { + /* + * Ohne Antworten kann der Kommentar vollständig + * aus der Datenbank entfernt werden. + */ + $deleteCommand = $db->prepare(" + DELETE FROM comments + WHERE id = :commentId + AND author = :author + "); + } + + $deleteCommand->execute([ + ":commentId" => $commentId, + ":author" => $author + ]); + + return $deleteCommand->rowCount() > 0; + + } catch (PDOException $e) { + throw new RuntimeException("internal_error"); + } + } + /** + * Löscht beziehungsweise anonymisiert alle Kommentare eines Nutzers. + * + * Kommentare ohne Antworten werden vollständig gelöscht. + * Kommentare mit Antworten bleiben als anonyme Platzhalter erhalten. + * + * @param string $author E-Mail-Adresse des Nutzers + * @return void + */ + public function deleteCommentsByAuthor(string $author): void + { + $db = $this->getConnection(); + + try { + $db->beginTransaction(); + + /* + * Zuerst werden alle Kommentare ohne Antworten gelöscht. + * + * Die Schleife ist wichtig, weil durch das Löschen einer Antwort + * eventuell auch der darüberliegende Kommentar keine Antworten + * mehr besitzt und anschließend ebenfalls gelöscht werden kann. + */ + do { + $deleteCommand = $db->prepare(" + DELETE FROM comments + WHERE author = :author + AND NOT EXISTS ( + SELECT 1 + FROM comments AS replies + WHERE replies.parent_comment_id = comments.id + ) + "); + + $deleteCommand->execute([ + ":author" => $author + ]); + + $deletedRows = $deleteCommand->rowCount(); + + } while ($deletedRows > 0); + + /* + * Kommentare, auf die noch Antworten anderer Nutzer folgen, + * müssen für den Kommentarbaum erhalten bleiben. + */ + $placeholderCommand = $db->prepare(" + UPDATE comments + SET author = NULL, + content = 'Dieser Kommentar wurde gelöscht.' + WHERE author = :author + "); + + $placeholderCommand->execute([ + ":author" => $author + ]); + + $db->commit(); + + } catch (PDOException $e) { + if ($db->inTransaction()) { + $db->rollBack(); + } + + throw new RuntimeException("internal_error"); + } + } } \ No newline at end of file diff --git a/php/model/DatabaseInitializer.php b/php/model/DatabaseInitializer.php index 573d43e..f928be1 100644 --- a/php/model/DatabaseInitializer.php +++ b/php/model/DatabaseInitializer.php @@ -46,17 +46,17 @@ class DatabaseInitializer { $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, - FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE, - FOREIGN KEY (author) REFERENCES users(email) ON DELETE CASCADE, - FOREIGN KEY (parent_comment_id) REFERENCES comments(id) ON DELETE CASCADE - ); - "); + id INTEGER PRIMARY KEY AUTOINCREMENT, + article_id INTEGER NOT NULL, + parent_comment_id INTEGER NULL, + author TEXT NULL, + content TEXT NOT NULL, + created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE, + FOREIGN KEY (author) REFERENCES users(email) ON DELETE SET NULL, + FOREIGN KEY (parent_comment_id) REFERENCES comments(id) ON DELETE CASCADE + ); + "); $initializer = new self(); $availableEmails = $initializer->seedDummyUsers($db);