@@ -35,15 +35,44 @@ The Voter Interface
35
35
-------------------
36
36
37
37
A custom voter needs to implement
38
- :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ VoterInterface `
38
+ :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ VoterInterface `, :class: ` Symfony \\ Component \\ Security \\ Core \\ Authorization \\ Voter \\ CacheableVoterInterface `
39
39
or extend :class: `Symfony\\ Component\\ Security\\ Core\\ Authorization\\ Voter\\ Voter `,
40
40
which makes creating a voter even easier::
41
41
42
42
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
43
43
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
44
44
45
- abstract class Voter implements VoterInterface
45
+ abstract class Voter implements VoterInterface, CacheableVoterInterface
46
46
{
47
+ public function vote(TokenInterface $token, mixed $subject, array $attributes): int
48
+ {
49
+ // abstain vote by default in case none of the attributes are supported
50
+ $vote = self::ACCESS_ABSTAIN;
51
+
52
+ foreach ($attributes as $attribute) {
53
+ try {
54
+ if (!$this->supports($attribute, $subject)) {
55
+ continue;
56
+ }
57
+ } catch (\TypeError $e) {
58
+ if (str_contains($e->getMessage(), 'supports(): Argument #1')) {
59
+ continue;
60
+ }
61
+
62
+ throw $e;
63
+ }
64
+
65
+ // as soon as at least one attribute is supported, default is to deny access
66
+ $vote = self::ACCESS_DENIED;
67
+
68
+ if ($this->voteOnAttribute($attribute, $subject, $token)) {
69
+ // grant access as soon as at least one attribute returns a positive response
70
+ return self::ACCESS_GRANTED;
71
+ }
72
+ }
73
+
74
+ return $vote;
75
+ }
47
76
abstract protected function supports(string $attribute, mixed $subject): bool;
48
77
abstract protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool;
49
78
}
0 commit comments