Add message model

This commit is contained in:
Michael Weimann 2019-12-12 21:30:28 +01:00 committed by Igor Scheller
parent 46f80fbed2
commit 95adeca0ae
4 changed files with 437 additions and 0 deletions

View File

@ -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,
]
);
}
}
}

68
src/Models/Message.php Normal file
View File

@ -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');
}
}

View File

@ -4,6 +4,7 @@ namespace Engelsystem\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Engelsystem\Models\BaseModel; use Engelsystem\Models\BaseModel;
use Engelsystem\Models\Message;
use Engelsystem\Models\News; use Engelsystem\Models\News;
use Engelsystem\Models\NewsComment; use Engelsystem\Models\NewsComment;
use Engelsystem\Models\Question; use Engelsystem\Models\Question;
@ -42,6 +43,9 @@ use Illuminate\Database\Query\Builder as QueryBuilder;
* *
* @property-read Collection|Question[] $questionsAsked * @property-read Collection|Question[] $questionsAsked
* @property-read Collection|Question[] $questionsAnswered * @property-read Collection|Question[] $questionsAnswered
* @property-read Collection|Message[] $messagesReceived
* @property-read Collection|Message[] $messagesSent
* @property-read Collection|Message[] $messages
*/ */
class User extends BaseModel class User extends BaseModel
{ {
@ -141,4 +145,38 @@ class User extends BaseModel
return $this->hasMany(Question::class, 'answerer_id') return $this->hasMany(Question::class, 'answerer_id')
->where('answerer_id', $this->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');
}
} }

View File

@ -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);
}
}