Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
WidgetService
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
6 / 6
7
100.00% covered (success)
100.00%
1 / 1
 types
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 make
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 area
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 areaHasWidgets
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Services\Builder;
4
5use App\Models\Widget;
6use App\Service\CacheService;
7use App\Widgets\WidgetContract;
8use Illuminate\Support\Collection;
9
10/**
11 * The widget/block registry + area resolver. Widget *types* come from
12 * config/widgets.php; placed widgets live in the `widgets` table and are
13 * rendered on the storefront via <x-widget-area name="…">.
14 */
15class WidgetService
16{
17    /** @var array<string, WidgetContract>|null key => handler */
18    private ?array $types = null;
19
20    /** @return array<string, WidgetContract> */
21    public function types(): array
22    {
23        return $this->types ??= collect(config('widgets', []))
24            ->map(fn ($class) => app($class))
25            ->keyBy(fn (WidgetContract $w) => $w->key())
26            ->all();
27    }
28
29    public function make(string $type): ?WidgetContract
30    {
31        return $this->types()[$type] ?? null;
32    }
33
34    public function hasType(string $type): bool
35    {
36        return isset($this->types()[$type]);
37    }
38
39    /** Placed widgets for an area, ordered. Optionally only the enabled ones. */
40    public function area(string $area, bool $onlyEnabled = true): Collection
41    {
42        $all = CacheService::remember(CacheService::KEY_WIDGETS, function () {
43            return Widget::query()->orderBy('sort_order')->get()->groupBy('area');
44        });
45
46        return collect($all[$area] ?? [])
47            ->when($onlyEnabled, fn ($c) => $c->where('enabled', true))
48            ->values();
49    }
50
51    /** Rendered HTML for a whole area. */
52    public function render(string $area): string
53    {
54        return $this->area($area)
55            ->map(fn (Widget $w) => $this->hasType($w->type) ? $w->render() : '')
56            ->implode('');
57    }
58
59    public function areaHasWidgets(string $area): bool
60    {
61        return $this->area($area)->isNotEmpty();
62    }
63}