Completed
Push — master ( 46765e...316bd1 )
by Sheela
03:07
created

UserController::index()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 30
ccs 0
cts 28
cp 0
rs 8.8571
cc 2
eloc 20
nc 2
nop 1
crap 6
1
<?php
2
3
namespace SET\Http\Controllers;
4
5
use Carbon\Carbon;
6
use Illuminate\Support\Facades\DB;
7
use Illuminate\Support\Facades\File;
8
use Illuminate\Support\Facades\Gate;
9
use Illuminate\Support\Facades\Input;
10
use Illuminate\Support\Facades\Storage;
11
use Krucas\Notification\Facades\Notification;
12
use SET\Duty;
13
use SET\Group;
14
use SET\Handlers\Excel\JpasImport;
15
use SET\Http\Requests\StoreUserRequest;
16
use SET\Training;
17
use SET\User;
18
19
/**
20
 * Class UserController.
21
 */
22
class UserController extends Controller
23
{
24
    /**
25
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
26
     */    
27
    public function index($userStatus = null)
28
    {
29
        $this->authorize('view');
30
31
        if ($userStatus)
32
        {
33
            $users = User::with([
34
                'assignedTrainings' => function ($q) {
35
                    $q->whereNull('completed_date')
36
                        ->whereBetween('due_date', [Carbon::now()->subYear(), Carbon::now()->addWeeks(4)]);
37
                },
38
                'trainings',
39
            ])
40
                ->skipSystem()
41
                ->where('status', $userStatus)
42
                ->orderBy('last_name')->get();   
43
        } else {
44
            $users = User::with([
45
                'assignedTrainings' => function ($q) {
46
                    $q->whereNull('completed_date')
47
                        ->whereBetween('due_date', [Carbon::now()->subYear(), Carbon::now()->addWeeks(4)]);
48
                },
49
                'trainings',
50
            ])
51
            ->skipSystem()
52
            ->orderBy('last_name')->get();
53
        }
54
55
        return view('user.index', compact('users', 'userStatus'));
56
    }
57
58
    public function create()
59
    {
60
        $this->authorize('edit');
61
62
        $supervisors = User::skipSystem()->active()->orderBy('last_name')->get()->pluck('userFullName', 'id')->toArray();
63
        $groups = Group::all();
64
65
        return view('user.create', compact('supervisors', 'groups'));
66
    }
67
68
    /**
69
     * @param StoreUserRequest $request
70
     *
71
     * @return \Illuminate\Http\RedirectResponse
72
     */
73
    public function store(StoreUserRequest $request)
74
    {
75
        $data = $request->all();
76
        $data['status'] = 'active';
77
        $user = User::create($data);
78
79
        if (array_key_exists('groups', $data)) {
80
            settype($data['groups'], 'array');
81
            $user->groups()->sync($data['groups']);
82
        }
83
84
        return redirect()->action('UserController@index');
85
    }
86
87
    /**
88
     * @param $userId
89
     *
90
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
91
     */
92
    public function show($userId, $sectionId = null)
93
    {
94
        $user = User::with(['subordinates' => function ($query) {
95
            $query->active();
96
        },
97
                            'groups', 'duties', 'attachments',
98
                            'visits', 'notes.author', 'notes.attachments',
99
                            'travels.author', 'travels.attachments', ])
100
                    ->findOrFail($userId);
101
102
        //Make sure the user can't access other people's pages.
103
        $this->authorize('show_user', $user);
104
105
        $user['clearance'] = $this->spellOutClearance($user['clearance']);
106
        $user['access_level'] = $this->spellOutClearance($user['access_level']);
107
108
        $trainings = $this->getUserTrainings($user, $sectionId);
109
        $user_training_types = $this->getUserTrainingTypes($trainings);
110
        $training_user_types = $user_training_types[0]; // List of the user's training types
111
        $training_blocks = $user_training_types[1]; // List of training block titles for user
112
113
        $activityLog = [];
114
        if (Gate::allows('view')) {
115
            $activityLog = $user->getUserLog($user);
116
        }
117
118
        $this->previousAndNextUsers($user, $previous, $next);
119
120
        //This mess is just so that we can output the Security Check list or show none. Mainly just to show none.
121
        $duties = Duty::whereHas('users', function ($q) use ($userId) {
122
            $q->where('id', $userId);
123
        })->orWhereHas('groups.users', function ($q) use ($userId) {
124
            $q->where('id', $userId);
125
        })->get();
126
127
        return view('user.show', compact('user', 'duties', 'previous', 'next',
128
            'trainings', 'activityLog', 'training_blocks', 'training_user_types'));
129
    }
130
131
    public function edit(User $user)
132
    {
133
        $this->authorize('edit');
134
135
        $supervisors = User::skipSystem()->active()->orderBy('last_name')->get()->pluck('userFullName', 'id')->toArray();
136
        $groups = Group::all();
137
138
        return view('user.edit', compact('user', 'supervisors', 'groups'));
139
    }
140
141
    public function update(User $user)
142
    {
143
        $this->authorize('edit');
144
145
        $data = Input::all();
146
147
        $data['destroyed_date'] = $user->getDestroyDate($data['status']);
148
149
        $user->update($data);
150
151
        //Handle user groups
152
        if (!array_key_exists('groups', $data)) {
153
            $data['groups'] = [];
154
        }
155
        $user->groups()->sync($data['groups']);
156
157
        //Handled closed area access (MUST come AFTER syncing groups).
158
        if (array_key_exists('access', $data)) {
159
            foreach ($data['access'] as $group_id => $accessLevel) {
160
                $user->groups()->updateExistingPivot($group_id, ['access' => $accessLevel]);
161
            }
162
        }
163
164
        return redirect()->action('UserController@show', $user->id);
165
    }
166
167
    /**
168
     * @param $userId
169
     *
170
     * @return string
171
     */
172
    public function destroy($userId)
173
    {
174
        $this->authorize('edit');
175
176
        Storage::deleteDirectory('user_'.$userId);
177
        User::findOrFail($userId)->delete();
178
179
        return 'success';
180
    }
181
182
    /**
183
     * Get all the scheduled trainings for the user and either the most recent completed
184
     * trainings or all completed trainings for the desired training type based on data values.
185
     *
186
     * @param $user
187
     * @param $data
188
     *
189
     * @return array trainings
190
     */
191
    private function getUserTrainings($user, $sectionId)
192
    {
193
        // Get the scheduled trainings and the completed trainings separately, so it will be easier to get either
194
        // the full list of completed trainings or the most recently completed training for each training type.
195
        $scheduledTrainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')
196
                                ->whereNull('completed_date');
197
                
198
        // Now fetch the recently completed training records for the specified  user
199
        $recentCompletedTrainings = DB::table('training_user as t1')
200
                                    ->where('id', function($query) use ($user) {
201
                                        $query->from('training_user as t2')
202
                                              ->selectRaw('t2.id')
203
                                              ->where('t2.user_id', '=', $user->id)
204
                                              ->whereRaw('t1.training_id = t2.training_id')
205
                                              ->orderBy('completed_date', 'DESC')->limit(1);
206
                                    });
207
208
        // If the user clicks the showAll button for a particular type of training,
209
        // show all the trainings completed by that user for that training type.
210
        if ($sectionId != null) {
211
            $selectedTraining = Training::trainingByType($sectionId)->get()->pluck('id')->toArray();
0 ignored issues
show
Bug introduced by
The method trainingByType() does not exist on SET\Training. Did you maybe mean scopeTrainingByType()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
212
213
            $completedTrainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')
214
                                    ->whereIn('training_id', $selectedTraining);
215
216
            $trainings = $scheduledTrainings->union($completedTrainings)->union($recentCompletedTrainings)
217
                                        ->orderBy('completed_date', 'DESC')->get();
218
        } else {
219
            $trainings = $scheduledTrainings->union($recentCompletedTrainings)->orderBy('completed_date', 'DESC')->get();
220
        }
221
222
        return $trainings;
223
    }
224
225
    /**
226
     * @param $trainings[]
227
     * From the User's trainings, a list of the training types is determined and
228
     * a list of the training block titles is determined.
229
     *
230
     * @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...
231
     */
232
    public function getUserTrainingTypes($trainings = [])
233
    {
234
        $training_block_titles = $user_training_types = [];
235
        foreach ($trainings as $trainingUser) {
236
            if (is_null($trainingUser->completed_date)) {
237
                $training_block_titles['AAA'] = 'Scheduled';
238
                $user_training_types[$trainingUser->id] = 'Scheduled';
239
            } elseif ($trainingUser->Training->trainingType) {
240
                $typeName = $trainingUser->Training->trainingType->name;
241
                $training_block_titles[$typeName] = $typeName;
242
                $user_training_types[$trainingUser->id] = $typeName;
243
            } else { // No training type
244
                $training_block_titles['999'] = 'Miscellaneous';
245
                $user_training_types[$trainingUser->id] = 'Miscellaneous';
246
            }
247
        }
248
        ksort($training_block_titles);  // Order by key
249
        return [$user_training_types, $training_block_titles];
250
    }
251
252
    /**
253
     * Process our JPAS import. Once that has been handled, we pass the file, changes,
254
     * unique/unmapped users & a user list to the user.import view.
255
     * That way we keep all this data for the resolve phase.
256
     *
257
     * @param JpasImport $import
258
     *
259
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
260
     */
261
    public function import(JpasImport $import)
262
    {
263
        $results = $import->handleImport();
264
        $uploadedFile = $import->getFile('file');
265
266
        $changes = $results['changes'];
267
        $unique = $results['unique'];
268
269
        $userList = User::orderBy('last_name')->get()->pluck('UserFullName', 'id')->toArray();
270
271
        return view('user.import', compact('unique', 'changes', 'userList', 'uploadedFile'));
272
    }
273
274
    /**
275
     * @param JpasImport $import
276
     *
277
     * @return \Illuminate\Http\RedirectResponse
278
     */
279
    public function resolveImport(JpasImport $import)
280
    {
281
        $import->handleImport();
282
283
        Notification::container()->success('Import Complete');
284
285
        File::delete($import->getFile('file'));
286
287
        return redirect()->action('HomeController@index');
288
    }
289
290
    /**
291
     * Generate the grab the previous and next user if our users are sorted alphabetically.
292
     *
293
     * @param $user
294
     * @param $previous
295
     * @param $next
296
     */
297
    private function previousAndNextUsers($user, &$previous, &$next)
298
    {
299
        //Build the previous/next user that are in alphabetical order.
300
        $users = User::skipSystem()->orderBy('last_name')->orderBy('first_name')->get();
301
        $previous = null; // set to null by default in case we are at the start of the list.
302
        while ($users->first()->id != $user->id) {
303
            $previous = $users->shift()->id;
304
        }
305
        //check if we have a record aft the current user. If not, then we are at the end.
306
        if ($users->count() > 1) {
307
            $users->shift();
308
            $next = $users->shift()->id;
309
        } else {
310
            $next = null;
311
        }
312
    }
313
314
    /**
315
     * @param $clearance
316
     *
317
     * @return mixed
318
     */
319
    private function spellOutClearance($clearance)
320
    {
321
        //fully spell out user's clearance.
322
        switch ($clearance) {
323
            case 'S':
324
                $clearance = 'Secret';
325
                break;
326
            case 'TS':
327
                $clearance = 'Top Secret';
328
                break;
329
            case 'Int S':
330
                $clearance = 'Interim Secret';
331
                break;
332
        }
333
334
        return $clearance;
335
    }
336
}
337