91 lines
2.1 KiB
PHP
91 lines
2.1 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class MenuItem extends Model
|
|
{
|
|
protected $fillable = [
|
|
'menu_id',
|
|
'parent_id',
|
|
'title',
|
|
'type',
|
|
'url',
|
|
'route',
|
|
'route_params',
|
|
'module',
|
|
'permission',
|
|
'icon',
|
|
'target',
|
|
'order',
|
|
'is_active',
|
|
];
|
|
|
|
protected $casts = [
|
|
'route_params' => 'array',
|
|
'is_active' => 'boolean',
|
|
'order' => 'integer',
|
|
];
|
|
|
|
public function menu(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Menu::class);
|
|
}
|
|
|
|
public function parent(): BelongsTo
|
|
{
|
|
return $this->belongsTo(MenuItem::class, 'parent_id');
|
|
}
|
|
|
|
public function children(): HasMany
|
|
{
|
|
return $this->hasMany(MenuItem::class, 'parent_id')->orderBy('order');
|
|
}
|
|
|
|
public function getUrlAttribute(): ?string
|
|
{
|
|
return match ($this->type) {
|
|
'link' => $this->attributes['url'],
|
|
'route' => $this->route ? route($this->route, $this->route_params ?? []) : null,
|
|
'module' => $this->module ? route("{$this->module}.index") : null,
|
|
default => null,
|
|
};
|
|
}
|
|
|
|
public function isVisibleToUser(?User $user = null): bool
|
|
{
|
|
if (!$this->is_active) {
|
|
return false;
|
|
}
|
|
|
|
$user = $user ?? Auth::user();
|
|
|
|
if (!$user) {
|
|
return !$this->permission && !$this->module;
|
|
}
|
|
|
|
if ($user->hasRole('admin')) {
|
|
return true;
|
|
}
|
|
|
|
if ($this->permission) {
|
|
return $user->can($this->permission);
|
|
}
|
|
|
|
if ($this->module) {
|
|
return $user->can("{$this->module}.view");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function getVisibleChildren(?User $user = null): \Illuminate\Support\Collection
|
|
{
|
|
return $this->children->filter(fn (MenuItem $item) => $item->isVisibleToUser($user));
|
|
}
|
|
}
|