diff --git a/php/model/Article.php b/php/model/Article.php index 4b1d492..a0e1b65 100644 --- a/php/model/Article.php +++ b/php/model/Article.php @@ -7,13 +7,14 @@ */ class Article { - public $id; - public $title; - public $content; - public $author; - public $creationDate; - public $category; - public $tags; + private $id; + private $title; + private $content; + private $author; + private $creationDate; + private $category; + private $tags; + private $likes; /** * Konstruktor @@ -26,7 +27,7 @@ class Article * @param $tags string optionale Schlagworte für eine bessere Suche * @param $creationDate string Datum der Beitragserstellung */ - public function __construct(int $id, string $title, string $content, string $author, string $category, string $tags, string $creationDate) + public function __construct(int $id, string $title, string $content, string $author, string $category, string $tags, string $creationDate, array $likes = []) { $this->id = $id; $this->title = $title; @@ -35,6 +36,7 @@ class Article $this->creationDate = $creationDate; $this->category = $category; $this->tags = $tags; + $this->likes = $likes; } /** @@ -67,7 +69,7 @@ class Article /** * Gibt den Content eines Beitrags zurück. - * TODO: Content muss noch definiert werden. + * * @return string */ public function getContent(): string @@ -77,7 +79,7 @@ class Article /** * Setzt den Content eines Beitrags. - * TODO: Content muss noch definiert werden. + * * @param $content * @return void */ @@ -141,7 +143,34 @@ class Article $this->tags = $tags; } + /** + * Gibt alle User-IDs zurück, die diesen Beitrag geliked haben. + * @return array + */ + public function getLikes(): array + { + return $this->likes; + } + /** + * Gibt die Gesamtzahl der Likes zurück. + * @return int + */ + public function getLikeCount(): int + { + return count($this->likes); + } + + /** + * Prüft, ob ein bestimmter Nutzer den Beitrag bereits geliked hat. + * + * @param string $userId + * @return bool + */ + public function hasLiked(string $userId): bool + { + return in_array($userId, $this->likes); + } } ?> \ No newline at end of file diff --git a/php/model/ArticleManagerDAO.php b/php/model/ArticleManagerDAO.php index 6dcf7e2..fea3d0c 100644 --- a/php/model/ArticleManagerDAO.php +++ b/php/model/ArticleManagerDAO.php @@ -92,6 +92,18 @@ interface ArticleManagerDAO */ public function getArticlesByCategory($category); + /** + * Registriert oder entfernt ein Like eines Nutzers für einen Beitrag. + * Wenn schon geliked -> Unlike + * Wenn noch nicht geliked -> Like + * + * @param int $articleId Die ID des Beitrags + * @param string $userId Die ID des Nutzers + * @return bool True wenn geliked, False wenn unliked + * @throws InternalServerErrorException + * @throws NotFoundException + */ + public function toggleLike(int $articleId, string $userId): bool; } ?> \ No newline at end of file diff --git a/php/model/DatabaseArticleManager.php b/php/model/DatabaseArticleManager.php index 7d9f31b..ad49ea4 100644 --- a/php/model/DatabaseArticleManager.php +++ b/php/model/DatabaseArticleManager.php @@ -23,6 +23,7 @@ class DatabaseArticleManager implements ArticleManagerDAO { $db = $this->getConnection(); + // Tabelle für Beiträge $db->exec(" CREATE TABLE articles ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -33,6 +34,15 @@ class DatabaseArticleManager implements ArticleManagerDAO { tags TEXT, created TIMESTAMP DEFAULT CURRENT_TIMESTAMP );"); + + // Tabelle für Likes + $db->exec(" + CREATE TABLE likes ( + article_id INTEGER, + user_id TEXT, + PRIMARY KEY (article_id, user_id), + FOREIGN KEY (article_id) REFERENCES articles(id) ON DELETE CASCADE + );"); unset($db); } catch (PDOException $e) { throw new InternalServerErrorException($e->getMessage()); @@ -189,6 +199,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $row = $command->fetch(PDO::FETCH_ASSOC); if ($row) { + $likes = $this->getLikesForArticle(intval($row['id'])); + return new Article( intval($row['id']), $row['title'], @@ -196,7 +208,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $row['author'], $row['category'], $row['tags'], - $row['created'] + $row['created'], + $likes ); } @@ -254,6 +267,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $filteredArticles = []; foreach ($rows as $row) { + $likes = $this->getLikesForArticle(intval($row['id'])); + $filteredArticles[] = new Article( intval($row['id']), $row['title'], @@ -261,7 +276,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $row['author'], $row['category'], $row['tags'], - $row['created'] + $row['created'], + $likes ); } @@ -287,6 +303,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $filteredArticles = []; foreach ($rows as $row) { + $likes = $this->getLikesForArticle(intval($row['id'])); + $filteredArticles[] = new Article( intval($row['id']), $row['title'], @@ -294,7 +312,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $row['author'], $row['category'], $row['tags'], - $row['created'] + $row['created'], + $likes ); } @@ -341,6 +360,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $filteredArticles = []; foreach ($rows as $row) { + $likes = $this->getLikesForArticle(intval($row['id'])); + $filteredArticles[] = new Article( intval($row['id']), $row['title'] ?? '', @@ -348,7 +369,8 @@ class DatabaseArticleManager implements ArticleManagerDAO { $row['author'] ?? '', $row['category'] ?? '', $row['tags'] ?? '', - $row['created'] ?? '' // Nutzt 'created' aus deiner DB-Struktur + $row['created'] ?? '', + $likes ); } @@ -359,4 +381,69 @@ class DatabaseArticleManager implements ArticleManagerDAO { } } + /** + * Holt alle User-IDs, die einen bestimmten Beitrag geliked haben. + * + * @return String[] UserIDs + * @throws InternalServerErrorException + */ + private function getLikesForArticle(int $articleId): array + { + try { + $db = $this->getConnection(); + $sql = "SELECT user_id FROM likes WHERE article_id = :article_id;"; + $command = $db->prepare($sql); + $command->execute([':article_id' => $articleId]); + + return $command->fetchAll(PDO::FETCH_COLUMN) ?: []; + } catch (PDOException $e) { + return []; + } + } + + public function toggleLike(int $articleId, string $userId): bool + { + // prüfen, ob der Artikel überhaupt existiert + $article = $this->getArticle($articleId); + if (!$article) { + throw new NotFoundException("missing_id"); + } + + try { + $db = $this->getConnection(); + + // prüfen, ob das Like bereits existiert + $checkSql = "SELECT COUNT(*) FROM likes WHERE article_id = :article_id AND user_id = :user_id;"; + $checkCommand = $db->prepare($checkSql); + $checkCommand->execute([ + ':article_id' => $articleId, + ':user_id' => $userId + ]); + + $hasLiked = (int)$checkCommand->fetchColumn() > 0; + + if ($hasLiked) { + // wenn bereits geliked -> Unlike + $deleteSql = "DELETE FROM likes WHERE article_id = :article_id AND user_id = :user_id;"; + $deleteCommand = $db->prepare($deleteSql); + $deleteCommand->execute([ + ':article_id' => $articleId, + ':user_id' => $userId + ]); + return false; // gibt false zurück, da der Beitrag jetzt nicht mehr geliked ist + } else { + // wenn noch nicht geliked -> Like + $insertSql = "INSERT INTO likes (article_id, user_id) VALUES (:article_id, :user_id);"; + $insertCommand = $db->prepare($insertSql); + $insertCommand->execute([ + ':article_id' => $articleId, + ':user_id' => $userId + ]); + return true; // gibt true zurück, da der Beitrag jetzt geliked ist + } + + } catch (PDOException $e) { + throw new InternalServerErrorException("internal_error"); + } + } } \ No newline at end of file