Completed
Pull Request — master (#33)
by ARCANEDEV
04:48
created

User::scopeVerifiedEmail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
cc 1
nc 1
nop 1
crap 1
1
<?php namespace Arcanedev\LaravelAuth\Models;
2
3
use Arcanedev\LaravelAuth\Events\Users\{
4
    ActivatedUser, ActivatingUser, AttachedRoleToUser, AttachingRoleToUser, CreatedUser, CreatingUser,
5
    DeactivatedUser, DeactivatingUser, DeletedUser, DeletingUser, DetachedRoleFromUser, DetachedRolesFromUser,
6
    DetachingRoleFromUser, DetachingRolesFromUser, RestoredUser, RestoringUser, SavedUser, SavingUser,
7
    SyncedUserWithRoles, SyncingUserWithRoles, UpdatedUser, UpdatingUser
8
};
9
use Arcanedev\LaravelAuth\Services\SocialAuthenticator;
10
use Arcanesoft\Contracts\Auth\Models\{
11
    Permission as PermissionContract,
12
    Role as RoleContract,
13
    User as UserContract
14
};
15
use Illuminate\Auth\{
16
    Authenticatable, MustVerifyEmail, Passwords\CanResetPassword
17
};
18
use Illuminate\Contracts\Auth\{
19
    Access\Authorizable as AuthorizableContract,
20
    Authenticatable as AuthenticatableContract,
21
    CanResetPassword as CanResetPasswordContract
22
};
23
use Illuminate\Database\Eloquent\SoftDeletes;
24
use Illuminate\Foundation\Auth\Access\Authorizable;
25
use Illuminate\Support\Collection;
26
use Illuminate\Support\Str;
27
28
/**
29
 * Class     User
30
 *
31
 * @package  Arcanedev\LaravelAuth\Models
32
 * @author   ARCANEDEV <[email protected]>
33
 *
34
 * @property  int                                       id
35
 * @property  string                                    username
36
 * @property  string                                    first_name
37
 * @property  string                                    last_name
38
 * @property  string                                    full_name
39
 * @property  string                                    email
40
 * @property  \Carbon\Carbon|null                       email_verified_at
41
 * @property  string                                    password
42
 * @property  string                                    remember_token
43
 * @property  bool                                      is_admin
44
 * @property  \Carbon\Carbon                            last_activity
45
 * @property  \Carbon\Carbon                            created_at
46
 * @property  \Carbon\Carbon                            updated_at
47
 * @property  \Carbon\Carbon|null                       activated_at
48
 * @property  \Carbon\Carbon                            deleted_at
49
 *
50
 * @property  \Illuminate\Database\Eloquent\Collection       roles
51
 * @property  \Illuminate\Support\Collection                 permissions
52
 * @property  \Arcanedev\LaravelAuth\Models\Pivots\RoleUser  pivot
53
 *
54
 * @method  static  \Illuminate\Database\Eloquent\Builder|static  lastActive(int $minutes = null)
55
 * @method  static  \Illuminate\Database\Eloquent\Builder|static  unverifiedEmail
56
 * @method  static  \Illuminate\Database\Eloquent\Builder|static  verifiedEmail
57
 */
58
class User
59
    extends AbstractModel
60
    implements UserContract, AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
61
{
62
    /* -----------------------------------------------------------------
63
     |  Traits
64
     | -----------------------------------------------------------------
65
     */
66
67
    use Authenticatable,
68
        Authorizable,
69
        CanResetPassword,
70
        MustVerifyEmail,
71
        Traits\Roleable,
72
        Traits\Activatable,
73
        SoftDeletes;
74
75
    /* -----------------------------------------------------------------
76
     |  Properties
77
     | -----------------------------------------------------------------
78
79
     */
80
    /**
81
     * The attributes that are mass assignable.
82
     *
83
     * @var array
84
     */
85
    protected $fillable = [
86
        'username',
87
        'first_name',
88
        'last_name',
89
        'email',
90
        'password',
91
        'confirmation_code',
92
    ];
93
94
    /**
95
     * The attributes excluded from the model's JSON form.
96
     *
97
     * @var array
98
     */
99
    protected $hidden   = [
100
        'password',
101
        'remember_token',
102
        'confirmation_code',
103
    ];
104
105
    /**
106
     * The attributes that should be casted to native types.
107
     *
108
     * @var array
109
     */
110
    protected $casts = [
111
        'id'           => 'integer',
112
        'is_admin'     => 'boolean',
113
        'is_active'    => 'boolean',
114
        'is_confirmed' => 'boolean',
115
    ];
116
117
    /**
118
     * The attributes that should be mutated to dates.
119
     *
120
     * @var array
121
     */
122
    protected $dates = [
123
        'confirmed_at',
124
        'last_activity',
125
        'activated_at',
126
        'deleted_at',
127
    ];
128
129
    /**
130
     * The event map for the model.
131
     *
132
     * @var array
133
     */
134
    protected $dispatchesEvents = [
135
        'creating'  => CreatingUser::class,
136
        'created'   => CreatedUser::class,
137
        'updating'  => UpdatingUser::class,
138
        'updated'   => UpdatedUser::class,
139
        'saving'    => SavingUser::class,
140
        'saved'     => SavedUser::class,
141
        'deleting'  => DeletingUser::class,
142
        'deleted'   => DeletedUser::class,
143
        'restoring' => RestoringUser::class,
144
        'restored'  => RestoredUser::class,
145
    ];
146
147
    /* -----------------------------------------------------------------
148
     |  Constructor
149
     | -----------------------------------------------------------------
150
     */
151
152
    /**
153
     * Create a new Eloquent model instance.
154
     *
155
     * @param  array  $attributes
156
     */
157 93
    public function __construct(array $attributes = [])
158
    {
159 93
        parent::__construct($attributes);
160
161 93
        $this->setupModel();
162 93
    }
163
164
    /**
165
     * Setup the model.
166
     */
167 93
    protected function setupModel()
168
    {
169 93
        $this->setTable(config('laravel-auth.users.table', 'users'));
170
171 93
        if (SocialAuthenticator::isEnabled()) {
172 93
            $this->hidden   = array_merge($this->hidden, ['social_provider_id']);
173 93
            $this->fillable = array_merge($this->fillable, ['social_provider', 'social_provider_id']);
174
        }
175 93
    }
176
177
    /* -----------------------------------------------------------------
178
     |  Relationships
179
     | -----------------------------------------------------------------
180
     */
181
182
    /**
183
     * User belongs to many roles.
184
     *
185
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
186
     */
187 42
    public function roles()
188
    {
189 42
        return $this->belongsToMany(
190 42
                config('laravel-auth.roles.model', Role::class),
191 42
                $this->getPrefix().config('laravel-auth.role-user.table', 'role_user')
192
            )
193 42
            ->using(Pivots\RoleUser::class)
194 42
            ->withTimestamps();
195
    }
196
197
    /**
198
     * Get all user permissions.
199
     *
200
     * @return \Illuminate\Support\Collection
201
     */
202 9
    public function getPermissionsAttribute()
203
    {
204 9
        return $this->active_roles
205 9
            ->pluck('permissions')
206 9
            ->flatten()
207
            ->unique(function (PermissionContract $permission) {
208 9
                return $permission->getKey();
209 9
            });
210
    }
211
212
    /* -----------------------------------------------------------------
213
     |  Scopes
214
     | -----------------------------------------------------------------
215
     */
216
217
    /**
218
     * Scope last active users.
219
     *
220
     * @param  \Illuminate\Database\Eloquent\Builder  $query
221
     * @param  int|null                               $minutes
222
     *
223
     * @return \Illuminate\Database\Eloquent\Builder
224
     */
225 3
    public function scopeLastActive($query, $minutes = null)
226
    {
227 3
        $date = $this->freshTimestamp()->subMinutes(
228 3
            $minutes ?: config('laravel_auth.track-activity.minutes', 5)
229
        );
230
231 3
        return $query->where('last_activity', '>=', $date->toDateTimeString());
232
    }
233
234
    /**
235
     * Scope unverified emails' users.
236
     *
237
     * @param  \Illuminate\Database\Eloquent\Builder  $query
238
     *
239
     * @return \Illuminate\Database\Eloquent\Builder
240
     */
241 3
    public function scopeUnverifiedEmail($query)
242
    {
243 3
        return $query->whereNull('email_verified_at');
244
    }
245
246
    /**
247
     * Scope unverified emails' users.
248
     *
249
     * @param  \Illuminate\Database\Eloquent\Builder  $query
250
     *
251
     * @return \Illuminate\Database\Eloquent\Builder
252
     */
253 3
    public function scopeVerifiedEmail($query)
254
    {
255 3
        return $query->whereNotNull('email_verified_at');
256
    }
257
258
    /* -----------------------------------------------------------------
259
     |  Getters & Setters
260
     | -----------------------------------------------------------------
261
     */
262
263
    /**
264
     * Set the `email` attribute.
265
     *
266
     * @param  string  $email
267
     */
268 75
    public function setEmailAttribute($email)
269
    {
270 75
        $this->attributes['email'] = Str::lower($email);
271 75
    }
272
273
    /**
274
     * Set the `username` attribute.
275
     *
276
     * @param  string  $username
277
     */
278 72
    public function setUsernameAttribute($username)
279
    {
280 72
        $this->attributes['username'] = Str::slug($username, config('laravel-auth.users.slug-separator', '.'));
281 72
    }
282
283
    /**
284
     * Set the `first_name` attribute.
285
     *
286
     * @param  string  $firstName
287
     */
288 75
    public function setFirstNameAttribute($firstName)
289
    {
290 75
        $this->attributes['first_name'] = Str::title(Str::lower($firstName));
291 75
    }
292
293
    /**
294
     * Set the `last_name` attribute.
295
     *
296
     * @param  string  $lastName
297
     */
298 75
    public function setLastNameAttribute($lastName)
299
    {
300 75
        $this->attributes['last_name'] = Str::upper($lastName);
301 75
    }
302
303
    /**
304
     * Get the `full_name` attribute.
305
     *
306
     * @return string
307
     */
308 6
    public function getFullNameAttribute()
309
    {
310 6
        return $this->first_name.' '.$this->last_name;
311
    }
312
313
    /**
314
     * Set the `password` attribute.
315
     *
316
     * @param  string  $password
317
     */
318 72
    public function setPasswordAttribute($password)
319
    {
320 72
        $this->attributes['password'] = bcrypt($password);
321 72
    }
322
323
    /* -----------------------------------------------------------------
324
     |  Main Methods
325
     | -----------------------------------------------------------------
326
     */
327
328
    /**
329
     * Activate the model.
330
     *
331
     * @param  bool  $save
332
     *
333
     * @return bool
334
     */
335 3
    public function activate($save = true)
336
    {
337 3
        event(new ActivatingUser($this));
338 3
        $result = $this->switchActive(true, $save);
339 3
        event(new ActivatedUser($this));
340
341 3
        return $result;
342
    }
343
344
    /**
345
     * Deactivate the model.
346
     *
347
     * @param  bool  $save
348
     *
349
     * @return bool
350
     */
351 3
    public function deactivate($save = true)
352
    {
353 3
        event(new DeactivatingUser($this));
354 3
        $result = $this->switchActive(false, $save);
355 3
        event(new DeactivatedUser($this));
356
357 3
        return $result;
358
    }
359
360
    /**
361
     * Attach a role to a user.
362
     *
363
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
364
     * @param  bool                                        $reload
365
     */
366 33
    public function attachRole($role, $reload = true)
367
    {
368 33
        if ($this->hasRole($role)) return;
369
370 33
        event(new AttachingRoleToUser($this, $role));
371 33
        $this->roles()->attach($role);
372 33
        event(new AttachedRoleToUser($this, $role));
373
374 33
        $this->loadRoles($reload);
375 33
    }
376
377
    /**
378
     * Sync the roles by its slugs.
379
     *
380
     * @param  array|\Illuminate\Support\Collection  $slugs
381
     * @param  bool                                  $reload
382
     *
383
     * @return array
384
     */
385 3
    public function syncRoles($slugs, $reload = true)
386
    {
387
        /** @var  \Illuminate\Database\Eloquent\Collection  $roles */
388 3
        $roles = app(RoleContract::class)->whereIn('slug', $slugs)->get();
389
390 3
        event(new SyncingUserWithRoles($this, $roles));
391 3
        $synced = $this->roles()->sync($roles->pluck('id'));
392 3
        event(new SyncedUserWithRoles($this, $roles, $synced));
393
394 3
        $this->loadRoles($reload);
395
396 3
        return $synced;
397
    }
398
399
    /**
400
     * Detach a role from a user.
401
     *
402
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
403
     * @param  bool                                        $reload
404
     *
405
     * @return int
406
     */
407 3
    public function detachRole($role, $reload = true)
408
    {
409 3
        event(new DetachingRoleFromUser($this, $role));
410 3
        $results = $this->roles()->detach($role);
411 3
        event(new DetachedRoleFromUser($this, $role, $results));
412
413 3
        $this->loadRoles($reload);
414
415 3
        return $results;
416
    }
417
418
    /**
419
     * Detach all roles from a user.
420
     *
421
     * @param  bool  $reload
422
     *
423
     * @return int
424
     */
425 3
    public function detachAllRoles($reload = true)
426
    {
427 3
        event(new DetachingRolesFromUser($this));
428 3
        $results = $this->roles()->detach();
429 3
        event(new DetachedRolesFromUser($this, $results));
430
431 3
        $this->loadRoles($reload);
432
433 3
        return $results;
434
    }
435
436
    /**
437
     * Update the user's last activity.
438
     *
439
     * @param  bool  $save
440
     */
441 3
    public function updateLastActivity($save = true)
442
    {
443 3
        $this->forceFill(['last_activity' => $this->freshTimestamp()]);
444
445 3
        if ($save) $this->save();
446 3
    }
447
448
    /* -----------------------------------------------------------------
449
     |  Permission Check Methods
450
     | -----------------------------------------------------------------
451
     */
452
    /**
453
     * Check if the user has a permission.
454
     *
455
     * @param  string  $slug
456
     *
457
     * @return bool
458
     */
459 9
    public function may($slug)
460
    {
461
        return ! $this->permissions->filter(function (PermissionContract $permission) use ($slug) {
462 9
            return $permission->hasSlug($slug);
463 9
        })->isEmpty();
464
    }
465
466
    /**
467
     * Check if the user has at least one permission.
468
     *
469
     * @param  \Illuminate\Support\Collection|array  $permissions
470
     * @param  \Illuminate\Support\Collection        &$failed
471
     *
472
     * @return bool
473
     */
474 6
    public function mayOne($permissions, &$failed = null)
475
    {
476 6
        $permissions = is_array($permissions) ? collect($permissions) : $permissions;
477
478
        $failed = $permissions->reject(function ($permission) {
479 6
            return $this->may($permission);
480 6
        })->values();
481
482 6
        return $permissions->count() !== $failed->count();
483
    }
484
485
    /**
486
     * Check if the user has all permissions.
487
     *
488
     * @param  \Illuminate\Support\Collection|array  $permissions
489
     * @param  \Illuminate\Support\Collection        &$failed
490
     *
491
     * @return bool
492
     */
493 3
    public function mayAll($permissions, &$failed = null)
494
    {
495 3
        $this->mayOne($permissions, $failed);
496
497 3
        return $failed instanceof Collection ? $failed->isEmpty() : false;
498
    }
499
500
    /* -----------------------------------------------------------------
501
     |  Check Methods
502
     | -----------------------------------------------------------------
503
     */
504
505
    /**
506
     * Check if user is an administrator.
507
     *
508
     * @return bool
509
     */
510 15
    public function isAdmin()
511
    {
512 15
        return $this->is_admin;
513
    }
514
515
    /**
516
     * Check if user is a moderator.
517
     *
518
     * @return bool
519
     */
520 6
    public function isModerator()
521
    {
522
        // Override this method to give more privileges than members.
523 6
        return false;
524
    }
525
526
    /**
527
     * Check if user is a member.
528
     *
529
     * @return bool
530
     */
531 9
    public function isMember()
532
    {
533 9
        return ! $this->isAdmin();
534
    }
535
536
    /**
537
     * Check if user can be impersonated.
538
     *
539
     * @return bool
540
     */
541 3
    public function canBeImpersonated()
542
    {
543 3
        return $this->isMember();
544
    }
545
}
546