|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace PhpCollective\MenuMaker; |
|
4
|
|
|
|
|
5
|
|
|
use Cache; |
|
6
|
|
|
use Route; |
|
7
|
|
|
use Kalnoy\Nestedset\Collection; |
|
8
|
|
|
use PhpCollective\MenuMaker\Storage\Role; |
|
9
|
|
|
use PhpCollective\MenuMaker\Storage\Menu; |
|
10
|
|
|
|
|
11
|
|
|
trait MenuMaker |
|
12
|
|
|
{ |
|
13
|
|
|
protected $section; |
|
14
|
|
|
|
|
15
|
|
|
/** |
|
16
|
|
|
* The group that associates with the group. |
|
17
|
|
|
*/ |
|
18
|
|
|
public function roles() |
|
19
|
|
|
{ |
|
20
|
|
|
return $this->belongsToMany(Role::class, 'pcmm_role_user', 'user_id', 'role_id'); |
|
|
|
|
|
|
21
|
|
|
} |
|
22
|
|
|
|
|
23
|
|
|
public function menus($alias) |
|
24
|
|
|
{ |
|
25
|
|
|
$this->section = Menu::whereAlias($alias)->first(); |
|
26
|
|
|
|
|
27
|
|
|
if (! $this->section) { |
|
28
|
|
|
return collect([]); |
|
29
|
|
|
} |
|
30
|
|
|
return $this->getMenuItemsWithActive(); |
|
31
|
|
|
|
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
protected function getMenuItemsWithActive() |
|
35
|
|
|
{ |
|
36
|
|
|
$currentRoute = Route::currentRouteName(); |
|
37
|
|
|
$currentPath = request()->path(); |
|
38
|
|
|
$menus = $this->getMenuItems(); |
|
39
|
|
|
|
|
40
|
|
|
$traverse = function ($menus) use (&$traverse, $currentRoute, $currentPath) { |
|
41
|
|
|
$checked = collect([]); |
|
42
|
|
|
foreach ($menus as $key => $menu) { |
|
43
|
|
|
$menu['children'] = $traverse($menu['children'], $currentRoute, $currentPath); |
|
44
|
|
|
if((is_array($menu['routes']) && in_array($currentRoute, $menu['routes'])) |
|
45
|
|
|
|| $currentPath === $menu['link'] |
|
46
|
|
|
|| $menu['children']->where('active', true)->count()) |
|
47
|
|
|
{ |
|
48
|
|
|
$menu['active'] = true; |
|
49
|
|
|
} |
|
50
|
|
|
$checked->put($key, new MenuItem($menu)); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
return $checked; |
|
54
|
|
|
}; |
|
55
|
|
|
|
|
56
|
|
|
return $traverse($menus); |
|
57
|
|
|
} |
|
58
|
|
|
|
|
59
|
|
|
protected function getMenuItems() |
|
60
|
|
|
{ |
|
61
|
|
|
return Cache::rememberForever('menus.section.' . optional($this->section)->id . '.user.' . $this->id, function () { |
|
62
|
|
|
return $this->admin() |
|
63
|
|
|
? $this->getAdminMenuItems() |
|
64
|
|
|
: $this->getUserMenuItems(); |
|
65
|
|
|
}); |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
private function getAdminMenuItems() |
|
69
|
|
|
{ |
|
70
|
|
|
$this->section->load([ |
|
71
|
|
|
'descendants' => function ($query) { |
|
72
|
|
|
$query->visible(); |
|
73
|
|
|
} |
|
74
|
|
|
]); |
|
75
|
|
|
|
|
76
|
|
|
return self::buildTree($this->section->descendants, $this->section->id); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
private function getUserMenuItems() |
|
80
|
|
|
{ |
|
81
|
|
|
$this->section->load([ |
|
82
|
|
|
'descendants' => function ($query) { |
|
83
|
|
|
$query->with([ |
|
84
|
|
|
'ancestors' => function ($query) { |
|
85
|
|
|
$query->descendantsOf($this->section); |
|
86
|
|
|
} |
|
87
|
|
|
])->select('pcmm_menus.*') |
|
88
|
|
|
->leftJoin('pcmm_menu_role', 'pcmm_menus.id', '=', 'pcmm_menu_role.menu_id') |
|
89
|
|
|
->leftJoin('pcmm_roles', 'pcmm_menu_role.role_id', '=', 'pcmm_roles.id') |
|
90
|
|
|
->leftJoin('pcmm_role_user', 'pcmm_roles.id', '=', 'pcmm_role_user.role_id') |
|
91
|
|
|
->leftJoin($this->getTable(), 'pcmm_role_user.user_id', '=', $this->getTable() . '.id') |
|
|
|
|
|
|
92
|
|
|
->visible() |
|
93
|
|
|
->where(function ($query) { |
|
94
|
|
|
$query->public() |
|
95
|
|
|
->orWhere(function ($query) { |
|
96
|
|
|
$query->where('pcmm_menus.privilege', 'PROTECTED') |
|
97
|
|
|
->where('pcmm_roles.is_active', true) |
|
98
|
|
|
->where($this->getTable() . '.id', $this->id); |
|
99
|
|
|
}); |
|
100
|
|
|
}); |
|
101
|
|
|
} |
|
102
|
|
|
]); |
|
103
|
|
|
|
|
104
|
|
|
$items = $this->section->descendants->reject(function ($item) { |
|
105
|
|
|
return $item->ancestors->contains('privilege', 'PRIVATE') |
|
106
|
|
|
|| $item->ancestors->contains('visible', false); |
|
107
|
|
|
}); |
|
108
|
|
|
|
|
109
|
|
|
$menus = collect([]); |
|
110
|
|
|
foreach ($items as $last) { |
|
111
|
|
|
$item = self::buildPartialTree($last->ancestors, $last); |
|
112
|
|
|
if ($menus->has($item['id'])) { |
|
113
|
|
|
$menus = self::mergeTree($menus, $item); |
|
114
|
|
|
} else { |
|
115
|
|
|
$menus->put($item['id'], $item); |
|
116
|
|
|
} |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
return $menus; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
protected static function mergeTree($menus, $item) |
|
123
|
|
|
{ |
|
124
|
|
|
if (isset($menus[$item['id']])) { |
|
125
|
|
|
$childItem = $item['children']->first(); |
|
126
|
|
|
if ($menus[$item['id']]['children']->has($childItem['id'])) { |
|
127
|
|
|
$children = $menus[$item['id']]['children']; |
|
128
|
|
|
$menus[$item['id']]['children'] = self::mergeTree($children, $childItem); |
|
129
|
|
|
} else { |
|
130
|
|
|
$menus[$item['id']]['children']->put($childItem['id'], $childItem); |
|
131
|
|
|
} |
|
132
|
|
|
} |
|
133
|
|
|
return $menus; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
protected static function buildPartialTree(Collection $nodes, $lastChild) |
|
137
|
|
|
{ |
|
138
|
|
|
if ($nodes->count()) { |
|
139
|
|
|
$node = $nodes->shift(); |
|
140
|
|
|
$element = self::prepareMenuItem($node); |
|
141
|
|
|
$child = $nodes->count() |
|
142
|
|
|
? self::buildPartialTree($nodes, $lastChild) |
|
143
|
|
|
: self::prepareMenuItem($lastChild); |
|
144
|
|
|
|
|
145
|
|
|
$element['children']->put( |
|
146
|
|
|
$child['id'], $child |
|
147
|
|
|
); |
|
148
|
|
|
} else { |
|
149
|
|
|
$element = self::prepareMenuItem($lastChild); |
|
150
|
|
|
} |
|
151
|
|
|
return $element; |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
protected static function buildTree(Collection $nodes, $parent_id = 0) |
|
155
|
|
|
{ |
|
156
|
|
|
$branch = collect([]); |
|
157
|
|
|
|
|
158
|
|
|
foreach ($nodes as $node) { |
|
159
|
|
|
if ($node->parent_id == $parent_id) { |
|
160
|
|
|
|
|
161
|
|
|
$element = self::prepareMenuItem($node); |
|
162
|
|
|
|
|
163
|
|
|
$children = self::buildTree($node->children()->visible()->get(), $node->id); |
|
164
|
|
|
if ($children) { |
|
165
|
|
|
$element['children'] = $children; |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
$branch->put($element['id'], $element); |
|
169
|
|
|
} |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
return $branch; |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
protected static function prepareMenuItem(Menu $node) |
|
176
|
|
|
{ |
|
177
|
|
|
return [ |
|
178
|
|
|
'id' => $node->id, |
|
179
|
|
|
'name' => $node->name, |
|
180
|
|
|
'alias' => $node->alias, |
|
181
|
|
|
'routes' => $node->routes, |
|
182
|
|
|
'link' => $node->link, |
|
183
|
|
|
'icon' => $node->icon, |
|
184
|
|
|
'class' => $node->class, |
|
185
|
|
|
'attr' => $node->attr, |
|
186
|
|
|
'active' => false, |
|
187
|
|
|
'children' => collect([]) |
|
188
|
|
|
]; |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
public function admin() |
|
192
|
|
|
{ |
|
193
|
|
|
return $this->roles()->admin()->exists(); |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
public function approve($alias) |
|
197
|
|
|
{ |
|
198
|
|
|
return $this->admin() || $this->whereHas('roles.menus', function ($query) use ($alias) { |
|
|
|
|
|
|
199
|
|
|
$query->whereAlias($alias); |
|
200
|
|
|
})->exists(); |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
public function authorize($request) |
|
204
|
|
|
{ |
|
205
|
|
|
$route = explode_route($request->route()); |
|
206
|
|
|
return $this->whereHas('roles.menus.permissions', function ($query) use ($route) { |
|
207
|
|
|
return $query->ofRoute($route); |
|
208
|
|
|
})->exists(); |
|
209
|
|
|
} |
|
210
|
|
|
} |
|
211
|
|
|
|