EnumType::populateOptionsWithDefaults()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 19
rs 9.9666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Zlikavac32\SymfonyEnum\Form\Type;
6
7
use LogicException;
8
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
9
use Symfony\Component\Form\FormBuilderInterface;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
use function Zlikavac32\Enum\assertFqnIsEnumClass;
12
use Zlikavac32\Enum\Enum;
13
14
class EnumType extends ChoiceType
15
{
16
    public function buildForm(FormBuilderInterface $builder, array $options)
17
    {
18
        $this->assertThatOverriddenOptionsAreNotSet($options);
19
20
        /* @var Enum|string $enumClass */
21
        $enumClass = $options['enum_class'];
22
23
        assertFqnIsEnumClass($enumClass);
24
25
        $options = $this->populateOptionsWithDefaults($options);
26
27
        parent::buildForm(
28
            $builder,
29
            [
30
                'choices'       => $this->buildChoicesForEnumClass($enumClass),
31
                'choice_loader' => null,
32
            ] + $options
33
        );
34
    }
35
36
    private function populateOptionsWithDefaults(array $options): array
37
    {
38
        $elementNameClosure = function (?Enum $enum): string {
39
            if (null === $enum) {
40
                return '';
41
            }
42
43
            return $enum->name();
44
        };
45
46
        foreach (['choice_label', 'choice_value'] as $optionKey) {
47
            if (isset($options[$optionKey])) {
48
                continue;
49
            }
50
51
            $options[$optionKey] = $elementNameClosure;
52
        }
53
54
        return $options;
55
    }
56
57
    private function buildChoicesForEnumClass(string $enumClass): array
58
    {
59
        $choices = [];
60
61
        /* @var Enum $enumClass Just for IDE auto-complete support */
62
        foreach ($enumClass::values() as $element) {
63
            $choices[$element->name()] = $element;
64
        }
65
66
        return $choices;
67
    }
68
69
    private function assertThatOverriddenOptionsAreNotSet(array $options): void
70
    {
71
        $optionsToCheckFor = [
72
            'choices',
73
            'choice_loader',
74
        ];
75
76
        foreach ($optionsToCheckFor as $optionName) {
77
            if (empty($options[$optionName])) {
78
                continue;
79
            }
80
81
            throw new LogicException(
82
                sprintf('Option %s is overridden by the type so don\'t pass your own value', $optionName)
83
            );
84
        }
85
    }
86
87
    public function configureOptions(OptionsResolver $resolver): void
88
    {
89
        parent::configureOptions($resolver);
90
91
        $resolver->setDefaults(['enum_class' => null])
92
            ->setAllowedTypes('enum_class', ['string']);
93
    }
94
}
95