Passed
Push — feature/job-builder/step-03 ( c9515d...117b8c )
by Yonathan
12:37
created

JobController::submitForReview()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.003

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 21
ccs 10
cts 11
cp 0.9091
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 2.003
1
<?php
2
3
namespace App\Http\Controllers;
4
5
use Illuminate\Support\Facades\Lang;
6
use Illuminate\Support\Facades\Auth;
7
use Illuminate\Support\Facades\Log;
8
use Illuminate\Support\Facades\Mail;
9
use Illuminate\Http\Request;
10
use App\Http\Controllers\Controller;
11
12
use Carbon\Carbon;
13
14
use App\Mail\JobPosterReviewRequested;
15
16
use App\Models\Criteria;
17
use App\Models\JobPoster;
18
use App\Models\JobPosterKeyTask;
19
use App\Models\JobPosterQuestion;
20
use App\Models\Lookup\JobTerm;
21
use App\Models\Lookup\Province;
22
use App\Models\Lookup\SecurityClearance;
23
use App\Models\Lookup\LanguageRequirement;
24
use App\Models\Lookup\Department;
25
use App\Models\Lookup\SkillLevel;
26
use App\Models\Lookup\CriteriaType;
27
use App\Models\Skill;
28
use App\Models\Manager;
29
30
use App\Services\Validation\JobPosterValidator;
31
use Jenssegers\Date\Date;
32
use App\Models\AssessmentPlanNotification;
33
use App\Models\Assessment;
34
35
class JobController extends Controller
36
{
37
    /**
38
     * Display a listing of JobPosters.
39
     *
40
     * @return \Illuminate\Http\Response
41
     */
42
    public function index()
43
    {
44
        $now = Carbon::now();
45
46
        // Find published jobs that are currently open for applications.
47
        // Eager load required relationships: Department, Province, JobTerm.
48
        // Eager load the count of submitted applications, to prevent the relationship
49
        // from being actually loaded and firing off events.
50
        $jobs = JobPoster::where('open_date_time', '<=', $now)
51
            ->where('close_date_time', '>=', $now)
52
            ->where('published', true)
53
            ->with([
54
                'department',
55
                'province',
56
                'job_term',
57
            ])
58
            ->withCount([
59
                'submitted_applications',
60
            ])
61
            ->get();
62
        return view('applicant/job_index', [
63
            'job_index' => Lang::get('applicant/job_index'),
64
            'jobs' => $jobs
65
        ]);
66
    }
67
68
    /**
69
     * Display a listing of a manager's JobPosters.
70
     *
71
     * @return \Illuminate\Http\Response
72
     */
73 1
    public function managerIndex()
74
    {
75 1
        $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...
76 1
        $jobs = JobPoster::where('manager_id', $manager->id)
77 1
            ->withCount('submitted_applications')
78 1
            ->get();
79
80 1
        return view('manager/job_index', [
81
            // Localization Strings.
82 1
            'jobs_l10n' => Lang::get('manager/job_index'),
83
            // Data.
84 1
            'jobs' => $jobs,
85
        ]);
86
    }
87
88
    /**
89
     * Submit the Job Poster for review.
90
     *
91
     * @param  \Illuminate\Http\Request $request   Incoming request object.
92
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
93
     * @return \Illuminate\Http\Response
94
     */
95 1
    public function submitForReview(Request $request, JobPoster $jobPoster)
96
    {
97
        // Update review request timestamp.
98 1
        $jobPoster->review_requested_at = new Date();
99 1
        $jobPoster->save();
100
101
        // Refresh model instance with updated DB values.
102 1
        $jobPoster = JobPoster::withCount('submitted_applications')->where('id', $jobPoster->id)->first();
103
104
        // Send email.
105 1
        $reviewer_email = config('mail.reviewer_email');
106 1
        if (isset($reviewer_email)) {
107 1
            Mail::to($reviewer_email)->send(new JobPosterReviewRequested($jobPoster, Auth::user()));
0 ignored issues
show
Bug introduced by
It seems like Illuminate\Support\Facades\Auth::user() can also be of type null; however, parameter $manager of App\Mail\JobPosterReviewRequested::__construct() does only seem to accept App\Models\User, maybe add an additional type check? ( Ignorable by Annotation )

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

107
            Mail::to($reviewer_email)->send(new JobPosterReviewRequested($jobPoster, /** @scrutinizer ignore-type */ Auth::user()));
Loading history...
108
        } else {
109
            Log::error('The reviewer email environment variable is not set.');
110
        }
111
112 1
        return view('manager/job_index/job', [
113
            // Localization Strings.
114 1
            'jobs_l10n' => Lang::get('manager/job_index'),
115 1
            'job' => $jobPoster
116
        ]);
117
    }
118
119
    /**
120
     * Delete a draft Job Poster.
121
     *
122
     * @param  \Illuminate\Http\Request $request   Incoming request object.
123
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
124
     * @return \Illuminate\Http\Response
1 ignored issue
show
Coding Style introduced by
Function return type is not void, but function has no return statement
Loading history...
125
     */
126
    public function destroy(Request $request, JobPoster $jobPoster)
127
    {
128
        $jobPoster->delete();
129
    }
130
131
    /**
132
     * Display the specified job poster.
133
     *
134
     * @param  \Illuminate\Http\Request $request   Incoming request object.
135
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
136
     * @return \Illuminate\Http\Response
137
     */
138 6
    public function show(Request $request, JobPoster $jobPoster)
139
    {
140 6
        $jobPoster->load([
141 6
            'department',
142
            'criteria.skill.skill_type',
143
            'manager.team_culture',
144
            'manager.work_environment'
145
        ]);
146
147 6
        $user = Auth::user();
0 ignored issues
show
Unused Code introduced by
The assignment to $user is dead and can be removed.
Loading history...
148
149
        // TODO: Improve workplace photos, and reference them in template direction from WorkEnvironment model.
150 6
        $workplacePhotos = [];
151 6
        foreach ($jobPoster->manager->work_environment->workplace_photo_captions as $photoCaption) {
152
            $workplacePhotos[] = [
153
                'description' => $photoCaption->description,
154
                'url' => '/images/user.png'
155
            ];
156
        }
157
158
        // TODO: replace route('manager.show',manager.id) in templates with link using slug.
159
        $criteria = [
160 6
            'essential' => $jobPoster->criteria->filter(
161
                function ($value, $key) {
162 4
                    return $value->criteria_type->name == 'essential';
163 6
                }
164
            ),
165 6
            'asset' => $jobPoster->criteria->filter(
166
                function ($value, $key) {
167 4
                    return $value->criteria_type->name == 'asset';
168 6
                }
169
            ),
170
        ];
171
172 6
        $jobLang = Lang::get('applicant/job_post');
173
174 6
        $applyButton = [];
175 6
        if (!$jobPoster->published && $this->authorize('update', $jobPoster)) {
176
            $applyButton = [
177 4
                'href' => route('manager.jobs.edit', $jobPoster->id),
178 4
                'title' => $jobLang['apply']['edit_link_title'],
179 4
                'text' => $jobLang['apply']['edit_link_label'],
180
            ];
181 2
        } elseif (Auth::check() && $jobPoster->isOpen()) {
182
            $applyButton = [
183 1
                'href' => route('job.application.edit.1', $jobPoster->id),
184 1
                'title' => $jobLang['apply']['apply_link_title'],
185 1
                'text' => $jobLang['apply']['apply_link_label'],
186
            ];
187 1
        } elseif (Auth::guest() && $jobPoster->isOpen()) {
188
            $applyButton = [
189 1
                'href' => route('job.application.edit.1', $jobPoster->id),
190 1
                'title' => $jobLang['apply']['login_link_title'],
191 1
                'text' => $jobLang['apply']['login_link_label'],
192
            ];
193
        } else {
194
            $applyButton = [
195
                'href' => null,
196
                'title' => null,
197
                'text' => $jobLang['apply']['job_closed_label'],
198
            ];
199
        }
200
201 6
        return view(
202 6
            'applicant/job_post',
203
            [
204 6
                'job_post' => $jobLang,
205 6
                'manager' => $jobPoster->manager,
206 6
                'manager_profile_photo_url' => '/images/user.png', // TODO get real photo.
207 6
                'team_culture' => $jobPoster->manager->team_culture,
208 6
                'work_environment' => $jobPoster->manager->work_environment,
209 6
                'workplace_photos' => $workplacePhotos,
210 6
                'job' => $jobPoster,
211 6
                'criteria' => $criteria,
212 6
                'apply_button' => $applyButton,
213 6
                'skill_template' => Lang::get('common/skills'),
214
            ]
215
        );
216
    }
217
218
    /**
219
     * Create a blank job poster for the specified manager
220
     *
221
     * @param  \App\Models\Manager $manager Incoming Manager object.
222
     * @return \Illuminate\Http\Response Job Create view
223
     */
224 2
    public function createAsManager(Manager $manager)
225
    {
226 2
        $jobPoster = new JobPoster();
227 2
        $jobPoster->manager_id = $manager->id;
228
229 2
        $jobPoster->save();
230
231 2
        $defaultQuestions = $this->populateDefaultQuestions();
232 2
        if (!empty($defaultQuestions)) {
233 2
            $jobPoster->job_poster_questions()->saveMany($defaultQuestions);
234
        }
235
236 2
        return redirect()->route('manager.jobs.edit', $jobPoster->id);
237
    }
238
239
    /**
240
     * Display the form for creating a new Job Poster
241
     *
242
     * @param  \Illuminate\Http\Request $request Incoming request object.
243
     * @return \Illuminate\Http\Response Job Create view
244
     */
245
    public function create(Request $request)
246
    {
247
        return $this->populateCreateView($request);
248
    }
249
250
    /**
251
     * Display the form for editing an existing Job Poster
252
     *
253
     * @param  \Illuminate\Http\Request $request   Incoming request object.
254
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
255
     * @return \Illuminate\Http\Response
256
     */
257 1
    public function edit(Request $request, JobPoster $jobPoster)
258
    {
259 1
        return $this->populateCreateView($request, $jobPoster);
260
    }
261
262
    /**
263
     * Get the manager from the request object and check if creating or editing
264
     *
265
     * @param  \Illuminate\Http\Request $request   Incoming request object.
266
     * @param  \App\Models\JobPoster    $jobPoster Optional Job Poster object.
267
     * @return \Illuminate\Http\Response
268
     */
269 1
    public function populateCreateView(Request $request, JobPoster $jobPoster = null)
270
    {
271 1
        if ($jobPoster == null || $jobPoster->manager == null) {
272
            $manager = $request->user() ? $request->user()->manager : null;
273
        } else {
274 1
            $manager = $jobPoster->manager;
275
        }
276
277 1
        if (isset($jobPoster)) {
278 1
            $job = $jobPoster;
279 1
            $route = ['manager.jobs.update', $jobPoster];
280 1
            $jobHeading = 'manager/job_edit';
281
        } else {
282
            $job = [];
283
            $defaultQuestions = $this->populateDefaultQuestions();
284
            if (!empty($defaultQuestions)) {
285
                $job['job_poster_questions'] = $defaultQuestions;
286
            }
287
            $route = ['manager.jobs.store'];
288
            $jobHeading = 'manager/job_create';
289
        }
290
291 1
        $skillLangs = Lang::get('common/skills');
292
293 1
        $softSkills = Skill::whereHas(
294 1
            'skill_type',
295
            function ($query) : void {
296 1
                $query->where('name', '=', 'soft');
297 1
            }
298 1
        )->get()
299 1
            ->mapWithKeys(
300
                function ($skill) {
301
                    return [
302 1
                        $skill->id => $skill->name
303
                    ];
304 1
                }
305
            )
306 1
            ->all();
307
308 1
        $hardSkills = Skill::whereHas(
309 1
            'skill_type',
310
            function ($query) : void {
311 1
                $query->where('name', '=', 'hard');
312 1
            }
313 1
        )->get()
314 1
            ->mapWithKeys(
315
                function ($skill) {
316
                    return [
317 1
                        $skill->id => $skill->name
318
                    ];
319 1
                }
320
            )
321 1
            ->all();
322
323 1
        asort($softSkills, SORT_LOCALE_STRING);
324 1
        asort($hardSkills, SORT_LOCALE_STRING);
325
326
        $skills = [
327
            'essential' => [
328 1
                'hard' => $hardSkills,
329 1
                'soft' => $softSkills
330
            ],
331
            'asset' => [
332 1
                'hard' => $hardSkills,
333 1
                'soft' => $softSkills
334
            ]
335
        ];
336
337 1
        $skillLevelCollection = SkillLevel::all();
338
339 1
        $skillLevels = array();
340
341 1
        $skillLevels['hard'] = $skillLevelCollection->mapWithKeys(
342
            function ($skillLevel) use ($skillLangs) {
343 1
                return [$skillLevel->id => $skillLangs['skill_levels']['hard'][$skillLevel->name]];
344 1
            }
345 1
        )->all();
346
347 1
        $skillLevels['soft'] = $skillLevelCollection->mapWithKeys(
348
            function ($skillLevel) use ($skillLangs) {
349 1
                return [$skillLevel->id => $skillLangs['skill_levels']['soft'][$skillLevel->name]];
350 1
            }
351 1
        )->all();
352
353 1
        return view(
354 1
            'manager/job_create',
355
            [
356
                // Localization Strings.
357 1
                'job_l10n' => Lang::get('manager/job_create'),
358
                // Data.
359 1
                'job' => Lang::get($jobHeading),
360 1
                'manager' => $manager,
361 1
                'provinces' => Province::all(),
362 1
                'departments' => Department::all(),
363 1
                'language_requirments' => LanguageRequirement::all(),
364 1
                'security_clearances' => SecurityClearance::all(),
365 1
                'job' => $job,
366 1
                '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

366
                'form_action_url' => route(/** @scrutinizer ignore-type */ /** @scrutinizer ignore-type */ ...$route), // phpcs:ignore
Loading history...
367 1
                'skills' => $skills,
368 1
                'skill_levels' => $skillLevels,
369 1
                'skill_template' => $skillLangs,
370
            ]
371
        );
372
    }
373
374
    /**
375
     * Create a new resource in storage
376
     *
377
     * @param  \Illuminate\Http\Request $request   Incoming request object.
378
     * @param  \App\Models\JobPoster    $jobPoster Optional Job Poster object.
379
     * @return \Illuminate\Http\Response
380
     */
381 6
    public function store(Request $request, JobPoster $jobPoster = null)
382
    {
383
        // Don't allow edits for published Job Posters
384
        // Also check auth while we're at it.
385 6
        if (isset($jobPoster)) {
386 6
            $this->authorize('update', $jobPoster);
387 6
            JobPosterValidator::validateUnpublished($jobPoster);
388
        } else {
389
            $this->authorize('create', JobPoster::class);
390
        }
391
392 6
        $input = $request->input();
393
394 6
        $job = (isset($jobPoster) ? $jobPoster : new JobPoster());
395
396 6
        if ($job->manager_id == null) {
397
            $job->manager_id = $request->user()->manager->id;
398
            $job->save();
399
        }
400
401 6
        $this->fillAndSaveJobPoster($input, $job);
402
403 6
        $this->fillAndSaveJobPosterTasks($input, $job, isset($jobPoster));
404
405 6
        $this->fillAndSaveJobPosterQuestions($input, $job, isset($jobPoster));
406
407 6
        $this->fillAndSaveJobPosterCriteria($input, $job, isset($jobPoster));
0 ignored issues
show
Unused Code introduced by
The call to App\Http\Controllers\Job...SaveJobPosterCriteria() has too many arguments starting with IssetNode. ( Ignorable by Annotation )

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

407
        $this->/** @scrutinizer ignore-call */ 
408
               fillAndSaveJobPosterCriteria($input, $job, isset($jobPoster));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
408
409 6
        return redirect(route('manager.jobs.show', $job->id));
410
    }
411
412
    /**
413
     * Fill Job Poster model's properties and save
414
     *
415
     * @param  mixed[]               $input     Field values.
416
     * @param  \App\Models\JobPoster $jobPoster Job Poster object.
417
     * @return void
418
     */
419 6
    protected function fillAndSaveJobPoster(array $input, JobPoster $jobPoster) : void
420
    {
421 6
        $jobPoster->fill(
422
            [
423 6
                'job_term_id' => JobTerm::where('name', 'month')->firstOrFail()->id,
424 6
                'term_qty' => $input['term_qty'],
425 6
                'open_date_time' => ptDayStartToUtcTime($input['open_date']),
426 6
                'close_date_time' => ptDayEndToUtcTime($input['close_date']),
427 6
                'start_date_time' => ptDayStartToUtcTime($input['start_date']),
428 6
                'department_id' => $input['department'],
429 6
                'province_id' => $input['province'],
430 6
                'salary_min' => $input['salary_min'],
431 6
                'salary_max' => $input['salary_max'],
432 6
                'noc' => $input['noc'],
433 6
                'classification' => $input['classification'],
434 6
                'security_clearance_id' => $input['security_clearance'],
435 6
                'language_requirement_id' => $input['language_requirement'],
436 6
                'remote_work_allowed' => (isset($input['remote_work_allowed']) ? $input['remote_work_allowed'] : false),
437
                'en' => [
438 6
                    'city' => $input['city'],
439 6
                    'title' => $input['title']['en'],
440 6
                    'impact' => $input['impact']['en'],
441 6
                    'branch' => $input['branch']['en'],
442 6
                    'division' => $input['division']['en'],
443 6
                    'education' => $input['education']['en'],
444
                ],
445
                'fr' => [
446 6
                    'city' => $input['city'],
447 6
                    'title' => $input['title']['fr'],
448 6
                    'impact' => $input['impact']['fr'],
449 6
                    'branch' => $input['branch']['fr'],
450 6
                    'division' => $input['division']['fr'],
451 6
                    'education' => $input['education']['fr'],
452
                ],
453
            ]
454
        );
455 6
        $jobPoster->save();
456 6
    }
457
458
    /**
459
     * Fill Job Poster's tasks and save
460
     *
461
     * @param  mixed[]               $input     Field values.
462
     * @param  \App\Models\JobPoster $jobPoster Job Poster object.
463
     * @param  boolean               $replace   Remove existing relationships.
464
     * @return void
465
     */
466 6
    protected function fillAndSaveJobPosterTasks(array $input, JobPoster $jobPoster, bool $replace) : void
467
    {
468 6
        if ($replace) {
469 6
            $jobPoster->job_poster_key_tasks()->delete();
470
        }
471
472 6
        if (!array_key_exists('task', $input) || !is_array($input['task'])) {
473 6
            return;
474
        }
475
476
        foreach ($input['task'] as $task) {
477
            $jobPosterTask = new JobPosterKeyTask();
478
            $jobPosterTask->job_poster_id = $jobPoster->id;
479
            $jobPosterTask->fill(
480
                [
481
                    'en' => [
482
                        'description' => $task['en']
483
                    ],
484
                    'fr' => [
485
                        'description' => $task['fr']
486
                    ]
487
                ]
488
            );
489
            $jobPosterTask->save();
490
        }
491
    }
492
493
    /**
494
     * Fill Job Poster's questions and save
495
     *
496
     * @param  mixed[]               $input     Field values.
497
     * @param  \App\Models\JobPoster $jobPoster Job Poster object.
498
     * @param  boolean               $replace   Remove existing relationships.
499
     * @return void
500
     */
501 6
    protected function fillAndSaveJobPosterQuestions(array $input, JobPoster $jobPoster, bool $replace) : void
502
    {
503 6
        if ($replace) {
504 6
            $jobPoster->job_poster_questions()->delete();
505
        }
506
507 6
        if (!array_key_exists('question', $input) || !is_array($input['question'])) {
508 6
            return;
509
        }
510
511
        foreach ($input['question'] as $question) {
512
            $jobQuestion = new JobPosterQuestion();
513
            $jobQuestion->job_poster_id = $jobPoster->id;
514
            $jobQuestion->fill(
515
                [
516
                    'en' => [
517
                        'question' => $question['question']['en'],
518
                        'description' => $question['description']['en']
519
                    ],
520
                    'fr' => [
521
                        'question' => $question['question']['fr'],
522
                        'description' => $question['description']['fr']
523
                    ]
524
                ]
525
            );
526
            $jobQuestion->save();
527
        }
528
    }
529
530
    /**
531
     * Fill Job Poster's criteria and save
532
     *
533
     * @param  mixed[]               $input     Field values.
534
     * @param  \App\Models\JobPoster $jobPoster Job Poster object.
535
     * @return void
536
     */
537 6
    protected function fillAndSaveJobPosterCriteria(array $input, JobPoster $jobPoster) : void
538
    {
539 6
        $affectedCriteriaIds = [];
540
541 6
        if (array_key_exists('criteria', $input) && is_array($input['criteria'])) {
542 2
            $criteria = $input['criteria'];
543
544
            // Old criteria must be updated, using the criteriaId that comes from the form element names.
545 2
            if (!empty($criteria['old'])) {
546 1
                foreach ($criteria['old'] as $criteriaType => $criteriaTypeInput) {
547 1
                    foreach ($criteriaTypeInput as $skillTypeInput) {
548 1
                        foreach ($skillTypeInput as $criteriaId => $criteriaInput) {
549 1
                            $updatedCriteria = $this->processCriteriaForm($jobPoster, $criteriaType, $criteriaInput, $criteriaId);
550 1
                            $affectedCriteriaIds[] = $updatedCriteria->id;
551
                        }
552
                    }
553
                }
554
            }
555
            // New criteria must be created from scratch, and the id in the form element name can be disregarded.
556 2
            if (!empty($criteria['new'])) {
557 1
                foreach ($criteria['new'] as $criteriaType => $criteriaTypeInput) {
558 1
                    foreach ($criteriaTypeInput as $skillTypeInput) {
559 1
                        foreach ($skillTypeInput as $criteriaInput) {
560 1
                            $newCriteria = $this->processCriteriaForm($jobPoster, $criteriaType, $criteriaInput, null);
561 1
                            $affectedCriteriaIds[] = $newCriteria->id;
562
                        }
563
                    }
564
                }
565
            }
566
        }
567
568
        // Existing criteria which were not resubmitted must be deleted.
569 6
        $deleteCriteria = $jobPoster->criteria()->whereNotIn('id', $affectedCriteriaIds)->get();
570 6
        foreach ($deleteCriteria as $criteria) {
571 6
            $this->deleteCriteria($criteria);
572
        }
573 6
    }
574
575
    /**
576
     * Process intput representing a single criteria from Job Poster form.
577
     *
578
     * @param  \App\Models\JobPoster $jobPoster     Incoming Job Poster.
579
     * @param  string                $criteriaType  Type of Criteria.
580
     * @param  array                 $criteriaInput Criteria data.
581
     * @param  integer|null          $criteriaId    Criteria ID.
582
     * @return \App\Models\Criteria
583
     */
584 2
    protected function processCriteriaForm(JobPoster $jobPoster, string $criteriaType, array $criteriaInput, ?int $criteriaId)
585
    {
586 2
        $skillId = $criteriaInput['skill_id'];
587
588
        // If no description was provided, use the default skill description.
589 2
        $descriptionEn = $criteriaInput['description']['en'] ?
590 2
            $criteriaInput['description']['en'] : Skill::find($skillId)->getTranslation('description', 'en');
591 2
        $descriptionFr = $criteriaInput['description']['fr'] ?
592 2
            $criteriaInput['description']['fr'] : Skill::find($criteriaInput['skill_id'])->getTranslation('description', 'fr');
593
        $data = [
594 2
            'skill_id' => $criteriaInput['skill_id'],
595 2
            'criteria_type_id' => CriteriaType::where('name', $criteriaType)->firstOrFail()->id,
596 2
            'skill_level_id' => $criteriaInput['skill_level_id'],
597
            'en' => [
598 2
                'description' => $descriptionEn,
599
            ],
600
            'fr' => [
601 2
                'description' => $descriptionFr,
602
            ],
603
        ];
604
605 2
        if ($criteriaId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $criteriaId of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
606 1
            $existingCriteria = Criteria::find($criteriaId);
607 1
            $this->updateCriteria($existingCriteria, $data);
608 1
            return $existingCriteria;
609
        } else {
610 1
            $newCriteria = $this->createCriteria($jobPoster, $skillId, $data);
611 1
            return $newCriteria;
612
        }
613
    }
614
615
    /**
616
     * Create a Job Criteria
617
     *
618
     * @param  \App\Models\JobPoster $jobPoster Incoming Job Poster.
619
     * @param  integer               $skillId   Skill ID.
620
     * @param  array                 $data      Criteria data.
621
     * @return \App\Models\Criteria
622
     */
623 1
    protected function createCriteria(JobPoster $jobPoster, int $skillId, array $data)
624
    {
625 1
        $criteria = new Criteria();
626 1
        $criteria->job_poster_id = $jobPoster->id;
627 1
        $criteria->skill_id = $skillId;
628 1
        $criteria->fill($data);
629 1
        $criteria->save();
630
631 1
        $notification = $this->makeAssessmentPlanNotification(
632 1
            'CREATE',
633 1
            $criteria
634
        );
635 1
        $notification->save();
636
637 1
        return $criteria;
638
    }
639
640
    /**
641
     * Update an existing Job Criteria
642
     *
643
     * @param  \App\Models\Criteria $criteria Incoming Critera.
644
     * @param  array                $data     Skill data.
645
     * @return void
646
     */
647 1
    protected function updateCriteria(Criteria $criteria, array $data): void
648
    {
649 1
        if ($criteria->skill_level_id != $data['skill_level_id'] ||
650 1
        $criteria->skill_id != $data['skill_id']) {
651 1
            $notification = $this->makeAssessmentPlanNotification(
652 1
                'UPDATE',
653 1
                $criteria,
654 1
                $data['skill_id'],
655 1
                $data['skill_level_id']
656
            );
657 1
            $notification->save();
658
        }
659 1
        $criteria->fill($data);
660 1
        $criteria->save();
661 1
    }
662
663
    /**
664
     * Delete existing Job Criteria
665
     *
666
     * @param  \App\Models\Criteria $criteria Incoming Criteria.
667
     * @return void
668
     */
669 6
    protected function deleteCriteria(Criteria $criteria): void
670
    {
671 6
        $notification = $notification = $this->makeAssessmentPlanNotification(
0 ignored issues
show
Unused Code introduced by
The assignment to $notification is dead and can be removed.
Loading history...
672 6
            'DELETE',
673 6
            $criteria
674
        );
675 6
        $notification->save();
676
677
        // Delete assessments related to this criteria.
678 6
        Assessment::where('criterion_id', $criteria->id)->delete();
679 6
        $criteria->delete();
680 6
    }
681
682
    /**
683
     * Create a new AssessmentPlanNotification for a modification to a Criteria
684
     *
685
     * @param  string               $type            Can be CREATE, UPDATE or DELETE.
686
     * @param  \App\Models\Criteria $criteria        Incoming Criteria.
687
     * @param  integer|null         $newSkillId      Only used for UPDATE type notifications.
688
     * @param  integer|null         $newSkillLevelId Only used for UPDATE type notifications.
689
     * @return \App\Models\AssessmentPlanNotification
690
     */
691 6
    protected function makeAssessmentPlanNotification(string $type, Criteria $criteria, $newSkillId = null, $newSkillLevelId = null)
692
    {
693 6
        $notification = new AssessmentPlanNotification();
694 6
        $notification->job_poster_id = $criteria->job_poster_id;
695 6
        $notification->type = $type;
696 6
        $notification->criteria_id = $criteria->id;
697 6
        $notification->skill_id = $criteria->skill_id;
698 6
        $notification->criteria_type_id = $criteria->criteria_type_id;
699 6
        $notification->skill_level_id = $criteria->skill_level_id;
700 6
        $notification->skill_id_new = $newSkillId;
701 6
        $notification->skill_level_id_new = $newSkillLevelId;
702 6
        $notification->acknowledged = false;
703 6
        return $notification;
704
    }
705
706
    /**
707
     * Get the localized default questions and add them to an array.
708
     *
709
     * @return mixed[]|void
710
     */
711 2
    protected function populateDefaultQuestions()
712
    {
713
        $defaultQuestions = [
714 2
            'en' => array_values(Lang::get('manager/job_create', [], 'en')['questions']),
715 2
            'fr' => array_values(Lang::get('manager/job_create', [], 'fr')['questions']),
716
        ];
717
718 2
        if (count($defaultQuestions['en']) !== count($defaultQuestions['fr'])) {
719
            Log::warning('There must be the same number of French and English default questions for a Job Poster.');
720
            return;
721
        }
722
723 2
        $jobQuestions = [];
724
725 2
        for ($i = 0; $i < count($defaultQuestions['en']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
726 2
            $jobQuestion = new JobPosterQuestion();
727 2
            $jobQuestion->fill(
728
                [
729
                    'en' => [
730 2
                        'question' => $defaultQuestions['en'][$i],
731
                    ],
732
                    'fr' => [
733 2
                        'question' => $defaultQuestions['fr'][$i],
734
                    ]
735
                ]
736
            );
737 2
            $jobQuestions[] = $jobQuestion;
738
        }
739
740 2
        return $jobQuestions;
741
    }
742
}
743