Completed
Push — master ( 4a10b5...ae10e5 )
by Jianhua
18:53 queued 15:33
created

ContentController   B

Complexity

Total Complexity 49

Size/Duplication

Total Lines 361
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 179
c 3
b 0
f 1
dl 0
loc 361
rs 8.48
wmc 49

17 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 11 1
A index() 0 16 2
A list() 0 14 2
A __construct() 0 11 2
A edit() 0 14 1
B save() 0 44 8
A delete() 0 14 2
A useUserDefinedIndexHandler() 0 7 2
B update() 0 44 10
A batch() 0 27 3
A userDefinedHandlerExists() 0 9 3
A getAddOrEditViewPath() 0 11 2
A useUserDefinedUpdateHandler() 0 7 2
A validateEntityRequest() 0 6 2
A useUserDefinedSaveHandler() 0 7 2
A useUserDefinedListHandler() 0 7 2
A getUpdateData() 0 10 3

How to fix   Complexity   

Complex Class

Complex classes like ContentController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ContentController, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @author  Eddy <[email protected]>
4
 */
5
6
namespace App\Http\Controllers\Admin;
7
8
use App\Http\Controllers\Controller;
9
use App\Http\Requests\Admin\ContentRequest;
10
use App\Model\Admin\Content;
11
use App\Model\Admin\Entity;
12
use App\Model\Admin\EntityField;
13
use App\Repository\Admin\ContentRepository;
14
use App\Repository\Admin\EntityFieldRepository;
15
use App\Repository\Admin\EntityRepository;
16
use Illuminate\Database\QueryException;
17
use Illuminate\Http\Request;
18
use Illuminate\Support\Str;
19
use Illuminate\View\View;
20
use App\Model\Admin\Tag;
21
use App\Model\Admin\ContentTag;
22
use Illuminate\Support\Facades\DB;
23
24
class ContentController extends Controller
25
{
26
    protected $formNames = [];
27
28
    protected $entity = null;
29
30
    public function __construct()
31
    {
32
        parent::__construct();
33
        $route = request()->route();
34
        if (is_null($route)) {
35
            return;
36
        }
37
        $entity = $route->parameter('entity');
38
        $this->entity = Entity::query()->findOrFail($entity);
39
        ContentRepository::setTable($this->entity->table_name);
40
        $this->breadcrumb[] = ['title' => '内容列表', 'url' => route('admin::content.index', ['entity' => $entity])];
41
    }
42
43
    /**
44
     * 内容管理-内容列表
45
     *
46
     */
47
    public function index($entity)
48
    {
49
        $result = $this->useUserDefinedIndexHandler($entity);
50
        if (!is_null($result)) {
51
            return $result;
52
        }
53
54
        $this->breadcrumb[] = ['title' => $this->entity->name . '内容列表', 'url' => ''];
55
        Content::$listField = [
56
            'title' => '标题'
57
        ];
58
        return view('admin.content.index', [
59
            'breadcrumb' => $this->breadcrumb,
60
            'entity' => $entity,
61
            'entityModel' => $this->entity,
62
            'autoMenu' => EntityRepository::systemMenu()
63
        ]);
64
    }
65
66
    /**
67
     * 内容列表数据接口
68
     *
69
     * @param Request $request
70
     * @param integer $entity
71
     * @return array
72
     */
73
    public function list(Request $request, $entity)
74
    {
75
        $result = $this->useUserDefinedListHandler($request, $entity);
76
        if (!is_null($result)) {
77
            return $result;
78
        }
79
80
        $perPage = (int) $request->get('limit', 50);
81
        $this->formNames = array_merge(['created_at'], EntityFieldRepository::getFields($entity));
82
        $condition = $request->only($this->formNames);
83
84
        $data = ContentRepository::list($entity, $perPage, $condition);
85
86
        return $data;
87
    }
88
89
    /**
90
     * 内容管理-新增内容
91
     *
92
     */
93
    public function create($entity)
94
    {
95
        $this->breadcrumb[] = ['title' => "新增{$this->entity->name}内容", 'url' => ''];
96
        $view = $this->getAddOrEditViewPath();
97
98
        return view($view, [
99
            'breadcrumb' => $this->breadcrumb,
100
            'entity' => $entity,
101
            'entityModel' => $this->entity,
102
            'entityFields' => EntityFieldRepository::getByEntityId($entity),
103
            'autoMenu' => EntityRepository::systemMenu()
104
        ]);
105
    }
106
107
    /**
108
     * 内容管理-保存内容
109
     *
110
     * @param ContentRequest $request
111
     * @param integer $entity
112
     * @return array
113
     */
114
    public function save(ContentRequest $request, $entity)
115
    {
116
        $this->validateEntityRequest();
117
        $result = $this->useUserDefinedSaveHandler($request, $entity);
118
        if (!is_null($result)) {
119
            return $result;
120
        }
121
122
        try {
123
            DB::beginTransaction();
124
125
            $content = ContentRepository::add($request->only(
126
                EntityFieldRepository::getSaveFields($entity)
127
            ));
128
129
            // 标签类型字段另外处理 多对多关联
130
            $inputTagsField = EntityFieldRepository::getInputTagsField($entity);
131
            $tags = null;
132
            if ($inputTagsField) {
133
                $tags = $request->post($inputTagsField->name);
134
            }
135
            if (!is_null($tags) && $tags = json_decode($tags, true)) {
136
                foreach ($tags as $v) {
137
                    $tag = Tag::firstOrCreate(['name' => $v['value']]);
138
                    ContentTag::firstOrCreate(
139
                        ['entity_id' => $entity, 'content_id' => $content->id, 'tag_id' => $tag->id]
140
                    );
141
                }
142
            }
143
144
            DB::commit();
145
146
            return [
147
                'code' => 0,
148
                'msg' => '新增成功',
149
                'redirect' => route('admin::content.index', ['entity' => $entity])
150
            ];
151
        } catch (QueryException $e) {
152
            DB::rollBack();
153
            \Log::error($e);
154
            return [
155
                'code' => 1,
156
                'msg' => '新增失败:' . (Str::contains($e->getMessage(), 'Duplicate entry') ? '当前内容已存在' : '其它错误'),
157
                'redirect' => false
158
            ];
159
        }
160
    }
161
162
    /**
163
     * 内容管理-编辑内容
164
     *
165
     * @param int $id
166
     * @return View
167
     */
168
    public function edit($entity, $id)
169
    {
170
        $this->breadcrumb[] = ['title' => "编辑{$this->entity->name}内容", 'url' => ''];
171
        $view = $this->getAddOrEditViewPath();
172
        $model = ContentRepository::find($id);
173
174
        return view($view, [
175
            'id' => $id,
176
            'model' => $model,
177
            'breadcrumb' => $this->breadcrumb,
178
            'entity' => $entity,
179
            'entityModel' => $this->entity,
180
            'entityFields' => EntityFieldRepository::getByEntityId($entity),
181
            'autoMenu' => EntityRepository::systemMenu()
182
        ]);
183
    }
184
185
    /**
186
     * 内容管理-更新内容
187
     *
188
     * @param ContentRequest $request
189
     * @param integer $entity
190
     * @param int $id
191
     * @return array
192
     */
193
    public function update(ContentRequest $request, $entity, $id)
194
    {
195
        $this->validateEntityRequest();
196
        $result = $this->useUserDefinedUpdateHandler($request, $entity, $id);
197
        if (!is_null($result)) {
198
            return $result;
199
        }
200
201
        $data = $this->getUpdateData($request, $entity);
202
        try {
203
            DB::beginTransaction();
204
205
            ContentRepository::update($id, $data);
206
            // 标签类型字段另外处理 多对多关联
207
            $inputTagsField = EntityFieldRepository::getInputTagsField($entity);
208
            $tags = null;
209
            if ($inputTagsField && $inputTagsField->is_edit === EntityField::EDIT_ENABLE) {
210
                $tags = $request->post($inputTagsField->name);
211
            }
212
            if (!is_null($tags) && $tags = json_decode($tags, true)) {
213
                $tagIds = [];
214
                foreach ($tags as $v) {
215
                    $tag = Tag::firstOrCreate(['name' => $v['value']]);
216
                    ContentTag::firstOrCreate(['entity_id' => $entity, 'content_id' => $id, 'tag_id' => $tag->id]);
217
                    $tagIds[] = $tag->id;
218
                }
219
                if ($tagIds) {
220
                    ContentTag::where('entity_id', $entity)->where('content_id', $id)->whereNotIn('tag_id', $tagIds)->delete();
221
                }
222
            }
223
224
            DB::commit();
225
            return [
226
                'code' => 0,
227
                'msg' => '编辑成功',
228
                'redirect' => route('admin::content.index', ['entity' => $entity])
229
            ];
230
        } catch (QueryException $e) {
231
            DB::rollBack();
232
            \Log::error($e);
233
            return [
234
                'code' => 1,
235
                'msg' => '编辑失败:' . (Str::contains($e->getMessage(), 'Duplicate entry') ? '当前内容已存在' : '其它错误'),
236
                'redirect' => false
237
            ];
238
        }
239
    }
240
241
    /**
242
     * 内容管理-删除内容
243
     *
244
     * @param int $id
245
     */
246
    public function delete($entity, $id)
247
    {
248
        try {
249
            ContentRepository::delete($id);
250
            return [
251
                'code' => 0,
252
                'msg' => '删除成功',
253
                'redirect' => route('admin::content.index')
254
            ];
255
        } catch (\RuntimeException $e) {
256
            return [
257
                'code' => 1,
258
                'msg' => '删除失败:' . $e->getMessage(),
259
                'redirect' => route('admin::content.index')
260
            ];
261
        }
262
    }
263
264
    /**
265
     * 内容管理-内容批量操作
266
     *
267
     * @param Request $request
268
     * @return array
269
     */
270
    public function batch(Request $request)
271
    {
272
        $type = $request->input('type', '');
273
        $ids = $request->input('ids');
274
        if (!is_array($ids)) {
275
            return [
276
                'code' => 1,
277
                'msg' => '参数错误'
278
            ];
279
        }
280
        $ids = array_map(function ($item) {
281
            return intval($item);
282
        }, $ids);
283
284
        $message = '';
285
        switch ($type) {
286
            case 'delete':
287
                ContentRepository::model()->whereIn('id', $ids)->delete();
288
                break;
289
            default:
290
                break;
291
        }
292
293
        return [
294
            'code' => 0,
295
            'msg' => '操作成功' . $message,
296
            'reload' => true
297
        ];
298
    }
299
300
    protected function validateEntityRequest()
301
    {
302
        $entityRequestClass = '\\App\\Http\\Requests\\Admin\\Entity\\' .
303
            Str::ucfirst(Str::singular($this->entity->table_name)) . 'Request';
304
        if (class_exists($entityRequestClass)) {
305
            $entityRequestClass::capture()->setContainer(app())->setRedirector(app()->make('redirect'))->validate();
306
        }
307
    }
308
309
    protected function useUserDefinedSaveHandler($request, $entity)
310
    {
311
        $entityControllerClass = $this->userDefinedHandlerExists('save');
312
        if ($entityControllerClass === false) {
313
            return null;
314
        }
315
        return call_user_func([new $entityControllerClass, 'save'], $request, $entity);
316
    }
317
318
    protected function useUserDefinedUpdateHandler($request, $entity, $id)
319
    {
320
        $entityControllerClass = $this->userDefinedHandlerExists('update');
321
        if ($entityControllerClass === false) {
322
            return null;
323
        }
324
        return call_user_func([new $entityControllerClass, 'update'], $request, $entity, $id);
325
    }
326
327
    protected function useUserDefinedIndexHandler($entity)
328
    {
329
        $entityControllerClass = $this->userDefinedHandlerExists('index');
330
        if ($entityControllerClass === false) {
331
            return null;
332
        }
333
        return call_user_func([new $entityControllerClass, 'index'], $entity);
334
    }
335
336
    protected function useUserDefinedListHandler($request, $entity)
337
    {
338
        $entityControllerClass = $this->userDefinedHandlerExists('list');
339
        if ($entityControllerClass === false) {
340
            return null;
341
        }
342
        return call_user_func([new $entityControllerClass, 'list'], $request, $entity);
343
    }
344
345
    /**
346
     * 判断自定义的处理方法是否存在
347
     *
348
     * @param string $method 方法名
349
     * @return string|boolean 存在返回控制器类名,不存在返回false
350
     */
351
    protected function userDefinedHandlerExists($method)
352
    {
353
        $entityControllerClass = '\\App\\Http\\Controllers\\Admin\\Entity\\' .
354
            Str::ucfirst(Str::singular($this->entity->table_name)) . 'Controller';
355
        if (class_exists($entityControllerClass) && method_exists($entityControllerClass, $method)) {
356
            return $entityControllerClass;
357
        }
358
359
        return false;
360
    }
361
362
    protected function getAddOrEditViewPath()
363
    {
364
        $view = 'admin.content.add';
365
        // 自定义模板
366
        $modelName = Str::singular($this->entity->table_name);
367
        $path = resource_path('views/admin/content/' . $modelName . '_add.blade.php');
368
        if (file_exists($path)) {
369
            $view = 'admin.content.' . $modelName . '_add';
370
        }
371
372
        return $view;
373
    }
374
375
    protected function getUpdateData($request, $entity)
376
    {
377
        $fieldInfo = EntityFieldRepository::getUpdateFields($entity);
378
        $data = [];
379
        foreach ($fieldInfo as $k => $v) {
380
            if ($v === 'checkbox') {
381
                $data[$k] = '';
382
            }
383
        }
384
        return array_merge($data, $request->only(array_keys($fieldInfo)));
385
    }
386
}
387