Passed
Push — master ( ea7d0c...20f36e )
by Marcel
09:46
created

TuitionResolvableValidator   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 37
c 1
b 0
f 0
dl 0
loc 73
rs 10
wmc 12

3 Methods

Rating   Name   Duplication   Size   Complexity  
B validate() 0 38 9
A findTuition() 0 17 2
A __construct() 0 3 1
1
<?php
2
3
namespace App\Validator;
4
5
use App\Entity\Section;
6
use App\Entity\Tuition;
7
use App\Repository\TuitionRepositoryInterface;
8
use App\Request\Data\TimetableLessonData;
9
use App\Section\SectionResolverInterface;
10
use App\Settings\ImportSettings;
11
use Symfony\Component\Validator\Constraint;
12
use Symfony\Component\Validator\ConstraintValidator;
13
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
14
15
class TuitionResolvableValidator extends ConstraintValidator {
16
17
    private array $cache = [ ];
18
19
    public function __construct(private readonly SectionResolverInterface $sectionResolver,
20
                                private readonly TuitionRepositoryInterface $tuitionRepository,
21
                                private readonly ImportSettings $importSettings) { }
22
23
    public function validate(mixed $value, Constraint $constraint) {
24
        if(!$value instanceof TimetableLessonData) {
25
            throw new UnexpectedTypeException($value, TimetableLessonData::class);
26
        }
27
28
        if(!$constraint instanceof TuitionResolvable) {
29
            throw new UnexpectedTypeException($constraint, TuitionResolvable::class);
30
        }
31
32
        if(empty($value->getSubject()) || count($value->getGrades()) === 0 || count($value->getTeachers()) === 0) {
33
            return;
34
        }
35
36
        if(in_array($value->getSubject(), $this->importSettings->getSubjectsWithoutTuition())) {
37
            return;
38
        }
39
40
        $section = $this->sectionResolver->getSectionForDate($value->getDate());
0 ignored issues
show
Bug introduced by
It seems like $value->getDate() can also be of type null; however, parameter $dateTime of App\Section\SectionResol...ce::getSectionForDate() does only seem to accept DateTime, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

40
        $section = $this->sectionResolver->getSectionForDate(/** @scrutinizer ignore-type */ $value->getDate());
Loading history...
41
        $tuition = $this->findTuition($value->getGrades(), $value->getTeachers(), $value->getSubject(), $section);
0 ignored issues
show
Bug introduced by
It seems like $section can also be of type null; however, parameter $section of App\Validator\TuitionRes...alidator::findTuition() does only seem to accept App\Entity\Section, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

41
        $tuition = $this->findTuition($value->getGrades(), $value->getTeachers(), $value->getSubject(), /** @scrutinizer ignore-type */ $section);
Loading history...
42
43
44
45
        if(count($tuition) === 0) {
46
            $this->context
47
                ->buildViolation($constraint->notMatchedmessage)
48
                ->setParameter('{{ subject }}', $value->getSubject())
49
                ->setParameter('{{ teachers }}', implode(', ', $value->getTeachers()))
50
                ->setParameter('{{ grades }}', implode(', ', $value->getGrades()))
51
                ->addViolation();
52
        }
53
54
        if(count($tuition) > 1) {
55
            $this->context
56
                ->buildViolation($constraint->ambiguousMessage)
57
                ->setParameter('{{ subject }}', $value->getSubject())
58
                ->setParameter('{{ teachers }}', implode(', ', $value->getTeachers()))
59
                ->setParameter('{{ grades }}', implode(', ', $value->getGrades()))
60
                ->addViolation();
61
        }
62
63
        // tuition resolved :)
64
    }
65
66
    /**
67
     * @param string[] $grades
68
     * @param string[] $teachers
69
     * @return Tuition[]
70
     */
71
    private function findTuition(array $grades, array $teachers, string $subjectOrCourse, Section $section): array {
72
        sort($grades);
73
        sort($teachers);
74
75
        $key = sprintf(
76
            '%d-%s-%s-%s',
77
            $section->getId(),
78
            implode('~', $grades),
79
            implode('~', $teachers),
80
            $subjectOrCourse
81
        );
82
83
        if(!isset($this->cache[$key])) {
84
            $this->cache[$key] = $this->tuitionRepository->findAllByGradeTeacherAndSubjectOrCourse($grades, $teachers, $subjectOrCourse, $section);
85
        }
86
87
        return $this->cache[$key];
88
    }
89
}