HasRoleAndPermission::allowed()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.2
c 0
b 0
f 0
cc 4
eloc 6
nc 3
nop 4
1
<?php
2
3
namespace Ultraware\Roles\Traits;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Collection;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
9
use Illuminate\Support\Str;
10
use InvalidArgumentException;
11
use Ultraware\Roles\Models\Permission;
12
use Ultraware\Roles\Models\Role;
13
14
trait HasRoleAndPermission
15
{
16
    /**
17
     * Property for caching roles.
18
     *
19
     * @var Collection|null
20
     */
21
    protected $roles;
22
23
    /**
24
     * Property for caching permissions.
25
     *
26
     * @var Collection|null
27
     */
28
    protected $permissions;
29
30
    /**
31
     * User belongs to many roles.
32
     *
33
     * @return BelongsToMany
34
     */
35
    public function roles()
36
    {
37
        return $this->belongsToMany(config('roles.models.role'))->withTimestamps();
38
    }
39
40
    /**
41
     * Get all roles as collection.
42
     *
43
     * @return Collection
44
     */
45
    public function getRoles()
46
    {
47
        return (!$this->roles) ? $this->roles = $this->roles()->get() : $this->roles;
48
    }
49
50
    /**
51
     * Check if the user has a role or roles.
52
     *
53
     * @param int|string|array $role
54
     * @param bool $all
55
     * @return bool
56
     */
57
    public function hasRole($role, $all = false)
58
    {
59
        if ($this->isPretendEnabled()) {
60
            return $this->pretend('hasRole');
61
        }
62
63
        if (!$all) {
64
            return $this->hasOneRole($role);
65
        }
66
67
        return $this->hasAllRoles($role);
68
    }
69
70
    /**
71
     * Check if the user has at least one of the given roles.
72
     *
73
     * @param int|string|array $role
74
     * @return bool
75
     */
76
    public function hasOneRole($role)
77
    {
78
        foreach ($this->getArrayFrom($role) as $role) {
79
            if ($this->checkRole($role)) {
80
                return true;
81
            }
82
        }
83
84
        return false;
85
    }
86
87
    /**
88
     * Check if the user has all roles.
89
     *
90
     * @param int|string|array $role
91
     * @return bool
92
     */
93
    public function hasAllRoles($role)
94
    {
95
        foreach ($this->getArrayFrom($role) as $role) {
96
            if (!$this->checkRole($role)) {
97
                return false;
98
            }
99
        }
100
101
        return true;
102
    }
103
104
    /**
105
     * Check if the user has role.
106
     *
107
     * @param int|string $role
108
     * @return bool
109
     */
110
    public function checkRole($role)
111
    {
112
        return $this->getRoles()->contains(function ($value) use ($role) {
113
            return $role == $value->id || Str::is($role, $value->slug);
114
        });
115
    }
116
117
    /**
118
     * Attach role to a user.
119
     *
120
     * @param int|Role $role
121
     * @return null|bool
122
     */
123
    public function attachRole($role)
124
    {
125
        if ($this->getRoles()->contains($role)) {
126
            return true;
127
        }
128
        $this->roles = null;
129
        return $this->roles()->attach($role);
130
    }
131
132
    /**
133
     * Detach role from a user.
134
     *
135
     * @param int|Role $role
136
     * @return int
137
     */
138
    public function detachRole($role)
139
    {
140
        $this->roles = null;
141
142
        return $this->roles()->detach($role);
143
    }
144
145
    /**
146
     * Detach all roles from a user.
147
     *
148
     * @return int
149
     */
150
    public function detachAllRoles()
151
    {
152
        $this->roles = null;
153
154
        return $this->roles()->detach();
155
    }
156
157
    /**
158
     * Sync roles for a user.
159
     *
160
     * @param array|\Ultraware\Roles\Models\Role[]|\Illuminate\Database\Eloquent\Collection $roles
161
     * @return array
162
     */
163
    public function syncRoles($roles)
164
    {
165
        $this->roles = null;
166
167
        return $this->roles()->sync($roles);
168
    }
169
170
    /**
171
     * Get role level of a user.
172
     *
173
     * @return int
174
     */
175
    public function level()
176
    {
177
        return ($role = $this->getRoles()->sortByDesc('level')->first()) ? $role->level : 0;
178
    }
179
180
    /**
181
     * Get all permissions from roles.
182
     *
183
     * @return Builder
184
     */
185
    public function rolePermissions()
186
    {
187
        $permissionModel = app(config('roles.models.permission'));
188
189
        if (!$permissionModel instanceof Model) {
190
            throw new InvalidArgumentException('[roles.models.permission] must be an instance of \Illuminate\Database\Eloquent\Model');
191
        }
192
193
        return $permissionModel
194
            ::select(['permissions.*', 'permission_role.created_at as pivot_created_at', 'permission_role.updated_at as pivot_updated_at'])
195
            ->join('permission_role', 'permission_role.permission_id', '=', 'permissions.id')
196
            ->join('roles', 'roles.id', '=', 'permission_role.role_id')
197
            ->whereIn('roles.id', $this->getRoles()->pluck('id')->toArray())
198
            ->orWhere('roles.level', '<', $this->level())
199
            ->groupBy(['permissions.id', 'permissions.name', 'permissions.slug', 'permissions.description', 'permissions.model', 'permissions.created_at', 'permissions.updated_at', 'pivot_created_at', 'pivot_updated_at']);
200
    }
201
202
    /**
203
     * User belongs to many permissions.
204
     *
205
     * @return BelongsToMany
206
     */
207
    public function userPermissions()
208
    {
209
        return $this->belongsToMany(config('roles.models.permission'))->withTimestamps();
210
    }
211
212
    /**
213
     * Get all permissions as collection.
214
     *
215
     * @return Collection
216
     */
217
    public function getPermissions()
218
    {
219
        return (!$this->permissions) ? $this->permissions = $this->rolePermissions()->get()->merge($this->userPermissions()->get()) : $this->permissions;
220
    }
221
222
    /**
223
     * Check if the user has a permission or permissions.
224
     *
225
     * @param int|string|array $permission
226
     * @param bool $all
227
     * @return bool
228
     */
229
    public function hasPermission($permission, $all = false)
230
    {
231
        if ($this->isPretendEnabled()) {
232
            return $this->pretend('hasPermission');
233
        }
234
235
        if (!$all) {
236
            return $this->hasOnePermission($permission);
237
        }
238
239
        return $this->hasAllPermissions($permission);
240
    }
241
242
    /**
243
     * Check if the user has at least one of the given permissions.
244
     *
245
     * @param int|string|array $permission
246
     * @return bool
247
     */
248
    public function hasOnePermission($permission)
249
    {
250
        foreach ($this->getArrayFrom($permission) as $permission) {
251
            if ($this->checkPermission($permission)) {
252
                return true;
253
            }
254
        }
255
256
        return false;
257
    }
258
259
    /**
260
     * Check if the user has all permissions.
261
     *
262
     * @param int|string|array $permission
263
     * @return bool
264
     */
265
    public function hasAllPermissions($permission)
266
    {
267
        foreach ($this->getArrayFrom($permission) as $permission) {
268
            if (!$this->checkPermission($permission)) {
269
                return false;
270
            }
271
        }
272
273
        return true;
274
    }
275
276
    /**
277
     * Check if the user has a permission.
278
     *
279
     * @param int|string $permission
280
     * @return bool
281
     */
282
    public function checkPermission($permission)
283
    {
284
        return $this->getPermissions()->contains(function ($value) use ($permission) {
285
            return $permission == $value->id || Str::is($permission, $value->slug);
286
        });
287
    }
288
289
    /**
290
     * Check if the user is allowed to manipulate with entity.
291
     *
292
     * @param string $providedPermission
293
     * @param Model $entity
294
     * @param bool $owner
295
     * @param string $ownerColumn
296
     * @return bool
297
     */
298
    public function allowed($providedPermission, Model $entity, $owner = true, $ownerColumn = 'user_id')
299
    {
300
        if ($this->isPretendEnabled()) {
301
            return $this->pretend('allowed');
302
        }
303
304
        if ($owner === true && $entity->{$ownerColumn} == $this->id) {
305
            return true;
306
        }
307
308
        return $this->isAllowed($providedPermission, $entity);
309
    }
310
311
    /**
312
     * Check if the user is allowed to manipulate with provided entity.
313
     *
314
     * @param string $providedPermission
315
     * @param Model $entity
316
     * @return bool
317
     */
318
    protected function isAllowed($providedPermission, Model $entity)
319
    {
320
        foreach ($this->getPermissions() as $permission) {
321
            if ($permission->model != '' && get_class($entity) == $permission->model
322
                && ($permission->id == $providedPermission || $permission->slug === $providedPermission)
323
            ) {
324
                return true;
325
            }
326
        }
327
328
        return false;
329
    }
330
331
    /**
332
     * Attach permission to a user.
333
     *
334
     * @param int|Permission $permission
335
     * @return null|bool
336
     */
337
    public function attachPermission($permission)
338
    {
339
        if ($this->getPermissions()->contains($permission)) {
340
            return true;
341
        }
342
        $this->permissions = null;
343
        return $this->userPermissions()->attach($permission);
344
    }
345
346
    /**
347
     * Detach permission from a user.
348
     *
349
     * @param int|Permission $permission
350
     * @return int
351
     */
352
    public function detachPermission($permission)
353
    {
354
        $this->permissions = null;
355
356
        return $this->userPermissions()->detach($permission);
357
    }
358
359
    /**
360
     * Detach all permissions from a user.
361
     *
362
     * @return int
363
     */
364
    public function detachAllPermissions()
365
    {
366
        $this->permissions = null;
367
368
        return $this->userPermissions()->detach();
369
    }
370
371
    /**
372
     * Sync permissions for a user.
373
     *
374
     * @param array|\Ultraware\Roles\Models\Permission[]|\Illuminate\Database\Eloquent\Collection $permissions
375
     * @return array
376
     */
377
    public function syncPermissions($permissions)
378
    {
379
        $this->permissions = null;
380
381
        return $this->userPermissions()->sync($permissions);
382
    }
383
384
    /**
385
     * Check if pretend option is enabled.
386
     *
387
     * @return bool
388
     */
389
    private function isPretendEnabled()
390
    {
391
        return (bool) config('roles.pretend.enabled');
392
    }
393
394
    /**
395
     * Allows to pretend or simulate package behavior.
396
     *
397
     * @param string $option
398
     * @return bool
399
     */
400
    private function pretend($option)
401
    {
402
        return (bool) config('roles.pretend.options.' . $option);
403
    }
404
405
    /**
406
     * Get an array from argument.
407
     *
408
     * @param int|string|array $argument
409
     * @return array
410
     */
411
    private function getArrayFrom($argument)
412
    {
413
        return (!is_array($argument)) ? preg_split('/ ?[,|] ?/', $argument) : $argument;
414
    }
415
416
    public function callMagic($method, $parameters)
417
    {
418
        if (starts_with($method, 'is')) {
419
            return $this->hasRole(snake_case(substr($method, 2), config('roles.separator')));
420
        } elseif (starts_with($method, 'can')) {
421
            return $this->hasPermission(snake_case(substr($method, 3), config('roles.separator')));
422
        } elseif (starts_with($method, 'allowed')) {
423
            return $this->allowed(snake_case(substr($method, 7), config('roles.separator')), $parameters[0], (isset($parameters[1])) ? $parameters[1] : true, (isset($parameters[2])) ? $parameters[2] : 'user_id');
424
        }
425
426
        return parent::__call($method, $parameters);
427
    }
428
429
    public function __call($method, $parameters)
430
    {
431
        return $this->callMagic($method, $parameters);
432
    }
433
}
434