diff --git a/db/migrations/2019_10_15_000000_create_news_table.php b/db/migrations/2019_10_15_000000_create_news_table.php index c87972ef..540348cd 100644 --- a/db/migrations/2019_10_15_000000_create_news_table.php +++ b/db/migrations/2019_10_15_000000_create_news_table.php @@ -128,7 +128,7 @@ class CreateNewsTable extends Migration private function copyNewToPreviousNewsTable(): void { $connection = $this->schema->getConnection(); - /** @var Collection[]|stdClass[] $newsRecords */ + /** @var Collection|stdClass[] $newsRecords */ $newsRecords = $connection ->table('new_news') ->get(); diff --git a/db/migrations/2019_11_12_000000_create_news_comments_table.php b/db/migrations/2019_11_12_000000_create_news_comments_table.php new file mode 100644 index 00000000..00cf99b2 --- /dev/null +++ b/db/migrations/2019_11_12_000000_create_news_comments_table.php @@ -0,0 +1,130 @@ +createNewNewsCommentsTable(); + + if ($this->schema->hasTable('NewsComments')) { + $this->copyPreviousToNewNewsCommentsTable(); + $this->changeReferences( + 'NewsComments', + 'ID', + 'news_comments', + 'id', + 'unsignedInteger' + ); + $this->schema->drop('NewsComments'); + } + } + + /** + * Recreates the previous NewsComments table, copies back the data and drops the new news_comments table. + */ + public function down(): void + { + $this->createPreviousNewsCommentsTable(); + $this->copyNewToPreviousNewsCommentsTable(); + $this->changeReferences( + 'news_comments', + 'id', + 'NewsComments', + 'ID', + 'unsignedInteger' + ); + + $this->schema->drop('news_comments'); + } + + /** + * @return void + */ + private function createNewNewsCommentsTable(): void + { + $this->schema->create('news_comments', function (Blueprint $table) { + $table->increments('id'); + $this->references($table, 'news', 'news_id'); + $table->text('text'); + $this->referencesUser($table, false); + $table->timestamps(); + }); + } + + /** + * @return void + */ + private function copyPreviousToNewNewsCommentsTable(): void + { + $connection = $this->schema->getConnection(); + /** @var stdClass[] $previousNewsCommentsRecords */ + $previousNewsCommentsRecords = $connection + ->table('NewsComments') + ->get(); + + foreach ($previousNewsCommentsRecords as $previousNewsComment) { + $connection->table('news_comments')->insert([ + 'id' => $previousNewsComment->ID, + 'news_id' => $previousNewsComment->Refid, + 'text' => $previousNewsComment->Text, + 'user_id' => $previousNewsComment->UID, + 'created_at' => $previousNewsComment->Datum, + 'updated_at' => $previousNewsComment->Datum, + ]); + } + } + + /** + * @return void + */ + private function createPreviousNewsCommentsTable(): void + { + $this->schema->create('NewsComments', function (Blueprint $table) { + $table->increments('ID'); + $this->references($table, 'news', 'Refid'); + $table->dateTime('Datum'); + $table->text('Text'); + $this->references($table, 'users', 'UID'); + }); + } + + /** + * @return void + */ + private function copyNewToPreviousNewsCommentsTable(): void + { + $connection = $this->schema->getConnection(); + /** @var Collection|stdClass[] $newsCommentsRecords */ + $newsCommentsRecords = $connection + ->table('news_comments') + ->get(); + + foreach ($newsCommentsRecords as $newsCommentRecord) { + $connection->table('NewsComments')->insert([ + 'ID' => $newsCommentRecord->id, + 'Datum' => $newsCommentRecord->created_at, + 'Refid' => $newsCommentRecord->news_id, + 'Text' => $newsCommentRecord->text, + 'UID' => $newsCommentRecord->user_id, + ]); + } + } +} diff --git a/includes/pages/user_news.php b/includes/pages/user_news.php index 643d9d04..8ce3dffb 100644 --- a/includes/pages/user_news.php +++ b/includes/pages/user_news.php @@ -1,8 +1,6 @@ ' . __('Comments') . ' » ' . '' - . count(DB::select('SELECT `ID` FROM `NewsComments` WHERE `Refid`=?', [$news->id])) + . $news->comments()->count() . ''; } $html .= ''; @@ -141,17 +139,10 @@ function user_news_comments() ) { if ($request->hasPostData('submit') && $request->has('text')) { $text = $request->input('text'); - DB::insert(' - INSERT INTO `NewsComments` (`Refid`, `Datum`, `Text`, `UID`) - VALUES (?, ?, ?, ?) - ', - [ - $nid, - date('Y-m-d H:i:s'), - $text, - $user->id, - ] - ); + $news->comments()->create([ + 'text' => $text, + 'user_id' => $user->id, + ]); engelsystem_log('Created news_comment: ' . $text); $html .= success(__('Entry saved.'), true); @@ -159,18 +150,12 @@ function user_news_comments() $html .= display_news($news); - $comments = DB::select( - 'SELECT * FROM `NewsComments` WHERE `Refid`=? ORDER BY \'ID\'', - [$nid] - ); - foreach ($comments as $comment) { - $user_source = User::find($comment['UID']); - + foreach ($news->comments as $comment) { $html .= '
'; - $html .= '
' . nl2br(htmlspecialchars($comment['Text'])) . '
'; + $html .= '
' . nl2br(htmlspecialchars($comment->text)) . '
'; $html .= ''; $html .= '
'; } diff --git a/src/Models/News.php b/src/Models/News.php index 55ab9c1d..febaae3a 100644 --- a/src/Models/News.php +++ b/src/Models/News.php @@ -6,15 +6,19 @@ namespace Engelsystem\Models; use Carbon\Carbon; use Engelsystem\Models\User\UsesUserModel; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Query\Builder as QueryBuilder; /** - * @property int $id - * @property string $title - * @property string $text - * @property bool $is_meeting - * @property Carbon|null $created_at - * @property Carbon|null $updated_at + * @property int $id + * @property string $title + * @property string $text + * @property bool $is_meeting + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * + * @property-read Collection|NewsComment[] $comments * * @method static QueryBuilder|LogEntry[] whereId($value) * @method static QueryBuilder|LogEntry[] whereTitle($value) @@ -42,4 +46,13 @@ class News extends BaseModel 'is_meeting', 'user_id', ]; + + /** + * @return HasMany + */ + public function comments(): HasMany + { + return $this->hasMany(NewsComment::class) + ->orderBy('created_at'); + } } diff --git a/src/Models/NewsComment.php b/src/Models/NewsComment.php new file mode 100644 index 00000000..c2697350 --- /dev/null +++ b/src/Models/NewsComment.php @@ -0,0 +1,48 @@ +belongsTo(News::class); + } +} diff --git a/src/Models/User/User.php b/src/Models/User/User.php index 058f9a8c..6db4de7e 100644 --- a/src/Models/User/User.php +++ b/src/Models/User/User.php @@ -5,6 +5,8 @@ namespace Engelsystem\Models\User; use Carbon\Carbon; use Engelsystem\Models\BaseModel; use Engelsystem\Models\News; +use Engelsystem\Models\NewsComment; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Query\Builder as QueryBuilder; @@ -23,6 +25,7 @@ use Illuminate\Database\Query\Builder as QueryBuilder; * @property-read QueryBuilder|PersonalData $personalData * @property-read QueryBuilder|Settings $settings * @property-read QueryBuilder|State $state + * @property-read Collection|NewsComment[] $newsComments * * @method static QueryBuilder|User whereId($value) * @method static QueryBuilder|User[] whereName($value) @@ -105,4 +108,12 @@ class User extends BaseModel { return $this->hasMany(News::class); } + + /** + * @return HasMany + */ + public function newsComments(): HasMany + { + return $this->hasMany(NewsComment::class); + } } diff --git a/tests/Unit/Models/NewsCommentsTest.php b/tests/Unit/Models/NewsCommentsTest.php new file mode 100644 index 00000000..dfded712 --- /dev/null +++ b/tests/Unit/Models/NewsCommentsTest.php @@ -0,0 +1,126 @@ +initDatabase(); + + $this->user = User::create([ + 'name' => 'lorem', + 'password' => '', + 'email' => 'lorem@example.com', + 'api_key' => '', + ]); + + $this->news = News::create([ + 'title' => 'test title', + 'text' => 'test text', + 'user_id' => $this->user->id, + ]); + + $this->newsCommentData = [ + 'news_id' => $this->news->id, + 'text' => 'test comment', + 'user_id' => $this->user->id, + ]; + } + + /** + * Tests that a NewsComment can be created and loaded. + * + * @return void + */ + public function testCreate(): void + { + $createdNewsComment = NewsComment::create($this->newsCommentData); + + $newsComment = NewsComment::find($createdNewsComment->id); + $this->assertInstanceOf(NewsComment::class, $newsComment); + $this->assertEquals($this->newsCommentData['news_id'], $newsComment->news_id); + $this->assertSame($this->newsCommentData['text'], $newsComment->text); + $this->assertEquals($this->newsCommentData['user_id'], $newsComment->user_id); + } + + /** + * Tests that accessing the User of a NewsComment works. + * + * @return void + */ + public function testUser(): void + { + $newsComment = NewsComment::create($this->newsCommentData); + $this->assertInstanceOf(User::class, $newsComment->user); + $this->assertSame($this->user->id, $newsComment->user->id); + } + + /** + * Tests that accessing the News of a NewsComment works. + * + * @return void + */ + public function testNews(): void + { + $newsComment = NewsComment::create($this->newsCommentData); + $this->assertInstanceOf(News::class, $newsComment->news); + $this->assertSame($this->news->id, $newsComment->news->id); + } + + /** + * Tests that accessing the NewsComments of a News works. + * + * @return void + */ + public function testNewsComments(): void + { + $newsComment = NewsComment::create($this->newsCommentData); + $comments = $this->news->comments; + $this->assertCount(1, $comments); + $comment = $comments->first(); + $this->assertSame($newsComment->id, $comment->id); + } + + /** + * Tests that accessing the NewsComments of an User works. + * + * @return void + */ + public function testUserNewsComments(): void + { + $newsComment = NewsComment::create($this->newsCommentData); + $comments = $this->user->newsComments; + $this->assertCount(1, $comments); + $comment = $comments->first(); + $this->assertSame($newsComment->id, $comment->id); + } +}