Zend_Acl find all inherited roles
Asked Answered
P

1

5

I got chain of roles:

acl.roles.guest  = null
acl.roles.member = "guest"
acl.roles.admin  = "member"
acl.roles.owner  = "admin"

in .....Controller/Action/Helper/Acl.php I have stored _acl object

Is it a way to get list of my role and parents ?

$this->_acl->getParents ( 'admin' )

should return

admin, member, guest

as array, or string (eg comma delimited)

Permanence answered 20/3, 2011 at 16:59 Comment(0)
E
14

You can use

  • getRoles() - Returns an array of registered roles.

and then check each of these with

  • inheritsRole() - Returns true if and only if $role inherits from $inherit

See the API docs Zend_Acl at http://framework.zend.com/apidoc/core/Zend_Acl/Zend_Acl.html

Example

$parents = array();
foreach ($acl->getRoles() as $inherit) {
    if ($acl->inheritsRole('owner', $inherit)) {
        $parents[] = $inherit;
    }
}

which would then return something like

Array
(
    [0] => guest
    [1] => member
    [2] => admin
)

Alternative

There actually is a getParents() method in Zend_Acl_Role_Registry, but there doesn't seem to be a way to access that through the public interface of Zend_Acl. See the sourcecode

It is trivial to extend Zend_Acl to have a method getParentsForRole() though:

class My_Acl extends Zend_Acl
{
    public function getParentsForRole($role)
    {
        return $this->_getRoleRegistry()->getParents($role);
    }
}

This does only return the immediate parents though, e.g. for 'owner' it returns 'admin', so you might want to add another method to fetch all the parents recursively down to the last one:

class My_Acl extends Zend_Acl
{
    public function getAllParentsForRole($role, $parents = array())
    {
        foreach ($this->getParentsForRole($role) as $parentName => $parentRole) {
            if (FALSE === isset($parents[$parentName])) {
                $parents[$parentName] = $parentRole;
                $parents = $this->getAllParentsForRole($parentRole, $parents);
            }
        }
        return $parents;
    }

    public function getParentsForRole($role)
    {
        return $this->_getRoleRegistry()->getParents($role);
    }
}

Example

$acl = new My_Acl;
$acl->addRole('guest');
$acl->addRole('other');
$acl->addRole('member', 'guest');
$acl->addRole('admin', 'member');
$acl->addRole('owner', array('admin', 'other'));

print_r($acl->getAllParentsForRole('owner'));

would result in

Array
(
    [admin] => Zend_Acl_Role Object
        (
            [_roleId:protected] => admin
        )

    [member] => Zend_Acl_Role Object
        (
            [_roleId:protected] => member
        )

    [guest] => Zend_Acl_Role Object
        (
            [_roleId:protected] => guest
        )

    [other] => Zend_Acl_Role Object
        (
            [_roleId:protected] => other
        )    
)

which is in accordance with what a single call to getParents would return. If you dont need that, you can also just use the foreach code from the first example, e.g.

class My_Acl extends Zend_Acl
{
    public function getAllParentsForRole($role)
    {
        $parents = array();
        foreach ($this->getRoles() as $inherit) {
            if($this->inheritsRole($role, $inherit)) {
                $parents[] = $inherit;
            }
        }
        return $parents;
    }
}
Exclosure answered 20/3, 2011 at 17:8 Comment(1)
WOW, WOW, WOW - I did not expect such complex answer and offcourse everything works as planned - I prefer second solution where looping thru getRoles() - THANK YOUPermanence

© 2022 - 2024 — McMap. All rights reserved.