197 lines
5.3 KiB
PHP
197 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace App\Concerns;
|
|
|
|
use App\Enums\TeamPermission;
|
|
use App\Enums\TeamRole;
|
|
use App\Models\Membership;
|
|
use App\Models\Team;
|
|
use App\Support\TeamPermissions;
|
|
use App\Support\UserTeam;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\URL;
|
|
|
|
trait HasTeams
|
|
{
|
|
/**
|
|
* Get all of the teams the user belongs to.
|
|
*
|
|
* @return BelongsToMany<Team, $this>
|
|
*/
|
|
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<Team, Membership, $this>
|
|
*/
|
|
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<Membership, $this>
|
|
*/
|
|
public function teamMemberships(): HasMany
|
|
{
|
|
return $this->hasMany(Membership::class, 'user_id');
|
|
}
|
|
|
|
/**
|
|
* Get the user's current team.
|
|
*
|
|
* @return BelongsTo<Team, $this>
|
|
*/
|
|
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<int, UserTeam>
|
|
*/
|
|
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;
|
|
}
|
|
}
|