*/ public function build(WebPortalContext $context, string $slug): array { $portalValues = $context->portalValues; $language = $context->language; $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) ->forPortalValues($portalValues) ->forLanguage($language) ->visibleInArchive() ->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 ->forPortalValues($portalValues) ->forLanguage($language) ->published() ->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 ->forPortalValues($portalValues) ->forLanguage($language) ->published(); $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 [ 'category' => $category, 'referenceNow' => $referenceNow, 'leadRelease' => $leadRelease, 'topReleases' => $topReleases, 'feedReleases' => $feedReleases, 'mostReadReleases' => $mostReadReleases, 'categoryStats' => $stats, 'topNewsrooms' => $topNewsrooms, 'subCategories' => $subCategories, 'relatedCategories' => $relatedCategories, ]; } }