Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
71 / 71 |
|
100.00% |
27 / 27 |
CRAP | |
100.00% |
1 / 1 |
User | |
100.00% |
71 / 71 |
|
100.00% |
27 / 27 |
29 | |
100.00% |
1 / 1 |
contact | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
groups | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isFreeloader | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
license | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
privileges | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
1 | |||
getPrivilegesAttribute | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
personalData | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
settings | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
state | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
userAngelTypes | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
isAngelTypeSupporter | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
logs | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
news | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newsComments | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
oauth | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
shiftEntries | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
worklogs | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
worklogsCreated | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
sessions | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
questionsAsked | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
questionsAnswered | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
messagesSent | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
messagesReceived | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
messages | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
shiftsCreated | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
shiftsUpdated | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDisplayNameAttribute | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Engelsystem\Models\User; |
6 | |
7 | use Carbon\Carbon; |
8 | use Engelsystem\Models\AngelType; |
9 | use Engelsystem\Models\BaseModel; |
10 | use Engelsystem\Models\Group; |
11 | use Engelsystem\Models\LogEntry; |
12 | use Engelsystem\Models\Message; |
13 | use Engelsystem\Models\News; |
14 | use Engelsystem\Models\NewsComment; |
15 | use Engelsystem\Models\OAuth; |
16 | use Engelsystem\Models\Privilege; |
17 | use Engelsystem\Models\Question; |
18 | use Engelsystem\Models\Session; |
19 | use Engelsystem\Models\Shifts\Shift; |
20 | use Engelsystem\Models\Shifts\ShiftEntry; |
21 | use Engelsystem\Models\UserAngelType; |
22 | use Engelsystem\Models\Worklog; |
23 | use Illuminate\Database\Eloquent\Builder; |
24 | use Illuminate\Database\Eloquent\Collection; |
25 | use Illuminate\Database\Eloquent\Factories\HasFactory; |
26 | use Illuminate\Database\Eloquent\Relations\BelongsToMany; |
27 | use Illuminate\Database\Eloquent\Relations\HasMany; |
28 | use Illuminate\Database\Eloquent\Relations\HasOne; |
29 | use Illuminate\Database\Query\Builder as QueryBuilder; |
30 | use Illuminate\Support\Collection as SupportCollection; |
31 | |
32 | /** |
33 | * @property int $id |
34 | * @property string $name |
35 | * @property string $email |
36 | * @property string $password |
37 | * @property string $api_key |
38 | * @property Carbon|null $last_login_at |
39 | * @property Carbon|null $created_at |
40 | * @property Carbon|null $updated_at |
41 | * |
42 | * @property-read QueryBuilder|Contact $contact |
43 | * @property-read QueryBuilder|License $license |
44 | * @property-read QueryBuilder|PersonalData $personalData |
45 | * @property-read QueryBuilder|Settings $settings |
46 | * @property-read QueryBuilder|State $state |
47 | * @property-read string $displayName |
48 | * |
49 | * @property-read Collection|Group[] $groups |
50 | * @property-read Collection|LogEntry[] $logs |
51 | * @property-read Collection|News[] $news |
52 | * @property-read Collection|NewsComment[] $newsComments |
53 | * @property-read Collection|OAuth[] $oauth |
54 | * @property-read SupportCollection|Privilege[] $privileges |
55 | * @property-read Collection|AngelType[] $userAngelTypes |
56 | * @property-read UserAngelType $pivot |
57 | * @property-read Collection|ShiftEntry[] $shiftEntries |
58 | * @property-read Collection|Session[] $sessions |
59 | * @property-read Collection|Worklog[] $worklogs |
60 | * @property-read Collection|Worklog[] $worklogsCreated |
61 | * @property-read Collection|Question[] $questionsAsked |
62 | * @property-read Collection|Question[] $questionsAnswered |
63 | * @property-read Collection|Message[] $messagesReceived |
64 | * @property-read Collection|Message[] $messagesSent |
65 | * @property-read Collection|Message[] $messages |
66 | * @property-read Collection|Shift[] $shiftsCreated |
67 | * @property-read Collection|Shift[] $shiftsUpdated |
68 | * |
69 | * @method static QueryBuilder|User[] whereId($value) |
70 | * @method static QueryBuilder|User[] whereName($value) |
71 | * @method static QueryBuilder|User[] whereEmail($value) |
72 | * @method static QueryBuilder|User[] wherePassword($value) |
73 | * @method static QueryBuilder|User[] whereApiKey($value) |
74 | * @method static QueryBuilder|User[] whereLastLoginAt($value) |
75 | * @method static QueryBuilder|User[] whereCreatedAt($value) |
76 | * @method static QueryBuilder|User[] whereUpdatedAt($value) |
77 | */ |
78 | class User extends BaseModel |
79 | { |
80 | use HasFactory; |
81 | |
82 | /** @var bool enable timestamps */ |
83 | public $timestamps = true; // phpcs:ignore |
84 | |
85 | /** @var array<string, null> default attributes */ |
86 | protected $attributes = [ // phpcs:ignore |
87 | 'last_login_at' => null, |
88 | ]; |
89 | |
90 | /** |
91 | * The attributes that are mass assignable. |
92 | * |
93 | * @var array<string> |
94 | */ |
95 | protected $fillable = [ // phpcs:ignore |
96 | 'name', |
97 | 'password', |
98 | 'email', |
99 | 'api_key', |
100 | 'last_login_at', |
101 | ]; |
102 | |
103 | /** @var array<string> The attributes that should be hidden for serialization */ |
104 | protected $hidden = [ // phpcs:ignore |
105 | 'api_key', |
106 | 'password', |
107 | ]; |
108 | |
109 | /** @var array<string, string> */ |
110 | protected $casts = [ // phpcs:ignore |
111 | 'last_login_at' => 'datetime', |
112 | ]; |
113 | |
114 | public function contact(): HasOne |
115 | { |
116 | return $this |
117 | ->hasOne(Contact::class) |
118 | ->withDefault(); |
119 | } |
120 | |
121 | public function groups(): BelongsToMany |
122 | { |
123 | return $this->belongsToMany(Group::class, 'users_groups'); |
124 | } |
125 | |
126 | public function isFreeloader(): bool |
127 | { |
128 | return $this->shiftEntries() |
129 | ->where('freeloaded', true) |
130 | ->count() |
131 | >= config('max_freeloadable_shifts'); |
132 | } |
133 | |
134 | public function license(): HasOne |
135 | { |
136 | return $this |
137 | ->hasOne(License::class) |
138 | ->withDefault(); |
139 | } |
140 | |
141 | public function privileges(): Builder |
142 | { |
143 | /** @var Builder $builder */ |
144 | $builder = Privilege::query() |
145 | ->whereIn('id', function ($query): void { |
146 | /** @var QueryBuilder $query */ |
147 | $query->select('privilege_id') |
148 | ->from('group_privileges') |
149 | ->join('users_groups', 'users_groups.group_id', '=', 'group_privileges.group_id') |
150 | ->where('users_groups.user_id', '=', $this->id) |
151 | ->distinct(); |
152 | }); |
153 | |
154 | return $builder; |
155 | } |
156 | |
157 | public function getPrivilegesAttribute(): SupportCollection |
158 | { |
159 | return $this->privileges()->get(); |
160 | } |
161 | |
162 | public function personalData(): HasOne |
163 | { |
164 | return $this |
165 | ->hasOne(PersonalData::class) |
166 | ->withDefault(); |
167 | } |
168 | |
169 | public function settings(): HasOne |
170 | { |
171 | return $this |
172 | ->hasOne(Settings::class) |
173 | ->withDefault(); |
174 | } |
175 | |
176 | public function state(): HasOne |
177 | { |
178 | return $this |
179 | ->hasOne(State::class) |
180 | ->withDefault(); |
181 | } |
182 | |
183 | public function userAngelTypes(): BelongsToMany |
184 | { |
185 | return $this |
186 | ->belongsToMany(AngelType::class, 'user_angel_type') |
187 | ->using(UserAngelType::class) |
188 | ->withPivot(UserAngelType::getPivotAttributes()); |
189 | } |
190 | |
191 | public function isAngelTypeSupporter(AngelType $angelType): bool |
192 | { |
193 | return $this->userAngelTypes() |
194 | ->wherePivot('angel_type_id', $angelType->id) |
195 | ->wherePivot('supporter', true) |
196 | ->exists(); |
197 | } |
198 | |
199 | public function logs(): HasMany |
200 | { |
201 | return $this->hasMany(LogEntry::class); |
202 | } |
203 | |
204 | public function news(): HasMany |
205 | { |
206 | return $this->hasMany(News::class); |
207 | } |
208 | |
209 | public function newsComments(): HasMany |
210 | { |
211 | return $this->hasMany(NewsComment::class); |
212 | } |
213 | |
214 | public function oauth(): HasMany |
215 | { |
216 | return $this->hasMany(OAuth::class); |
217 | } |
218 | |
219 | public function shiftEntries(): HasMany |
220 | { |
221 | return $this->hasMany(ShiftEntry::class); |
222 | } |
223 | |
224 | public function worklogs(): HasMany |
225 | { |
226 | return $this->hasMany(Worklog::class); |
227 | } |
228 | |
229 | public function worklogsCreated(): HasMany |
230 | { |
231 | return $this->hasMany(Worklog::class, 'creator_id'); |
232 | } |
233 | |
234 | public function sessions(): HasMany |
235 | { |
236 | return $this->hasMany(Session::class); |
237 | } |
238 | |
239 | public function questionsAsked(): HasMany |
240 | { |
241 | return $this->hasMany(Question::class, 'user_id') |
242 | ->where('user_id', $this->id); |
243 | } |
244 | |
245 | public function questionsAnswered(): HasMany |
246 | { |
247 | return $this->hasMany(Question::class, 'answerer_id') |
248 | ->where('answerer_id', $this->id); |
249 | } |
250 | |
251 | public function messagesSent(): HasMany |
252 | { |
253 | return $this->hasMany(Message::class, 'user_id') |
254 | ->orderBy('created_at', 'DESC') |
255 | ->orderBy('id', 'DESC'); |
256 | } |
257 | |
258 | public function messagesReceived(): HasMany |
259 | { |
260 | return $this->hasMany(Message::class, 'receiver_id') |
261 | ->orderBy('read') |
262 | ->orderBy('created_at', 'DESC') |
263 | ->orderBy('id', 'DESC'); |
264 | } |
265 | |
266 | /** |
267 | * Returns a HasMany relation for all messages sent or received by the user. |
268 | */ |
269 | public function messages(): HasMany |
270 | { |
271 | return $this->messagesSent() |
272 | ->union($this->messagesReceived()) |
273 | ->orderBy('read') |
274 | ->orderBy('id', 'DESC'); |
275 | } |
276 | |
277 | public function shiftsCreated(): HasMany |
278 | { |
279 | return $this->hasMany(Shift::class, 'created_by'); |
280 | } |
281 | |
282 | public function shiftsUpdated(): HasMany |
283 | { |
284 | return $this->hasMany(Shift::class, 'updated_by'); |
285 | } |
286 | |
287 | public function getDisplayNameAttribute(): string |
288 | { |
289 | if ( |
290 | config('display_full_name') |
291 | && !empty(trim($this->personalData->first_name . $this->personalData->last_name)) |
292 | ) { |
293 | return trim( |
294 | trim((string) $this->personalData->first_name) |
295 | . ' ' . |
296 | trim((string) $this->personalData->last_name) |
297 | ); |
298 | } |
299 | |
300 | return $this->name; |
301 | } |
302 | } |