Completed
Push — master ( 4623fe...be1a12 )
by ARCANEDEV
09:43
created

User::setLastNameAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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