Completed
Push — master ( a07a51...d6976d )
by Mostafa Abd El-Salam
15s
created

HasRoles::getRoleClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 2
cts 2
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Maklad\Permission\Traits;
4
5
use Illuminate\Support\Collection;
6
use Jenssegers\Mongodb\Eloquent\Builder;
7
use Jenssegers\Mongodb\Eloquent\Model;
8
use Maklad\Permission\Contracts\RoleInterface as Role;
9
use Maklad\Permission\PermissionRegistrar;
10
use ReflectionException;
11
12
/**
13
 * Trait HasRoles
14
 * @package Maklad\Permission\Traits
15
 */
16
trait HasRoles
17
{
18
    use HasPermissions;
19
20
    private $roleClass;
21
22 123
    public static function bootHasRoles()
23 5
    {
24 2
        static::deleting(function (Model $model) {
25
            if (isset($model->forceDeleting) && !$model->forceDeleting) {
0 ignored issues
show
Bug introduced by
The property forceDeleting does not seem to exist on Jenssegers\Mongodb\Eloquent\Model. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
26
                return;
27 3
            }
28 123
29 123
            $model->roles()->sync([]);
30
        });
31
    }
32
33
    public function getRoleClass()
34 69
    {
35
        if ($this->roleClass === null) {
36 69
            $this->roleClass = app(PermissionRegistrar::class)->getRoleClass();
37
        }
38
        return $this->roleClass;
39
    }
40
41
    /**
42
     * A model may have multiple roles.
43
     */
44
    public function roles()
45
    {
46
        return $this->belongsToMany(config('permission.models.role'));
0 ignored issues
show
Bug introduced by
It seems like belongsToMany() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
        return $this->/** @scrutinizer ignore-call */ belongsToMany(config('permission.models.role'));
Loading history...
47 4
    }
48
49 4
    /**
50
     * Scope the model query to certain roles only.
51 4
     *
52
     * @param Builder $query
53
     * @param string|array|Role|Collection $roles
54
     *
55
     * @return Builder
56
     */
57
    public function scopeRole(Builder $query, $roles): Builder
58
    {
59
        $roles = $this->convertToRoleModels($roles);
60
61 55
        return $query->whereIn('role_ids', $roles->pluck('_id'));
62
    }
63 55
64 55
    /**
65 55
     * Assign the given role to the model.
66 55
     *
67 55
     * @param array|string|Role ...$roles
68 53
     *
69 53
     * @return array|Role|string
70 53
     */
71 51
    public function assignRole(...$roles)
72
    {
73 51
        $roles = \collect($roles)
74
            ->flatten()
75 51
            ->map(function ($role) {
76
                return $this->getStoredRole($role);
77 51
            })
78
            ->each(function ($role) {
79
                $this->ensureModelSharesGuard($role);
80
            })
81
            ->all();
82
83
        $this->roles()->saveMany($roles);
84
85
        $this->forgetCachedPermissions();
86
87 3
        return $roles;
88
    }
89 3
90 3
    /**
91 3
     * Revoke the given role from the model.
92 3
     *
93 3
     * @param array|string|Role ...$roles
94
     *
95 3
     * @return array|Role|string
96 3
     */
97
    public function removeRole(...$roles)
98 3
    {
99
        \collect($roles)
100 3
            ->flatten()
101
            ->map(function ($role) {
102
                $role = $this->getStoredRole($role);
103
                $this->roles()->detach($role);
104
105
                return $role;
106
            });
107
108
        $this->forgetCachedPermissions();
109
110 6
        return $roles;
111
    }
112 6
113
    /**
114 6
     * Remove all current roles and set the given ones.
115
     *
116
     * @param array ...$roles
117
     *
118
     * @return array|Role|string
119
     */
120
    public function syncRoles(...$roles)
121
    {
122
        $this->roles()->sync([]);
123
124 48
        return $this->assignRole($roles);
125
    }
126 48
127 3
    /**
128
     * Determine if the model has (one of) the given role(s).
129
     *
130 48
     * @param string|array|Role|\Illuminate\Support\Collection $roles
131 22
     *
132
     * @return bool
133
     */
134 29
    public function hasRole($roles): bool
135 16
    {
136 29
        if (\is_string($roles) && false !== \strpos($roles, '|')) {
137
            $roles = \explode('|', $roles);
138 29
        }
139
140
        if (\is_string($roles) || $roles instanceof Role) {
141
            return $this->roles->contains('name', $roles->name ?? $roles);
0 ignored issues
show
Bug introduced by
The property roles does not exist on Maklad\Permission\Traits\HasRoles. Did you mean roleClass?
Loading history...
Bug introduced by
Accessing name on the interface Maklad\Permission\Contracts\RoleInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
Bug introduced by
The property name does not exist on string.
Loading history...
142
        }
143
144
        $roles = \collect()->make($roles)->map(function ($role) {
145
            return $role instanceof Role ? $role->name : $role;
0 ignored issues
show
Bug introduced by
Accessing name on the interface Maklad\Permission\Contracts\RoleInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
146
        });
147
148 13
        return ! $roles->intersect($this->roles->pluck('name'))->isEmpty();
149
    }
150 13
151
    /**
152
     * Determine if the model has any of the given role(s).
153
     *
154
     * @param string|array|Role|\Illuminate\Support\Collection $roles
155
     *
156
     * @return bool
157
     */
158
    public function hasAnyRole($roles): bool
159
    {
160 7
        return $this->hasRole($roles);
161
    }
162 7
163 4
    /**
164
     * Determine if the model has all of the given role(s).
165
     *
166 7
     * @param string|Role|\Illuminate\Support\Collection $roles
167 2
     *
168
     * @return bool
169
     */
170 6
    public function hasAllRoles($roles): bool
171 6
    {
172 6
        if (\is_string($roles) && false !== strpos($roles, '|')) {
173
            $roles = \explode('|', $roles);
174 6
        }
175
176
        if (\is_string($roles) || $roles instanceof Role) {
177
            return $this->hasRole($roles);
178
        }
179
180
        $roles = \collect()->make($roles)->map(function ($role) {
181
            return $role instanceof Role ? $role->name : $role;
0 ignored issues
show
Bug introduced by
Accessing name on the interface Maklad\Permission\Contracts\RoleInterface suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
182
        });
183
184
        return $roles->intersect($this->roles->pluck('name')) == $roles;
0 ignored issues
show
Bug introduced by
The property roles does not exist on Maklad\Permission\Traits\HasRoles. Did you mean roleClass?
Loading history...
185 55
    }
186
187 55
    /**
188 47
     * Return Role object
189
     *
190
     * @param String|Role $role role name
191 13
     *
192
     * @return Role
193
     * @throws ReflectionException
194
     */
195
    protected function getStoredRole($role): Role
196
    {
197
        if (\is_string($role)) {
198
            return $this->getRoleClass()->findByName($role, $this->getDefaultGuardName());
199 1
        }
200
201 1
        return $role;
202
    }
203
204
    /**
205
     * Return a collection of role names associated with this user.
206
     *
207
     * @return Collection
208
     */
209
    public function getRoleNames(): Collection
210
    {
211 4
        return $this->roles()->pluck('name');
212
    }
213 4
214 3
    /**
215
     * Convert to Role Models
216
     *
217 4
     * @param $roles
218 2
     *
219
     * @return Collection
220
     */
221 4
    private function convertToRoleModels($roles): Collection
222 4
    {
223 4
        if (is_array($roles)) {
224
            $roles = collect($roles);
225 4
        }
226
227
        if (!$roles instanceof Collection) {
228
            $roles = collect([$roles]);
229
        }
230
231
        $roles = $roles->map(function ($role) {
232
            return $this->getStoredRole($role);
233
        });
234
235
        return $roles;
236
    }
237
}
238