Completed
Push — master ( 399dd2...21b117 )
by ARCANEDEV
11s
created

User::detachRole()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

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