'datetime', 'recurrence_until' => 'date', 'settings' => 'array', 'source' => 'array', ]; } protected static function booted(): void { static::creating(function (Room $room) { if (empty($room->uuid)) { $room->uuid = (string) Str::uuid(); } }); } public function getRouteKeyName(): string { return 'uuid'; } public function organization(): BelongsTo { return $this->belongsTo(Organization::class, 'organization_id'); } public function branch(): BelongsTo { return $this->belongsTo(Branch::class, 'branch_id'); } public function sessions(): HasMany { return $this->hasMany(Session::class, 'room_id'); } public function invitations(): HasMany { return $this->hasMany(Invitation::class, 'room_id'); } public function webinarRegistrations(): HasMany { return $this->hasMany(WebinarRegistration::class, 'room_id'); } public function sessionFiles(): HasMany { return $this->hasMany(SessionFile::class, 'room_id'); } /** * @param \Illuminate\Database\Eloquent\Builder $query */ public function scopeForSource($query, string $app, string $entityId, ?string $ownerRef = null): void { $query->where('source->app', $app) ->where('source->entity_id', $entityId); if ($ownerRef !== null) { $query->where('owner_ref', $ownerRef); } } public function isWebinar(): bool { return $this->type === 'webinar'; } public function isConference(): bool { return $this->type === 'town_hall'; } public function isSpace(): bool { return $this->type === 'space'; } public function isAudioOnly(): bool { return $this->isSpace() || (bool) $this->setting('audio_only', false); } public function canRestart(): bool { if ($this->status === 'cancelled' || $this->activeSession()) { return false; } return $this->status === 'ended' || $this->type === 'personal' || $this->status === 'scheduled'; } public function restartLabel(): string { $restarting = $this->status === 'ended' || $this->sessions()->exists(); if ($this->isWebinar()) { return $restarting ? 'Restart webinar' : 'Start webinar'; } if ($this->isConference()) { return $restarting ? 'Restart conference' : 'Start conference'; } if ($this->isSpace()) { return $restarting ? 'Reopen room' : 'Open room'; } return $restarting ? 'Restart meeting' : 'Start meeting'; } public function isTownHall(): bool { return $this->type === 'town_hall'; } public function isRecurring(): bool { return filled($this->recurrence_rule); } public function activeSession(): ?Session { return $this->sessions()->where('status', 'live')->latest()->first(); } public function setting(string $key, mixed $default = null): mixed { return data_get($this->settings, $key, data_get(config('meet.default_settings'), $key, $default)); } public function safeTimezone(): string { $timezone = (string) ($this->timezone ?: 'UTC'); try { new \DateTimeZone($timezone); return $timezone; } catch (\Throwable) { return 'UTC'; } } public function isLive(): bool { return $this->status === 'live'; } public function requiresWaitingRoom(?User $user, string $role): bool { if (! $this->setting('waiting_room', true)) { return false; } if ($role === 'host' || ($user && $user->ownerRef() === $this->host_user_ref)) { return false; } return true; } public function joinUrl(): string { return rtrim((string) config('app.meet_url', 'https://meet.ladill.com'), '/').'/r/'.$this->uuid; } }