Complex classes like DbManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use DbManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
39 | class DbManager extends BaseManager |
||
40 | { |
||
41 | /** |
||
42 | * @var Connection|array|string the DB connection object or the application component ID of the DB connection. |
||
43 | * After the DbManager object is created, if you want to change this property, you should only assign it |
||
44 | * with a DB connection object. |
||
45 | * Starting from version 2.0.2, this can also be a configuration array for creating the object. |
||
46 | */ |
||
47 | public $db = 'db'; |
||
48 | /** |
||
49 | * @var string the name of the table storing authorization items. Defaults to "auth_item". |
||
50 | */ |
||
51 | public $itemTable = '{{%auth_item}}'; |
||
52 | /** |
||
53 | * @var string the name of the table storing authorization item hierarchy. Defaults to "auth_item_child". |
||
54 | */ |
||
55 | public $itemChildTable = '{{%auth_item_child}}'; |
||
56 | /** |
||
57 | * @var string the name of the table storing authorization item assignments. Defaults to "auth_assignment". |
||
58 | */ |
||
59 | public $assignmentTable = '{{%auth_assignment}}'; |
||
60 | /** |
||
61 | * @var string the name of the table storing rules. Defaults to "auth_rule". |
||
62 | */ |
||
63 | public $ruleTable = '{{%auth_rule}}'; |
||
64 | /** |
||
65 | * @var Cache|array|string the cache used to improve RBAC performance. This can be one of the following: |
||
66 | * |
||
67 | * - an application component ID (e.g. `cache`) |
||
68 | * - a configuration array |
||
69 | * - a [[\yii\caching\Cache]] object |
||
70 | * |
||
71 | * When this is not set, it means caching is not enabled. |
||
72 | * |
||
73 | * Note that by enabling RBAC cache, all auth items, rules and auth item parent-child relationships will |
||
74 | * be cached and loaded into memory. This will improve the performance of RBAC permission check. However, |
||
75 | * it does require extra memory and as a result may not be appropriate if your RBAC system contains too many |
||
76 | * auth items. You should seek other RBAC implementations (e.g. RBAC based on Redis storage) in this case. |
||
77 | * |
||
78 | * Also note that if you modify RBAC items, rules or parent-child relationships from outside of this component, |
||
79 | * you have to manually call [[invalidateCache()]] to ensure data consistency. |
||
80 | * |
||
81 | * @since 2.0.3 |
||
82 | */ |
||
83 | public $cache; |
||
84 | /** |
||
85 | * @var string the key used to store RBAC data in cache |
||
86 | * @see cache |
||
87 | * @since 2.0.3 |
||
88 | */ |
||
89 | public $cacheKey = 'rbac'; |
||
90 | |||
91 | /** |
||
92 | * @var Item[] all auth items (name => Item) |
||
93 | */ |
||
94 | protected $items; |
||
95 | /** |
||
96 | * @var Rule[] all auth rules (name => Rule) |
||
97 | */ |
||
98 | protected $rules; |
||
99 | /** |
||
100 | * @var array auth item parent-child relationships (childName => list of parents) |
||
101 | */ |
||
102 | protected $parents; |
||
103 | |||
104 | |||
105 | /** |
||
106 | * Initializes the application component. |
||
107 | * This method overrides the parent implementation by establishing the database connection. |
||
108 | */ |
||
109 | 46 | public function init() |
|
110 | { |
||
111 | 46 | parent::init(); |
|
112 | 46 | $this->db = Instance::ensure($this->db, Connection::className()); |
|
113 | 46 | if ($this->cache !== null) { |
|
114 | $this->cache = Instance::ensure($this->cache, Cache::className()); |
||
115 | } |
||
116 | 46 | } |
|
117 | |||
118 | /** |
||
119 | * @inheritdoc |
||
120 | */ |
||
121 | 2 | public function checkAccess($userId, $permissionName, $params = []) |
|
122 | { |
||
123 | 2 | $assignments = $this->getAssignments($userId); |
|
124 | 2 | $this->loadFromCache(); |
|
125 | 2 | if ($this->items !== null) { |
|
126 | return $this->checkAccessFromCache($userId, $permissionName, $params, $assignments); |
||
127 | } else { |
||
128 | 2 | return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments); |
|
129 | } |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Performs access check for the specified user based on the data loaded from cache. |
||
134 | * This method is internally called by [[checkAccess()]] when [[cache]] is enabled. |
||
135 | * @param string|int $user the user ID. This should can be either an integer or a string representing |
||
136 | * the unique identifier of a user. See [[\yii\web\User::id]]. |
||
137 | * @param string $itemName the name of the operation that need access check |
||
138 | * @param array $params name-value pairs that would be passed to rules associated |
||
139 | * with the tasks and roles assigned to the user. A param with name 'user' is added to this array, |
||
140 | * which holds the value of `$userId`. |
||
141 | * @param Assignment[] $assignments the assignments to the specified user |
||
142 | * @return bool whether the operations can be performed by the user. |
||
143 | * @since 2.0.3 |
||
144 | */ |
||
145 | protected function checkAccessFromCache($user, $itemName, $params, $assignments) |
||
146 | { |
||
147 | if (!isset($this->items[$itemName])) { |
||
148 | return false; |
||
149 | } |
||
150 | |||
151 | $item = $this->items[$itemName]; |
||
152 | |||
153 | Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission: $itemName", __METHOD__); |
||
154 | |||
155 | if (!$this->executeRule($user, $item, $params)) { |
||
156 | return false; |
||
157 | } |
||
158 | |||
159 | if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) { |
||
160 | return true; |
||
161 | } |
||
162 | |||
163 | if (!empty($this->parents[$itemName])) { |
||
164 | foreach ($this->parents[$itemName] as $parent) { |
||
165 | if ($this->checkAccessFromCache($user, $parent, $params, $assignments)) { |
||
166 | return true; |
||
167 | } |
||
168 | } |
||
169 | } |
||
170 | |||
171 | return false; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Performs access check for the specified user. |
||
176 | * This method is internally called by [[checkAccess()]]. |
||
177 | * @param string|int $user the user ID. This should can be either an integer or a string representing |
||
178 | * the unique identifier of a user. See [[\yii\web\User::id]]. |
||
179 | * @param string $itemName the name of the operation that need access check |
||
180 | * @param array $params name-value pairs that would be passed to rules associated |
||
181 | * with the tasks and roles assigned to the user. A param with name 'user' is added to this array, |
||
182 | * which holds the value of `$userId`. |
||
183 | * @param Assignment[] $assignments the assignments to the specified user |
||
184 | * @return bool whether the operations can be performed by the user. |
||
185 | */ |
||
186 | 2 | protected function checkAccessRecursive($user, $itemName, $params, $assignments) |
|
187 | { |
||
188 | 2 | if (($item = $this->getItem($itemName)) === null) { |
|
189 | return false; |
||
190 | } |
||
191 | |||
192 | 2 | Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission: $itemName", __METHOD__); |
|
193 | |||
194 | 2 | if (!$this->executeRule($user, $item, $params)) { |
|
195 | return false; |
||
196 | } |
||
197 | |||
198 | 2 | if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) { |
|
199 | 2 | return true; |
|
200 | } |
||
201 | |||
202 | $query = new Query; |
||
203 | $parents = $query->select(['parent']) |
||
204 | ->from($this->itemChildTable) |
||
205 | ->where(['child' => $itemName]) |
||
206 | ->column($this->db); |
||
207 | foreach ($parents as $parent) { |
||
208 | if ($this->checkAccessRecursive($user, $parent, $params, $assignments)) { |
||
209 | return true; |
||
210 | } |
||
211 | } |
||
212 | |||
213 | return false; |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * @inheritdoc |
||
218 | */ |
||
219 | 2 | protected function getItem($name) |
|
220 | { |
||
221 | 2 | if (empty($name)) { |
|
222 | return null; |
||
223 | } |
||
224 | |||
225 | 2 | if (!empty($this->items[$name])) { |
|
226 | return $this->items[$name]; |
||
227 | } |
||
228 | |||
229 | 2 | $row = (new Query)->from($this->itemTable) |
|
230 | 2 | ->where(['name' => $name]) |
|
231 | 2 | ->one($this->db); |
|
232 | |||
233 | 2 | if ($row === false) { |
|
234 | return null; |
||
235 | } |
||
236 | |||
237 | 2 | return $this->populateItem($row); |
|
238 | } |
||
239 | |||
240 | /** |
||
241 | * Returns a value indicating whether the database supports cascading update and delete. |
||
242 | * The default implementation will return false for SQLite database and true for all other databases. |
||
243 | * @return bool whether the database supports cascading update and delete. |
||
244 | */ |
||
245 | protected function supportsCascadeUpdate() |
||
246 | { |
||
247 | return strncmp($this->db->getDriverName(), 'sqlite', 6) !== 0; |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * @inheritdoc |
||
252 | */ |
||
253 | 40 | protected function addItem($item) |
|
277 | |||
278 | /** |
||
279 | * @inheritdoc |
||
280 | */ |
||
281 | protected function removeItem($item) |
||
282 | { |
||
283 | if (!$this->supportsCascadeUpdate()) { |
||
284 | $this->db->createCommand() |
||
285 | ->delete($this->itemChildTable, ['or', '[[parent]]=:name', '[[child]]=:name'], [':name' => $item->name]) |
||
286 | ->execute(); |
||
287 | $this->db->createCommand() |
||
288 | ->delete($this->assignmentTable, ['item_name' => $item->name]) |
||
289 | ->execute(); |
||
290 | } |
||
291 | |||
292 | $this->db->createCommand() |
||
293 | ->delete($this->itemTable, ['name' => $item->name]) |
||
294 | ->execute(); |
||
295 | |||
296 | $this->invalidateCache(); |
||
297 | |||
298 | return true; |
||
299 | } |
||
300 | |||
301 | /** |
||
302 | * @inheritdoc |
||
303 | */ |
||
304 | protected function updateItem($name, $item) |
||
305 | { |
||
306 | if ($item->name !== $name && !$this->supportsCascadeUpdate()) { |
||
307 | $this->db->createCommand() |
||
308 | ->update($this->itemChildTable, ['parent' => $item->name], ['parent' => $name]) |
||
309 | ->execute(); |
||
310 | $this->db->createCommand() |
||
311 | ->update($this->itemChildTable, ['child' => $item->name], ['child' => $name]) |
||
312 | ->execute(); |
||
313 | $this->db->createCommand() |
||
314 | ->update($this->assignmentTable, ['item_name' => $item->name], ['item_name' => $name]) |
||
315 | ->execute(); |
||
316 | } |
||
317 | |||
318 | $item->updatedAt = time(); |
||
319 | |||
320 | $this->db->createCommand() |
||
321 | ->update($this->itemTable, [ |
||
322 | 'name' => $item->name, |
||
323 | 'description' => $item->description, |
||
324 | 'rule_name' => $item->ruleName, |
||
325 | 'data' => $item->data === null ? null : serialize($item->data), |
||
326 | 'updated_at' => $item->updatedAt, |
||
327 | ], [ |
||
328 | 'name' => $name, |
||
329 | ])->execute(); |
||
330 | |||
331 | $this->invalidateCache(); |
||
332 | |||
333 | return true; |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * @inheritdoc |
||
338 | */ |
||
339 | 40 | protected function addRule($rule) |
|
360 | |||
361 | /** |
||
362 | * @inheritdoc |
||
363 | */ |
||
364 | protected function updateRule($name, $rule) |
||
365 | { |
||
366 | if ($rule->name !== $name && !$this->supportsCascadeUpdate()) { |
||
367 | $this->db->createCommand() |
||
368 | ->update($this->itemTable, ['rule_name' => $rule->name], ['rule_name' => $name]) |
||
369 | ->execute(); |
||
370 | } |
||
371 | |||
372 | $rule->updatedAt = time(); |
||
373 | |||
374 | $this->db->createCommand() |
||
375 | ->update($this->ruleTable, [ |
||
376 | 'name' => $rule->name, |
||
377 | 'data' => serialize($rule), |
||
378 | 'updated_at' => $rule->updatedAt, |
||
379 | ], [ |
||
380 | 'name' => $name, |
||
381 | ])->execute(); |
||
382 | |||
383 | $this->invalidateCache(); |
||
384 | |||
385 | return true; |
||
386 | } |
||
387 | |||
388 | /** |
||
389 | * @inheritdoc |
||
390 | */ |
||
391 | protected function removeRule($rule) |
||
392 | { |
||
393 | if (!$this->supportsCascadeUpdate()) { |
||
394 | $this->db->createCommand() |
||
395 | ->update($this->itemTable, ['rule_name' => null], ['rule_name' => $rule->name]) |
||
396 | ->execute(); |
||
397 | } |
||
398 | |||
399 | $this->db->createCommand() |
||
400 | ->delete($this->ruleTable, ['name' => $rule->name]) |
||
401 | ->execute(); |
||
402 | |||
403 | $this->invalidateCache(); |
||
404 | |||
405 | return true; |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * @inheritdoc |
||
410 | */ |
||
411 | protected function getItems($type) |
||
412 | { |
||
413 | $query = (new Query) |
||
414 | ->from($this->itemTable) |
||
415 | ->where(['type' => $type]); |
||
416 | |||
417 | $items = []; |
||
418 | foreach ($query->all($this->db) as $row) { |
||
419 | $items[$row['name']] = $this->populateItem($row); |
||
420 | } |
||
421 | |||
422 | return $items; |
||
423 | } |
||
424 | |||
425 | /** |
||
426 | * Populates an auth item with the data fetched from database |
||
427 | * @param array $row the data from the auth item table |
||
428 | * @return Item the populated auth item instance (either Role or Permission) |
||
429 | */ |
||
430 | 4 | protected function populateItem($row) |
|
448 | |||
449 | /** |
||
450 | * @inheritdoc |
||
451 | */ |
||
452 | public function getRolesByUser($userId) |
||
453 | { |
||
454 | if (!isset($userId) || $userId === '') { |
||
455 | return []; |
||
456 | } |
||
457 | |||
458 | $query = (new Query)->select('b.*') |
||
459 | ->from(['a' => $this->assignmentTable, 'b' => $this->itemTable]) |
||
460 | ->where('{{a}}.[[item_name]]={{b}}.[[name]]') |
||
461 | ->andWhere(['a.user_id' => (string) $userId]) |
||
462 | ->andWhere(['b.type' => Item::TYPE_ROLE]); |
||
463 | |||
464 | $roles = []; |
||
465 | foreach ($query->all($this->db) as $row) { |
||
466 | $roles[$row['name']] = $this->populateItem($row); |
||
467 | } |
||
468 | return $roles; |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * @inheritdoc |
||
473 | */ |
||
474 | public function getChildRoles($roleName) |
||
475 | { |
||
476 | $role = $this->getRole($roleName); |
||
477 | |||
478 | if (is_null($role)) { |
||
479 | throw new InvalidParamException("Role \"$roleName\" not found."); |
||
480 | } |
||
481 | |||
482 | $result = []; |
||
483 | $this->getChildrenRecursive($roleName, $this->getChildrenList(), $result); |
||
484 | |||
485 | $roles = [$roleName => $role]; |
||
486 | |||
487 | $roles += array_filter($this->getRoles(), function (Role $roleItem) use ($result) { |
||
488 | return array_key_exists($roleItem->name, $result); |
||
489 | }); |
||
490 | |||
491 | return $roles; |
||
492 | } |
||
493 | |||
494 | /** |
||
495 | * @inheritdoc |
||
496 | */ |
||
497 | public function getPermissionsByRole($roleName) |
||
498 | { |
||
499 | $childrenList = $this->getChildrenList(); |
||
500 | $result = []; |
||
501 | $this->getChildrenRecursive($roleName, $childrenList, $result); |
||
502 | if (empty($result)) { |
||
503 | return []; |
||
504 | } |
||
505 | $query = (new Query)->from($this->itemTable)->where([ |
||
506 | 'type' => Item::TYPE_PERMISSION, |
||
507 | 'name' => array_keys($result), |
||
508 | ]); |
||
509 | $permissions = []; |
||
510 | foreach ($query->all($this->db) as $row) { |
||
511 | $permissions[$row['name']] = $this->populateItem($row); |
||
512 | } |
||
513 | return $permissions; |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * @inheritdoc |
||
518 | */ |
||
519 | public function getPermissionsByUser($userId) |
||
520 | { |
||
521 | if (empty($userId)) { |
||
522 | return []; |
||
523 | } |
||
524 | |||
525 | $directPermission = $this->getDirectPermissionsByUser($userId); |
||
526 | $inheritedPermission = $this->getInheritedPermissionsByUser($userId); |
||
527 | |||
528 | return array_merge($directPermission, $inheritedPermission); |
||
529 | } |
||
530 | |||
531 | /** |
||
532 | * Returns all permissions that are directly assigned to user. |
||
533 | * @param string|int $userId the user ID (see [[\yii\web\User::id]]) |
||
534 | * @return Permission[] all direct permissions that the user has. The array is indexed by the permission names. |
||
535 | * @since 2.0.7 |
||
536 | */ |
||
537 | protected function getDirectPermissionsByUser($userId) |
||
538 | { |
||
539 | $query = (new Query)->select('b.*') |
||
540 | ->from(['a' => $this->assignmentTable, 'b' => $this->itemTable]) |
||
541 | ->where('{{a}}.[[item_name]]={{b}}.[[name]]') |
||
542 | ->andWhere(['a.user_id' => (string) $userId]) |
||
543 | ->andWhere(['b.type' => Item::TYPE_PERMISSION]); |
||
544 | |||
545 | $permissions = []; |
||
546 | foreach ($query->all($this->db) as $row) { |
||
547 | $permissions[$row['name']] = $this->populateItem($row); |
||
548 | } |
||
549 | return $permissions; |
||
550 | } |
||
551 | |||
552 | /** |
||
553 | * Returns all permissions that the user inherits from the roles assigned to him. |
||
554 | * @param string|int $userId the user ID (see [[\yii\web\User::id]]) |
||
555 | * @return Permission[] all inherited permissions that the user has. The array is indexed by the permission names. |
||
556 | * @since 2.0.7 |
||
557 | */ |
||
558 | protected function getInheritedPermissionsByUser($userId) |
||
559 | { |
||
560 | $query = (new Query)->select('item_name') |
||
561 | ->from($this->assignmentTable) |
||
562 | ->where(['user_id' => (string) $userId]); |
||
563 | |||
564 | $childrenList = $this->getChildrenList(); |
||
565 | $result = []; |
||
566 | foreach ($query->column($this->db) as $roleName) { |
||
567 | $this->getChildrenRecursive($roleName, $childrenList, $result); |
||
568 | } |
||
569 | |||
570 | if (empty($result)) { |
||
571 | return []; |
||
572 | } |
||
573 | |||
574 | $query = (new Query)->from($this->itemTable)->where([ |
||
575 | 'type' => Item::TYPE_PERMISSION, |
||
576 | 'name' => array_keys($result), |
||
577 | ]); |
||
578 | $permissions = []; |
||
579 | foreach ($query->all($this->db) as $row) { |
||
580 | $permissions[$row['name']] = $this->populateItem($row); |
||
581 | } |
||
582 | return $permissions; |
||
583 | } |
||
584 | |||
585 | /** |
||
586 | * Returns the children for every parent. |
||
587 | * @return array the children list. Each array key is a parent item name, |
||
588 | * and the corresponding array value is a list of child item names. |
||
589 | */ |
||
590 | protected function getChildrenList() |
||
591 | { |
||
592 | $query = (new Query)->from($this->itemChildTable); |
||
593 | $parents = []; |
||
594 | foreach ($query->all($this->db) as $row) { |
||
595 | $parents[$row['parent']][] = $row['child']; |
||
596 | } |
||
597 | return $parents; |
||
598 | } |
||
599 | |||
600 | /** |
||
601 | * Recursively finds all children and grand children of the specified item. |
||
602 | * @param string $name the name of the item whose children are to be looked for. |
||
603 | * @param array $childrenList the child list built via [[getChildrenList()]] |
||
604 | * @param array $result the children and grand children (in array keys) |
||
605 | */ |
||
606 | protected function getChildrenRecursive($name, $childrenList, &$result) |
||
607 | { |
||
608 | if (isset($childrenList[$name])) { |
||
609 | foreach ($childrenList[$name] as $child) { |
||
610 | $result[$child] = true; |
||
611 | $this->getChildrenRecursive($child, $childrenList, $result); |
||
612 | } |
||
613 | } |
||
614 | } |
||
615 | |||
616 | /** |
||
617 | * @inheritdoc |
||
618 | */ |
||
619 | 38 | public function getRule($name) |
|
620 | { |
||
621 | 38 | if ($this->rules !== null) { |
|
622 | return isset($this->rules[$name]) ? $this->rules[$name] : null; |
||
623 | } |
||
624 | |||
625 | 38 | $row = (new Query)->select(['data']) |
|
626 | 38 | ->from($this->ruleTable) |
|
627 | 38 | ->where(['name' => $name]) |
|
628 | 38 | ->one($this->db); |
|
629 | 38 | return $row === false ? null : unserialize($row['data']); |
|
630 | } |
||
631 | |||
632 | /** |
||
633 | * @inheritdoc |
||
634 | */ |
||
635 | public function getRules() |
||
636 | { |
||
637 | if ($this->rules !== null) { |
||
638 | return $this->rules; |
||
639 | } |
||
640 | |||
641 | $query = (new Query)->from($this->ruleTable); |
||
642 | |||
643 | $rules = []; |
||
644 | foreach ($query->all($this->db) as $row) { |
||
645 | $rules[$row['name']] = unserialize($row['data']); |
||
646 | } |
||
647 | |||
648 | return $rules; |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * @inheritdoc |
||
653 | */ |
||
654 | public function getAssignment($roleName, $userId) |
||
674 | |||
675 | /** |
||
676 | * @inheritdoc |
||
677 | */ |
||
678 | 2 | public function getAssignments($userId) |
|
679 | { |
||
680 | 2 | if (empty($userId)) { |
|
681 | return []; |
||
682 | } |
||
683 | |||
684 | 2 | $query = (new Query) |
|
685 | 2 | ->from($this->assignmentTable) |
|
686 | 2 | ->where(['user_id' => (string) $userId]); |
|
687 | |||
688 | 2 | $assignments = []; |
|
689 | 2 | foreach ($query->all($this->db) as $row) { |
|
690 | 2 | $assignments[$row['item_name']] = new Assignment([ |
|
691 | 2 | 'userId' => $row['user_id'], |
|
692 | 2 | 'roleName' => $row['item_name'], |
|
693 | 2 | 'createdAt' => $row['created_at'], |
|
694 | 2 | ]); |
|
695 | 2 | } |
|
696 | |||
697 | 2 | return $assignments; |
|
698 | } |
||
699 | |||
700 | /** |
||
701 | * @inheritdoc |
||
702 | * @since 2.0.8 |
||
703 | */ |
||
704 | public function canAddChild($parent, $child) |
||
705 | { |
||
706 | return !$this->detectLoop($parent, $child); |
||
707 | } |
||
708 | |||
709 | /** |
||
710 | * @inheritdoc |
||
711 | */ |
||
712 | 2 | public function addChild($parent, $child) |
|
734 | |||
735 | /** |
||
736 | * @inheritdoc |
||
737 | */ |
||
738 | public function removeChild($parent, $child) |
||
748 | |||
749 | /** |
||
750 | * @inheritdoc |
||
751 | */ |
||
752 | public function removeChildren($parent) |
||
762 | |||
763 | /** |
||
764 | * @inheritdoc |
||
765 | */ |
||
766 | public function hasChild($parent, $child) |
||
773 | |||
774 | /** |
||
775 | * @inheritdoc |
||
776 | */ |
||
777 | 2 | public function getChildren($name) |
|
791 | |||
792 | /** |
||
793 | * Checks whether there is a loop in the authorization item hierarchy. |
||
794 | * @param Item $parent the parent item |
||
795 | * @param Item $child the child item to be added to the hierarchy |
||
796 | * @return bool whether a loop exists |
||
797 | */ |
||
798 | 2 | protected function detectLoop($parent, $child) |
|
799 | { |
||
800 | 2 | if ($child->name === $parent->name) { |
|
801 | return true; |
||
802 | } |
||
803 | 2 | foreach ($this->getChildren($child->name) as $grandchild) { |
|
804 | if ($this->detectLoop($parent, $grandchild)) { |
||
805 | return true; |
||
806 | } |
||
807 | 2 | } |
|
808 | 2 | return false; |
|
809 | } |
||
810 | |||
811 | /** |
||
812 | * @inheritdoc |
||
813 | */ |
||
814 | 2 | public function assign($role, $userId) |
|
831 | |||
832 | /** |
||
833 | * @inheritdoc |
||
834 | */ |
||
835 | public function revoke($role, $userId) |
||
845 | |||
846 | /** |
||
847 | * @inheritdoc |
||
848 | */ |
||
849 | public function revokeAll($userId) |
||
859 | |||
860 | /** |
||
861 | * @inheritdoc |
||
862 | */ |
||
863 | 46 | public function removeAll() |
|
871 | |||
872 | /** |
||
873 | * @inheritdoc |
||
874 | */ |
||
875 | public function removeAllPermissions() |
||
876 | { |
||
877 | $this->removeAllItems(Item::TYPE_PERMISSION); |
||
878 | } |
||
879 | |||
880 | /** |
||
881 | * @inheritdoc |
||
882 | */ |
||
883 | public function removeAllRoles() |
||
884 | { |
||
885 | $this->removeAllItems(Item::TYPE_ROLE); |
||
886 | } |
||
887 | |||
888 | /** |
||
889 | * Removes all auth items of the specified type. |
||
890 | * @param int $type the auth item type (either Item::TYPE_PERMISSION or Item::TYPE_ROLE) |
||
891 | */ |
||
892 | protected function removeAllItems($type) |
||
893 | { |
||
894 | if (!$this->supportsCascadeUpdate()) { |
||
895 | $names = (new Query) |
||
896 | ->select(['name']) |
||
897 | ->from($this->itemTable) |
||
898 | ->where(['type' => $type]) |
||
899 | ->column($this->db); |
||
900 | if (empty($names)) { |
||
901 | return; |
||
902 | } |
||
903 | $key = $type == Item::TYPE_PERMISSION ? 'child' : 'parent'; |
||
904 | $this->db->createCommand() |
||
905 | ->delete($this->itemChildTable, [$key => $names]) |
||
906 | ->execute(); |
||
907 | $this->db->createCommand() |
||
908 | ->delete($this->assignmentTable, ['item_name' => $names]) |
||
909 | ->execute(); |
||
910 | } |
||
911 | $this->db->createCommand() |
||
912 | ->delete($this->itemTable, ['type' => $type]) |
||
913 | ->execute(); |
||
914 | |||
915 | $this->invalidateCache(); |
||
916 | } |
||
917 | |||
918 | /** |
||
919 | * @inheritdoc |
||
920 | */ |
||
921 | public function removeAllRules() |
||
922 | { |
||
923 | if (!$this->supportsCascadeUpdate()) { |
||
924 | $this->db->createCommand() |
||
925 | ->update($this->itemTable, ['rule_name' => null]) |
||
926 | ->execute(); |
||
927 | } |
||
928 | |||
929 | $this->db->createCommand()->delete($this->ruleTable)->execute(); |
||
930 | |||
931 | $this->invalidateCache(); |
||
932 | } |
||
933 | |||
934 | /** |
||
935 | * @inheritdoc |
||
936 | */ |
||
937 | 46 | public function removeAllAssignments() |
|
941 | |||
942 | 46 | public function invalidateCache() |
|
943 | { |
||
944 | 46 | if ($this->cache !== null) { |
|
945 | $this->cache->delete($this->cacheKey); |
||
951 | |||
952 | 2 | public function loadFromCache() |
|
986 | |||
987 | /** |
||
988 | * Returns all role assignment information for the specified role. |
||
989 | * @param string $roleName |
||
990 | * @return Assignment[] the assignments. An empty array will be |
||
991 | * returned if role is not assigned to any user. |
||
992 | * @since 2.0.7 |
||
993 | */ |
||
994 | public function getUserIdsByRole($roleName) |
||
995 | { |
||
996 | if (empty($roleName)) { |
||
997 | return []; |
||
998 | } |
||
999 | |||
1000 | return (new Query)->select('[[user_id]]') |
||
1001 | ->from($this->assignmentTable) |
||
1002 | ->where(['item_name' => $roleName])->column($this->db); |
||
1003 | } |
||
1004 | } |
||
1005 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..