Passed
Pull Request — develop (#18)
by
unknown
07:13
created

Student::confirmGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 14
rs 10
1
<?php
2
3
namespace App\Judite\Models;
4
5
use Illuminate\Database\Eloquent\Model;
6
use App\Exceptions\EnrollmentCannotBeDeleted;
7
use App\Exceptions\StudentIsNotMemberOfGroupException;
8
use App\Exceptions\StudentIsNotInvitedToGroupException;
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
    protected $visible = ['user','student_number'];
29
30
    /**
31
     * Get user who owns this student.
32
     *
33
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
34
     */
35
    public function user()
36
    {
37
        return $this->belongsTo(User::class);
38
    }
39
40
    /**
41
     * Get exchanges requested by this student.
42
     *
43
     * @return \Illuminate\Database\Eloquent\Builder
44
     */
45
    public function requestedExchanges()
46
    {
47
        $enrollmentsRelationship = $this->enrollments();
48
        $enrollmentsKeyName = $enrollmentsRelationship->getRelated()->getKeyName();
49
        $enrollmentsIdsQuery = $enrollmentsRelationship
50
            ->select($enrollmentsKeyName)
51
            ->getBaseQuery();
52
53
        return Exchange::whereFromEnrollmentIn($enrollmentsIdsQuery);
54
    }
55
56
    /**
57
     * Get exchanges proposed to this student.
58
     *
59
     * @return \Illuminate\Database\Eloquent\Builder
60
     */
61
    public function proposedExchanges()
62
    {
63
        $enrollmentsRelationship = $this->enrollments();
64
        $enrollmentsKeyName = $enrollmentsRelationship->getRelated()->getKeyName();
65
        $enrollmentsIdsQuery = $enrollmentsRelationship
66
            ->select($enrollmentsKeyName)
67
            ->getBaseQuery();
68
69
        return Exchange::whereToEnrollmentIn($enrollmentsIdsQuery);
70
    }
71
72
    /**
73
     * Get enrollments of this student.
74
     *
75
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
76
     */
77
    public function enrollments()
78
    {
79
        return $this->hasMany(Enrollment::class);
80
    }
81
82
    /**
83
     * Get groups for this student.
84
     *
85
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
86
     */
87
    public function groups()
88
    {
89
        return $this->belongsToMany(Group::class)
90
                    ->as('invitation')
91
                    ->withPivot('accepted_at');
92
    }
93
94
    /**
95
     * Get pending groups for this student.
96
     *
97
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
98
     */
99
    public function pendingGroups()
100
    {
101
        return $this->groups()->wherePivot('accepted_at', '=', null);
102
    }
103
104
    /**
105
     * Get confirmed groups for this student.
106
     *
107
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
108
     */
109
    public function confirmedGroups()
110
    {
111
        return $this->groups()->wherePivot('accepted_at', '!=', null);
112
    }
113
114
    /**
115
     * Get enrollment of this student in a given course.
116
     *
117
     * @param \App\Judite\Models\Course $course
118
     *
119
     * @return \App\Judite\Models\Enrollment|null
120
     */
121
    public function getEnrollmentInCourse(Course $course)
122
    {
123
        return $this->enrollments()
124
            ->where('course_id', $course->id)
125
            ->first();
126
    }
127
128
    /**
129
     * Get group of this student in a given course.
130
     *
131
     * @param \App\Judite\Models\Course $course
132
     *
133
     * @return \App\Judite\Models\Group|null
134
     */
135
    public function getGroupInCourse(Course $course)
136
    {
137
        return $this->groups()
138
            ->where('course_id', $course->id)
139
            ->first();
140
    }
141
142
    /**
143
     * Enroll this student with a given course.
144
     *
145
     * @param \App\Judite\Models\Course $course
146
     *
147
     * @throws \App\Exceptions\UserIsAlreadyEnrolledInCourseException
148
     *
149
     * @return \App\Judite\Models\Enrollment
150
     */
151
    public function enroll(Course $course): Enrollment
152
    {
153
        if ($this->isEnrolledInCourse($course)) {
154
            throw new UserIsAlreadyEnrolledInCourseException($course);
155
        }
156
157
        $enrollment = $this->enrollments()->make();
158
        $enrollment->course()->associate($course);
159
        $enrollment->save();
160
161
        return $enrollment;
162
    }
163
164
    /**
165
     * Check if this student is enrolled in a course.
166
     *
167
     * @param \App\Judite\Models\Course $course
168
     *
169
     * @return bool
170
     */
171
    public function isEnrolledInCourse(Course $course): bool
172
    {
173
        return $this->enrollments()->where('course_id', $course->id)->exists();
174
    }
175
176
    /**
177
     * Remove enrollment in the given course.
178
     *
179
     * @param \App\Judite\Models\Course $course
180
     *
181
     * @throws \App\Exceptions\StudentIsNotEnrolledInCourseException|\App\Exceptions\EnrollmentCannotBeDeleted
182
     *
183
     * @return bool
184
     */
185
    public function unenroll(Course $course): bool
186
    {
187
        $enrollment = $this->getEnrollmentInCourse($course);
188
189
        if (is_null($enrollment)) {
190
            throw new StudentIsNotEnrolledInCourseException($course);
191
        }
192
193
        if (! $enrollment->isDeletable()) {
194
            throw new EnrollmentCannotBeDeleted($enrollment);
195
        }
196
197
        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...
198
    }
199
200
    /**
201
     * Confirm this student with a given group.
202
     *
203
     * @param \App\Judite\Models\Group $group
204
     *
205
     * @return \App\Judite\Models\Student
206
     */
207
    public function confirmGroup(Group $group): self
208
    {
209
        throw_unless(
210
            $this->isInvitedToGroup($group),
211
            new StudentIsNotMemberOfGroupException()
212
        );
213
214
        $atributtes = [
215
            'accepted_at' => now(),
216
        ];
217
218
        $this->groups()->updateExistingPivot($group->id, $atributtes);
219
220
        return $this;
221
    }
222
223
    /**
224
     * Decline this student with a given group.
225
     *
226
     * @param \App\Judite\Models\Group $group
227
     *
228
     * @return \App\Judite\Models\Student
229
     */
230
    public function declineGroup(Group $group): self
231
    {
232
        throw_unless(
233
            $this->isInvitedToGroup($group),
234
            new StudentIsNotInvitedToGroupException()
235
        );
236
237
        $group->removeMember($this);
238
239
        return $this;
240
    }
241
242
    /**
243
     * Leave the given group.
244
     *
245
     * @param \App\Judite\Models\Group $group
246
     *
247
     * @return \App\Judite\Models\Student
248
     */
249
    public function leaveGroup(Group $group): self
250
    {
251
        throw_unless(
252
            $this->isMemberOfGroup($group),
253
            new StudentIsNotMemberOfGroupException()
254
        );
255
256
        $group->removeMember($this);
257
258
        return $this;
259
    }
260
261
    /**
262
     * Check if this student has a group in the given course.
263
     *
264
     * @param \App\Judite\Models\Course $course
265
     *
266
     * @return bool
267
     */
268
    public function hasGroupInCourse(Course $course): bool
269
    {
270
        return $this->confirmedGroups()->where('course_id', $course->id)->exists();
271
    }
272
273
    /**
274
     * Check if this student has an eligible group in the given course.
275
     *
276
     * @param \App\Judite\Models\Course $course
277
     *
278
     * @return bool
279
     */
280
    public function hasAvailableGroupInCourse(Course $course)
281
    {
282
        return $this->hasGroupInCourse($course) &&
283
        $this->getGroupInCourse($course)->isAvailableToJoin();
284
    }
285
286
    /**
287
     * Check if this student is attached to the given group.
288
     *
289
     * @param \App\Judite\Models\Group $group
290
     *
291
     * @return bool
292
     */
293
    public function isAssociatedToGroup(Group $group): bool
294
    {
295
        return $this->groups()->where('group_id', $group->id)->exists();
296
    }
297
298
    /**
299
     * Check if this student is invited to the given group.
300
     *
301
     * @param \App\Judite\Models\Group $group
302
     *
303
     * @return bool
304
     */
305
    public function isInvitedToGroup(Group $group): bool
306
    {
307
        return $this->pendingGroups()->where('group_id', $group->id)->exists();
308
    }
309
310
    /**
311
     * Check if this student is a member of the given group.
312
     *
313
     * @param \App\Judite\Models\Group $group
314
     *
315
     * @return bool
316
     */
317
    public function isMemberOfGroup(Group $group): bool
318
    {
319
        return $this->confirmedGroups()->where('group_id', $group->id)->exists();
320
    }
321
322
    public function getCoursesWithoutGroup()
323
    {
324
        $enrollments = $this->enrollments()->get();
325
        $courses = collect([]);
326
        foreach($enrollments as $enrollment) {
327
            if(! $this->hasGroupInCourse($enrollment->course()->first())) {
328
                $courses->prepend($enrollment->course()->first());
329
            }
330
        }
331
        return $courses;
332
    }
333
    
334
    /**
335
     * Scope a query to only include users with the given student number.
336
     *
337
     * @param \Illuminate\Database\Eloquent\Builder $query
338
     * @param string                                $studentNumber
339
     *
340
     * @return \Illuminate\Database\Eloquent\Builder
341
     */
342
    public function scopeWhereNumber($query, $studentNumber)
343
    {
344
        return $query->where('student_number', $studentNumber);
345
    }
346
}
347