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