Completed
Push — develop ( d42c3f...ac22da )
by Freddie
02:15
created

InputBuilder::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
c 1
b 0
f 0
dl 0
loc 4
rs 10
eloc 2
nc 1
nop 2
1
<?php
2
3
namespace FlexPHP\Inputs\Builder;
4
5
use Symfony\Component\Form\Extension\Core\Type\FormType;
6
use Symfony\Component\Form\FormBuilderInterface;
7
use Symfony\Component\Form\Forms;
8
use Symfony\Component\Form\FormInterface;
9
use \InvalidArgumentException;
10
use Symfony\Component\Form\Extension\Core\Type\TextType;
11
12
class InputBuilder extends AbstractBuilder
13
{
14
    protected $type;
15
16
    public function __construct(string $name, array $options)
17
    {
18
        $this->name = $name;
19
        $this->options = $this->parseOptions($this->getDefaultOptions($options));
20
    }
21
22
    public function getOptions(): array
23
    {
24
        return $this->options;
25
    }
26
27
    public function build(): FormInterface
28
    {
29
        $options = $this->getOptions();
30
        $classType = trim($this->getType());
31
32
        if (\strpos($classType, 'Symfony') === false) {
33
            // Not symfony type
34
            $type = preg_replace('/type$/i', '', $classType) ?? $classType;
35
            $classType = \sprintf('\Symfony\Component\Form\Extension\Core\Type\%1$sType', $type);
36
        } elseif (!empty($options['type']) && \stripos($classType, $options['type']) === false) {
37
            // Symfony type, but its diff in options type contraint
38
            $type = $options['type'];
39
            $classType = \sprintf('\Symfony\Component\Form\Extension\Core\Type\%1$sType', $type);
40
        }
41
42
        unset($options['type']);
43
44
        if (!\class_exists($classType)) {
45
            throw new InvalidArgumentException(\sprintf('Type [%1$s] is not supported', $classType));
46
        }
47
48
        return $this
49
            ->factory()
50
            ->add($this->getName(), $classType, $options)
51
            ->getForm();
52
    }
53
54
    public function render(): string
55
    {
56
        return $this->twig()->createTemplate(\sprintf('{{ form_row(form.%1$s) }}', $this->getName()))->render([
57
            'form' => $this->build()->createView(),
58
        ]);
59
    }
60
61
    protected function factory(): FormBuilderInterface
62
    {
63
        return Forms::createFormFactory()->createBuilder(FormType::class, null);
64
    }
65
66
    protected function getType(): string
67
    {
68
        return TextType::class;
69
    }
70
71
    private function getDefaultOptions(array $options = []): array
72
    {
73
        return array_merge([
74
            'required' => false,
75
        ], $options);
76
    }
77
78
    private function parseOptions(array $options): array
79
    {
80
        $_options = [];
81
82
        $options = array_change_key_case(array_filter($options, function ($var) {
83
            return !is_null($var);
84
        }));
85
86
        if (!empty($options['attr']['type'])) {
87
            $options['type'] = $options['attr']['type'];
88
            unset($options['attr']['type']);
89
        }
90
91
        foreach ($options as $option => $value) {
92
            switch ($option) {
93
                case 'default':
94
                    $_options['data'] = $value;
95
                    break;
96
                case 'constraints':
97
                    $attributes = \json_decode($value, true);
98
99
                    if ((\json_last_error() !== JSON_ERROR_NONE)) {
100
                        $attributes = [$value];
101
                    }
102
103
                    foreach ($attributes as $attribute => $_value) {
104
                        $attribute = \strtolower($attribute);
105
106
                        if ($attribute == 'required' || $_value == 'required') {
107
                            $_options['required'] = true;
108
                        } elseif (in_array($attribute, ['length', 'mincheck', 'maxcheck', 'check', 'equalto'])) {
109
                            $_options['attr']['data-parsley-' . $attribute] = $_value;
110
                        } elseif ($attribute == 'range') {
111
                            $_options['type'] = $attribute;
112
                            list($min, $max) = explode(',', $_value);
113
                            $_options['attr'] = compact('min', 'max');
114
                        } elseif ($attribute == 'type') {
115
                            $_options['type'] = $_value;
116
                        } else {
117
                            $_options['attr'][$attribute] = $_value;
118
                        }
119
                    }
120
                    break;
121
                case 'empty_data':
122
                    $_options[$option] = $value;
123
124
                    if (empty($_options['attr'])) {
125
                        $_options['attr'] = [];
126
                    }
127
128
                    $_options['attr']['placeholder'] = $value;
129
130
                    break;
131
                default:
132
                    if (is_array($value) && !empty($_options[$option])) {
133
                        $_options[$option] = array_merge_recursive($_options[$option], $value);
134
                    } else {
135
                        $_options[$option] = $value;
136
                    }
137
                    break;
138
            }
139
140
            unset($options[$option]);
141
        }
142
143
        if (!empty($_options['type'])) {
144
            $_type = strtolower($_options['type']);
145
146
            switch ($_type) {
147
                case 'digits':
148
                case 'alphanum':
149
                    $_options['attr']['data-parsley-type'] = $_type;
150
                    $_options['type'] = 'text';
151
                    break;
152
            }
153
        }
154
155
        return $_options;
156
    }
157
}
158