$data */ public function createInstant(User $user, Organization $organization, array $data = []): Room { return $this->create($user, $organization, array_merge($data, [ 'type' => 'instant', 'status' => 'scheduled', 'title' => $data['title'] ?? 'Instant meeting', ])); } /** * @param array $data */ public function createScheduled(User $user, Organization $organization, array $data): Room { return $this->create($user, $organization, array_merge($data, [ 'type' => 'scheduled', 'status' => 'scheduled', ])); } /** * @param array $data */ public function create(User $user, Organization $organization, array $data): Room { $ownerRef = $user->ownerRef(); $settings = array_merge(config('meet.default_settings'), $data['settings'] ?? []); $room = Room::create([ 'owner_ref' => $ownerRef, 'organization_id' => $organization->id, 'branch_id' => $data['branch_id'] ?? null, 'host_user_ref' => $data['host_user_ref'] ?? $ownerRef, 'title' => $data['title'], 'description' => $data['description'] ?? null, 'type' => $data['type'] ?? 'instant', 'status' => $data['status'] ?? 'scheduled', 'slug' => $data['slug'] ?? null, 'scheduled_at' => $data['scheduled_at'] ?? now(), 'duration_minutes' => $data['duration_minutes'] ?? 60, 'timezone' => $data['timezone'] ?? $organization->timezone, 'passcode' => isset($data['passcode']) ? (string) $data['passcode'] : null, 'settings' => $settings, 'source' => $data['source'] ?? null, ]); AuditLogger::record($ownerRef, 'room.created', $organization->id, $ownerRef, Room::class, $room->id); app(\App\Services\Integrations\WebhookDispatcher::class)->roomCreated($room); return $room; } /** * @param array $data */ public function update(Room $room, array $data, ?User $host = null): Room { $settings = isset($data['settings']) ? array_merge($room->settings ?? [], $data['settings']) : $room->settings; $room->update(array_filter([ 'title' => $data['title'] ?? null, 'description' => array_key_exists('description', $data) ? $data['description'] : null, 'scheduled_at' => $data['scheduled_at'] ?? null, 'duration_minutes' => $data['duration_minutes'] ?? null, 'timezone' => $data['timezone'] ?? null, 'passcode' => array_key_exists('passcode', $data) ? ($data['passcode'] !== null ? (string) $data['passcode'] : null) : null, 'settings' => $settings, 'source' => $data['source'] ?? null, 'host_user_ref' => $data['host_user_ref'] ?? null, ], fn ($value) => $value !== null)); AuditLogger::record($room->owner_ref, 'room.updated', $room->organization_id, $room->host_user_ref, Room::class, $room->id); if ($host && $room->scheduled_at) { app(CalendarService::class)->syncRoomCreated($room->fresh(), $host); } return $room->fresh(); } public function ensurePersonalRoom(User $user, Organization $organization): Room { $ownerRef = $user->ownerRef(); $slug = 'personal-'.Str::slug($organization->slug); return Room::firstOrCreate( [ 'owner_ref' => $ownerRef, 'organization_id' => $organization->id, 'type' => 'personal', 'slug' => $slug, ], [ 'host_user_ref' => $ownerRef, 'title' => $user->name."'s meeting room", 'status' => 'scheduled', 'scheduled_at' => now(), 'timezone' => $organization->timezone, 'settings' => config('meet.default_settings'), ], ); } public function cancel(Room $room, string $actorRef, ?User $host = null): Room { $room->update(['status' => 'cancelled']); AuditLogger::record($room->owner_ref, 'room.cancelled', $room->organization_id, $actorRef, Room::class, $room->id); if ($host) { app(CalendarService::class)->syncRoomCancelled($room, $host); } app(\App\Services\Integrations\WebhookDispatcher::class)->roomCancelled($room); return $room; } public function mediaRoomName(Room $room, ?string $sessionUuid = null): string { return 'meet-'.$room->uuid.($sessionUuid ? '-'.$sessionUuid : ''); } }