$portalValues */ public function findClaimable(array $portalValues, string $slug): ?Company { return Company::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('slug', $slug) ->whereNull('gone_at') ->first(); } /** * Empfänger des Anmeldelinks: die Firmen-E-Mail, sonst die Adressen der * Pressekontakte. Bewusst nicht beides — ein Klick eines Fremden soll * nicht fünf Postfächer treffen. Gesperrte Adressen (Bounce-Suppression, * 1b.6) zählen nicht: Ein Newsroom, dessen einzige Adresse tot ist, ist * nicht beanspruchbar — siehe isUnreachable(). * * @return Collection */ public function recipients(Company $company): Collection { $candidates = $this->candidateRecipients($company); if ($candidates === []) { return collect(); } $suppressed = $this->suppressions->suppressedAmong($candidates); return collect(array_values(array_filter($candidates, fn (string $email): bool => ! in_array($email, $suppressed, true)))); } /** * Es gäbe Adressen, aber alle sind gesperrt. */ public function isUnreachable(Company $company): bool { return $this->candidateRecipients($company) !== [] && $this->recipients($company)->isEmpty(); } /** * @return list */ private function candidateRecipients(Company $company): array { $companyEmail = Company::emailKey($company->email); if ($companyEmail !== null) { return [$companyEmail]; } $emails = []; foreach ($company->contacts()->withoutGlobalScope(PortalScope::class)->pluck('email') as $email) { $key = Company::emailKey($email); if ($key !== null) { $emails[$key] = $key; } } return array_values($emails); } /** * Verschickt die Anmeldelinks. Gibt zurück, an wie viele Adressen * tatsächlich etwas ging — deaktivierte Konten bekommen nichts. */ public function request(Company $company, ?string $ip, ConversionSource $source = ConversionSource::ProfileClaim, ?int $landingPressReleaseId = null): int { $sent = 0; foreach ($this->recipients($company) as $email) { if ($this->contactAccess->requestMagicAccess($email, $ip, $source, $company->getKey(), $landingPressReleaseId)) { $sent++; } } return $sent; } /** * @return Collection */ public function maskedRecipients(Company $company): Collection { return $this->recipients($company)->map(fn (string $email): string => self::mask($email)); } public static function mask(string $email): string { [$local, $domain] = array_pad(explode('@', $email, 2), 2, ''); return Str::substr($local, 0, 1).'***@'.$domain; } }