Permalink
Cannot retrieve contributors at this time
<?php | |
/* | |
* This file is part of the Symfony package. | |
* | |
* (c) Fabien Potencier <fabien@symfony.com> | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
*/ | |
namespace Symfony\Component\Security\Core\Authorization; | |
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; | |
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; | |
/** | |
* AccessDecisionManager is the base class for all access decision managers | |
* that use decision voters. | |
* | |
* @author Fabien Potencier <fabien@symfony.com> | |
*/ | |
class AccessDecisionManager implements AccessDecisionManagerInterface | |
{ | |
private $voters; | |
private $strategy; | |
private $allowIfAllAbstainDecisions; | |
private $allowIfEqualGrantedDeniedDecisions; | |
/** | |
* Constructor. | |
* | |
* @param VoterInterface[] $voters An array of VoterInterface instances | |
* @param string $strategy The vote strategy | |
* @param Boolean $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not | |
* @param Boolean $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals | |
* | |
* @throws \InvalidArgumentException | |
*/ | |
public function __construct(array $voters, $strategy = 'affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true) | |
{ | |
if (!$voters) { | |
throw new \InvalidArgumentException('You must at least add one voter.'); | |
} | |
$this->voters = $voters; | |
$this->strategy = 'decide'.ucfirst($strategy); | |
$this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions; | |
$this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function decide(TokenInterface $token, array $attributes, $object = null) | |
{ | |
return $this->{$this->strategy}($token, $attributes, $object); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function supportsAttribute($attribute) | |
{ | |
foreach ($this->voters as $voter) { | |
if ($voter->supportsAttribute($attribute)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function supportsClass($class) | |
{ | |
foreach ($this->voters as $voter) { | |
if ($voter->supportsClass($class)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Grants access if any voter returns an affirmative response. | |
* | |
* If all voters abstained from voting, the decision will be based on the | |
* allowIfAllAbstainDecisions property value (defaults to false). | |
*/ | |
private function decideAffirmative(TokenInterface $token, array $attributes, $object = null) | |
{ | |
$deny = 0; | |
foreach ($this->voters as $voter) { | |
$result = $voter->vote($token, $object, $attributes); | |
switch ($result) { | |
case VoterInterface::ACCESS_GRANTED: | |
return true; | |
case VoterInterface::ACCESS_DENIED: | |
++$deny; | |
break; | |
default: | |
break; | |
} | |
} | |
if ($deny > 0) { | |
return false; | |
} | |
return $this->allowIfAllAbstainDecisions; | |
} | |
/** | |
* Grants access if there is consensus of granted against denied responses. | |
* | |
* Consensus means majority-rule (ignoring abstains) rather than unanimous | |
* agreement (ignoring abstains). If you require unanimity, see | |
* UnanimousBased. | |
* | |
* If there were an equal number of grant and deny votes, the decision will | |
* be based on the allowIfEqualGrantedDeniedDecisions property value | |
* (defaults to true). | |
* | |
* If all voters abstained from voting, the decision will be based on the | |
* allowIfAllAbstainDecisions property value (defaults to false). | |
*/ | |
private function decideConsensus(TokenInterface $token, array $attributes, $object = null) | |
{ | |
$grant = 0; | |
$deny = 0; | |
$abstain = 0; | |
foreach ($this->voters as $voter) { | |
$result = $voter->vote($token, $object, $attributes); | |
switch ($result) { | |
case VoterInterface::ACCESS_GRANTED: | |
++$grant; | |
break; | |
case VoterInterface::ACCESS_DENIED: | |
++$deny; | |
break; | |
default: | |
++$abstain; | |
break; | |
} | |
} | |
if ($grant > $deny) { | |
return true; | |
} | |
if ($deny > $grant) { | |
return false; | |
} | |
if ($grant == $deny && $grant != 0) { | |
return $this->allowIfEqualGrantedDeniedDecisions; | |
} | |
return $this->allowIfAllAbstainDecisions; | |
} | |
/** | |
* Grants access if only grant (or abstain) votes were received. | |
* | |
* If all voters abstained from voting, the decision will be based on the | |
* allowIfAllAbstainDecisions property value (defaults to false). | |
*/ | |
private function decideUnanimous(TokenInterface $token, array $attributes, $object = null) | |
{ | |
$grant = 0; | |
foreach ($attributes as $attribute) { | |
foreach ($this->voters as $voter) { | |
$result = $voter->vote($token, $object, array($attribute)); | |
switch ($result) { | |
case VoterInterface::ACCESS_GRANTED: | |
++$grant; | |
break; | |
case VoterInterface::ACCESS_DENIED: | |
return false; | |
default: | |
break; | |
} | |
} | |
} | |
// no deny votes | |
if ($grant > 0) { | |
return true; | |
} | |
return $this->allowIfAllAbstainDecisions; | |
} | |
} |