Completed
Push — TrainingTypePhase2 ( 02e5d6 )
by D.
07:24
created

UserController   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 259
Duplicated Lines 6.95 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 25
lcom 1
cbo 8
dl 18
loc 259
rs 10
c 1
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A store() 0 13 2
A index() 0 16 1
A destroy() 0 9 1
A create() 9 9 1
B show() 0 39 2
A edit() 9 9 1
B update() 0 25 4
A getUserTrainingTypes() 0 19 4
A import() 0 12 1
A resolveImport() 0 10 1
A previousAndNextUsers() 0 16 3
A spellOutClearance() 0 17 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace SET\Http\Controllers;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Facades\File;
7
use Illuminate\Support\Facades\Gate;
8
use Illuminate\Support\Facades\Input;
9
use Illuminate\Support\Facades\Storage;
10
use Krucas\Notification\Facades\Notification;
11
use SET\Duty;
12
use SET\Group;
13
use SET\Handlers\Excel\JpasImport;
14
use SET\Http\Requests\StoreUserRequest;
15
use SET\User;
16
17
/**
18
 * Class UserController.
19
 */
20
class UserController extends Controller
21
{
22
    /**
23
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
24
     */
25
    public function index()
26
    {
27
        $this->authorize('view');
28
29
        $users = User::with([
30
            'assignedTrainings' => function ($q) {
31
                $q->whereNull('completed_date')
32
                    ->whereBetween('due_date', [Carbon::now()->subYear(), Carbon::now()->addWeeks(4)]);
33
            },
34
            'trainings',
35
        ])
36
            ->skipSystem()
37
            ->orderBy('last_name')->get();
38
39
        return view('user.index', compact('users'));
40
    }
41
42 View Code Duplication
    public function create()
43
    {
44
        $this->authorize('edit');
45
46
        $supervisors = User::skipSystem()->active()->orderBy('last_name')->get()->pluck('userFullName', 'id')->toArray();
47
        $groups = Group::all();
48
49
        return view('user.create', compact('supervisors', 'groups'));
50
    }
51
52
    /**
53
     * @param StoreUserRequest $request
54
     *
55
     * @return \Illuminate\Http\RedirectResponse
56
     */
57
    public function store(StoreUserRequest $request)
58
    {
59
        $data = $request->all();
60
        $data['status'] = 'active';
61
        $user = User::create($data);
62
63
        if (array_key_exists('groups', $data)) {
64
            settype($data['groups'], 'array');
65
            $user->groups()->sync($data['groups']);
66
        }
67
68
        return redirect()->action('UserController@index');
69
    }
70
71
    /**
72
     * @param $userId
73
     *
74
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
75
     */
76
    public function show($userId)
77
    {
78
        $user = User::with(['subordinates' => function ($query) {
79
            $query->active();
80
        },
81
                            'groups', 'duties', 'attachments',
82
                            'visits', 'notes.author', 'notes.attachments',
83
                            'travels.author', 'travels.attachments', ])
84
                    ->findOrFail($userId);
85
86
        //Make sure the user can't access other people's pages.
87
        $this->authorize('show_user', $user);
88
89
        $user['clearance'] = $this->spellOutClearance($user['clearance']);
90
        $user['access_level'] = $this->spellOutClearance($user['access_level']);
91
92
        $trainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')->orderBy('completed_date', 'DESC')->get();
93
94
        $user_training_types = $this->getUserTrainingTypes($trainings);
95
        $training_user_types = $user_training_types[0]; // List of the user's training types
96
        $training_blocks = $user_training_types[1]; // List of training block titles for user
97
98
        $activityLog = [];
99
        if (Gate::allows('view')) {
100
            $activityLog = $user->getUserLog($user);
101
        }
102
103
        $this->previousAndNextUsers($user, $previous, $next);
104
105
        //This mess is just so that we can output the Security Check list or show none. Mainly just to show none.
106
        $duties = Duty::whereHas('users', function ($q) use ($userId) {
107
            $q->where('id', $userId);
108
        })->orWhereHas('groups.users', function ($q) use ($userId) {
109
            $q->where('id', $userId);
110
        })->get();
111
112
        return view('user.show', compact('user', 'duties', 'previous', 'next',
113
            'trainings', 'activityLog', 'training_blocks', 'training_user_types'));
114
    }
115
116 View Code Duplication
    public function edit(User $user)
117
    {
118
        $this->authorize('edit');
119
120
        $supervisors = User::skipSystem()->active()->orderBy('last_name')->get()->pluck('userFullName', 'id')->toArray();
121
        $groups = Group::all();
122
123
        return view('user.edit', compact('user', 'supervisors', 'groups'));
124
    }
125
126
    public function update(User $user)
127
    {
128
        $this->authorize('edit');
129
130
        $data = Input::all();
131
132
        $data['destroyed_date'] = $user->getDestroyDate($data['status']);
133
134
        $user->update($data);
135
136
        //Handle user groups
137
        if (!array_key_exists('groups', $data)) {
138
            $data['groups'] = [];
139
        }
140
        $user->groups()->sync($data['groups']);
141
142
        //Handled closed area access (MUST come AFTER syncing groups).
143
        if (array_key_exists('access', $data)) {
144
            foreach ($data['access'] as $group_id => $accessLevel) {
145
                $user->groups()->updateExistingPivot($group_id, ['access' => $accessLevel]);
146
            }
147
        }
148
149
        return redirect()->action('UserController@show', $user->id);
150
    }
151
152
    /**
153
     * @param $userId
154
     *
155
     * @return string
156
     */
157
    public function destroy($userId)
158
    {
159
        $this->authorize('edit');
160
161
        Storage::deleteDirectory('user_'.$userId);
162
        User::findOrFail($userId)->delete();
163
164
        return 'success';
165
    }
166
167
168
    /**
169
     * @param $trainings[]
170
     * From the User's trainings, a list of the training types is determined and
171
     * a list of the training block titles is determined.
172
     * @return user_training_types[], training_block_titles[]
0 ignored issues
show
Documentation introduced by
The doc-type user_training_types[], could not be parsed: Expected "|" or "end of type", but got "," at position 21. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
173
     */
174
    public function getUserTrainingTypes($trainings=[])
175
    {
176
        $training_block_titles = $user_training_types = [];
177
        foreach ($trainings as $trainingUser) {
178
            if (is_null($trainingUser->completed_date)) {
179
                $training_block_titles['AAA']='Scheduled';
180
                $user_training_types[$trainingUser->id] = 'Scheduled';
181
            } elseif ($trainingUser->Training->trainingType) {
182
                $typeName = $trainingUser->Training->trainingType->name;
183
                $training_block_titles[$typeName] = $typeName;
184
                $user_training_types[$trainingUser->id] = $typeName;
185
            } else { // No training type
186
                $training_block_titles['999']='Miscellaneous';
187
                $user_training_types[$trainingUser->id] = 'Miscellaneous';
188
            }
189
        }
190
        ksort($training_block_titles);  // Order by key
191
        return [$user_training_types, $training_block_titles];
192
    }
193
194
    /**
195
     * Process our JPAS import. Once that has been handled, we pass the file, changes,
196
     * unique/unmapped users & a user list to the user.import view.
197
     * That way we keep all this data for the resolve phase.
198
     *
199
     * @param JpasImport $import
200
     *
201
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
202
     */
203
    public function import(JpasImport $import)
204
    {
205
        $results = $import->handleImport();
206
        $uploadedFile = $import->getFile('file');
207
208
        $changes = $results['changes'];
209
        $unique = $results['unique'];
210
211
        $userList = User::orderBy('last_name')->get()->pluck('UserFullName', 'id')->toArray();
212
213
        return view('user.import', compact('unique', 'changes', 'userList', 'uploadedFile'));
214
    }
215
216
    /**
217
     * @param JpasImport $import
218
     *
219
     * @return \Illuminate\Http\RedirectResponse
220
     */
221
    public function resolveImport(JpasImport $import)
222
    {
223
        $import->handleImport();
224
225
        Notification::container()->success('Import Complete');
226
227
        File::delete($import->getFile('file'));
228
229
        return redirect()->action('HomeController@index');
230
    }
231
232
    /**
233
     * Generate the grab the previous and next user if our users are sorted alphabetically.
234
     *
235
     * @param $user
236
     * @param $previous
237
     * @param $next
238
     */
239
    private function previousAndNextUsers($user, &$previous, &$next)
240
    {
241
        //Build the previous/next user that are in alphabetical order.
242
        $users = User::skipSystem()->orderBy('last_name')->orderBy('first_name')->get();
243
        $previous = null; // set to null by default in case we are at the start of the list.
244
        while ($users->first()->id != $user->id) {
245
            $previous = $users->shift()->id;
246
        }
247
        //check if we have a record aft the current user. If not, then we are at the end.
248
        if ($users->count() > 1) {
249
            $users->shift();
250
            $next = $users->shift()->id;
251
        } else {
252
            $next = null;
253
        }
254
    }
255
256
    /**
257
     * @param $clearance
258
     *
259
     * @return mixed
260
     */
261
    private function spellOutClearance($clearance)
262
    {
263
        //fully spell out user's clearance.
264
        switch ($clearance) {
265
            case 'S':
266
                $clearance = 'Secret';
267
                break;
268
            case 'TS':
269
                $clearance = 'Top Secret';
270
                break;
271
            case 'Int S':
272
                $clearance = 'Interim Secret';
273
                break;
274
        }
275
276
        return $clearance;
277
    }
278
}
279