'ello all.
I am having an issue getting inheritance to work properly using Zend_Acl.
Here is my ACL model
<?php
class Acl extends Zend_Acl {
protected static $_instance = NULL;
private function __construct(){
$this->_init();
}
protected function _init(){
$this->db = Zend_Registry::get('db');
$query = "SELECT `".DB_TABLE_ACL_MODULE."`.`module_name`, `".DB_TABLE_ACL_RESOURCE."`.`resource_name`";
$query .= ", `".DB_TABLE_ACL_PRIVILEGE."`.`priv_name`, `".DB_TABLE_ACL_ROLE."`.`roleid`, `".DB_TABLE_ACL_ROLE."`.`role_name`";
$query .= " FROM `".DB_TABLE_ACL_PRIVILEGE."` ";
$query .= " INNER JOIN `".DB_TABLE_ACL_ROLE_PRIVILEGE."` ON `".DB_TABLE_ACL_ROLE_PRIVILEGE."`.`privid` = `".DB_TABLE_ACL_PRIVILEGE."`.`privid`";
$query .= " INNER JOIN `".DB_TABLE_ACL_RESOURCE."` ON `".DB_TABLE_ACL_ROLE_PRIVILEGE."`.`resourceid` = `".DB_TABLE_ACL_RESOURCE."`.`resourceid`";
$query .= " INNER JOIN `".DB_TABLE_ACL_MODULE."` ON `".DB_TABLE_ACL_RESOURCE."`.`moduleid` = `".DB_TABLE_ACL_MODULE."`.`moduleid`";
$query .= " RIGHT JOIN `".DB_TABLE_ACL_ROLE."` ON `".DB_TABLE_ACL_ROLE_PRIVILEGE."`.`roleid` = `".DB_TABLE_ACL_ROLE."`.`roleid` ORDER BY `".DB_TABLE_ACL_ROLE."`.`lft` ASC";
$roles = $this->db->fetchAll($query);
foreach($roles as $role){
if(!empty($role['module_name']) && !empty($role['resource_name']) && !$this->has($role['module_name'].'_'.$role['resource_name']))
$this->add(new Zend_Acl_Resource($role['module_name'].'_'.$role['resource_name']));
if(!$this->hasRole($role['role_name'])){
#echo 'No role '.$role['roleid'].'<br />';
$parents = $this->getRoleParents($role['roleid']);
#if($parent)
# echo 'Parent = '.$parent.'<br />';
#else
# echo 'No parent<br />';
if($parents){
foreach($parents as $value){
if(!$this->hasRole($value)){
#echo '1: Adding role '.$parent.' with parent '.$this->getRoleParent($parent).'<br />';
$this->addRole(new Zend_Acl_Role($value), $this->getRoleParents($value));
}
}
}
#echo '2: Adding role '.$role['roleid'].' with parent '.$parent.'<br />';
if($parents)
$this->addRole(new Zend_Acl_Role($role['role_name']), $parents);
else
$this->addRole(new Zend_Acl_Role($role['role_name']));
}
}
// add default error resource
# added manually this time
#$this->add(new Zend_Acl_Resource('default_error'));
// deny all
$this->deny();
// allow all to error page
$this->allow(null, 'default_error');
// allow to resources
foreach($roles as $role){
if(!empty($role['module_name']) && !empty($role['resource_name']) && $this->has($role['module_name'].'_'.$role['resource_name']))
$this->allow($role['role_name'], $role['module_name'].'_'.$role['resource_name'], $role['priv_name']);
}
}
public static function getInstance(){
if(self::$_instance === NULL){
self::$_instance = new Acl();
}
return self::$_instance;
}
public static function getRoleId($role_name){
$db = Zend_Registry::get('db');
$ret = $db->fetchCol("SELECT `roleid` FROM `".DB_TABLE_ACL_ROLE."` WHERE `role_name` = '$role_name' LIMIT 1");
return $ret[0];
}
public static function getRoleName($roleid){
$db = Zend_Registry::get('db');
$ret = $db->fetchCol("SELECT `role_name` FROM `".DB_TABLE_ACL_ROLE."` WHERE `roleid` = '$roleid' LIMIT 1");
return $ret[0];
}
protected function getRoleParents($roleid){
$res = $this->db->fetchRow("SELECT `lft`, `rght` FROM `".DB_TABLE_ACL_ROLE."` WHERE `roleid` = '$roleid' LIMIT 1");
list($left, $right) = array_values($res);
$ret = $this->db->fetchAll("SELECT `role_name` FROM `".DB_TABLE_ACL_ROLE."` WHERE `lft` < $left AND `rght` > $right ORDER BY `lft` DESC");
$return = array();
foreach($ret as $arr){
$return[] = $arr['role_name'];
}
if(count($return)) return $return;
return false;
}
protected function getRoleParent($roleid){
$res = $this->db->fetchRow("SELECT `lft`, `rght` FROM `".DB_TABLE_ACL_ROLE."` WHERE `roleid` = '$roleid' LIMIT 1");
list($left, $right) = array_values($res);
$left--;
$right++;
$ret = $this->db->fetchRow("SELECT `role_name` FROM `".DB_TABLE_ACL_ROLE."` WHERE `lft` = $left AND `rght` = $right LIMIT 1");
if(!empty($ret['role_name'])) return $ret['role_name'];
return false;
}
}
Here is my ACL plugin
<?php
class AclPlugin extends Zend_Controller_Plugin_Abstract {
public function preDispatch() {
$session = Zend_Registry::get('session');
if(empty($session->roleid)) $session->roleid = 0;
$acl = Acl::getInstance();
$request = $this->getRequest();
#echo '<pre>'; print_r($acl);echo '</pre>';
if (!$acl->hasRole($session->roleid)) {
$error = "Sorry, the requested user role '".$session->roleid."' does not exist";
}
if (!$acl->has($request->getModuleName().'_'.$request->getControllerName())) {
$error = "Sorry, the requested controller '".$request->getControllerName()."' does not exist as an ACL resource";
}
if (!$acl->isAllowed($session->roleid, $request->getModuleName().'_'.$request->getControllerName(), $request->getActionName())) {
$error = "Sorry, the page you requested does not exist or you do not have access. <br />Role: ".$session->roleid."<br />Resource: ".$request->getModuleName().'_'.$request->getControllerName()." <br />Privilege: ".$request->getActionName();
}
if (isset($error)) {
Zend_Registry::set('error', $error);
$request->setModuleName('default');
$request->setControllerName('error');
$request->setActionName('index');
$request->setDispatched(false);
echo $error;
echo '<pre>'; print_r($acl);
exit;
}
}
}
Could someone please help me resolve this issue? I am pretty new to the ACL for ZF.
TIA!