Passed
Push — allow-managers-to-edit-job-pos... ( dee288...ebc53e )
by
unknown
08:57
created

JobController::fillAndSaveJobPosterQuestions()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
eloc 15
dl 0
loc 26
ccs 0
cts 14
cp 0
rs 9.7666
c 0
b 0
f 0
cc 4
nc 6
nop 3
crap 20
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\Request;
8
use App\Http\Controllers\Controller;
9
use Carbon\Carbon;
10
use App\Models\JobPoster;
11
use App\Models\Lookup\JobTerm;
12
use App\Models\Lookup\Province;
13
use App\Models\Lookup\SecurityClearance;
14
use App\Models\Lookup\LanguageRequirement;
15
use App\Models\Lookup\CitizenshipDeclaration;
16
use App\Models\Lookup\Department;
17
use App\Models\Lookup\SkillLevel;
18
use App\Models\Lookup\CriteriaType;
19
use App\Models\Lookup\VeteranStatus;
20
use App\Models\JobApplication;
21
use App\Models\Criteria;
22
use App\Models\Skill;
23
use App\Models\JobPosterQuestion;
24
use App\Models\JobPosterKeyTask;
25
use App\Services\Validation\JobPosterValidator;
26
use Jenssegers\Date\Date;
27
28
class JobController extends Controller
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class JobController
Loading history...
29
{
30
    /**
31
     * Display a listing of JobPosters.
32
     *
33
     * @return \Illuminate\Http\Response
34
     */
35
    public function index()
36
    {
37
        $now = Carbon::now();
38
        //Find published jobs that are currently open for applications
39
        $jobs = JobPoster::where('open_date_time', '<=', $now)
40
            ->where('close_date_time', '>=', $now)
41
            ->where('published', true)
42
            ->get();
43
        $jobs->load('manager.work_environment');
44
        return view('applicant/job_index', ['job_index' => Lang::get('applicant/job_index'),
1 ignored issue
show
Bug Best Practice introduced by
The expression return view('applicant/j...ex'), 'jobs' => $jobs)) returns the type Illuminate\View\View which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
45
            'jobs' => $jobs]);
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...
46
    }
47
48
    /**
49
     * Display a listing of a manager's JobPosters.
50
     *
51
     * @return \Illuminate\Http\Response
52
     */
53
    public function managerIndex()
54
    {
55
        $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...
56
57
        $veteran_applications = [];
58
        $citizen_applications = [];
59
        $other_applications = [];
60
61
        foreach($manager->job_posters as $job) {
0 ignored issues
show
Coding Style introduced by
Expected "foreach (...) {\n"; found "foreach(...) {\n"
Loading history...
62
            $job->submitted_applications->load(['veteran_status', 'citizenship_declaration']);
63
            $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...
64
                return $application->veteran_status->name !== "none" &&
65
                        $application->citizenship_declaration->name === "citizen";
66
            });
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...
67
            $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...
68
                return $application->veteran_status->name === "none" &&
69
                        $application->citizenship_declaration->name === "citizen";
70
            });
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...
71
            $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...
72
                return $application->citizenship_declaration->name !== "citizen";
73
            });
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...
74
        }
75
76
        return view('manager/job_index', [
1 ignored issue
show
Bug Best Practice introduced by
The expression return view('manager/job...> $other_applications)) returns the type Illuminate\View\View which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
77
            "manager_job_index" => [
78
                "title" => "My Job Posts"
79
            ],
80
            'jobs' => $manager->job_posters,
81
            'veteran_applications' => $veteran_applications,
82
            'citizen_applications' => $citizen_applications,
83
            'other_applications' => $other_applications,
84
        ]);
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...
85
    }
86
87
    /**
88
     * Display the specified job poster.
89
     *
90
     * @param \Illuminate\Http\Request $request   Incoming request object
91
     * @param \App\Models\JobPoster    $jobPoster Job Poster object
92
     *
93
     * @return \Illuminate\Http\Response
94
     */
95
    public function show(Request $request, JobPoster $jobPoster)
96
    {
97
        //TODO: Improve workplace photos, and reference them in template direction from WorkEnvironment model
98
        $workplacePhotos = [];
99
        foreach ($jobPoster->manager->work_environment->workplace_photo_captions as $photoCaption) {
100
            $workplacePhotos[] = [
101
                'description' => $photoCaption->description,
102
                'url' => '/images/user.png'
103
            ];
104
        }
105
106
        //TODO: replace route('manager.show',manager.id) in templates with link using slug
107
108
        $criteria = [
109
            'essential' => $jobPoster->criteria->filter(
110
                function ($value, $key) {
111
                    return $value->criteria_type->name == 'essential';
112
                }
113
            ),
114
            'asset' => $jobPoster->criteria->filter(
115
                function ($value, $key) {
116
                    return $value->criteria_type->name == 'asset';
117
                }
118
            ),
119
        ];
120
121
        return view(
1 ignored issue
show
Bug Best Practice introduced by
The expression return view('applicant/j...:get('common/skills'))) returns the type Illuminate\View\View which is incompatible with the documented return type Illuminate\Http\Response.
Loading history...
122
            'applicant/job_post',
123
            [
124
                'job_post' => Lang::get('applicant/job_post'),
125
                'manager' => $jobPoster->manager,
126
                'manager_profile_photo_url' => '/images/user.png', //TODO get real photo
127
                'team_culture' => $jobPoster->manager->team_culture,
128
                'work_environment' => $jobPoster->manager->work_environment,
129
                'workplace_photos' => $workplacePhotos,
130
                'job' => $jobPoster,
131
                'criteria' => $criteria,
132
                'skill_template' => Lang::get('common/skills'),
133
            ]
134
        );
135
    }
136
137
    /**
138
     * Display the form for creating a new Job Poster
139
     *
140
     * @param \Illuminate\Http\Request $request Incoming request object
141
     *
142
     * @return Illuminate\View\View Job Create view
0 ignored issues
show
Bug introduced by
The type App\Http\Controllers\Illuminate\View\View was not found. Did you mean Illuminate\View\View? If so, make sure to prefix the type with \.
Loading history...
143
     */
144
    public function create(Request $request)
145
    {
146
        return $this->populateCreateView($request);
147
    }
148
149
    /**
150
     * Display the form for editing an existing Job Poster
151
     *
152
     * @param \Illuminate\Http\Request $request   Incoming request object
153
     * @param \App\Models\JobPoster    $jobPoster Job Poster object
154
     *
155
     * @return Illuminate\View\View Job Create view
156
     */
157
    public function edit(Request $request, JobPoster $jobPoster)
158
    {
159
        return $this->populateCreateView($request, $jobPoster);
160
    }
161
162
    /**
163
     * Get the manager from the request object and check if creating or editing
164
     *
165
     * @param \Illuminate\Http\Request $request   Incoming request object
166
     * @param \App\Models\JobPoster    $jobPoster Optional Job Poster object
167
     *
168
     * @return Illuminate\View\View Job Create view
169
     */
170
    public function populateCreateView(Request $request, JobPoster $jobPoster = null)
171
    {
172
        $manager = $request->user() ? $request->user()->manager : null;
173
        if (isset($jobPoster)) {
174
            $job = $jobPoster;
175
            $route = ['manager.jobs.store', $jobPoster];
176
            $jobHeading = 'manager/job_edit';
177
        } else {
178
            $job = [];
179
            $route = ['manager.jobs.store'];
180
            $jobHeading = 'manager/job_create';
181
        }
182
183
        return view(
1 ignored issue
show
Bug Best Practice introduced by
The expression return view('manager/job...:get('common/skills'))) returns the type Illuminate\View\View which is incompatible with the documented return type App\Http\Controllers\Illuminate\View\View.
Loading history...
184
            'manager/job_create',
185
            [
186
                'job_heading' => Lang::get($jobHeading),
187
                'manager' => $manager,
188
                'provinces' => Province::all(),
189
                'departments' => Department::all(),
190
                'language_requirments' => LanguageRequirement::all(),
191
                'security_clearances' => SecurityClearance::all(),
192
                'job' => $job,
193
                'form_action_url' => route(
194
                    /** @scrutinizer ignore-type */ // phpcs:ignore
195
                    ...$route
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

195
                    /** @scrutinizer ignore-type */ ...$route
Loading history...
196
                ),
197
                'skills' => Skill::all(),
198
                'skill_levels' => SkillLevel::all(),
199
                'skill_template' => Lang::get('common/skills'),
200
            ]
201
        );
202
    }
203
204
    /**
205
     * Create a new resource in storage
206
     *
207
     * @param \Illuminate\Http\Request $request   Incoming request object
208
     * @param \App\Models\JobPoster    $jobPoster Optional Job Poster object
209
     *
210
     * @return Illuminate\Http\RedirectResponsee A redirect to the Job Index
211
     */
212
    public function store(Request $request, JobPoster $jobPoster = null)
213
    {
214
        // Don't allow edits for published Job Posters
215
        if (isset($jobPoster)) {
216
            JobPosterValidator::validateUnpublished($jobPoster);
217
        }
218
219
        $input = $request->input();
220
221
        $job = (isset($jobPoster) ? $jobPoster : new JobPoster());
222
223
        $job->manager_id = $request->user()->manager->id;
224
        $job->published = ($input['submit'] == 'publish');
225
226
        $this->fillAndSaveJobPoster($input, $job);
227
228
        $this->fillAndSaveJobPosterTasks($input, $job, isset($jobPoster));
229
230
        $this->fillAndSaveJobPosterQuestions($input, $job, isset($jobPoster));
231
232
        $this->fillAndSaveJobPosterCriteria($input, $job, isset($jobPoster));
233
234
        return redirect(route('manager.jobs.index'));
1 ignored issue
show
Bug Best Practice introduced by
The expression return redirect(route('manager.jobs.index')) returns the type Illuminate\Http\RedirectResponse which is incompatible with the documented return type App\Http\Controllers\Ill...\Http\RedirectResponsee.
Loading history...
235
    }
236
237
    /**
238
     * Fill Job Poster model's properties and save
239
     *
240
     * @param array                 $input     Field values
241
     * @param \App\Models\JobPoster $jobPoster Job Poster object
242
     *
243
     * @return null
244
     */
245
    protected function fillAndSaveJobPoster(array $input, JobPoster $jobPoster)
246
    {
247
        $jobPoster->fill(
248
            [
249
                'job_term_id' => JobTerm::where('name', 'month')->firstOrFail()->id,
250
                'term_qty' => $input['term_qty'],
251
                'open_date_time' => new Date($input['open_date'] . $input['open_time']),
252
                'close_date_time' => new Date($input['close_date'] . $input['close_time']),
253
                'start_date_time' => new Date($input['start_date_time']),
254
                'department_id' => $input['department'],
255
                'province_id' => $input['province'],
256
                'salary_min' => $input['salary_min'],
257
                'salary_max' => $input['salary_max'],
258
                'noc' => $input['noc'],
259
                'classification' => $input['classification'],
260
                'security_clearance_id' => $input['security_clearance'],
261
                'language_requirement_id' => $input['language_requirement'],
262
                'remote_work_allowed' => (isset($input['remote_work_allowed']) ? $input['remote_work_allowed'] : false),
263
                'en' => [
264
                    'city' => $input['city'],
265
                    'title' => $input['title']['en'],
266
                    'impact' => $input['impact']['en'],
267
                    'branch' => $input['branch']['en'],
268
                    'division' => $input['division']['en'],
269
                    'education' => $input['education']['en'],
270
                ],
271
                'fr' => [
272
                    'city' => $input['city'],
273
                    'title' => $input['title']['fr'],
274
                    'impact' => $input['impact']['fr'],
275
                    'branch' => $input['branch']['fr'],
276
                    'division' => $input['division']['fr'],
277
                    'education' => $input['education']['fr'],
278
                ],
279
            ]
280
        );
281
        $jobPoster->save();
282
    }
283
284
    /**
285
     * Fill Job Poster's tasks and save
286
     *
287
     * @param array                 $input     Field values
288
     * @param \App\Models\JobPoster $jobPoster Job Poster object
289
     * @param bool                  $replace   Remove existing relationships
290
     *
291
     * @return null
292
     */
293
    protected function fillAndSaveJobPosterTasks(array $input, JobPoster $jobPoster, bool $replace)
294
    {
295
        if ($replace) {
296
            $jobPoster->job_poster_key_tasks()->delete();
297
        }
298
299
        if (!is_array($input['task'])) {
300
            return;
301
        }
302
303
        foreach ($input['task'] as $task) {
304
            $jobPosterTask = new JobPosterKeyTask();
305
            $jobPosterTask->job_poster_id = $jobPoster->id;
306
            $jobPosterTask->fill(
307
                [
308
                    'en' => [
309
                        'description' => $task['en']
310
                    ],
311
                    'fr' => [
312
                        'description' => $task['fr']
313
                    ]
314
                ]
315
            );
316
            $jobPosterTask->save();
317
        }
318
    }
319
320
    /**
321
     * Fill Job Poster's questions and save
322
     *
323
     * @param array                 $input     Field values
324
     * @param \App\Models\JobPoster $jobPoster Job Poster object
325
     * @param bool                  $replace   Remove existing relationships
326
     *
327
     * @return null
328
     */
329
    protected function fillAndSaveJobPosterQuestions(array $input, JobPoster $jobPoster, bool $replace)
330
    {
331
        if ($replace) {
332
            $jobPoster->job_poster_questions()->delete();
333
        }
334
335
        if (!is_array($input['question'])) {
336
            return;
337
        }
338
339
        foreach ($input['question'] as $question) {
340
            $jobQuestion = new JobPosterQuestion();
341
            $jobQuestion->job_poster_id = $jobPoster->id;
342
            $jobQuestion->fill(
343
                [
344
                    'en' => [
345
                        'question' => $question['question']['en'],
346
                        'description' => $question['description']['en']
347
                    ],
348
                    'fr' => [
349
                        'question' => $question['question']['fr'],
350
                        'description' => $question['description']['fr']
351
                    ]
352
                ]
353
            );
354
            $jobQuestion->save();
355
        }
356
    }
357
358
    /**
359
     * Fill Job Poster's criteria and save
360
     *
361
     * @param array                 $input     Field values
362
     * @param \App\Models\JobPoster $jobPoster Job Poster object
363
     * @param bool                  $replace   Remove existing relationships
364
     *
365
     * @return null
366
     */
367
    protected function fillAndSaveJobPosterCriteria(array $input, JobPoster $jobPoster, bool $replace)
368
    {
369
        if ($replace) {
370
            $jobPoster->criteria()->delete();
371
        }
372
373
        if (!is_array($input['criteria'])) {
374
            return;
375
        }
376
377
        $criteria = $input['criteria'];
378
379
        $combinedCriteria = [];
380
        if (isset($criteria['old'])) {
381
            $combinedCriteria = array_replace_recursive($combinedCriteria, $criteria['old']);
382
        }
383
        if (isset($criteria['new'])) {
384
            $combinedCriteria = array_replace_recursive($combinedCriteria, $criteria['new']);
385
        }
386
387
        if (! empty($combinedCriteria)) {
388
            foreach ($combinedCriteria as $criteriaType => $criteriaTypeInput) {
389
                foreach ($criteriaTypeInput as $skillType => $skillTypeInput) {
390
                    foreach ($skillTypeInput as $criteriaInput) {
391
                        $criteria = new Criteria();
392
                        $criteria->job_poster_id = $jobPoster->id;
393
                        $criteria->fill(
394
                            [
395
                                'criteria_type_id' => CriteriaType::where('name', $criteriaType)->firstOrFail()->id,
396
                                'skill_id' => $criteriaInput['skill_id'],
397
                                'skill_level_id' => $criteriaInput['skill_level_id'],
398
                                'en' => [
399
                                    'description' => $criteriaInput['description']['en'],
400
                                ],
401
                                'fr' => [
402
                                    'description' => $criteriaInput['description']['fr'],
403
                                ],
404
                            ]
405
                        );
406
                        $criteria->save();
407
                    }
408
                }
409
            }
410
        }
411
    }
412
}
413