Web: Boost-Platzierung auf Start- und Branchenseite ausspielen
Geboostete PMs besetzen Lead- und Top-Slots vor der Chronologie (HomePageData/CategoryPageData ueber boosted()-Scope) und tragen das Badge "Top-Platzierung". Abgelaufene Boosts wirken nicht. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0665553c88
commit
df6b24518c
10 changed files with 183 additions and 19 deletions
|
|
@ -95,18 +95,36 @@ class CategoryPageData
|
|||
'images' => fn ($query) => $query->orderByDesc('is_preview')->orderBy('sort_order')->limit(1),
|
||||
];
|
||||
|
||||
$leadRelease = $base()->with($with)->orderByDesc('published_at')->first();
|
||||
// Gebuchte Boosts (Decision-Update §2.2): geboostete PMs der Branche
|
||||
// besetzen Lead- und Top-Plätze vor der Chronologie; die Views
|
||||
// markieren sie über `boostedIds`.
|
||||
$boostedReleases = $base()
|
||||
->boosted()
|
||||
->with($with)
|
||||
->orderByDesc('published_at')
|
||||
->limit(3)
|
||||
->get();
|
||||
$boostedIds = $boostedReleases->modelKeys();
|
||||
|
||||
$leadRelease = $boostedReleases->first()
|
||||
?? $base()->with($with)->orderByDesc('published_at')->first();
|
||||
|
||||
// Ohne mediumText-Spalte `text`: Top-/Feed-Listen rendern nur
|
||||
// Titel/Meta, der Volltext wäre unnötiger I/O.
|
||||
$listColumns = ['id', 'portal', 'language', 'slug', 'title', 'category_id', 'company_id', 'published_at', 'content_score'];
|
||||
|
||||
$topReleases = $base()
|
||||
->with($with)
|
||||
->when($leadRelease, fn (Builder $query) => $query->whereKeyNot($leadRelease->getKey()))
|
||||
->orderByDesc('published_at')
|
||||
->limit(2)
|
||||
->get($listColumns);
|
||||
$topBoosted = $boostedReleases->slice(1)->take(2)->values();
|
||||
$topChronoSlots = 2 - $topBoosted->count();
|
||||
$topReleases = $topChronoSlots > 0
|
||||
? $base()
|
||||
->with($with)
|
||||
->when($leadRelease, fn (Builder $query) => $query->whereKeyNot($leadRelease->getKey()))
|
||||
->when($boostedIds !== [], fn (Builder $query) => $query->whereNotIn('id', $boostedIds))
|
||||
->orderByDesc('published_at')
|
||||
->limit($topChronoSlots)
|
||||
->get($listColumns)
|
||||
: collect();
|
||||
$topReleases = $topBoosted->concat($topReleases)->values();
|
||||
|
||||
$excludeIds = collect([$leadRelease?->getKey()])->merge($topReleases->modelKeys())->filter()->all();
|
||||
|
||||
|
|
@ -249,6 +267,7 @@ class CategoryPageData
|
|||
'leadRelease' => $leadRelease,
|
||||
'topReleases' => $topReleases,
|
||||
'feedReleases' => $feedReleases,
|
||||
'boostedIds' => $boostedIds,
|
||||
'mostReadReleases' => $mostReadReleases,
|
||||
'categoryStats' => $stats,
|
||||
'topNewsrooms' => $topNewsrooms,
|
||||
|
|
|
|||
|
|
@ -72,19 +72,37 @@ class HomePageData
|
|||
->oldest('published_at')
|
||||
->value('published_at');
|
||||
|
||||
$leadRelease = $publishedQuery()
|
||||
// Gebuchte Boosts (Decision-Update §2.2): geboostete PMs besetzen die
|
||||
// Top-Positionen vor der Chronologie — die jüngste als Lead, weitere
|
||||
// in der Seitenleiste. Die Views markieren sie über `boostedIds`.
|
||||
$boostedReleases = $publishedQuery()
|
||||
->boosted()
|
||||
->with($with)
|
||||
->orderByDesc('published_at')
|
||||
->first();
|
||||
->limit(5)
|
||||
->get();
|
||||
$boostedIds = $boostedReleases->modelKeys();
|
||||
|
||||
$leadRelease = $boostedReleases->first()
|
||||
?? $publishedQuery()
|
||||
->with($with)
|
||||
->orderByDesc('published_at')
|
||||
->first();
|
||||
|
||||
// Ohne mediumText-Spalte `text`: die Seitenleisten-Teaser rendern nur
|
||||
// Titel/Meta, der Volltext wäre unnötiger I/O.
|
||||
$sideReleases = $publishedQuery()
|
||||
->with($with)
|
||||
->when($leadRelease, fn (Builder $query) => $query->where('id', '!=', $leadRelease->id))
|
||||
->orderByDesc('published_at')
|
||||
->limit(4)
|
||||
->get(['id', 'portal', 'language', 'slug', 'title', 'category_id', 'company_id', 'published_at', 'content_score']);
|
||||
$sideBoosted = $boostedReleases->slice(1)->take(4)->values();
|
||||
$sideChronoSlots = 4 - $sideBoosted->count();
|
||||
$sideReleases = $sideChronoSlots > 0
|
||||
? $publishedQuery()
|
||||
->with($with)
|
||||
->when($leadRelease, fn (Builder $query) => $query->where('id', '!=', $leadRelease->id))
|
||||
->when($boostedIds !== [], fn (Builder $query) => $query->whereNotIn('id', $boostedIds))
|
||||
->orderByDesc('published_at')
|
||||
->limit($sideChronoSlots)
|
||||
->get(['id', 'portal', 'language', 'slug', 'title', 'category_id', 'company_id', 'published_at', 'content_score'])
|
||||
: collect();
|
||||
$sideReleases = $sideBoosted->concat($sideReleases)->values();
|
||||
|
||||
$mostReadReleases = $publishedQuery()
|
||||
->orderByDesc('hits')
|
||||
|
|
@ -244,6 +262,7 @@ class HomePageData
|
|||
return [
|
||||
'leadRelease' => $leadRelease,
|
||||
'sideReleases' => $sideReleases,
|
||||
'boostedIds' => $boostedIds,
|
||||
'mostReadReleases' => $mostReadReleases,
|
||||
'activeNewsrooms' => $activeNewsrooms,
|
||||
'industryIndex' => $industryIndex,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue