From 4ec80b1ae8d8026e05246c57ca23e283dd29f9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Vasseur?= Date: Wed, 1 Mar 2017 16:05:29 +0100 Subject: [PATCH] Use IteratorArgument for voters --- UPGRADE-3.3.md | 2 ++ UPGRADE-4.0.md | 2 ++ .../Compiler/AddSecurityVotersPass.php | 5 +++-- .../Compiler/AddSecurityVotersPassTest.php | 4 ++-- src/Symfony/Component/Security/CHANGELOG.md | 5 +++++ .../Authorization/AccessDecisionManager.php | 20 ++++++++++--------- .../TraceableAccessDecisionManager.php | 11 ++++++++-- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 5a8b44f1d8..f6e6fdcf63 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -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 -------------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 06edd2cde2..ab63496b30 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -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 -------------- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php index 898d38ef87..e907b7d567 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php @@ -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)); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php index af7933a36e..66d6bde205 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php @@ -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); diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 6bebfba400..20cb160555 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -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 ----- diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index e40d90664c..431597940d 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -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) { diff --git a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php index 6ba2cab1a1..f07f117eec 100644 --- a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php @@ -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() {