Kommentare löschen
This commit is contained in:
+131
-10
@@ -153,19 +153,78 @@ if ($replyAuthor === null) {
|
|||||||
<div id="comments-list">
|
<div id="comments-list">
|
||||||
<?php if (!empty($mainComments)): ?>
|
<?php if (!empty($mainComments)): ?>
|
||||||
<?php foreach ($mainComments as $comment): ?>
|
<?php foreach ($mainComments as $comment): ?>
|
||||||
<div class="comment-item" data-comment-id="<?php echo htmlspecialchars($comment->getId()); ?>">
|
<div class="comment-item"
|
||||||
<p>
|
data-comment-id="<?php echo htmlspecialchars(
|
||||||
<strong><?php echo htmlspecialchars($comment->getAuthor()); ?></strong>
|
(string) $comment->getId()
|
||||||
<span><?php echo htmlspecialchars($comment->getCreated()); ?></span>
|
); ?>">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$isDeleted = $comment->getContent()
|
||||||
|
=== "Dieser Kommentar wurde gelöscht.";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($isDeleted): ?>
|
||||||
|
|
||||||
|
<p class="deleted-comment">
|
||||||
|
Dieser Kommentar wurde gelöscht.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><?php echo nl2br(htmlspecialchars($comment->getContent())); ?></p>
|
<?php else: ?>
|
||||||
|
|
||||||
|
<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"])
|
||||||
|
&& $_SESSION["user_email"] === $comment->getAuthor()
|
||||||
|
): ?>
|
||||||
|
|
||||||
|
<form method="post"
|
||||||
|
action="php/controller/deleteComment-controller.php"
|
||||||
|
class="delete-comment-form">
|
||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
name="comment_id"
|
||||||
|
value="<?php echo htmlspecialchars(
|
||||||
|
(string) $comment->getId()
|
||||||
|
); ?>">
|
||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
name="article_id"
|
||||||
|
value="<?php echo htmlspecialchars(
|
||||||
|
(string) $comment->getArticleId()
|
||||||
|
); ?>">
|
||||||
|
|
||||||
|
<button type="submit"
|
||||||
|
class="delete-comment-button"
|
||||||
|
onclick="return confirm('Möchtest du diesen Kommentar wirklich löschen?');">
|
||||||
|
Kommentar löschen
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php if (isset($_SESSION["user_email"])): ?>
|
<?php if (isset($_SESSION["user_email"])): ?>
|
||||||
|
|
||||||
<a href="index.php?pfad=<?php
|
<a href="index.php?pfad=<?php
|
||||||
echo urlencode($_GET["pfad"] ?? "showArticle");
|
echo urlencode($_GET["pfad"] ?? "showArticle");
|
||||||
?>&id=<?php
|
?>&id=<?php
|
||||||
echo urlencode((string) ($_GET["id"] ?? ""));
|
echo urlencode((string) $comment->getArticleId());
|
||||||
?>&reply_to=<?php
|
?>&reply_to=<?php
|
||||||
echo urlencode((string) $comment->getId());
|
echo urlencode((string) $comment->getId());
|
||||||
?>#comment-form"
|
?>#comment-form"
|
||||||
@@ -176,20 +235,82 @@ if ($replyAuthor === null) {
|
|||||||
data-author="<?php echo htmlspecialchars(
|
data-author="<?php echo htmlspecialchars(
|
||||||
$comment->getAuthor()
|
$comment->getAuthor()
|
||||||
); ?>">
|
); ?>">
|
||||||
|
|
||||||
Antworten
|
Antworten
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="comment-replies">
|
<div class="comment-replies">
|
||||||
<?php if (isset($repliesByParent[$comment->getId()])): ?>
|
<?php if (isset($repliesByParent[$comment->getId()])): ?>
|
||||||
<?php foreach ($repliesByParent[$comment->getId()] as $reply): ?>
|
<?php foreach ($repliesByParent[$comment->getId()] as $reply): ?>
|
||||||
<div class="comment-item comment-reply">
|
<div class="comment-item comment-reply">
|
||||||
<p>
|
|
||||||
<strong><?php echo htmlspecialchars($reply->getAuthor()); ?></strong>
|
<?php
|
||||||
<span><?php echo htmlspecialchars($reply->getCreated()); ?></span>
|
$isReplyDeleted = $reply->getContent()
|
||||||
|
=== "Dieser Kommentar wurde gelöscht.";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($isReplyDeleted): ?>
|
||||||
|
|
||||||
|
<p class="deleted-comment">
|
||||||
|
Dieser Kommentar wurde gelöscht.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><?php echo nl2br(htmlspecialchars($reply->getContent())); ?></p>
|
<?php else: ?>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
<?php echo htmlspecialchars($reply->getAuthor()); ?>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
<?php echo htmlspecialchars($reply->getCreated()); ?>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
echo nl2br(
|
||||||
|
htmlspecialchars($reply->getContent())
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<?php if (
|
||||||
|
isset($_SESSION["user_email"])
|
||||||
|
&& $_SESSION["user_email"] === $reply->getAuthor()
|
||||||
|
): ?>
|
||||||
|
|
||||||
|
<form method="post"
|
||||||
|
action="php/controller/deleteComment-controller.php"
|
||||||
|
class="delete-comment-form">
|
||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
name="comment_id"
|
||||||
|
value="<?php echo htmlspecialchars(
|
||||||
|
(string) $reply->getId()
|
||||||
|
); ?>">
|
||||||
|
|
||||||
|
<input type="hidden"
|
||||||
|
name="article_id"
|
||||||
|
value="<?php echo htmlspecialchars(
|
||||||
|
(string) $reply->getArticleId()
|
||||||
|
); ?>">
|
||||||
|
|
||||||
|
<button type="submit"
|
||||||
|
class="delete-comment-button"
|
||||||
|
onclick="return confirm('Möchtest du diesen Kommentar wirklich löschen?');">
|
||||||
|
Kommentar löschen
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . "/../model/CommentManager.php";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kommentare dürfen nur über ein POST-Formular gelöscht werden.
|
||||||
|
*/
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
|
||||||
|
header("Location: ../../index.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
$commentId = filter_input(
|
||||||
|
INPUT_POST,
|
||||||
|
"comment_id",
|
||||||
|
FILTER_VALIDATE_INT
|
||||||
|
);
|
||||||
|
|
||||||
|
$articleId = filter_input(
|
||||||
|
INPUT_POST,
|
||||||
|
"article_id",
|
||||||
|
FILTER_VALIDATE_INT
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nur angemeldete Nutzer dürfen Kommentare löschen.
|
||||||
|
*/
|
||||||
|
if (!isset($_SESSION["user_email"])) {
|
||||||
|
$_SESSION["comment_message"] = "Du musst angemeldet sein.";
|
||||||
|
$_SESSION["comment_message_type"] = "error";
|
||||||
|
|
||||||
|
if ($articleId !== false && $articleId !== null) {
|
||||||
|
header(
|
||||||
|
"Location: ../../index.php?pfad=showArticle&id="
|
||||||
|
. urlencode((string) $articleId)
|
||||||
|
. "#comments"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
header("Location: ../../index.php");
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Kommentar-ID und Beitrags-ID müssen gültige Zahlen sein.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
$commentId === false
|
||||||
|
|| $commentId === null
|
||||||
|
|| $articleId === false
|
||||||
|
|| $articleId === null
|
||||||
|
) {
|
||||||
|
$_SESSION["comment_message"] =
|
||||||
|
"Der Kommentar konnte nicht gelöscht werden.";
|
||||||
|
|
||||||
|
$_SESSION["comment_message_type"] = "error";
|
||||||
|
|
||||||
|
header("Location: ../../index.php");
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$commentManager = CommentManager::getInstance();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Die E-Mail-Adresse aus der Session wird mitgegeben.
|
||||||
|
* Dadurch kann der Nutzer nur eigene Kommentare löschen.
|
||||||
|
*/
|
||||||
|
$deleted = $commentManager->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();
|
||||||
@@ -51,4 +51,25 @@ interface CommentManagerDAO
|
|||||||
* @return Comment[] Liste der Kommentare
|
* @return Comment[] Liste der Kommentare
|
||||||
*/
|
*/
|
||||||
public function getCommentsByAuthor($author);
|
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;
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ class DatabaseCommentManager implements CommentManagerDAO
|
|||||||
/**
|
/**
|
||||||
* Erstellt die Kommentartabelle, falls diese noch nicht existiert.
|
* Erstellt die Kommentartabelle, falls diese noch nicht existiert.
|
||||||
*/
|
*/
|
||||||
public function __construct()
|
private function __construct()
|
||||||
{
|
{
|
||||||
$this->dbPath = __DIR__ . '/../../db/eduforgeDB.db';
|
$this->dbPath = __DIR__ . '/../../db/eduforgeDB.db';
|
||||||
DatabaseInitializer::initialize($this->dbPath);
|
DatabaseInitializer::initialize($this->dbPath);
|
||||||
@@ -223,4 +223,156 @@ class DatabaseCommentManager implements CommentManagerDAO
|
|||||||
|
|
||||||
return $comments;
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -49,11 +49,11 @@ class DatabaseInitializer {
|
|||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
article_id INTEGER NOT NULL,
|
article_id INTEGER NOT NULL,
|
||||||
parent_comment_id INTEGER NULL,
|
parent_comment_id INTEGER NULL,
|
||||||
author TEXT NOT NULL,
|
author TEXT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE,
|
FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE,
|
||||||
FOREIGN KEY (author) REFERENCES users(email) ON DELETE CASCADE,
|
FOREIGN KEY (author) REFERENCES users(email) ON DELETE SET NULL,
|
||||||
FOREIGN KEY (parent_comment_id) REFERENCES comments(id) ON DELETE CASCADE
|
FOREIGN KEY (parent_comment_id) REFERENCES comments(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
");
|
");
|
||||||
|
|||||||
Reference in New Issue
Block a user