Phases 0–18: core meetings, webinar, breakouts, team chat, live streaming, town hall, billing, and Ladill Mail calendar wiring. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Meet;
|
||||
|
||||
use App\Models\BreakoutAssignment;
|
||||
use App\Models\BreakoutRoom;
|
||||
use App\Models\Message;
|
||||
use App\Models\Participant;
|
||||
use App\Models\Session;
|
||||
use App\Services\Meet\Media\MediaProviderInterface;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class BreakoutService
|
||||
{
|
||||
public function __construct(
|
||||
protected MediaProviderInterface $media,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<int, array{participant_id: int, breakout_room_id?: int}>|null $assignments
|
||||
* @return \Illuminate\Support\Collection<int, BreakoutRoom>
|
||||
*/
|
||||
public function createRooms(Session $session, int $count, ?int $timerMinutes = null, ?array $assignments = null)
|
||||
{
|
||||
$timerMinutes ??= config('meet.breakouts.default_timer_minutes', 15);
|
||||
$closesAt = now()->addMinutes($timerMinutes);
|
||||
$rooms = collect();
|
||||
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$mediaName = $session->media_room_name.'-breakout-'.Str::random(8);
|
||||
$this->media->createRoom($mediaName);
|
||||
|
||||
$rooms->push(BreakoutRoom::create([
|
||||
'owner_ref' => $session->owner_ref,
|
||||
'session_id' => $session->id,
|
||||
'name' => 'Breakout '.$i,
|
||||
'media_room_name' => $mediaName,
|
||||
'status' => 'open',
|
||||
'closes_at' => $closesAt,
|
||||
]));
|
||||
}
|
||||
|
||||
$participants = $session->participants()->where('status', 'joined')->get();
|
||||
|
||||
if ($assignments) {
|
||||
foreach ($assignments as $assignment) {
|
||||
$this->assignParticipant(
|
||||
$rooms->firstWhere('id', $assignment['breakout_room_id']) ?? $rooms->first(),
|
||||
Participant::findOrFail($assignment['participant_id']),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$participants->values()->each(function (Participant $participant, int $index) use ($rooms) {
|
||||
$this->assignParticipant($rooms[$index % $rooms->count()], $participant);
|
||||
});
|
||||
}
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
|
||||
public function assignParticipant(BreakoutRoom $breakout, Participant $participant): void
|
||||
{
|
||||
BreakoutAssignment::updateOrCreate(
|
||||
['breakout_room_id' => $breakout->id, 'participant_id' => $participant->id],
|
||||
);
|
||||
$participant->update(['breakout_room_id' => $breakout->id]);
|
||||
}
|
||||
|
||||
public function moveParticipant(Participant $participant, BreakoutRoom $breakout): void
|
||||
{
|
||||
$this->assignParticipant($breakout, $participant);
|
||||
}
|
||||
|
||||
public function returnToMain(Participant $participant): void
|
||||
{
|
||||
$participant->update(['breakout_room_id' => null]);
|
||||
BreakoutAssignment::where('participant_id', $participant->id)->delete();
|
||||
}
|
||||
|
||||
public function broadcast(Session $session, string $message, string $senderName): Message
|
||||
{
|
||||
return Message::create([
|
||||
'owner_ref' => $session->owner_ref,
|
||||
'session_id' => $session->id,
|
||||
'sender_name' => $senderName,
|
||||
'type' => 'breakout_broadcast',
|
||||
'body' => $message,
|
||||
]);
|
||||
}
|
||||
|
||||
public function closeAll(Session $session): void
|
||||
{
|
||||
$session->breakoutRooms()->update(['status' => 'closed']);
|
||||
$session->participants()->whereNotNull('breakout_room_id')->update(['breakout_room_id' => null]);
|
||||
BreakoutAssignment::whereIn('breakout_room_id', $session->breakoutRooms()->pluck('id'))->delete();
|
||||
}
|
||||
|
||||
public function mediaRoomForParticipant(Participant $participant): string
|
||||
{
|
||||
if ($participant->breakout_room_id) {
|
||||
return $participant->breakoutRoom?->media_room_name ?? $participant->session->media_room_name;
|
||||
}
|
||||
|
||||
return $participant->session->media_room_name;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user