*/ public function companiesFor(User $user): Collection { $linkedCompanies = $user->companies() ->withoutGlobalScopes() ->select(['companies.id', 'companies.name', 'companies.portal', 'companies.owner_user_id']) ->withPivot('role') ->get(); $ownedCompanies = $user->ownedCompanies() ->withoutGlobalScopes() ->whereNotIn('id', $linkedCompanies->pluck('id')) ->get(['id', 'name', 'portal', 'owner_user_id']); return $linkedCompanies ->concat($ownedCompanies) ->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE) ->values(); } public function selectedCompanyId(User $user): ?int { $companyId = session(self::SessionKey); if (! is_numeric($companyId)) { return null; } $companyId = (int) $companyId; if (! $this->userCanAccessCompany($user, $companyId)) { $this->clear(); return null; } return $companyId; } public function selectedCompany(User $user): ?Company { $companyId = $this->selectedCompanyId($user); if ($companyId === null) { return null; } return $this->findFor($user, $companyId); } /** * @return Collection */ public function latestCompaniesFor(User $user, int $limit = 10): Collection { return $this->accessibleCompanyQuery($user) ->select(['companies.id', 'companies.name', 'companies.portal', 'companies.owner_user_id', 'companies.created_at']) ->latest('companies.created_at') ->latest('companies.id') ->limit($limit) ->get(); } /** * @return Collection */ public function searchCompaniesFor(User $user, string $term = '', ?int $selectedCompanyId = null, int $limit = 10): Collection { $term = Portal::stripTrailingAbbreviation($term); $limit = max(1, $limit); if ($term === '') { return $this->companyOptionsWithSelected($user, $selectedCompanyId, $limit); } return $this->companyOptionQuery($user) ->where(function (Builder $query) use ($term): void { $query->where('companies.name', 'like', '%'.$term.'%') ->orWhere('companies.slug', 'like', '%'.$term.'%') ->orWhere('companies.email', 'like', '%'.$term.'%'); }) ->orderBy('companies.name') ->orderBy('companies.id') ->limit($limit) ->get(); } public function companyCountFor(User $user): int { return $this->accessibleCompanyQuery($user)->count(); } /** * @return Collection */ public function switcherCompaniesFor(User $user, ?int $selectedCompanyId = null, int $limit = 50): Collection { $companies = $this->switcherCompanyQuery($user) ->latest('companies.created_at') ->latest('companies.id') ->limit($limit) ->get(); if ($selectedCompanyId === null || $companies->contains('id', $selectedCompanyId)) { return $companies; } $selectedCompany = $this->switcherCompanyQuery($user) ->whereKey($selectedCompanyId) ->first(); if (! $selectedCompany) { return $companies; } return $companies ->prepend($selectedCompany) ->unique('id') ->values(); } /** * @return Builder */ public function accessibleCompanyQuery(User $user): Builder { return Company::query() ->withoutGlobalScopes() ->where(function ($query) use ($user): void { $query->where('owner_user_id', $user->id) ->orWhereHas('users', fn ($userQuery) => $userQuery->whereKey($user->id)); }); } public function findFor(User $user, int $companyId): ?Company { return $this->accessibleCompanyQuery($user) ->whereKey($companyId) ->first(); } public function select(User $user, ?int $companyId): void { if ($companyId === null) { $this->clear(); return; } if (! $this->userCanAccessCompany($user, $companyId)) { return; } session([self::SessionKey => $companyId]); } public function clear(): void { Session::forget(self::SessionKey); } public function roleLabelFor(Company $company, User $user): string { $role = $company->owner_user_id === $user->id ? 'owner' : ($company->getAttribute('current_user_role') ?? $company->pivot?->role ?? 'member'); return match ($role) { 'owner' => __('Owner'), 'responsible' => __('Verantwortlich'), default => __('Mitglied'), }; } /** * @return Builder */ private function switcherCompanyQuery(User $user): Builder { return $this->accessibleCompanyQuery($user) ->select(['companies.id', 'companies.name', 'companies.portal', 'companies.owner_user_id', 'companies.created_at']) ->addSelect([ 'current_user_role' => DB::table('company_user') ->select('role') ->whereColumn('company_user.company_id', 'companies.id') ->where('company_user.user_id', $user->id) ->limit(1), ]); } /** * @return Builder */ private function companyOptionQuery(User $user): Builder { return $this->accessibleCompanyQuery($user) ->select(['companies.id', 'companies.name', 'companies.portal', 'companies.owner_user_id', 'companies.created_at']); } /** * @return Collection */ private function companyOptionsWithSelected(User $user, ?int $selectedCompanyId, int $limit): Collection { $selectedCompany = $selectedCompanyId ? $this->companyOptionQuery($user)->whereKey($selectedCompanyId)->first() : null; $companies = $this->companyOptionQuery($user) ->when($selectedCompany, fn (Builder $query): Builder => $query->whereKeyNot($selectedCompany->id)) ->latest('companies.created_at') ->latest('companies.id') ->limit($selectedCompany ? max(0, $limit - 1) : $limit) ->get(); if (! $selectedCompany) { return $companies; } return $companies ->prepend($selectedCompany) ->unique('id') ->values(); } private function userCanAccessCompany(User $user, int $companyId): bool { return $this->accessibleCompanyQuery($user) ->whereKey($companyId) ->exists(); } }