<?php
// src/Security/Voter/OccurrenceVoter.php
namespace App\Security\Voter;
use App\Entity\Occurrence;
use Menke\UserBundle\Entity\User;
use App\Repository\CourseProviderRepository;
use App\Repository\OccurrenceProviderRepository;
use App\Repository\VenueProviderRepository;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class OccurrenceVoter extends Voter
{
public const VIEW = 'OCCURRENCE_VIEW';
public const EDIT = 'OCCURRENCE_EDIT';
public const CREATE = 'OCCURRENCE_CREATE';
private $occRepo;
private $courseRepo;
private $venueRepo;
public function __construct(
OccurrenceProviderRepository $occRepo,
CourseProviderRepository $courseRepo,
VenueProviderRepository $venueRepo
) {
$this->occRepo = $occRepo;
$this->courseRepo = $courseRepo;
$this->venueRepo = $venueRepo;
}
protected function supports($attribute, $subject): bool
{
if (\in_array($attribute, [self::VIEW, self::EDIT]) && $subject instanceof Occurrence) {
return true;
}
if ($attribute === self::CREATE && ($subject === null || $subject instanceof \App\Entity\Course)) {
return true; // CREATE wird mit Course-Kontext aufgerufen
}
return false;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
if (!\in_array('ROLE_PROVIDER', $user->getRoles(), true) && !\in_array('ROLE_ADMIN', $user->getRoles(), true)) {
return false;
}
if (\in_array('ROLE_ADMIN', $user->getRoles(), true)) {
return true; // Admin darf immer
}
$provider = $user->getProvider();
if (!$provider) {
return false;
}
switch ($attribute) {
case self::CREATE:
// subject ist der Course, zu dem die Occurrence angelegt werden soll
/** @var \App\Entity\Course $course */
$course = $subject;
return $this->courseRepo->existsFor($course->getId(), $provider->getId());
case self::VIEW:
case self::EDIT:
/** @var Occurrence $occ */
$occ = $subject;
// Direkt an Occurrence?
if ($this->occRepo->existsFor($occ->getId(), $provider->getId())) return true;
// Über Course?
if ($occ->getCourse() && $this->courseRepo->existsFor($occ->getCourse()->getId(), $provider->getId())) return true;
// Über Venue?
if ($occ->getVenue() && $this->venueRepo->existsFor($occ->getVenue()->getId(), $provider->getId())) return true;
return false;
}
return false;
}
}