Use IteratorArgument for voters

This commit is contained in:
Jérôme Vasseur 2017-03-01 16:05:29 +01:00
parent 4a5f22bc1e
commit 4ec80b1ae8
7 changed files with 34 additions and 15 deletions

View File

@ -258,6 +258,8 @@ Security
* The `LogoutUrlGenerator::registerListener()` method will expect a 6th `$context = null` argument in 4.0.
Define the argument when overriding this method.
* The `AccessDecisionManager::setVoters()` has been deprecated. Pass the voters to the constructor instead.
SecurityBundle
--------------

View File

@ -384,6 +384,8 @@ Security
* The `LogoutUrlGenerator::registerListener()` method expects a 6th `$context = null` argument.
* The `AccessDecisionManager::setVoters()` has been removed. Pass the voters to the constructor instead.
SecurityBundle
--------------

View File

@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
@ -39,7 +40,7 @@ class AddSecurityVotersPass implements CompilerPassInterface
throw new LogicException('No security voters found. You need to tag at least one with "security.voter"');
}
$adm = $container->getDefinition($container->hasDefinition('debug.security.access.decision_manager') ? 'debug.security.access.decision_manager' : 'security.access.decision_manager');
$adm->addMethodCall('setVoters', array($voters));
$adm = $container->getDefinition('security.access.decision_manager');
$adm->replaceArgument(0, new IteratorArgument($voters));
}
}

View File

@ -59,8 +59,8 @@ class AddSecurityVotersPassTest extends TestCase
$compilerPass = new AddSecurityVotersPass();
$compilerPass->process($container);
$calls = $container->getDefinition('security.access.decision_manager')->getMethodCalls();
$refs = $calls[0][1][0];
$argument = $container->getDefinition('security.access.decision_manager')->getArgument(0);
$refs = $argument->getValues();
$this->assertEquals(new Reference('highest_prio_service'), $refs[0]);
$this->assertEquals(new Reference('lowest_prio_service'), $refs[1]);
$this->assertCount(4, $refs);

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
3.3.0
-----
* deprecated `setVoters()` of the `AccessDecisionManager` class in favor of passing the voters to the constructor.
3.2.0
-----

View File

@ -32,16 +32,14 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
private $allowIfEqualGrantedDeniedDecisions;
/**
* Constructor.
*
* @param VoterInterface[] $voters An array of VoterInterface instances
* @param string $strategy The vote strategy
* @param bool $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not
* @param bool $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals
* @param iterable|VoterInterface[] $voters An iterator of VoterInterface instances
* @param string $strategy The vote strategy
* @param bool $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not
* @param bool $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals
*
* @throws \InvalidArgumentException
*/
public function __construct(array $voters = array(), $strategy = self::STRATEGY_AFFIRMATIVE, $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
public function __construct($voters = array(), $strategy = self::STRATEGY_AFFIRMATIVE, $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
{
$strategyMethod = 'decide'.ucfirst($strategy);
if (!is_callable(array($this, $strategyMethod))) {
@ -58,9 +56,13 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
* Configures the voters.
*
* @param VoterInterface[] $voters An array of VoterInterface instances
*
* @deprecated since version 3.3, to be removed in 4.0. Pass the voters to the constructor instead.
*/
public function setVoters(array $voters)
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass the voters to the constructor instead.', __METHOD__), E_USER_DEPRECATED);
$this->voters = $voters;
}
@ -162,8 +164,8 @@ class AccessDecisionManager implements AccessDecisionManagerInterface
private function decideUnanimous(TokenInterface $token, array $attributes, $object = null)
{
$grant = 0;
foreach ($attributes as $attribute) {
foreach ($this->voters as $voter) {
foreach ($this->voters as $voter) {
foreach ($attributes as $attribute) {
$result = $voter->vote($token, $object, array($attribute));
switch ($result) {

View File

@ -33,10 +33,13 @@ class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
$this->manager = $manager;
if ($this->manager instanceof AccessDecisionManager) {
// The strategy is stored in a private property of the decorated service
// The strategy and voters are stored in a private properties of the decorated service
$reflection = new \ReflectionProperty(AccessDecisionManager::class, 'strategy');
$reflection->setAccessible(true);
$this->strategy = $reflection->getValue($manager);
$reflection = new \ReflectionProperty(AccessDecisionManager::class, 'voters');
$reflection->setAccessible(true);
$this->voters = $reflection->getValue($manager);
}
}
@ -58,9 +61,13 @@ class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
/**
* {@inheritdoc}
*
* @deprecated since version 3.3, to be removed in 4.0. Pass voters to the decorated AccessDecisionManager instead.
*/
public function setVoters(array $voters)
{
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass voters to the decorated AccessDecisionManager instead.', __METHOD__), E_USER_DEPRECATED);
if (!method_exists($this->manager, 'setVoters')) {
return;
}
@ -81,7 +88,7 @@ class TraceableAccessDecisionManager implements AccessDecisionManagerInterface
}
/**
* @return array
* @return iterable|VoterInterface[]
*/
public function getVoters()
{