Skip to content

Commit

Permalink
Merge branch 'master' into laravel-10
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamiras authored Dec 3, 2023
2 parents dcc8743 + 783a02f commit 35f3d6c
Show file tree
Hide file tree
Showing 82 changed files with 2,356 additions and 901 deletions.
31 changes: 31 additions & 0 deletions app/Community/Actions/AddToMessageThreadAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace App\Community\Actions;

use App\Community\Events\MessageCreated;
use App\Community\Models\Message;
use App\Community\Models\MessageThread;
use App\Site\Models\User;
use Illuminate\Support\Carbon;

class AddToMessageThreadAction
{
public function execute(MessageThread $thread, User $userFrom, string $body): void
{
$message = new Message([
'thread_id' => $thread->id,
'author_id' => $userFrom->ID,
'body' => $body,
'created_at' => Carbon::now(),
]);
$message->save();

$thread->num_messages++;
$thread->last_message_id = $message->id;
$thread->save();

MessageCreated::dispatch($message);
}
}
50 changes: 50 additions & 0 deletions app/Community/Actions/CreateMessageThreadAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace App\Community\Actions;

use App\Community\Models\MessageThread;
use App\Community\Models\MessageThreadParticipant;
use App\Site\Models\User;
use Illuminate\Support\Carbon;

class CreateMessageThreadAction
{
public function execute(User $userFrom, User $userTo, string $title, string $body, bool $isProxied = false): MessageThread
{
$thread = new MessageThread([
'title' => $title,
]);
$thread->save();

$participantFrom = new MessageThreadParticipant([
'user_id' => $userFrom->ID,
'thread_id' => $thread->id,
]);

if ($isProxied) {
$participantFrom->deleted_at = Carbon::now();
}

$participantFrom->save();

if ($userTo->ID != $userFrom->ID) {
$participantTo = new MessageThreadParticipant([
'user_id' => $userTo->ID,
'thread_id' => $thread->id,
]);

// if the recipient has blocked the sender, immediately mark the thread as deleted for the recipient
if ($userTo->isBlocking($userFrom->User)) {
$participantTo->deleted_at = Carbon::now();
}

$participantTo->save();
}

(new AddToMessageThreadAction())->execute($thread, $userFrom, $body);

return $thread;
}
}
40 changes: 40 additions & 0 deletions app/Community/Actions/DeleteMessageThreadAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace App\Community\Actions;

use App\Community\Models\MessageThread;
use App\Community\Models\MessageThreadParticipant;
use App\Site\Models\User;

class DeleteMessageThreadAction
{
public function execute(MessageThread $thread, User $user): void
{
$participant = MessageThreadParticipant::where('thread_id', $thread->id)
->where('user_id', $user->id)
->first();

if ($participant) {
// make sure num_unread is 0 before we soft-delete the record.
if ($participant->num_unread) {
$participant->num_unread = 0;
$participant->save();
}

$participant->delete();

(new UpdateUnreadMessageCountAction())->execute($user);

$hasOtherActiveParticipants = MessageThreadParticipant::where('thread_id', $thread->id)
->where('user_id', '!=', $user->id)
->whereNull('deleted_at')
->exists();
if (!$hasOtherActiveParticipants) {
// this will also cascade delete the message_participants and messages
$thread->delete();
}
}
}
}
34 changes: 34 additions & 0 deletions app/Community/Actions/ReadMessageThreadAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Community\Actions;

use App\Community\Models\MessageThread;
use App\Community\Models\MessageThreadParticipant;
use App\Site\Models\User;

class ReadMessageThreadAction
{
public function execute(MessageThread $thread, User $user): void
{
$participant = MessageThreadParticipant::where('user_id', $user->id)
->where('thread_id', $thread->id)
->whereNull('deleted_at')
->first();

if ($participant) {
ReadMessageThreadAction::markParticipantRead($participant, $user);
}
}

public static function markParticipantRead(MessageThreadParticipant $participant, User $user): void
{
if ($participant->num_unread) {
$participant->num_unread = 0;
$participant->save();

(new UpdateUnreadMessageCountAction())->execute($user);
}
}
}
21 changes: 21 additions & 0 deletions app/Community/Actions/UpdateUnreadMessageCountAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace App\Community\Actions;

use App\Community\Models\MessageThreadParticipant;
use App\Site\Models\User;

class UpdateUnreadMessageCountAction
{
public function execute(User $user): void
{
$totalUnread = MessageThreadParticipant::where('user_id', $user->id)
->whereNull('deleted_at')
->sum('num_unread');

$user->UnreadMessageCount = $totalUnread;
$user->save();
}
}
4 changes: 2 additions & 2 deletions app/Community/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

namespace App\Community;

use App\Community\Commands\MigrateMessages;
use App\Community\Commands\SyncComments;
use App\Community\Commands\SyncForumCategories;
use App\Community\Commands\SyncForums;
use App\Community\Commands\SyncForumTopics;
use App\Community\Commands\SyncMessages;
use App\Community\Commands\SyncNews;
use App\Community\Commands\SyncRatings;
use App\Community\Commands\SyncTickets;
Expand Down Expand Up @@ -54,11 +54,11 @@ public function boot(): void
{
if ($this->app->runningInConsole()) {
$this->commands([
MigrateMessages::class,
SyncComments::class,
SyncForumCategories::class,
SyncForums::class,
SyncForumTopics::class,
SyncMessages::class,
SyncNews::class,
SyncRatings::class,
SyncTickets::class,
Expand Down
3 changes: 3 additions & 0 deletions app/Community/AuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use App\Community\Models\ForumTopicComment;
use App\Community\Models\GameComment;
use App\Community\Models\Message;
use App\Community\Models\MessageThread;
use App\Community\Models\News;
use App\Community\Models\NewsComment;
use App\Community\Models\TriggerTicket;
Expand All @@ -27,6 +28,7 @@
use App\Community\Policies\ForumTopicPolicy;
use App\Community\Policies\GameCommentPolicy;
use App\Community\Policies\MessagePolicy;
use App\Community\Policies\MessageThreadPolicy;
use App\Community\Policies\NewsCommentPolicy;
use App\Community\Policies\NewsPolicy;
use App\Community\Policies\TriggerTicketPolicy;
Expand All @@ -46,6 +48,7 @@ class AuthServiceProvider extends ServiceProvider
ForumTopic::class => ForumTopicPolicy::class,
GameComment::class => GameCommentPolicy::class,
Message::class => MessagePolicy::class,
MessageThread::class => MessageThreadPolicy::class,
News::class => NewsPolicy::class,
NewsComment::class => NewsCommentPolicy::class,
TriggerTicket::class => TriggerTicketPolicy::class,
Expand Down
157 changes: 157 additions & 0 deletions app/Community/Commands/MigrateMessages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<?php

declare(strict_types=1);

namespace App\Community\Commands;

use App\Community\Models\Message;
use App\Community\Models\MessageThread;
use App\Community\Models\MessageThreadParticipant;
use App\Site\Models\User;
use Illuminate\Console\Command;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class MigrateMessages extends Command
{
protected $signature = 'ra:platform:messages:migrate-to-threads';
protected $description = 'Sync messages';

public function __construct()
{
parent::__construct();
}

public function handle(): void
{
$count = Message::where('thread_id', 0)->count();

$progressBar = $this->output->createProgressBar($count);
$progressBar->start();

// populate author_id for all records
DB::statement("UPDATE messages m SET m.author_id = (SELECT u.ID FROM UserAccounts u WHERE u.User = m.UserFrom)");

// delete records associated to non-existant users
DB::statement("DELETE FROM messages WHERE author_id=0");

// process remaining unprocessed records (thread_id=0)
// have to do this in batches to prevent exhausting memory
// due to requesting payloads (message content)
Message::where('thread_id', 0)->chunkById(100, function ($messages) use ($progressBar) {
foreach ($messages as $message) {
$this->migrateMessage($message);
$progressBar->advance();
}
});

$count = Message::where('thread_id', 0)->count();
if ($count == 0) {
// all messages sync'd. add the foreign keys so deletes will cascade
$sm = Schema::getConnection()->getDoctrineSchemaManager();
$foreignKeysFound = $sm->listTableForeignKeys('messages');

$foundThreadForeignKey = false;
$foundAuthorForeignKey = false;
foreach ($foreignKeysFound as $foreignKey) {
if ($foreignKey->getName() == 'messages_thread_id_foreign') {
$foundThreadForeignKey = true;
} elseif ($foreignKey->getName() == 'messages_author_id_foreign') {
$foundAuthorForeignKey = true;
}
}

if (!$foundThreadForeignKey) {
Schema::table('messages', function (Blueprint $table) {
$table->foreign('thread_id')->references('ID')->on('message_threads')->onDelete('cascade');
});
}

if (!$foundAuthorForeignKey) {
Schema::table('messages', function (Blueprint $table) {
$table->foreign('author_id')->references('ID')->on('UserAccounts')->onDelete('cascade');
});
}
}

// automatically mark bug report notifications as deleted by the sender if
// the recipient hasn't replied to them.
DB::statement("UPDATE message_thread_participants mtp
INNER JOIN message_threads mt ON mt.id=mtp.thread_id
INNER JOIN messages m ON m.thread_id=mtp.thread_id AND m.author_id=mtp.user_id
SET mtp.deleted_at=mtp.updated_at
WHERE mt.num_messages=1 AND mt.title LIKE 'Bug Report (%'");

$progressBar->finish();
$this->line(PHP_EOL);
}

private function migrateMessage(Message $message): void
{
// recipient can be entered by user. trim whitespace before trying to match
$message->UserTo = trim($message->UserTo);
$userTo = User::withTrashed()->where('User', $message->UserTo)->first();
if (!$userTo) {
$message->delete();

return;
}

$thread = null;
if (strtolower(substr($message->Title, 0, 4)) == 're: ') {
$threadId = Message::where('title', '=', substr($message->Title, 4))
->where('UserFrom', '=', $message->UserTo)
->where('UserTo', '=', $message->UserFrom)
->where('id', '<', $message->id)
->value('thread_id');
if ($threadId > 0) {
$thread = MessageThread::firstWhere('id', $threadId);
}
}

if ($thread === null) {
$thread = new MessageThread([
'title' => $message->Title,
'created_at' => $message->created_at,
'updated_at' => $message->created_at,
]);
$thread->save();

$participantTo = new MessageThreadParticipant([
'user_id' => $userTo->ID,
'thread_id' => $thread->id,
'created_at' => $message->created_at,
'updated_at' => $message->created_at,
]);
$participantTo->save();

if ($message->author_id != $userTo->ID) {
$participantFrom = new MessageThreadParticipant([
'user_id' => $message->author_id,
'thread_id' => $thread->id,
'created_at' => $message->created_at,
'updated_at' => $message->created_at,
]);
$participantFrom->save();
}
} else {
$threadParticipants = MessageThreadParticipant::withTrashed()->where('thread_id', $thread->id);
$participantTo = $threadParticipants->where('user_id', $userTo->ID)->first();
}

if ($message->Unread) {
$participantTo->num_unread++;
$participantTo->save();
}

$thread->num_messages++;
$thread->last_message_id = $message->id;
$thread->updated_at = $message->created_at;
$thread->timestamps = false;
$thread->save();

$message->thread_id = $thread->id;
$message->save();
}
}
Loading

0 comments on commit 35f3d6c

Please sign in to comment.