portalForHost($parts['host']); if ($portal === null) { return null; } // Detail-Route: /{edition}/press-release/{slug}. Ohne Ausgabe im Pfad // gilt wie in SetEdition die Standard-Ausgabe. $editions = implode('|', SetEdition::EDITIONS); if (! preg_match('#^/(?:('.$editions.')/)?press-release/([^/]+)/?$#', $parts['path'] ?? '', $matches)) { return null; } $language = $matches[1] !== '' ? $matches[1] : SetEdition::DEFAULT_EDITION; $slug = rawurldecode($matches[2]); return PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->forPortalValues([$portal->value, Portal::Both->value]) ->forLanguage($language) ->where('slug', $slug) ->visibleInArchive() // Doppelveröffentlichung: beide Fassungen tragen denselben Slug — // die Erstquelle gewinnt (wie in RedirectPortalOnlyPagesFromHub). ->orderByRaw('canonical_press_release_id is null desc') ->orderBy('id') ->first(); } /** * Portal hinter dem Host laut config/domains.php — oder null für jeden * Host, der dort nicht als Portal steht (Hub, fremde Domains, Subdomains * mit vorangestelltem Portalnamen). */ private function portalForHost(string $host): ?Portal { $host = strtolower($host); if (str_starts_with($host, 'www.')) { $host = substr($host, 4); } foreach ((array) config('domains.domains', []) as $key => $domain) { $portal = Portal::tryFrom((string) $key); if ($portal === null || $portal === Portal::Both) { continue; } $configuredHosts = array_filter([ strtolower((string) ($domain['domain_name'] ?? '')), strtolower((string) (parse_url((string) ($domain['url'] ?? ''), PHP_URL_HOST) ?: '')), ]); if (in_array($host, $configuredHosts, true)) { return $portal; } } return null; } }