Files
myep-team/src/Validator/Constraints/SeasonAssignmentValidator.php
T

64 lines
2.0 KiB
PHP

<?php
namespace App\Validator\Constraints;
use App\Config\SeasonCalendar;
use App\Repository\SeasonAssignmentRepository;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* One season assignment per teamer per season.
*
* "Once a year" was a stated fact rather than an enforced one; this is what enforces it, on
* create and on edit alike, so the teamer's season view can rely on resolving a single
* assignment.
*/
class SeasonAssignmentValidator extends ConstraintValidator
{
public function __construct(
private readonly SeasonAssignmentRepository $seasonAssignmentRepository,
private readonly SeasonCalendar $seasonCalendar,
) {
}
public function validate(mixed $value, Constraint $constraint): void
{
/** @var \App\Entity\SeasonAssignment $seasonAssignment */
$seasonAssignment = $value;
// An assignment the office has laid out but not staffed yet is a normal working state,
// and a missing start date is the create form's own problem to report.
if (null === $teamer = $seasonAssignment->getTeamer()) {
return;
}
if (null === $dateFrom = $seasonAssignment->getDateFrom()) {
return;
}
// A placement starting outside any season window belongs to no season, so there is
// nothing to be the second of.
if (null === $seasonYear = $this->seasonCalendar->seasonYearFor($dateFrom)) {
return;
}
[$windowStart, $windowEnd] = $this->seasonCalendar->windowFor($seasonYear);
$existing = $this->seasonAssignmentRepository->countInSeasonWindow(
$teamer,
$windowStart->toDateTimeImmutable(),
$windowEnd->toDateTimeImmutable(),
$seasonAssignment->getId()
);
if (0 < $existing) {
$this
->context
->buildViolation($constraint->message)
->addViolation()
;
}
}
}