Skip to content

Commit 5bb4dd4

Browse files
committed
Rewrote logic of AbstractVoter
1 parent 8a9a1e5 commit 5bb4dd4

File tree

3 files changed

+143
-4
lines changed

3 files changed

+143
-4
lines changed

src/Symfony/Component/Security/Core/Authorization/Voter/AbstractVoter.php

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ abstract class AbstractVoter implements VoterInterface
2626
*/
2727
public function supportsAttribute($attribute)
2828
{
29+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
30+
2931
return in_array($attribute, $this->getSupportedAttributes());
3032
}
3133

@@ -34,6 +36,8 @@ public function supportsAttribute($attribute)
3436
*/
3537
public function supportsClass($class)
3638
{
39+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
40+
3741
foreach ($this->getSupportedClasses() as $supportedClass) {
3842
if ($supportedClass === $class || is_subclass_of($class, $supportedClass)) {
3943
return true;
@@ -58,15 +62,16 @@ public function supportsClass($class)
5862
*/
5963
public function vote(TokenInterface $token, $object, array $attributes)
6064
{
61-
if (!$object || !$this->supportsClass(get_class($object))) {
65+
if (!$object) {
6266
return self::ACCESS_ABSTAIN;
6367
}
6468

6569
// abstain vote by default in case none of the attributes are supported
6670
$vote = self::ACCESS_ABSTAIN;
71+
$class = get_class($object);
6772

6873
foreach ($attributes as $attribute) {
69-
if (!$this->supportsAttribute($attribute)) {
74+
if (!$this->supports($attribute, $class)) {
7075
continue;
7176
}
7277

@@ -82,19 +87,57 @@ public function vote(TokenInterface $token, $object, array $attributes)
8287
return $vote;
8388
}
8489

90+
protected function supports($attribute, $class)
91+
{
92+
@trigger_error('The getSupportedClasses and getSupportedAttributes methods are deprecated since version 2.8 and will be removed in version 3.0. Overwrite supports instead.');
93+
94+
$classIsSupported = false;
95+
foreach ($this->getSupportedClasses() as $supportedClass) {
96+
if ($this->isClassInstanceOf($class, $supportedClass)) {
97+
$classIsSupported = true;
98+
break;
99+
}
100+
}
101+
102+
if (!$classIsSupported) {
103+
return false;
104+
}
105+
106+
if (!in_array($attribute, $this->getSupportedAttributes())) {
107+
return false;
108+
}
109+
110+
return true;
111+
}
112+
113+
protected function isClassInstanceOf($actualClass, $expectedClass)
114+
{
115+
return $expectedClass === $actualClass || is_subclass_of($actualClass, $expectedClass);
116+
}
117+
85118
/**
86119
* Return an array of supported classes. This will be called by supportsClass
87120
*
88121
* @return array an array of supported classes, i.e. array('Acme\DemoBundle\Model\Product')
122+
*
123+
* @deprecated since version 2.8, to be removed in 3.0. Use supports() instead.
89124
*/
90-
abstract protected function getSupportedClasses();
125+
protected function getSupportedClasses()
126+
{
127+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
128+
}
91129

92130
/**
93131
* Return an array of supported attributes. This will be called by supportsAttribute
94132
*
95133
* @return array an array of supported attributes, i.e. array('CREATE', 'READ')
134+
*
135+
* @deprecated since version 2.8, to be removed in 3.0. Use supports() instead.
96136
*/
97-
abstract protected function getSupportedAttributes();
137+
protected function getSupportedAttributes()
138+
{
139+
@trigger_error('The '.__METHOD__.' is deprecated since version 2.8 and will be removed in version 3.0.');
140+
}
98141

99142
/**
100143
* Perform a single access check operation on a given attribute, object and (optionally) user
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
4+
5+
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
6+
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
7+
use Symfony\Component\Security\Core\User\UserInterface;
8+
9+
class AbstractVoterTest_Voter extends AbstractVoter
10+
{
11+
protected function isGranted($attribute, $object, $user = null)
12+
{
13+
return 'EDIT' === $attribute;
14+
}
15+
16+
protected function supports($attribute, $class)
17+
{
18+
return $this->isClassInstanceOf($class, 'AbstractVoterTest_Object')
19+
&& in_array($attribute, array('EDIT', 'CREATE'));
20+
}
21+
}
22+
23+
class AbstractVoterTest extends \PHPUnit_Framework_TestCase
24+
{
25+
protected $voter;
26+
protected $object;
27+
protected $token;
28+
29+
protected function setUp()
30+
{
31+
$this->voter = new AbstractVoterTest_Voter();
32+
$this->object = $this->getMock('AbstractVoterTest_Object');
33+
$this->token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface');
34+
}
35+
36+
public function testAttributeAndClassSupported()
37+
{
38+
$this->assertEquals(VoterInterface::ACCESS_GRANTED, $this->voter->vote($this->token, $this->object, array('EDIT')));
39+
$this->assertEquals(VoterInterface::ACCESS_DENIED, $this->voter->vote($this->token, $this->object, array('CREATE')));
40+
}
41+
42+
public function testAttributeNotSupported()
43+
{
44+
$this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, $this->object, array('DELETE')));
45+
}
46+
47+
public function testOneAttributeSupported()
48+
{
49+
$this->assertEquals(VoterInterface::ACCESS_GRANTED, $this->voter->vote($this->token, $this->object, array('DELETE', 'EDIT')));
50+
$this->assertEquals(VoterInterface::ACCESS_DENIED, $this->voter->vote($this->token, $this->object, array('DELETE', 'CREATE')));
51+
}
52+
53+
public function testClassNotSupported()
54+
{
55+
$this->assertEquals(VoterInterface::ACCESS_ABSTAIN, $this->voter->vote($this->token, $this->getMock('AbstractVoterTest_Object1'), array('EDIT')));
56+
}
57+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Symfony\Component\Security\Core\Tests\Authorization\Voter;
4+
5+
use Symfony\Component\Security\Core\Authorization\Voter\AbstractVoter;
6+
7+
class LegacyAbstractVoterTest_Voter extends AbstractVoter
8+
{
9+
protected function getSupportedClasses()
10+
{
11+
return array('AbstractVoterTest_Object');
12+
}
13+
14+
/**
15+
* @inheritDoc
16+
*/
17+
protected function getSupportedAttributes()
18+
{
19+
return array('EDIT', 'CREATE');
20+
}
21+
22+
/**
23+
* @inheritDoc
24+
*/
25+
protected function isGranted($attribute, $object, $user = null)
26+
{
27+
return 'EDIT' === $attribute;
28+
}
29+
}
30+
31+
class LegacyAbstractVoterTest extends AbstractVoterTest
32+
{
33+
protected function setUp()
34+
{
35+
parent::setUp();
36+
37+
$this->voter = new LegacyAbstractVoterTest_Voter();
38+
}
39+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy