Completed
Push — master ( 3d3760...b0d42a )
by John
30s queued 13s
created

GroupManageController   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 402
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 237
dl 0
loc 402
rs 5.5199
c 1
b 0
f 1
wmc 56

11 Methods

Rating   Name   Duplication   Size   Complexity  
A changeJoinPolicy() 0 21 4
C createHomework() 0 102 14
A changeGroupName() 0 17 2
A inviteMember() 0 34 4
A createNotice() 0 17 2
A approveMember() 0 20 3
A changeMemberClearance() 0 27 5
A changeSubGroup() 0 18 3
B changeGroupImage() 0 38 8
A removeMember() 0 19 3
B arrangeContest() 0 59 8

How to fix   Complexity   

Complex Class

Complex classes like GroupManageController 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 GroupManageController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace App\Http\Controllers\Ajax;
4
5
use App\Models\ContestModel;
6
use App\Models\GroupModel;
7
use App\Models\ResponseModel;
8
use App\Models\Eloquent\User;
9
use App\Models\Eloquent\Group;
10
use App\Models\Eloquent\Problem;
11
use App\Http\Controllers\Controller;
12
use Illuminate\Http\Request;
13
use Illuminate\Support\Facades\Storage;
14
use Auth;
15
use Carbon;
16
use Exception;
17
use Validator;
18
19
class GroupManageController extends Controller
20
{
21
    /**
22
     * The Ajax Contest Arrange.
23
     *
24
     * @param Request $request web request
25
     *
26
     * @return JsonResponse
0 ignored issues
show
Bug introduced by
The type App\Http\Controllers\Ajax\JsonResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
27
     */
28
    public function arrangeContest(Request $request)
29
    {
30
        $request->validate([
31
            'name' => 'required|max:255',
32
            'problems' => 'required|max:2550',
33
            'begin_time' => 'required|date',
34
            'status_visibility' => 'required|integer',
35
            'end_time' => 'required|date|after:begin_time',
36
            'gid' => 'required|integer',
37
            'description' => 'string',
38
            'public' => 'integer',
39
            'practice' => 'integer'
40
        ]);
41
42
        $all_data=$request->all();
43
44
        if (($all_data['public'] ?? 0) && ($all_data['practice'] ?? 0)) {
45
            return ResponseModel::err(4007);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\ResponseModel::err(4007) returns the type Illuminate\Http\JsonResponse which is incompatible with the documented return type App\Http\Controllers\Ajax\JsonResponse.
Loading history...
46
        }
47
48
        $contestModel=new ContestModel();
49
        $groupModel=new GroupModel();
50
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
51
        if ($clearance<2) {
52
            return ResponseModel::err(2001);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\ResponseModel::err(2001) returns the type Illuminate\Http\JsonResponse which is incompatible with the documented return type App\Http\Controllers\Ajax\JsonResponse.
Loading history...
53
        }
54
        $problems=explode(",", $all_data["problems"]);
55
        if (count($problems)>26) {
56
            return ResponseModel::err(4002);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\ResponseModel::err(4002) returns the type Illuminate\Http\JsonResponse which is incompatible with the documented return type App\Http\Controllers\Ajax\JsonResponse.
Loading history...
57
        }
58
        $i=0;
59
        $problemSet=[];
60
        foreach ($problems as $p) {
61
            if (!empty($p)) {
62
                $i++;
63
                $problemSet[]=[
64
                    "number"=>$i,
65
                    "pcode"=>$p,
66
                    "points"=>100
67
                ];
68
            }
69
        }
70
71
        if (empty($problemSet)) {
72
            return ResponseModel::err(1003);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\ResponseModel::err(1003) returns the type Illuminate\Http\JsonResponse which is incompatible with the documented return type App\Http\Controllers\Ajax\JsonResponse.
Loading history...
73
        }
74
75
        $cid=$contestModel->arrangeContest($all_data["gid"], [
76
            "assign_uid"=>Auth::user()->id,
77
            "name"=>$all_data["name"],
78
            "description"=>$all_data["description"],
79
            "status_visibility"=>$all_data["status_visibility"],
80
            "begin_time"=>$all_data["begin_time"],
81
            "end_time"=>$all_data["end_time"],
82
            "practice"=>$all_data["practice"] ?? 0,
83
            "public"=>$all_data["public"] ?? 0,
84
        ], $problemSet);
85
86
        return ResponseModel::success(200, 'Successful!', $cid);
0 ignored issues
show
Bug Best Practice introduced by
The expression return App\Models\Respon...0, 'Successful!', $cid) returns the type Illuminate\Http\JsonResponse which is incompatible with the documented return type App\Http\Controllers\Ajax\JsonResponse.
Loading history...
87
    }
88
89
    public function changeGroupName(Request $request)
90
    {
91
        $request->validate([
92
            'gid' => 'required|integer',
93
            'group_name' => 'max:50',
94
        ]);
95
96
        $all_data=$request->all();
97
98
        $groupModel=new GroupModel();
99
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
100
        if ($clearance<2) {
101
            return ResponseModel::err(2001);
102
        }
103
104
        $groupModel->changeGroupName($all_data["gid"], $all_data["group_name"]);
105
        return ResponseModel::success(200);
106
    }
107
108
    public function changeJoinPolicy(Request $request)
109
    {
110
        $request->validate([
111
            'gid' => 'required|integer',
112
            'join_policy' => 'required|integer',
113
        ]);
114
115
        $all_data=$request->all();
116
117
        $groupModel=new GroupModel();
118
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
119
        if ($clearance<2) {
120
            return ResponseModel::err(2001);
121
        }
122
123
        if ($all_data["join_policy"]<1 || $all_data["join_policy"]>3) {
124
            return ResponseModel::err(1007);
125
        }
126
127
        $groupModel->changeJoinPolicy($all_data["gid"], $all_data["join_policy"]);
128
        return ResponseModel::success(200);
129
    }
130
131
    public function changeGroupImage(Request $request)
132
    {
133
        $request->validate([
134
            'gid' => 'required|integer',
135
        ]);
136
137
        $all_data=$request->all();
138
139
        if (!empty($request->file('img')) && $request->file('img')->isValid()) {
140
            $extension=$request->file('img')->extension();
141
        } else {
142
            return ResponseModel::err(1005);
143
        }
144
145
        $allow_extension=['jpg', 'png', 'jpeg', 'gif', 'bmp'];
146
147
        $groupModel=new GroupModel();
148
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
149
        if ($clearance<2) {
150
            return ResponseModel::err(2001);
151
        }
152
153
        if (!in_array($extension, $allow_extension)) {
154
            return ResponseModel::err(1005);
155
        }
156
157
        $path=$request->file('img')->store('/static/img/group', 'NOJPublic');
158
159
        $group=GroupModel::find($all_data["gid"]);
160
        $old_path=$group->img;
161
        if ($old_path!='/static/img/group/default.png' && $old_path!='/static/img/group/noj.png' && $old_path!='/static/img/group/icpc.png') {
162
            Storage::disk('NOJPublic')->delete($old_path);
163
        }
164
165
        $group->img='/'.$path;
0 ignored issues
show
Bug introduced by
Are you sure $path of type false|string can be used in concatenation? ( Ignorable by Annotation )

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

165
        $group->img='/'./** @scrutinizer ignore-type */ $path;
Loading history...
166
        $group->save();
167
168
        return ResponseModel::success(200, null, '/'.$path);
169
170
    }
171
172
    public function changeMemberClearance(Request $request)
173
    {
174
        $request->validate([
175
            'gid' => 'required|integer',
176
            'uid' => 'required|integer',
177
            'permission' => 'required|integer|max:3|min:1',
178
        ]);
179
180
        $all_data=$request->all();
181
182
        $groupModel=new GroupModel();
183
184
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
185
        $target_clearance=$groupModel->judgeClearance($all_data["gid"], $all_data['uid']);
186
187
        if ($target_clearance==-3) {
188
            return ResponseModel::err(7004);
189
        }
190
191
        if ($target_clearance>=$clearance || $clearance<2 || $all_data['permission']>=$clearance) {
192
            return ResponseModel::err(2001);
193
        }
194
195
        $groupModel->changeClearance($all_data['uid'], $all_data["gid"], $all_data['permission']);
196
197
        $result_info=$groupModel->userProfile($all_data['uid'], $all_data["gid"]);
198
        return ResponseModel::success(200, null, $result_info);
199
    }
200
201
    public function approveMember(Request $request)
202
    {
203
        $request->validate([
204
            'gid' => 'required|integer',
205
            'uid' => 'required|integer',
206
        ]);
207
208
        $all_data=$request->all();
209
210
        $groupModel=new GroupModel();
211
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
212
        $targetClearance=$groupModel->judgeClearance($all_data["gid"], $all_data["uid"]);
213
        if ($clearance>1) {
214
            if ($targetClearance!=0) {
215
                return ResponseModel::err(7003);
216
            }
217
            $groupModel->changeClearance($all_data["uid"], $all_data["gid"], 1);
218
            return ResponseModel::success(200);
219
        }
220
        return ResponseModel::err(7002);
221
    }
222
223
    public function removeMember(Request $request)
224
    {
225
        $request->validate([
226
            'gid' => 'required|integer',
227
            'uid' => 'required|integer',
228
        ]);
229
230
        $all_data=$request->all();
231
232
        $groupModel=new GroupModel();
233
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
234
        $targetClearance=$groupModel->judgeClearance($all_data["gid"], $all_data["uid"]);
235
        if ($clearance<=1 || $clearance<=$targetClearance) {
236
            return ResponseModel::err(7002);
237
        }
238
239
        $groupModel->removeClearance($all_data["uid"], $all_data["gid"]);
240
        $groupModel->refreshElo($all_data["gid"]);
241
        return ResponseModel::success(200);
242
    }
243
244
    public function inviteMember(Request $request)
245
    {
246
        $request->validate([
247
            'gid' => 'required|integer',
248
            'email' => 'required|email',
249
        ]);
250
251
        $all_data=$request->all();
252
253
        $groupModel=new GroupModel();
254
        $is_user=$groupModel->isUser($all_data["email"]);
255
        if (!$is_user) {
256
            return ResponseModel::err(2006);
257
        }
258
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
259
        if ($clearance<2) {
260
            return ResponseModel::err(7002);
261
        }
262
        $targetClearance=$groupModel->judgeEmailClearance($all_data["gid"], $all_data["email"]);
263
        if ($targetClearance!=-3) {
264
            return ResponseModel::err(7003);
265
        }
266
        $groupModel->inviteMember($all_data["gid"], $all_data["email"]);
267
        $basic=$groupModel->basic($all_data['gid']);
268
        $url=route('group.detail', ['gcode' => $basic['gcode']]);
269
        $receiverInfo=User::where('email', $all_data['email'])->first();
270
        $sender_name=Auth::user()->name;
0 ignored issues
show
Bug introduced by
Accessing name on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
271
        sendMessage([
272
            'receiver' => $receiverInfo["id"],
273
            'sender' => Auth::user()->id,
274
            'title' => __('group.message.inviteJoin.title', ['sender_name' => $sender_name, 'group_name' => $basic['name']]),
275
            'content' => __('group.message.inviteJoin.content', ['reciver_name' => $receiverInfo['name'], 'group_name' => $basic['name'], 'group_url' => $url]),
276
        ]);
277
        return ResponseModel::success(200);
278
    }
279
280
    public function changeSubGroup(Request $request)
281
    {
282
        $request->validate([
283
            'gid'=>'required|integer',
284
            'uid'=>'required|integer',
285
            'sub'=>'nullable|max:60000'
286
        ]);
287
288
        $all_data=$request->all();
289
290
        $groupModel=new GroupModel();
291
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
292
        $targetClearance=$groupModel->judgeClearance($all_data["gid"], $all_data["uid"]);
293
        if ($clearance>1 && $clearance>=$targetClearance) {
294
            $groupModel->changeGroup($all_data["uid"], $all_data["gid"], $all_data["sub"]);
295
            return ResponseModel::success(200);
296
        }
297
        return ResponseModel::err(7002);
298
    }
299
300
    public function createNotice(Request $request)
301
    {
302
        $request->validate([
303
            'gid' => 'required|integer',
304
            'title' => 'required|min:3|max:50',
305
            'content' => 'required|min:3|max:60000',
306
        ]);
307
308
        $all_data=$request->all();
309
310
        $groupModel=new GroupModel();
311
        $clearance=$groupModel->judgeClearance($all_data["gid"], Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
312
        if ($clearance<2) {
313
            return ResponseModel::err(2001);
314
        }
315
        $groupModel->createNotice($all_data["gid"], Auth::user()->id, $all_data["title"], $all_data["content"]);
316
        return ResponseModel::success(200);
317
    }
318
319
    public function createHomework(Request $request)
320
    {
321
        try {
322
            $all = $request->all();
323
            $all['currently_at'] = strtotime('now');
324
            $validator = Validator::make($all, [
325
                'title'         => 'required|string|min:1|max:100',
326
                'description'   => 'required|string|min:1|max:65535',
327
                'ended_at'      => 'required|date|after:currently_at',
328
                'gid'           => 'required|integer|gte:1',
329
                'problems'      => 'required|array',
330
            ], [], [
331
                'title'         => 'Title',
332
                'description'   => 'Description',
333
                'ended_at'      => 'Ended Time',
334
                'currently_at'  => 'Current Time',
335
                'gid'           => 'Group ID',
336
                'problems'      => 'Problems',
337
            ]);
338
339
            if ($validator->fails()) {
340
                throw new Exception($validator->errors()->first());
341
            }
342
343
            if (count($request->problems) > 26) {
344
                throw new Exception('Please include no more than 26 problems.');
345
            }
346
347
            if (count($request->problems) < 1) {
348
                throw new Exception('Please include at least one problem.');
349
            }
350
351
            $proceedProblems = $request->problems;
352
            $proceedProblemCodes = [];
353
354
            foreach ($proceedProblems as &$problem) {
355
                if (!is_array($problem)) {
356
                    throw new Exception('Each problem object must be an array.');
357
                }
358
359
                $problem['pcode'] = mb_strtoupper(trim($problem['pcode']));
360
361
                if(array_search($problem['pcode'], $proceedProblemCodes) !== false) {
362
                    throw new Exception("Duplicate Problem");
363
                }
364
365
                $validator = Validator::make($problem, [
366
                    'pcode'         => 'required|string|min:1|max:100',
367
                    // 'alias'         => 'required|string|min:0|max:100|nullable',
368
                    // 'points'        => 'required|integer|gte:1',
369
                ], [], [
370
                    'pcode'         => 'Problem Code',
371
                    // 'alias'         => 'Alias',
372
                    // 'points'        => 'Points',
373
                ]);
374
375
                if ($validator->fails()) {
376
                    throw new Exception($validator->errors()->first());
377
                }
378
379
                $proceedProblemCodes[] = $problem['pcode'];
380
            }
381
382
            unset($problem);
383
384
            $problemsDict = Problem::whereIn('pcode', $proceedProblemCodes)->select('pid', 'pcode')->get()->pluck('pid', 'pcode');
385
386
            try {
387
                foreach($proceedProblems as &$proceedProblem) {
388
                    $proceedProblem['pid'] = $problemsDict[$proceedProblem['pcode']];
389
                    if(blank($proceedProblem['pid'])) {
390
                        throw new Exception();
391
                    }
392
                }
393
                unset($proceedProblem);
394
            } catch (Exception $e) {
395
                throw new Exception('Problem Not Found');
396
            }
397
        } catch (Exception $e) {
398
            return response()->json([
399
                'errors' => [
400
                    'description' => [
401
                        $e->getMessage()
402
                    ]
403
                ],
404
                'message' => "The given data was invalid."
405
            ], 422);
406
        }
407
408
        $groupModel = new GroupModel();
409
        $clearance = $groupModel->judgeClearance($request->gid, Auth::user()->id);
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
410
        if ($clearance < 2) {
411
            return ResponseModel::err(2001);
412
        }
413
414
        try {
415
            $homeworkID = Group::find($request->gid)->addHomework($request->title, $request->description, Carbon::parse($request->ended_at), $proceedProblems);
0 ignored issues
show
Unused Code introduced by
The assignment to $homeworkID is dead and can be removed.
Loading history...
416
        } catch (Exception $e) {
417
            return ResponseModel::err(7009);
418
        }
419
420
        return ResponseModel::success(200);
421
    }
422
}
423