<?php
namespace App\Security;
use App\Entity\Alumno;
use App\Entity\Usuario;
use DateTime;
use LogicException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class AlumnoVoter extends Voter
{
public const PUEDE_VER = 'VER_ALUMNO';
public const VER_SEGUIMIENTO = 'VER_SEGUIMIENTO';
public const PUEDE_HACER_TEST_EVALUACION = 'PUEDE_HACER_TEST_EVALUACION';
public const PUEDE_SOLICITAR_BECA = 'PUEDE_SOLICITAR_BECA';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, $subject): bool
{
if (!in_array($attribute, [self::PUEDE_VER, self::VER_SEGUIMIENTO, self::PUEDE_HACER_TEST_EVALUACION, self::PUEDE_SOLICITAR_BECA])) {
return false;
}
if (!$subject instanceof Alumno) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
/** @var Usuario $user */
$user = $token->getUser();
if (!$user) {
return false;
}
/** @var Alumno $alumno */
$alumno = $subject;
switch ($attribute) {
case self::PUEDE_VER:
return $this->puedeVer($alumno, $user);
case self::VER_SEGUIMIENTO:
return $this->verSeguimiento($alumno, $user);
case self::PUEDE_HACER_TEST_EVALUACION:
return $this->puedeHacerTestEvaluacion($alumno, $user);
case self::PUEDE_SOLICITAR_BECA:
return $this->puedeSolicitarBeca($alumno, $user);
}
throw new LogicException('This code should not be reached!');
}
// Comprobamos si la solicitud está marcada como "borrada", y si el estado de la solicitud está en borrador.
private function estaBorrado(Alumno $alumno): bool
{
// Si esta marcada como "borrada" o su estado es "borrador".
if ($alumno->getSolicitud()->isBorrado() || $alumno->getSolicitud()->getEstado()->getId() === 4) {
return false;
}
return true;
}
// Comprobamos si está marcado como "borrado", y si es formador que el alumno pertenezca a un curso de su empresa.
private function puedeVer(Alumno $alumno, Usuario $user): bool
{
if (!$this->estaBorrado($alumno)) {
return false;
}
// Si es formador e intenta ver un alumno que no es de un curso de su empresa.
if (!$this->security->isGranted('ROLE_ADMIN') &&
$this->security->isGranted('ROLE_FORMADOR') &&
$alumno->getSolicitud()->getUsuario()->getEmpresaFormacion() !== $user->getEmpresaFormacion()) {
return false;
}
return true;
}
// Comprueba si se puede ver un seguimiento para el alumno. Retorna `true` si la fecha de llamada del mes del alumno ya ha llegado
// o ha pasado respecto al momento actual. Retorna `false` si no hay fecha de llamada definida o si aún no se ha alcanzado.
private function verSeguimiento(Alumno $alumno, Usuario $user): bool
{
if (!$this->puedeVer($alumno, $user)) {
return false;
}
$now = new DateTime();
if (!$alumno->getFechaLlamadaMes() || ($now < $alumno->getFechaLlamadaMes())) {
return false;
}
return true;
}
// Comprueba si un alumno puede hacer un test de evaluación.
private function puedeHacerTestEvaluacion(Alumno $alumno, Usuario $user): bool
{
// Si el usuario logueado intenta hacer un test que no le corresponde.
if ($user !== $alumno->getSolicitud()->getUsuario()) {
return false;
}
// Si tiene la solicitud borrada o en estado borrador.
if (!$this->estaBorrado($alumno)) {
return false;
}
// Si ya tiene el test hecho o el alumno se encuentra en estado a "Baja".
if ($alumno->getTestEvaluacion() || $alumno->getEstado()->getId() === 3) {
return false;
}
return true;
}
// Comprueba si un alumno puede solicitar una beca.
private function puedeSolicitarBeca(Alumno $alumno, Usuario $user): bool
{
// Si el usuario logueado intenta solicitar una beca siendo otro alumno.
if ($user !== $alumno->getSolicitud()->getUsuario()) {
return false;
}
// Si tiene la solicitud borrada o en estado borrador.
if (!$this->estaBorrado($alumno)) {
return false;
}
// Si no tiene test de evaluación, no hay fecha max. definida o la fecha de la solicitud ya ha pasado.
$now = new DateTime();
$fechaMaximaSolicitudBeca = $alumno->getSolicitud()->getCurso()->getFechaMaximaSolicitudBeca();
if ($alumno->getSolicitudBeca() || !$alumno->getTestEvaluacion() || !$fechaMaximaSolicitudBeca || $now >= $fechaMaximaSolicitudBeca) {
return false;
}
return true;
}
}