*/ public function teams(): BelongsToMany { return $this->belongsToMany(Team::class, 'team_members', 'user_id', 'team_id') ->withPivot(['role']) ->withTimestamps(); } /** * Get all of the teams the user owns. * * @return HasManyThrough */ public function ownedTeams(): HasManyThrough { return $this->hasManyThrough( Team::class, Membership::class, 'user_id', 'id', 'id', 'team_id', )->where('team_members.role', TeamRole::Owner->value); } /** * Get all of the memberships for the user. * * @return HasMany */ public function teamMemberships(): HasMany { return $this->hasMany(Membership::class, 'user_id'); } /** * Get the user's current team. * * @return BelongsTo */ public function currentTeam(): BelongsTo { return $this->belongsTo(Team::class, 'current_team_id'); } /** * Get the user's personal team. */ public function personalTeam(): ?Team { return $this->teams() ->where('is_personal', true) ->first(); } /** * Switch to the given team. */ public function switchTeam(Team $team): bool { if (! $this->belongsToTeam($team)) { return false; } $this->update(['current_team_id' => $team->id]); $this->setRelation('currentTeam', $team); URL::defaults(['current_team' => $team->slug]); return true; } /** * Determine if the user belongs to the given team. */ public function belongsToTeam(Team $team): bool { return $this->teams()->where('teams.id', $team->id)->exists(); } /** * Determine if the given team is the user's current team. */ public function isCurrentTeam(Team $team): bool { return $this->current_team_id === $team->id; } /** * Determine if the user is the owner of the given team. */ public function ownsTeam(Team $team): bool { return $this->teamRole($team) === TeamRole::Owner; } /** * Get the user's role on the given team. */ public function teamRole(Team $team): ?TeamRole { return $this->teamMemberships() ->where('team_id', $team->id) ->first() ?->role; } /** * Get the user's teams as a collection of UserTeam objects. * * @return Collection */ public function toUserTeams(bool $includeCurrent = false): Collection { return $this->teams() ->get() ->map(fn (Team $team) => ! $includeCurrent && $this->isCurrentTeam($team) ? null : $this->toUserTeam($team)) ->filter() ->values(); } /** * Get the user's team as a UserTeam object. */ public function toUserTeam(Team $team): UserTeam { $role = $this->teamRole($team); return new UserTeam( id: $team->id, name: $team->name, slug: $team->slug, isPersonal: $team->is_personal, role: $role?->value, roleLabel: $role?->label(), isCurrent: $this->isCurrentTeam($team), ); } /** * Get the standard permissions for a team as a TeamPermissions object. */ public function toTeamPermissions(Team $team): TeamPermissions { $role = $this->teamRole($team); return new TeamPermissions( canUpdateTeam: $role?->hasPermission(TeamPermission::UpdateTeam) ?? false, canDeleteTeam: $role?->hasPermission(TeamPermission::DeleteTeam) ?? false, canAddMember: $role?->hasPermission(TeamPermission::AddMember) ?? false, canUpdateMember: $role?->hasPermission(TeamPermission::UpdateMember) ?? false, canRemoveMember: $role?->hasPermission(TeamPermission::RemoveMember) ?? false, canCreateInvitation: $role?->hasPermission(TeamPermission::CreateInvitation) ?? false, canCancelInvitation: $role?->hasPermission(TeamPermission::CancelInvitation) ?? false, ); } public function fallbackTeam(?Team $excluding = null): ?Team { return $this->teams() ->when($excluding, fn ($query) => $query->where('teams.id', '!=', $excluding->id)) ->orderByRaw('LOWER(teams.name)') ->first(); } /** * Determine if the user has the given permission on the team. */ public function hasTeamPermission(Team $team, TeamPermission $permission): bool { return $this->teamRole($team)?->hasPermission($permission) ?? false; } }