where('token', '[A-Za-z0-9]{40,}') ->name('press-releases.preview'); // 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; }; $webHomeData = static function (Portal $primaryPortal, string $language = 'de'): array { $portalValues = [$primaryPortal->value, Portal::Both->value]; // Aktualitäts-Stichtag an den jüngsten Datensatz koppeln (historisches Archiv). $referenceNow = EditorialClock::reference($portalValues, $language); $recentSince = $referenceNow->copy()->subDays(7); $previousSince = $referenceNow->copy()->subDays(14); $publishedQuery = static fn (): Builder => PressRelease::query() ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()); $with = [ 'company', 'category.translations' => fn ($query) => $query->where('locale', $language), 'images' => fn ($query) => $query ->orderByDesc('is_preview') ->orderBy('sort_order') ->limit(1), ]; $oldestPublishedAt = $publishedQuery() ->oldest('published_at') ->value('published_at'); $leadRelease = $publishedQuery() ->with($with) ->orderByDesc('published_at') ->first(); $sideReleases = $publishedQuery() ->with($with) ->when($leadRelease, fn (Builder $query) => $query->where('id', '!=', $leadRelease->id)) ->orderByDesc('published_at') ->limit(4) ->get(); $mostReadReleases = $publishedQuery() ->orderByDesc('hits') ->orderByDesc('published_at') ->limit(4) ->get(['id', 'slug', 'title', 'hits', 'portal', 'language']); $activeNewsrooms = Company::query() ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereHas('pressReleases', function (Builder $query) use ($portalValues, $recentSince, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '>=', $recentSince); }) ->withCount([ 'pressReleases as recent_releases_count' => function (Builder $query) use ($portalValues, $recentSince, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '>=', $recentSince); }, 'pressReleases as today_releases_count' => function (Builder $query) use ($portalValues, $referenceNow, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereDate('published_at', $referenceNow->toDateString()); }, ]) ->orderByDesc('today_releases_count') ->orderByDesc('recent_releases_count') ->limit(6) ->get() ->map(fn (Company $company): array => [ 'name' => $company->name, 'slug' => $company->slug, 'initial' => mb_strtoupper(mb_substr((string) $company->name, 0, 1)), 'count' => (int) $company->recent_releases_count, 'today' => (int) $company->today_releases_count > 0, ]); $industryIndex = Category::query() ->with(['translations' => fn ($query) => $query->where('locale', $language)]) ->withCount([ 'pressReleases as recent_count' => function (Builder $query) use ($portalValues, $recentSince, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->where('published_at', '>=', $recentSince) ->whereNotNull('published_at'); }, 'pressReleases as previous_count' => function (Builder $query) use ($portalValues, $recentSince, $previousSince, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->where('published_at', '>=', $previousSince) ->where('published_at', '<', $recentSince); }, ]) ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereNull('parent_id') ->orderByDesc('recent_count') ->limit(7) ->get() ->map(function (Category $category): ?array { $translation = $category->translations->first(); if (! $translation) { return null; } return [ 'name' => $translation->name, 'href' => $translation->slug ? route('kategorie', ['slug' => $translation->slug]) : route('web.home'), 'count' => (int) ($category->recent_count ?? 0), 'delta' => (int) ($category->recent_count ?? 0) - (int) ($category->previous_count ?? 0), ]; }) ->filter() ->values(); // "Heute im Fokus · Branche": aktivste Top-Rubrik im Stichtag-Fenster mit echten Meldungen. $spotlightCategory = Category::query() ->with(['translations' => fn ($query) => $query->where('locale', $language)]) ->withCount([ 'pressReleases as window_count' => function (Builder $query) use ($portalValues, $recentSince, $referenceNow, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '>=', $recentSince) ->where('published_at', '<=', $referenceNow); }, ]) ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereNull('parent_id') ->orderByDesc('window_count') ->first(); $spotlight = null; if ($spotlightCategory && $spotlightTranslation = $spotlightCategory->translations->first()) { $spotlightBase = static fn (): Builder => PressRelease::query() ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()) ->where('category_id', $spotlightCategory->id); $spotlightReleases = $spotlightBase() ->with(['company']) ->orderByDesc('published_at') ->limit(3) ->get() ->map(static function (PressRelease $release) use ($spotlightTranslation): array { $words = str_word_count(strip_tags((string) $release->text)); $publishedAt = $release->published_at; return [ 'time' => $publishedAt?->format('H:i') ?? '', 'date' => $publishedAt?->translatedFormat('j. M') ?? '', 'category' => $spotlightTranslation->name, 'title' => $release->title, 'company' => $release->company?->name ?? '', 'city' => null, 'minutes' => max(1, (int) ceil($words / 200)), 'href' => $release->slug ? route('release.detail', ['slug' => $release->slug]) : '#', ]; }); if ($spotlightReleases->isNotEmpty()) { $windowCount = (int) ($spotlightCategory->window_count ?? 0); $archiveCount = $spotlightBase()->count(); $activeCompanies = (clone $spotlightBase()) ->where('published_at', '>=', $recentSince) ->where('published_at', '<=', $referenceNow) ->distinct() ->count('company_id'); $spotlight = [ 'industry' => $spotlightTranslation->name, 'stats' => [ ['label' => 'Meldungen (7 Tage)', 'value' => number_format($windowCount, 0, ',', '.'), 'sub' => 'Stand '.$referenceNow->translatedFormat('j. M Y')], ['label' => 'Aktive Unternehmen', 'value' => number_format($activeCompanies, 0, ',', '.'), 'sub' => 'in dieser Branche'], ['label' => 'Im Archiv', 'value' => number_format($archiveCount, 0, ',', '.'), 'sub' => 'Meldungen gesamt'], ], 'releases' => $spotlightReleases->all(), ]; } } // Ad-Hoc-Ticker aus den jüngsten echten Pressemitteilungen. $tickerItems = $publishedQuery() ->orderByDesc('published_at') ->limit(8) ->get(['id', 'title', 'published_at']) ->map(static fn (PressRelease $release): array => [ 'time' => $release->published_at?->format('H:i') ?? '', 'text' => Str::limit((string) $release->title, 70), ]) ->all(); return [ 'leadRelease' => $leadRelease, 'sideReleases' => $sideReleases, 'mostReadReleases' => $mostReadReleases, 'activeNewsrooms' => $activeNewsrooms, 'industryIndex' => $industryIndex, 'spotlight' => $spotlight, 'tickerItems' => $tickerItems, 'homeStats' => [ 'publishedCount' => $publishedQuery()->count(), 'publishedToday' => $publishedQuery()->whereDate('published_at', $referenceNow->toDateString())->count(), 'archiveSince' => $oldestPublishedAt ? (int) Carbon::parse($oldestPublishedAt)->format('Y') : null, ], ]; }; // 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]; $category = Category::query() ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereHas('translations', fn (Builder $query) => $query->where('locale', $language)->where('slug', $slug)) ->with([ 'translations' => fn ($query) => $query->where('locale', $language), 'parent.translations' => fn ($query) => $query->where('locale', $language), ]) ->first(); if (! $category) { abort(404); } $childCategories = Category::query() ->where('parent_id', $category->id) ->where('is_active', true) ->with(['translations' => fn ($query) => $query->where('locale', $language)]) ->get(); $categoryIds = collect([$category->id])->merge($childCategories->pluck('id'))->unique()->values()->all(); $base = static fn (): Builder => PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()) ->whereIn('category_id', $categoryIds); // Kategoriespezifischer Stichtag: jüngste Meldung dieser Branche. $latest = $base()->max('published_at'); $referenceNow = $latest ? Carbon::parse($latest) : now(); if ($referenceNow->gt(now())) { $referenceNow = now(); } $recentSince = $referenceNow->copy()->subDays(7); $previousSince = $referenceNow->copy()->subDays(14); $monthSince = $referenceNow->copy()->subDays(30); $with = [ 'company', 'category.translations' => fn ($query) => $query->where('locale', $language), 'images' => fn ($query) => $query->orderByDesc('is_preview')->orderBy('sort_order')->limit(1), ]; $leadRelease = $base()->with($with)->orderByDesc('published_at')->first(); $topReleases = $base() ->with($with) ->when($leadRelease, fn (Builder $query) => $query->whereKeyNot($leadRelease->getKey())) ->orderByDesc('published_at') ->limit(2) ->get(); $excludeIds = collect([$leadRelease?->getKey()])->merge($topReleases->modelKeys())->filter()->all(); $feedReleases = $base() ->with($with) ->when($excludeIds !== [], fn (Builder $query) => $query->whereNotIn('id', $excludeIds)) ->orderByDesc('published_at') ->limit(12) ->get(); $mostReadReleases = $base() ->orderByDesc('hits') ->orderByDesc('published_at') ->limit(5) ->get(['id', 'slug', 'title', 'hits', 'portal', 'language']); $stats = [ 'today' => $base()->whereDate('published_at', $referenceNow->toDateString())->count(), 'week' => $base()->where('published_at', '>=', $recentSince)->count(), 'previousWeek' => $base()->where('published_at', '>=', $previousSince)->where('published_at', '<', $recentSince)->count(), 'month' => $base()->where('published_at', '>=', $monthSince)->count(), 'total' => $base()->count(), 'activeCompanies' => $base()->where('published_at', '>=', $recentSince)->distinct()->count('company_id'), 'totalCompanies' => $base()->distinct()->count('company_id'), ]; $newsroomFilter = static function (Builder $query) use ($portalValues, $categoryIds, $language): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->whereIn('category_id', $categoryIds); }; $topNewsrooms = Company::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereHas('pressReleases', function (Builder $query) use ($newsroomFilter, $recentSince): void { $newsroomFilter($query); $query->where('published_at', '>=', $recentSince); }) ->withCount([ 'pressReleases as recent_releases_count' => function (Builder $query) use ($newsroomFilter, $recentSince): void { $newsroomFilter($query); $query->where('published_at', '>=', $recentSince); }, 'pressReleases as today_releases_count' => function (Builder $query) use ($newsroomFilter, $referenceNow): void { $newsroomFilter($query); $query->whereDate('published_at', $referenceNow->toDateString()); }, ]) ->orderByDesc('recent_releases_count') ->limit(6) ->get() ->map(fn (Company $company): array => [ 'name' => $company->name, 'slug' => $company->slug, 'initial' => mb_strtoupper(mb_substr((string) $company->name, 0, 1)), 'count' => (int) $company->recent_releases_count, 'today' => (int) $company->today_releases_count > 0, ]); $publishedCount = static fn (Builder $query) => $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at'); $subCategories = $childCategories ->map(function (Category $child) use ($recentSince, $previousSince, $publishedCount): ?array { $translation = $child->translations->first(); if (! $translation) { return null; } $total = PressRelease::query()->withoutGlobalScope(PortalScope::class) ->where('category_id', $child->id)->tap($publishedCount)->count(); $recent = PressRelease::query()->withoutGlobalScope(PortalScope::class) ->where('category_id', $child->id)->tap($publishedCount)->where('published_at', '>=', $recentSince)->count(); $previous = PressRelease::query()->withoutGlobalScope(PortalScope::class) ->where('category_id', $child->id)->tap($publishedCount) ->where('published_at', '>=', $previousSince)->where('published_at', '<', $recentSince)->count(); return [ 'name' => $translation->name, 'href' => $translation->slug ? route('kategorie', ['slug' => $translation->slug]) : route('web.home'), 'total' => $total, 'recent' => $recent, 'delta' => $recent - $previous, ]; }) ->filter() ->sortByDesc('total') ->values(); $relatedCategories = Category::query() ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereNull('parent_id') ->whereKeyNot($category->id) ->when($category->parent_id, fn (Builder $query) => $query->whereKeyNot($category->parent_id)) ->with(['translations' => fn ($query) => $query->where('locale', $language)]) ->withCount([ 'pressReleases as total_count' => fn (Builder $query) => $publishedCount($query), ]) ->orderByDesc('total_count') ->limit(8) ->get() ->map(function (Category $related): ?array { $translation = $related->translations->first(); if (! $translation) { return null; } return [ 'name' => $translation->name, 'href' => $translation->slug ? route('kategorie', ['slug' => $translation->slug]) : route('web.home'), 'count' => (int) ($related->total_count ?? 0), ]; }) ->filter() ->values(); return view('web.kategorie', [ 'category' => $category, 'referenceNow' => $referenceNow, 'leadRelease' => $leadRelease, 'topReleases' => $topReleases, 'feedReleases' => $feedReleases, 'mostReadReleases' => $mostReadReleases, 'categoryStats' => $stats, 'topNewsrooms' => $topNewsrooms, 'subCategories' => $subCategories, 'relatedCategories' => $relatedCategories, ]); }; // 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]; $publishedScope = static fn (Builder $query): Builder => $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()); $release = PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->tap($publishedScope) ->where('slug', $slug) ->with([ 'company', 'category.translations' => fn ($query) => $query->where('locale', $language), 'category.parent.translations' => fn ($query) => $query->where('locale', $language), 'images' => fn ($query) => $query->orderByDesc('is_preview')->orderBy('sort_order'), 'contacts', ]) ->first(); if (! $release) { abort(404); } PressRelease::withoutGlobalScope(PortalScope::class) ->whereKey($release->getKey()) ->update(['hits' => ($release->hits ?? 0) + 1]); $with = [ 'company', 'category.translations' => fn ($query) => $query->where('locale', $language), 'images' => fn ($query) => $query->orderByDesc('is_preview')->orderBy('sort_order')->limit(1), ]; $companyReleases = $release->company_id ? PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->tap($publishedScope) ->where('company_id', $release->company_id) ->whereKeyNot($release->getKey()) ->with($with) ->orderByDesc('published_at') ->limit(3) ->get() : collect(); $relatedReleases = $release->category_id ? PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->tap($publishedScope) ->where('category_id', $release->category_id) ->whereKeyNot($release->getKey()) ->when($companyReleases->isNotEmpty(), fn (Builder $query) => $query->whereNotIn('id', $companyReleases->modelKeys())) ->with($with) ->orderByDesc('published_at') ->limit(3) ->get() : collect(); return view('web.release-detail', [ 'release' => $release, 'companyReleases' => $companyReleases, 'relatedReleases' => $relatedReleases, ]); }; // 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]; $referenceNow = EditorialClock::reference($portalValues, $language); $recentSince = $referenceNow->copy()->subDays(30); $publishedBase = static fn (): Builder => PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()); $archiveTotal = $publishedBase()->count(); $publishedToday = $publishedBase()->whereDate('published_at', $referenceNow->toDateString())->count(); $oldest = $publishedBase()->min('published_at'); $oldestYear = $oldest ? (int) Carbon::parse($oldest)->format('Y') : null; $inReview = PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Review) ->where('language', $language) ->count(); $exampleRelease = $publishedBase() ->with([ 'company', 'category.translations' => fn ($query) => $query->where('locale', $language), ]) ->orderByDesc('published_at') ->first(); $newsroomFilter = static function (Builder $query) use ($portalValues, $language, $recentSince): void { $query ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '>=', $recentSince); }; $newsroomQuery = Company::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('is_active', true) ->whereHas('pressReleases', fn (Builder $query) => $newsroomFilter($query)); $activeNewsroomsTotal = (clone $newsroomQuery)->count(); $activeNewsroomNames = (clone $newsroomQuery) ->withCount(['pressReleases as recent_count' => fn (Builder $query) => $newsroomFilter($query)]) ->orderByDesc('recent_count') ->limit(10) ->pluck('name') ->all(); return view('web.veroeffentlichen', [ 'referenceNow' => $referenceNow, 'archiveTotal' => $archiveTotal, 'publishedToday' => $publishedToday, 'inReview' => $inReview, 'oldestYear' => $oldestYear, 'exampleRelease' => $exampleRelease, 'activeNewsroomNames' => $activeNewsroomNames, 'activeNewsroomsTotal' => $activeNewsroomsTotal, ]); }; // 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]; $mostReadReleases = PressRelease::query() ->withoutGlobalScope(PortalScope::class) ->whereIn('portal', $portalValues) ->where('status', PressReleaseStatus::Published) ->where('language', $language) ->whereNotNull('published_at') ->where('published_at', '<=', now()) ->orderByDesc('hits') ->orderByDesc('published_at') ->limit(5) ->get(['id', 'slug', 'title', 'hits', 'portal', 'language']); return view('web.suche', [ 'portal' => $portal->value, 'language' => $language, 'mostReadReleases' => $mostReadReleases, ]); }; // --------------------------------------------------------------------------- // Bare Root: Publisher-Hub (pressekonto) oder Redirect auf die Default-Ausgabe. // --------------------------------------------------------------------------- Route::get('/', function () use ($applyWebDomainConfig) { $domain = request()->getHost(); if (str_contains($domain, 'pressekonto')) { $applyWebDomainConfig('pressekonto'); return view('web.pressekonto'); } return redirect(request()->getSchemeAndHttpHost().'/'.SetEdition::DEFAULT_EDITION, 301); })->name('home'); // --------------------------------------------------------------------------- // Legacy .html-URLs -> saubere 301-Weiterleitung (vor der Edition-Gruppe, damit // `category/x.html` nicht als Slug `x.html` in die Kategorie-Route läuft). // --------------------------------------------------------------------------- $htmlRedirect = static function (string $edition, string $path) { $clean = trim((string) preg_replace('/\.html$/', '', $path), '/'); $staticPages = [ 'preise', 'faq', 'kontakt', 'ueber-uns', 'veroeffentlichen', 'suche', 'newsrooms', 'api', 'team', 'partner', 'karriere', 'presse', 'hilfe', 'impressum', 'datenschutz', 'agb', 'cookies', ]; // Entfallene Rubriken-Übersicht -> Startseite der Ausgabe. if ($clean === 'kategorien') { return redirect(request()->getSchemeAndHttpHost().'/'.$edition, 301); } if (str_starts_with($clean, 'category/') || str_starts_with($clean, 'press-release/')) { $target = $clean; } elseif ($clean === '' || str_contains($clean, '/')) { $target = $clean; } elseif (in_array($clean, $staticPages, true)) { $target = $clean; } else { // Flache Detail-URL der Altseite: /{edition}/{slug}.html $target = 'press-release/'.$clean; } return redirect(request()->getSchemeAndHttpHost().rtrim('/'.$edition.'/'.$target, '/'), 301); }; Route::get('{edition}/{path}', function (string $edition, string $path) use ($htmlRedirect) { return $htmlRedirect($edition, $path); })->where('path', '.*\.html')->whereIn('edition', SetEdition::EDITIONS); // Top-Level Legacy ohne Ausgabe-Präfix -> Default-Ausgabe. Route::get('{path}', function (string $path) use ($htmlRedirect) { return $htmlRedirect(SetEdition::DEFAULT_EDITION, $path); })->where('path', '.*\.html'); // --------------------------------------------------------------------------- // Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/... // --------------------------------------------------------------------------- Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(function () use ($applyWebDomainConfig, $webHomeData, $categoryPage, $releaseDetailPage, $veroeffentlichenPage, $suchePage) { // Startseite je Ausgabe Route::get('/', function (string $edition) use ($applyWebDomainConfig, $webHomeData) { $domain = request()->getHost(); if (str_contains($domain, 'pressekonto')) { return redirect(request()->getSchemeAndHttpHost().'/', 301); } [$domainKey, $portal, $view] = match (true) { str_contains($domain, 'presseecho') => ['presseecho', Portal::Presseecho, 'web.presseecho'], default => ['businessportal24', Portal::Businessportal24, 'web.businessportal24'], }; $applyWebDomainConfig($domainKey); return view($view, $webHomeData($portal, app()->getLocale())); })->name('web.home'); // Kategorie / Branchenseite (z.B. /de/category/energie-klima) Route::get('category/{slug}', $categoryPage)->name('kategorie'); // Detailseite einer Pressemitteilung (z.B. /de/press-release/ki-revolution) Route::get('press-release/{slug}', $releaseDetailPage)->name('release.detail'); // Statische Seiten Route::view('preise', 'web.preise')->name('preise'); Route::view('faq', 'web.faq')->name('faq'); Route::view('kontakt', 'web.kontakt')->name('kontakt'); Route::view('ueber-uns', 'web.ueber-uns')->name('ueber-uns'); Route::get('veroeffentlichen', $veroeffentlichenPage)->name('veroeffentlichen'); Route::get('suche', $suchePage)->name('suche'); Route::view('newsrooms', 'web.newsrooms')->name('newsrooms'); Route::view('api', 'web.api')->name('api'); Route::view('team', 'web.team')->name('team'); Route::view('partner', 'web.partner')->name('partner'); Route::view('karriere', 'web.karriere')->name('karriere'); Route::view('presse', 'web.presse')->name('presse'); Route::view('hilfe', 'web.hilfe')->name('hilfe'); Route::view('impressum', 'web.impressum')->name('impressum'); Route::view('datenschutz', 'web.datenschutz')->name('datenschutz'); Route::view('agb', 'web.agb')->name('agb'); Route::view('cookies', 'web.cookies')->name('cookies'); }); // --------------------------------------------------------------------------- // Sprach-/Edition-unabhängige Routen (Dev-Varianten, API-Doku). // --------------------------------------------------------------------------- Route::get('/variant-1', function () { $domain = request()->getHost(); if (str_contains($domain, 'presseecho')) { return view('web.presseecho'); } return view('web.businessportal24-variant-float-glow'); })->name('variant-1'); Route::get('/variant-2', function () { $domain = request()->getHost(); if (str_contains($domain, 'presseecho')) { return view('web.presseecho'); } return view('web.businessportal24-variant-glass-gradient'); }); Route::get('/docs/api/v1', function () { return response((string) file_get_contents(base_path('docs/api/v1.yml')), 200, [ 'Content-Type' => 'application/yaml; charset=UTF-8', ]); })->name('docs.api.v1');