helper = $voterHelperFactory ->generate(self::class) ->addCheckFor(Center::class, [self::STATS]) ->build(); } public function getRoles(): array { return [self::STATS]; } public function getRolesWithHierarchy(): array { return ['Household' => $this->getRoles()]; } public function getRolesWithoutScope(): array { return $this->getRoles(); } protected function supports($attribute, $subject) { return ($subject instanceof Household && \in_array($attribute, self::ALL, true)) || $this->helper->supports($attribute, $subject); } protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool { return match ($attribute) { self::SEE => $this->checkAssociatedMembersRole($subject, PersonVoter::SEE), self::EDIT => $this->checkAssociatedMembersRole($subject, PersonVoter::UPDATE), self::STATS => $this->voteOnAttribute($attribute, $subject, $token), default => throw new \UnexpectedValueException('attribute not supported'), }; } private function checkAssociatedMembersRole(Household $household, string $attribute): bool { foreach ($household->getCurrentMembers()->map(static fn (HouseholdMember $member) => $member->getPerson()) as $person) { if ($this->security->isGranted($attribute, $person)) { return true; } } return false; } }