Administrable::countAdministrativeRoles()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 17
rs 10
cc 4
nc 4
nop 0
1
<?php
2
3
namespace Itstructure\LaRbac\Traits;
4
5
use Itstructure\LaRbac\Interfaces\RbacUserInterface;
6
use Itstructure\LaRbac\Models\{Role, Permission};
7
8
/**
9
 * Class Administrable
10
 *
11
 * @package Itstructure\LaRbac\Traits
12
 */
13
trait Administrable
14
{
15
    /**
16
     * New filled roles.
17
     *
18
     * @var array
19
     */
20
    private $_roles;
21
22
    /**
23
     * @var int|null
24
     */
25
    private $_countAdministrativeRoles;
26
27
    /**
28
     * User identifier.
29
     * @return mixed
30
     */
31
    public function getMemberKeyAttribute()
32
    {
33
        return $this->attributes[$this->getAuthIdentifierName()];
0 ignored issues
show
Bug introduced by
It seems like getAuthIdentifierName() 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

33
        return $this->attributes[$this->/** @scrutinizer ignore-call */ getAuthIdentifierName()];
Loading history...
34
    }
35
36
    /**
37
     * @return string
38
     */
39
    public function getMemberNameAttribute(): string
40
    {
41
        $userNameAttributeKey = config('rbac.memberNameAttributeKey');
42
43
        if (empty($userNameAttributeKey)) {
44
            return '';
45
        }
46
47
        if (is_string($userNameAttributeKey)) {
48
            return $this->attributes[$userNameAttributeKey];
49
        }
50
51
        if (is_callable($userNameAttributeKey)) {
52
            return $userNameAttributeKey($this);
53
        }
54
55
        return '';
56
    }
57
58
    /**
59
     * Set new filled roles.
60
     * @param $value
61
     * @return void
62
     */
63
    public function setRolesAttribute($value): void
64
    {
65
        $this->_roles = $value;
66
    }
67
68
    /**
69
     * Get user roles by relation.
70
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
71
     */
72
    public function roles()
73
    {
74
        return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id')->withTimestamps();
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

74
        return $this->/** @scrutinizer ignore-call */ belongsToMany(Role::class, 'user_role', 'user_id', 'role_id')->withTimestamps();
Loading history...
75
    }
76
77
    /**
78
     * Checks if User has access to $permissions.
79
     * @param array $permissions
80
     * @return bool
81
     */
82
    public function hasAccess(array $permissions) : bool
83
    {
84
        // check if the permission is available in any role
85
        /* @var Role $role */
86
        foreach ($this->roles()->get() as $role) {
87
88
            if($role->hasAccess($permissions)) {
89
                return true;
90
            }
91
        }
92
        return false;
93
    }
94
95
    /**
96
     * Checks if the user belongs to role.
97
     * @param string $roleSlug
98
     * @return bool
99
     */
100
    public function inRole(string $roleSlug): bool
101
    {
102
        return $this->roles()->where('slug', $roleSlug)->count() == 1;
103
    }
104
105
    /**
106
     * Can assign role checking.
107
     * @param RbacUserInterface $member
108
     * @param Role $role
109
     * @return bool
110
     */
111
    public function canAssignRole(RbacUserInterface $member, Role $role): bool
112
    {
113
        if ($this->countAdministrativeRoles() == 0) {
114
            return false;
115
        }
116
117
        if ($this->getMemberKeyAttribute() != $member->getMemberKeyAttribute()) {
118
            return true;
119
        }
120
121
        if ($this->countAdministrativeRoles() > 1) {
122
            return true;
123
        }
124
125
        if (!$role->hasAccess([Permission::ADMINISTRATE_PERMISSION])) {
126
            return true;
127
        }
128
129
        if ($this->inRole($role->slug)) {
130
            return false;
131
        }
132
133
        return true;
134
    }
135
136
    /**
137
     * Synchronize user roles after save model.
138
     * @param array $options
139
     * @return bool
140
     */
141
    public function save(array $options = [])
142
    {
143
        if (!parent::save($options)) {
144
            return false;
145
        }
146
147
        if (null !== $this->_roles) {
148
            $this->roles()->sync($this->_roles);
149
        }
150
151
        return true;
152
    }
153
154
    /**
155
     * @return int
156
     */
157
    private function countAdministrativeRoles(): int
158
    {
159
        if (null !== $this->_countAdministrativeRoles) {
160
            return $this->_countAdministrativeRoles;
161
        }
162
163
        $this->_countAdministrativeRoles = 0;
164
165
        /* @var Role $role */
166
        foreach ($this->roles()->get() as $role) {
167
168
            if($role->hasAccess([Permission::ADMINISTRATE_PERMISSION])) {
169
                $this->_countAdministrativeRoles += 1;
170
            }
171
        }
172
173
        return $this->_countAdministrativeRoles;
174
    }
175
}
176