Completed
Pull Request — master (#23)
by ARCANEDEV
02:45
created

AuthUserTrait   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 161
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 11

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 12
lcom 2
cbo 11
dl 0
loc 161
rs 10
c 0
b 0
f 0
ccs 17
cts 17
cp 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getPermissionsAttribute() 0 11 2
A attachRole() 0 9 2
A syncRoles() 0 13 1
A detachRole() 0 10 1
A detachAllRoles() 0 10 1
A may() 0 8 1
A mayOne() 0 9 3
A mayAll() 0 6 1
1
<?php namespace Arcanedev\LaravelAuth\Models\Traits;
2
3
use Arcanedev\LaravelAuth\Events\Users\AttachedRoleToUser;
4
use Arcanedev\LaravelAuth\Events\Users\AttachingRoleToUser;
5
use Arcanedev\LaravelAuth\Events\Users\DetachedRole;
6
use Arcanedev\LaravelAuth\Events\Users\DetachedRoles;
7
use Arcanedev\LaravelAuth\Events\Users\DetachingRole;
8
use Arcanedev\LaravelAuth\Events\Users\DetachingRoles;
9
use Arcanedev\LaravelAuth\Events\Users\SyncedUserWithRoles;
10
use Arcanedev\LaravelAuth\Events\Users\SyncingUserWithRoles;
11
use Arcanedev\LaravelAuth\Models\Permission;
12
use Arcanedev\LaravelAuth\Models\Role;
13
use Arcanesoft\Contracts\Auth\Models\Role as RoleContract;
14
use Illuminate\Database\Eloquent\Collection;
15
16
/**
17
 * Trait     AuthUserTrait
18
 *
19
 * @package  Arcanedev\LaravelAuth\Traits
20
 * @author   ARCANEDEV <[email protected]>
21
 *
22
 * @property  \Illuminate\Database\Eloquent\Collection  permissions
23
 */
24
trait AuthUserTrait
25
{
26
    /* ------------------------------------------------------------------------------------------------
27
     |  Traits
28
     | ------------------------------------------------------------------------------------------------
29
     */
30
    use AuthRoleTrait;
31
32
    /* ------------------------------------------------------------------------------------------------
33
     |  Getters & Setters
34 9
     | ------------------------------------------------------------------------------------------------
35
     */
36 9
    /**
37
     * Get all user permissions.
38 9
     *
39
     * @return \Illuminate\Database\Eloquent\Collection
40 9
     */
41
    public function getPermissionsAttribute()
42
    {
43 9
        $permissions = new Collection;
44
45
        foreach ($this->roles as $role) {
46
            /** @var Role $role */
47
            $permissions = $permissions->merge($role->permissions);
48
        }
49
50
        return $permissions;
51
    }
52
53
    /* -----------------------------------------------------------------
54
     |  Main Methods
55
     | -----------------------------------------------------------------
56
     */
57
    /**
58
     * Attach a role to a user.
59 9
     *
60 9
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
61 9
     * @param  bool                                    $reload
62
     */
63 9
    public function attachRole($role, $reload = true)
64
    {
65
        if ( ! $this->hasRole($role)) {
66
            event(new AttachingRoleToUser($this, $role));
0 ignored issues
show
Bug introduced by
It seems like $role defined by parameter $role on line 63 can also be of type integer; however, Arcanedev\LaravelAuth\Ev...leToUser::__construct() does only seem to accept object<Arcanesoft\Contracts\Auth\Models\Role>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
67
            $this->roles()->attach($role);
68
            $this->loadRoles($reload);
69
            event(new AttachedRoleToUser($this, $role));
0 ignored issues
show
Bug introduced by
It seems like $role defined by parameter $role on line 63 can also be of type integer; however, Arcanedev\LaravelAuth\Ev...leToUser::__construct() does only seem to accept object<Arcanesoft\Contracts\Auth\Models\Role>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
70
        }
71
    }
72
73
    /**
74 6
     * Sync the roles by its slugs.
75
     *
76 6
     * @param  array  $slugs
77 6
     * @param  bool   $reload
78 6
     *
79
     * @return array
80
     */
81 6
    public function syncRoles(array $slugs, $reload = true)
82
    {
83
        /** @var \Illuminate\Database\Eloquent\Collection $roles */
84
        $roles  = app(RoleContract::class)->whereIn('slug', $slugs)->get();
85
86
        event(new SyncingUserWithRoles($this, $roles));
87
        $synced = $this->roles()->sync($roles->pluck('id'));
88
        event(new SyncedUserWithRoles($this, $roles, $synced));
89
90
        $this->loadRoles($reload);
91
92 3
        return $synced;
93
    }
94 3
95
    /**
96 3
     * Detach a role from a user.
97
     *
98
     * @param  \Arcanesoft\Contracts\Auth\Models\Role|int  $role
99
     * @param  bool                                        $reload
100
     *
101
     * @return int
102
     */
103
    public function detachRole($role, $reload = true)
104
    {
105
        event(new DetachingRole($this, $role));
0 ignored issues
show
Bug introduced by
It seems like $role defined by parameter $role on line 103 can also be of type integer; however, Arcanedev\LaravelAuth\Ev...hingRole::__construct() does only seem to accept object<Arcanesoft\Contracts\Auth\Models\Role>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
106
        $results = $this->roles()->detach($role);
107
        event(new DetachedRole($this, $role, $results));
0 ignored issues
show
Bug introduced by
It seems like $role defined by parameter $role on line 103 can also be of type integer; however, Arcanedev\LaravelAuth\Ev...chedRole::__construct() does only seem to accept object<Arcanesoft\Contracts\Auth\Models\Role>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
108
109
        $this->loadRoles($reload);
110
111
        return $results;
112
    }
113
114
    /**
115
     * Detach all roles from a user.
116
     *
117
     * @param  bool  $reload
118
     *
119
     * @return int
120
     */
121
    public function detachAllRoles($reload = true)
122
    {
123
        event(new DetachingRoles($this));
124
        $results = $this->roles()->detach();
125
        event(new DetachedRoles($this, $results));
126
127
        $this->loadRoles($reload);
128
129
        return $results;
130
    }
131
132
    /* -----------------------------------------------------------------
133
     |  Permission Check Methods
134
     | -----------------------------------------------------------------
135
     */
136
    /**
137
     * Check if the user has a permission.
138
     *
139
     * @param  string  $slug
140
     *
141
     * @return bool
142
     */
143
    public function may($slug)
144
    {
145
        $permissions = $this->permissions->filter(function(Permission $permission) use ($slug) {
146
            return $permission->slug === str_slug($slug, config('laravel-auth.slug-separator', '.'));
147
        });
148
149
        return ! $permissions->isEmpty();
150
    }
151
152
    /**
153
     * Check if the user has at least one permission.
154
     *
155
     * @param  array  $permissions
156
     * @param  array  $failedPermissions
157
     *
158
     * @return bool
159
     */
160
    public function mayOne(array $permissions, array &$failedPermissions = [])
161
    {
162
        foreach ($permissions as $permission) {
163
            if ( ! $this->may($permission))
164
                $failedPermissions[] = $permission;
165
        }
166
167
        return count($permissions) !== count($failedPermissions);
168
    }
169
170
    /**
171
     * Check if the user has all permissions.
172
     *
173
     * @param  array  $permissions
174
     * @param  array  $failedPermissions
175
     *
176
     * @return bool
177
     */
178
    public function mayAll(array $permissions, array &$failedPermissions = [])
179
    {
180
        $this->mayOne($permissions, $failedPermissions);
181
182
        return count($failedPermissions) === 0;
183
    }
184
}
185