<?php
namespace App\Security;
use App\Entity\Section;
use App\Entity\SectionAcl;
use App\Entity\User;
use App\Entity\UserGroup;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class SectionVoter extends Voter
{
/**
* @var EntityManagerInterface
*/
private $em;
/**
* SectionVoter constructor.
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* {@inheritdoc}
*/
protected function supports($attribute, $subject)
{
if (!in_array($attribute, SectionAcl::getPermissions())) {
return false;
}
if (!$subject instanceof Section) {
return false;
}
return true;
}
/**
* {@inheritdoc}
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
/** @var Section $section */
$section = $subject;
$user = $token->getUser();
$group = ($user instanceof User) ?
$user->getGroup() :
$this->em->getRepository(UserGroup::class)->findOneBy(['role' => UserGroup::ROLE_ANONYMOUS]);
$acl = $this->em->getRepository(SectionAcl::class)->findOneBy([
'section' => $section,
'userGroup' => $group,
]);
if (!$acl instanceof SectionAcl) {
return false;
}
switch ($attribute) {
case SectionAcl::PERMISSION_READ:
return $this->canRead($acl);
case SectionAcl::PERMISSION_READ_WRITE:
return $this->canWrite($acl);
}
throw new \LogicException("This code should not be reached.");
}
/**
* @return bool
*/
private function canRead(SectionAcl $acl): bool
{
if ($this->canWrite($acl)) {
return true;
}
return $acl->getPermission() === SectionAcl::PERMISSION_READ;
}
/**
* @return bool
*/
private function canWrite(SectionAcl $acl): bool
{
return $acl->getPermission() === SectionAcl::PERMISSION_READ_WRITE;
}
}