loadMissing('sites'); $primarySites = $account->sites->where('type', 'primary')->values(); $hasPlaceholderPrimarySite = $primarySites->contains( fn (HostedSite $site): bool => static::isPlaceholderDomain($site->domain) ); $hasRealPrimarySite = $primarySites->contains( fn (HostedSite $site): bool => ! static::isPlaceholderDomain($site->domain) ); // Never steal primary from an account that already has a real primary site. if ($hasRealPrimarySite) { return false; } // Placeholder primary_domain (incl. null/empty) or only placeholder primary sites. if (static::isPlaceholderDomain($account->primary_domain) || $hasPlaceholderPrimarySite) { return true; } return false; } /** * Whether a newly linked host should be stored as the account primary site. */ public function shouldBecomePrimary(HostingAccount $account, string $domainHost): bool { if ($this->accountNeedsPromotion($account)) { return true; } $primary = strtolower(trim((string) $account->primary_domain)); return $primary !== '' && $primary === strtolower(trim($domainHost)) && ! $account->sites->contains( fn (HostedSite $site): bool => $site->type === 'primary' && ! static::isPlaceholderDomain($site->domain) ); } /** * Prefer a real hosted site over a placeholder primary_domain for UI labels. */ public function displayLabel(HostingAccount $account): string { $account->loadMissing('sites'); $real = $account->sites ->filter(fn (HostedSite $site): bool => ! static::isPlaceholderDomain($site->domain)) ->sortBy(fn (HostedSite $site): array => [$site->type !== 'primary', $site->domain]) ->values(); if ($real->isNotEmpty()) { if ($real->count() === 1) { return (string) $real->first()->domain; } $preview = $real->take(2)->pluck('domain')->implode(', '); return $real->count() > 2 ? "{$preview} +".($real->count() - 2) : $preview; } if (! static::isPlaceholderDomain($account->primary_domain)) { return (string) $account->primary_domain; } return (string) $account->username; } public function promoteSite(HostingAccount $account, HostedSite $site): void { if (static::isPlaceholderDomain($site->domain)) { return; } $account->loadMissing(['sites', 'node']); $site->update(['type' => 'primary']); $account->update([ 'primary_domain' => $site->domain, ]); foreach ($account->sites as $other) { if ((int) $other->id === (int) $site->id) { continue; } if ($other->type === 'primary' && static::isPlaceholderDomain($other->domain)) { $this->retirePlaceholderSite($account, $other); } elseif ($other->type === 'primary') { $other->update(['type' => 'addon']); } } $account->unsetRelation('sites'); } /** * Heal accounts that already have a real linked domain but still carry a * placeholder primary_domain / primary HostedSite. */ public function healAccount(HostingAccount $account): bool { if (! $this->accountNeedsPromotion($account)) { return false; } $account->loadMissing(['sites', 'node']); $candidate = $account->sites ->filter(fn (HostedSite $site): bool => ! static::isPlaceholderDomain($site->domain) && in_array($site->type, ['primary', 'addon'], true)) ->sortBy(fn (HostedSite $site): array => [$site->type !== 'primary', $site->id]) ->first(); if (! $candidate) { // No real site yet — just clear a stale placeholder label. if (static::isPlaceholderDomain($account->primary_domain) && filled($account->primary_domain)) { $account->update(['primary_domain' => null]); foreach ($account->sites->where('type', 'primary') as $placeholder) { if (static::isPlaceholderDomain($placeholder->domain)) { $this->retirePlaceholderSite($account, $placeholder); } } return true; } return false; } $this->promoteSite($account, $candidate); return true; } protected function retirePlaceholderSite(HostingAccount $account, HostedSite $site): void { try { if ($account->node) { $this->provider->removeSite($site); } } catch (\Throwable $e) { Log::info('PlaceholderPrimaryDomainService: best-effort nginx cleanup failed', [ 'site_id' => $site->id, 'domain' => $site->domain, 'error' => $e->getMessage(), ]); } $site->delete(); } }