ExtraFieldType::buildForm()   F
last analyzed

Complexity

Conditions 51
Paths 25

Size

Total Lines 247
Code Lines 155

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 51
eloc 155
c 0
b 0
f 0
nc 25
nop 2
dl 0
loc 247
rs 3.3333

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Form;
8
9
use Chamilo\CoreBundle\Entity\ExtraField;
10
use Chamilo\CoreBundle\Entity\User;
11
use Chamilo\CoreBundle\Repository\ExtraFieldRepository;
12
use Chamilo\CoreBundle\Repository\ExtraFieldValuesRepository;
13
use Chamilo\CoreBundle\Repository\TagRepository;
14
use DateTime;
15
use GoogleMapsPlugin;
16
use Oh\GoogleMapFormTypeBundle\Form\Type\GoogleMapType;
17
use Symfony\Bundle\SecurityBundle\Security;
18
use Symfony\Component\Form\AbstractType;
19
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
20
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
21
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
22
use Symfony\Component\Form\Extension\Core\Type\DateType;
23
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
24
use Symfony\Component\Form\Extension\Core\Type\NumberType;
25
use Symfony\Component\Form\Extension\Core\Type\TelType;
26
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
27
use Symfony\Component\Form\Extension\Core\Type\TextType;
28
use Symfony\Component\Form\Extension\Core\Type\UrlType;
29
use Symfony\Component\Form\FormBuilderInterface;
30
use Symfony\Component\Form\FormEvent;
31
use Symfony\Component\Form\FormEvents;
32
33
/**
34
 * @template-extends AbstractType<array>
35
 */
36
class ExtraFieldType extends AbstractType
37
{
38
    private ExtraFieldValuesRepository $extraFieldValuesRepository;
39
    private Security $security;
40
    private ExtraFieldRepository $extraFieldRepository;
41
    private TagRepository $tagRepository;
42
43
    public function __construct(
44
        ExtraFieldValuesRepository $extraFieldValuesRepository,
45
        ExtraFieldRepository $extraFieldRepository,
46
        TagRepository $tagRepository,
47
        Security $security
48
    ) {
49
        $this->extraFieldValuesRepository = $extraFieldValuesRepository;
50
        $this->extraFieldRepository = $extraFieldRepository;
51
        $this->security = $security;
52
        $this->tagRepository = $tagRepository;
53
    }
54
55
    public function buildForm(FormBuilderInterface $builder, array $options): void
56
    {
57
        // @todo implement Course/Session extra fields
58
        /** @var User|null $item */
59
        $item = $this->security->getUser();
60
61
        if (null === $item) {
62
            return;
63
        }
64
65
        $extraFieldType = ExtraField::USER_FIELD_TYPE; // user/course/session ?
66
        $extraFields = $this->extraFieldRepository->getExtraFields($extraFieldType);
67
        $values = $this->extraFieldValuesRepository->getExtraFieldValuesFromItem($item, $extraFieldType);
68
69
        $data = [];
70
        foreach ($values as $value) {
71
            $data[$value->getField()->getVariable()] = $value->getFieldValue();
72
        }
73
74
        $gMapsPlugin = GoogleMapsPlugin::create();
75
        $geolocalization = 'true' === $gMapsPlugin->get('enable_api');
76
77
        foreach ($extraFields as $extraField) {
78
            $text = $extraField->getDisplayText();
79
            $variable = $extraField->getVariable();
80
            $value = $data[$extraField->getVariable()] ?? null;
81
82
            $defaultOptions = [
83
                'label' => $text,
84
                'required' => false,
85
                'by_reference' => false,
86
                'mapped' => false,
87
                'data' => $value,
88
            ];
89
90
            // @todo validate data.
91
            switch ($extraField->getValueType()) {
92
                case \ExtraField::FIELD_TYPE_DOUBLE_SELECT:
93
                case \ExtraField::FIELD_TYPE_DIVIDER:
94
                case \ExtraField::FIELD_TYPE_TIMEZONE:
95
                case \ExtraField::FIELD_TYPE_FILE_IMAGE:
96
                case \ExtraField::FIELD_TYPE_FILE:
97
                case \ExtraField::FIELD_TYPE_LETTERS_SPACE:
98
                case \ExtraField::FIELD_TYPE_ALPHANUMERIC_SPACE:
99
                case \ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
100
                case \ExtraField::FIELD_TYPE_TRIPLE_SELECT:
101
                    // @todo
102
                    break;
103
104
                case \ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
105
                case \ExtraField::FIELD_TYPE_GEOLOCALIZATION:
106
                    if (!$geolocalization) {
107
                        break 2;
108
                    }
109
110
                    $defaultOptions['data'] = [];
111
                    if (!empty($value)) {
112
                        $parts = explode('::', $value);
113
                        $coordinates = isset($parts[1]) ? explode(',', $parts[1]) : [];
114
                        $mapArray = [
115
                            'address' => $parts[0] ?? '',
116
                            'latitude' => $coordinates[0] ?? '',
117
                            'longitude' => $coordinates[1] ?? '',
118
                        ];
119
                        $defaultOptions['data'] = $mapArray;
120
                    }
121
122
                    $builder->add($variable, GoogleMapType::class, $defaultOptions);
123
124
                    break;
125
126
                case \ExtraField::FIELD_TYPE_TAG:
127
                    $defaultOptions['expanded'] = false;
128
                    $defaultOptions['multiple'] = true;
129
130
                    // The class will be loaded in the template: src/CoreBundle/Resources/views/Account/edit.html.twig
131
                    // @todo implement generic form.
132
                    $class = 'select2_extra_rel_tag';
133
                    if (ExtraField::USER_FIELD_TYPE === $extraFieldType) {
134
                        $class = 'select2_user_rel_tag';
135
                        $tags = $this->tagRepository->getTagsByUser($extraField, $item);
136
137
                        $choices = [];
138
                        $choicesAttributes = [];
139
                        foreach ($tags as $tag) {
140
                            $stringTag = $tag->getTag();
141
                            if (empty($stringTag)) {
142
                                continue;
143
                            }
144
                            $choices[$stringTag] = $stringTag;
145
                            $choicesAttributes[$stringTag] = ['data-id' => $tag->getId()];
146
                        }
147
148
                        $defaultOptions['choices'] = $choices;
149
                        $defaultOptions['choice_attr'] = $choicesAttributes;
150
                        $defaultOptions['data'] = $choices;
151
                    }
152
153
                    $defaultOptions['attr'] = [
154
                        'class' => $class,
155
                        'style' => 'width:500px',
156
                        'data.field_id' => $extraField->getId(),
157
                    ];
158
                    $builder->add($variable, ChoiceType::class, $defaultOptions);
159
160
                    break;
161
162
                case \ExtraField::FIELD_TYPE_VIDEO_URL:
163
                case \ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
164
                    $builder->add($variable, UrlType::class, $defaultOptions);
165
166
                    break;
167
168
                case \ExtraField::FIELD_TYPE_MOBILE_PHONE_NUMBER:
169
                    $builder->add($variable, TelType::class, $defaultOptions);
170
171
                    break;
172
173
                case \ExtraField::FIELD_TYPE_DATE:
174
                    $defaultOptions['data'] = null;
175
                    if (!empty($value)) {
176
                        $defaultOptions['data'] = new DateTime($value);
177
                    }
178
                    $defaultOptions['widget'] = 'single_text';
179
                    $builder->add($variable, DateType::class, $defaultOptions);
180
181
                    break;
182
183
                case \ExtraField::FIELD_TYPE_DATETIME:
184
                    $defaultOptions['data'] = null;
185
                    if (!empty($value)) {
186
                        $defaultOptions['data'] = new DateTime($value);
187
                    }
188
                    $defaultOptions['widget'] = 'single_text';
189
                    $builder->add($variable, DateTimeType::class, $defaultOptions);
190
191
                    break;
192
193
                case \ExtraField::FIELD_TYPE_TEXTAREA:
194
                    $builder->add($variable, TextareaType::class, $defaultOptions);
195
196
                    break;
197
198
                case \ExtraField::FIELD_TYPE_FLOAT:
199
                    $builder->add($variable, NumberType::class, $defaultOptions);
200
201
                    break;
202
203
                case \ExtraField::FIELD_TYPE_INTEGER:
204
                    $builder->add($variable, IntegerType::class, $defaultOptions);
205
206
                    break;
207
208
                case \ExtraField::FIELD_TYPE_LETTERS_ONLY:
209
                case \ExtraField::FIELD_TYPE_ALPHANUMERIC:
210
                case \ExtraField::FIELD_TYPE_TEXT:
211
                    $builder->add($variable, TextType::class, $defaultOptions);
212
213
                    break;
214
215
                case \ExtraField::FIELD_TYPE_CHECKBOX:
216
                    $defaultOptions['data'] = 1 === (int) $value;
217
218
                    $builder->add($variable, CheckboxType::class, $defaultOptions);
219
220
                    break;
221
222
                case \ExtraField::FIELD_TYPE_RADIO:
223
                case \ExtraField::FIELD_TYPE_SELECT:
224
                case \ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
225
                    if (empty($value)) {
226
                        $defaultOptions['data'] = null;
227
                        if (\ExtraField::FIELD_TYPE_CHECKBOX === $extraField->getValueType()) {
228
                            $defaultOptions['data'] = [];
229
                        }
230
                    }
231
                    $options = $extraField->getOptions();
232
                    $choices = [];
233
                    foreach ($options as $option) {
234
                        $choices[$option->getDisplayText()] = $option->getValue();
235
                    }
236
                    $defaultOptions['choices'] = $choices;
237
238
                    if (\ExtraField::FIELD_TYPE_SELECT === $extraField->getValueType()) {
239
                        $defaultOptions['expanded'] = false;
240
                        $defaultOptions['multiple'] = false;
241
                    }
242
                    if (\ExtraField::FIELD_TYPE_SELECT_MULTIPLE === $extraField->getValueType()) {
243
                        $defaultOptions['expanded'] = false;
244
                        $defaultOptions['multiple'] = true;
245
                    }
246
                    $builder->add($variable, ChoiceType::class, $defaultOptions);
247
248
                    break;
249
            }
250
        }
251
252
        /*$builder->addEventListener(
253
            FormEvents::POST_SET_DATA,
254
            function (FormEvent $event) use ($item, $extraFields): void {
255
                $data = $event->getData();
256
                foreach ($extraFields as $extraField) {
257
                    $newValue = $data[$extraField->getVariable()] ?? null;
258
                    if (!empty($newValue)) {
259
                        if (\ExtraField::FIELD_TYPE_TAG === $extraField->getValueType()) {
260
                            $formItem = $event->getForm()->get($extraField->getVariable());
261
                            $formItem->setData($newValue);
262
                        }
263
                    }
264
                }
265
            }
266
        );*/
267
        $builder->addEventListener(
268
            FormEvents::PRE_SUBMIT,
269
            function (FormEvent $event) use ($item, $extraFields): void {
270
                $data = $event->getData();
271
                foreach ($extraFields as $extraField) {
272
                    $newValue = $data[$extraField->getVariable()] ?? null;
273
274
                    switch ($extraField->getValueType()) {
275
                        case \ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
276
                        case \ExtraField::FIELD_TYPE_GEOLOCALIZATION:
277
                            if (!empty($newValue)) {
278
                                $newValue = $newValue['address'].'::'.$newValue['latitude'].','.$newValue['longitude'];
279
                            }
280
                            $this->extraFieldValuesRepository->updateItemData($extraField, $item, $newValue);
281
282
                            break;
283
284
                        case \ExtraField::FIELD_TYPE_TAG:
285
                            $formItem = $event->getForm()->get($extraField->getVariable());
286
                            $options = $formItem->getConfig()->getOptions();
287
                            $options['choices'] = $newValue;
288
                            $event->getForm()->add($extraField->getVariable(), ChoiceType::class, $options);
289
290
                            if (!empty($newValue)) {
291
                                foreach ($newValue as $tag) {
292
                                    $this->tagRepository->addTagToUser($extraField, $item, $tag);
293
                                }
294
                            }
295
296
                            break;
297
298
                        default:
299
                            $this->extraFieldValuesRepository->updateItemData($extraField, $item, $newValue);
300
301
                            break;
302
                    }
303
                }
304
            }
305
        );
306
    }
307
}
308