@php /** * Reusable blog sidebar, composed of independent widgets: * featured · search · categories · recent · popular · newsletter * * Pass $widgets to render only a subset, in order (e.g. the blog-2 right column * uses ['featured','categories','search']). Omit it to render the full default * set. Data ($cats/$recent/$popular/$featured) may be injected by the controller; * each widget self-fetches as a fallback so the partial is safe standalone. * * @var string $active selected category slug (optional) * @var array|null $widgets ordered widget keys to render (optional) * @var array|null $featured featured post row for the Featured card (optional) */ $activeCat = $active ?? (request()->query('cat') ?? ''); $activeTag = $activeTag ?? (request()->query('tag') ?? ''); $q = is_scalar($qIn = request()->query('q')) ? (string) $qIn : ''; $widgets = $widgets ?? ['search', 'categories', 'recent', 'popular', 'newsletter']; // Unique suffix so field ids never collide if two sidebars share a page. $uid = $uid ?? substr(md5(implode(',', $widgets)), 0, 6); // Categories may be injected by the controller; otherwise self-fetch. $cats = $cats ?? \Illuminate\Support\Facades\DB::table('blog_categories') // The published test sits on the JOIN, not in a WHERE: a category with no // published post must still be listed, with a count of zero. ->leftJoin('blog_posts', function ($join): void { $join->on('blog_posts.blog_category_id', '=', 'blog_categories.id') ->where('blog_posts.status', '=', 'published'); }) ->groupBy('blog_categories.id', 'blog_categories.name', 'blog_categories.slug') ->orderBy('blog_categories.name') ->select('blog_categories.name', 'blog_categories.slug') // select() is prefixed by the builder; a raw fragment is NOT, so spell it out. ->selectRaw('COUNT(' . \Illuminate\Support\Facades\DB::getTablePrefix() . 'blog_posts.id) AS post_count') ->get() ->map(static fn (object $r): array => (array) $r) ->all(); $recent = $recent ?? (new \App\Models\BlogPost())->published(5); // Popular posts: most-viewed published posts (template "Popular Posts" widget). $popular = $popular ?? \App\Models\BlogPost::query() ->where('status', 'published') ->orderByDesc('views') ->orderByDesc('published_at') ->limit(4) ->get(['title', 'slug', 'featured_image', 'published_at', 'views']) ->all(); $featured = $featured ?? null; // Optional widgets (controller-provided): tag cloud + featured restaurants. They // render only when data is passed, so the partial stays safe standalone. $tagCloud = $tagCloud ?? []; $featuredRestaurants = $featuredRestaurants ?? []; // Crisp 100x100 niche thumbnail — single source of truth shared with the controller. $thumb = static fn (\App\Models\BlogPost|array $row): string => \App\Http\Controllers\Public\BlogController::thumbFor($row); @endphp