summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Weimann <mail@michael-weimann.eu>2019-12-12 21:30:28 +0100
committerIgor Scheller <igor.scheller@igorshp.de>2019-12-30 01:53:20 +0100
commit95adeca0ae1cd6c5475242d036ee75584aedd2a1 (patch)
tree593dbc9888cf447429f3c8f954b52b60095d2ca0
parent46f80fbed262a30ba31e1d031e2512f278352e12 (diff)
Add message model
-rw-r--r--db/migrations/2019_11_25_000000_create_messages_table.php160
-rw-r--r--src/Models/Message.php68
-rw-r--r--src/Models/User/User.php38
-rw-r--r--tests/Unit/Models/MessageTest.php171
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);
+ }
+}