diff --git a/app/Http/Controllers/Web/NewsroomDetailController.php b/app/Http/Controllers/Web/NewsroomDetailController.php new file mode 100644 index 00000000..195e1169 --- /dev/null +++ b/app/Http/Controllers/Web/NewsroomDetailController.php @@ -0,0 +1,18 @@ +build(WebPortalContext::fromRequest(), $slug)); + } +} diff --git a/app/Services/Web/NewsroomDetailPageData.php b/app/Services/Web/NewsroomDetailPageData.php new file mode 100644 index 00000000..a8674b60 --- /dev/null +++ b/app/Services/Web/NewsroomDetailPageData.php @@ -0,0 +1,131 @@ + + */ + public function build(WebPortalContext $context, string $slug): array + { + $portalValues = $context->portalValues; + $language = $context->language; + + $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 [ + '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, + ], + ]; + } +} diff --git a/routes/web.php b/routes/web.php index f3de068e..471fe584 100644 --- a/routes/web.php +++ b/routes/web.php @@ -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');