Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
72.73% covered (warning)
72.73%
8 / 11
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Menu
72.73% covered (warning)
72.73%
8 / 11
75.00% covered (warning)
75.00%
3 / 4
5.51
0.00% covered (danger)
0.00%
0 / 1
 auditExcept
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 items
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 tree
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 booted
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace App\Models;
4
5use App\Service\CacheService;
6use App\Support\Auditable;
7use Illuminate\Database\Eloquent\Factories\HasFactory;
8use Illuminate\Database\Eloquent\Model;
9use Illuminate\Database\Eloquent\Relations\HasMany;
10use Illuminate\Support\Str;
11
12class Menu extends Model
13{
14    use Auditable, HasFactory;
15
16    protected $fillable = ['name', 'handle', 'location'];
17
18    protected function auditExcept(): array
19    {
20        return ['handle'];
21    }
22
23    public function items(): HasMany
24    {
25        return $this->hasMany(MenuItem::class)->orderBy('sort_order');
26    }
27
28    /** Top-level items with their children eager-loaded, ordered. */
29    public function tree(): HasMany
30    {
31        return $this->items()
32            ->whereNull('parent_id')
33            ->with(['children' => fn ($q) => $q->orderBy('sort_order')]);
34    }
35
36    protected static function booted(): void
37    {
38        static::saving(function (Menu $menu) {
39            if (blank($menu->handle)) {
40                $menu->handle = Str::slug($menu->name);
41            }
42        });
43
44        static::saved(fn () => CacheService::forgetMenusBuilder());
45        static::deleted(fn () => CacheService::forgetMenusBuilder());
46    }
47}