Optimierung 4.1: Web-Portal-/Domain-Kontext extrahiert

- WebPortalContext::fromRequest() buendelt die zuvor ~6x je Route-Closure
  wiederholte Host->Portal-Ableitung (portal, language, portalValues,
  domainConfig).
- DomainAssetContext::applyWebDomainConfig() ist die Single Source of Truth fuer
  die Domain-/Theme-Anwendung (config + View::share + Vite); die fruehere
  $applyWebDomainConfig-Closure in routes/web.php ist nur noch ein duenner
  Delegations-Wrapper, damit Bare-Root- und Edition-Home-Route unveraendert
  per Closure aufrufen koennen.
- Die 6 Portal-Seiten-Closures (Kategorie, Detail, Veroeffentlichen, Suche,
  Newsrooms, Newsroom-Detail) sowie Preise nutzen jetzt den zentralen Kontext.

Abgesichert durch die 92 Web/-Tests (jede Seite laeuft ueber den neuen Kontext).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-19 11:42:00 +00:00
parent 987a5a2c42
commit e5a63bcedd
4 changed files with 106 additions and 98 deletions

View file

@ -12,10 +12,10 @@ use App\Models\PressRelease;
use App\Scopes\PortalScope;
use App\Support\DomainAssetContext;
use App\Support\EditorialClock;
use App\Support\WebPortalContext;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Str;
Route::get('/pm-vorschau/{token}', PressReleasePreviewController::class)
@ -25,27 +25,9 @@ Route::get('/pm-vorschau/{token}', PressReleasePreviewController::class)
// Gemeinsame Web-Routes für alle Landingpages
// Jede Landing-Page hat das gleiche Gerüst, aber unterschiedliches Styling
$applyWebDomainConfig = static function (string $domainKey): array {
$domainConfig = config("domains.domains.{$domainKey}", []);
config([
'app.theme' => $domainConfig['theme'] ?? $domainKey,
'app.view_prefix' => $domainConfig['view_prefix'] ?? 'web',
'app.domain_name' => $domainConfig['domain_name'] ?? request()->getHost(),
'app.url' => $domainConfig['url'] ?? config('app.url'),
]);
View::share('theme', $domainConfig['theme'] ?? $domainKey);
View::share('viewPrefix', $domainConfig['view_prefix'] ?? 'web');
View::share('domainName', $domainConfig['domain_name'] ?? request()->getHost());
View::share('domainConfig', $domainConfig);
View::share('domainUrl', $domainConfig['url'] ?? config('app.url'));
View::share('assetUrl', DomainAssetContext::staticAssetOrigin($domainConfig));
DomainAssetContext::configureVite($domainConfig);
return $domainConfig;
};
// Dünner Delegations-Wrapper auf die Single Source of Truth (DomainAssetContext),
// damit Bare-Root- und Edition-Home-Route unverändert per Closure aufrufen können.
$applyWebDomainConfig = static fn (string $domainKey): array => DomainAssetContext::applyWebDomainConfig($domainKey);
$webHomeData = static function (Portal $primaryPortal, string $language = 'de'): array {
$portalValues = [$primaryPortal->value, Portal::Both->value];
@ -269,18 +251,10 @@ $webHomeData = static function (Portal $primaryPortal, string $language = 'de'):
};
// Kategorie-/Branchenseite je Ausgabe.
$categoryPage = static function (string $edition, string $slug) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$categoryPage = static function (string $edition, string $slug) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$category = Category::query()
->whereIn('portal', $portalValues)
@ -475,18 +449,10 @@ $categoryPage = static function (string $edition, string $slug) use ($applyWebDo
};
// Detailseite einer Pressemitteilung je Ausgabe.
$releaseDetailPage = static function (string $edition, string $slug) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$releaseDetailPage = static function (string $edition, string $slug) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$publishedScope = static fn (Builder $query): Builder => $query
->forPortalValues($portalValues)
@ -553,18 +519,10 @@ $releaseDetailPage = static function (string $edition, string $slug) use ($apply
};
// Veröffentlichen-Marketingseite je Ausgabe (Einreichung läuft im Publisher-Hub).
$veroeffentlichenPage = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$veroeffentlichenPage = static function (string $edition) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$referenceNow = EditorialClock::reference($portalValues, $language);
$recentSince = $referenceNow->copy()->subDays(30);
@ -630,11 +588,11 @@ $veroeffentlichenPage = static function (string $edition) use ($applyWebDomainCo
// Preise-/Tarifseite je Ausgabe: Abos (Plan-Modell), Einzel-PM (config/billing)
// und Add-on-Einzelkosten (config/credits). Inhalte liegen in lang/*/pricing.php.
$preisePage = static function (string $edition) use ($applyWebDomainConfig) {
$preisePage = static function (string $edition) {
$domain = request()->getHost();
$domainKey = str_contains($domain, 'presseecho') ? 'presseecho' : 'businessportal24';
$applyWebDomainConfig($domainKey);
DomainAssetContext::applyWebDomainConfig($domainKey);
// Add-on-Einzelkosten aus der Credit-Ökonomie (1 Credit = 1 €).
$extraPm = collect(config('credits.extra_pm', []))
@ -670,18 +628,10 @@ $preisePage = static function (string $edition) use ($applyWebDomainConfig) {
};
// Archiv-Suchseite je Ausgabe (interaktive Suche läuft in der Volt-Komponente).
$suchePage = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$suchePage = static function (string $edition) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$mostReadReleases = PressRelease::query()
->withoutGlobalScope(PortalScope::class)
@ -694,25 +644,17 @@ $suchePage = static function (string $edition) use ($applyWebDomainConfig) {
->get(['id', 'slug', 'title', 'hits', 'portal', 'language']);
return view('web.suche', [
'portal' => $portal->value,
'portal' => $context->portal->value,
'language' => $language,
'mostReadReleases' => $mostReadReleases,
]);
};
// Newsrooms-Verzeichnis je Ausgabe: alle aktiven Unternehmen mit Meldungen.
$newsroomsIndex = static function (string $edition) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$newsroomsIndex = static function (string $edition) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$referenceNow = EditorialClock::reference($portalValues, $language);
$recentSince = $referenceNow->copy()->subDays(30);
@ -768,18 +710,10 @@ $newsroomsIndex = static function (string $edition) use ($applyWebDomainConfig)
};
// Newsroom-Markenseite eines Unternehmens je Ausgabe: alle Meldungen der Firma.
$newsroomDetail = static function (string $edition, string $slug) use ($applyWebDomainConfig) {
$domain = request()->getHost();
$language = app()->getLocale();
[$domainKey, $portal] = match (true) {
str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho],
default => ['businessportal24', Portal::Businessportal24],
};
$applyWebDomainConfig($domainKey);
$portalValues = [$portal->value, Portal::Both->value];
$newsroomDetail = static function (string $edition, string $slug) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$company = Company::query()
->withoutGlobalScope(PortalScope::class)