Passed
Push — task/screening-plan-hr ( 582176...c52cc0 )
by Yonathan
07:46 queued 03:08
created

CriteriaController   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 152
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 13
eloc 60
c 0
b 0
f 0
dl 0
loc 152
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
B batchUpdate() 0 34 6
A createCriteria() 0 10 1
A indexByJob() 0 4 1
A deleteCriteria() 0 11 1
A updateCriteria() 0 20 3
A makeAssessmentPlanNotification() 0 19 1
1
<?php
2
3
namespace App\Http\Controllers\Api;
4
5
use App\Http\Controllers\Controller;
6
use App\Models\Assessment;
7
use App\Models\AssessmentPlanNotification;
8
use App\Models\Criteria;
9
use App\Models\JobPoster;
10
use Illuminate\Http\Request;
11
use Illuminate\Http\Resources\Json\JsonResource;
12
13
class CriteriaController extends Controller
14
{
15
    /**
16
     * Returns all criteria by JobPoster ID.
17
     *
18
     * @param  \App\Models\JobPoster $jobPoster Incoming Job Poster object.
19
     * @return \Illuminate\Http\Response
20
     */
21
    public function indexByJob(JobPoster $jobPoster)
22
    {
23
        $criteriaByJob = Criteria::where('job_poster_id', $jobPoster->id)->get();
24
        return JsonResource::collection($criteriaByJob);
25
    }
26
27
    /**
28
     * Update the set of criteria associated with a Job.
29
     *
30
     * @param  Request $request
31
     * @param  JobPoster $jobPoster
32
     * @return \Illuminate\Http\Response
33
     */
34
    public function batchUpdate(Request $request, JobPoster $jobPoster)
35
    {
36
        $newCriteria = collect($request->input()); // TODO: switch to validated.
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

36
        $newCriteria = /** @scrutinizer ignore-call */ collect($request->input()); // TODO: switch to validated.
Loading history...
37
        $oldCriteria = $jobPoster->criteria;
38
39
        $updatedIds = [];
40
41
        // First, delete old criteria that weren't resubmitted, and update those that were.
42
        foreach ($oldCriteria as $criteria) {
43
            $newData = $newCriteria->firstWhere('id', $criteria['id']);
44
            if ($newData) {
45
                $updatedIds[] = $criteria->id;
46
                $this->updateCriteria($criteria, $newData);
47
            } else {
48
                $this->deleteCriteria($criteria);
49
            }
50
        }
51
52
        $isUnsaved = function ($criteria, $savedIds): bool {
53
            return !array_key_exists('id', $criteria) || !in_array($criteria['id'], $savedIds);
54
        };
55
56
        // Now, save any new criteria that remain.
57
        foreach ($newCriteria as $criteriaData) {
58
            if ($isUnsaved($criteriaData, $updatedIds)) {
59
                $criteria = new Criteria();
60
                $criteria->job_poster_id = $jobPoster->id;
61
                $fillableData = collect($criteriaData)->except(['id', 'job_poster_id'])->toArray();
62
                $criteria->fill($fillableData);
63
                $this->createCriteria($criteria);
64
            }
65
        }
66
67
        return JsonResource::collection($jobPoster->fresh()->criteria);
68
    }
69
70
    /**
71
     * Save a new criteria and create a notification.
72
     *
73
     * @param Criteria $criteria
74
     * @return void
75
     */
76
    protected function createCriteria(Criteria $criteria)
77
    {
78
        $criteria->save();
79
        $notification = $this->makeAssessmentPlanNotification(
80
            'CREATE',
81
            $criteria
82
        );
83
        $notification->save();
84
85
        return $criteria;
86
    }
87
88
    /**
89
     * Update an existing Job Criteria and create a notification if necessary.
90
     *
91
     * @param  \App\Models\Criteria $oldCriteria Existing Criteria.
92
     * @param  mixed[] $newData Updated version of the Criteria.
93
     * @return void
94
     */
95
    protected function updateCriteria(Criteria $oldCriteria, $newData): void
96
    {
97
        // We only need to create a notification when the non-descriptive fields change.
98
        if (
99
            $oldCriteria->skill_level_id != $newData['skill_level_id']
100
            || $oldCriteria->skill_id != $newData['skill_id']
101
        ) {
102
            $notification = $this->makeAssessmentPlanNotification(
103
                'UPDATE',
104
                $oldCriteria,
105
                $newData['skill_id'],
106
                $newData['skill_level_id'],
107
                $newData['criteria_type_id']
108
            );
109
            $notification->save();
110
        }
111
        // Get just the data that can be changed.
112
        $fillableData = collect($newData)->except(['id', 'job_poster_id'])->toArray();
0 ignored issues
show
Bug introduced by
The function collect was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

112
        $fillableData = /** @scrutinizer ignore-call */ collect($newData)->except(['id', 'job_poster_id'])->toArray();
Loading history...
113
        $oldCriteria->fill($fillableData);
114
        $oldCriteria->save();
115
    }
116
117
    /**
118
     * Delete existing Job Criteria and create a notification.
119
     *
120
     * @param  \App\Models\Criteria $criteria Incoming Criteria.
121
     * @return void
122
     */
123
    protected function deleteCriteria(Criteria $criteria): void
124
    {
125
        $notification = $notification = $this->makeAssessmentPlanNotification(
0 ignored issues
show
Unused Code introduced by
The assignment to $notification is dead and can be removed.
Loading history...
126
            'DELETE',
127
            $criteria
128
        );
129
        $notification->save();
130
131
        // Delete assessments related to this criteria.
132
        Assessment::where('criterion_id', $criteria->id)->delete();
133
        $criteria->delete();
134
    }
135
136
    /**
137
     * Create a new AssessmentPlanNotification for a modification to a Criteria
138
     *
139
     * @param  string               $type            Can be CREATE, UPDATE or DELETE.
140
     * @param  \App\Models\Criteria $criteria        The Criteria (the OLD criteria if updating or deleting)
141
     * @param  integer|null         $newSkillId      Only used for UPDATE type notifications.
142
     * @param  integer|null         $newSkillLevelId Only used for UPDATE type notifications.
143
     * @param  integer|null         $newCriteriaTypeId Only used for UPDATE type notifications.
144
     * @return \App\Models\AssessmentPlanNotification
145
     */
146
    protected function makeAssessmentPlanNotification(
147
        string $type,
148
        Criteria $criteria,
149
        $newSkillId = null,
150
        $newSkillLevelId = null,
151
        $newCriteriaTypeId = null
152
    ) {
153
        $notification = new AssessmentPlanNotification();
154
        $notification->job_poster_id = $criteria->job_poster_id;
155
        $notification->type = $type;
156
        $notification->criteria_id = $criteria->id;
157
        $notification->skill_id = $criteria->skill_id;
158
        $notification->criteria_type_id = $criteria->criteria_type_id;
159
        $notification->skill_level_id = $criteria->skill_level_id;
160
        $notification->skill_id_new = $newSkillId;
161
        $notification->skill_level_id_new = $newSkillLevelId;
162
        $notification->criteria_type_id_new = $newCriteriaTypeId;
163
        $notification->acknowledged = false;
164
        return $notification;
165
    }
166
}
167