array( 'allRoles' => array( 'allPrivileges' => array( 'type' => self::TYPE_DENY, 'assert' => null ), 'byPrivilegeId' => array() ), 'byRoleId' => array() ), 'byResourceId' => array() ); public function addRole($role, $parents = null) { if (is_string($role)) { $role = new Zend_Acl_Role($role); } if (!$role instanceof Zend_Acl_Role_Interface) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('addRole() expects $role to be of type Zend_Acl_Role_Interface'); } $this->_getRoleRegistry()->add($role, $parents); return $this; } public function getRole($role) { return $this->_getRoleRegistry()->get($role); } public function hasRole($role) { return $this->_getRoleRegistry()->has($role); } public function inheritsRole($role, $inherit, $onlyParents = false) { return $this->_getRoleRegistry()->inherits($role, $inherit, $onlyParents); } public function removeRole($role) { $this->_getRoleRegistry()->remove($role); if ($role instanceof Zend_Acl_Role_Interface) { $roleId = $role->getRoleId(); } else { $roleId = $role; } foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) { if ($roleId === $roleIdCurrent) { unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]); } } foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) { if (array_key_exists('byRoleId', $visitor)) { foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) { if ($roleId === $roleIdCurrent) { unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]); } } } } return $this; } public function removeRoleAll() { $this->_getRoleRegistry()->removeAll(); foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) { unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]); } foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) { foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) { unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]); } } return $this; } public function addResource($resource, $parent = null) { if (is_string($resource)) { $resource = new Zend_Acl_Resource($resource); } if (!$resource instanceof Zend_Acl_Resource_Interface) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('addResource() expects $resource to be of type Zend_Acl_Resource_Interface'); } $resourceId = $resource->getResourceId(); if ($this->has($resourceId)) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception("Resource id '$resourceId' already exists in the ACL"); } $resourceParent = null; if (null !== $parent) { try { if ($parent instanceof Zend_Acl_Resource_Interface) { $resourceParentId = $parent->getResourceId(); } else { $resourceParentId = $parent; } $resourceParent = $this->get($resourceParentId); } catch (Zend_Acl_Exception $e) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception("Parent Resource id '$resourceParentId' does not exist", 0, $e); } $this->_resources[$resourceParentId]['children'][$resourceId] = $resource; } $this->_resources[$resourceId] = array( 'instance' => $resource, 'parent' => $resourceParent, 'children' => array() ); return $this; } public function add(Zend_Acl_Resource_Interface $resource, $parent = null) { return $this->addResource($resource, $parent); } public function get($resource) { if ($resource instanceof Zend_Acl_Resource_Interface) { $resourceId = $resource->getResourceId(); } else { $resourceId = (string) $resource; } if (!$this->has($resource)) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception("Resource '$resourceId' not found"); } return $this->_resources[$resourceId]['instance']; } public function has($resource) { if ($resource instanceof Zend_Acl_Resource_Interface) { $resourceId = $resource->getResourceId(); } else { $resourceId = (string) $resource; } return isset($this->_resources[$resourceId]); } public function inherits($resource, $inherit, $onlyParent = false) { try { $resourceId = $this->get($resource)->getResourceId(); $inheritId = $this->get($inherit)->getResourceId(); } catch (Zend_Acl_Exception $e) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e); } if (null !== $this->_resources[$resourceId]['parent']) { $parentId = $this->_resources[$resourceId]['parent']->getResourceId(); if ($inheritId === $parentId) { return true; } else if ($onlyParent) { return false; } } else { return false; } while (null !== $this->_resources[$parentId]['parent']) { $parentId = $this->_resources[$parentId]['parent']->getResourceId(); if ($inheritId === $parentId) { return true; } } return false; } public function remove($resource) { try { $resourceId = $this->get($resource)->getResourceId(); } catch (Zend_Acl_Exception $e) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e); } $resourcesRemoved = array($resourceId); if (null !== ($resourceParent = $this->_resources[$resourceId]['parent'])) { unset($this->_resources[$resourceParent->getResourceId()]['children'][$resourceId]); } foreach ($this->_resources[$resourceId]['children'] as $childId => $child) { $this->remove($childId); $resourcesRemoved[] = $childId; } foreach ($resourcesRemoved as $resourceIdRemoved) { foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) { if ($resourceIdRemoved === $resourceIdCurrent) { unset($this->_rules['byResourceId'][$resourceIdCurrent]); } } } unset($this->_resources[$resourceId]); return $this; } public function removeAll() { foreach ($this->_resources as $resourceId => $resource) { foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) { if ($resourceId === $resourceIdCurrent) { unset($this->_rules['byResourceId'][$resourceIdCurrent]); } } } $this->_resources = array(); return $this; } public function allow($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null) { return $this->setRule(self::OP_ADD, self::TYPE_ALLOW, $roles, $resources, $privileges, $assert); } public function deny($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null) { return $this->setRule(self::OP_ADD, self::TYPE_DENY, $roles, $resources, $privileges, $assert); } public function removeAllow($roles = null, $resources = null, $privileges = null) { return $this->setRule(self::OP_REMOVE, self::TYPE_ALLOW, $roles, $resources, $privileges); } public function removeDeny($roles = null, $resources = null, $privileges = null) { return $this->setRule(self::OP_REMOVE, self::TYPE_DENY, $roles, $resources, $privileges); } public function setRule($operation, $type, $roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null) { $type = strtoupper($type); if (self::TYPE_ALLOW !== $type && self::TYPE_DENY !== $type) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception("Unsupported rule type; must be either '" . self::TYPE_ALLOW . "' or '" . self::TYPE_DENY . "'"); } if (!is_array($roles)) { $roles = array($roles); } else if (0 === count($roles)) { $roles = array(null); } $rolesTemp = $roles; $roles = array(); foreach ($rolesTemp as $role) { if (null !== $role) { $roles[] = $this->_getRoleRegistry()->get($role); } else { $roles[] = null; } } unset($rolesTemp); if ($resources !== null) { if (!is_array($resources)) { $resources = array($resources); } else if (0 === count($resources)) { $resources = array(null); } $resourcesTemp = $resources; $resources = array(); foreach ($resourcesTemp as $resource) { if (null !== $resource) { $resources[] = $this->get($resource); } else { $resources[] = null; } } unset($resourcesTemp, $resource); } else { $allResources = array(); foreach ($this->_resources as $rTarget) { $allResources[] = $rTarget['instance']; } unset($rTarget); } if (null === $privileges) { $privileges = array(); } else if (!is_array($privileges)) { $privileges = array($privileges); } switch ($operation) { case self::OP_ADD: if ($resources !== null) { foreach ($resources as $resource) { foreach ($roles as $role) { $rules =& $this->_getRules($resource, $role, true); if (0 === count($privileges)) { $rules['allPrivileges']['type'] = $type; $rules['allPrivileges']['assert'] = $assert; if (!isset($rules['byPrivilegeId'])) { $rules['byPrivilegeId'] = array(); } } else { foreach ($privileges as $privilege) { $rules['byPrivilegeId'][$privilege]['type'] = $type; $rules['byPrivilegeId'][$privilege]['assert'] = $assert; } } } } } else { foreach ($roles as $role) { $rules =& $this->_getRules(null, $role, true); if (0 === count($privileges)) { $rules['allPrivileges']['type'] = $type; $rules['allPrivileges']['assert'] = $assert; } else { foreach ($privileges as $privilege) { $rules['byPrivilegeId'][$privilege]['type'] = $type; $rules['byPrivilegeId'][$privilege]['assert'] = $assert; } } } } break; case self::OP_REMOVE: if ($resources !== null) { foreach ($resources as $resource) { foreach ($roles as $role) { $rules =& $this->_getRules($resource, $role); if (null === $rules) { continue; } if (0 === count($privileges)) { if (null === $resource && null === $role) { if ($type === $rules['allPrivileges']['type']) { $rules = array( 'allPrivileges' => array( 'type' => self::TYPE_DENY, 'assert' => null ), 'byPrivilegeId' => array() ); } continue; } if (isset($rules['allPrivileges']['type']) && $type === $rules['allPrivileges']['type']) { unset($rules['allPrivileges']); } } else { foreach ($privileges as $privilege) { if (isset($rules['byPrivilegeId'][$privilege]) && $type === $rules['byPrivilegeId'][$privilege]['type']) { unset($rules['byPrivilegeId'][$privilege]); } } } } } } else { foreach ($roles as $role) { foreach (array_merge(array(null), $allResources) as $resource) { $rules =& $this->_getRules($resource, $role, true); if (null === $rules) { continue; } if (0 === count($privileges)) { if (null === $role) { if ($type === $rules['allPrivileges']['type']) { $rules = array( 'allPrivileges' => array( 'type' => self::TYPE_DENY, 'assert' => null ), 'byPrivilegeId' => array() ); } continue; } if (isset($rules['allPrivileges']['type']) && $type === $rules['allPrivileges']['type']) { unset($rules['allPrivileges']); } } else { foreach ($privileges as $privilege) { if (isset($rules['byPrivilegeId'][$privilege]) && $type === $rules['byPrivilegeId'][$privilege]['type']) { unset($rules['byPrivilegeId'][$privilege]); } } } } } } break; default: require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception("Unsupported operation; must be either '" . self::OP_ADD . "' or '" . self::OP_REMOVE . "'"); } return $this; } public function isAllowed($role = null, $resource = null, $privilege = null) { $this->_isAllowedRole = null; $this->_isAllowedResource = null; $this->_isAllowedPrivilege = null; if (null !== $role) { $this->_isAllowedRole = $role; $role = $this->_getRoleRegistry()->get($role); if (!$this->_isAllowedRole instanceof Zend_Acl_Role_Interface) { $this->_isAllowedRole = $role; } } if (null !== $resource) { $this->_isAllowedResource = $resource; $resource = $this->get($resource); if (!$this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) { $this->_isAllowedResource = $resource; } } if (null === $privilege) { do { if (null !== $role && null !== ($result = $this->_roleDFSAllPrivileges($role, $resource, $privilege))) { return $result; } if (null !== ($rules = $this->_getRules($resource, null))) { foreach ($rules['byPrivilegeId'] as $privilege => $rule) { if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, null, $privilege))) { return false; } } if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) { return self::TYPE_ALLOW === $ruleTypeAllPrivileges; } } $resource = $this->_resources[$resource->getResourceId()]['parent']; } while (true); } else { $this->_isAllowedPrivilege = $privilege; do { if (null !== $role && null !== ($result = $this->_roleDFSOnePrivilege($role, $resource, $privilege))) { return $result; } if (null !== ($ruleType = $this->_getRuleType($resource, null, $privilege))) { return self::TYPE_ALLOW === $ruleType; } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) { return self::TYPE_ALLOW === $ruleTypeAllPrivileges; } $resource = $this->_resources[$resource->getResourceId()]['parent']; } while (true); } } protected function _getRoleRegistry() { if (null === $this->_roleRegistry) { $this->_roleRegistry = new Zend_Acl_Role_Registry(); } return $this->_roleRegistry; } protected function _roleDFSAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null) { $dfs = array( 'visited' => array(), 'stack' => array() ); if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) { return $result; } while (null !== ($role = array_pop($dfs['stack']))) { if (!isset($dfs['visited'][$role->getRoleId()])) { if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) { return $result; } } } return null; } protected function _roleDFSVisitAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, &$dfs = null) { if (null === $dfs) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('$dfs parameter may not be null'); } if (null !== ($rules = $this->_getRules($resource, $role))) { foreach ($rules['byPrivilegeId'] as $privilege => $rule) { if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) { return false; } } if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) { return self::TYPE_ALLOW === $ruleTypeAllPrivileges; } } $dfs['visited'][$role->getRoleId()] = true; foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) { $dfs['stack'][] = $roleParent; } return null; } protected function _roleDFSOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, $privilege = null) { if (null === $privilege) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('$privilege parameter may not be null'); } $dfs = array( 'visited' => array(), 'stack' => array() ); if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) { return $result; } while (null !== ($role = array_pop($dfs['stack']))) { if (!isset($dfs['visited'][$role->getRoleId()])) { if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) { return $result; } } } return null; } protected function _roleDFSVisitOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null, $privilege = null, &$dfs = null) { if (null === $privilege) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('$privilege parameter may not be null'); } if (null === $dfs) { require_once 'Zend/Acl/Exception.php'; throw new Zend_Acl_Exception('$dfs parameter may not be null'); } if (null !== ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) { return self::TYPE_ALLOW === $ruleTypeOnePrivilege; } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) { return self::TYPE_ALLOW === $ruleTypeAllPrivileges; } $dfs['visited'][$role->getRoleId()] = true; foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) { $dfs['stack'][] = $roleParent; } return null; } protected function _getRuleType(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null, $privilege = null) { if (null === ($rules = $this->_getRules($resource, $role))) { return null; } if (null === $privilege) { if (isset($rules['allPrivileges'])) { $rule = $rules['allPrivileges']; } else { return null; } } else if (!isset($rules['byPrivilegeId'][$privilege])) { return null; } else { $rule = $rules['byPrivilegeId'][$privilege]; } if ($rule['assert']) { $assertion = $rule['assert']; $assertionValue = $assertion->assert( $this, ($this->_isAllowedRole instanceof Zend_Acl_Role_Interface) ? $this->_isAllowedRole : $role, ($this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) ? $this->_isAllowedResource : $resource, $this->_isAllowedPrivilege ); } if (null === $rule['assert'] || $assertionValue) { return $rule['type']; } else if (null !== $resource || null !== $role || null !== $privilege) { return null; } else if (self::TYPE_ALLOW === $rule['type']) { return self::TYPE_DENY; } else { return self::TYPE_ALLOW; } } protected function &_getRules(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null, $create = false) { $null = null; $nullRef =& $null; do { if (null === $resource) { $visitor =& $this->_rules['allResources']; break; } $resourceId = $resource->getResourceId(); if (!isset($this->_rules['byResourceId'][$resourceId])) { if (!$create) { return $nullRef; } $this->_rules['byResourceId'][$resourceId] = array(); } $visitor =& $this->_rules['byResourceId'][$resourceId]; } while (false); if (null === $role) { if (!isset($visitor['allRoles'])) { if (!$create) { return $nullRef; } $visitor['allRoles']['byPrivilegeId'] = array(); } return $visitor['allRoles']; } $roleId = $role->getRoleId(); if (!isset($visitor['byRoleId'][$roleId])) { if (!$create) { return $nullRef; } $visitor['byRoleId'][$roleId]['byPrivilegeId'] = array(); $visitor['byRoleId'][$roleId]['allPrivileges'] = array('type' => null, 'assert' => null); } return $visitor['byRoleId'][$roleId]; } public function getRegisteredRoles() { trigger_error('The method getRegisteredRoles() was deprecated as of ' . 'version 1.0, and may be removed. You\'re encouraged ' . 'to use getRoles() instead.'); return $this->_getRoleRegistry()->getRoles(); } public function getRoles() { return array_keys($this->_getRoleRegistry()->getRoles()); } public function getResources() { return array_keys($this->_resources); } }