Lines 90.00% 18 / 20
Functions and Methods 50.00% 1 / 2
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
NoOverlappingTravelValidator 90.00% 18 / 20 50.00% 1 / 2 9.08 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 validate 89.47% 17 / 19 0.00% 0 / 1 8.07
1<?php
2
3declare(strict_types=1);
4
5namespace App\Validator;
6
7use App\Entity\TimelineEvent;
8use App\Entity\User;
9use App\Repository\TimelineEventRepository;
10use Symfony\Bundle\SecurityBundle\Security;
11use Symfony\Component\Validator\Constraint;
12use Symfony\Component\Validator\ConstraintValidator;
13use Symfony\Component\Validator\Exception\UnexpectedTypeException;
14
15/**
16 * Looks for another travel of the owner on the event's days; a new event has no owner yet (the
17 * form's controller and TimelineEventProcessor set it after validating): it is the current user's.
18 */
19final class NoOverlappingTravelValidator extends ConstraintValidator
20{
21    public function __construct(
22        private readonly TimelineEventRepository $timelineEventRepository,
23        private readonly Security $security,
24    ) {
25    }
26
27    public function validate(mixed $value, Constraint $constraint): void
28    {
29        if (!$constraint instanceof NoOverlappingTravel) {
30            throw new UnexpectedTypeException($constraint, NoOverlappingTravel::class);
31        }
32
33        if (!$value instanceof TimelineEvent || !$value->date instanceof \DateTimeImmutable || !$value->endDate instanceof \DateTimeImmutable) {
34            return;
35        }
36
37        $owner = $value->owner ?? $this->security->getUser();
38        if (!$owner instanceof User) {
39            return;
40        }
41
42        $other = $this->timelineEventRepository->findOverlappingTravel($owner, $value, $value->date, $value->endDate);
43        if (!$other instanceof TimelineEvent) {
44            return;
45        }
46
47        $this->context->buildViolation($constraint->message)
48            ->setParameter('{{ travel }}', \sprintf(
49                '%s (%s – %s)',
50                \strtok($other->text, "\n") ?: '',
51                $other->date?->format('Y-m-d'),
52                $other->endDate?->format('Y-m-d'),
53            ))
54            ->atPath('endDate')
55            ->addViolation();
56    }
57}