From eb56b8d6a0710291cf55a8b031916ee2a0acb67d Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 21:45:17 +0200 Subject: [PATCH 01/20] Implementierung --- .idea/dataSources.local.xml | 2 +- content/showArticle.php | 83 +++++++++++-- php/model/Comment.php | 92 ++++++++++++++ php/model/CommentManager.php | 25 ++++ php/model/CommentManagerDAO.php | 40 +++++++ php/model/DatabaseCommentManager.php | 173 +++++++++++++++++++++++++++ 6 files changed, 401 insertions(+), 14 deletions(-) create mode 100644 php/model/Comment.php create mode 100644 php/model/CommentManager.php create mode 100644 php/model/CommentManagerDAO.php create mode 100644 php/model/DatabaseCommentManager.php diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml index cdc31de..707e2b3 100644 --- a/.idea/dataSources.local.xml +++ b/.idea/dataSources.local.xml @@ -1,6 +1,6 @@ - + " diff --git a/content/showArticle.php b/content/showArticle.php index 4457dcc..fff5b00 100644 --- a/content/showArticle.php +++ b/content/showArticle.php @@ -1,18 +1,31 @@ getCommentsByArticle($_GET["id"]); + } catch (Exception $e) { + $_SESSION["message"] = "internal_error"; + } +} ?> + -

Es ist ein interner Fehler aufgetreten. Bitte versuche es erneut.

+

Es ist ein Fehler aufgetreten. Die ID konnte nicht ausgelesen werden. Bitte versuche es erneut. @@ -24,54 +37,59 @@ include_once 'php/controller/showArticle-controller.php'; Jeder Beitrag muss einen Titel, Kategorie und Inhalt besitzen.

+

Dein Beitrag wurde erfolgreich bearbeitet!

- - + +
+

- Von: + + Von: +
-
- -
+
+ +
-
Tags:
+
- + + + -
+
+

Kommentare

+
+ + +
+

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

+ +

getContent())); ?>

+
+ + +

Noch keine Kommentare vorhanden.

+ +
+ + +
+ "> + + + + +
+ +

Du musst angemeldet sein, um einen Kommentar zu schreiben.

+ +
+ + \ No newline at end of file diff --git a/php/model/Comment.php b/php/model/Comment.php new file mode 100644 index 0000000..42405a1 --- /dev/null +++ b/php/model/Comment.php @@ -0,0 +1,92 @@ +id = $id; + $this->articleId = $articleId; + $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 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; + } +} diff --git a/php/model/CommentManager.php b/php/model/CommentManager.php new file mode 100644 index 0000000..6ca6cb4 --- /dev/null +++ b/php/model/CommentManager.php @@ -0,0 +1,25 @@ +getConnection(); + + $db->exec(" + CREATE TABLE IF NOT EXISTS comments ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + article_id INTEGER NOT NULL, + author TEXT NOT NULL, + content TEXT NOT NULL, + created TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + "); + + unset($db); + + } catch (PDOException $e) { + throw new RuntimeException( + "Kommentardatenbank konnte nicht erstellt werden." + ); + } + } + + /** + * 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( + "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 + * zu einem Beitrag. + * + * @param int $articleId ID des Beitrags + * @param string $author Autor des Kommentars + * @param string $content Inhalt des Kommentars + * + * @return void + */ + public function addComment( + $articleId, + $author, + $content + ) { + try { + $db = $this->getConnection(); + + $sql = " + INSERT INTO comments ( + article_id, + author, + content + ) + VALUES ( + :articleId, + :author, + :content + ) + "; + + $command = $db->prepare($sql); + + $command->execute([ + ":articleId" => $articleId, + ":author" => $author, + ":content" => $content + ]); + + } 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 * + FROM comments + WHERE article_id = :articleId + ORDER BY created DESC + "; + + $command = $db->prepare($sql); + + $command->execute([ + ":articleId" => $articleId + ]); + + $comments = []; + + while ($row = $command->fetch(PDO::FETCH_ASSOC)) { + + $comments[] = new Comment( + $row["id"], + $row["article_id"], + $row["author"], + $row["content"], + $row["created"] + ); + } + + return $comments; + + } catch (PDOException $e) { + throw new RuntimeException( + "Kommentare konnten nicht geladen werden." + ); + } + } +} -- 2.47.3 From e1ee70b46f60e97ad5733f02844d9ed2472c1c8b Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 21:54:06 +0200 Subject: [PATCH 02/20] ajax implementiert --- content/showArticle.php | 4 ++- index.php | 71 +++++++++++++--------------------------- js/comments.js | 55 +++++++++++++++++++++++++++++++ php/ajax/add-comment.php | 48 +++++++++++++++++++++++++++ 4 files changed, 129 insertions(+), 49 deletions(-) create mode 100644 js/comments.js create mode 100644 php/ajax/add-comment.php diff --git a/content/showArticle.php b/content/showArticle.php index fff5b00..3feb0bf 100644 --- a/content/showArticle.php +++ b/content/showArticle.php @@ -114,7 +114,9 @@ if (isset($_GET["id"])) { -

Noch keine Kommentare vorhanden.

+

+ Noch keine Kommentare vorhanden. +

diff --git a/index.php b/index.php index 1006322..5b5a7cb 100644 --- a/index.php +++ b/index.php @@ -29,55 +29,30 @@ if ($pfad === "deleteAccount") { } ?> - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - + - EduForge - - - - - - - - - - \ No newline at end of file + EduForge + \ No newline at end of file diff --git a/js/comments.js b/js/comments.js new file mode 100644 index 0000000..7ee43f7 --- /dev/null +++ b/js/comments.js @@ -0,0 +1,55 @@ +document.addEventListener("DOMContentLoaded", function () { + const form = document.getElementById("comment-form"); + const commentsList = document.getElementById("comments-list"); + const commentContent = document.getElementById("comment-content"); + + if (!form || !commentsList || !commentContent) { + return; + } + + form.addEventListener("submit", function (event) { + event.preventDefault(); + + const formData = new FormData(form); + + 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"); + + commentElement.innerHTML = ` +

+ ${escapeHtml(data.author)} + ${escapeHtml(data.created)} +

+

${escapeHtml(data.content).replace(/\n/g, "
")}

+ `; + + commentsList.prepend(commentElement); + commentContent.value = ""; + }) + .catch(() => { + alert("Kommentar konnte nicht gesendet werden."); + }); + }); + + function escapeHtml(text) { + const div = document.createElement("div"); + div.textContent = text; + return div.innerHTML; + } +}); \ No newline at end of file diff --git a/php/ajax/add-comment.php b/php/ajax/add-comment.php new file mode 100644 index 0000000..0895de3 --- /dev/null +++ b/php/ajax/add-comment.php @@ -0,0 +1,48 @@ + false, + "message" => "Du musst angemeldet sein." + ]); + exit(); +} + +$articleId = $_POST["article_id"] ?? null; +$content = trim($_POST["content"] ?? ""); + +if (empty($articleId) || empty($content)) { + echo json_encode([ + "success" => false, + "message" => "Kommentar darf nicht leer sein." + ]); + exit(); +} + +try { + $commentManager = CommentManager::getInstance(); + + $commentManager->addComment( + $articleId, + $_SESSION["user_email"], + $content + ); + + echo json_encode([ + "success" => true, + "author" => $_SESSION["user_email"], + "content" => $content, + "created" => date("Y-m-d H:i:s") + ]); + +} catch (Exception $e) { + echo json_encode([ + "success" => false, + "message" => "Kommentar konnte nicht gespeichert werden." + ]); +} -- 2.47.3 From 21c5471d73f7362982852015a0cd378e71f3f9c9 Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 22:08:46 +0200 Subject: [PATCH 03/20] fehlerkorrektur --- index.php | 71 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/index.php b/index.php index 5b5a7cb..3cd00fb 100644 --- a/index.php +++ b/index.php @@ -29,30 +29,55 @@ if ($pfad === "deleteAccount") { } ?> - - - + + + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - + - EduForge - \ No newline at end of file + EduForge + + + + + + + + + + \ No newline at end of file -- 2.47.3 From 59012cacfbbb86b62587f2c7ba0d59a280421561 Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 22:14:51 +0200 Subject: [PATCH 04/20] css design --- css/showArticle.css | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/css/showArticle.css b/css/showArticle.css index ca3b40a..cfe0aed 100644 --- a/css/showArticle.css +++ b/css/showArticle.css @@ -115,4 +115,66 @@ .article-view-title { 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; + color: #1a202c; + } + + .comment-item { + background-color: #f8fafc; + border: 1px solid #e2e8f0; + border-radius: 10px; + padding: 1rem 1.25rem; + margin-bottom: 1rem; + } + + .comment-item strong { + color: #1a202c; + } + + .comment-item span { + color: #64748b; + font-size: 0.9rem; + margin-left: 0.5rem; + } + + .comment-item p { + margin: 0.5rem 0; + } + + #comment-form { + margin-top: 2rem; + } + + #comment-content { + width: 100%; + min-height: 120px; + padding: 1rem; + border: 1px solid #cbd5e1; + border-radius: 8px; + font-size: 1rem; + font-family: inherit; + resize: vertical; + margin-bottom: 1rem; + } + + #comment-content:focus { + outline: none; + border-color: #2563eb; + } + + .no-comments-message { + color: #64748b; + font-style: italic; + } } -- 2.47.3 From f13a2c6f1e4d12cd5dc0cb8da5e1db82f01955ba Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 22:17:44 +0200 Subject: [PATCH 05/20] css design --- css/showArticle.css | 40 +++++++++++++--------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/css/showArticle.css b/css/showArticle.css index cfe0aed..1539f90 100644 --- a/css/showArticle.css +++ b/css/showArticle.css @@ -115,6 +115,7 @@ .article-view-title { font-size: 1.85rem; } +} /* --- KOMMENTARE --- */ @@ -127,7 +128,10 @@ .article-comments-section h2 { font-size: 2rem; margin-bottom: 1.5rem; - color: #1a202c; + } + + #comments-list { + margin-bottom: 2rem; } .comment-item { @@ -138,43 +142,25 @@ margin-bottom: 1rem; } - .comment-item strong { - color: #1a202c; - } - - .comment-item span { - color: #64748b; - font-size: 0.9rem; - margin-left: 0.5rem; - } - - .comment-item p { - margin: 0.5rem 0; - } - #comment-form { - margin-top: 2rem; + width: 100%; + display: flex; + flex-direction: column; + gap: 1rem; } #comment-content { - width: 100%; - min-height: 120px; + width: 100% !important; + min-height: 130px !important; padding: 1rem; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 1rem; font-family: inherit; resize: vertical; - margin-bottom: 1rem; } - #comment-content:focus { - outline: none; - border-color: #2563eb; + #comment-form .button { + width: 100%; } - .no-comments-message { - color: #64748b; - font-style: italic; - } -} -- 2.47.3 From 6f6e53a483bbee4aa8358333108844f5a45791c5 Mon Sep 17 00:00:00 2001 From: Caroline Schulte Date: Mon, 15 Jun 2026 22:32:00 +0200 Subject: [PATCH 06/20] =?UTF-8?q?Antwortm=C3=B6glichkeit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/showArticle.php | 44 +++++++++-- js/comments.js | 106 +++++++++++++++++++++++++-- php/ajax/add-comment.php | 13 +++- php/model/Comment.php | 31 +++++++- php/model/CommentManagerDAO.php | 9 ++- php/model/DatabaseCommentManager.php | 39 ++++++++-- 6 files changed, 213 insertions(+), 29 deletions(-) diff --git a/content/showArticle.php b/content/showArticle.php index 3feb0bf..dbd4082 100644 --- a/content/showArticle.php +++ b/content/showArticle.php @@ -104,14 +104,38 @@ if (isset($_GET["id"])) {
-
-

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

+ isReply()): ?> +
+

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

-

getContent())); ?>

-
+

getContent())); ?>

+ + + +
+ + getParentCommentId() === $comment->getId()): ?> +
+

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

+ +

getContent())); ?>

+
+ + +
+
+

@@ -125,6 +149,12 @@ if (isset($_GET["id"])) { "> + + +