Passed
Push — feature/preview-job-posters ( 85d5af )
by
unknown
14:13
created

JobController::show()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 67
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 5.0569

Importance

Changes 0
Metric Value
eloc 43
dl 0
loc 67
rs 8.9208
c 0
b 0
f 0
ccs 33
cts 38
cp 0.8684
cc 5
nc 6
nop 2
crap 5.0569

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace App\Http\Controllers;
4
5
use Illuminate\Support\Facades\Lang;
6
use Illuminate\Support\Facades\Auth;
7
use Illuminate\Http\RedirectResponse;
8
use Illuminate\Http\Request;
9
use Illuminate\Http\Response;
10
use Illuminate\View\View;
11
use App\Http\Controllers\Controller;
12
use Carbon\Carbon;
13
use App\Models\JobPoster;
14
use App\Models\Lookup\JobTerm;
15
use App\Models\Lookup\Province;
16
use App\Models\Lookup\SecurityClearance;
17
use App\Models\Lookup\LanguageRequirement;
18
use App\Models\Lookup\CitizenshipDeclaration;
19
use App\Models\Lookup\Department;
20
use App\Models\Lookup\SkillLevel;
21
use App\Models\Lookup\CriteriaType;
22
use App\Models\Lookup\VeteranStatus;
23
use App\Models\JobApplication;
24
use App\Models\Criteria;
25
use App\Models\Skill;
26
use App\Models\JobPosterQuestion;
27
use App\Models\JobPosterKeyTask;
28
use App\Services\Validation\JobPosterValidator;
29
use Jenssegers\Date\Date;
30
31
class JobController extends Controller
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class JobController
Loading history...
32
{
33
    /**
34
     * Display a listing of JobPosters.
35
     *
36
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
37
     */
38
    public function index()
39
    {
40
        $now = Carbon::now();
41
        //Find published jobs that are currently open for applications
42
        $jobs = JobPoster::where('open_date_time', '<=', $now)
43
            ->where('close_date_time', '>=', $now)
44
            ->where('published', true)
45
            ->get();
46
        $jobs->load('manager.work_environment');
47
        return view('applicant/job_index', [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
48
            'job_index' => Lang::get('applicant/job_index'),
49
            'jobs' => $jobs
50
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
51
    }
52
53
    /**
54
     * Display a listing of a manager's JobPosters.
55
     *
56
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
57
     */
58 2
    public function managerIndex()
59
    {
60 2
        $manager = Auth::user()->manager;
0 ignored issues
show
Bug introduced by
Accessing manager on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
61
62 2
        $veteran_applications = [];
63 2
        $citizen_applications = [];
64 2
        $other_applications = [];
65
66 2
        foreach ($manager->job_posters as $job) {
67 2
            $job->submitted_applications->load(['veteran_status', 'citizenship_declaration']);
68
            $veteran_applications[$job->id] = $job->submitted_applications->filter(function ($application) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
69
                return $application->veteran_status->name !== "none" &&
70
                    $application->citizenship_declaration->name === "citizen";
71 2
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
72
            $citizen_applications[$job->id] = $job->submitted_applications->filter(function ($application) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
73
                return $application->veteran_status->name === "none" &&
74
                    $application->citizenship_declaration->name === "citizen";
75 2
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
76
            $other_applications[$job->id] = $job->submitted_applications->filter(function ($application) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
77
                return $application->citizenship_declaration->name !== "citizen";
78 2
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
79
        }
80
81 2
        return view('manager/job_index', [
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
82 2
            "manager_job_index" => [
83
                "title" => "My Job Posts"
84
            ],
85 2
            'jobs' => $manager->job_posters,
86 2
            'veteran_applications' => $veteran_applications,
87 2
            'citizen_applications' => $citizen_applications,
88 2
            'other_applications' => $other_applications,
89
        ]);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
90
    }
91
92
    /**
93
     * Display the specified job poster.
94
     *
95
     * @param \Illuminate\Http\Request $request   Incoming request object.
96
     * @param \App\Models\JobPoster    $jobPoster Job Poster object.
97
     *
98
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
99
     */
100 6
    public function show(Request $request, JobPoster $jobPoster)
101
    {
102 6
        $user = Auth::user();
103
104
        //TODO: Improve workplace photos, and reference them in template direction from WorkEnvironment model
105 6
        $workplacePhotos = [];
106 6
        foreach ($jobPoster->manager->work_environment->workplace_photo_captions as $photoCaption) {
107
            $workplacePhotos[] = [
108
                'description' => $photoCaption->description,
109
                'url' => '/images/user.png'
110
            ];
111
        }
112
113
        //TODO: replace route('manager.show',manager.id) in templates with link using slug
114
115
        $criteria = [
116 6
            'essential' => $jobPoster->criteria->filter(
117
                function ($value, $key) {
118
                    return $value->criteria_type->name == 'essential';
119 6
                }
120
            ),
121 6
            'asset' => $jobPoster->criteria->filter(
122
                function ($value, $key) {
123
                    return $value->criteria_type->name == 'asset';
124 6
                }
125
            ),
126
        ];
127
128 6
        $jobLang = Lang::get('applicant/job_post');
129
130 6
        $applyButton = [];
131
132 6
        if (isset($user)) {
133 4
            if (!$jobPoster->published && $this->authorize('update', $jobPoster)) {
134
                $applyButton = [
135 2
                    'href' => route('manager.jobs.edit', $jobPoster->id),
136 2
                    'title' => $jobLang['apply']['edit_link_title'],
137 2
                    'text' => $jobLang['apply']['edit_link_label'],
138
                ];
139
            } else {
140
                $applyButton = [
141 2
                    'href' => route('job.application.edit.1', $jobPoster->id),
142 2
                    'title' => $jobLang['apply']['apply_link_title'],
143 4
                    'text' => $jobLang['apply']['apply_link_label'],
144
                ];
145
            }
146
        } else {
147
            $applyButton = [
148 2
                'href' => route('job.application.edit.1', $jobPoster->id),
149 2
                'title' => $jobLang['apply']['login_link_title'],
150 2
                'text' => $jobLang['apply']['login_link_label'],
151
            ];
152
        }
153
154 6
        return view(
155 6
            'applicant/job_post',
156
            [
157 6
                'job_post' => $jobLang,
158 6
                'manager' => $jobPoster->manager,
159 6
                'manager_profile_photo_url' => '/images/user.png', //TODO get real photo
160 6
                'team_culture' => $jobPoster->manager->team_culture,
161 6
                'work_environment' => $jobPoster->manager->work_environment,
162 6
                'workplace_photos' => $workplacePhotos,
163 6
                'job' => $jobPoster,
164 6
                'criteria' => $criteria,
165 6
                'apply_button' => $applyButton,
166 6
                'skill_template' => Lang::get('common/skills'),
167
            ]
168
        );
169
    }
170
171
    /**
172
     * Display the form for creating a new Job Poster
173
     *
174
     * @param \Illuminate\Http\Request $request Incoming request object.
175
     *
176
     * @return \Illuminate\View\View Job Create view
177
     */
178 2
    public function create(Request $request) : View
179
    {
180 2
        return $this->populateCreateView($request);
181
    }
182
183
    /**
184
     * Display the form for editing an existing Job Poster
185
     *
186
     * @param \Illuminate\Http\Request $request   Incoming request object.
187
     * @param \App\Models\JobPoster    $jobPoster Job Poster object.
188
     *
189
     * @return \Illuminate\View\View Job Create view
190
     */
191 2
    public function edit(Request $request, JobPoster $jobPoster) : View
192
    {
193 2
        return $this->populateCreateView($request, $jobPoster);
194
    }
195
196
    /**
197
     * Get the manager from the request object and check if creating or editing
198
     *
199
     * @param \Illuminate\Http\Request $request   Incoming request object.
200
     * @param \App\Models\JobPoster    $jobPoster Optional Job Poster object.
201
     *
202
     * @return \Illuminate\View\View Job Create view
203
     */
204 4
    public function populateCreateView(Request $request, JobPoster $jobPoster = null) : View
205
    {
206 4
        $manager = $request->user() ? $request->user()->manager : null;
207 4
        if (isset($jobPoster)) {
208 2
            $job = $jobPoster;
209 2
            $route = ['manager.jobs.store', $jobPoster];
210 2
            $jobHeading = 'manager/job_edit';
211
        } else {
212 2
            $job = [];
213 2
            $route = ['manager.jobs.store'];
214 2
            $jobHeading = 'manager/job_create';
215
        }
216
217 4
        $skillLangs = Lang::get('common/skills');
218
219 4
        $softSkills = Skill::whereHas(
220 4
            'skill_type',
221
            function ($query) : void {
222 4
                $query->where('name', '=', 'soft');
223 4
            }
224 4
        )->get()
225 4
            ->mapWithKeys(
226
                function ($skill) use ($skillLangs) {
227
                    return [
228 4
                        $skill->id => $skillLangs['skills'][$skill->name]['name']
229
                    ];
230 4
                }
231
            )
232 4
            ->all();
233
234 4
        $hardSkills = Skill::whereHas(
235 4
            'skill_type',
236
            function ($query) : void {
237 4
                $query->where('name', '=', 'hard');
238 4
            }
239 4
        )->get()
240 4
            ->mapWithKeys(
241
                function ($skill) use ($skillLangs) {
242
                    return [
243 4
                        $skill->id => $skillLangs['skills'][$skill->name]['name']
244
                    ];
245 4
                }
246
            )
247 4
            ->all();
248
249 4
        asort($softSkills, SORT_LOCALE_STRING);
250 4
        asort($hardSkills, SORT_LOCALE_STRING);
251
252
        $skills = [
253
            'essential' => [
254 4
                'hard' => $hardSkills,
255 4
                'soft' => $softSkills
256
            ],
257
            'asset' => [
258 4
                'hard' => $hardSkills,
259 4
                'soft' => $softSkills
260
            ]
261
        ];
262
263 4
        $skillLevelCollection = SkillLevel::all();
264
265 4
        $skillLevels = array();
266
267 4
        $skillLevels['hard'] = $skillLevelCollection->mapWithKeys(
268
            function ($skillLevel) use ($skillLangs) {
269 4
                return [$skillLevel->id => $skillLangs['skill_levels']['hard'][$skillLevel->name]];
270 4
            }
271 4
        )->all();
272
273 4
        $skillLevels['soft'] = $skillLevelCollection->mapWithKeys(
274
            function ($skillLevel) use ($skillLangs) {
275 4
                return [$skillLevel->id => $skillLangs['skill_levels']['soft'][$skillLevel->name]];
276 4
            }
277 4
        )->all();
278
279 4
        return view(
280 4
            'manager/job_create',
281
            [
282 4
                'job_heading' => Lang::get($jobHeading),
283 4
                'manager' => $manager,
284 4
                'provinces' => Province::all(),
285 4
                'departments' => Department::all(),
286 4
                'language_requirments' => LanguageRequirement::all(),
287 4
                'security_clearances' => SecurityClearance::all(),
288 4
                'job' => $job,
289 4
                'form_action_url' => route(/** @scrutinizer ignore-type */ ...$route), // phpcs:ignore
0 ignored issues
show
Bug introduced by
$route is expanded, but the parameter $name of route() does not expect variable arguments. ( Ignorable by Annotation )

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

289
                'form_action_url' => route(/** @scrutinizer ignore-type */ /** @scrutinizer ignore-type */ ...$route), // phpcs:ignore
Loading history...
290 4
                'skills' => $skills,
291 4
                'skill_levels' => $skillLevels,
292 4
                'skill_template' => $skillLangs,
293
            ]
294
        );
295
    }
296
297
    /**
298
     * Create a new resource in storage
299
     *
300
     * @param \Illuminate\Http\Request $request   Incoming request object.
301
     * @param \App\Models\JobPoster    $jobPoster Optional Job Poster object.
302
     *
303
     * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
304
     */
305 2
    public function store(Request $request, JobPoster $jobPoster = null)
306
    {
307
        // Don't allow edits for published Job Posters
308
        // Also check auth while we're at it
309 2
        if (isset($jobPoster)) {
310
            $this->authorize('update', $jobPoster);
311
            JobPosterValidator::validateUnpublished($jobPoster);
312
        } else {
313 2
            $this->authorize('create', JobPoster::class);
314
        }
315
316 2
        $input = $request->input();
317
318 2
        $job = (isset($jobPoster) ? $jobPoster : new JobPoster());
319
320 2
        $job->manager_id = $request->user()->manager->id;
321 2
        $job->published = ($input['submit'] == 'publish');
322
323 2
        $this->fillAndSaveJobPoster($input, $job);
324
325 2
        $this->fillAndSaveJobPosterTasks($input, $job, isset($jobPoster));
326
327 2
        $this->fillAndSaveJobPosterQuestions($input, $job, isset($jobPoster));
328
329 2
        $this->fillAndSaveJobPosterCriteria($input, $job, isset($jobPoster));
330
331 2
        $route = $job->published ? route('manager.jobs.index') : route('manager.jobs.show', $job->id);
332
333 2
        return redirect($route);
334
    }
335
336
    /**
337
     * Fill Job Poster model's properties and save
338
     *
339
     * @param mixed[]               $input     Field values.
340
     * @param \App\Models\JobPoster $jobPoster Job Poster object.
341
     *
342
     * @return void
343
     */
344 2
    protected function fillAndSaveJobPoster(array $input, JobPoster $jobPoster) : void
345
    {
346 2
        $jobPoster->fill(
347
            [
348 2
                'job_term_id' => JobTerm::where('name', 'month')->firstOrFail()->id,
349 2
                'term_qty' => $input['term_qty'],
350 2
                'open_date_time' => new Date($input['open_date'] . $input['open_time']),
351 2
                'close_date_time' => new Date($input['close_date'] . $input['close_time']),
352 2
                'start_date_time' => new Date($input['start_date_time']),
353 2
                'department_id' => $input['department'],
354 2
                'province_id' => $input['province'],
355 2
                'salary_min' => $input['salary_min'],
356 2
                'salary_max' => $input['salary_max'],
357 2
                'noc' => $input['noc'],
358 2
                'classification' => $input['classification'],
359 2
                'security_clearance_id' => $input['security_clearance'],
360 2
                'language_requirement_id' => $input['language_requirement'],
361 2
                'remote_work_allowed' => (isset($input['remote_work_allowed']) ? $input['remote_work_allowed'] : false),
362
                'en' => [
363 2
                    'city' => $input['city'],
364 2
                    'title' => $input['title']['en'],
365 2
                    'impact' => $input['impact']['en'],
366 2
                    'branch' => $input['branch']['en'],
367 2
                    'division' => $input['division']['en'],
368 2
                    'education' => $input['education']['en'],
369
                ],
370
                'fr' => [
371 2
                    'city' => $input['city'],
372 2
                    'title' => $input['title']['fr'],
373 2
                    'impact' => $input['impact']['fr'],
374 2
                    'branch' => $input['branch']['fr'],
375 2
                    'division' => $input['division']['fr'],
376 2
                    'education' => $input['education']['fr'],
377
                ],
378
            ]
379
        );
380 2
        $jobPoster->save();
381 2
    }
382
383
    /**
384
     * Fill Job Poster's tasks and save
385
     *
386
     * @param mixed[]               $input     Field values.
387
     * @param \App\Models\JobPoster $jobPoster Job Poster object.
388
     * @param boolean               $replace   Remove existing relationships.
389
     *
390
     * @return void
391
     */
392 2
    protected function fillAndSaveJobPosterTasks(array $input, JobPoster $jobPoster, bool $replace) : void
393
    {
394 2
        if ($replace) {
395
            $jobPoster->job_poster_key_tasks()->delete();
396
        }
397
398 2
        if (!array_key_exists('task', $input) || !is_array($input['task'])) {
399 2
            return;
400
        }
401
402
        foreach ($input['task'] as $task) {
403
            $jobPosterTask = new JobPosterKeyTask();
404
            $jobPosterTask->job_poster_id = $jobPoster->id;
405
            $jobPosterTask->fill(
406
                [
407
                    'en' => [
408
                        'description' => $task['en']
409
                    ],
410
                    'fr' => [
411
                        'description' => $task['fr']
412
                    ]
413
                ]
414
            );
415
            $jobPosterTask->save();
416
        }
417
    }
418
419
    /**
420
     * Fill Job Poster's questions and save
421
     *
422
     * @param mixed[]               $input     Field values.
423
     * @param \App\Models\JobPoster $jobPoster Job Poster object.
424
     * @param boolean               $replace   Remove existing relationships.
425
     *
426
     * @return void
427
     */
428 2
    protected function fillAndSaveJobPosterQuestions(array $input, JobPoster $jobPoster, bool $replace) : void
429
    {
430 2
        if ($replace) {
431
            $jobPoster->job_poster_questions()->delete();
432
        }
433
434 2
        if (!array_key_exists('question', $input) || !is_array($input['question'])) {
435 2
            return;
436
        }
437
438
        foreach ($input['question'] as $question) {
439
            $jobQuestion = new JobPosterQuestion();
440
            $jobQuestion->job_poster_id = $jobPoster->id;
441
            $jobQuestion->fill(
442
                [
443
                    'en' => [
444
                        'question' => $question['question']['en'],
445
                        'description' => $question['description']['en']
446
                    ],
447
                    'fr' => [
448
                        'question' => $question['question']['fr'],
449
                        'description' => $question['description']['fr']
450
                    ]
451
                ]
452
            );
453
            $jobQuestion->save();
454
        }
455
    }
456
457
    /**
458
     * Fill Job Poster's criteria and save
459
     *
460
     * @param mixed[]               $input     Field values.
461
     * @param \App\Models\JobPoster $jobPoster Job Poster object.
462
     * @param boolean               $replace   Remove existing relationships.
463
     *
464
     * @return void
465
     */
466 2
    protected function fillAndSaveJobPosterCriteria(array $input, JobPoster $jobPoster, bool $replace) : void
467
    {
468 2
        if ($replace) {
469
            $jobPoster->criteria()->delete();
470
        }
471
472 2
        if (!array_key_exists('criteria', $input) || !is_array($input['criteria'])) {
473 2
            return;
474
        }
475
476
        $criteria = $input['criteria'];
477
478
        $combinedCriteria = [];
479
        if (isset($criteria['old'])) {
480
            $combinedCriteria = array_replace_recursive($combinedCriteria, $criteria['old']);
481
        }
482
        if (isset($criteria['new'])) {
483
            $combinedCriteria = array_replace_recursive($combinedCriteria, $criteria['new']);
484
        }
485
486
        if (! empty($combinedCriteria)) {
487
            foreach ($combinedCriteria as $criteriaType => $criteriaTypeInput) {
488
                foreach ($criteriaTypeInput as $skillType => $skillTypeInput) {
489
                    foreach ($skillTypeInput as $criteriaInput) {
490
                        $criteria = new Criteria();
491
                        $criteria->job_poster_id = $jobPoster->id;
492
                        $criteria->fill(
493
                            [
494
                                'criteria_type_id' => CriteriaType::where('name', $criteriaType)->firstOrFail()->id,
495
                                'skill_id' => $criteriaInput['skill_id'],
496
                                'skill_level_id' => $criteriaInput['skill_level_id'],
497
                                'en' => [
498
                                    'description' => $criteriaInput['description']['en'],
499
                                ],
500
                                'fr' => [
501
                                    'description' => $criteriaInput['description']['fr'],
502
                                ],
503
                            ]
504
                        );
505
                        $criteria->save();
506
                    }
507
                }
508
            }
509
        }
510
    }
511
}
512