Optimierung 4.3/4.4 (Newsroom-Detail): Page-Data-Service + Invokable Controller

Newsroom-Markenseite in NewsroomDetailPageData + Web\NewsroomDetailController.
Controller-Signatur fuehrt {edition} vor {slug} (positionsgebundene
Route-Parameter-Aufloesung). Verhalten unveraendert, 92 Web-Tests gruen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-06-19 12:08:21 +00:00
parent a2179ea47f
commit 179dd8e004
3 changed files with 152 additions and 111 deletions

View file

@ -2,6 +2,7 @@
use App\Enums\Portal;
use App\Http\Controllers\PressReleasePreviewController;
use App\Http\Controllers\Web\NewsroomDetailController;
use App\Http\Controllers\Web\NewsroomsController;
use App\Http\Controllers\Web\PreiseController;
use App\Http\Controllers\Web\SucheController;
@ -520,115 +521,6 @@ $releaseDetailPage = static function (string $edition, string $slug) {
]);
};
// Newsroom-Markenseite eines Unternehmens je Ausgabe: alle Meldungen der Firma.
$newsroomDetail = static function (string $edition, string $slug) {
$context = WebPortalContext::fromRequest();
$language = $context->language;
$portalValues = $context->portalValues;
$company = Company::query()
->withoutGlobalScope(PortalScope::class)
->whereIn('portal', $portalValues)
->where('is_active', true)
->where('slug', $slug)
->with(['contacts'])
->first();
if (! $company) {
abort(404);
}
$base = static fn (): Builder => PressRelease::query()
->withoutGlobalScope(PortalScope::class)
->where('company_id', $company->id)
->forPortalValues($portalValues)
->forLanguage($language)
->visibleInArchive();
// Keine öffentliche Newsroom-Seite ohne veröffentlichte Meldung.
if (! $base()->exists()) {
abort(404);
}
$latest = $base()->max('published_at');
$referenceNow = $latest ? Carbon::parse($latest) : now();
if ($referenceNow->gt(now())) {
$referenceNow = now();
}
$recentSince = $referenceNow->copy()->subDays(30);
$oldest = $base()->min('published_at');
$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();
$releases = $base()
->with($with)
->when($leadRelease, fn (Builder $query) => $query->whereKeyNot($leadRelease->getKey()))
->orderByDesc('published_at')
->paginate(10)
->withQueryString();
$mostReadReleases = $base()
->orderByDesc('hits')
->orderByDesc('published_at')
->limit(5)
->get(['id', 'slug', 'title', 'hits', 'portal', 'language']);
$companyFilter = static function (Builder $query) use ($company, $portalValues, $language): void {
$query
->withoutGlobalScope(PortalScope::class)
->where('company_id', $company->id)
->forPortalValues($portalValues)
->forLanguage($language)
->published();
};
$categories = Category::query()
->whereIn('portal', $portalValues)
->whereHas('pressReleases', fn (Builder $query) => $companyFilter($query))
->with(['translations' => fn ($query) => $query->where('locale', $language)])
->withCount(['pressReleases as releases_count' => fn (Builder $query) => $companyFilter($query)])
->orderByDesc('releases_count')
->limit(8)
->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->releases_count ?? 0),
];
})
->filter()
->values();
return view('web.newsroom', [
'company' => $company,
'referenceNow' => $referenceNow,
'leadRelease' => $leadRelease,
'releases' => $releases,
'mostReadReleases' => $mostReadReleases,
'categories' => $categories,
'newsroomStats' => [
'total' => $base()->count(),
'recent' => $base()->where('published_at', '>=', $recentSince)->count(),
'today' => $base()->whereDate('published_at', $referenceNow->toDateString())->count(),
'totalHits' => (int) $base()->sum('hits'),
'sinceYear' => $oldest ? (int) Carbon::parse($oldest)->format('Y') : null,
],
]);
};
// ---------------------------------------------------------------------------
// Bare Root: Publisher-Hub (pressekonto) oder Redirect auf die Default-Ausgabe.
// ---------------------------------------------------------------------------
@ -772,7 +664,7 @@ Route::get('{path}', function (string $path) use ($htmlRedirect) {
// ---------------------------------------------------------------------------
// Öffentliche Inhalte je Ausgabe (Sprache): /de/... und /en/...
// ---------------------------------------------------------------------------
Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(function () use ($applyWebDomainConfig, $webHomeData, $categoryPage, $releaseDetailPage, $newsroomDetail) {
Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(function () use ($applyWebDomainConfig, $webHomeData, $categoryPage, $releaseDetailPage) {
// Startseite je Ausgabe
Route::get('/', function (string $edition) use ($applyWebDomainConfig, $webHomeData) {
$domain = request()->getHost();
@ -807,7 +699,7 @@ Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(func
Route::get('veroeffentlichen', VeroeffentlichenController::class)->name('veroeffentlichen');
Route::get('suche', SucheController::class)->name('suche');
Route::get('newsrooms', NewsroomsController::class)->name('newsrooms');
Route::get('newsroom/{slug}', $newsroomDetail)->name('newsroom');
Route::get('newsroom/{slug}', NewsroomDetailController::class)->name('newsroom');
Route::view('api', 'web.api')->name('api');
Route::view('team', 'web.team')->name('team');
Route::view('partner', 'web.partner')->name('partner');