Passed
Pull Request — develop (#11)
by
unknown
03:46 queued 56s
created

Student::join()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 2
nop 1
dl 0
loc 18
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace App\Judite\Models;
4
5
use Illuminate\Support\Facades\DB;
6
use Illuminate\Database\Eloquent\Model;
7
use App\Exceptions\EnrollmentCannotBeDeleted;
8
use App\Exceptions\UserHasAlreadyGroupInCourseException;
9
use App\Exceptions\StudentIsNotEnrolledInCourseException;
10
use App\Exceptions\UserIsAlreadyEnrolledInCourseException;
11
12
class Student extends Model
13
{
14
    /**
15
     * The relations to eager load on every query.
16
     *
17
     * @var array
18
     */
19
    protected $with = ['user'];
20
21
    /**
22
     * The attributes that are mass assignable.
23
     *
24
     * @var array
25
     */
26
    protected $fillable = ['student_number'];
27
28
    /**
29
     * Get user who owns this student.
30
     *
31
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
32
     */
33
    public function user()
34
    {
35
        return $this->belongsTo(User::class);
36
    }
37
38
    /**
39
     * Get exchanges requested by this student.
40
     *
41
     * @return \Illuminate\Database\Eloquent\Builder
42
     */
43
    public function requestedExchanges()
44
    {
45
        $enrollmentsRelationship = $this->enrollments();
46
        $enrollmentsKeyName = $enrollmentsRelationship->getRelated()->getKeyName();
47
        $enrollmentsIdsQuery = $enrollmentsRelationship
48
            ->select($enrollmentsKeyName)
49
            ->getBaseQuery();
50
51
        return Exchange::whereFromEnrollmentIn($enrollmentsIdsQuery);
52
    }
53
54
    /**
55
     * Get exchanges proposed to this student.
56
     *
57
     * @return \Illuminate\Database\Eloquent\Builder
58
     */
59
    public function proposedExchanges()
60
    {
61
        $enrollmentsRelationship = $this->enrollments();
62
        $enrollmentsKeyName = $enrollmentsRelationship->getRelated()->getKeyName();
63
        $enrollmentsIdsQuery = $enrollmentsRelationship
64
            ->select($enrollmentsKeyName)
65
            ->getBaseQuery();
66
67
        return Exchange::whereToEnrollmentIn($enrollmentsIdsQuery);
68
    }
69
70
    /**
71
     * Get enrollments of this student.
72
     *
73
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
74
     */
75
    public function enrollments()
76
    {
77
        return $this->hasMany(Enrollment::class);
78
    }
79
80
    /**
81
     * Get enrollment of this student in a given course.
82
     *
83
     * @param \App\Judite\Models\Course $course
84
     *
85
     * @return \App\Judite\Models\Enrollment|null
86
     */
87
    public function getEnrollmentInCourse(Course $course)
88
    {
89
        return $this->enrollments()
90
            ->where('course_id', $course->id)
91
            ->first();
92
    }
93
94
    /**
95
     * Enroll this student with a given course.
96
     *
97
     * @param \App\Judite\Models\Course $course
98
     *
99
     * @throws \App\Exceptions\UserIsAlreadyEnrolledInCourseException
100
     *
101
     * @return \App\Judite\Models\Enrollment
102
     */
103
    public function enroll(Course $course): Enrollment
104
    {
105
        if ($this->isEnrolledInCourse($course)) {
106
            throw new UserIsAlreadyEnrolledInCourseException($course);
107
        }
108
109
        $enrollment = $this->enrollments()->make();
110
        $enrollment->course()->associate($course);
111
        $enrollment->save();
112
113
        return $enrollment;
114
    }
115
116
    /**
117
     * Check if this student is enrolled in a course.
118
     *
119
     * @param \App\Judite\Models\Course $course
120
     *
121
     * @return bool
122
     */
123
    public function isEnrolledInCourse(Course $course): bool
124
    {
125
        return $this->enrollments()->where('course_id', $course->id)->exists();
126
    }
127
128
    /**
129
     * Remove enrollment in the given course.
130
     *
131
     * @param \App\Judite\Models\Course $course
132
     *
133
     * @throws \App\Exceptions\StudentIsNotEnrolledInCourseException|\App\Exceptions\EnrollmentCannotBeDeleted
134
     *
135
     * @return bool
136
     */
137
    public function unenroll(Course $course): bool
138
    {
139
        $enrollment = $this->getEnrollmentInCourse($course);
140
141
        if (is_null($enrollment)) {
142
            throw new StudentIsNotEnrolledInCourseException($course);
143
        }
144
145
        if (! $enrollment->isDeletable()) {
146
            throw new EnrollmentCannotBeDeleted($enrollment);
147
        }
148
149
        return $enrollment->delete();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $enrollment->delete() could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
150
    }
151
152
    /**
153
     * Scope a query to only include users with the given student number.
154
     *
155
     * @param \Illuminate\Database\Eloquent\Builder $query
156
     * @param string                                $studentNumber
157
     *
158
     * @return \Illuminate\Database\Eloquent\Builder
159
     */
160
    public function scopeWhereNumber($query, $studentNumber)
161
    {
162
        return $query->where('student_number', $studentNumber);
163
    }
164
165
    /**
166
     * Get memberships of this student.
167
     *
168
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
169
     */
170
    public function memberships()
171
    {
172
        return $this->hasMany(Membership::class);
173
    }
174
175
    /**
176
     * Make this student member of a given group.
177
     *
178
     * @param \App\Judite\Models\Group $group
179
     *
180
     * @throws \App\Exceptions\UserHasAlreadyGroupInCourseException
181
     *
182
     * @return \App\Judite\Models\Membership
183
     */
184
    public function join(Group $group): Membership
185
    {
186
        $exception = DB::transaction(function () use ($group) {
187
            if ($this->isMemberOfGroupInCourse($group->course_id)) {
188
                return new UserHasAlreadyGroupInCourseException(Course::find($group->course_id));
189
            }
190
        });
191
192
        if ($exception) {
193
            throw $exception;
194
        }
195
196
        $membership = $this->memberships()->make();
197
        $membership->group()->associate($group);
198
        $membership->course_id = $group->course_id;
199
        $membership->save();
200
201
        return $membership;
202
    }
203
204
    /**
205
     * Check if this student is member of a group in a course.
206
     *
207
     * @param $course_id
208
     *
209
     * @return bool
210
     */
211
    public function isMemberOfGroupInCourse($courseId): bool
212
    {
213
        return $this->memberships()->where('course_id', $courseId)->exists();
214
    }
215
216
    /**
217
     * Remove membership in the given group.
218
     *
219
     * @param \App\Judite\Models\Group $group
220
     *
221
     * @return bool
222
     */
223
    public function leave(Group $group): bool
224
    {
225
        return $this->getMembershipInGroup($group)->delete();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getMembers...Group($group)->delete() could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
226
    }
227
228
    /**
229
     * Get membership of this student in a given course.
230
     *
231
     * @param \App\Judite\Models\Group $group
232
     *
233
     * @return \App\Judite\Models\Membership|null
234
     */
235
    public function getMembershipInGroup(Group $group)
236
    {
237
        return $this->memberships()
238
            ->where('group_id', $group->id)
239
            ->first();
240
    }
241
242
    /**
243
     * Get invitations of this student.
244
     *
245
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
246
     */
247
    public function invitations()
248
    {
249
        return $this->hasMany(Invitation::class);
250
    }
251
252
    public function findMembershipByCourse($courseId)
253
    {
254
        return $this->memberships()
255
            ->whereCourseId($courseId)
256
            ->first();
257
    }
258
}
259