Passed
Push — master ( 6ceee8...d4902a )
by Tristan
20:51 queued 08:57
created

JobController::submitForReview()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 11
c 0
b 0
f 0
dl 0
loc 21
ccs 6
cts 6
cp 1
rs 9.9
cc 2
nc 2
nop 2
crap 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A JobController::destroy() 0 3 1
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\Http\Request;
9
use App\Http\Controllers\Controller;
10
use Carbon\Carbon;
11
use App\Models\JobPoster;
12
use App\Models\JobPosterQuestion;
13
use App\Models\Manager;
14
use Mcamara\LaravelLocalization\Facades\LaravelLocalization;
15
use App\Services\Validation\JobPosterValidator;
16
17
class JobController extends Controller
18
{
19
    /**
20
     * Display a listing of JobPosters.
21
     *
22
     * @return \Illuminate\Http\Response
23
     */
24
    public function index()
25
    {
26
        $now = Carbon::now();
27
28
        // Find published jobs that are currently open for applications.
29
        // Eager load required relationships: Department, Province, JobTerm.
30
        // Eager load the count of submitted applications, to prevent the relationship
31
        // from being actually loaded and firing off events.
32
        $jobs = JobPoster::where('open_date_time', '<=', $now)
33
            ->where('close_date_time', '>=', $now)
34
            ->where('published', true)
35
            ->with([
36
                'department',
37
                'province',
38
                'job_term',
39
            ])
40
            ->withCount([
41
                'submitted_applications',
42
            ])
43
            ->get();
44
        return view('applicant/job_index', [
45
            'job_index' => Lang::get('applicant/job_index'),
46
            'jobs' => $jobs
47
        ]);
48
    }
49
50
    /**
51
     * Display a listing of a manager's JobPosters.
52
     *
53
     * @return \Illuminate\Http\Response
54
     */
55
    public function managerIndex()
56
    {
57
        $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...
58
59
        $jobs = JobPoster::where('manager_id', $manager->id)
60
            ->with('classification')
61
            ->withCount('submitted_applications')
62
            ->get();
63
64
        foreach ($jobs as &$job) {
65
            $chosen_lang = $job->chosen_lang;
66
67
            // Show chosen lang title if current title is empty.
68
            if (empty($job->title)) {
69
                $job->title = $job->translate($chosen_lang)->title;
70
                $job->trans_required = true;
0 ignored issues
show
Bug introduced by
The property trans_required does not seem to exist on App\Models\JobPoster. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
71
            }
72
73 1
            // Always preview and edit in the chosen language.
74
            $job->preview_link = LaravelLocalization::getLocalizedURL($chosen_lang, route('manager.jobs.show', $job));
0 ignored issues
show
Bug introduced by
The property preview_link does not seem to exist on App\Models\JobPoster. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
75 1
            $job->edit_link = LaravelLocalization::getLocalizedURL($chosen_lang, route('manager.jobs.edit', $job));
0 ignored issues
show
Bug introduced by
The property edit_link does not seem to exist on App\Models\JobPoster. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
76 1
        }
77 1
78 1
79
        return view('manager/job_index', [
80 1
            // Localization Strings.
81
            'jobs_l10n' => Lang::get('manager/job_index'),
82 1
            // Data.
83
            'jobs' => $jobs,
84 1
        ]);
85
    }
86
87
    /**
88
     * Delete a draft Job Poster.
89
     *
90
     * @param  \Illuminate\Http\Request $request   Incoming request object.
91
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
92
     * @return \Illuminate\Http\Response
93
     */
94
    public function destroy(Request $request, JobPoster $jobPoster)
95 1
    {
96
        $jobPoster->delete();
97
    }
98 1
99 1
    /**
100
     * Display the specified job poster.
101
     *
102 1
     * @param  \Illuminate\Http\Request $request   Incoming request object.
103
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
104
     * @return \Illuminate\Http\Response
105 1
     */
106 1
    public function show(Request $request, JobPoster $jobPoster)
107 1
    {
108
        $jobPoster->load([
109
            'department',
110
            'criteria.skill.skill_type',
111
            'manager.team_culture',
112 1
            'manager.work_environment'
113
        ]);
114 1
115 1
        $user = Auth::user();
0 ignored issues
show
Unused Code introduced by
The assignment to $user is dead and can be removed.
Loading history...
116
117
        // TODO: Improve workplace photos, and reference them in template direction from WorkEnvironment model.
118
        $workplacePhotos = [];
119
        foreach ($jobPoster->manager->work_environment->workplace_photo_captions as $photoCaption) {
120
            $workplacePhotos[] = [
121
                'description' => $photoCaption->description,
122
                'url' => '/images/user.png'
123
            ];
124
        }
125
126
        // TODO: replace route('manager.show',manager.id) in templates with link using slug.
127
        $criteria = [
128
            'essential' => $jobPoster->criteria->filter(
129
                function ($value, $key) {
130
                    return $value->criteria_type->name == 'essential';
131
                }
132
            ),
133
            'asset' => $jobPoster->criteria->filter(
134
                function ($value, $key) {
135
                    return $value->criteria_type->name == 'asset';
136
                }
137
            ),
138 6
        ];
139
140 6
        $jobLang = Lang::get('applicant/job_post');
141 6
142
        $applyButton = [];
143
        if (!$jobPoster->published && $this->authorize('update', $jobPoster)) {
144
            $applyButton = [
145
                'href' => route('manager.jobs.edit', $jobPoster->id),
146
                'title' => $jobLang['apply']['edit_link_title'],
147 6
                'text' => $jobLang['apply']['edit_link_label'],
148
            ];
149
        } elseif (Auth::check() && $jobPoster->isOpen()) {
150 6
            $applyButton = [
151 6
                'href' => route('job.application.edit.1', $jobPoster->id),
152
                'title' => $jobLang['apply']['apply_link_title'],
153
                'text' => $jobLang['apply']['apply_link_label'],
154
            ];
155
        } elseif (Auth::guest() && $jobPoster->isOpen()) {
156
            $applyButton = [
157
                'href' => route('job.application.edit.1', $jobPoster->id),
158
                'title' => $jobLang['apply']['login_link_title'],
159
                'text' => $jobLang['apply']['login_link_label'],
160 6
            ];
161
        } else {
162 4
            $applyButton = [
163 6
                'href' => null,
164
                'title' => null,
165 6
                'text' => $jobLang['apply']['job_closed_label'],
166
            ];
167 4
        }
168 6
169
        $jpb_release_date = strtotime('2019-08-21 16:18:17');
170
        $job_created_at = strtotime($jobPoster->created_at);
171
172 6
        // If the job poster is created after the release of the JPB.
173
        // Then, render with updated poster template.
174 6
        // Else, render with old poster template.
175 6
        if ($job_created_at > $jpb_release_date) {
176
            // Updated job poster (JPB).
177 4
            return view(
178 4
                'applicant/jpb_job_post',
179 4
                [
180
                    'job_post' => $jobLang,
181 2
                    'skill_template' => Lang::get('common/skills'),
182
                    'job' => $jobPoster,
183 1
                    'manager' => $jobPoster->manager,
184 1
                    'criteria' => $criteria,
185 1
                    'apply_button' => $applyButton,
186
                ]
187 1
            );
188
        } else {
189 1
            // Old job poster.
190 1
            return view(
191 1
                'applicant/job_post',
192
                [
193
                    'job_post' => $jobLang,
194
                    'manager' => $jobPoster->manager,
195
                    'manager_profile_photo_url' => '/images/user.png', // TODO get real photo.
196
                    'team_culture' => $jobPoster->manager->team_culture,
197
                    'work_environment' => $jobPoster->manager->work_environment,
198
                    'workplace_photos' => $workplacePhotos,
199
                    'job' => $jobPoster,
200
                    'criteria' => $criteria,
201 6
                    'apply_button' => $applyButton,
202 6
                    'skill_template' => Lang::get('common/skills'),
203
                ]
204 6
            );
205 6
        }
206 6
    }
207 6
208 6
    /**
209 6
     * Display the form for editing an existing Job Poster
210 6
     * Only allows editing fields that don't appear on the react-built Job Poster Builder.
211 6
     *
212 6
     * @param  \Illuminate\Http\Request $request   Incoming request object.
213 6
     * @param  \App\Models\JobPoster    $jobPoster Job Poster object.
214
     * @return \Illuminate\Http\Response
215
     */
216
    public function edit(Request $request, JobPoster $jobPoster)
217
    {
218
        $manager = $jobPoster->manager;
219
220
        if ($jobPoster->job_poster_questions === null || $jobPoster->job_poster_questions->count() === 0) {
221
            $jobPoster->job_poster_questions()->saveMany($this->populateDefaultQuestions());
222
            $jobPoster->refresh();
223
        }
224 2
225
        return view(
226 2
            'manager/job_create',
227 2
            [
228
                // Localization Strings.
229 2
                'job_l10n' => Lang::get('manager/job_edit'),
230
                // Data.
231 2
                'manager' => $manager,
232 2
                'job' => $jobPoster,
233 2
                'form_action_url' => route('admin.jobs.update', $jobPoster),
234
            ]
235
        );
236 2
    }
237
238
    /**
239
     * Create a blank job poster for the specified manager
240
     *
241
     * @param  \App\Models\Manager $manager Incoming Manager object.
242
     * @return \Illuminate\Http\Response Job Create view
243
     */
244
    public function createAsManager(Manager $manager)
245
    {
246
        $jobPoster = new JobPoster();
247
        $jobPoster->manager_id = $manager->id;
248
249
        // Save manager-specific info to the job poster - equivalent to the intro step of the JPB
250
        $divisionEn = $manager->translate('en') !== null ? $manager->translate('en')->division : null;
251
        $divisionFr = $manager->translate('fr') !== null ? $manager->translate('fr')->division : null;
252
        $jobPoster->fill([
253
            'department_id' => $manager->department_id,
254
            'en' => ['division' => $divisionEn],
255
            'fr' => ['division' => $divisionFr],
256
        ]);
257 1
258
        $jobPoster->save();
259 1
260
        return redirect()->route('manager.jobs.edit', $jobPoster->id);
261
    }
262
263
    /**
264
     * Update a resource in storage
265
     * NOTE: Only saves fields that are not on the react-built Job Poster Builder
266
     *
267
     * @param  \Illuminate\Http\Request $request   Incoming request object.
268
     * @param  \App\Models\JobPoster    $jobPoster Optional Job Poster object.
269 1
     * @return \Illuminate\Http\Response
270
     */
271 1
    public function store(Request $request, JobPoster $jobPoster)
272
    {
273
        // Don't allow edits for published Job Posters
274 1
        // Also check auth while we're at it.
275
        $this->authorize('update', $jobPoster);
276
        JobPosterValidator::validateUnpublished($jobPoster);
277 1
278 1
        $input = $request->input();
279 1
280 1
        if ($jobPoster->manager_id == null) {
281
            $jobPoster->manager_id = $request->user()->manager->id;
282
            $jobPoster->save();
283
        }
284
285
        $this->fillAndSaveJobPosterQuestions($input, $jobPoster, true);
286
287
        return redirect(route('manager.jobs.show', $jobPoster->id));
288
    }
289
290
    /**
291 1
     * Fill Job Poster's questions and save
292
     *
293 1
     * @param  mixed[]               $input     Field values.
294 1
     * @param  \App\Models\JobPoster $jobPoster Job Poster object.
295
     * @param  boolean               $replace   Remove existing relationships.
296 1
     * @return void
297 1
     */
298 1
    protected function fillAndSaveJobPosterQuestions(array $input, JobPoster $jobPoster, bool $replace) : void
299 1
    {
300
        if ($replace) {
301
            $jobPoster->job_poster_questions()->delete();
302 1
        }
303
304 1
        if (!array_key_exists('question', $input) || !is_array($input['question'])) {
305
            return;
306 1
        }
307
308 1
        foreach ($input['question'] as $question) {
309 1
            $jobQuestion = new JobPosterQuestion();
310
            $jobQuestion->job_poster_id = $jobPoster->id;
311 1
            $jobQuestion->fill(
312 1
                [
313 1
                    'en' => [
314 1
                        'question' => $question['question']['en'],
315
                        'description' => $question['description']['en']
316
                    ],
317 1
                    'fr' => [
318
                        'question' => $question['question']['fr'],
319 1
                        'description' => $question['description']['fr']
320
                    ]
321 1
                ]
322
            );
323 1
            $jobPoster->save();
324 1
            $jobQuestion->save();
325
        }
326
    }
327
328 1
    /**
329 1
     * Get the localized default questions and add them to an array.
330
     *
331
     * @return mixed[]|void
332 1
     */
333 1
    protected function populateDefaultQuestions()
334
    {
335
        $defaultQuestions = [
336
            'en' => array_values(Lang::get('manager/job_create', [], 'en')['questions']),
337 1
            'fr' => array_values(Lang::get('manager/job_create', [], 'fr')['questions']),
338
        ];
339 1
340
        if (count($defaultQuestions['en']) !== count($defaultQuestions['fr'])) {
341 1
            Log::warning('There must be the same number of French and English default questions for a Job Poster.');
342
            return;
343 1
        }
344 1
345 1
        $jobQuestions = [];
346
347 1
        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...
348
            $jobQuestion = new JobPosterQuestion();
349 1
            $jobQuestion->fill(
350 1
                [
351 1
                    'en' => [
352
                        'question' => $defaultQuestions['en'][$i],
353 1
                    ],
354 1
                    'fr' => [
355
                        'question' => $defaultQuestions['fr'][$i],
356
                    ]
357 1
                ]
358
            );
359 1
            $jobQuestions[] = $jobQuestion;
360 1
        }
361 1
362 1
        return $jobQuestions;
363 1
    }
364
}
365