Files

134 lines
4.4 KiB
PHP

<?php
namespace App\Http\Livewire\WireChat\Chat\Group;
use App\Models\User;
use Namu\WireChat\Enums\Actions;
use Namu\WireChat\Facades\WireChat;
use Namu\WireChat\Livewire\Chat\Group\Info;
use Namu\WireChat\Livewire\Chat\Group\Members as BaseMembers;
use Namu\WireChat\Models\Action;
use Namu\WireChat\Models\Participant;
class Members extends BaseMembers
{
public bool $confirmingSync = false;
/**
* Show the sync confirmation modal.
* Profile name is resolved server-side — no client input trusted.
*/
public function confirmSync(): void
{
abort_unless(auth()->check(), 401);
abort_unless(auth()->user()->isAdminIn($this->conversation), 403);
$activeProfile = getActiveProfile();
if (!$activeProfile) {
return;
}
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
$activeProfileType = getActiveProfileType();
if (!in_array($activeProfileType, ['Organization', 'Bank', 'Admin'])) {
return;
}
$this->confirmingSync = true;
}
/**
* Sync conversation members to match the linked users of the active profile.
* - Adds linked users not yet in the group
* - Removes participants who are no longer linked (except the owner and auth user)
*/
public function syncLinkedMembers(): void
{
abort_unless(auth()->check(), 401);
abort_unless(auth()->user()->isAdminIn($this->conversation), 403);
$activeProfile = getActiveProfile();
if (!$activeProfile) {
$this->confirmingSync = false;
return;
}
\App\Helpers\ProfileAuthorizationHelper::authorize($activeProfile);
$activeProfileType = getActiveProfileType();
if (!in_array($activeProfileType, ['Organization', 'Bank', 'Admin'])) {
$this->confirmingSync = false;
return;
}
$this->confirmingSync = false;
$relationMethod = $activeProfileType === 'Bank' ? 'managers' : 'users';
$linkedUserIds = $activeProfile->$relationMethod()
->select('users.id')
->pluck('users.id')
->toArray();
$authParticipant = $this->conversation->participant(auth()->user());
$maxMembers = WireChat::maxGroupMembers();
// --- Add linked users not yet in the group ---
foreach ($linkedUserIds as $userId) {
if ($this->conversation->participants()->count() >= $maxMembers) {
break;
}
$user = User::find($userId);
if (!$user) {
continue;
}
if (!$user->belongsToConversation($this->conversation)) {
$this->conversation->addParticipant($user, undoAdminRemovalAction: $authParticipant?->isAdmin());
}
}
// --- Remove participants no longer linked ---
$participantsToRemove = $this->conversation->participants()
->with('participantable')
->get()
->filter(function (Participant $participant) use ($linkedUserIds) {
// Never remove the owner
if ($participant->isOwner()) {
return false;
}
// Never remove the currently authenticated user
if (
$participant->participantable_id == auth()->id() &&
$participant->participantable_type == auth()->user()->getMorphClass()
) {
return false;
}
// Remove if not in the linked users list
return !in_array($participant->participantable_id, $linkedUserIds);
});
foreach ($participantsToRemove as $participant) {
Action::create([
'actionable_id' => $participant->id,
'actionable_type' => Participant::class,
'actor_id' => auth()->id(),
'actor_type' => auth()->user()->getMorphClass(),
'type' => Actions::REMOVED_BY_ADMIN,
]);
}
// Reload participants and dispatch updated count
$this->page = 1;
$this->participants = collect();
$this->loadParticipants();
$actualCount = $this->conversation->participants()->count();
$this->totalMembersCount = $actualCount;
$this->dispatch('participantsCountUpdated', $actualCount)->to(Info::class);
}
}