Completed
Push — master ( 863ff8...9a7373 )
by Sheela
11:06 queued 08:11
created

UserController::getUserTrainings()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 0
cts 16
cp 0
rs 8.9713
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 2
crap 6
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\Training;
16
use SET\User;
17
18
/**
19
 * Class UserController.
20
 */
21
class UserController extends Controller
22
{
23
    /**
24
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
25
     */
26
    public function index()
27
    {
28
        $this->authorize('view');
29
30
        $users = User::with([
31
            'assignedTrainings' => function ($q) {
32
                $q->whereNull('completed_date')
33
                    ->whereBetween('due_date', [Carbon::now()->subYear(), Carbon::now()->addWeeks(4)]);
34
            },
35
            'trainings',
36
        ])
37
            ->skipSystem()
38
            ->orderBy('last_name')->get();
39
40
        return view('user.index', compact('users'));
41
    }
42
43
    public function create()
44
    {
45
        $this->authorize('edit');
46
47
        $supervisors = User::skipSystem()->active()->orderBy('last_name')->get()->pluck('userFullName', 'id')->toArray();
48
        $groups = Group::all();
49
50
        return view('user.create', compact('supervisors', 'groups'));
51
    }
52
53
    /**
54
     * @param StoreUserRequest $request
55
     *
56
     * @return \Illuminate\Http\RedirectResponse
57
     */
58
    public function store(StoreUserRequest $request)
59
    {
60
        $data = $request->all();
61
        $data['status'] = 'active';
62
        $user = User::create($data);
63
64
        if (array_key_exists('groups', $data)) {
65
            settype($data['groups'], 'array');
66
            $user->groups()->sync($data['groups']);
67
        }
68
69
        return redirect()->action('UserController@index');
70
    }
71
72
    /**
73
     * @param $userId
74
     *
75
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
76
     */
77
    public function show($userId, $sectionId = null)
78
    {
79
        $user = User::with(['subordinates' => function ($query) {
80
            $query->active();
81
        },
82
                            'groups', 'duties', 'attachments',
83
                            'visits', 'notes.author', 'notes.attachments',
84
                            'travels.author', 'travels.attachments', ])
85
                    ->findOrFail($userId);
86
87
        //Make sure the user can't access other people's pages.
88
        $this->authorize('show_user', $user);
89
90
        $user['clearance'] = $this->spellOutClearance($user['clearance']);
91
        $user['access_level'] = $this->spellOutClearance($user['access_level']);
92
93
        $trainings = $this->getUserTrainings($user, $sectionId);
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
    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
     * Get all the scheduled trainings for the user and either the most recent completed
169
     * trainings or all completed trainings for the desired training type based on data values.
170
     *
171
     * @param $user
172
     * @param $data
173
     *
174
     * @return array trainings
175
     */
176
    private function getUserTrainings($user, $sectionId)
177
    {
178
        // Get the scheduled trainings and the completed trainings separately, so it will be easier to get either
179
        // the full list of completed trainings or the most recently completed training for each training type.
180
        $scheduledTrainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')
181
                                ->whereNull('completed_date');
182
        $recentCompletedTrainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')
183
                                    ->whereNotNull('completed_date')->orderBy('completed_date', 'DESC')->groupBy('training_id');
184
185
        // If the user clicks the showAll button for a particular type of training,
186
        // show all the trainings completed by that user for that training type.
187
        if ($sectionId != null) {
188
            $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...
189
190
            $completedTrainings = $user->assignedTrainings()->with('author', 'training.attachments', 'attachments')
191
                                    ->whereIn('training_id', $selectedTraining);
192
193
            $trainings = $scheduledTrainings->union($completedTrainings)->union($recentCompletedTrainings)->get();
194
        } else {
195
            $trainings = $scheduledTrainings->union($recentCompletedTrainings)->get();
196
        }
197
198
        return $trainings;
199
    }
200
201
    /**
202
     * @param $trainings[]
203
     * From the User's trainings, a list of the training types is determined and
204
     * a list of the training block titles is determined.
205
     *
206
     * @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...
207
     */
208
    public function getUserTrainingTypes($trainings = [])
209
    {
210
        $training_block_titles = $user_training_types = [];
211
        foreach ($trainings as $trainingUser) {
212
            if (is_null($trainingUser->completed_date)) {
213
                $training_block_titles['AAA'] = 'Scheduled';
214
                $user_training_types[$trainingUser->id] = 'Scheduled';
215
            } elseif ($trainingUser->Training->trainingType) {
216
                $typeName = $trainingUser->Training->trainingType->name;
217
                $training_block_titles[$typeName] = $typeName;
218
                $user_training_types[$trainingUser->id] = $typeName;
219
            } else { // No training type
220
                $training_block_titles['999'] = 'Miscellaneous';
221
                $user_training_types[$trainingUser->id] = 'Miscellaneous';
222
            }
223
        }
224
        ksort($training_block_titles);  // Order by key
225
        return [$user_training_types, $training_block_titles];
226
    }
227
228
    /**
229
     * Process our JPAS import. Once that has been handled, we pass the file, changes,
230
     * unique/unmapped users & a user list to the user.import view.
231
     * That way we keep all this data for the resolve phase.
232
     *
233
     * @param JpasImport $import
234
     *
235
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
236
     */
237
    public function import(JpasImport $import)
238
    {
239
        $results = $import->handleImport();
240
        $uploadedFile = $import->getFile('file');
241
242
        $changes = $results['changes'];
243
        $unique = $results['unique'];
244
245
        $userList = User::orderBy('last_name')->get()->pluck('UserFullName', 'id')->toArray();
246
247
        return view('user.import', compact('unique', 'changes', 'userList', 'uploadedFile'));
248
    }
249
250
    /**
251
     * @param JpasImport $import
252
     *
253
     * @return \Illuminate\Http\RedirectResponse
254
     */
255
    public function resolveImport(JpasImport $import)
256
    {
257
        $import->handleImport();
258
259
        Notification::container()->success('Import Complete');
260
261
        File::delete($import->getFile('file'));
262
263
        return redirect()->action('HomeController@index');
264
    }
265
266
    /**
267
     * Generate the grab the previous and next user if our users are sorted alphabetically.
268
     *
269
     * @param $user
270
     * @param $previous
271
     * @param $next
272
     */
273
    private function previousAndNextUsers($user, &$previous, &$next)
274
    {
275
        //Build the previous/next user that are in alphabetical order.
276
        $users = User::skipSystem()->orderBy('last_name')->orderBy('first_name')->get();
277
        $previous = null; // set to null by default in case we are at the start of the list.
278
        while ($users->first()->id != $user->id) {
279
            $previous = $users->shift()->id;
280
        }
281
        //check if we have a record aft the current user. If not, then we are at the end.
282
        if ($users->count() > 1) {
283
            $users->shift();
284
            $next = $users->shift()->id;
285
        } else {
286
            $next = null;
287
        }
288
    }
289
290
    /**
291
     * @param $clearance
292
     *
293
     * @return mixed
294
     */
295
    private function spellOutClearance($clearance)
296
    {
297
        //fully spell out user's clearance.
298
        switch ($clearance) {
299
            case 'S':
300
                $clearance = 'Secret';
301
                break;
302
            case 'TS':
303
                $clearance = 'Top Secret';
304
                break;
305
            case 'Int S':
306
                $clearance = 'Interim Secret';
307
                break;
308
        }
309
310
        return $clearance;
311
    }
312
}
313