<?php
namespace App\ApiPlatform\Voter;
use App\Entity\Section;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class SectionVoter extends Voter
{
public const CREATE = 'CREATE';
public const EDIT = 'EDIT';
public const DELETE = 'DELETE';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, $subject): bool
{
if (!$subject instanceof Section) {
return false;
}
return in_array($attribute, [self::CREATE, self::EDIT, self::DELETE]);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
if ($user->isMasterAdmin()) {
return true;
}
switch ($attribute) {
case self::CREATE:
return $this->canCreate($user, $subject);
case self::EDIT:
case self::DELETE:
return $this->canEditOrDelete($user, $subject);
}
return false;
}
private function canCreate(User $user, Section $section): bool
{
// For section creation, check if the user has access to any of the sites
// that the parent document is affectated to
if (!$section->getDocument() || $section->getDocument()->getAffectations()->isEmpty()) {
return false;
}
$userSiteIds = [];
foreach ($user->getUserSites() as $userSite) {
$userSiteIds[] = $userSite->getSite()->getId();
}
foreach ($section->getDocument()->getAffectations() as $affectation) {
if (!$affectation->getSite()) {
continue;
}
if (in_array($affectation->getSite()->getId(), $userSiteIds)) {
return true;
}
}
return false;
}
private function canEditOrDelete(User $user, Section $section): bool
{
// For edit/delete, check if the user has access to any of the sites
// that the parent document is affectated to
if (!$section->getDocument() || $section->getDocument()->getAffectations()->isEmpty()) {
return false;
}
$userSiteIds = [];
foreach ($user->getUserSites() as $userSite) {
$userSiteIds[] = $userSite->getSite()->getId();
}
foreach ($section->getDocument()->getAffectations() as $affectation) {
if (!$affectation->getSite()) {
continue;
}
if (in_array($affectation->getSite()->getId(), $userSiteIds)) {
return true;
}
}
return false;
}
}