hasRole('Admin')) { return User::query()->pluck('id')->all(); } $visibleIds = [$user->id]; $frontier = [$user->id]; while ($frontier !== []) { $directReportIds = User::query() ->whereIn('manager_id', $frontier) ->pluck('id') ->all(); $directReportIds = array_values(array_diff($directReportIds, $visibleIds)); if ($directReportIds === []) { break; } $visibleIds = array_merge($visibleIds, $directReportIds); $frontier = $directReportIds; } return $visibleIds; } public function scopeClientsVisibleTo(Builder $query, User $user): Builder { if ($user->hasRole('Admin')) { return $query; } $visibleUserIds = $this->visibleUserIds($user); return $query->whereHas('assignations', function (Builder $query) use ($visibleUserIds) { $query->whereIn('user_id', $visibleUserIds); }); } public function canViewClient(User $user, Client $client): bool { if ($user->hasRole('Admin')) { return true; } return $client->assignations() ->whereIn('user_id', $this->visibleUserIds($user)) ->exists(); } public function wouldCreateCycle(User $user, ?int $managerId): bool { if ($managerId === null) { return false; } if ($user->id === $managerId) { return true; } $frontier = [$user->id]; $checkedIds = [$user->id]; while ($frontier !== []) { $directReportIds = User::query() ->whereIn('manager_id', $frontier) ->pluck('id') ->all(); $directReportIds = array_values(array_diff($directReportIds, $checkedIds)); if (in_array($managerId, $directReportIds, true)) { return true; } $checkedIds = array_merge($checkedIds, $directReportIds); $frontier = $directReportIds; } return false; } }