voterHelper = $voterHelperFactory ->generate(self::class) ->addCheckFor(AccompanyingPeriod::class, [self::SEE, self::CREATE]) ->addCheckFor(Person::class, [self::SEE, self::CREATE]) ->addCheckFor(Calendar::class, [self::SEE, self::CREATE, self::EDIT, self::DELETE]) ->build(); } public function getRoles(): array { return [ self::CREATE, self::DELETE, self::EDIT, self::SEE, ]; } public function getRolesWithHierarchy(): array { return ['Calendar' => $this->getRoles()]; } public function getRolesWithoutScope(): array { return [ self::CREATE, self::DELETE, self::EDIT, self::SEE, ]; } protected function supports($attribute, $subject): bool { return $this->voterHelper->supports($attribute, $subject); } protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool { if ($subject instanceof AccompanyingPeriod) { switch ($attribute) { case self::SEE: case self::CREATE: if (AccompanyingPeriod::STEP_DRAFT === $subject->getStep()) { return false; } // we first check here that the user has read access to the period if (!$this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject)) { return false; } // There is no scope on Calendar, but there are some on accompanying period // so, to ignore AccompanyingPeriod's scopes, we create a blank Calendar // linked with an accompanying period. return $this->voterHelper->voteOnAttribute($attribute, (new Calendar())->setAccompanyingPeriod($subject), $token); } } elseif ($subject instanceof Person) { switch ($attribute) { case self::SEE: case self::CREATE: return $this->voterHelper->voteOnAttribute($attribute, $subject, $token); } } elseif ($subject instanceof Calendar) { switch ($attribute) { case self::SEE: case self::EDIT: case self::CREATE: case self::DELETE: return $this->voterHelper->voteOnAttribute($attribute, $subject, $token); } } throw new \LogicException('attribute or not implemented'); } }