diff options
author | Michael Weimann <mail@michael-weimann.eu> | 2019-12-12 21:30:28 +0100 |
---|---|---|
committer | Igor Scheller <igor.scheller@igorshp.de> | 2019-12-30 01:53:20 +0100 |
commit | 95adeca0ae1cd6c5475242d036ee75584aedd2a1 (patch) | |
tree | 593dbc9888cf447429f3c8f954b52b60095d2ca0 | |
parent | 46f80fbed262a30ba31e1d031e2512f278352e12 (diff) |
Add message model
-rw-r--r-- | db/migrations/2019_11_25_000000_create_messages_table.php | 160 | ||||
-rw-r--r-- | src/Models/Message.php | 68 | ||||
-rw-r--r-- | src/Models/User/User.php | 38 | ||||
-rw-r--r-- | tests/Unit/Models/MessageTest.php | 171 |
4 files changed, 437 insertions, 0 deletions
diff --git a/db/migrations/2019_11_25_000000_create_messages_table.php b/db/migrations/2019_11_25_000000_create_messages_table.php new file mode 100644 index 00000000..b34a6c19 --- /dev/null +++ b/db/migrations/2019_11_25_000000_create_messages_table.php @@ -0,0 +1,160 @@ +<?php + +declare(strict_types=1); + +namespace Engelsystem\Migrations; + +use Carbon\Carbon; +use Engelsystem\Database\Migration\Migration; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Schema\Blueprint; +use stdClass; + +/** + * This migration creates the "messages" table and copies the existing "Messages" table records to the new one. + */ +class CreateMessagesTable extends Migration +{ + use ChangesReferences; + use Reference; + + /** + * Creates the "messages" table, copies the data and drops the "Message" table. + */ + public function up(): void + { + $hasPreviousMessagesTable = $this->schema->hasTable('Messages'); + + if ($hasPreviousMessagesTable) { + // Rename because some SQL DBMS handle identifiers case insensitive + $this->schema->rename('Messages', 'PreviousMessages'); + } + + $this->createNewMessagesTable(); + + if ($hasPreviousMessagesTable) { + $this->copyPreviousToNewMessagesTable(); + $this->changeReferences( + 'PreviousMessages', + 'ID', + 'messages', + 'id', + 'unsignedInteger' + ); + $this->schema->drop('PreviousMessages'); + } + } + + /** + * Recreates the previous "Messages" table, copies back the data and drops the new "messages" table. + */ + public function down(): void + { + // Rename as some SQL DBMS handle identifiers case insensitive + $this->schema->rename('messages', 'new_messages'); + + $this->createPreviousMessagesTable(); + $this->copyNewToPreviousMessagesTable(); + $this->changeReferences( + 'new_messages', + 'id', + 'Messages', + 'ID', + 'unsignedInteger' + ); + + $this->schema->drop('new_messages'); + } + + /** + * @return void + */ + private function createNewMessagesTable(): void + { + $this->schema->create( + 'messages', + function (Blueprint $table) { + $table->increments('id'); + $this->references($table, 'users', 'user_id'); + $this->references($table, 'users', 'receiver_id'); + $table->boolean('read')->default(0); + $table->text('text'); + $table->timestamps(); + } + ); + } + + /** + * @return void + */ + private function copyPreviousToNewMessagesTable(): void + { + $connection = $this->schema->getConnection(); + /** @var stdClass[] $previousMessageRecords */ + $previousMessageRecords = $connection + ->table('PreviousMessages') + ->get(); + + foreach ($previousMessageRecords as $previousMessage) { + $date = Carbon::createFromTimestamp($previousMessage->Datum); + $connection->table('messages')->insert( + [ + 'id' => $previousMessage->id, + 'user_id' => $previousMessage->SUID, + 'receiver_id' => $previousMessage->RUID, + 'read' => $previousMessage->isRead === 'N' ? 0 : 1, + 'text' => $previousMessage->Text, + 'created_at' => $date, + 'updated_at' => $date, + ] + ); + } + } + + /** + * @return void + */ + private function createPreviousMessagesTable(): void + { + $this->schema->create( + 'Messages', + function (Blueprint $table) { + $table->increments('id'); + $table->integer('Datum'); + $this->references($table, 'users', 'SUID'); + $this->references($table, 'users', 'RUID'); + $table->char('isRead') + ->default('N'); + $table->text('Text'); + } + ); + } + + /** + * @return void + */ + private function copyNewToPreviousMessagesTable(): void + { + $connection = $this->schema->getConnection(); + /** @var Collection|stdClass[] $messageRecords */ + $messageRecords = $connection + ->table('new_messages') + ->get(); + + foreach ($messageRecords as $messageRecord) { + $date = Carbon::createFromFormat('Y-m-d H:i:s', $messageRecord->created_at) + ->getTimestamp(); + + $connection->table('Messages')->insert( + [ + 'id' => $messageRecord->id, + 'Datum' => $date, + 'SUID' => $messageRecord->user_id, + 'RUID' => $messageRecord->receiver_id, + 'isRead' => $messageRecord->read === 0 ? 'N' : 'Y', + 'Text' => $messageRecord->text, + ] + ); + } + } +} diff --git a/src/Models/Message.php b/src/Models/Message.php new file mode 100644 index 00000000..cb658fc6 --- /dev/null +++ b/src/Models/Message.php @@ -0,0 +1,68 @@ +<?php + +declare(strict_types=1); + +namespace Engelsystem\Models; + +use Engelsystem\Models\User\User; +use Engelsystem\Models\User\UsesUserModel; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Support\Carbon; + +/** + * This class represents a message send trough the system. + * + * @property integer $id + * @property integer $receiver_id + * @property boolean $read + * @property string $text + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property-read User $receiver + * @method static Builder|Message newModelQuery() + * @method static Builder|Message newQuery() + * @method static Builder|Message query() + * @method static Builder|Message whereCreatedAt($value) + * @method static Builder|Message whereId($value) + * @method static Builder|Message whereRead($value) + * @method static Builder|Message whereReceiverId($value) + * @method static Builder|Message whereSenderId($value) + * @method static Builder|Message whereText($value) + * @method static Builder|Message whereUpdatedAt($value) + */ +class Message extends BaseModel +{ + use UsesUserModel; + + /** @var bool enable timestamps */ + public $timestamps = true; + + /** @var string[] */ + protected $casts = [ + 'user_id' => 'integer', + 'receiver_id' => 'integer', + 'read' => 'boolean', + ]; + + /** @var string[] */ + protected $fillable = [ + 'user_id', + 'receiver_id', + 'read', + 'text', + ]; + + /** @var array */ + protected $attributes = [ + 'read' => false, + ]; + + /** + * @return BelongsTo + */ + public function receiver(): BelongsTo + { + return $this->belongsTo(User::class, 'receiver_id'); + } +} diff --git a/src/Models/User/User.php b/src/Models/User/User.php index e2ee9b21..c4bc1fcb 100644 --- a/src/Models/User/User.php +++ b/src/Models/User/User.php @@ -4,6 +4,7 @@ namespace Engelsystem\Models\User; use Carbon\Carbon; use Engelsystem\Models\BaseModel; +use Engelsystem\Models\Message; use Engelsystem\Models\News; use Engelsystem\Models\NewsComment; use Engelsystem\Models\Question; @@ -42,6 +43,9 @@ use Illuminate\Database\Query\Builder as QueryBuilder; * * @property-read Collection|Question[] $questionsAsked * @property-read Collection|Question[] $questionsAnswered + * @property-read Collection|Message[] $messagesReceived + * @property-read Collection|Message[] $messagesSent + * @property-read Collection|Message[] $messages */ class User extends BaseModel { @@ -141,4 +145,38 @@ class User extends BaseModel return $this->hasMany(Question::class, 'answerer_id') ->where('answerer_id', $this->id); } + + /** + * @return HasMany + */ + public function messagesSent(): HasMany + { + return $this->hasMany(Message::class, 'user_id') + ->orderBy('created_at', 'DESC') + ->orderBy('id', 'DESC'); + } + + /** + * @return HasMany + */ + public function messagesReceived(): HasMany + { + return $this->hasMany(Message::class, 'receiver_id') + ->orderBy('read') + ->orderBy('created_at', 'DESC') + ->orderBy('id', 'DESC'); + } + + /** + * Returns a HasMany relation for all messages sent or received by the user. + * + * @return HasMany + */ + public function messages(): HasMany + { + return $this->messagesSent() + ->union($this->messagesReceived()) + ->orderBy('read') + ->orderBy('id', 'DESC'); + } } diff --git a/tests/Unit/Models/MessageTest.php b/tests/Unit/Models/MessageTest.php new file mode 100644 index 00000000..11af9a83 --- /dev/null +++ b/tests/Unit/Models/MessageTest.php @@ -0,0 +1,171 @@ +<?php + +declare(strict_types=1); + +namespace Engelsystem\Test\Unit\Models; + +use Engelsystem\Models\Message; +use Engelsystem\Models\User\User; +use Engelsystem\Test\Unit\HasDatabase; +use Engelsystem\Test\Unit\TestCase; + +/** + * This class provides tests covering the Message model and its relations. + */ +class MessageTest extends TestCase +{ + use HasDatabase; + + /** @var User */ + private $user1; + + /** @var User */ + private $user2; + + /** @var Message */ + private $message1; + + /** @var Message */ + private $message2; + + /** @var Message */ + private $message3; + + /** + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + $this->initDatabase(); + + $this->user1 = User::create([ + 'name' => 'user1', + 'password' => '', + 'email' => 'user1@example.com', + 'api_key' => '', + ]); + + $this->user2 = User::create([ + 'name' => 'user2', + 'password' => '', + 'email' => 'user2@example.com', + 'api_key' => '', + ]); + + $this->message1 = Message::create([ + 'user_id' => $this->user1->id, + 'receiver_id' => $this->user2->id, + 'text' => 'message1', + ]); + + $this->message2 = Message::create([ + 'user_id' => $this->user1->id, + 'receiver_id' => $this->user2->id, + 'read' => true, + 'text' => 'message2', + ]); + + $this->message3 = Message::create([ + 'user_id' => $this->user2->id, + 'receiver_id' => $this->user1->id, + 'text' => 'message3', + ]); + } + + /** + * Tests that loading Messages works. + * + * @return void + */ + public function testLoad(): void + { + $message1 = Message::find($this->message1->id); + $this->assertSame($this->message1->user_id, $message1->user_id); + $this->assertSame($this->message1->receiver_id, $message1->receiver_id); + $this->assertSame($this->message1->read, $message1->read); + $this->assertSame($this->message1->text, $message1->text); + + $message2 = Message::find($this->message2->id); + $this->assertSame($this->message2->user_id, $message2->user_id); + $this->assertSame($this->message2->receiver_id, $message2->receiver_id); + $this->assertSame($this->message2->read, $message2->read); + $this->assertSame($this->message2->text, $message2->text); + } + + /** + * Tests that the Messages have the correct senders. + * + * @return void + */ + public function testSenders(): void + { + $this->assertSame($this->user1->id, $this->message1->user->id); + $this->assertSame($this->user1->id, $this->message2->user->id); + $this->assertSame($this->user2->id, $this->message3->user->id); + } + + /** + * Tests that the Messages have the correct receivers. + * + * @return void + */ + public function testReceivers(): void + { + $this->assertSame($this->user2->id, $this->message1->receiver->id); + $this->assertSame($this->user2->id, $this->message2->receiver->id); + $this->assertSame($this->user1->id, $this->message3->receiver->id); + } + + /** + * Tests that the Users have the correct sent Messages. + * + * @return void + */ + public function testUserSentMessages(): void + { + $sentByUser1 = $this->user1->messagesSent->all(); + $this->assertCount(2, $sentByUser1); + $this->assertSame($this->message2->id, $sentByUser1[0]->id); + $this->assertSame($this->message1->id, $sentByUser1[1]->id); + + $sentByUser2 = $this->user2->messagesSent->all(); + $this->assertCount(1, $sentByUser2); + $this->assertSame($this->message3->id, $sentByUser2[0]->id); + } + + /** + * Tests that the Users have the correct received Messages. + * + * @return void + */ + public function testUserReceivedMessages(): void + { + $receivedByUser1 = $this->user1->messagesReceived->all(); + $this->assertCount(1, $receivedByUser1); + $this->assertSame($this->message3->id, $receivedByUser1[0]->id); + + $receivedByUser2 = $this->user2->messagesReceived->all(); + $this->assertCount(2, $receivedByUser2); + $this->assertSame($this->message1->id, $receivedByUser2[0]->id); + $this->assertSame($this->message2->id, $receivedByUser2[1]->id); + } + + /** + * Tests that the user have the correct Messages. + */ + public function testUserMessages(): void + { + $user1Messages = $this->user1->messages->all(); + $this->assertCount(3, $user1Messages); + $this->assertSame($this->message3->id, $user1Messages[0]->id); + $this->assertSame($this->message1->id, $user1Messages[1]->id); + $this->assertSame($this->message2->id, $user1Messages[2]->id); + + $user2Messages = $this->user2->messages->all(); + $this->assertCount(3, $user2Messages); + $this->assertSame($this->message3->id, $user2Messages[0]->id); + $this->assertSame($this->message1->id, $user2Messages[1]->id); + $this->assertSame($this->message2->id, $user2Messages[2]->id); + } +} |