Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
91.18% covered (success)
91.18%
31 / 34
82.35% covered (warning)
82.35%
14 / 17
63.64% covered (warning)
63.64%
7 / 11
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
RequestFactory
91.18% covered (success)
91.18%
31 / 34
82.35% covered (warning)
82.35%
14 / 17
63.64% covered (warning)
63.64%
7 / 11
50.00% covered (danger)
50.00%
2 / 4
14.81
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
17 / 17
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
 convertIntArray
88.89% covered (warning)
88.89%
8 / 9
87.50% covered (warning)
87.50%
7 / 8
40.00% covered (danger)
40.00%
2 / 5
0.00% covered (danger)
0.00%
0 / 1
7.46
 convertEnum
60.00% covered (warning)
60.00%
3 / 5
60.00% covered (warning)
60.00%
3 / 5
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
3.33
 fromParameters
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace App\Dto\Request;
4
5use App\Enum\Enum;
6use App\Enum\GrammaticalRoleType;
7use App\Enum\Lang;
8use App\Enum\OffenseLevel;
9use App\Enum\WordGender;
10use App\Exception\ConversionException;
11
12/**
13 * @author Wilhelm Zwertvaegher
14 */
15readonly class RequestFactory
16{
17    /**
18     * @var array<class-string, \Closure>
19     */
20    private array $strategies;
21
22    public function __construct(private EnumConverter $enumConverter)
23    {
24        $this->strategies = [
25            RandomNickRequest::class => fn (array $parameters) => new RandomNickRequest(
26                lang: $this->convertEnum(Lang::class, 'lang', $parameters, Lang::FR),
27                gender: $this->convertEnum(WordGender::class, 'gender', $parameters, WordGender::AUTO),
28                offenseLevel: $this->convertEnum(OffenseLevel::class, 'offenseLevel', $parameters),
29                previousId: $parameters['previousId'] ?? null,
30                replaceRole: $this->convertEnum(GrammaticalRoleType::class, 'replaceRole', $parameters),
31                exclusions: $this->convertIntArray('exclusions', $parameters)
32            ),
33            RandomWordRequest::class => fn (array $parameters) => new RandomWordRequest(
34                previousId: $parameters['previousId'] ?? null,
35                role: $this->convertEnum(GrammaticalRoleType::class, 'role', $parameters),
36                gender: $this->convertEnum(WordGender::class, 'gender', $parameters),
37                offenseLevel: $this->convertEnum(OffenseLevel::class, 'offenseLevel', $parameters),
38                exclusions: $this->convertIntArray('exclusions', $parameters)
39            ),
40        ];
41    }
42
43    /**
44     * @param array<string, string> $parameters
45     *
46     * @return array<int>
47     *
48     * @throws ConversionException
49     */
50    private function convertIntArray(string $field, array $parameters): array
51    {
52        $str = $parameters[$field] ?? '';
53        $intArray = [];
54        if ('' != $str) {
55            $strArray = explode(',', $str);
56            foreach ($strArray as $value) {
57                if (!filter_var($value, FILTER_VALIDATE_INT)) {
58                    throw new ConversionException($field, $str);
59                }
60                $intArray[] = (int) $value;
61            }
62        }
63
64        return $intArray;
65    }
66
67    /**
68     * @template  T of Enum
69     *
70     * @param class-string<T>       $enumClass
71     * @param array<string, string> $parameters
72     *
73     * @return ?T
74     *
75     * @throws ConversionException
76     */
77    private function convertEnum(string $enumClass, string $field, array $parameters, ?Enum $defaultValue = null): ?Enum
78    {
79        if (!isset($parameters[$field])) {
80            return $defaultValue;
81        }
82
83        try {
84            return $this->enumConverter->convert($enumClass, $parameters[$field]);
85        } catch (\Throwable $t) {
86            throw new ConversionException($field, $parameters[$field], 0, $t);
87        }
88    }
89
90    /**
91     * @param class-string          $class
92     * @param array<string, string> $parameters
93     *
94     * @throws ConversionException|\TypeError
95     */
96    public function fromParameters(string $class, array $parameters): Request
97    {
98        if (!array_key_exists($class, $this->strategies)) {
99            throw new \InvalidArgumentException('Strategy not found');
100        }
101
102        return $this->strategies[$class]($parameters);
103    }
104}