Gebuendelt, da ueber gemeinsame lang-/Service-Dateien verschraenkt: - Kontakt-Nachrichten: contact_messages-Tabelle + Model/Enums/Factory, Admin-Queue (livewire/admin/contact-messages), ContactController persistiert das Anliegen zusaetzlich zur Brand-Mail - Page-Data-Cache (Services/Web/*PageData) + web-archive-Indizes auf press_releases - Validierungs-Feedback + Company-Portal-Restriction (Feature-Tests) - i18n-Auslagerung lang/de|en (auth, passwords, validation, static) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.6 KiB
PHP
70 lines
2.6 KiB
PHP
<?php
|
||
|
||
namespace App\Support;
|
||
|
||
use App\Enums\Portal;
|
||
use App\Enums\PressReleaseStatus;
|
||
use App\Models\Category;
|
||
use App\Scopes\PortalScope;
|
||
use Illuminate\Database\Eloquent\Builder;
|
||
use Illuminate\Support\Collection;
|
||
|
||
/**
|
||
* Liefert die Rubriken-Navigation der aktiven Ausgabe (Portal × Sprache).
|
||
*
|
||
* Es gibt bewusst keine separate Rubriken-Übersichtsseite: Die Navigation
|
||
* führt direkt auf die jeweilige Kategorieseite (`route('kategorie', …)`),
|
||
* auf der die Pressemitteilungen dieser Rubrik erscheinen.
|
||
*/
|
||
class CategoryNavigation
|
||
{
|
||
/**
|
||
* Top-Level-Rubriken der aktiven Ausgabe als Navigationsitems.
|
||
*
|
||
* Sortiert nach Anzahl veröffentlichter Pressemitteilungen; `null` als
|
||
* Limit liefert alle Rubriken (z. B. für das „Mehr“-Dropdown im Header).
|
||
*
|
||
* @return Collection<int, array{label:string, slug:string, href:string}>
|
||
*/
|
||
public static function items(?int $limit = 9): Collection
|
||
{
|
||
$portal = Portal::tryFrom((string) config('app.theme')) ?? Portal::Businessportal24;
|
||
$language = app()->getLocale();
|
||
$portalValues = [$portal->value, Portal::Both->value];
|
||
|
||
return Category::query()
|
||
->with(['translations' => fn ($query) => $query->where('locale', $language)])
|
||
->withCount([
|
||
'pressReleases as published_count' => function (Builder $query) use ($portalValues, $language): void {
|
||
$query
|
||
->withoutGlobalScope(PortalScope::class)
|
||
->whereIn('portal', $portalValues)
|
||
->where('status', PressReleaseStatus::Published)
|
||
->where('language', $language)
|
||
->whereNotNull('published_at');
|
||
},
|
||
])
|
||
->whereIn('portal', $portalValues)
|
||
->where('is_active', true)
|
||
->whereNull('parent_id')
|
||
->orderByDesc('published_count')
|
||
->orderBy('id')
|
||
->when($limit !== null, fn (Builder $query) => $query->limit($limit))
|
||
->get()
|
||
->map(function (Category $category): ?array {
|
||
$translation = $category->translations->first();
|
||
|
||
if (! $translation || ! $translation->slug) {
|
||
return null;
|
||
}
|
||
|
||
return [
|
||
'label' => $translation->name,
|
||
'slug' => $translation->slug,
|
||
'href' => route('kategorie', ['slug' => $translation->slug]),
|
||
];
|
||
})
|
||
->filter()
|
||
->values();
|
||
}
|
||
}
|