Class yii\mongodb\rbac\MongoDbManager

Inheritanceyii\mongodb\rbac\MongoDbManager » yii\rbac\BaseManager
Available since extension's version2.0.5
Source Code https://github.com/yiisoft/yii2-mongodb/blob/master/rbac/MongoDbManager.php

MongoDbManager represents an authorization manager that stores authorization information in MongoDB.

Manager uses 3 collections for the RBAC data storage:

These collection are better to be pre-created with search fields indexed.

Public Properties

Hide inherited properties

Property Type Description Defined By
$assignmentCollection string|array The name of the collection storing authorization item assignments. yii\mongodb\rbac\MongoDbManager
$cache \yii\caching\Cache|array|string The cache used to improve RBAC performance. yii\mongodb\rbac\MongoDbManager
$cacheKey string The key used to store RBAC data in cache yii\mongodb\rbac\MongoDbManager
$db yii\mongodb\Connection|array|string The MongoDB connection object or the application component ID of the MongoDB connection. yii\mongodb\rbac\MongoDbManager
$itemCollection string|array The name of the collection storing authorization items. yii\mongodb\rbac\MongoDbManager
$items \yii\rbac\Item[] All auth items (name => Item) yii\mongodb\rbac\MongoDbManager
$ruleCollection string|array The name of the collection storing rules. yii\mongodb\rbac\MongoDbManager
$rules \yii\rbac\Rule[] All auth rules (name => Rule) yii\mongodb\rbac\MongoDbManager

Protected Properties

Hide inherited properties

Property Type Description Defined By

Protected Methods

Hide inherited methods

Method Description Defined By
addItem() yii\mongodb\rbac\MongoDbManager
addRule() yii\mongodb\rbac\MongoDbManager
checkAccessFromCache() Performs access check for the specified user based on the data loaded from cache. yii\mongodb\rbac\MongoDbManager
checkAccessRecursive() Performs access check for the specified user. yii\mongodb\rbac\MongoDbManager
detectLoop() Checks whether there is a loop in the authorization item hierarchy. yii\mongodb\rbac\MongoDbManager
getChildrenList() Returns the children for every parent. yii\mongodb\rbac\MongoDbManager
getChildrenRecursive() Recursively finds all children and grand children of the specified item. yii\mongodb\rbac\MongoDbManager
getItem() yii\mongodb\rbac\MongoDbManager
getItems() yii\mongodb\rbac\MongoDbManager
populateItem() Populates an auth item with the data fetched from collection yii\mongodb\rbac\MongoDbManager
removeAllItems() Removes all auth items of the specified type. yii\mongodb\rbac\MongoDbManager
removeItem() yii\mongodb\rbac\MongoDbManager
removeRule() yii\mongodb\rbac\MongoDbManager
updateItem() yii\mongodb\rbac\MongoDbManager
updateRule() yii\mongodb\rbac\MongoDbManager

Property Details

Hide inherited properties

$assignmentCollection public property

The name of the collection storing authorization item assignments. Defaults to "auth_assignment".

public string|array $assignmentCollection 'auth_assignment'
$cache public property

The cache used to improve RBAC performance. This can be one of the following:

  • an application component ID (e.g. cache)
  • a configuration array
  • a \yii\caching\Cache object

When this is not set, it means caching is not enabled.

Note that by enabling RBAC cache, all auth items, rules and auth item parent-child relationships will be cached and loaded into memory. This will improve the performance of RBAC permission check. However, it does require extra memory and as a result may not be appropriate if your RBAC system contains too many auth items. You should seek other RBAC implementations (e.g. RBAC based on Redis storage) in this case.

Also note that if you modify RBAC items, rules or parent-child relationships from outside of this component, you have to manually call invalidateCache() to ensure data consistency.

public \yii\caching\Cache|array|string $cache null
$cacheKey public property

The key used to store RBAC data in cache

See also $cache.

public string $cacheKey 'rbac'
$db public property

The MongoDB connection object or the application component ID of the MongoDB connection. After the MongoDbManager object is created, if you want to change this property, you should only assign it with a MongoDB connection object.

$itemCollection public property

The name of the collection storing authorization items. Defaults to "auth_item".

public string|array $itemCollection 'auth_item'
$items protected property

All auth items (name => Item)

protected \yii\rbac\Item[] $items null
$ruleCollection public property

The name of the collection storing rules. Defaults to "auth_rule".

public string|array $ruleCollection 'auth_rule'
$rules protected property

All auth rules (name => Rule)

protected \yii\rbac\Rule[] $rules null

Method Details

Hide inherited methods

addChild() public method

public void addChild ( $parent, $child )
$parent
$child

                public function addChild($parent, $child)
{
    if ($parent->name === $child->name) {
        throw new InvalidParamException("Cannot add '{$parent->name}' as a child of itself.");
    }
    if ($parent instanceof Permission && $child instanceof Role) {
        throw new InvalidParamException('Cannot add a role as a child of a permission.');
    }
    if ($this->detectLoop($parent, $child)) {
        throw new InvalidCallException("Cannot add '{$child->name}' as a child of '{$parent->name}'. A loop has been detected.");
    }
    $result = $this->db->getCollection($this->itemCollection)
        ->update(
            [
                'name' => $child->name,
            ],
            [
                '$push' => [
                    'parents' => $parent->name
                ]
            ],
            [
                'multi' => false
            ]
        ) > 0;
    $this->invalidateCache();
    return $result;
}

            
addItem() protected method

protected void addItem ( $item )
$item

                protected function addItem($item)
{
    $time = time();
    if ($item->createdAt === null) {
        $item->createdAt = $time;
    }
    if ($item->updatedAt === null) {
        $item->updatedAt = $time;
    }
    $this->db->getCollection($this->itemCollection)
        ->insert([
            'name' => $item->name,
            'type' => $item->type,
            'description' => $item->description,
            'rule_name' => $item->ruleName,
            'data' => $item->data === null ? null : serialize($item->data),
            'created_at' => $item->createdAt,
            'updated_at' => $item->updatedAt,
        ]);
    $this->invalidateCache();
    return true;
}

            
addRule() protected method

protected void addRule ( $rule )
$rule

                protected function addRule($rule)
{
    $time = time();
    if ($rule->createdAt === null) {
        $rule->createdAt = $time;
    }
    if ($rule->updatedAt === null) {
        $rule->updatedAt = $time;
    }
    $this->db->getCollection($this->ruleCollection)
        ->insert([
            'name' => $rule->name,
            'data' => serialize($rule),
            'created_at' => $rule->createdAt,
            'updated_at' => $rule->updatedAt,
        ]);
    $this->invalidateCache();
    return true;
}

            
assign() public method

public void assign ( $role, $userId )
$role
$userId

                public function assign($role, $userId)
{
    $assignment = new Assignment([
        'userId' => (string)$userId,
        'roleName' => $role->name,
        'createdAt' => time(),
    ]);
    $this->db->getCollection($this->assignmentCollection)
        ->insert([
            'user_id' => $assignment->userId,
            'item_name' => $assignment->roleName,
            'created_at' => $assignment->createdAt,
        ]);
    return $assignment;
}

            
canAddChild() public method

public void canAddChild ( $parent, $child )
$parent
$child

                public function canAddChild($parent, $child)
{
    return !$this->detectLoop($parent, $child);
}

            
checkAccess() public method

public void checkAccess ( $userId, $permissionName, $params = [] )
$userId
$permissionName
$params

                public function checkAccess($userId, $permissionName, $params = [])
{
    $assignments = $this->getAssignments($userId);
    $this->loadFromCache();
    if ($this->items !== null) {
        return $this->checkAccessFromCache($userId, $permissionName, $params, $assignments);
    } else {
        return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments);
    }
}

            
checkAccessFromCache() protected method

Performs access check for the specified user based on the data loaded from cache.

This method is internally called by checkAccess() when $cache is enabled.

protected boolean checkAccessFromCache ( $user, $itemName, $params, $assignments )
$user string|integer

The user ID. This should can be either an integer or a string representing the unique identifier of a user. See \yii\web\User::id.

$itemName string

The name of the operation that need access check

$params array

Name-value pairs that would be passed to rules associated with the tasks and roles assigned to the user. A param with name 'user' is added to this array, which holds the value of $userId.

$assignments \yii\rbac\Assignment[]

The assignments to the specified user

return boolean

Whether the operations can be performed by the user.

                protected function checkAccessFromCache($user, $itemName, $params, $assignments)
{
    if (!isset($this->items[$itemName])) {
        return false;
    }
    $item = $this->items[$itemName];
    Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission: $itemName", __METHOD__);
    if (!$this->executeRule($user, $item, $params)) {
        return false;
    }
    if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) {
        return true;
    }
    if (!empty($item->parents)) {
        foreach ($item->parents as $parent) {
            if ($this->checkAccessFromCache($user, $parent, $params, $assignments)) {
                return true;
            }
        }
    }
    return false;
}

            
checkAccessRecursive() protected method

Performs access check for the specified user.

This method is internally called by checkAccess().

protected boolean checkAccessRecursive ( $user, $itemName, $params, $assignments )
$user string|integer

The user ID. This should can be either an integer or a string representing the unique identifier of a user. See \yii\web\User::id.

$itemName string

The name of the operation that need access check

$params array

Name-value pairs that would be passed to rules associated with the tasks and roles assigned to the user. A param with name 'user' is added to this array, which holds the value of $userId.

$assignments \yii\rbac\Assignment[]

The assignments to the specified user

return boolean

Whether the operations can be performed by the user.

                protected function checkAccessRecursive($user, $itemName, $params, $assignments)
{
    if (($item = $this->getItem($itemName)) === null) {
        return false;
    }
    Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission: $itemName", __METHOD__);
    if (!$this->executeRule($user, $item, $params)) {
        return false;
    }
    if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) {
        return true;
    }
    if (!empty($item->parents)) {
        foreach ($item->parents as $parent) {
            if ($this->checkAccessRecursive($user, $parent, $params, $assignments)) {
                return true;
            }
        }
    }
    return false;
}

            
detectLoop() protected method

Checks whether there is a loop in the authorization item hierarchy.

protected boolean detectLoop ( $parent, $child )
$parent \yii\rbac\Item

The parent item

$child \yii\rbac\Item

The child item to be added to the hierarchy

return boolean

Whether a loop exists

                protected function detectLoop($parent, $child)
{
    if ($child->name === $parent->name) {
        return true;
    }
    foreach ($this->getChildren($child->name) as $grandchild) {
        if ($this->detectLoop($parent, $grandchild)) {
            return true;
        }
    }
    return false;
}

            
getAssignment() public method

public void getAssignment ( $roleName, $userId )
$roleName
$userId

                public function getAssignment($roleName, $userId)
{
    if (empty($userId)) {
        return null;
    }
    $row = (new Query)->from($this->assignmentCollection)
        ->where(['user_id' => (string) $userId, 'item_name' => $roleName])
        ->one($this->db);
    if ($row === false) {
        return null;
    }
    return new Assignment([
        'userId' => $row['user_id'],
        'roleName' => $row['item_name'],
        'createdAt' => $row['created_at'],
    ]);
}

            
getAssignments() public method

public void getAssignments ( $userId )
$userId

                public function getAssignments($userId)
{
    if (empty($userId)) {
        return [];
    }
    $query = (new Query)
        ->from($this->assignmentCollection)
        ->where(['user_id' => (string) $userId]);
    $assignments = [];
    foreach ($query->all($this->db) as $row) {
        $assignments[$row['item_name']] = new Assignment([
            'userId' => $row['user_id'],
            'roleName' => $row['item_name'],
            'createdAt' => $row['created_at'],
        ]);
    }
    return $assignments;
}

            
getChildren() public method

public void getChildren ( $name )
$name

                public function getChildren($name)
{
    $query = (new Query)
        ->from($this->itemCollection)
        ->where([
            'parents' => [
                '$in' => [$name]
            ]
        ]);
    $children = [];
    foreach ($query->all($this->db) as $row) {
        $children[$row['name']] = $this->populateItem($row);
    }
    return $children;
}

            
getChildrenList() protected method

Returns the children for every parent.

protected array getChildrenList ( )
return array

The children list. Each array key is a parent item name, and the corresponding array value is a list of child item names.

                protected function getChildrenList()
{
    $query = (new Query)
        ->select(['name', 'parents'])
        ->from($this->itemCollection);
    $children = [];
    foreach ($query->all($this->db) as $row) {
        if (!empty($row['parents'])) {
            foreach ($row['parents'] as $name) {
                $children[$name][] = $row['name'];
            }
        }
    }
    return $children;
}

            
getChildrenRecursive() protected method

Recursively finds all children and grand children of the specified item.

protected void getChildrenRecursive ( $name, $childrenList, &$result )
$name string

The name of the item whose children are to be looked for.

$childrenList array

The child list built via getChildrenList()

$result array

The children and grand children (in array keys)

                protected function getChildrenRecursive($name, $childrenList, &$result)
{
    if (isset($childrenList[$name])) {
        foreach ($childrenList[$name] as $child) {
            $result[$child] = true;
            $this->getChildrenRecursive($child, $childrenList, $result);
        }
    }
}

            
getItem() protected method

protected void getItem ( $name )
$name

                protected function getItem($name)
{
    if (empty($name)) {
        return null;
    }
    if (!empty($this->items[$name])) {
        return $this->items[$name];
    }
    $row = (new Query)->from($this->itemCollection)
        ->where(['name' => $name])
        ->one($this->db);
    if ($row === false) {
        return null;
    }
    return $this->populateItem($row);
}

            
getItems() protected method

protected void getItems ( $type )
$type

                protected function getItems($type)
{
    $query = (new Query)
        ->from($this->itemCollection)
        ->where(['type' => $type]);
    $items = [];
    foreach ($query->all($this->db) as $row) {
        $items[$row['name']] = $this->populateItem($row);
    }
    return $items;
}

            
getPermissionsByRole() public method

public void getPermissionsByRole ( $roleName )
$roleName

                public function getPermissionsByRole($roleName)
{
    $childrenList = $this->getChildrenList();
    $result = [];
    $this->getChildrenRecursive($roleName, $childrenList, $result);
    if (empty($result)) {
        return [];
    }
    $query = (new Query)
        ->from($this->itemCollection)
        ->where([
            'type' => Item::TYPE_PERMISSION,
            'name' => array_keys($result),
        ]);
    $permissions = [];
    foreach ($query->all($this->db) as $row) {
        $permissions[$row['name']] = $this->populateItem($row);
    }
    return $permissions;
}

            
getPermissionsByUser() public method

public void getPermissionsByUser ( $userId )
$userId

                public function getPermissionsByUser($userId)
{
    if (empty($userId)) {
        return [];
    }
    $this->getAssignments($userId);
    $rows = (new Query)
        ->select(['item_name'])
        ->from($this->assignmentCollection)
        ->where(['user_id' => (string) $userId])
        ->all($this->db);
    if (empty($rows)) {
        return [];
    }
    $names = ArrayHelper::getColumn($rows, 'item_name');
    $childrenList = $this->getChildrenList();
    $result = [];
    foreach ($names as $roleName) {
        $this->getChildrenRecursive($roleName, $childrenList, $result);
    }
    $names = array_merge($names, array_keys($result));
    $query = (new Query)
        ->from($this->itemCollection)
        ->where([
            'type' => Item::TYPE_PERMISSION,
            'name' => $names,
        ]);
    $permissions = [];
    foreach ($query->all($this->db) as $row) {
        $permissions[$row['name']] = $this->populateItem($row);
    }
    return $permissions;
}

            
getRolesByUser() public method

public void getRolesByUser ( $userId )
$userId

                public function getRolesByUser($userId)
{
    if (!isset($userId) || $userId === '') {
        return [];
    }
    $rows = (new Query)->select(['item_name'])
        ->from($this->assignmentCollection)
        ->where(['user_id' => (string) $userId])
        ->all($this->db);
    if (empty($rows)) {
        return [];
    }
    $itemNames = ArrayHelper::getColumn($rows, 'item_name');
    $query = (new Query)
        ->from($this->itemCollection)
        ->where(['name' => $itemNames])
        ->andWhere(['type' => Item::TYPE_ROLE]);
    $roles = [];
    foreach ($query->all($this->db) as $row) {
        $roles[$row['name']] = $this->populateItem($row);
    }
    return $roles;
}

            
getRule() public method

public void getRule ( $name )
$name

                public function getRule($name)
{
    if ($this->rules !== null) {
        return isset($this->rules[$name]) ? $this->rules[$name] : null;
    }
    $row = (new Query)->select(['data'])
        ->from($this->ruleCollection)
        ->where(['name' => $name])
        ->one($this->db);
    return $row === false ? null : unserialize($row['data']);
}

            
getRules() public method

public void getRules ( )

                public function getRules()
{
    if ($this->rules !== null) {
        return $this->rules;
    }
    $query = (new Query)->from($this->ruleCollection);
    $rules = [];
    foreach ($query->all($this->db) as $row) {
        $rules[$row['name']] = unserialize($row['data']);
    }
    return $rules;
}

            
getUserIdsByRole() public method

public void getUserIdsByRole ( $roleName )
$roleName

                public function getUserIdsByRole($roleName)
{
    if (empty($roleName)) {
        return [];
    }
    $rows = (new Query)->select(['user_id'])
        ->from($this->assignmentCollection)
        ->where(['item_name' => $roleName])
        ->all($this->db);
    return ArrayHelper::getColumn($rows, 'user_id');
}

            
hasChild() public method

public void hasChild ( $parent, $child )
$parent
$child

                public function hasChild($parent, $child)
{
    return (new Query)
        ->from($this->itemCollection)
        ->where([
            'name' => $child->name
        ])
        ->andWhere([
            'parents' => [
                '$in' => [$parent->name]
            ]
        ])
        ->one($this->db) !== false;
}

            
init() public method

Initializes the application component.

This method overrides the parent implementation by establishing the MongoDB connection.

public void init ( )

                public function init()
{
    parent::init();
    $this->db = Instance::ensure($this->db, Connection::className());
    if ($this->cache !== null) {
        $this->cache = Instance::ensure($this->cache, Cache::className());
    }
}

            
invalidateCache() public method

Invalidates RBAC related cache

public void invalidateCache ( )

                public function invalidateCache()
{
    if ($this->cache !== null) {
        $this->cache->delete($this->cacheKey);
        $this->items = null;
        $this->rules = null;
        $this->parents = null;
    }
}

            
loadFromCache() public method

Loads data from cache

public void loadFromCache ( )

                public function loadFromCache()
{
    if ($this->items !== null || !$this->cache instanceof Cache) {
        return;
    }
    $data = $this->cache->get($this->cacheKey);
    if (is_array($data) && isset($data[0], $data[1])) {
        list ($this->items, $this->rules) = $data;
        return;
    }
    $query = (new Query)->from($this->itemCollection);
    $this->items = [];
    foreach ($query->all($this->db) as $row) {
        $this->items[$row['name']] = $this->populateItem($row);
    }
    $query = (new Query)->from($this->ruleCollection);
    $this->rules = [];
    foreach ($query->all($this->db) as $row) {
        $this->rules[$row['name']] = unserialize($row['data']);
    }
    $this->cache->set($this->cacheKey, [$this->items, $this->rules]);
}

            
populateItem() protected method

Populates an auth item with the data fetched from collection

protected \yii\rbac\Item populateItem ( $row )
$row array

The data from the auth item collection

return \yii\rbac\Item

The populated auth item instance (either Role or Permission)

                protected function populateItem($row)
{
    $class = $row['type'] == Item::TYPE_PERMISSION ? Permission::className() : Role::className();
    if (!isset($row['data']) || ($data = @unserialize($row['data'])) === false) {
        $data = null;
    }
    return new $class([
        'name' => $row['name'],
        'type' => $row['type'],
        'description' => $row['description'],
        'ruleName' => $row['rule_name'],
        'data' => $data,
        'createdAt' => $row['created_at'],
        'updatedAt' => $row['updated_at'],
        'parents' => isset($row['parents']) ? $row['parents'] : null,
    ]);
}

            
removeAll() public method

public void removeAll ( )

                public function removeAll()
{
    $this->removeAllAssignments();
    $this->db->getCollection($this->itemCollection)->remove();
    $this->db->getCollection($this->ruleCollection)->remove();
    $this->invalidateCache();
}

            
removeAllAssignments() public method

public void removeAllAssignments ( )

                public function removeAllAssignments()
{
    $this->db->getCollection($this->assignmentCollection)->remove();
}

            
removeAllItems() protected method

Removes all auth items of the specified type.

protected void removeAllItems ( $type )
$type integer

The auth item type (either Item::TYPE_PERMISSION or Item::TYPE_ROLE)

                protected function removeAllItems($type)
{
    $rows = (new Query)
        ->select(['name'])
        ->from($this->itemCollection)
        ->where(['type' => $type])
        ->all($this->db);
    if (empty($rows)) {
        return;
    }
    $names = ArrayHelper::getColumn($rows, 'name');
    $this->db->getCollection($this->assignmentCollection)
        ->remove(['item_name' => $names]);
    $this->db->getCollection($this->itemCollection)
        ->remove(['type' => $type]);
    $this->db->getCollection($this->itemCollection)
        ->update(
            [],
            [
                '$pull' => [
                    'parents' => [
                        '$in' => $names,
                    ]
                ],
            ],
            [
                'multi' => true
            ]
        );
    $this->invalidateCache();
}

            
removeAllPermissions() public method

public void removeAllPermissions ( )

                public function removeAllPermissions()
{
    $this->removeAllItems(Item::TYPE_PERMISSION);
}

            
removeAllRoles() public method

public void removeAllRoles ( )

                public function removeAllRoles()
{
    $this->removeAllItems(Item::TYPE_ROLE);
}

            
removeAllRules() public method

public void removeAllRules ( )

                public function removeAllRules()
{
    $this->db->getCollection($this->itemCollection)
        ->update([], ['rule_name' => null]);
    $this->db->getCollection($this->ruleCollection)->remove();
    $this->invalidateCache();
}

            
removeChild() public method

public void removeChild ( $parent, $child )
$parent
$child

                public function removeChild($parent, $child)
{
    $result = $this->db->getCollection($this->itemCollection)
        ->update(
            [
                'name' => $child->name,
            ],
            [
                '$pull' => [
                    'parents' => [
                        '$in' => [$parent->name]
                    ]
                ]
            ],
            [
                'multi' => false
            ]
        ) > 0;
    $this->invalidateCache();
    return $result;
}

            
removeChildren() public method

public void removeChildren ( $parent )
$parent

                public function removeChildren($parent)
{
    $result = $this->db->getCollection($this->itemCollection)
        ->update(
            [],
            [
                '$pull' => [
                    'parents' => [
                        '$in' => [$parent->name]
                    ]
                ]
            ],
            [
                'multi' => true
            ]
        ) > 0;
    $this->invalidateCache();
    return $result;
}

            
removeItem() protected method

protected void removeItem ( $item )
$item

                protected function removeItem($item)
{
    $this->db->getCollection($this->assignmentCollection)
        ->remove(['item_name' => $item->name]);
    $this->db->getCollection($this->itemCollection)
        ->remove(['name' => $item->name]);
    $this->db->getCollection($this->itemCollection)
        ->update(
            [
                'parents' => [
                    '$in' => [$item->name]
                ],
            ],
            [
                '$pull' => [
                    'parents' => [
                        '$in' => [$item->name],
                    ]
                ]
            ],
            [
                'multi' => true
            ]
        );
    $this->invalidateCache();
    return true;
}

            
removeRule() protected method

protected void removeRule ( $rule )
$rule

                protected function removeRule($rule)
{
    $this->db->getCollection($this->itemCollection)
        ->update(['rule_name' => $rule->name], ['rule_name' => null]);
    $this->db->getCollection($this->ruleCollection)
        ->remove(['name' => $rule->name]);
    $this->invalidateCache();
    return true;
}

            
revoke() public method

public void revoke ( $role, $userId )
$role
$userId

                public function revoke($role, $userId)
{
    if (empty($userId)) {
        return false;
    }
    return $this->db->getCollection($this->assignmentCollection)
        ->remove(['user_id' => (string) $userId, 'item_name' => $role->name]) > 0;
}

            
revokeAll() public method

public void revokeAll ( $userId )
$userId

                public function revokeAll($userId)
{
    if (empty($userId)) {
        return false;
    }
    return $this->db->getCollection($this->assignmentCollection)
        ->remove(['user_id' => (string) $userId]) > 0;
}

            
updateItem() protected method

protected void updateItem ( $name, $item )
$name
$item

                protected function updateItem($name, $item)
{
    if ($item->name !== $name) {
        $this->db->getCollection($this->assignmentCollection)
            ->update(['item_name' => $name], ['item_name' => $item->name]);
        $this->db->getCollection($this->itemCollection)
            ->update(
                [
                    'parents' => [
                        '$in' => [$item->name]
                    ],
                ],
                [
                    '$pull' => [
                        'parents' => [
                            '$in' => [$item->name],
                        ]
                    ],
                ],
                [
                    'multi' => true
                ]
            );
        $this->db->getCollection($this->itemCollection)
            ->update(
                [
                    'parents' => [
                        '$in' => [$item->name]
                    ],
                ],
                [
                    '$push' => [
                        'parents' => $name
                    ]
                ],
                [
                    'multi' => true
                ]
            );
    }
    $item->updatedAt = time();
    $this->db->getCollection($this->itemCollection)
        ->update(
            [
                'name' => $name,
            ],
            [
                'name' => $item->name,
                'description' => $item->description,
                'rule_name' => $item->ruleName,
                'data' => $item->data === null ? null : serialize($item->data),
                'updated_at' => $item->updatedAt,
            ]
        );
    $this->invalidateCache();
    return true;
}

            
updateRule() protected method

protected void updateRule ( $name, $rule )
$name
$rule

                protected function updateRule($name, $rule)
{
    if ($rule->name !== $name) {
        $this->db->getCollection($this->itemCollection)
            ->update(['rule_name' => $name], ['rule_name' => $rule->name]);
    }
    $rule->updatedAt = time();
    $this->db->getCollection($this->ruleCollection)
        ->update(
            [
                'name' => $name,
            ],
            [
                'name' => $rule->name,
                'data' => serialize($rule),
                'updated_at' => $rule->updatedAt,
            ]
        );
    $this->invalidateCache();
    return true;
}