1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Charcoal\User\Acl; |
4
|
|
|
|
5
|
|
|
// Dependency from 'charcoal-core' |
6
|
|
|
use Charcoal\Model\AbstractModel; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* ACL Roles define hierarchical allowed and denied permissions. |
10
|
|
|
* |
11
|
|
|
* They can be attached to user accounts for fine-grained permission control. |
12
|
|
|
*/ |
13
|
|
|
class Role extends AbstractModel |
14
|
|
|
{ |
15
|
|
|
const SEPARATOR = ','; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @var string $ident |
19
|
|
|
*/ |
20
|
|
|
public $ident; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* The parent ACL role. |
24
|
|
|
* |
25
|
|
|
* This role will inherit all of its parent's permissions. |
26
|
|
|
* |
27
|
|
|
* @var string $parent |
28
|
|
|
*/ |
29
|
|
|
public $parent; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* List of explicitely allowed permissions. |
33
|
|
|
* |
34
|
|
|
* @var string[]|null $allowed |
35
|
|
|
*/ |
36
|
|
|
public $allowed; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* List of explicitely denied permissions. |
40
|
|
|
* |
41
|
|
|
* @var string[]|null $denied |
42
|
|
|
*/ |
43
|
|
|
public $denied; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var boolean |
47
|
|
|
*/ |
48
|
|
|
private $superuser; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var integer |
52
|
|
|
*/ |
53
|
|
|
private $position; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* ACL Role can be used as a string (ident). |
57
|
|
|
* |
58
|
|
|
* @return string |
59
|
|
|
*/ |
60
|
|
|
public function __toString() |
61
|
|
|
{ |
62
|
|
|
return (string)$this->ident; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @param string $parent Role's parent. |
67
|
|
|
* @return AclRole Chainable |
68
|
|
|
*/ |
69
|
|
|
public function setParent($parent) |
70
|
|
|
{ |
71
|
|
|
$this->parent = (string)$parent; |
72
|
|
|
return $this; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @return string |
77
|
|
|
*/ |
78
|
|
|
public function parent() |
79
|
|
|
{ |
80
|
|
|
return $this->parent; |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* @param string[]|string|null $allowed The allowed permissions for this role. |
85
|
|
|
* @throws InvalidArgumentException If the passed arguments is not an array, null, or a comma-separated string. |
86
|
|
|
* @return AclRole Chainable |
87
|
|
|
*/ |
88
|
|
View Code Duplication |
public function setAllowed($allowed) |
|
|
|
|
89
|
|
|
{ |
90
|
|
|
if ($allowed === null) { |
91
|
|
|
$this->allowed = null; |
92
|
|
|
return $this; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
if (is_string($allowed)) { |
96
|
|
|
$allowed = explode(self::SEPARATOR, $allowed); |
97
|
|
|
$allowed = array_walk('trim', $allowed); |
|
|
|
|
98
|
|
|
} |
99
|
|
|
if (!is_array($allowed)) { |
100
|
|
|
throw new InvalidArgumentException( |
101
|
|
|
'Invalid allowed value. Must be an array, null, or a comma-separated string.' |
102
|
|
|
); |
103
|
|
|
} |
104
|
|
|
$this->allowed = $allowed; |
105
|
|
|
return $this; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @return string[]|null |
110
|
|
|
*/ |
111
|
|
|
public function allowed() |
112
|
|
|
{ |
113
|
|
|
return $this->allowed(); |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @param string[]|string|null $denied The denied permissions for this role. |
118
|
|
|
* @throws InvalidArgumentException If the passed arguments is not an array, null, or a comma-separated string. |
119
|
|
|
* @return AclRole Chainable |
120
|
|
|
*/ |
121
|
|
View Code Duplication |
public function setDenied($denied) |
|
|
|
|
122
|
|
|
{ |
123
|
|
|
if ($denied === null) { |
124
|
|
|
$this->denied = null; |
125
|
|
|
return $this; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
if (is_string($denied)) { |
129
|
|
|
$denied = explode(self::SEPARATOR, $denied); |
130
|
|
|
$denied = array_walk('trim', $denied); |
|
|
|
|
131
|
|
|
} |
132
|
|
|
if (!is_array($denied)) { |
133
|
|
|
throw new InvalidArgumentException( |
134
|
|
|
'Invalid denied value. Must be an array, null, or a comma-separated string.' |
135
|
|
|
); |
136
|
|
|
} |
137
|
|
|
$this->denied = $denied; |
138
|
|
|
return $this; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* @return string[]|null |
143
|
|
|
*/ |
144
|
|
|
public function denied() |
145
|
|
|
{ |
146
|
|
|
return $this->denied(); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* @param boolean $isSuper The superuser flag. |
151
|
|
|
* @return AclRole Chainable |
152
|
|
|
*/ |
153
|
|
|
public function setSuperuser($isSuper) |
154
|
|
|
{ |
155
|
|
|
$this->superuser = !!$isSuper; |
156
|
|
|
return $this; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* @return boolean |
161
|
|
|
*/ |
162
|
|
|
public function superuser() |
163
|
|
|
{ |
164
|
|
|
return $this->superuser; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @param integer $position The role's ordering position. |
169
|
|
|
* @return AclRole Chainable |
170
|
|
|
*/ |
171
|
|
|
public function setPosition($position) |
172
|
|
|
{ |
173
|
|
|
$this->position = (int)$position; |
174
|
|
|
return $this; |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @return integer |
179
|
|
|
*/ |
180
|
|
|
public function position() |
181
|
|
|
{ |
182
|
|
|
return $this->position; |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.