web/enmi/Zend/Acl.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Acl
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: Acl.php 23358 2010-11-18 16:19:31Z ralph $
       
    20  */
       
    21 
       
    22 
       
    23 /**
       
    24  * @see Zend_Acl_Resource_Interface
       
    25  */
       
    26 require_once 'Zend/Acl/Resource/Interface.php';
       
    27 
       
    28 
       
    29 /**
       
    30  * @see Zend_Acl_Role_Registry
       
    31  */
       
    32 require_once 'Zend/Acl/Role/Registry.php';
       
    33 
       
    34 
       
    35 /**
       
    36  * @see Zend_Acl_Assert_Interface
       
    37  */
       
    38 require_once 'Zend/Acl/Assert/Interface.php';
       
    39 
       
    40 
       
    41 /**
       
    42  * @see Zend_Acl_Role
       
    43  */
       
    44 require_once 'Zend/Acl/Role.php';
       
    45 
       
    46 
       
    47 /**
       
    48  * @see Zend_Acl_Resource
       
    49  */
       
    50 require_once 'Zend/Acl/Resource.php';
       
    51 
       
    52 
       
    53 /**
       
    54  * @category   Zend
       
    55  * @package    Zend_Acl
       
    56  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    57  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    58  */
       
    59 class Zend_Acl
       
    60 {
       
    61     /**
       
    62      * Rule type: allow
       
    63      */
       
    64     const TYPE_ALLOW = 'TYPE_ALLOW';
       
    65 
       
    66     /**
       
    67      * Rule type: deny
       
    68      */
       
    69     const TYPE_DENY  = 'TYPE_DENY';
       
    70 
       
    71     /**
       
    72      * Rule operation: add
       
    73      */
       
    74     const OP_ADD = 'OP_ADD';
       
    75 
       
    76     /**
       
    77      * Rule operation: remove
       
    78      */
       
    79     const OP_REMOVE = 'OP_REMOVE';
       
    80 
       
    81     /**
       
    82      * Role registry
       
    83      *
       
    84      * @var Zend_Acl_Role_Registry
       
    85      */
       
    86     protected $_roleRegistry = null;
       
    87 
       
    88     /**
       
    89      * Resource tree
       
    90      *
       
    91      * @var array
       
    92      */
       
    93     protected $_resources = array();
       
    94 
       
    95     /**
       
    96      * @var Zend_Acl_Role_Interface
       
    97      */
       
    98     protected $_isAllowedRole     = null;
       
    99 
       
   100     /**
       
   101      * @var Zend_Acl_Resource_Interface
       
   102      */
       
   103     protected $_isAllowedResource = null;
       
   104 
       
   105     /**
       
   106      * @var String
       
   107      */
       
   108     protected $_isAllowedPrivilege = null;
       
   109 
       
   110     /**
       
   111      * ACL rules; whitelist (deny everything to all) by default
       
   112      *
       
   113      * @var array
       
   114      */
       
   115     protected $_rules = array(
       
   116         'allResources' => array(
       
   117             'allRoles' => array(
       
   118                 'allPrivileges' => array(
       
   119                     'type'   => self::TYPE_DENY,
       
   120                     'assert' => null
       
   121                     ),
       
   122                 'byPrivilegeId' => array()
       
   123                 ),
       
   124             'byRoleId' => array()
       
   125             ),
       
   126         'byResourceId' => array()
       
   127         );
       
   128 
       
   129     /**
       
   130      * Adds a Role having an identifier unique to the registry
       
   131      *
       
   132      * The $parents parameter may be a reference to, or the string identifier for,
       
   133      * a Role existing in the registry, or $parents may be passed as an array of
       
   134      * these - mixing string identifiers and objects is ok - to indicate the Roles
       
   135      * from which the newly added Role will directly inherit.
       
   136      *
       
   137      * In order to resolve potential ambiguities with conflicting rules inherited
       
   138      * from different parents, the most recently added parent takes precedence over
       
   139      * parents that were previously added. In other words, the first parent added
       
   140      * will have the least priority, and the last parent added will have the
       
   141      * highest priority.
       
   142      *
       
   143      * @param  Zend_Acl_Role_Interface              $role
       
   144      * @param  Zend_Acl_Role_Interface|string|array $parents
       
   145      * @uses   Zend_Acl_Role_Registry::add()
       
   146      * @return Zend_Acl Provides a fluent interface
       
   147      */
       
   148     public function addRole($role, $parents = null)
       
   149     {
       
   150         if (is_string($role)) {
       
   151             $role = new Zend_Acl_Role($role);
       
   152         }
       
   153 
       
   154         if (!$role instanceof Zend_Acl_Role_Interface) {
       
   155             require_once 'Zend/Acl/Exception.php';
       
   156             throw new Zend_Acl_Exception('addRole() expects $role to be of type Zend_Acl_Role_Interface');
       
   157         }
       
   158 
       
   159 
       
   160         $this->_getRoleRegistry()->add($role, $parents);
       
   161 
       
   162         return $this;
       
   163     }
       
   164 
       
   165     /**
       
   166      * Returns the identified Role
       
   167      *
       
   168      * The $role parameter can either be a Role or Role identifier.
       
   169      *
       
   170      * @param  Zend_Acl_Role_Interface|string $role
       
   171      * @uses   Zend_Acl_Role_Registry::get()
       
   172      * @return Zend_Acl_Role_Interface
       
   173      */
       
   174     public function getRole($role)
       
   175     {
       
   176         return $this->_getRoleRegistry()->get($role);
       
   177     }
       
   178 
       
   179     /**
       
   180      * Returns true if and only if the Role exists in the registry
       
   181      *
       
   182      * The $role parameter can either be a Role or a Role identifier.
       
   183      *
       
   184      * @param  Zend_Acl_Role_Interface|string $role
       
   185      * @uses   Zend_Acl_Role_Registry::has()
       
   186      * @return boolean
       
   187      */
       
   188     public function hasRole($role)
       
   189     {
       
   190         return $this->_getRoleRegistry()->has($role);
       
   191     }
       
   192 
       
   193     /**
       
   194      * Returns true if and only if $role inherits from $inherit
       
   195      *
       
   196      * Both parameters may be either a Role or a Role identifier. If
       
   197      * $onlyParents is true, then $role must inherit directly from
       
   198      * $inherit in order to return true. By default, this method looks
       
   199      * through the entire inheritance DAG to determine whether $role
       
   200      * inherits from $inherit through its ancestor Roles.
       
   201      *
       
   202      * @param  Zend_Acl_Role_Interface|string $role
       
   203      * @param  Zend_Acl_Role_Interface|string $inherit
       
   204      * @param  boolean                        $onlyParents
       
   205      * @uses   Zend_Acl_Role_Registry::inherits()
       
   206      * @return boolean
       
   207      */
       
   208     public function inheritsRole($role, $inherit, $onlyParents = false)
       
   209     {
       
   210         return $this->_getRoleRegistry()->inherits($role, $inherit, $onlyParents);
       
   211     }
       
   212 
       
   213     /**
       
   214      * Removes the Role from the registry
       
   215      *
       
   216      * The $role parameter can either be a Role or a Role identifier.
       
   217      *
       
   218      * @param  Zend_Acl_Role_Interface|string $role
       
   219      * @uses   Zend_Acl_Role_Registry::remove()
       
   220      * @return Zend_Acl Provides a fluent interface
       
   221      */
       
   222     public function removeRole($role)
       
   223     {
       
   224         $this->_getRoleRegistry()->remove($role);
       
   225 
       
   226         if ($role instanceof Zend_Acl_Role_Interface) {
       
   227             $roleId = $role->getRoleId();
       
   228         } else {
       
   229             $roleId = $role;
       
   230         }
       
   231 
       
   232         foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) {
       
   233             if ($roleId === $roleIdCurrent) {
       
   234                 unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]);
       
   235             }
       
   236         }
       
   237         foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) {
       
   238             if (array_key_exists('byRoleId', $visitor)) {
       
   239                 foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) {
       
   240                     if ($roleId === $roleIdCurrent) {
       
   241                         unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]);
       
   242                     }
       
   243                 }
       
   244             }
       
   245         }
       
   246 
       
   247         return $this;
       
   248     }
       
   249 
       
   250     /**
       
   251      * Removes all Roles from the registry
       
   252      *
       
   253      * @uses   Zend_Acl_Role_Registry::removeAll()
       
   254      * @return Zend_Acl Provides a fluent interface
       
   255      */
       
   256     public function removeRoleAll()
       
   257     {
       
   258         $this->_getRoleRegistry()->removeAll();
       
   259 
       
   260         foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) {
       
   261             unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]);
       
   262         }
       
   263         foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) {
       
   264             foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) {
       
   265                 unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]);
       
   266             }
       
   267         }
       
   268 
       
   269         return $this;
       
   270     }
       
   271 
       
   272     /**
       
   273      * Adds a Resource having an identifier unique to the ACL
       
   274      *
       
   275      * The $parent parameter may be a reference to, or the string identifier for,
       
   276      * the existing Resource from which the newly added Resource will inherit.
       
   277      *
       
   278      * @param  Zend_Acl_Resource_Interface|string $resource
       
   279      * @param  Zend_Acl_Resource_Interface|string $parent
       
   280      * @throws Zend_Acl_Exception
       
   281      * @return Zend_Acl Provides a fluent interface
       
   282      */
       
   283     public function addResource($resource, $parent = null)
       
   284     {
       
   285         if (is_string($resource)) {
       
   286             $resource = new Zend_Acl_Resource($resource);
       
   287         }
       
   288 
       
   289         if (!$resource instanceof Zend_Acl_Resource_Interface) {
       
   290             require_once 'Zend/Acl/Exception.php';
       
   291             throw new Zend_Acl_Exception('addResource() expects $resource to be of type Zend_Acl_Resource_Interface');
       
   292         }
       
   293 
       
   294         $resourceId = $resource->getResourceId();
       
   295 
       
   296         if ($this->has($resourceId)) {
       
   297             require_once 'Zend/Acl/Exception.php';
       
   298             throw new Zend_Acl_Exception("Resource id '$resourceId' already exists in the ACL");
       
   299         }
       
   300 
       
   301         $resourceParent = null;
       
   302 
       
   303         if (null !== $parent) {
       
   304             try {
       
   305                 if ($parent instanceof Zend_Acl_Resource_Interface) {
       
   306                     $resourceParentId = $parent->getResourceId();
       
   307                 } else {
       
   308                     $resourceParentId = $parent;
       
   309                 }
       
   310                 $resourceParent = $this->get($resourceParentId);
       
   311             } catch (Zend_Acl_Exception $e) {
       
   312                 require_once 'Zend/Acl/Exception.php';
       
   313                 throw new Zend_Acl_Exception("Parent Resource id '$resourceParentId' does not exist", 0, $e);
       
   314             }
       
   315             $this->_resources[$resourceParentId]['children'][$resourceId] = $resource;
       
   316         }
       
   317 
       
   318         $this->_resources[$resourceId] = array(
       
   319             'instance' => $resource,
       
   320             'parent'   => $resourceParent,
       
   321             'children' => array()
       
   322             );
       
   323 
       
   324         return $this;
       
   325     }
       
   326 
       
   327     /**
       
   328      * Adds a Resource having an identifier unique to the ACL
       
   329      *
       
   330      * The $parent parameter may be a reference to, or the string identifier for,
       
   331      * the existing Resource from which the newly added Resource will inherit.
       
   332      *
       
   333      * @deprecated in version 1.9.1 and will be available till 2.0.  New code
       
   334      *             should use addResource() instead.
       
   335      *
       
   336      * @param  Zend_Acl_Resource_Interface        $resource
       
   337      * @param  Zend_Acl_Resource_Interface|string $parent
       
   338      * @throws Zend_Acl_Exception
       
   339      * @return Zend_Acl Provides a fluent interface
       
   340      */
       
   341     public function add(Zend_Acl_Resource_Interface $resource, $parent = null)
       
   342     {
       
   343         return $this->addResource($resource, $parent);
       
   344     }
       
   345 
       
   346     /**
       
   347      * Returns the identified Resource
       
   348      *
       
   349      * The $resource parameter can either be a Resource or a Resource identifier.
       
   350      *
       
   351      * @param  Zend_Acl_Resource_Interface|string $resource
       
   352      * @throws Zend_Acl_Exception
       
   353      * @return Zend_Acl_Resource_Interface
       
   354      */
       
   355     public function get($resource)
       
   356     {
       
   357         if ($resource instanceof Zend_Acl_Resource_Interface) {
       
   358             $resourceId = $resource->getResourceId();
       
   359         } else {
       
   360             $resourceId = (string) $resource;
       
   361         }
       
   362 
       
   363         if (!$this->has($resource)) {
       
   364             require_once 'Zend/Acl/Exception.php';
       
   365             throw new Zend_Acl_Exception("Resource '$resourceId' not found");
       
   366         }
       
   367 
       
   368         return $this->_resources[$resourceId]['instance'];
       
   369     }
       
   370 
       
   371     /**
       
   372      * Returns true if and only if the Resource exists in the ACL
       
   373      *
       
   374      * The $resource parameter can either be a Resource or a Resource identifier.
       
   375      *
       
   376      * @param  Zend_Acl_Resource_Interface|string $resource
       
   377      * @return boolean
       
   378      */
       
   379     public function has($resource)
       
   380     {
       
   381         if ($resource instanceof Zend_Acl_Resource_Interface) {
       
   382             $resourceId = $resource->getResourceId();
       
   383         } else {
       
   384             $resourceId = (string) $resource;
       
   385         }
       
   386 
       
   387         return isset($this->_resources[$resourceId]);
       
   388     }
       
   389 
       
   390     /**
       
   391      * Returns true if and only if $resource inherits from $inherit
       
   392      *
       
   393      * Both parameters may be either a Resource or a Resource identifier. If
       
   394      * $onlyParent is true, then $resource must inherit directly from
       
   395      * $inherit in order to return true. By default, this method looks
       
   396      * through the entire inheritance tree to determine whether $resource
       
   397      * inherits from $inherit through its ancestor Resources.
       
   398      *
       
   399      * @param  Zend_Acl_Resource_Interface|string $resource
       
   400      * @param  Zend_Acl_Resource_Interface|string $inherit
       
   401      * @param  boolean                            $onlyParent
       
   402      * @throws Zend_Acl_Resource_Registry_Exception
       
   403      * @return boolean
       
   404      */
       
   405     public function inherits($resource, $inherit, $onlyParent = false)
       
   406     {
       
   407         try {
       
   408             $resourceId     = $this->get($resource)->getResourceId();
       
   409             $inheritId = $this->get($inherit)->getResourceId();
       
   410         } catch (Zend_Acl_Exception $e) {
       
   411             require_once 'Zend/Acl/Exception.php';
       
   412             throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e);
       
   413         }
       
   414 
       
   415         if (null !== $this->_resources[$resourceId]['parent']) {
       
   416             $parentId = $this->_resources[$resourceId]['parent']->getResourceId();
       
   417             if ($inheritId === $parentId) {
       
   418                 return true;
       
   419             } else if ($onlyParent) {
       
   420                 return false;
       
   421             }
       
   422         } else {
       
   423             return false;
       
   424         }
       
   425 
       
   426         while (null !== $this->_resources[$parentId]['parent']) {
       
   427             $parentId = $this->_resources[$parentId]['parent']->getResourceId();
       
   428             if ($inheritId === $parentId) {
       
   429                 return true;
       
   430             }
       
   431         }
       
   432 
       
   433         return false;
       
   434     }
       
   435 
       
   436     /**
       
   437      * Removes a Resource and all of its children
       
   438      *
       
   439      * The $resource parameter can either be a Resource or a Resource identifier.
       
   440      *
       
   441      * @param  Zend_Acl_Resource_Interface|string $resource
       
   442      * @throws Zend_Acl_Exception
       
   443      * @return Zend_Acl Provides a fluent interface
       
   444      */
       
   445     public function remove($resource)
       
   446     {
       
   447         try {
       
   448             $resourceId = $this->get($resource)->getResourceId();
       
   449         } catch (Zend_Acl_Exception $e) {
       
   450             require_once 'Zend/Acl/Exception.php';
       
   451             throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e);
       
   452         }
       
   453 
       
   454         $resourcesRemoved = array($resourceId);
       
   455         if (null !== ($resourceParent = $this->_resources[$resourceId]['parent'])) {
       
   456             unset($this->_resources[$resourceParent->getResourceId()]['children'][$resourceId]);
       
   457         }
       
   458         foreach ($this->_resources[$resourceId]['children'] as $childId => $child) {
       
   459             $this->remove($childId);
       
   460             $resourcesRemoved[] = $childId;
       
   461         }
       
   462 
       
   463         foreach ($resourcesRemoved as $resourceIdRemoved) {
       
   464             foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) {
       
   465                 if ($resourceIdRemoved === $resourceIdCurrent) {
       
   466                     unset($this->_rules['byResourceId'][$resourceIdCurrent]);
       
   467                 }
       
   468             }
       
   469         }
       
   470 
       
   471         unset($this->_resources[$resourceId]);
       
   472 
       
   473         return $this;
       
   474     }
       
   475 
       
   476     /**
       
   477      * Removes all Resources
       
   478      *
       
   479      * @return Zend_Acl Provides a fluent interface
       
   480      */
       
   481     public function removeAll()
       
   482     {
       
   483         foreach ($this->_resources as $resourceId => $resource) {
       
   484             foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) {
       
   485                 if ($resourceId === $resourceIdCurrent) {
       
   486                     unset($this->_rules['byResourceId'][$resourceIdCurrent]);
       
   487                 }
       
   488             }
       
   489         }
       
   490 
       
   491         $this->_resources = array();
       
   492 
       
   493         return $this;
       
   494     }
       
   495 
       
   496     /**
       
   497      * Adds an "allow" rule to the ACL
       
   498      *
       
   499      * @param  Zend_Acl_Role_Interface|string|array     $roles
       
   500      * @param  Zend_Acl_Resource_Interface|string|array $resources
       
   501      * @param  string|array                             $privileges
       
   502      * @param  Zend_Acl_Assert_Interface                $assert
       
   503      * @uses   Zend_Acl::setRule()
       
   504      * @return Zend_Acl Provides a fluent interface
       
   505      */
       
   506     public function allow($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null)
       
   507     {
       
   508         return $this->setRule(self::OP_ADD, self::TYPE_ALLOW, $roles, $resources, $privileges, $assert);
       
   509     }
       
   510 
       
   511     /**
       
   512      * Adds a "deny" rule to the ACL
       
   513      *
       
   514      * @param  Zend_Acl_Role_Interface|string|array     $roles
       
   515      * @param  Zend_Acl_Resource_Interface|string|array $resources
       
   516      * @param  string|array                             $privileges
       
   517      * @param  Zend_Acl_Assert_Interface                $assert
       
   518      * @uses   Zend_Acl::setRule()
       
   519      * @return Zend_Acl Provides a fluent interface
       
   520      */
       
   521     public function deny($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null)
       
   522     {
       
   523         return $this->setRule(self::OP_ADD, self::TYPE_DENY, $roles, $resources, $privileges, $assert);
       
   524     }
       
   525 
       
   526     /**
       
   527      * Removes "allow" permissions from the ACL
       
   528      *
       
   529      * @param  Zend_Acl_Role_Interface|string|array     $roles
       
   530      * @param  Zend_Acl_Resource_Interface|string|array $resources
       
   531      * @param  string|array                             $privileges
       
   532      * @uses   Zend_Acl::setRule()
       
   533      * @return Zend_Acl Provides a fluent interface
       
   534      */
       
   535     public function removeAllow($roles = null, $resources = null, $privileges = null)
       
   536     {
       
   537         return $this->setRule(self::OP_REMOVE, self::TYPE_ALLOW, $roles, $resources, $privileges);
       
   538     }
       
   539 
       
   540     /**
       
   541      * Removes "deny" restrictions from the ACL
       
   542      *
       
   543      * @param  Zend_Acl_Role_Interface|string|array     $roles
       
   544      * @param  Zend_Acl_Resource_Interface|string|array $resources
       
   545      * @param  string|array                             $privileges
       
   546      * @uses   Zend_Acl::setRule()
       
   547      * @return Zend_Acl Provides a fluent interface
       
   548      */
       
   549     public function removeDeny($roles = null, $resources = null, $privileges = null)
       
   550     {
       
   551         return $this->setRule(self::OP_REMOVE, self::TYPE_DENY, $roles, $resources, $privileges);
       
   552     }
       
   553 
       
   554     /**
       
   555      * Performs operations on ACL rules
       
   556      *
       
   557      * The $operation parameter may be either OP_ADD or OP_REMOVE, depending on whether the
       
   558      * user wants to add or remove a rule, respectively:
       
   559      *
       
   560      * OP_ADD specifics:
       
   561      *
       
   562      *      A rule is added that would allow one or more Roles access to [certain $privileges
       
   563      *      upon] the specified Resource(s).
       
   564      *
       
   565      * OP_REMOVE specifics:
       
   566      *
       
   567      *      The rule is removed only in the context of the given Roles, Resources, and privileges.
       
   568      *      Existing rules to which the remove operation does not apply would remain in the
       
   569      *      ACL.
       
   570      *
       
   571      * The $type parameter may be either TYPE_ALLOW or TYPE_DENY, depending on whether the
       
   572      * rule is intended to allow or deny permission, respectively.
       
   573      *
       
   574      * The $roles and $resources parameters may be references to, or the string identifiers for,
       
   575      * existing Resources/Roles, or they may be passed as arrays of these - mixing string identifiers
       
   576      * and objects is ok - to indicate the Resources and Roles to which the rule applies. If either
       
   577      * $roles or $resources is null, then the rule applies to all Roles or all Resources, respectively.
       
   578      * Both may be null in order to work with the default rule of the ACL.
       
   579      *
       
   580      * The $privileges parameter may be used to further specify that the rule applies only
       
   581      * to certain privileges upon the Resource(s) in question. This may be specified to be a single
       
   582      * privilege with a string, and multiple privileges may be specified as an array of strings.
       
   583      *
       
   584      * If $assert is provided, then its assert() method must return true in order for
       
   585      * the rule to apply. If $assert is provided with $roles, $resources, and $privileges all
       
   586      * equal to null, then a rule having a type of:
       
   587      *
       
   588      *      TYPE_ALLOW will imply a type of TYPE_DENY, and
       
   589      *
       
   590      *      TYPE_DENY will imply a type of TYPE_ALLOW
       
   591      *
       
   592      * when the rule's assertion fails. This is because the ACL needs to provide expected
       
   593      * behavior when an assertion upon the default ACL rule fails.
       
   594      *
       
   595      * @param  string                                   $operation
       
   596      * @param  string                                   $type
       
   597      * @param  Zend_Acl_Role_Interface|string|array     $roles
       
   598      * @param  Zend_Acl_Resource_Interface|string|array $resources
       
   599      * @param  string|array                             $privileges
       
   600      * @param  Zend_Acl_Assert_Interface                $assert
       
   601      * @throws Zend_Acl_Exception
       
   602      * @uses   Zend_Acl_Role_Registry::get()
       
   603      * @uses   Zend_Acl::get()
       
   604      * @return Zend_Acl Provides a fluent interface
       
   605      */
       
   606     public function setRule($operation, $type, $roles = null, $resources = null, $privileges = null,
       
   607                             Zend_Acl_Assert_Interface $assert = null)
       
   608     {
       
   609         // ensure that the rule type is valid; normalize input to uppercase
       
   610         $type = strtoupper($type);
       
   611         if (self::TYPE_ALLOW !== $type && self::TYPE_DENY !== $type) {
       
   612             require_once 'Zend/Acl/Exception.php';
       
   613             throw new Zend_Acl_Exception("Unsupported rule type; must be either '" . self::TYPE_ALLOW . "' or '"
       
   614                                        . self::TYPE_DENY . "'");
       
   615         }
       
   616 
       
   617         // ensure that all specified Roles exist; normalize input to array of Role objects or null
       
   618         if (!is_array($roles)) {
       
   619             $roles = array($roles);
       
   620         } else if (0 === count($roles)) {
       
   621             $roles = array(null);
       
   622         }
       
   623         $rolesTemp = $roles;
       
   624         $roles = array();
       
   625         foreach ($rolesTemp as $role) {
       
   626             if (null !== $role) {
       
   627                 $roles[] = $this->_getRoleRegistry()->get($role);
       
   628             } else {
       
   629                 $roles[] = null;
       
   630             }
       
   631         }
       
   632         unset($rolesTemp);
       
   633 
       
   634         // ensure that all specified Resources exist; normalize input to array of Resource objects or null
       
   635         if ($resources !== null) {
       
   636             if (!is_array($resources)) {
       
   637                 $resources = array($resources);
       
   638             } else if (0 === count($resources)) {
       
   639                 $resources = array(null);
       
   640             }
       
   641             $resourcesTemp = $resources;
       
   642             $resources = array();
       
   643             foreach ($resourcesTemp as $resource) {
       
   644                 if (null !== $resource) {
       
   645                     $resources[] = $this->get($resource);
       
   646                 } else {
       
   647                     $resources[] = null;
       
   648                 }
       
   649             }
       
   650             unset($resourcesTemp, $resource);
       
   651         } else {
       
   652             $allResources = array(); // this might be used later if resource iteration is required
       
   653             foreach ($this->_resources as $rTarget) {
       
   654                 $allResources[] = $rTarget['instance'];
       
   655             }
       
   656             unset($rTarget);
       
   657         }
       
   658         
       
   659         // normalize privileges to array
       
   660         if (null === $privileges) {
       
   661             $privileges = array();
       
   662         } else if (!is_array($privileges)) {
       
   663             $privileges = array($privileges);
       
   664         }
       
   665 
       
   666         switch ($operation) {
       
   667 
       
   668             // add to the rules
       
   669             case self::OP_ADD:
       
   670                 if ($resources !== null) {
       
   671                     // this block will iterate the provided resources
       
   672                     foreach ($resources as $resource) {
       
   673                         foreach ($roles as $role) {
       
   674                             $rules =& $this->_getRules($resource, $role, true);
       
   675                             if (0 === count($privileges)) {
       
   676                                 $rules['allPrivileges']['type']   = $type;
       
   677                                 $rules['allPrivileges']['assert'] = $assert;
       
   678                                 if (!isset($rules['byPrivilegeId'])) {
       
   679                                     $rules['byPrivilegeId'] = array();
       
   680                                 }
       
   681                             } else {
       
   682                                 foreach ($privileges as $privilege) {
       
   683                                     $rules['byPrivilegeId'][$privilege]['type']   = $type;
       
   684                                     $rules['byPrivilegeId'][$privilege]['assert'] = $assert;
       
   685                                 }
       
   686                             }
       
   687                         }
       
   688                     }
       
   689                 } else {
       
   690                     // this block will apply to all resources in a global rule
       
   691                     foreach ($roles as $role) {
       
   692                         $rules =& $this->_getRules(null, $role, true);
       
   693                         if (0 === count($privileges)) {
       
   694                             $rules['allPrivileges']['type']   = $type;
       
   695                             $rules['allPrivileges']['assert'] = $assert;
       
   696                         } else {
       
   697                             foreach ($privileges as $privilege) {
       
   698                                 $rules['byPrivilegeId'][$privilege]['type']   = $type;
       
   699                                 $rules['byPrivilegeId'][$privilege]['assert'] = $assert;
       
   700                             }
       
   701                         }
       
   702                     }
       
   703                 }
       
   704                 break;
       
   705 
       
   706             // remove from the rules
       
   707             case self::OP_REMOVE:
       
   708                 if ($resources !== null) {
       
   709                     // this block will iterate the provided resources
       
   710                     foreach ($resources as $resource) {
       
   711                         foreach ($roles as $role) {
       
   712                             $rules =& $this->_getRules($resource, $role);
       
   713                             if (null === $rules) {
       
   714                                 continue;
       
   715                             }
       
   716                             if (0 === count($privileges)) {
       
   717                                 if (null === $resource && null === $role) {
       
   718                                     if ($type === $rules['allPrivileges']['type']) {
       
   719                                         $rules = array(
       
   720                                             'allPrivileges' => array(
       
   721                                                 'type'   => self::TYPE_DENY,
       
   722                                                 'assert' => null
       
   723                                                 ),
       
   724                                             'byPrivilegeId' => array()
       
   725                                             );
       
   726                                     }
       
   727                                     continue;
       
   728                                 }
       
   729     
       
   730                                 if (isset($rules['allPrivileges']['type']) &&
       
   731                                     $type === $rules['allPrivileges']['type'])
       
   732                                 {
       
   733                                     unset($rules['allPrivileges']);
       
   734                                 }
       
   735                             } else {
       
   736                                 foreach ($privileges as $privilege) {
       
   737                                     if (isset($rules['byPrivilegeId'][$privilege]) &&
       
   738                                         $type === $rules['byPrivilegeId'][$privilege]['type'])
       
   739                                     {
       
   740                                         unset($rules['byPrivilegeId'][$privilege]);
       
   741                                     }
       
   742                                 }
       
   743                             }
       
   744                         }
       
   745                     }
       
   746                 } else {
       
   747                     // this block will apply to all resources in a global rule
       
   748                     foreach ($roles as $role) {
       
   749                         /**
       
   750                          * since null (all resources) was passed to this setRule() call, we need
       
   751                          * clean up all the rules for the global allResources, as well as the indivually
       
   752                          * set resources (per privilege as well)
       
   753                          */ 
       
   754                         foreach (array_merge(array(null), $allResources) as $resource) {
       
   755                             $rules =& $this->_getRules($resource, $role, true);
       
   756                             if (null === $rules) {
       
   757                                 continue;
       
   758                             }
       
   759                             if (0 === count($privileges)) {
       
   760                                 if (null === $role) {
       
   761                                     if ($type === $rules['allPrivileges']['type']) {
       
   762                                         $rules = array(
       
   763                                             'allPrivileges' => array(
       
   764                                                 'type'   => self::TYPE_DENY,
       
   765                                                 'assert' => null
       
   766                                                 ),
       
   767                                             'byPrivilegeId' => array()
       
   768                                             );
       
   769                                     }
       
   770                                     continue;
       
   771                                 }
       
   772     
       
   773                                 if (isset($rules['allPrivileges']['type']) && $type === $rules['allPrivileges']['type']) {
       
   774                                     unset($rules['allPrivileges']);
       
   775                                 }
       
   776                             } else {
       
   777                                 foreach ($privileges as $privilege) {
       
   778                                     if (isset($rules['byPrivilegeId'][$privilege]) &&
       
   779                                         $type === $rules['byPrivilegeId'][$privilege]['type'])
       
   780                                     {
       
   781                                         unset($rules['byPrivilegeId'][$privilege]);
       
   782                                     }
       
   783                                 }
       
   784                             }
       
   785                         }
       
   786                     }
       
   787                 }
       
   788                 break;
       
   789 
       
   790             default:
       
   791                 require_once 'Zend/Acl/Exception.php';
       
   792                 throw new Zend_Acl_Exception("Unsupported operation; must be either '" . self::OP_ADD . "' or '"
       
   793                                            . self::OP_REMOVE . "'");
       
   794         }
       
   795 
       
   796         return $this;
       
   797     }
       
   798 
       
   799     /**
       
   800      * Returns true if and only if the Role has access to the Resource
       
   801      *
       
   802      * The $role and $resource parameters may be references to, or the string identifiers for,
       
   803      * an existing Resource and Role combination.
       
   804      *
       
   805      * If either $role or $resource is null, then the query applies to all Roles or all Resources,
       
   806      * respectively. Both may be null to query whether the ACL has a "blacklist" rule
       
   807      * (allow everything to all). By default, Zend_Acl creates a "whitelist" rule (deny
       
   808      * everything to all), and this method would return false unless this default has
       
   809      * been overridden (i.e., by executing $acl->allow()).
       
   810      *
       
   811      * If a $privilege is not provided, then this method returns false if and only if the
       
   812      * Role is denied access to at least one privilege upon the Resource. In other words, this
       
   813      * method returns true if and only if the Role is allowed all privileges on the Resource.
       
   814      *
       
   815      * This method checks Role inheritance using a depth-first traversal of the Role registry.
       
   816      * The highest priority parent (i.e., the parent most recently added) is checked first,
       
   817      * and its respective parents are checked similarly before the lower-priority parents of
       
   818      * the Role are checked.
       
   819      *
       
   820      * @param  Zend_Acl_Role_Interface|string     $role
       
   821      * @param  Zend_Acl_Resource_Interface|string $resource
       
   822      * @param  string                             $privilege
       
   823      * @uses   Zend_Acl::get()
       
   824      * @uses   Zend_Acl_Role_Registry::get()
       
   825      * @return boolean
       
   826      */
       
   827     public function isAllowed($role = null, $resource = null, $privilege = null)
       
   828     {
       
   829         // reset role & resource to null
       
   830         $this->_isAllowedRole = null;
       
   831         $this->_isAllowedResource = null;
       
   832         $this->_isAllowedPrivilege = null;
       
   833 
       
   834         if (null !== $role) {
       
   835             // keep track of originally called role
       
   836             $this->_isAllowedRole = $role;
       
   837             $role = $this->_getRoleRegistry()->get($role);
       
   838             if (!$this->_isAllowedRole instanceof Zend_Acl_Role_Interface) {
       
   839                 $this->_isAllowedRole = $role;
       
   840             }
       
   841         }
       
   842 
       
   843         if (null !== $resource) {
       
   844             // keep track of originally called resource
       
   845             $this->_isAllowedResource = $resource;
       
   846             $resource = $this->get($resource);
       
   847             if (!$this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) {
       
   848                 $this->_isAllowedResource = $resource;
       
   849             }
       
   850         }
       
   851 
       
   852         if (null === $privilege) {
       
   853             // query on all privileges
       
   854             do {
       
   855                 // depth-first search on $role if it is not 'allRoles' pseudo-parent
       
   856                 if (null !== $role && null !== ($result = $this->_roleDFSAllPrivileges($role, $resource, $privilege))) {
       
   857                     return $result;
       
   858                 }
       
   859 
       
   860                 // look for rule on 'allRoles' psuedo-parent
       
   861                 if (null !== ($rules = $this->_getRules($resource, null))) {
       
   862                     foreach ($rules['byPrivilegeId'] as $privilege => $rule) {
       
   863                         if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, null, $privilege))) {
       
   864                             return false;
       
   865                         }
       
   866                     }
       
   867                     if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) {
       
   868                         return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
       
   869                     }
       
   870                 }
       
   871 
       
   872                 // try next Resource
       
   873                 $resource = $this->_resources[$resource->getResourceId()]['parent'];
       
   874 
       
   875             } while (true); // loop terminates at 'allResources' pseudo-parent
       
   876         } else {
       
   877             $this->_isAllowedPrivilege = $privilege;
       
   878             // query on one privilege
       
   879             do {
       
   880                 // depth-first search on $role if it is not 'allRoles' pseudo-parent
       
   881                 if (null !== $role && null !== ($result = $this->_roleDFSOnePrivilege($role, $resource, $privilege))) {
       
   882                     return $result;
       
   883                 }
       
   884 
       
   885                 // look for rule on 'allRoles' pseudo-parent
       
   886                 if (null !== ($ruleType = $this->_getRuleType($resource, null, $privilege))) {
       
   887                     return self::TYPE_ALLOW === $ruleType;
       
   888                 } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) {
       
   889                     return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
       
   890                 }
       
   891 
       
   892                 // try next Resource
       
   893                 $resource = $this->_resources[$resource->getResourceId()]['parent'];
       
   894 
       
   895             } while (true); // loop terminates at 'allResources' pseudo-parent
       
   896         }
       
   897     }
       
   898 
       
   899     /**
       
   900      * Returns the Role registry for this ACL
       
   901      *
       
   902      * If no Role registry has been created yet, a new default Role registry
       
   903      * is created and returned.
       
   904      *
       
   905      * @return Zend_Acl_Role_Registry
       
   906      */
       
   907     protected function _getRoleRegistry()
       
   908     {
       
   909         if (null === $this->_roleRegistry) {
       
   910             $this->_roleRegistry = new Zend_Acl_Role_Registry();
       
   911         }
       
   912         return $this->_roleRegistry;
       
   913     }
       
   914 
       
   915     /**
       
   916      * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
       
   917      * allowing/denying $role access to all privileges upon $resource
       
   918      *
       
   919      * This method returns true if a rule is found and allows access. If a rule exists and denies access,
       
   920      * then this method returns false. If no applicable rule is found, then this method returns null.
       
   921      *
       
   922      * @param  Zend_Acl_Role_Interface     $role
       
   923      * @param  Zend_Acl_Resource_Interface $resource
       
   924      * @return boolean|null
       
   925      */
       
   926     protected function _roleDFSAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null)
       
   927     {
       
   928         $dfs = array(
       
   929             'visited' => array(),
       
   930             'stack'   => array()
       
   931             );
       
   932 
       
   933         if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) {
       
   934             return $result;
       
   935         }
       
   936 
       
   937         while (null !== ($role = array_pop($dfs['stack']))) {
       
   938             if (!isset($dfs['visited'][$role->getRoleId()])) {
       
   939                 if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) {
       
   940                     return $result;
       
   941                 }
       
   942             }
       
   943         }
       
   944 
       
   945         return null;
       
   946     }
       
   947 
       
   948     /**
       
   949      * Visits an $role in order to look for a rule allowing/denying $role access to all privileges upon $resource
       
   950      *
       
   951      * This method returns true if a rule is found and allows access. If a rule exists and denies access,
       
   952      * then this method returns false. If no applicable rule is found, then this method returns null.
       
   953      *
       
   954      * This method is used by the internal depth-first search algorithm and may modify the DFS data structure.
       
   955      *
       
   956      * @param  Zend_Acl_Role_Interface     $role
       
   957      * @param  Zend_Acl_Resource_Interface $resource
       
   958      * @param  array                  $dfs
       
   959      * @return boolean|null
       
   960      * @throws Zend_Acl_Exception
       
   961      */
       
   962     protected function _roleDFSVisitAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
       
   963                                                  &$dfs = null)
       
   964     {
       
   965         if (null === $dfs) {
       
   966             /**
       
   967              * @see Zend_Acl_Exception
       
   968              */
       
   969             require_once 'Zend/Acl/Exception.php';
       
   970             throw new Zend_Acl_Exception('$dfs parameter may not be null');
       
   971         }
       
   972 
       
   973         if (null !== ($rules = $this->_getRules($resource, $role))) {
       
   974             foreach ($rules['byPrivilegeId'] as $privilege => $rule) {
       
   975                 if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) {
       
   976                     return false;
       
   977                 }
       
   978             }
       
   979             if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) {
       
   980                 return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
       
   981             }
       
   982         }
       
   983 
       
   984         $dfs['visited'][$role->getRoleId()] = true;
       
   985         foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) {
       
   986             $dfs['stack'][] = $roleParent;
       
   987         }
       
   988 
       
   989         return null;
       
   990     }
       
   991 
       
   992     /**
       
   993      * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
       
   994      * allowing/denying $role access to a $privilege upon $resource
       
   995      *
       
   996      * This method returns true if a rule is found and allows access. If a rule exists and denies access,
       
   997      * then this method returns false. If no applicable rule is found, then this method returns null.
       
   998      *
       
   999      * @param  Zend_Acl_Role_Interface     $role
       
  1000      * @param  Zend_Acl_Resource_Interface $resource
       
  1001      * @param  string                      $privilege
       
  1002      * @return boolean|null
       
  1003      * @throws Zend_Acl_Exception
       
  1004      */
       
  1005     protected function _roleDFSOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
       
  1006                                             $privilege = null)
       
  1007     {
       
  1008         if (null === $privilege) {
       
  1009             /**
       
  1010              * @see Zend_Acl_Exception
       
  1011              */
       
  1012             require_once 'Zend/Acl/Exception.php';
       
  1013             throw new Zend_Acl_Exception('$privilege parameter may not be null');
       
  1014         }
       
  1015 
       
  1016         $dfs = array(
       
  1017             'visited' => array(),
       
  1018             'stack'   => array()
       
  1019             );
       
  1020 
       
  1021         if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) {
       
  1022             return $result;
       
  1023         }
       
  1024 
       
  1025         while (null !== ($role = array_pop($dfs['stack']))) {
       
  1026             if (!isset($dfs['visited'][$role->getRoleId()])) {
       
  1027                 if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) {
       
  1028                     return $result;
       
  1029                 }
       
  1030             }
       
  1031         }
       
  1032 
       
  1033         return null;
       
  1034     }
       
  1035 
       
  1036     /**
       
  1037      * Visits an $role in order to look for a rule allowing/denying $role access to a $privilege upon $resource
       
  1038      *
       
  1039      * This method returns true if a rule is found and allows access. If a rule exists and denies access,
       
  1040      * then this method returns false. If no applicable rule is found, then this method returns null.
       
  1041      *
       
  1042      * This method is used by the internal depth-first search algorithm and may modify the DFS data structure.
       
  1043      *
       
  1044      * @param  Zend_Acl_Role_Interface     $role
       
  1045      * @param  Zend_Acl_Resource_Interface $resource
       
  1046      * @param  string                      $privilege
       
  1047      * @param  array                       $dfs
       
  1048      * @return boolean|null
       
  1049      * @throws Zend_Acl_Exception
       
  1050      */
       
  1051     protected function _roleDFSVisitOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
       
  1052                                                 $privilege = null, &$dfs = null)
       
  1053     {
       
  1054         if (null === $privilege) {
       
  1055             /**
       
  1056              * @see Zend_Acl_Exception
       
  1057              */
       
  1058             require_once 'Zend/Acl/Exception.php';
       
  1059             throw new Zend_Acl_Exception('$privilege parameter may not be null');
       
  1060         }
       
  1061 
       
  1062         if (null === $dfs) {
       
  1063             /**
       
  1064              * @see Zend_Acl_Exception
       
  1065              */
       
  1066             require_once 'Zend/Acl/Exception.php';
       
  1067             throw new Zend_Acl_Exception('$dfs parameter may not be null');
       
  1068         }
       
  1069 
       
  1070         if (null !== ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) {
       
  1071             return self::TYPE_ALLOW === $ruleTypeOnePrivilege;
       
  1072         } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) {
       
  1073             return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
       
  1074         }
       
  1075 
       
  1076         $dfs['visited'][$role->getRoleId()] = true;
       
  1077         foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) {
       
  1078             $dfs['stack'][] = $roleParent;
       
  1079         }
       
  1080 
       
  1081         return null;
       
  1082     }
       
  1083 
       
  1084     /**
       
  1085      * Returns the rule type associated with the specified Resource, Role, and privilege
       
  1086      * combination.
       
  1087      *
       
  1088      * If a rule does not exist or its attached assertion fails, which means that
       
  1089      * the rule is not applicable, then this method returns null. Otherwise, the
       
  1090      * rule type applies and is returned as either TYPE_ALLOW or TYPE_DENY.
       
  1091      *
       
  1092      * If $resource or $role is null, then this means that the rule must apply to
       
  1093      * all Resources or Roles, respectively.
       
  1094      *
       
  1095      * If $privilege is null, then the rule must apply to all privileges.
       
  1096      *
       
  1097      * If all three parameters are null, then the default ACL rule type is returned,
       
  1098      * based on whether its assertion method passes.
       
  1099      *
       
  1100      * @param  Zend_Acl_Resource_Interface $resource
       
  1101      * @param  Zend_Acl_Role_Interface     $role
       
  1102      * @param  string                      $privilege
       
  1103      * @return string|null
       
  1104      */
       
  1105     protected function _getRuleType(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null,
       
  1106                                     $privilege = null)
       
  1107     {
       
  1108         // get the rules for the $resource and $role
       
  1109         if (null === ($rules = $this->_getRules($resource, $role))) {
       
  1110             return null;
       
  1111         }
       
  1112 
       
  1113         // follow $privilege
       
  1114         if (null === $privilege) {
       
  1115             if (isset($rules['allPrivileges'])) {
       
  1116                 $rule = $rules['allPrivileges'];
       
  1117             } else {
       
  1118                 return null;
       
  1119             }
       
  1120         } else if (!isset($rules['byPrivilegeId'][$privilege])) {
       
  1121             return null;
       
  1122         } else {
       
  1123             $rule = $rules['byPrivilegeId'][$privilege];
       
  1124         }
       
  1125 
       
  1126         // check assertion first
       
  1127         if ($rule['assert']) {
       
  1128             $assertion = $rule['assert'];
       
  1129             $assertionValue = $assertion->assert(
       
  1130                 $this,
       
  1131                 ($this->_isAllowedRole instanceof Zend_Acl_Role_Interface) ? $this->_isAllowedRole : $role,
       
  1132                 ($this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) ? $this->_isAllowedResource : $resource,
       
  1133                 $this->_isAllowedPrivilege
       
  1134                 );
       
  1135         }
       
  1136 
       
  1137         if (null === $rule['assert'] || $assertionValue) {
       
  1138             return $rule['type'];
       
  1139         } else if (null !== $resource || null !== $role || null !== $privilege) {
       
  1140             return null;
       
  1141         } else if (self::TYPE_ALLOW === $rule['type']) {
       
  1142             return self::TYPE_DENY;
       
  1143         } else {
       
  1144             return self::TYPE_ALLOW;
       
  1145         }
       
  1146     }
       
  1147 
       
  1148     /**
       
  1149      * Returns the rules associated with a Resource and a Role, or null if no such rules exist
       
  1150      *
       
  1151      * If either $resource or $role is null, this means that the rules returned are for all Resources or all Roles,
       
  1152      * respectively. Both can be null to return the default rule set for all Resources and all Roles.
       
  1153      *
       
  1154      * If the $create parameter is true, then a rule set is first created and then returned to the caller.
       
  1155      *
       
  1156      * @param  Zend_Acl_Resource_Interface $resource
       
  1157      * @param  Zend_Acl_Role_Interface     $role
       
  1158      * @param  boolean                     $create
       
  1159      * @return array|null
       
  1160      */
       
  1161     protected function &_getRules(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null,
       
  1162                                   $create = false)
       
  1163     {
       
  1164         // create a reference to null
       
  1165         $null = null;
       
  1166         $nullRef =& $null;
       
  1167 
       
  1168         // follow $resource
       
  1169         do {
       
  1170             if (null === $resource) {
       
  1171                 $visitor =& $this->_rules['allResources'];
       
  1172                 break;
       
  1173             }
       
  1174             $resourceId = $resource->getResourceId();
       
  1175             if (!isset($this->_rules['byResourceId'][$resourceId])) {
       
  1176                 if (!$create) {
       
  1177                     return $nullRef;
       
  1178                 }
       
  1179                 $this->_rules['byResourceId'][$resourceId] = array();
       
  1180             }
       
  1181             $visitor =& $this->_rules['byResourceId'][$resourceId];
       
  1182         } while (false);
       
  1183 
       
  1184 
       
  1185         // follow $role
       
  1186         if (null === $role) {
       
  1187             if (!isset($visitor['allRoles'])) {
       
  1188                 if (!$create) {
       
  1189                     return $nullRef;
       
  1190                 }
       
  1191                 $visitor['allRoles']['byPrivilegeId'] = array();
       
  1192             }
       
  1193             return $visitor['allRoles'];
       
  1194         }
       
  1195         $roleId = $role->getRoleId();
       
  1196         if (!isset($visitor['byRoleId'][$roleId])) {
       
  1197             if (!$create) {
       
  1198                 return $nullRef;
       
  1199             }
       
  1200             $visitor['byRoleId'][$roleId]['byPrivilegeId'] = array();
       
  1201             $visitor['byRoleId'][$roleId]['allPrivileges'] = array('type' => null, 'assert' => null);
       
  1202         }
       
  1203         return $visitor['byRoleId'][$roleId];
       
  1204     }
       
  1205 
       
  1206 
       
  1207     /**
       
  1208      * @return array of registered roles (Deprecated)
       
  1209      * @deprecated Deprecated since version 1.10 (December 2009)
       
  1210      */
       
  1211     public function getRegisteredRoles()
       
  1212     {
       
  1213         trigger_error('The method getRegisteredRoles() was deprecated as of '
       
  1214                     . 'version 1.0, and may be removed. You\'re encouraged '
       
  1215                     . 'to use getRoles() instead.');
       
  1216 
       
  1217         return $this->_getRoleRegistry()->getRoles();
       
  1218     }
       
  1219 
       
  1220     /**
       
  1221      * @return array of registered roles
       
  1222      */
       
  1223     public function getRoles()
       
  1224     {
       
  1225         return array_keys($this->_getRoleRegistry()->getRoles());
       
  1226     }
       
  1227 
       
  1228     /**
       
  1229      * @return array of registered resources
       
  1230      */
       
  1231     public function getResources()
       
  1232     {
       
  1233         return array_keys($this->_resources);
       
  1234     }
       
  1235     
       
  1236 }
       
  1237