ExtraFieldType::buildForm()   F
last analyzed

Complexity

Conditions 52
Paths 435

Size

Total Lines 252
Code Lines 158

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 52
eloc 158
nc 435
nop 2
dl 0
loc 252
rs 0.6277
c 1
b 0
f 0

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
            $isEditable = $extraField->isChangeable();
83
            $defaultOptions = [
84
                'label' => $text,
85
                'required' => false,
86
                'by_reference' => false,
87
                'mapped' => false,
88
                'data' => $value,
89
                'attr' => $isEditable ? [] : ['readonly' => true, 'class' => 'readonly-field'],
90
            ];
91
92
            // @todo validate data.
93
            switch ($extraField->getValueType()) {
94
                case \ExtraField::FIELD_TYPE_DOUBLE_SELECT:
95
                case \ExtraField::FIELD_TYPE_DIVIDER:
96
                case \ExtraField::FIELD_TYPE_TIMEZONE:
97
                case \ExtraField::FIELD_TYPE_FILE_IMAGE:
98
                case \ExtraField::FIELD_TYPE_FILE:
99
                case \ExtraField::FIELD_TYPE_LETTERS_SPACE:
100
                case \ExtraField::FIELD_TYPE_ALPHANUMERIC_SPACE:
101
                case \ExtraField::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
102
                case \ExtraField::FIELD_TYPE_TRIPLE_SELECT:
103
                    // @todo
104
                    break;
105
106
                case \ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
107
                case \ExtraField::FIELD_TYPE_GEOLOCALIZATION:
108
                    if (!$geolocalization) {
109
                        break;
110
                    }
111
112
                    $defaultOptions['data'] = [];
113
                    if (!empty($value)) {
114
                        $parts = explode('::', $value);
115
                        $coordinates = isset($parts[1]) ? explode(',', $parts[1]) : [];
116
                        $mapArray = [
117
                            'address' => $parts[0] ?? '',
118
                            'latitude' => $coordinates[0] ?? '',
119
                            'longitude' => $coordinates[1] ?? '',
120
                        ];
121
                        $defaultOptions['data'] = $mapArray;
122
                    }
123
124
                    $builder->add($variable, GoogleMapType::class, $defaultOptions);
125
126
                    break;
127
128
                case \ExtraField::FIELD_TYPE_TAG:
129
                    $defaultOptions['expanded'] = false;
130
                    $defaultOptions['multiple'] = true;
131
132
                    // The class will be loaded in the template: src/CoreBundle/Resources/views/Account/edit.html.twig
133
                    // @todo implement generic form.
134
                    $class = 'select2_extra_rel_tag';
135
                    if (ExtraField::USER_FIELD_TYPE === $extraFieldType) {
136
                        $class = 'select2_user_rel_tag';
137
                        $tags = $this->tagRepository->getTagsByUser($extraField, $item);
138
139
                        $choices = [];
140
                        $choicesAttributes = [];
141
                        foreach ($tags as $tag) {
142
                            $stringTag = $tag->getTag();
143
                            if (empty($stringTag)) {
144
                                continue;
145
                            }
146
                            $choices[$stringTag] = $stringTag;
147
                            $choicesAttributes[$stringTag] = ['data-id' => $tag->getId()];
148
                        }
149
150
                        $defaultOptions['choices'] = $choices;
151
                        $defaultOptions['choice_attr'] = $choicesAttributes;
152
                        $defaultOptions['data'] = $choices;
153
                    }
154
155
                    $defaultOptions['attr'] = [
156
                        'class' => $class,
157
                        'style' => 'width:500px',
158
                        'data.field_id' => $extraField->getId(),
159
                    ];
160
                    $builder->add($variable, ChoiceType::class, $defaultOptions);
161
162
                    break;
163
164
                case \ExtraField::FIELD_TYPE_VIDEO_URL:
165
                case \ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
166
                    $builder->add($variable, UrlType::class, $defaultOptions);
167
168
                    break;
169
170
                case \ExtraField::FIELD_TYPE_MOBILE_PHONE_NUMBER:
171
                    $builder->add($variable, TelType::class, $defaultOptions);
172
173
                    break;
174
175
                case \ExtraField::FIELD_TYPE_DATE:
176
                    $defaultOptions['data'] = null;
177
                    if (!empty($value)) {
178
                        $defaultOptions['data'] = new DateTime($value);
179
                    }
180
                    $defaultOptions['widget'] = 'single_text';
181
                    $builder->add($variable, DateType::class, $defaultOptions);
182
183
                    break;
184
185
                case \ExtraField::FIELD_TYPE_DATETIME:
186
                    $defaultOptions['data'] = null;
187
                    if (!empty($value)) {
188
                        $defaultOptions['data'] = new DateTime($value);
189
                    }
190
                    $defaultOptions['widget'] = 'single_text';
191
                    $builder->add($variable, DateTimeType::class, $defaultOptions);
192
193
                    break;
194
195
                case \ExtraField::FIELD_TYPE_TEXTAREA:
196
                    $builder->add($variable, TextareaType::class, $defaultOptions);
197
198
                    break;
199
200
                case \ExtraField::FIELD_TYPE_FLOAT:
201
                    $builder->add($variable, NumberType::class, $defaultOptions);
202
203
                    break;
204
205
                case \ExtraField::FIELD_TYPE_INTEGER:
206
                    $builder->add($variable, IntegerType::class, $defaultOptions);
207
208
                    break;
209
210
                case \ExtraField::FIELD_TYPE_LETTERS_ONLY:
211
                case \ExtraField::FIELD_TYPE_ALPHANUMERIC:
212
                case \ExtraField::FIELD_TYPE_TEXT:
213
                    $builder->add($variable, TextType::class, $defaultOptions);
214
215
                    break;
216
217
                case \ExtraField::FIELD_TYPE_CHECKBOX:
218
                    $defaultOptions['data'] = 1 === (int) $value;
219
220
                    $builder->add($variable, CheckboxType::class, $defaultOptions);
221
222
                    break;
223
224
                case \ExtraField::FIELD_TYPE_RADIO:
225
                case \ExtraField::FIELD_TYPE_SELECT:
226
                    $defaultOptions['attr']['class'] = 'p-select p-component p-inputwrapper p-inputwrapper-filled';
227
228
                    // no break
229
                case \ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
230
                    if (empty($value)) {
231
                        $defaultOptions['data'] = null;
232
                        if (\ExtraField::FIELD_TYPE_CHECKBOX === $extraField->getValueType()) {
233
                            $defaultOptions['data'] = [];
234
                        }
235
                    }
236
                    $options = $extraField->getOptions();
237
                    $choices = [];
238
                    foreach ($options as $option) {
239
                        $choices[$option->getDisplayText()] = $option->getValue();
240
                    }
241
                    $defaultOptions['choices'] = $choices;
242
243
                    if (\ExtraField::FIELD_TYPE_SELECT === $extraField->getValueType()) {
244
                        $defaultOptions['expanded'] = false;
245
                        $defaultOptions['multiple'] = false;
246
                    }
247
                    if (\ExtraField::FIELD_TYPE_SELECT_MULTIPLE === $extraField->getValueType()) {
248
                        $defaultOptions['expanded'] = false;
249
                        $defaultOptions['multiple'] = true;
250
                    }
251
                    $builder->add($variable, ChoiceType::class, $defaultOptions);
252
253
                    break;
254
            }
255
        }
256
257
        /*$builder->addEventListener(
258
            FormEvents::POST_SET_DATA,
259
            function (FormEvent $event) use ($item, $extraFields): void {
260
                $data = $event->getData();
261
                foreach ($extraFields as $extraField) {
262
                    $newValue = $data[$extraField->getVariable()] ?? null;
263
                    if (!empty($newValue)) {
264
                        if (\ExtraField::FIELD_TYPE_TAG === $extraField->getValueType()) {
265
                            $formItem = $event->getForm()->get($extraField->getVariable());
266
                            $formItem->setData($newValue);
267
                        }
268
                    }
269
                }
270
            }
271
        );*/
272
        $builder->addEventListener(
273
            FormEvents::PRE_SUBMIT,
274
            function (FormEvent $event) use ($item, $extraFields): void {
275
                $data = $event->getData();
276
                foreach ($extraFields as $extraField) {
277
                    $newValue = $data[$extraField->getVariable()] ?? null;
278
279
                    switch ($extraField->getValueType()) {
280
                        case \ExtraField::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
281
                        case \ExtraField::FIELD_TYPE_GEOLOCALIZATION:
282
                            if (!empty($newValue)) {
283
                                $newValue = $newValue['address'].'::'.$newValue['latitude'].','.$newValue['longitude'];
284
                            }
285
                            $this->extraFieldValuesRepository->updateItemData($extraField, $item, $newValue);
286
287
                            break;
288
289
                        case \ExtraField::FIELD_TYPE_TAG:
290
                            $formItem = $event->getForm()->get($extraField->getVariable());
291
                            $options = $formItem->getConfig()->getOptions();
292
                            $options['choices'] = $newValue;
293
                            $event->getForm()->add($extraField->getVariable(), ChoiceType::class, $options);
294
295
                            if (!empty($newValue)) {
296
                                foreach ($newValue as $tag) {
297
                                    $this->tagRepository->addTagToUser($extraField, $item, $tag);
298
                                }
299
                            }
300
301
                            break;
302
303
                        default:
304
                            $this->extraFieldValuesRepository->updateItemData($extraField, $item, $newValue);
305
306
                            break;
307
                    }
308
                }
309
            }
310
        );
311
    }
312
}
313