Completed
Push — master ( ac047e...863ff8 )
by Sheela
06:46
created

UserController::getUserTrainings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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