Passed
Push — master ( da6314...127f02 )
by Lee
04:23 queued 11s
created

RoleManager::loadOrStormRoles()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
declare(strict_types=1);
4
5
namespace Casbin\Rbac\DefaultRoleManager;
6
7
use Casbin\Exceptions\CasbinException;
8
use Casbin\Rbac\Role;
9
use Casbin\Rbac\RoleManager as RoleManagerContract;
10
use Casbin\Log\Log;
11
use Casbin\Rbac\Roles;
12
use Closure;
13
14
/**
15
 * Class RoleManager.
16
 * provides a default implementation for the RoleManager interface.
17
 *
18
 * @author [email protected]
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
19
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
20
class RoleManager implements RoleManagerContract
21
{
22
    const DEFAULTDOMAIN = 'casbin::default';
23
24
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
25
     * @var array
26
     */
27
    protected $allDomains;
28
29
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
30
     * @var int
31
     */
32
    protected $maxHierarchyLevel;
33
34
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
35
     * @var bool
36
     */
37
    protected $hasPattern;
38
39
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
40
     * @var Closure
41
     */
42
    protected $matchingFunc;
43
44
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
45
     * @var bool
46
     */
47
    protected $hasDomainPattern;
48
49
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
50
     * @var Closure
51
     */
52
    protected $domainMatchingFunc;
53
54
    /**
55
     * RoleManager constructor.
56
     *
57
     * @param int $maxHierarchyLevel
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
58
     */
59 195
    public function __construct(int $maxHierarchyLevel)
60
    {
61 195
        $this->allDomains[self::DEFAULTDOMAIN] = new Roles();
62 195
        $this->maxHierarchyLevel = $maxHierarchyLevel;
63 195
        $this->hasPattern = false;
64 195
        $this->hasDomainPattern = false;
65 195
    }
66
67
    /**
68
     * support use pattern in g.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
69
     *
70
     * @param string  $name
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
71
     * @param Closure $fn
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
72
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
73 12
    public function addMatchingFunc(string $name, Closure $fn): void
74
    {
75 12
        $this->hasPattern = true;
76 12
        $this->matchingFunc = $fn;
77 12
    }
78
79
    /**
80
     * support use domain pattern in g.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
81
     *
82
     * @param string  $name
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
83
     * @param Closure $fn
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
84
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
85 12
    public function addDomainMatchingFunc(string $name, Closure $fn): void
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed. ( Ignorable by Annotation )

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

85
    public function addDomainMatchingFunc(/** @scrutinizer ignore-unused */ string $name, Closure $fn): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
    {
87 12
        $this->hasDomainPattern = true;
88 12
        $this->domainMatchingFunc = $fn;
89 12
    }
90
91
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
92
     * @param string $domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
93
     *
94
     * @return Roles
95
     */
96 18
    protected function generateTempRoles(string $domain): Roles
97
    {
98 18
        $this->loadOrStormRoles($domain);
99
100 18
        $patternDomain = [$domain];
101
102 18
        if ($this->hasDomainPattern) {
103 12
            foreach ($this->allDomains as $key => $allDomain) {
104 12
                $fu = $this->domainMatchingFunc;
105 12
                if ($fu($domain, (string) $key)) {
106 12
                    $patternDomain = array_merge($patternDomain, [$key]);
107 12
                    $patternDomain[] = $key;
108
                }
109
            }
110
        }
111
112 18
        $allRoles = new Roles();
113
114 18
        foreach ($patternDomain as $domain) {
115 18
            $values = $this->loadOrStormRoles($domain);
116 18
            foreach ($values->roles as $key => $value) {
117
                /** @var Role $role2 */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
118 18
                $role2 = $value;
119 18
                $role1 = $allRoles->createRole($role2->name, $this->matchingFunc);
120 18
                foreach ($role2->getRoles() as $v) {
121 18
                    $role3 = $allRoles->createRole($v, $this->matchingFunc);
122 18
                    $role1->addRole($role3);
123
                }
124
            }
125
        }
126
127 18
        return $allRoles;
128
    }
129
130
    /**
131
     * clears all stored data and resets the role manager to the initial state.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
132
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
133 171
    public function clear(): void
134
    {
135 171
        $this->allDomains = [];
136 171
        $this->allDomains[self::DEFAULTDOMAIN] = new Roles();
137 171
    }
138
139
    /**
140
     * adds the inheritance link between role: name1 and role: name2.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
141
     * aka role: name1 inherits role: name2.
142
     * domain is a prefix to the roles.
143
     *
144
     * @param string $name1
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
145
     * @param string $name2
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
146
     * @param string ...$domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
147
     *
148
     * @throws CasbinException
149
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
150 105
    public function addLink(string $name1, string $name2, string ...$domain): void
151
    {
152 105
        $domain = $this->checkDomainLength($domain);
153 105
        $allRoles = $this->loadOrStormRoles($domain[0]);
154 105
        $role1 = $this->loadOrStormRole($allRoles, $name1);
155 105
        $role2 = $this->loadOrStormRole($allRoles, $name2);
156 105
        $role1->addRole($role2);
157 105
    }
158
159
    /**
160
     * deletes the inheritance link between role: name1 and role: name2.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
161
     * aka role: name1 does not inherit role: name2 any more.
162
     * domain is a prefix to the roles.
163
     *
164
     * @param string $name1
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
165
     * @param string $name2
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
166
     * @param string ...$domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
167
     *
168
     * @throws CasbinException
169
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
170 3
    public function deleteLink(string $name1, string $name2, string ...$domain): void
171
    {
172 3
        $domain = $this->checkDomainLength($domain);
173 3
        $allRoles = $this->loadOrStormRoles($domain[0]);
174
175 3
        if (!isset($allRoles->roles[$name1]) || !isset($allRoles->roles[$name2])) {
176 3
            throw new CasbinException('error: name1 or name2 does not exist');
177
        }
178
179 3
        $role1 = $this->loadOrStormRole($allRoles, $name1);
180 3
        $role2 = $this->loadOrStormRole($allRoles, $name2);
181 3
        $role1->deleteRole($role2);
182 3
    }
183
184
    /**
185
     * determines whether role: name1 inherits role: name2.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
186
     * domain is a prefix to the roles.
187
     *
188
     * @param string $name1
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
189
     * @param string $name2
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
190
     * @param string ...$domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
191
     *
192
     * @return bool
193
     *
194
     * @throws CasbinException
195
     */
196 54
    public function hasLink(string $name1, string $name2, string ...$domain): bool
197
    {
198 54
        $domain = $this->checkDomainLength($domain);
199
200 54
        if ($name1 == $name2) {
201 33
            return true;
202
        }
203
204 51
        $allRoles = $this->checkHasDomainPatternOrHasPattern($domain[0]);
205
206 51
        if (!$allRoles->hasRole($name1, $this->matchingFunc) || !$allRoles->hasRole($name2, $this->matchingFunc)) {
207 30
            return false;
208
        }
209
210 48
        $role1 = $allRoles->createRole($name1, $this->matchingFunc);
211
212 48
        return $role1->hasRole($name2, $this->maxHierarchyLevel);
213
    }
214
215
    /**
216
     * gets the roles that a subject inherits.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
217
     * domain is a prefix to the roles.
218
     *
219
     * @param string $name
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
220
     * @param string ...$domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
221
     *
222
     * @return array
223
     *
224
     * @throws CasbinException
225
     */
226 33
    public function getRoles(string $name, string ...$domain): array
227
    {
228 33
        $domain = $this->checkDomainLength($domain);
229 33
        $allRoles = $this->checkHasDomainPatternOrHasPattern($domain[0]);
230
231 33
        if (!$allRoles->hasRole($name, $this->matchingFunc)) {
232 21
            return [];
233
        }
234 27
        $roles = $allRoles->createRole($name, $this->matchingFunc)->getRoles();
235
236 27
        return $roles;
237
    }
238
239
    /**
240
     * gets the users that inherits a subject.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
241
     * domain is an unreferenced parameter here, may be used in other implementations.
242
     *
243
     * @param string $name
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
244
     * @param string ...$domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
245
     *
246
     * @return array
247
     *
248
     * @throws CasbinException
249
     */
250 9
    public function getUsers(string $name, string ...$domain): array
251
    {
252 9
        $domain = $this->checkDomainLength($domain);
253 9
        $allRoles = $this->checkHasDomainPatternOrHasPattern($domain[0]);
254
255 9
        if (!$allRoles->hasRole($name, $this->domainMatchingFunc)) {
256
            // throw new CasbinException('error: name does not exist');
257 3
            return [];
258
        }
259
260 9
        $names = [];
261
        /** @var Role $allRole */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
262 9
        foreach ($allRoles->roles as $allRole) {
263 9
            if ($allRole->hasDirectRole($name)) {
264 9
                $names[] = $allRole->name;
265
            }
266
        }
267
268 9
        return $names;
269
    }
270
271
    /**
272
     * prints all the roles to log.
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
273
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
274 90
    public function printRoles(): void
275
    {
276 90
        $line = [];
277
278
        array_map(function ($roles) use (&$line) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
279
            array_map(function ($role) use (&$line) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
280 87
                if ($text = $role->toString()) {
281 87
                    $line[] = $text;
282
                }
283 90
            }, $roles->roles);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
284 90
        }, $this->allDomains);
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
285
286 90
        Log::logPrint(implode(', ', $line));
287 90
    }
288
289
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
290
     * @param array $domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
291
     *
292
     * @return array|string[]
293
     *
294
     * @throws CasbinException
295
     */
296 108
    protected function checkDomainLength(array $domain): array
297
    {
298 108
        if (0 === count($domain)) {
299 81
            $domain = [self::DEFAULTDOMAIN];
300 33
        } elseif (count($domain) > 1) {
301
            throw new CasbinException('error: domain should be 1 parameter');
302
        }
303
304 108
        return $domain;
305
    }
306
307
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
308
     * @param string $domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
309
     *
310
     * @return Roles
311
     */
312 105
    protected function loadOrStormRoles(string $domain): Roles
313
    {
314 105
        if (!isset($this->allDomains[$domain])) {
315 33
            $this->allDomains[$domain] = new Roles();
316
        }
317
318 105
        return $this->allDomains[$domain];
319
    }
320
321
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
322
     * @param Roles  $allRoles
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
323
     * @param string $name
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
324
     *
325
     * @return Role
326
     */
327 105
    protected function loadOrStormRole(Roles $allRoles, string $name): Role
328
    {
329 105
        if (!isset($allRoles->roles[$name])) {
330 105
            $allRoles->roles[$name] = new Role($name);
331
        }
332
333 105
        return $allRoles->roles[$name];
334
    }
335
336
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
337
     * @param $domain
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
338
     *
339
     * @return Roles
340
     */
341 90
    protected function checkHasDomainPatternOrHasPattern($domain): Roles
342
    {
343 90
        if ($this->hasDomainPattern || $this->hasPattern) {
344 18
            $allRoles = $this->generateTempRoles($domain);
345
        } else {
346 75
            $allRoles = $this->loadOrStormRoles($domain);
347
        }
348
349 90
        return $allRoles;
350
    }
351
}
352