MenuController::discovery()   F
last analyzed

Complexity

Conditions 21
Paths 318

Size

Total Lines 82
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 21
eloc 59
c 1
b 0
f 0
nc 318
nop 0
dl 0
loc 82
rs 1.8583

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Date: 2019/2/25 Time: 14:49
4
 *
5
 * @author  Eddy <[email protected]>
6
 * @version v1.0.0
7
 */
8
9
namespace App\Http\Controllers\Admin;
10
11
use App\Events\MenuUpdated;
12
use App\Http\Controllers\Controller;
13
use App\Http\Requests\Admin\MenuRequest;
14
use App\Model\Admin\Menu;
15
use App\Repository\Admin\MenuRepository;
16
use Illuminate\Database\QueryException;
17
use Illuminate\Http\Request;
18
use Illuminate\Routing\Exceptions\UrlGenerationException;
19
use Illuminate\Support\Str;
20
use Illuminate\Support\Facades\Route;
21
22
class MenuController extends Controller
23
{
24
    protected $formNames = [
25
        'name', 'pid', 'status', 'order', 'route', 'group', 'remark', 'url', 'is_lock_name', 'route_params'
26
    ];
27
28
    public function __construct()
29
    {
30
        parent::__construct();
31
32
        $this->breadcrumb[] = ['title' => '菜单管理', 'url' => route('admin::menu.index')];
33
    }
34
35
    /**
36
     * 菜单管理-菜单列表
37
     *
38
     */
39
    public function index()
40
    {
41
        $this->breadcrumb[] = ['title' => '菜单列表', 'url' => ''];
42
        return view('admin.menu.index', ['breadcrumb' => $this->breadcrumb]);
43
    }
44
45
    /**
46
     * 菜单管理-菜单列表数据
47
     *
48
     * @param Request $request
49
     * @return array
50
     */
51
    public function list(Request $request)
52
    {
53
        $perPage = (int) $request->get('limit', 50);
54
        $action = $request->get('action');
55
        $this->formNames[] = 'created_at';
56
        $condition = $request->only($this->formNames);
57
58
        if (isset($condition['pid'])) {
59
            $condition['pid'] = ['=', $condition['pid']];
60
        } else {
61
            if ($action !== 'search') {
62
                $condition['pid'] = ['=', 0];
63
            }
64
        }
65
66
        $data = MenuRepository::list($perPage, $condition);
67
68
        return $data;
69
    }
70
71
    /**
72
     * 菜单管理-新增菜单
73
     *
74
     */
75
    public function create()
76
    {
77
        $this->breadcrumb[] = ['title' => '新增菜单', 'url' => ''];
78
        return view('admin.menu.add', ['breadcrumb' => $this->breadcrumb]);
79
    }
80
81
    /**
82
     * 菜单管理-保存菜单
83
     *
84
     * @param MenuRequest $request
85
     * @return array
86
     */
87
    public function save(MenuRequest $request)
88
    {
89
        try {
90
            MenuRepository::add(array_merge($request->only($this->formNames), ['guard_name' => 'admin']));
91
            event(new MenuUpdated());
92
            return [
93
                'code' => 0,
94
                'msg' => '新增成功',
95
                'redirect' => true
96
            ];
97
        } catch (QueryException $e) {
98
            return [
99
                'code' => 1,
100
                'msg' => '新增失败:' . (Str::contains($e->getMessage(), 'Duplicate entry') ? '当前菜单已存在' : '其它错误'),
101
                'redirect' => false
102
            ];
103
        }
104
    }
105
106
    /**
107
     * 菜单管理-编辑菜单
108
     *
109
     * @param int $id
110
     */
111
    public function edit($id)
112
    {
113
        $this->breadcrumb[] = ['title' => '编辑菜单', 'url' => ''];
114
115
        $model = MenuRepository::find($id);
116
        return view('admin.menu.add', ['id' => $id, 'model' => $model, 'breadcrumb' => $this->breadcrumb]);
117
    }
118
119
    /**
120
     * 菜单管理-更新菜单
121
     *
122
     * @param MenuRequest $request
123
     * @param int $id
124
     * @return array
125
     */
126
    public function update(MenuRequest $request, $id)
127
    {
128
        $data = array_merge(
129
            [
130
                'is_lock_name' => Menu::UNLOCK_NAME,
131
                'status' => Menu::STATUS_DISABLE
132
            ],
133
            $request->only($this->formNames)
134
        );
135
136
        try {
137
            MenuRepository::update($id, $data);
138
            event(new MenuUpdated());
139
            return [
140
                'code' => 0,
141
                'msg' => '编辑成功',
142
                'redirect' => true
143
            ];
144
        } catch (QueryException $e) {
145
            return [
146
                'code' => 1,
147
                'msg' => '编辑失败:' . (Str::contains($e->getMessage(), 'Duplicate entry') ? '当前菜单已存在' : '其它错误'),
148
                'redirect' => false
149
            ];
150
        }
151
    }
152
153
    /**
154
     * 菜单管理-删除菜单
155
     *
156
     * @param int $id
157
     * @return array
158
     */
159
    public function delete($id)
160
    {
161
        try {
162
            MenuRepository::delete($id);
163
            event(new MenuUpdated());
164
            return [
165
                'code' => 0,
166
                'msg' => '删除成功',
167
                'redirect' => true
168
            ];
169
        } catch (\RuntimeException $e) {
170
            return [
171
                'code' => 1,
172
                'msg' => '删除失败:' . $e->getMessage(),
173
                'redirect' => false
174
            ];
175
        }
176
    }
177
178
    /**
179
     * 菜单管理-自动更新菜单
180
     *
181
     * @return array
182
     * @throws \ReflectionException
183
     */
184
    public function discovery()
185
    {
186
        $addNum = 0;
187
        $updateNum = 0;
188
189
        foreach (Route::getRoutes()->getRoutesByName() as $k => $v) {
190
            if (Str::startsWith($k, 'admin::')) {
191
                // 取方法的第一行注释作为菜单的名称、分组名。格式:分组名称-菜单名称。未写分组名称,则注释直接作为菜单名称。未写注释则选用uri作为菜单名称。
192
                $action = explode('@', $v->getActionName());
193
                if (!method_exists($action[0], $action[1])) {
194
                    continue;
195
                }
196
                $reflection = new \ReflectionMethod($action[0], $action[1]);
197
                $comment = trim(array_get(explode("\n", $reflection->getDocComment()), 1, ''), " \t\n\r\0\x0B*");
0 ignored issues
show
Bug introduced by
It seems like array_get(explode(' ', $...etDocComment()), 1, '') can also be of type string[]; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

197
                $comment = trim(/** @scrutinizer ignore-type */ array_get(explode("\n", $reflection->getDocComment()), 1, ''), " \t\n\r\0\x0B*");
Loading history...
198
                if ($comment === '') {
199
                    $data['name'] = $v->uri;
200
                    $data['group'] = '';
201
                } else {
202
                    if (Str::contains($comment, '-')) {
203
                        $arr = explode('-', $comment);
204
                        $data['name'] = trim($arr[1]);
205
                        $data['group'] = trim($arr[0]);
206
                    } else {
207
                        $data['name'] = trim($comment);
208
                        $data['group'] = '';
209
                    }
210
                }
211
212
                $data['route'] = $k;
213
                $data['guard_name'] = 'admin';
214
                if (in_array('GET', $v->methods) && !Str::contains($v->uri, '{')) {
215
                    $data['status'] = Menu::STATUS_ENABLE;
216
                } else {
217
                    $data['status'] = Menu::STATUS_DISABLE;
218
                }
219
                try {
220
                    $data['url'] = route($k, [], false);
221
                } catch (UrlGenerationException $e) {
222
                    $data['url'] = '';
223
                }
224
225
                try {
226
                    $model = MenuRepository::exist($k);
227
                    if ($model) {
228
                        if (($model->is_lock_name == Menu::UNLOCK_NAME &&
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($model->is_lock_name ==...el->url != $data['url'], Probably Intended Meaning: $model->is_lock_name == ...l->url != $data['url'])
Loading history...
229
                            ($model->name != $data['name'] || $model->group != $data['group'])) ||
230
                                ($data['url'] != '' && $model->url != $data['url'])) {
231
                            unset($data['status']);
232
                            MenuRepository::update($model->id, $data);
233
                            $updateNum++;
234
                        }
235
                    } else {
236
                        MenuRepository::add($data);
237
                        $addNum++;
238
                    }
239
                } catch (QueryException $e) {
240
                    if ($addNum > 0 || $updateNum > 0) {
241
                        event(new MenuUpdated());
242
                    }
243
244
                    if ($e->getCode() == 23000) {
245
                        return [
246
                            'code' => 1,
247
                            'msg' => "唯一性冲突:请检查菜单名称或路由名称。name: {$data['name']} route: {$data['route']}",
248
                        ];
249
                    } else {
250
                        return [
251
                            'code' => 2,
252
                            'msg' => $e->getMessage(),
253
                        ];
254
                    }
255
                }
256
            }
257
        }
258
259
        if ($addNum > 0 || $updateNum > 0) {
260
            event(new MenuUpdated());
261
        }
262
        return [
263
            'code' => 0,
264
            'msg' => "更新成功。新增菜单数:{$addNum},更新菜单数:{$updateNum}。",
265
            'redirect' => true
266
        ];
267
    }
268
269
    /**
270
     * 菜单管理-批量操作
271
     */
272
    public function batch(Request $request)
273
    {
274
        $type = $request->input('type', '');
275
        $ids = $request->input('ids');
276
        if (!is_array($ids)) {
277
            return [
278
                'code' => 1,
279
                'msg' => '参数错误'
280
            ];
281
        }
282
        $ids = array_map(function ($item) {
283
            return intval($item);
284
        }, $ids);
285
286
        $message = '';
287
        switch ($type) {
288
            case 'disable':
289
                Menu::query()->whereIn('id', $ids)->update(['status' => Menu::STATUS_DISABLE]);
290
                break;
291
            case 'enable':
292
                Menu::query()->whereIn('id', $ids)->update(['status' => Menu::STATUS_ENABLE]);
293
                break;
294
            case 'delete':
295
                // 过滤掉有子项目的
296
                $hasChildren = array_unique(Menu::query()->whereIn('pid', $ids)->pluck('pid')->toArray());
297
                $deleteIds = array_diff($ids, $hasChildren);
298
                if (!empty($deleteIds)) {
299
                    Menu::query()->whereIn('id', $deleteIds)->delete();
300
                }
301
                if (!empty($hasChildren)) {
302
                    $message = ' 以下菜单ID因有子菜单不能直接删除:' . implode(',', $hasChildren);
303
                }
304
                break;
305
            case 'parent':
306
                $pid = intval($request->input('params', -1));
307
                if ($pid < 0 || ($pid > 0 && !MenuRepository::find($pid))) {
308
                    return [
309
                        'code' => 2,
310
                        'msg' => '父级菜单ID错误'
311
                    ];
312
                }
313
                if (in_array($pid, $ids)) {
314
                    return [
315
                        'code' => 3,
316
                        'msg' => '不能将父级菜单指定为自身'
317
                    ];
318
                }
319
                Menu::query()->whereIn('id', $ids)->update(['pid' => $pid]);
320
                break;
321
            case 'order':
322
                $order = intval($request->input('params', 77));
323
                if ($order < 0) {
324
                    return [
325
                        'code' => 4,
326
                        'msg' => '排序值不能小于0'
327
                    ];
328
                }
329
                Menu::query()->whereIn('id', $ids)->update(['order' => $order]);
330
                break;
331
            case 'group':
332
                $group = strval($request->input('params', ''));
333
                Menu::query()->whereIn('id', $ids)->update(['group' => $group]);
334
                break;
335
            case 'lock_name':
336
                Menu::query()->whereIn('id', $ids)->update(['is_lock_name' => Menu::LOCK_NAME]);
337
                break;
338
            default:
339
                break;
340
        }
341
342
        event(new MenuUpdated());
343
        return [
344
            'code' => 0,
345
            'msg' => '操作成功' . $message,
346
            'reload' => true
347
        ];
348
    }
349
}
350