Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
88.24% covered (warning)
88.24%
15 / 17
81.82% covered (warning)
81.82%
9 / 11
57.14% covered (warning)
57.14%
4 / 7
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
WordFinder
88.24% covered (warning)
88.24%
15 / 17
81.82% covered (warning)
81.82%
9 / 11
57.14% covered (warning)
57.14%
4 / 7
50.00% covered (danger)
50.00%
1 / 2
8.83
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 findSimilar
87.50% covered (warning)
87.50%
14 / 16
80.00% covered (warning)
80.00%
8 / 10
50.00% covered (danger)
50.00%
3 / 6
0.00% covered (danger)
0.00%
0 / 1
8.12
1<?php
2
3namespace App\Service\Generator;
4
5use App\Dto\Command\GetWordCommand;
6use App\Entity\GrammaticalRole;
7use App\Entity\Word;
8use App\Enum\GrammaticalRoleType;
9use App\Specification\Criteria;
10use App\Specification\Criterion\GenderConstraintType;
11use App\Specification\Criterion\GenderCriterion;
12use App\Specification\Criterion\LangCriterion;
13use App\Specification\Criterion\OffenseConstraintType;
14use App\Specification\Criterion\OffenseLevelCriterion;
15use App\Specification\Criterion\ValuesCriterion;
16use App\Specification\Criterion\ValuesCriterionCheck;
17use Psr\Container\ContainerInterface;
18use Symfony\Component\DependencyInjection\Attribute\AutowireLocator;
19
20/**
21 * @author Wilhelm Zwertvaegher
22 */
23readonly class WordFinder implements WordFinderInterface
24{
25    public function __construct(
26        #[AutowireLocator('app.word_type_data_service', indexAttribute: 'index')]
27        private ContainerInterface $services,
28    ) {
29    }
30
31    public function findSimilar(GetWordCommand $command): ?GrammaticalRole
32    {
33        if (!$this->services->has($command->getRole()->value)) {
34            throw new \LogicException('Command with role "'.$command->getRole()->value.'" has no matching GrammaticalRoleServiceInterface.');
35        }
36        $service = $this->services->get($command->getRole()->value);
37        $previous = $command->getPrevious() ?? $service->findByWordId($command->getPreviousId());
38
39        if (null === $previous) {
40            throw new \LogicException('Cannot get a word without a previous word');
41        }
42
43        $criteria = [new LangCriterion($previous->getWord()->getLang())];
44        $criteria[] = new GenderCriterion($command->getGender(), GenderConstraintType::EXACT);
45        $criteria[] = new OffenseLevelCriterion(
46            $command->getOffenseLevel(),
47            GrammaticalRoleType::SUBJECT === $command->getRole() ? OffenseConstraintType::EXACT : OffenseConstraintType::LTE
48        );
49
50        if (count($command->getExclusions())) {
51            $criteria[] = new ValuesCriterion(Word::class, 'id', $command->getExclusions(), ValuesCriterionCheck::NOT_IN);
52        }
53
54        $wordCriteria = new Criteria($criteria);
55
56        return $service->findSimilar($previous, $wordCriteria);
57    }
58}