isWebinar() || $room->isConference(); } public function canManageSpeakAccess(Participant $participant): bool { $room = $participant->session->room; if (! $this->usesSpeakAccess($room)) { return false; } return in_array($participant->role, ['host', 'co_host', 'panelist'], true); } public function requestSpeak(Participant $participant): Participant { $room = $participant->session->room; abort_unless($this->usesSpeakAccess($room), 422); abort_unless($participant->role === 'attendee', 422); abort_unless(! $participant->speak_granted, 422, 'You already have speak access.'); $participant->update(['speak_requested' => true]); return $participant->fresh(); } public function cancelSpeakRequest(Participant $participant): Participant { $participant->update(['speak_requested' => false]); return $participant->fresh(); } public function grantSpeak(Participant $target, Participant $actor): Participant { abort_unless($this->canManageSpeakAccess($actor), 403); abort_unless($target->session_id === $actor->session_id, 404); abort_unless($target->status === 'joined', 422); abort_unless($this->usesSpeakAccess($target->session->room), 422); $target->update([ 'speak_granted' => true, 'speak_requested' => false, ]); return $target->fresh(); } public function revokeSpeak(Participant $target, Participant $actor): Participant { abort_unless($this->canManageSpeakAccess($actor), 403); abort_unless($target->session_id === $actor->session_id, 404); $target->update([ 'speak_granted' => false, 'speak_requested' => false, 'is_muted' => true, ]); return $target->fresh(); } public function dismissSpeakRequest(Participant $target, Participant $actor): Participant { abort_unless($this->canManageSpeakAccess($actor), 403); abort_unless($target->session_id === $actor->session_id, 404); $target->update(['speak_requested' => false]); return $target->fresh(); } }