Passed
Push — master ( d50113...c8b87f )
by Julito
20:21
created

ExtraField::addElements()   B

Complexity

Conditions 10
Paths 13

Size

Total Lines 78
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 43
c 0
b 0
f 0
nc 13
nop 17
dl 0
loc 78
rs 7.6666

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\Asset;
6
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
7
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
8
use Chamilo\CoreBundle\Entity\Tag;
9
use Chamilo\CoreBundle\Framework\Container;
10
11
class ExtraField extends Model
12
{
13
    public const FIELD_TYPE_TEXT = 1;
14
    public const FIELD_TYPE_TEXTAREA = 2;
15
    public const FIELD_TYPE_RADIO = 3;
16
    public const FIELD_TYPE_SELECT = 4;
17
    public const FIELD_TYPE_SELECT_MULTIPLE = 5;
18
    public const FIELD_TYPE_DATE = 6;
19
    public const FIELD_TYPE_DATETIME = 7;
20
    public const FIELD_TYPE_DOUBLE_SELECT = 8;
21
    public const FIELD_TYPE_DIVIDER = 9;
22
    public const FIELD_TYPE_TAG = 10;
23
    public const FIELD_TYPE_TIMEZONE = 11;
24
    public const FIELD_TYPE_SOCIAL_PROFILE = 12;
25
    public const FIELD_TYPE_CHECKBOX = 13;
26
    public const FIELD_TYPE_MOBILE_PHONE_NUMBER = 14;
27
    public const FIELD_TYPE_INTEGER = 15;
28
    public const FIELD_TYPE_FILE_IMAGE = 16;
29
    public const FIELD_TYPE_FLOAT = 17;
30
    public const FIELD_TYPE_FILE = 18;
31
    public const FIELD_TYPE_VIDEO_URL = 19;
32
    public const FIELD_TYPE_LETTERS_ONLY = 20;
33
    public const FIELD_TYPE_ALPHANUMERIC = 21;
34
    public const FIELD_TYPE_LETTERS_SPACE = 22;
35
    public const FIELD_TYPE_ALPHANUMERIC_SPACE = 23;
36
    public const FIELD_TYPE_GEOLOCALIZATION = 24;
37
    public const FIELD_TYPE_GEOLOCALIZATION_COORDINATES = 25;
38
    public const FIELD_TYPE_SELECT_WITH_TEXT_FIELD = 26;
39
    public const FIELD_TYPE_TRIPLE_SELECT = 27;
40
41
    public $columns = [
42
        'id',
43
        'field_type',
44
        'variable',
45
        'description',
46
        'display_text',
47
        'default_value',
48
        'field_order',
49
        'visible_to_self',
50
        'visible_to_others',
51
        'changeable',
52
        'filter',
53
        'extra_field_type',
54
        //Enable this when field_loggeable is introduced as a table field (2.0)
55
        //'field_loggeable',
56
        'created_at',
57
    ];
58
59
    public $ops = [
60
        'eq' => '=', //equal
61
        'ne' => '<>', //not equal
62
        'lt' => '<', //less than
63
        'le' => '<=', //less than or equal
64
        'gt' => '>', //greater than
65
        'ge' => '>=', //greater than or equal
66
        'bw' => 'LIKE', //begins with
67
        'bn' => 'NOT LIKE', //doesn't begin with
68
        'in' => 'LIKE', //is in
69
        'ni' => 'NOT LIKE', //is not in
70
        'ew' => 'LIKE', //ends with
71
        'en' => 'NOT LIKE', //doesn't end with
72
        'cn' => 'LIKE', //contains
73
        'nc' => 'NOT LIKE',  //doesn't contain
74
    ];
75
76
    public $type = 'user';
77
    public $pageName;
78
    public $pageUrl;
79
    public $extraFieldType = 0;
80
    public $table_field_options;
81
    public $table_field_values;
82
    public $table_field_tag;
83
    public $table_field_rel_tag;
84
    public $handler_id;
85
    public $primaryKey;
86
87
    /**
88
     * @param string $type
89
     */
90
    public function __construct($type)
91
    {
92
        parent::__construct();
93
94
        $this->type = $type;
95
        $this->table = Database::get_main_table(TABLE_EXTRA_FIELD);
96
        $this->table_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
97
        $this->table_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
98
        $this->table_field_tag = Database::get_main_table(TABLE_MAIN_TAG);
99
        $this->table_field_rel_tag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
100
        $this->handler_id = 'item_id';
101
102
        switch ($this->type) {
103
            case 'calendar_event':
104
                $this->extraFieldType = EntityExtraField::CALENDAR_FIELD_TYPE;
105
                break;
106
            case 'course':
107
                $this->extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
108
                $this->primaryKey = 'id';
109
                break;
110
            case 'user':
111
                $this->extraFieldType = EntityExtraField::USER_FIELD_TYPE;
112
                $this->primaryKey = 'id';
113
                break;
114
            case 'session':
115
                $this->extraFieldType = EntityExtraField::SESSION_FIELD_TYPE;
116
                $this->primaryKey = 'id';
117
                break;
118
            case 'exercise':
119
                $this->extraFieldType = EntityExtraField::EXERCISE_FIELD_TYPE;
120
                break;
121
            case 'question':
122
                $this->extraFieldType = EntityExtraField::QUESTION_FIELD_TYPE;
123
                break;
124
            case 'lp':
125
                $this->extraFieldType = EntityExtraField::LP_FIELD_TYPE;
126
                break;
127
            case 'lp_item':
128
                $this->extraFieldType = EntityExtraField::LP_ITEM_FIELD_TYPE;
129
                break;
130
            case 'skill':
131
                $this->extraFieldType = EntityExtraField::SKILL_FIELD_TYPE;
132
                break;
133
            case 'work':
134
                $this->extraFieldType = EntityExtraField::WORK_FIELD_TYPE;
135
                break;
136
            case 'career':
137
                $this->extraFieldType = EntityExtraField::CAREER_FIELD_TYPE;
138
                break;
139
            case 'user_certificate':
140
                $this->extraFieldType = EntityExtraField::USER_CERTIFICATE;
141
                break;
142
            case 'survey':
143
                $this->extraFieldType = EntityExtraField::SURVEY_FIELD_TYPE;
144
                break;
145
            case 'scheduled_announcement':
146
                $this->extraFieldType = EntityExtraField::SCHEDULED_ANNOUNCEMENT;
147
                break;
148
            case 'terms_and_condition':
149
                $this->extraFieldType = EntityExtraField::TERMS_AND_CONDITION_TYPE;
150
                break;
151
            case 'forum_category':
152
                $this->extraFieldType = EntityExtraField::FORUM_CATEGORY_TYPE;
153
                break;
154
            case 'forum_post':
155
                $this->extraFieldType = EntityExtraField::FORUM_POST_TYPE;
156
                break;
157
            case 'track_exercise':
158
                $this->extraFieldType = EntityExtraField::TRACK_EXERCISE_FIELD_TYPE;
159
                break;
160
            case 'portfolio':
161
                $this->extraFieldType = EntityExtraField::PORTFOLIO_TYPE;
162
                break;
163
            case 'lp_view':
164
                $this->extraFieldType = EntityExtraField::LP_VIEW_TYPE;
165
        }
166
167
        $this->pageUrl = 'extra_fields.php?type='.$this->type;
168
        // Example QuestionFields
169
        $this->pageName = ucwords($this->type).'Fields';
170
    }
171
172
    /**
173
     * @return array
174
     */
175
    public static function getValidExtraFieldTypes()
176
    {
177
        $result = [
178
            'user',
179
            'course',
180
            'session',
181
            'question',
182
            'lp',
183
            'calendar_event',
184
            'lp_item',
185
            'skill',
186
            'work',
187
            'career',
188
            'user_certificate',
189
            'survey',
190
            'terms_and_condition',
191
            'forum_category',
192
            'forum_post',
193
            'exercise',
194
            'track_exercise',
195
            'lp_view',
196
        ];
197
198
        if (api_get_configuration_value('allow_scheduled_announcements')) {
199
            $result[] = 'scheduled_announcement';
200
        }
201
        if (api_get_configuration_value('allow_portfolio_tool')) {
202
            $result[] = 'portfolio';
203
        }
204
        sort($result);
205
206
        return $result;
207
    }
208
209
    /**
210
     * Converts a string like this:
211
     * France:Paris;Bretagne;Marseille;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
212
     * into
213
     * array(
214
     *   'France' =>
215
     *      array('Paris', 'Bretagne', 'Marseille'),
216
     *   'Belgique' =>
217
     *      array('Namur', 'Liège')
218
     * ), etc.
219
     *
220
     * @param string $string
221
     *
222
     * @return array
223
     */
224
    public static function extra_field_double_select_convert_string_to_array($string)
225
    {
226
        $options = explode('|', $string);
227
        $options_parsed = [];
228
        $id = 0;
229
230
        if (!empty($options)) {
231
            foreach ($options as $sub_options) {
232
                $options = explode(':', $sub_options);
233
                $sub_sub_options = isset($options[1]) ? explode(';', $options[1]) : [];
234
                $options_parsed[$id] = [
235
                    'label' => $options[0],
236
                    'options' => $sub_sub_options,
237
                ];
238
                $id++;
239
            }
240
        }
241
242
        return $options_parsed;
243
    }
244
245
    /**
246
     * @param $string
247
     *
248
     * @return array
249
     */
250
    public static function tripleSelectConvertStringToArray($string)
251
    {
252
        $options = [];
253
        foreach (explode('|', $string) as $i => $item0) {
254
            $level1 = explode('\\', $item0);
255
256
            foreach ($level1 as $j => $item1) {
257
                if (0 === $j) {
258
                    $options[] = ['label' => $item1, 'options' => []];
259
260
                    continue;
261
                }
262
263
                foreach (explode(':', $item1) as $k => $item2) {
264
                    if (0 === $k) {
265
                        $options[$i]['options'][] = ['label' => $item2, 'options' => []];
266
267
                        continue;
268
                    }
269
270
                    $options[$i]['options'][$j - 1]['options'][] = explode(';', $item2);
271
                }
272
            }
273
        }
274
275
        array_walk_recursive(
276
            $options,
277
            function (&$item) {
278
                $item = trim($item);
279
            }
280
        );
281
282
        return $options;
283
    }
284
285
    /**
286
     * @param array $options the result of the get_field_options_by_field() array
287
     *
288
     * @return string
289
     */
290
    public static function extra_field_double_select_convert_array_to_string($options)
291
    {
292
        $string = null;
293
        $optionsParsed = self::extra_field_double_select_convert_array_to_ordered_array($options);
294
295
        if (!empty($optionsParsed)) {
296
            foreach ($optionsParsed as $option) {
297
                foreach ($option as $key => $item) {
298
                    $string .= $item['display_text'];
299
                    if (0 == $key) {
300
                        $string .= ':';
301
                    } else {
302
                        if (isset($option[$key + 1])) {
303
                            $string .= ';';
304
                        }
305
                    }
306
                }
307
                $string .= '|';
308
            }
309
        }
310
311
        if (!empty($string)) {
312
            $string = substr($string, 0, strlen($string) - 1);
313
        }
314
315
        return $string;
316
    }
317
318
    /**
319
     * @param array $options The result of the get_field_options_by_field() array
320
     *
321
     * @return string
322
     */
323
    public static function extraFieldSelectWithTextConvertArrayToString(array $options)
324
    {
325
        $parsedOptions = self::extra_field_double_select_convert_array_to_ordered_array($options);
326
327
        if (empty($parsedOptions)) {
328
            return '';
329
        }
330
331
        $string = '';
332
        foreach ($parsedOptions as $options) {
333
            $option = current($options);
334
            $string .= $option['display_text'];
335
            $string .= '|';
336
        }
337
338
        return rtrim($string, '|');
339
    }
340
341
    /**
342
     * @return string
343
     */
344
    public static function tripleSelectConvertArrayToString(array $options)
345
    {
346
        $parsedOptions = self::tripleSelectConvertArrayToOrderedArray($options);
347
        $string = '';
348
        foreach ($parsedOptions['level1'] as $item1) {
349
            $string .= $item1['display_text'];
350
            $level2 = self::getOptionsFromTripleSelect($parsedOptions['level2'], $item1['id']);
351
352
            foreach ($level2 as $item2) {
353
                $string .= '\\'.$item2['display_text'].':';
354
                $level3 = self::getOptionsFromTripleSelect($parsedOptions['level3'], $item2['id']);
355
356
                $string .= implode(';', array_column($level3, 'display_text'));
357
            }
358
359
            $string .= '|';
360
        }
361
362
        return trim($string, '\\|;');
363
    }
364
365
    /**
366
     * @param string $variable
367
     * @param string $dataValue
368
     *
369
     * @return string
370
     */
371
    public static function getLocalizationJavascript($variable, $dataValue)
372
    {
373
        $dataValue = addslashes($dataValue);
374
        $html = "<script>
375
            $(function() {
376
                if (typeof google === 'object') {
377
                    var address = '$dataValue';
378
                    initializeGeo{$variable}(address, false);
379
380
                    $('#geolocalization_extra_{$variable}').on('click', function() {
381
                        var address = $('#{$variable}').val();
382
                        initializeGeo{$variable}(address, false);
383
                        return false;
384
                    });
385
386
                    $('#myLocation_extra_{$variable}').on('click', function() {
387
                        myLocation{$variable}();
388
                        return false;
389
                    });
390
391
                    // When clicking enter
392
                    $('#{$variable}').keypress(function(event) {
393
                        if (event.which == 13) {
394
                            $('#geolocalization_extra_{$variable}').click();
395
                            return false;
396
                        }
397
                    });
398
399
                    // On focus out update city
400
                    $('#{$variable}').focusout(function() {
401
                        $('#geolocalization_extra_{$variable}').click();
402
                        return false;
403
                    });
404
405
                    return;
406
                }
407
408
                $('#map_extra_{$variable}')
409
                    .html('<div class=\"alert alert-info\">"
410
            .addslashes(get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap'))
411
            ."</div>');
412
            });
413
414
            function myLocation{$variable}()
415
            {
416
                if (navigator.geolocation) {
417
                    var geoPosition = function(position) {
418
                        var lat = position.coords.latitude;
419
                        var lng = position.coords.longitude;
420
                        var latLng = new google.maps.LatLng(lat, lng);
421
                        initializeGeo{$variable}(false, latLng);
422
                    };
423
424
                    var geoError = function(error) {
425
                        alert('Geocode ".get_lang('Error').": ' + error);
426
                    };
427
428
                    var geoOptions = {
429
                        enableHighAccuracy: true
430
                    };
431
                    navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
432
                }
433
            }
434
435
            function initializeGeo{$variable}(address, latLng)
436
            {
437
                var geocoder = new google.maps.Geocoder();
438
                var latlng = new google.maps.LatLng(-34.397, 150.644);
439
                var myOptions = {
440
                    zoom: 15,
441
                    center: latlng,
442
                    mapTypeControl: true,
443
                    mapTypeControlOptions: {
444
                        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
445
                    },
446
                    navigationControl: true,
447
                    mapTypeId: google.maps.MapTypeId.ROADMAP
448
                };
449
450
                map_{$variable} = new google.maps.Map(
451
                    document.getElementById('map_extra_{$variable}'),
452
                    myOptions
453
                );
454
455
                var parameter = address ? {'address': address} : latLng ? {'latLng': latLng} : false;
456
457
                if (geocoder && parameter) {
458
                    geocoder.geocode(parameter, function(results, status) {
459
                        if (status == google.maps.GeocoderStatus.OK) {
460
                            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
461
                                map_{$variable}.setCenter(results[0].geometry.location);
462
463
                                // get city and country
464
                                var defaultAddress = results[0].formatted_address;
465
                                var city = '';
466
                                var country = '';
467
468
                                for (var i=0; i<results[0].address_components.length; i++) {
469
                                    if (results[0].address_components[i].types[0] == \"locality\") {
470
                                        //this is the object you are looking for City
471
                                        city = results[0].address_components[i];
472
                                    }
473
                                    /*if (results[j].address_components[i].types[0] == \"administrative_area_level_1\") {
474
                                        //this is the object you are looking for State
475
                                        region = results[0].address_components[i];
476
                                    }*/
477
                                    if (results[0].address_components[i].types[0] == \"country\") {
478
                                        //this is the object you are looking for
479
                                        country = results[0].address_components[i];
480
                                    }
481
                                }
482
483
                                if (city && city.long_name && country && country.long_name) {
484
                                    defaultAddress = city.long_name + ', ' + country.long_name;
485
                                }
486
                                $('#{$variable}').val(defaultAddress);
487
                                $('#{$variable}_coordinates').val(
488
                                    results[0].geometry.location.lat()+','+results[0].geometry.location.lng()
489
                                );
490
491
                                var infowindow = new google.maps.InfoWindow({
492
                                    content: '<b>' + $('#extra_{$variable}').val() + '</b>',
493
                                    size: new google.maps.Size(150, 50)
494
                                });
495
496
                                var marker = new google.maps.Marker({
497
                                    position: results[0].geometry.location,
498
                                    map: map_{$variable},
499
                                    title: $('#extra_{$variable}').val()
500
                                });
501
                                google.maps.event.addListener(marker, 'click', function() {
502
                                    infowindow.open(map_{$variable}, marker);
503
                                });
504
                            } else {
505
                                alert('".get_lang('NotFound')."');
506
                            }
507
                        } else {
508
                            alert('Geocode ".get_lang('Error').': '.get_lang('AddressField').' '.get_lang('NotFound')."');
509
                        }
510
                    });
511
                }
512
            }
513
            </script>";
514
515
        return $html;
516
    }
517
518
    /**
519
     * @param string $variable
520
     * @param string $text
521
     *
522
     * @return string
523
     */
524
    public static function getLocalizationInput($variable, $text)
525
    {
526
        $textHelp = $text;
527
        if (is_array($text)) {
528
            $textHelp = $text[0];
529
        }
530
        return '
531
                <div class="form-group">
532
                    <label for="geolocalization_extra_'.$variable.'"
533
                        class="col-sm-2 control-label"></label>
534
                    <div class="col-sm-8">
535
                        <button class="btn btn-default"
536
                            id="geolocalization_extra_'.$variable.'"
537
                            name="geolocalization_extra_'.$variable.'"
538
                            type="submit">
539
                            <em class="fa fa-map-marker"></em> '.get_lang('SearchGeolocalization').'
540
                        </button>
541
                        <button class="btn btn-default" id="myLocation_extra_'.$variable.'"
542
                            name="myLocation_extra_'.$variable.'"
543
                            type="submit">
544
                            <em class="fa fa-crosshairs"></em> '.get_lang('MyLocation').'
545
                        </button>
546
                    </div>
547
                </div>
548
                <div class="form-group">
549
                    <label for="map_extra_'.$variable.'" class="col-sm-2 control-label">
550
                        '.$textHelp.' - '.get_lang('Map').'
551
                    </label>
552
                    <div class="col-sm-8">
553
                        <div name="map_extra_'.$variable.'"
554
                            id="map_extra_'.$variable.'" style="width:100%; height:300px;">
555
                        </div>
556
                    </div>
557
                </div>
558
            ';
559
    }
560
561
    /**
562
     * @return int
563
     */
564
    public function get_count()
565
    {
566
        $em = Database::getManager();
567
        $query = $em->getRepository(EntityExtraField::class)->createQueryBuilder('e');
568
        $query->select('count(e.id)');
569
        $query->where('e.extraFieldType = :type');
570
        $query->setParameter('type', $this->getExtraFieldType());
571
572
        return $query->getQuery()->getSingleScalarResult();
573
    }
574
575
    /**
576
     * @return int
577
     */
578
    public function getExtraFieldType()
579
    {
580
        return (int) $this->extraFieldType;
581
    }
582
583
    /**
584
     * @param string $sidx
585
     * @param string $sord
586
     * @param int    $start
587
     * @param int    $limit
588
     *
589
     * @return array
590
     */
591
    public function getAllGrid($sidx, $sord, $start, $limit)
592
    {
593
        switch ($sidx) {
594
            case 'field_order':
595
                $sidx = 'e.fieldOrder';
596
                break;
597
            case 'variable':
598
                $sidx = 'e.variable';
599
                break;
600
            case 'display_text':
601
                $sidx = 'e.displayText';
602
                break;
603
            case 'changeable':
604
                $sidx = 'e.changeable';
605
                break;
606
            case 'visible_to_self':
607
                $sidx = 'e.visibleToSelf';
608
                break;
609
            case 'visible_to_others':
610
                $sidx = 'e.visibleToOthers';
611
                break;
612
            case 'filter':
613
                $sidx = 'e.filter';
614
                break;
615
        }
616
        $em = Database::getManager();
617
        $query = $em->getRepository(EntityExtraField::class)->createQueryBuilder('e');
618
        $query->select('e')
619
            ->where('e.extraFieldType = :type')
620
            ->setParameter('type', $this->getExtraFieldType())
621
            ->orderBy($sidx, $sord)
622
            ->setFirstResult($start)
623
            ->setMaxResults($limit);
624
625
        return $query->getQuery()->getArrayResult();
626
    }
627
628
    /**
629
     * Get all the field info for tags.
630
     *
631
     * @param string $variable
632
     *
633
     * @return array|bool
634
     */
635
    public function get_handler_field_info_by_tags($variable)
636
    {
637
        $variable = Database::escape_string($variable);
638
        $sql = "SELECT * FROM {$this->table}
639
                WHERE
640
                    variable = '$variable' AND
641
                    extra_field_type = $this->extraFieldType";
642
        $result = Database::query($sql);
643
        $extraFieldRepo = Container::getExtraFieldRepository();
644
        if (Database::num_rows($result)) {
645
            $row = Database::fetch_array($result, 'ASSOC');
646
            $extraFieldId = $row['id'];
647
            /** @var \Chamilo\CoreBundle\Entity\ExtraField $extraField */
648
            $extraField = $extraFieldRepo->find($extraFieldId);
649
            $row['display_text'] = $extraField->getDisplayText();
650
651
            // All the tags of the field
652
            $sql = "SELECT * FROM $this->table_field_tag
653
                    WHERE field_id='".$extraFieldId."'
654
                    ORDER BY id ASC";
655
            $result = Database::query($sql);
656
            while ($option = Database::fetch_array($result, 'ASSOC')) {
657
                $row['options'][$option['id']] = $option;
658
            }
659
660
            return $row;
661
        }
662
663
        return false;
664
    }
665
666
    /**
667
     * @param int $fieldId
668
     *
669
     * @return array|bool
670
     */
671
    public function getFieldInfoByFieldId($fieldId)
672
    {
673
        $fieldId = (int) $fieldId;
674
        $sql = "SELECT * FROM {$this->table}
675
                WHERE
676
                    id = '$fieldId' AND
677
                    extra_field_type = $this->extraFieldType";
678
        $result = Database::query($sql);
679
        if (Database::num_rows($result)) {
680
            $row = Database::fetch_array($result, 'ASSOC');
681
682
            // All the options of the field
683
            $sql = "SELECT * FROM $this->table_field_options
684
                    WHERE field_id='".$fieldId."'
685
                    ORDER BY option_order ASC";
686
            $result = Database::query($sql);
687
            while ($option = Database::fetch_array($result)) {
688
                $row['options'][$option['id']] = $option;
689
            }
690
691
            return $row;
692
        } else {
693
            return false;
694
        }
695
    }
696
697
    /**
698
     * Add elements to a form.
699
     *
700
     * @param FormValidator $form                            The form object to which to attach this element
701
     * @param int           $itemId                          The item (course, user, session, etc) this extra_field is
702
     *                                                       linked to
703
     * @param array         $exclude                         Variables of extra field to exclude
704
     * @param bool          $filter                          Whether to get only the fields with the "filter" flag set
705
     *                                                       to 1 (true) or not (false)
706
     * @param bool          $useTagAsSelect                  Whether to show tag fields as select drop-down or not
707
     * @param array         $showOnlyTheseFields             Limit the extra fields shown to just the list given here
708
     * @param array         $orderFields                     An array containing the names of the fields shown, in the
709
     *                                                       right order
710
     * @param array         $extraData
711
     * @param bool          $orderDependingDefaults
712
     * @param bool          $adminPermissions
713
     * @param array         $separateExtraMultipleSelect
714
     * @param array         $customLabelsExtraMultipleSelect
715
     * @param bool          $addEmptyOptionSelects
716
     * @param array         $introductionTextList
717
     * @param array         $requiredFields
718
     * @param bool          $hideGeoLocalizationDetails
719
     *
720
     * @throws Exception
721
     *
722
     * @return array|bool If relevant, returns a one-element array with JS code to be added to the page HTML headers.
723
     *                    Returns false if the form object was not given
724
     */
725
    public function addElements(
726
        $form,
727
        $itemId = 0,
728
        $exclude = [],
729
        $filter = false,
730
        $useTagAsSelect = false,
731
        $showOnlyTheseFields = [],
732
        $orderFields = [],
733
        $extraData = [],
734
        $orderDependingDefaults = false,
735
        $adminPermissions = false,
736
        $separateExtraMultipleSelect = [],
737
        $customLabelsExtraMultipleSelect = [],
738
        $addEmptyOptionSelects = false,
739
        $introductionTextList = [],
740
        $requiredFields = [],
741
        $hideGeoLocalizationDetails = false,
742
        $help = false
743
    ) {
744
        if (empty($form)) {
745
            return false;
746
        }
747
748
        $itemId = (int) $itemId;
749
        $form->addHidden('item_id', $itemId);
750
        $extraData = false;
751
        if (!empty($itemId)) {
752
            $extraData = $this->get_handler_extra_data($itemId);
753
            if (!empty($showOnlyTheseFields)) {
754
                $setData = [];
755
                foreach ($showOnlyTheseFields as $variable) {
756
                    $extraName = 'extra_'.$variable;
757
                    if (in_array($extraName, array_keys($extraData))) {
758
                        $setData[$extraName] = $extraData[$extraName];
759
                    }
760
                }
761
                $form->setDefaults($setData);
762
            } else {
763
                $form->setDefaults($extraData);
764
            }
765
        }
766
767
        $conditions = [];
768
        if ($filter) {
769
            $conditions = ['filter = ?' => 1];
770
        }
771
772
        $extraFields = $this->get_all($conditions, 'option_order');
773
        $extra = $this->set_extra_fields_in_form(
774
            $form,
775
            $extraData,
776
            $adminPermissions,
777
            $extraFields,
778
            $itemId,
779
            $exclude,
780
            $useTagAsSelect,
781
            $showOnlyTheseFields,
782
            $orderFields,
783
            $orderDependingDefaults,
784
            $separateExtraMultipleSelect,
785
            $customLabelsExtraMultipleSelect,
786
            $addEmptyOptionSelects,
787
            $introductionTextList,
788
            $hideGeoLocalizationDetails,
789
            $help
790
        );
791
792
        if (!empty($requiredFields)) {
793
            /** @var HTML_QuickForm_input $element */
794
            foreach ($form->getElements() as $element) {
795
                $name = str_replace('extra_', '', $element->getName());
796
                if (in_array($name, $requiredFields)) {
797
                    $form->setRequired($element);
798
                }
799
            }
800
        }
801
802
        return $extra;
803
    }
804
805
    /**
806
     * Return an array of all the extra fields available for this item.
807
     *
808
     * @param int $itemId (session_id, question_id, course id)
809
     *
810
     * @return array
811
     */
812
    public function get_handler_extra_data($itemId)
813
    {
814
        if (empty($itemId)) {
815
            return [];
816
        }
817
818
        $extra_data = [];
819
        $fields = $this->get_all();
820
        $field_values = new ExtraFieldValue($this->type);
821
822
        if (!empty($fields)) {
823
            foreach ($fields as $field) {
824
                $field_value = $fieldValueArray = $field_values->get_values_by_handler_and_field_id(
825
                    $itemId,
826
                    $field['id']
827
                );
828
829
                if (self::FIELD_TYPE_TAG == $field['field_type']) {
830
                    $tags = UserManager::get_user_tags_to_string(
831
                        $itemId,
832
                        $field['id'],
833
                        false
834
                    );
835
                    $extra_data['extra_'.$field['variable']] = $tags;
836
837
                    continue;
838
                }
839
840
                if ($field_value) {
841
                    $variable = $field['variable'];
842
                    $field_value = $field_value['value'];
843
                    switch ($field['field_type']) {
844
                        case self::FIELD_TYPE_FILE_IMAGE:
845
                        case self::FIELD_TYPE_FILE:
846
                            // Get asset id
847
                            $extra_data['extra_'.$field['variable']] = $fieldValueArray['asset_id'] ?? 0;
848
                            break;
849
                        case self::FIELD_TYPE_TAG:
850
                            $tags = UserManager::get_user_tags_to_string(
851
                                $itemId,
852
                                $field['id'],
853
                                false
854
                            );
855
856
                            $extra_data['extra_'.$field['variable']] = $tags;
857
                            break;
858
                        case self::FIELD_TYPE_DOUBLE_SELECT:
859
                        case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
860
                            $selected_options = explode('::', $field_value);
861
                            $firstOption = isset($selected_options[0]) ? $selected_options[0] : '';
862
                            $secondOption = isset($selected_options[1]) ? $selected_options[1] : '';
863
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $firstOption;
864
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable'].'_second'] = $secondOption;
865
866
                            break;
867
                        case self::FIELD_TYPE_SELECT_MULTIPLE:
868
                            $field_value = explode(';', $field_value);
869
                            $extra_data['extra_'.$field['variable']] = $field_value;
870
                            break;
871
                        case self::FIELD_TYPE_RADIO:
872
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $field_value;
873
                            break;
874
                        case self::FIELD_TYPE_TRIPLE_SELECT:
875
                            [$level1, $level2, $level3] = explode(';', $field_value);
876
877
                            $extra_data["extra_$variable"]["extra_$variable"] = $level1;
878
                            $extra_data["extra_$variable"]["extra_{$variable}_second"] = $level2;
879
                            $extra_data["extra_$variable"]["extra_{$variable}_third"] = $level3;
880
                            break;
881
                        default:
882
                            $extra_data['extra_'.$field['variable']] = $field_value;
883
                            break;
884
                    }
885
                } else {
886
                    // Set default values
887
                    if (isset($field['field_default_value']) &&
888
                        !empty($field['field_default_value'])
889
                    ) {
890
                        $extra_data['extra_'.$field['variable']] = $field['field_default_value'];
891
                    }
892
                }
893
            }
894
        }
895
896
        return $extra_data;
897
    }
898
899
    /**
900
     * Get an array of all the values from the extra_field and extra_field_options tables
901
     * based on the current object's type.
902
     *
903
     * @param array $options
904
     * @param null  $order_field_options_by
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $order_field_options_by is correct as it would always require null to be passed?
Loading history...
905
     *
906
     * @return array
907
     */
908
    public function get_all($options = [], $order_field_options_by = null)
909
    {
910
        $options = Database::parse_conditions(['where' => $options]);
911
912
        if (empty($options)) {
913
            $options .= ' WHERE extra_field_type = '.$this->extraFieldType;
914
        } else {
915
            $options .= ' AND extra_field_type = '.$this->extraFieldType;
916
        }
917
918
        $sql = "SELECT * FROM $this->table
919
                $options
920
                ORDER BY field_order ASC
921
        ";
922
923
        $result = Database::query($sql);
924
        $extraFields = Database::store_result($result, 'ASSOC');
925
926
        $extraFieldRepo = Container::getExtraFieldRepository();
927
        $option = new ExtraFieldOption($this->type);
928
        if (!empty($extraFields)) {
929
            foreach ($extraFields as &$extraField) {
930
                $extraFieldId = $extraField['id'];
931
                /** @var \Chamilo\CoreBundle\Entity\ExtraField $extraField */
932
                $field = $extraFieldRepo->find($extraFieldId);
933
                $extraField['display_text'] = $field->getDisplayText();
934
                $extraField['options'] = $option->get_field_options_by_field(
935
                    $extraField['id'],
936
                    false,
937
                    $order_field_options_by
938
                );
939
            }
940
        }
941
942
        return $extraFields;
943
    }
944
945
    /**
946
     * Add an element that matches the given extra field to the given $form object.
947
     *
948
     * @param FormValidator $form                The form these fields are to be attached to
949
     * @param array         $extraData
950
     * @param bool          $adminPermissions    Whether the display is considered without edition limits (true) or not
951
     *                                           (false)
952
     * @param array         $extra
953
     * @param int           $itemId              The item (course, user, session, etc) this extra_field is attached to
954
     * @param array         $exclude             Extra fields to be skipped, by textual ID
955
     * @param bool          $useTagAsSelect      Whether to show tag fields as select drop-down or not
956
     * @param array         $showOnlyTheseFields Limit the extra fields shown to just the list given here
957
     * @param array         $orderFields         An array containing the names of the fields shown, in the right order
958
     *
959
     * @throws Exception
960
     *
961
     * @return array If relevant, returns a one-element array with JS code to be added to the page HTML headers
962
     */
963
    public function set_extra_fields_in_form(
964
        $form,
965
        $extraData,
966
        $adminPermissions = false,
967
        $extra = [],
968
        $itemId = null,
969
        $exclude = [],
970
        $useTagAsSelect = false,
971
        $showOnlyTheseFields = [],
972
        $orderFields = [],
973
        $orderDependingDefaults = false,
974
        $separateExtraMultipleSelect = [],
975
        $customLabelsExtraMultipleSelect = [],
976
        $addEmptyOptionSelects = false,
977
        $introductionTextList = [],
978
        $hideGeoLocalizationDetails = false,
979
        $help = false
980
    ) {
981
        $jquery_ready_content = null;
982
983
        $assetRepo = Container::getAssetRepository();
984
        $extraFieldRepo = Container::getExtraFieldRepository();
985
986
        if (!empty($extra)) {
987
            $newOrder = [];
988
            if (!empty($orderFields)) {
989
                foreach ($orderFields as $order) {
990
                    foreach ($extra as $field_details) {
991
                        if ($order == $field_details['variable']) {
992
                            $newOrder[] = $field_details;
993
                        }
994
                    }
995
                }
996
                $extra = $newOrder;
997
            }
998
999
            foreach ($extra as $field_details) {
1000
                $variable = $field_details['variable'];
1001
                if (!empty($showOnlyTheseFields)) {
1002
                    if (!in_array($variable, $showOnlyTheseFields)) {
1003
                        continue;
1004
                    }
1005
                }
1006
1007
                // Getting default value id if is set
1008
                $defaultValueId = null;
1009
                if (isset($field_details['options']) && !empty($field_details['options'])) {
1010
                    $valueToFind = null;
1011
                    if (isset($field_details['field_default_value'])) {
1012
                        $valueToFind = $field_details['field_default_value'];
1013
                    }
1014
                    // If a value is found we override the default value
1015
                    if (isset($extraData['extra_'.$variable])) {
1016
                        $valueToFind = $extraData['extra_'.$variable];
1017
                    }
1018
1019
                    foreach ($field_details['options'] as $option) {
1020
                        if ($option['option_value'] == $valueToFind) {
1021
                            $defaultValueId = $option['id'];
1022
                        }
1023
                    }
1024
                }
1025
1026
                if (!$adminPermissions) {
1027
                    if (0 == $field_details['visible_to_self']) {
1028
                        continue;
1029
                    }
1030
1031
                    if (in_array($variable, $exclude)) {
1032
                        continue;
1033
                    }
1034
                }
1035
1036
                if (!empty($introductionTextList) &&
1037
                    in_array($variable, array_keys($introductionTextList))
1038
                ) {
1039
                    $form->addHtml($introductionTextList[$variable]);
1040
                }
1041
1042
                $freezeElement = false;
1043
                if (!$adminPermissions) {
1044
                    $freezeElement = 0 == $field_details['visible_to_self'] || 0 == $field_details['changeable'];
1045
                }
1046
1047
                //$translatedDisplayText = $field_details['display_text'];
1048
                /** @var \Chamilo\CoreBundle\Entity\ExtraField $extraField */
1049
                $extraField = $extraFieldRepo->find($field_details['id']);
1050
                $translatedDisplayText = $extraField->getDisplayText();
1051
1052
                $translatedDisplayHelpText = '';
1053
                if ($help) {
1054
                    $translatedDisplayHelpText .= get_lang($field_details['display_text'].'Help');
1055
                }
1056
1057
                if (!empty($translatedDisplayText)) {
1058
                    if (!empty($translatedDisplayHelpText)) {
1059
                        // In this case, exceptionally, display_text is an array
1060
                        // which is then treated by display_form()
1061
                        $field_details['display_text'] = [$translatedDisplayText, $translatedDisplayHelpText];
1062
                    } else {
1063
                        // We have an helper text, use it
1064
                        $field_details['display_text'] = $translatedDisplayText;
1065
                    }
1066
                }
1067
1068
                switch ($field_details['field_type']) {
1069
                    case self::FIELD_TYPE_TEXT:
1070
                        $form->addElement(
1071
                            'text',
1072
                            'extra_'.$variable,
1073
                            $field_details['display_text'],
1074
                            [
1075
                                'id' => 'extra_'.$variable,
1076
                            ]
1077
                        );
1078
                        $form->applyFilter(
1079
                            'extra_'.$variable,
1080
                            'stripslashes'
1081
                        );
1082
                        $form->applyFilter(
1083
                            'extra_'.$variable,
1084
                            'trim'
1085
                        );
1086
                        if ($freezeElement) {
1087
                            $form->freeze('extra_'.$variable);
1088
                        }
1089
                        break;
1090
                    case self::FIELD_TYPE_TEXTAREA:
1091
                        $form->addHtmlEditor(
1092
                            'extra_'.$variable,
1093
                            $field_details['display_text'],
1094
                            false,
1095
                            false,
1096
                            [
1097
                                'ToolbarSet' => 'Profile',
1098
                                'Width' => '100%',
1099
                                'Height' => '130',
1100
                                'id' => 'extra_'.$variable,
1101
                            ]
1102
                        );
1103
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1104
                        $form->applyFilter('extra_'.$variable, 'trim');
1105
                        if ($freezeElement) {
1106
                            $form->freeze('extra_'.$variable);
1107
                        }
1108
                        break;
1109
                    case self::FIELD_TYPE_RADIO:
1110
                        $group = [];
1111
                        if (isset($field_details['options']) &&
1112
                            !empty($field_details['options'])
1113
                        ) {
1114
                            foreach ($field_details['options'] as $option_details) {
1115
                                $options[$option_details['option_value']] = $option_details['display_text'];
1116
                                $group[] = $form->createElement(
1117
                                    'radio',
1118
                                    'extra_'.$variable,
1119
                                    $option_details['option_value'],
1120
                                    $option_details['display_text'].'<br />',
1121
                                    $option_details['option_value']
1122
                                );
1123
                            }
1124
                        }
1125
                        $form->addGroup(
1126
                            $group,
1127
                            'extra_'.$variable,
1128
                            $field_details['display_text']
1129
                        );
1130
                        if ($freezeElement) {
1131
                            $form->freeze('extra_'.$variable);
1132
                        }
1133
                        break;
1134
                    case self::FIELD_TYPE_CHECKBOX:
1135
                        $group = [];
1136
                        if (isset($field_details['options']) &&
1137
                            !empty($field_details['options'])
1138
                        ) {
1139
                            foreach ($field_details['options'] as $option_details) {
1140
                                $options[$option_details['option_value']] = $option_details['display_text'];
1141
                                $group[] = $form->createElement(
1142
                                    'checkbox',
1143
                                    'extra_'.$variable,
1144
                                    $option_details['option_value'],
1145
                                    $option_details['display_text'].'<br />',
1146
                                    $option_details['option_value']
1147
                                );
1148
                            }
1149
                        } else {
1150
                            $fieldVariable = "extra_$variable";
1151
                            $checkboxAttributes = [];
1152
                            if (is_array($extraData) &&
1153
                                array_key_exists($fieldVariable, $extraData)
1154
                            ) {
1155
                                if (!empty($extraData[$fieldVariable])) {
1156
                                    $checkboxAttributes['checked'] = 1;
1157
                                }
1158
                            }
1159
1160
                            if (empty($checkboxAttributes) &&
1161
                                isset($field_details['default_value']) && empty($extraData)) {
1162
                                if (1 == $field_details['default_value']) {
1163
                                    $checkboxAttributes['checked'] = 1;
1164
                                }
1165
                            }
1166
1167
                            // We assume that is a switch on/off with 1 and 0 as values
1168
                            $group[] = $form->createElement(
1169
                                'checkbox',
1170
                                'extra_'.$variable,
1171
                                null,
1172
                                get_lang('Yes'),
1173
                                $checkboxAttributes
1174
                            );
1175
                        }
1176
1177
                        $form->addGroup(
1178
                            $group,
1179
                            'extra_'.$variable,
1180
                            $field_details['display_text']
1181
                        );
1182
                        if ($freezeElement) {
1183
                            $form->freeze('extra_'.$variable);
1184
                        }
1185
                        break;
1186
                    case self::FIELD_TYPE_SELECT:
1187
                        $this->addSelectElement($form, $field_details, $defaultValueId, $freezeElement);
1188
                        break;
1189
                    case self::FIELD_TYPE_SELECT_MULTIPLE:
1190
                        $options = [];
1191
                        if (empty($defaultValueId)) {
1192
                            $options[''] = get_lang('Please select an option');
1193
                        }
1194
                        if (isset($field_details['options']) && !empty($field_details['options'])) {
1195
                            foreach ($field_details['options'] as $optionDetails) {
1196
                                $options[$optionDetails['option_value']] = $optionDetails['display_text'];
1197
                            }
1198
                        }
1199
1200
                        if ($orderDependingDefaults) {
1201
                            if (isset($extraData['extra_'.$variable])) {
1202
                                $defaultOptions = $extraData['extra_'.$variable];
1203
                                $firstList = [];
1204
                                if ($addEmptyOptionSelects) {
1205
                                    $firstList[] = '';
1206
                                }
1207
                                foreach ($defaultOptions as $key) {
1208
                                    if (isset($options[$key])) {
1209
                                        $firstList[$key] = $options[$key];
1210
                                    }
1211
                                }
1212
                                if (!empty($firstList)) {
1213
                                    $options = array_merge($firstList, $options);
1214
                                }
1215
                            } else {
1216
                                $firstList = [];
1217
                                if ($addEmptyOptionSelects) {
1218
                                    $firstList[] = '&nbsp;';
1219
                                    $options = array_merge($firstList, $options);
1220
                                }
1221
                            }
1222
                        }
1223
                        // OFAJ
1224
                        $separateValue = 0;
1225
                        if (isset($separateExtraMultipleSelect[$variable])) {
1226
                            $separateValue = $separateExtraMultipleSelect[$variable];
1227
                        }
1228
1229
                        if ($separateValue > 0) {
1230
                            for ($i = 0; $i < $separateValue; $i++) {
1231
                                $form->addSelect(
1232
                                    'extra_'.$variable.'['.$i.']',
1233
                                    $customLabelsExtraMultipleSelect[$variable][$i],
1234
                                    $options,
1235
                                    ['id' => 'extra_'.$variable.'_'.$i]
1236
                                );
1237
                            }
1238
                        } else {
1239
                            // Ofaj
1240
                            $attributes = ['multiple' => 'multiple', 'id' => 'extra_'.$variable];
1241
                            $chosenSelect = [
1242
                                'ecouter',
1243
                                'lire',
1244
                                'participer_a_une_conversation',
1245
                                's_exprimer_oralement_en_continu',
1246
                                'ecrire',
1247
                            ];
1248
1249
                            if (in_array($variable, $chosenSelect)) {
1250
                                $attributes['select_chosen'] = true;
1251
                            }
1252
1253
                            // default behaviour
1254
                            $form->addSelect(
1255
                                'extra_'.$variable,
1256
                                $field_details['display_text'],
1257
                                $options,
1258
                                $attributes,
1259
                            );
1260
1261
                        }
1262
1263
                        if ($freezeElement) {
1264
                            $form->freeze('extra_'.$variable);
1265
                        }
1266
                        /*$form->addSelect(
1267
                            'extra_'.$variable,
1268
                            $field_details['display_text'],
1269
                            $options,
1270
                            [
1271
                                'multiple' => 'multiple',
1272
                                'id' => 'extra_'.$variable,
1273
                            ]
1274
                        );
1275
                        if ($freezeElement) {
1276
                            $form->freeze('extra_'.$variable);
1277
                        }*/
1278
                        break;
1279
                    case self::FIELD_TYPE_DATE:
1280
                        $form->addDatePicker('extra_'.$variable, $field_details['display_text']);
1281
                        if ($freezeElement) {
1282
                            $form->freeze('extra_'.$variable);
1283
                        }
1284
                        break;
1285
                    case self::FIELD_TYPE_DATETIME:
1286
                        $form->addDateTimePicker(
1287
                            'extra_'.$variable,
1288
                            $field_details['display_text']
1289
                        );
1290
1291
                        $defaults['extra_'.$variable] = api_get_local_time();
1292
                        if (!isset($form->_defaultValues['extra_'.$variable])) {
1293
                            $form->setDefaults($defaults);
1294
                        }
1295
                        if ($freezeElement) {
1296
                            $form->freeze('extra_'.$variable);
1297
                        }
1298
                        break;
1299
                    case self::FIELD_TYPE_DOUBLE_SELECT:
1300
                        $jquery_ready_content .= self::addDoubleSelectElement(
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::addDoubleSelectElement() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1300
                        $jquery_ready_content .= self::/** @scrutinizer ignore-call */ addDoubleSelectElement(
Loading history...
1301
                            $form,
1302
                            $field_details,
1303
                            $extraData,
1304
                            $freezeElement
1305
                        );
1306
                        break;
1307
                    case self::FIELD_TYPE_DIVIDER:
1308
                        $form->addHtml('
1309
                            <div class="form-group ">
1310
                                <div class="col-sm-12">
1311
                                    <div class="panel-separator">
1312
                                       <h4 id="'.$variable.'" class="form-separator">'
1313
                                            .$field_details['display_text'].'
1314
                                       </h4>
1315
                                    </div>
1316
                                </div>
1317
                            </div>
1318
                        ');
1319
                        break;
1320
                    case self::FIELD_TYPE_TAG:
1321
                        $field_id = $field_details['id'];
1322
                        $separateValue = 0;
1323
                        if (isset($separateExtraMultipleSelect[$variable])) {
1324
                            $separateValue = $separateExtraMultipleSelect[$variable];
1325
                        }
1326
1327
                        $selectedOptions = [];
1328
                        if ($separateValue > 0) {
1329
                            $em = Database::getManager();
1330
                            $fieldTags = $em
1331
                                ->getRepository(ExtraFieldRelTag::class)
1332
                                ->findBy(
1333
                                    [
1334
                                        'field' => $field_id,
1335
                                        'itemId' => $itemId,
1336
                                    ]
1337
                                );
1338
                            // ofaj.
1339
                            for ($i = 0; $i < $separateValue; $i++) {
1340
                                $tagsSelect = $form->addSelect(
1341
                                    'extra_'.$variable.'['.$i.']',
1342
                                    $customLabelsExtraMultipleSelect[$variable][$i], //$field_details['display_text'],
1343
                                    [],
1344
                                    ['id' => 'extra_'.$variable.'_'.$i]
1345
                                );
1346
1347
                                if ($addEmptyOptionSelects) {
1348
                                    $tagsSelect->addOption(
1349
                                        '',
1350
                                        ''
1351
                                    );
1352
                                }
1353
                                /** @var ExtraFieldRelTag $fieldTag */
1354
                                foreach ($fieldTags as $fieldTag) {
1355
                                    $tag = $fieldTag->getTag();
1356
1357
                                    if (empty($tag)) {
1358
                                        continue;
1359
                                    }
1360
1361
                                    $tagsSelect->addOption(
1362
                                        $tag->getTag(),
1363
                                        $tag->getTag()
1364
                                    );
1365
                                }
1366
                            }
1367
                        } else {
1368
                            $tagsSelect = $form->addSelect(
1369
                                "extra_{$variable}",
1370
                                $field_details['display_text'],
1371
                                [],
1372
                                ['style' => 'width: 100%;']
1373
                            );
1374
1375
                            if (false === $useTagAsSelect) {
1376
                                $tagsSelect->setAttribute('class', null);
1377
                            }
1378
1379
                            $tagsSelect->setAttribute(
1380
                                'id',
1381
                                "extra_{$variable}"
1382
                            );
1383
                            $tagsSelect->setMultiple(true);
1384
1385
                            $selectedOptions = [];
1386
                            if ('user' === $this->type) {
1387
                                // The magic should be here
1388
                                $user_tags = UserManager::get_user_tags(
1389
                                    $itemId,
1390
                                    $field_details['id']
1391
                                );
1392
1393
                                if (is_array($user_tags) && count($user_tags) > 0) {
1394
                                    foreach ($user_tags as $tag) {
1395
                                        if (empty($tag['tag'])) {
1396
                                            continue;
1397
                                        }
1398
                                        $tagsSelect->addOption(
1399
                                            $tag['tag'],
1400
                                            $tag['tag'],
1401
                                            [
1402
                                                'selected' => 'selected',
1403
                                                'class' => 'selected',
1404
                                            ]
1405
                                        );
1406
                                        $selectedOptions[] = $tag['tag'];
1407
                                    }
1408
                                }
1409
                                $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
1410
                            } else {
1411
                                $em = Database::getManager();
1412
                                $fieldTags = $em->getRepository(
1413
                                    ExtraFieldRelTag::class
1414
                                )
1415
                                ->findBy(
1416
                                    [
1417
                                        'field' => $field_id,
1418
                                        'itemId' => $itemId,
1419
                                    ]
1420
                                );
1421
1422
                                /** @var ExtraFieldRelTag $fieldTag */
1423
                                foreach ($fieldTags as $fieldTag) {
1424
                                    $tag = $fieldTag->getTag();
1425
                                    if (empty($tag)) {
1426
                                        continue;
1427
                                    }
1428
                                    $tagsSelect->addOption(
1429
                                        $tag->getTag(),
1430
                                        $tag->getTag()
1431
                                    );
1432
                                    $selectedOptions[] = $tag->getTag();
1433
                                }
1434
1435
                                if (!empty($extraData) && isset($extraData['extra_'.$variable])) {
1436
                                    $data = $extraData['extra_'.$variable];
1437
                                    if (!empty($data)) {
1438
                                        foreach ($data as $option) {
1439
                                            $tagsSelect->addOption(
1440
                                                $option,
1441
                                                $option
1442
                                            );
1443
                                        }
1444
                                    }
1445
                                }
1446
1447
                                if ($useTagAsSelect) {
1448
                                    $fieldTags = $em->getRepository(ExtraFieldRelTag::class)
1449
                                        ->findBy(
1450
                                            [
1451
                                                'field' => $field_id,
1452
                                            ]
1453
                                        );
1454
                                    $tagsAdded = [];
1455
                                    /** @var ExtraFieldRelTag $fieldTag */
1456
                                    foreach ($fieldTags as $fieldTag) {
1457
                                        $tag = $fieldTag->getTag();
1458
1459
                                        if (empty($tag)) {
1460
                                            continue;
1461
                                        }
1462
1463
                                        $tagText = $tag->getTag();
1464
                                        if (in_array($tagText, $tagsAdded)) {
1465
                                            continue;
1466
                                        }
1467
1468
                                        $tagsSelect->addOption(
1469
                                            $tag->getTag(),
1470
                                            $tag->getTag(),
1471
                                            []
1472
                                        );
1473
1474
                                        $tagsAdded[] = $tagText;
1475
                                    }
1476
                                }
1477
                                $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
1478
                            }
1479
1480
                            $form->setDefaults(
1481
                                [
1482
                                    'extra_'.$variable => $selectedOptions,
1483
                                ]
1484
                            );
1485
1486
                            if (false == $useTagAsSelect) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1487
                                $jquery_ready_content .= "
1488
                                $('#extra_$variable').select2({
1489
                                    ajax: {
1490
                                        url: '$url?a=search_tags&field_id=$field_id&type={$this->type}',
1491
                                        processResults: function (data) {
1492
                                            return {
1493
                                                results: data.items
1494
                                            }
1495
                                        }
1496
                                    },
1497
                                    cache: false,
1498
                                    tags: true,
1499
                                    tokenSeparators: [','],
1500
                                    placeholder: '".get_lang('Start to type, then click on this bar to validate tag')."'
1501
                                });
1502
                            ";
1503
                            }
1504
                        }
1505
1506
                        break;
1507
                    case self::FIELD_TYPE_TIMEZONE:
1508
                        $form->addSelect(
1509
                            'extra_'.$variable,
1510
                            $field_details['display_text'],
1511
                            api_get_timezones(),
1512
                        );
1513
                        if ($freezeElement) {
1514
                            $form->freeze('extra_'.$variable);
1515
                        }
1516
                        break;
1517
                    case self::FIELD_TYPE_SOCIAL_PROFILE:
1518
                        // get the social network's favicon
1519
                        $extra_data_variable = isset($extraData['extra_'.$variable]) ? $extraData['extra_'.$variable] : null;
1520
                        $field_default_value = isset($field_details['field_default_value']) ? $field_details['field_default_value'] : null;
1521
                        $icon_path = UserManager::get_favicon_from_url(
1522
                            $extra_data_variable,
1523
                            $field_default_value
1524
                        );
1525
                        // special hack for hi5
1526
                        $leftpad = '1.7';
1527
                        $top = '0.4';
1528
                        $domain = parse_url($icon_path, PHP_URL_HOST);
1529
                        if ('www.hi5.com' === $domain || 'hi5.com' === $domain) {
1530
                            $leftpad = '3';
1531
                            $top = '0';
1532
                        }
1533
                        // print the input field
1534
                        $form->addElement(
1535
                            'text',
1536
                            'extra_'.$variable,
1537
                            $field_details['display_text'],
1538
                            [
1539
                                //'size' => 60,
1540
                                'size' => implode(
1541
                                    '; ',
1542
                                    [
1543
                                        "background-image: url('$icon_path')",
1544
                                        'background-repeat: no-repeat',
1545
                                        "background-position: 0.4em {$top}em",
1546
                                        "padding-left: {$leftpad}em",
1547
                                    ]
1548
                                ),
1549
                            ]
1550
                        );
1551
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1552
                        $form->applyFilter('extra_'.$variable, 'trim');
1553
                        if ($freezeElement) {
1554
                            $form->freeze('extra_'.$variable);
1555
                        }
1556
                        break;
1557
                    case self::FIELD_TYPE_MOBILE_PHONE_NUMBER:
1558
                        $form->addElement(
1559
                            'text',
1560
                            'extra_'.$variable,
1561
                            $field_details['display_text'].' ('.get_lang('Include the country dial code').')',
1562
                            ['size' => 40, 'placeholder' => '(xx)xxxxxxxxx']
1563
                        );
1564
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1565
                        $form->applyFilter('extra_'.$variable, 'trim');
1566
                        $form->applyFilter('extra_'.$variable, 'mobile_phone_number_filter');
1567
                        $form->addRule(
1568
                            'extra_'.$variable,
1569
                            get_lang('Mobile phone number is incomplete or contains invalid characters'),
1570
                            'mobile_phone_number'
1571
                        );
1572
                        if ($freezeElement) {
1573
                            $form->freeze('extra_'.$variable);
1574
                        }
1575
                        break;
1576
                    case self::FIELD_TYPE_INTEGER:
1577
                        $form->addElement(
1578
                            'number',
1579
                            'extra_'.$variable,
1580
                            $field_details['display_text'],
1581
                            ['class' => 'span1', 'step' => 1]
1582
                        );
1583
1584
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1585
                        $form->applyFilter('extra_'.$variable, 'trim');
1586
                        $form->applyFilter('extra_'.$variable, 'intval');
1587
1588
                        if ($freezeElement) {
1589
                            $form->freeze('extra_'.$variable);
1590
                        }
1591
                        break;
1592
                    case self::FIELD_TYPE_FLOAT:
1593
                        $form->addElement(
1594
                            'number',
1595
                            'extra_'.$variable,
1596
                            $field_details['display_text'],
1597
                            ['class' => 'span1', 'step' => '0.01']
1598
                        );
1599
1600
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1601
                        $form->applyFilter('extra_'.$variable, 'trim');
1602
                        $form->applyFilter('extra_'.$variable, 'floatval');
1603
1604
                        if ($freezeElement) {
1605
                            $form->freeze('extra_'.$variable);
1606
                        }
1607
                        break;
1608
                    case self::FIELD_TYPE_FILE_IMAGE:
1609
                        $fieldVariable = "extra_{$variable}";
1610
                        $fieldTexts = [
1611
                            $field_details['display_text'],
1612
                        ];
1613
1614
                        if (is_array($extraData) && array_key_exists($fieldVariable, $extraData)) {
1615
                            $assetId = $extraData[$fieldVariable];
1616
                            if (!empty($assetId)) {
1617
                                $asset = $assetRepo->find($assetId);
1618
                                if (null !== $asset) {
1619
                                    $fieldTexts[] = Display::img(
1620
                                        $assetRepo->getAssetUrl($asset),
1621
                                        $field_details['display_text'],
1622
                                        ['width' => '300'],
1623
                                        false
1624
                                    );
1625
                                }
1626
                            }
1627
                        }
1628
1629
                        if ('Image' === $fieldTexts[0]) {
1630
                            $fieldTexts[0] = get_lang($fieldTexts[0]);
1631
                        }
1632
1633
                        $form->addFile(
1634
                            $fieldVariable,
1635
                            $fieldTexts,
1636
                            ['accept' => 'image/*', 'id' => 'extra_image', 'crop_image' => 'true']
1637
                        );
1638
1639
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1640
                        $form->applyFilter('extra_'.$variable, 'trim');
1641
1642
                        $allowedPictureTypes = ['jpg', 'jpeg', 'png', 'gif'];
1643
                        $form->addRule(
1644
                            'extra_'.$variable,
1645
                            get_lang('Only PNG, JPG or GIF images allowed').' ('.implode(',', $allowedPictureTypes).')',
1646
                            'filetype',
1647
                            $allowedPictureTypes
1648
                        );
1649
1650
                        if ($freezeElement) {
1651
                            $form->freeze('extra_'.$variable);
1652
                        }
1653
                        break;
1654
                    case self::FIELD_TYPE_FILE:
1655
                        $fieldVariable = "extra_{$variable}";
1656
                        $fieldTexts = [
1657
                            $field_details['display_text'],
1658
                        ];
1659
1660
                        if (is_array($extraData) &&
1661
                            array_key_exists($fieldVariable, $extraData)
1662
                        ) {
1663
                            $assetId = $extraData[$fieldVariable] ?? 0;
1664
                            /** @var Asset $asset */
1665
                            $asset = $assetRepo->find($assetId);
1666
                            if (null !== $asset) {
1667
                                $fileName = $asset->getTitle();
1668
                                $linkUrl = $assetRepo->getAssetUrl($asset);
1669
                                $linkToDelete = '';
1670
                                if (api_is_platform_admin()) {
1671
                                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?type='.$this->type;
1672
                                    $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId;
1673
                                    $deleteId = $variable.'_delete';
1674
                                    $form->addHtml(
1675
                                        "
1676
                                        <script>
1677
                                            $(function() {
1678
                                                $('#".$deleteId."').on('click', function() {
1679
                                                    $.ajax({
1680
                                                        type: 'GET',
1681
                                                        url: '".$url."',
1682
                                                        success: function(result) {
1683
                                                            if (result == 1) {
1684
                                                                $('#".$variable."').html('".get_lang('Deleted')."');
1685
                                                            }
1686
                                                        }
1687
                                                    });
1688
                                                });
1689
                                            });
1690
                                        </script>
1691
                                    "
1692
                                    );
1693
1694
                                    $linkToDelete = '&nbsp;'.Display::url(
1695
                                        Display::return_icon('delete.png', get_lang('Delete')),
1696
                                        'javascript:void(0)',
1697
                                        ['id' => $deleteId]
1698
                                    );
1699
                                }
1700
                                $anchor = Display::url(
1701
                                    $fileName,
1702
                                    $linkUrl,
1703
                                    [
1704
                                        'title' => $field_details['display_text'],
1705
                                        'target' => '_blank',
1706
                                    ]
1707
                                );
1708
                                $fieldTexts[] = '<div id="'.$variable.'">'.$anchor.$linkToDelete.'</div>';
1709
                            }
1710
                        }
1711
1712
                        $form->addElement(
1713
                            'file',
1714
                            $fieldVariable,
1715
                            $fieldTexts,
1716
                            []
1717
                        );
1718
1719
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1720
                        $form->applyFilter('extra_'.$variable, 'trim');
1721
1722
                        if ($freezeElement) {
1723
                            $form->freeze('extra_'.$variable);
1724
                        }
1725
                        break;
1726
                    case self::FIELD_TYPE_VIDEO_URL:
1727
                        $form->addUrl(
1728
                            "extra_{$variable}",
1729
                            $field_details['display_text'],
1730
                            false,
1731
                            ['placeholder' => 'https://']
1732
                        );
1733
                        if ($freezeElement) {
1734
                            $form->freeze('extra_'.$variable);
1735
                        }
1736
                        break;
1737
                    case self::FIELD_TYPE_LETTERS_ONLY:
1738
                        $form->addTextLettersOnly(
1739
                            "extra_{$variable}",
1740
                            $field_details['display_text']
1741
                        );
1742
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1743
1744
                        if ($freezeElement) {
1745
                            $form->freeze('extra_'.$variable);
1746
                        }
1747
                        break;
1748
                    case self::FIELD_TYPE_ALPHANUMERIC:
1749
                        $form->addTextAlphanumeric(
1750
                            "extra_{$variable}",
1751
                            $field_details['display_text']
1752
                        );
1753
                        $form->applyFilter(
1754
                            'extra_'.$variable,
1755
                            'stripslashes'
1756
                        );
1757
                        if ($freezeElement) {
1758
                            $form->freeze('extra_'.$variable);
1759
                        }
1760
                        break;
1761
                    case self::FIELD_TYPE_LETTERS_SPACE:
1762
                        $form->addTextLettersAndSpaces(
1763
                            "extra_{$variable}",
1764
                            $field_details['display_text']
1765
                        );
1766
                        $form->applyFilter('extra_'.$variable, 'stripslashes');
1767
1768
                        if ($freezeElement) {
1769
                            $form->freeze('extra_'.$variable);
1770
                        }
1771
                        break;
1772
                    case self::FIELD_TYPE_ALPHANUMERIC_SPACE:
1773
                        $form->addTextAlphanumericAndSpaces(
1774
                            "extra_{$variable}",
1775
                            $field_details['display_text']
1776
                        );
1777
                        $form->applyFilter(
1778
                            'extra_'.$variable,
1779
                            'stripslashes'
1780
                        );
1781
                        if ($freezeElement) {
1782
                            $form->freeze('extra_'.$variable);
1783
                        }
1784
                        break;
1785
                    case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
1786
                    case self::FIELD_TYPE_GEOLOCALIZATION:
1787
                        $dataValue = isset($extraData['extra_'.$variable]) ? $extraData['extra_'.$variable] : '';
1788
                        $form->addGeoLocationMapField(
1789
                            'extra_'.$variable,
1790
                            $field_details['display_text'],
1791
                            $dataValue,
1792
                            $hideGeoLocalizationDetails
1793
                        );
1794
1795
                        if ($freezeElement) {
1796
                            $form->freeze('extra_'.$variable);
1797
                        }
1798
                        break;
1799
                    case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
1800
                        $jquery_ready_content .= $this->addSelectWithTextFieldElement(
1801
                            $form,
1802
                            $field_details,
1803
                            $freezeElement
1804
                        );
1805
                        break;
1806
                    case self::FIELD_TYPE_TRIPLE_SELECT:
1807
                        $jquery_ready_content .= $this->addTripleSelectElement(
1808
                            $form,
1809
                            $field_details,
1810
                            is_array($extraData) ? $extraData : [],
1811
                            $freezeElement
1812
                        );
1813
                        break;
1814
                }
1815
            }
1816
        }
1817
1818
        $return = [];
1819
        $return['jquery_ready_content'] = $jquery_ready_content;
1820
1821
        return $return;
1822
    }
1823
1824
    /**
1825
     * @param array $options
1826
     *
1827
     * @return array
1828
     */
1829
    public static function extra_field_double_select_convert_array_to_ordered_array($options)
1830
    {
1831
        $optionsParsed = [];
1832
        if (!empty($options)) {
1833
            foreach ($options as $option) {
1834
                if (0 == $option['option_value']) {
1835
                    $optionsParsed[$option['id']][] = $option;
1836
                } else {
1837
                    $optionsParsed[$option['option_value']][] = $option;
1838
                }
1839
            }
1840
        }
1841
1842
        return $optionsParsed;
1843
    }
1844
1845
    /**
1846
     * @return array
1847
     */
1848
    public static function tripleSelectConvertArrayToOrderedArray(array $options)
1849
    {
1850
        $level1 = self::getOptionsFromTripleSelect($options, 0);
1851
        $level2 = [];
1852
        $level3 = [];
1853
1854
        foreach ($level1 as $item1) {
1855
            $level2 += self::getOptionsFromTripleSelect($options, $item1['id']);
1856
        }
1857
1858
        foreach ($level2 as $item2) {
1859
            $level3 += self::getOptionsFromTripleSelect($options, $item2['id']);
1860
        }
1861
1862
        return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3];
1863
    }
1864
1865
    /**
1866
     * @param string $type
1867
     *
1868
     * @return array
1869
     */
1870
    public function get_all_extra_field_by_type($type)
1871
    {
1872
        // all the information of the field
1873
        $sql = "SELECT * FROM {$this->table}
1874
                WHERE
1875
                    field_type = '".Database::escape_string($type)."' AND
1876
                    extra_field_type = $this->extraFieldType
1877
                ";
1878
        $result = Database::query($sql);
1879
1880
        $return = [];
1881
        while ($row = Database::fetch_array($result)) {
1882
            $return[] = $row['id'];
1883
        }
1884
1885
        return $return;
1886
    }
1887
1888
    /**
1889
     * @param int $id
1890
     */
1891
    public function get_field_type_by_id($id)
1892
    {
1893
        $types = $this->get_field_types();
1894
        if (isset($types[$id])) {
1895
            return $types[$id];
1896
        }
1897
1898
        return null;
1899
    }
1900
1901
    /**
1902
     * @return array
1903
     */
1904
    public function get_field_types()
1905
    {
1906
        return $this->get_extra_fields_by_handler($this->type);
1907
    }
1908
1909
    /**
1910
     * @param string $handler
1911
     *
1912
     * @return array
1913
     */
1914
    public static function get_extra_fields_by_handler($handler)
1915
    {
1916
        $types = [];
1917
        $types[self::FIELD_TYPE_TEXT] = get_lang('Text');
1918
        $types[self::FIELD_TYPE_TEXTAREA] = get_lang('Text area');
1919
        $types[self::FIELD_TYPE_RADIO] = get_lang('Radio buttons');
1920
        $types[self::FIELD_TYPE_SELECT] = get_lang('Select drop-down');
1921
        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('Multiple selection drop-down');
1922
        $types[self::FIELD_TYPE_DATE] = get_lang('Date');
1923
        $types[self::FIELD_TYPE_DATETIME] = get_lang('Date and time');
1924
        $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('Double select');
1925
        $types[self::FIELD_TYPE_DIVIDER] = get_lang('Visual divider');
1926
        $types[self::FIELD_TYPE_TAG] = get_lang('User tag');
1927
        $types[self::FIELD_TYPE_TIMEZONE] = get_lang('Timezone');
1928
        $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('Social network link');
1929
        $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('Mobile phone number');
1930
        $types[self::FIELD_TYPE_CHECKBOX] = get_lang('Checkbox');
1931
        $types[self::FIELD_TYPE_INTEGER] = get_lang('Integer');
1932
        $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('Image');
1933
        $types[self::FIELD_TYPE_FLOAT] = get_lang('Float');
1934
        $types[self::FIELD_TYPE_FILE] = get_lang('File');
1935
        $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('Video URL');
1936
        $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('Text only letters');
1937
        $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('Text only alphanumeric characters');
1938
        $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('Text letters and spaces');
1939
        $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('Text alphanumeric characters and spaces');
1940
        $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization');
1941
        $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('Geolocalization by coordinates');
1942
        $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('Select with text field');
1943
        $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('Triple select');
1944
1945
        switch ($handler) {
1946
            case 'course':
1947
            case 'session':
1948
            case 'user':
1949
            case 'skill':
1950
                break;
1951
        }
1952
1953
        return $types;
1954
    }
1955
1956
    /**
1957
     * @param array $params
1958
     * @param bool  $showQuery
1959
     *
1960
     * @return int|bool
1961
     */
1962
    public function save($params, $showQuery = false)
1963
    {
1964
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_handler_...nfo_by_field_variable() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1964
        /** @scrutinizer ignore-call */ 
1965
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1965
        $params = $this->clean_parameters($params);
1966
        $params['extra_field_type'] = $this->extraFieldType;
1967
1968
        if ($fieldInfo) {
1969
            return $fieldInfo['id'];
1970
        } else {
1971
            $id = parent::save($params, $showQuery);
1972
            if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1973
                $fieldOption = new ExtraFieldOption($this->type);
1974
                $params['field_id'] = $id;
1975
                $fieldOption->save($params);
1976
            }
1977
1978
            return $id;
1979
        }
1980
    }
1981
1982
    /**
1983
     * @param string $variable
1984
     *
1985
     * @return array|bool
1986
     */
1987
    public function get_handler_field_info_by_field_variable($variable)
1988
    {
1989
        $variable = Database::escape_string($variable);
1990
        $sql = "SELECT * FROM {$this->table}
1991
                WHERE
1992
                    variable = '$variable' AND
1993
                    extra_field_type = $this->extraFieldType";
1994
        $result = Database::query($sql);
1995
        if (Database::num_rows($result)) {
1996
            $extraFieldRepo = Container::getExtraFieldRepository();
1997
            $row = Database::fetch_array($result, 'ASSOC');
1998
            if ($row) {
1999
                $extraFieldId = $row['id'];
2000
                /** @var \Chamilo\CoreBundle\Entity\ExtraField $extraField */
2001
                $field = $extraFieldRepo->find($extraFieldId);
2002
                $row['display_text'] = $field->getDisplayText();
2003
2004
                // All the options of the field
2005
                $sql = "SELECT * FROM $this->table_field_options
2006
                        WHERE field_id='".$extraFieldId."'
2007
                        ORDER BY option_order ASC";
2008
                $result = Database::query($sql);
2009
                while ($option = Database::fetch_array($result)) {
2010
                    $row['options'][$option['id']] = $option;
2011
                }
2012
2013
                return $row;
2014
            }
2015
        }
2016
2017
        return false;
2018
    }
2019
2020
    /**
2021
     * @param array $params
2022
     *
2023
     * @return array
2024
     */
2025
    public function clean_parameters($params)
2026
    {
2027
        if (!isset($params['variable']) || empty($params['variable'])) {
2028
            $params['variable'] = $params['display_text'];
2029
        }
2030
2031
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
2032
2033
        if (!isset($params['field_order'])) {
2034
            $max_order = self::get_max_field_order();
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_max_field_order() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2034
            /** @scrutinizer ignore-call */ 
2035
            $max_order = self::get_max_field_order();
Loading history...
2035
            $params['field_order'] = $max_order;
2036
        } else {
2037
            $params['field_order'] = (int) $params['field_order'];
2038
        }
2039
2040
        return $params;
2041
    }
2042
2043
    /**
2044
     * @return int
2045
     */
2046
    public function get_max_field_order()
2047
    {
2048
        $sql = "SELECT MAX(field_order)
2049
                FROM {$this->table}
2050
                WHERE
2051
                    extra_field_type = '.$this->extraFieldType.'";
2052
        $res = Database::query($sql);
2053
2054
        $order = 0;
2055
        if (Database::num_rows($res) > 0) {
2056
            $row = Database::fetch_row($res);
2057
            $order = $row[0] + 1;
2058
        }
2059
2060
        return $order;
2061
    }
2062
2063
    /**
2064
     * {@inheritdoc}
2065
     */
2066
    public function update($params, $showQuery = false)
2067
    {
2068
        $params = $this->clean_parameters($params);
2069
        if (isset($params['id'])) {
2070
            $fieldOption = new ExtraFieldOption($this->type);
2071
            $params['field_id'] = $params['id'];
2072
            if (empty($params['field_type'])) {
2073
                $params['field_type'] = $this->type;
2074
            }
2075
            $fieldOption->save($params, $showQuery);
2076
        }
2077
2078
        return parent::update($params, $showQuery);
2079
    }
2080
2081
    /**
2082
     * @param $id
2083
     *
2084
     * @return bool
2085
     */
2086
    public function delete($id)
2087
    {
2088
        $em = Database::getManager();
2089
        $items = $em->getRepository(\Chamilo\CoreBundle\Entity\ExtraFieldSavedSearch::class)->findBy(['field' => $id]);
2090
        if ($items) {
2091
            foreach ($items as $item) {
2092
                $em->remove($item);
2093
            }
2094
            $em->flush();
2095
        }
2096
        $field_option = new ExtraFieldOption($this->type);
2097
        $field_option->delete_all_options_by_field_id($id);
2098
2099
        $session_field_values = new ExtraFieldValue($this->type);
2100
        $session_field_values->delete_all_values_by_field_id($id);
2101
2102
        return parent::delete($id);
2103
    }
2104
2105
    /**
2106
     * @param $breadcrumb
2107
     * @param $action
2108
     */
2109
    public function setupBreadcrumb(&$breadcrumb, $action)
2110
    {
2111
        if ('add' === $action) {
2112
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2113
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Add')];
2114
        } elseif ('edit' === $action) {
2115
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2116
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')];
2117
        } else {
2118
            $breadcrumb[] = ['url' => '#', 'name' => $this->pageName];
2119
        }
2120
    }
2121
2122
    /**
2123
     * Displays the title + grid.
2124
     */
2125
    public function display()
2126
    {
2127
        $actions = '<a href="../admin/index.php">';
2128
        $actions .= Display::return_icon(
2129
            'back.png',
2130
            get_lang('Back to').' '.get_lang('Administration'),
2131
            '',
2132
            ICON_SIZE_MEDIUM
2133
        );
2134
        $actions .= '</a>';
2135
        $actions .= '<a href="'.api_get_self().'?action=add&type='.$this->type.'">';
2136
        $actions .= Display::return_icon(
2137
            'add_user_fields.png',
2138
            get_lang('Add'),
2139
            '',
2140
            ICON_SIZE_MEDIUM
2141
        );
2142
        $actions .= '</a>';
2143
2144
        echo Display::toolbarAction('toolbar', [$actions]);
2145
        echo Display::grid_html($this->type.'_fields');
2146
    }
2147
2148
    /**
2149
     * @return array
2150
     */
2151
    public function getJqgridColumnNames()
2152
    {
2153
        return [
2154
            get_lang('Name'),
2155
            get_lang('Field label'),
2156
            get_lang('Type'),
2157
            get_lang('Can change'),
2158
            get_lang('Visible to self'),
2159
            get_lang('Visible to others'),
2160
            get_lang('Filter'),
2161
            get_lang('Order'),
2162
            get_lang('Detail'),
2163
        ];
2164
    }
2165
2166
    /**
2167
     * @return array
2168
     */
2169
    public function getJqgridColumnModel()
2170
    {
2171
        return [
2172
            [
2173
                'name' => 'display_text',
2174
                'index' => 'display_text',
2175
                'width' => '140',
2176
                'align' => 'left',
2177
            ],
2178
            [
2179
                'name' => 'variable',
2180
                'index' => 'variable',
2181
                'width' => '90',
2182
                'align' => 'left',
2183
                'sortable' => 'true',
2184
            ],
2185
            [
2186
                'name' => 'field_type',
2187
                'index' => 'field_type',
2188
                'width' => '70',
2189
                'align' => 'left',
2190
                'sortable' => 'true',
2191
            ],
2192
            [
2193
                'name' => 'changeable',
2194
                'index' => 'changeable',
2195
                'width' => '35',
2196
                'align' => 'left',
2197
                'sortable' => 'true',
2198
            ],
2199
            [
2200
                'name' => 'visible_to_self',
2201
                'index' => 'visible_to_self',
2202
                'width' => '45',
2203
                'align' => 'left',
2204
                'sortable' => 'true',
2205
            ],
2206
            [
2207
                'name' => 'visible_to_others',
2208
                'index' => 'visible_to_others',
2209
                'width' => '35',
2210
                'align' => 'left',
2211
                'sortable' => 'true',
2212
            ],
2213
            [
2214
                'name' => 'filter',
2215
                'index' => 'filter',
2216
                'width' => '30',
2217
                'align' => 'left',
2218
                'sortable' => 'true',
2219
            ],
2220
            [
2221
                'name' => 'field_order',
2222
                'index' => 'field_order',
2223
                'width' => '25',
2224
                'align' => 'left',
2225
                'sortable' => 'true',
2226
            ],
2227
            [
2228
                'name' => 'actions',
2229
                'index' => 'actions',
2230
                'width' => '40',
2231
                'align' => 'left',
2232
                'formatter' => 'action_formatter',
2233
                'sortable' => 'false',
2234
            ],
2235
        ];
2236
    }
2237
2238
    /**
2239
     * @param string $url
2240
     * @param string $action
2241
     *
2242
     * @return FormValidator
2243
     */
2244
    public function return_form($url, $action)
2245
    {
2246
        $form = new FormValidator($this->type.'_field', 'post', $url);
2247
2248
        $form->addElement('hidden', 'type', $this->type);
2249
        $id = isset($_GET['id']) ? (int) $_GET['id'] : null;
2250
        $form->addElement('hidden', 'id', $id);
2251
2252
        // Setting the form elements
2253
        $header = get_lang('Add');
2254
        $defaults = [];
2255
2256
        if ('edit' === $action) {
2257
            $header = get_lang('Edit');
2258
            // Setting the defaults
2259
            $defaults = $this->get($id, false);
2260
        }
2261
2262
        $form->addElement('header', $header);
2263
2264
        if ('edit' === $action) {
2265
            $translateUrl = api_get_path(WEB_CODE_PATH).'extrafield/translate.php?'.http_build_query(['id' => $id]);
2266
            $translateButton = Display::toolbarButton(
2267
                get_lang('Translate this term'),
2268
                $translateUrl,
2269
                'language',
2270
                'link'
2271
            );
2272
2273
            $form->addText(
2274
                'display_text',
2275
                [get_lang('Name'), $translateButton]
2276
            );
2277
        } else {
2278
            $form->addElement('text', 'display_text', get_lang('Name'));
2279
        }
2280
2281
        $form->addHtmlEditor('description', get_lang('Description'), false);
2282
2283
        // Field type
2284
        $types = self::get_field_types();
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_field_types() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2284
        /** @scrutinizer ignore-call */ 
2285
        $types = self::get_field_types();
Loading history...
2285
2286
        $form->addSelect(
2287
            'field_type',
2288
            get_lang('Field type'),
2289
            $types,
2290
            ['id' => 'field_type']
2291
        );
2292
        $form->addElement('label', get_lang('Example'), '<div id="example">-</div>');
2293
        $form->addElement('text', 'variable', get_lang('Field label'), ['class' => 'span5']);
2294
        $form->addElement(
2295
            'text',
2296
            'field_options',
2297
            get_lang('Possible values'),
2298
            ['id' => 'field_options', 'class' => 'span6']
2299
        );
2300
2301
        $fieldWithOptions = [
2302
            self::FIELD_TYPE_RADIO,
2303
            self::FIELD_TYPE_SELECT_MULTIPLE,
2304
            self::FIELD_TYPE_SELECT,
2305
            self::FIELD_TYPE_TAG,
2306
            self::FIELD_TYPE_DOUBLE_SELECT,
2307
            self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD,
2308
            self::FIELD_TYPE_TRIPLE_SELECT,
2309
        ];
2310
2311
        if ('edit' === $action) {
2312
            if (in_array($defaults['field_type'], $fieldWithOptions)) {
2313
                $url = Display::url(
2314
                    get_lang('Edit extra field options'),
2315
                    'extra_field_options.php?type='.$this->type.'&field_id='.$id,
2316
                    ['class' => 'btn']
2317
                );
2318
                $form->addElement('label', null, $url);
2319
2320
                if (self::FIELD_TYPE_SELECT == $defaults['field_type']) {
2321
                    $urlWorkFlow = Display::url(
2322
                        get_lang('Edit this field\'s workflow'),
2323
                        'extra_field_workflow.php?type='.$this->type.'&field_id='.$id,
2324
                        ['class' => 'btn']
2325
                    );
2326
                    $form->addElement('label', null, $urlWorkFlow);
2327
                }
2328
2329
                $form->freeze('field_options');
2330
            }
2331
        }
2332
        $form->addElement(
2333
            'text',
2334
            'default_value',
2335
            get_lang('Default value'),
2336
            ['id' => 'default_value']
2337
        );
2338
2339
        $group = [];
2340
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('Yes'), 1);
2341
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('No'), 0);
2342
        $form->addGroup($group, '', get_lang('Visible to self'), null, false);
2343
2344
        $group = [];
2345
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('Yes'), 1);
2346
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('No'), 0);
2347
        $form->addGroup($group, '', get_lang('Visible to others'), null, false);
2348
2349
        $group = [];
2350
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('Yes'), 1);
2351
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('No'), 0);
2352
        $form->addGroup($group, '', get_lang('Can change'), null, false);
2353
2354
        $group = [];
2355
        $group[] = $form->createElement('radio', 'filter', null, get_lang('Yes'), 1);
2356
        $group[] = $form->createElement('radio', 'filter', null, get_lang('No'), 0);
2357
        $form->addGroup($group, '', get_lang('Filter'), null, false);
2358
2359
        /* Enable this when field_loggeable is introduced as a table field (2.0)
2360
        $group   = array();
2361
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('Yes'), 1);
2362
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('No'), 0);
2363
        $form->addGroup($group, '', get_lang('Field changes should be logged'), '', false);
2364
        */
2365
2366
        $form->addElement('text', 'field_order', get_lang('Order'));
2367
2368
        if ('edit' == $action) {
2369
            $option = new ExtraFieldOption($this->type);
2370
            $defaults['field_options'] = $option->get_field_options_by_field_to_string($id);
2371
            $form->addButtonUpdate(get_lang('Edit'));
2372
        } else {
2373
            $defaults['visible_to_self'] = 0;
2374
            $defaults['visible_to_others'] = 0;
2375
            $defaults['changeable'] = 0;
2376
            $defaults['filter'] = 0;
2377
            $form->addButtonCreate(get_lang('Add'));
2378
        }
2379
2380
        /*if (!empty($defaults['created_at'])) {
2381
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
2382
        }
2383
        if (!empty($defaults['updated_at'])) {
2384
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
2385
        }*/
2386
        $form->setDefaults($defaults);
2387
2388
        // Setting the rules
2389
        $form->addRule('display_text', get_lang('Required field'), 'required');
2390
        $form->addRule('field_type', get_lang('Required field'), 'required');
2391
2392
        return $form;
2393
    }
2394
2395
    /**
2396
     * Gets an element.
2397
     *
2398
     * @param int  $id
2399
     * @param bool $translateDisplayText Optional
2400
     *
2401
     * @return array
2402
     */
2403
    public function get($id, $translateDisplayText = true)
2404
    {
2405
        $info = parent::get($id);
2406
2407
        if ($translateDisplayText) {
2408
            $extraFieldRepo = Container::getExtraFieldRepository();
2409
            /** @var \Chamilo\CoreBundle\Entity\ExtraField $extraField */
2410
            $field = $extraFieldRepo->find($id);
2411
            $info['display_text'] = $field->getDisplayText();
2412
        }
2413
2414
        return $info;
2415
    }
2416
2417
    /**
2418
     * @param $token
2419
     *
2420
     * @return string
2421
     */
2422
    public function getJqgridActionLinks($token)
2423
    {
2424
        //With this function we can add actions to the jgrid (edit, delete, etc)
2425
        $editIcon = Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL);
2426
        $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2427
        $confirmMessage = addslashes(
2428
            api_htmlentities(get_lang("Please confirm your choice"), ENT_QUOTES)
2429
        );
2430
2431
        $editButton = <<<JAVASCRIPT
2432
            <a href="?action=edit&type={$this->type}&id=' + options.rowId + '" class="btn btn-link btn-xs">\
2433
                $editIcon\
2434
            </a>
2435
JAVASCRIPT;
2436
        $deleteButton = <<<JAVASCRIPT
2437
            <a \
2438
                    onclick="if (!confirm(\'$confirmMessage\')) {return false;}" \
2439
                href="?sec_token=$token&type={$this->type}&id=' + options.rowId + '&action=delete" \
2440
                class="btn btn-link btn-xs">\
2441
                $deleteIcon\
2442
            </a>
2443
JAVASCRIPT;
2444
2445
        return "function action_formatter(cellvalue, options, rowObject) {
2446
            return '$editButton $deleteButton';
2447
        }";
2448
    }
2449
2450
    /**
2451
     * @param array $columns
2452
     * @param array $column_model
2453
     * @param array $extraFields
2454
     *
2455
     * @return array
2456
     */
2457
    public function getRules(&$columns, &$column_model, $extraFields = [], $checkExtraFieldExistence = false)
2458
    {
2459
        $fields = $this->get_all(
2460
            [
2461
                'visible_to_self = ? AND filter = ?' => [1, 1],
2462
            ],
2463
            'display_text'
2464
        );
2465
        $extraFieldOption = new ExtraFieldOption($this->type);
2466
2467
        $rules = [];
2468
        if (!empty($fields)) {
2469
            foreach ($fields as $field) {
2470
                $search_options = [];
2471
                $type = 'text';
2472
                if (in_array($field['field_type'], [self::FIELD_TYPE_SELECT, self::FIELD_TYPE_DOUBLE_SELECT])) {
2473
                    $type = 'select';
2474
                    $search_options['sopt'] = ['eq', 'ne']; //equal not equal
2475
                } else {
2476
                    $search_options['sopt'] = ['cn', 'nc']; //contains not contains
2477
                }
2478
2479
                $search_options['searchhidden'] = 'true';
2480
                $search_options['defaultValue'] = isset($search_options['field_default_value'])
2481
                    ? $search_options['field_default_value']
2482
                    : null;
2483
2484
                if (self::FIELD_TYPE_DOUBLE_SELECT == $field['field_type']) {
2485
                    // Add 2 selects
2486
                    $options = $extraFieldOption->get_field_options_by_field($field['id']);
2487
                    $options = self::extra_field_double_select_convert_array_to_ordered_array($options);
2488
2489
                    $first_options = [];
2490
                    if (!empty($options)) {
2491
                        foreach ($options as $option) {
2492
                            foreach ($option as $sub_option) {
2493
                                if (0 == $sub_option['option_value']) {
2494
                                    $first_options[] = $sub_option['field_id'].'#'.$sub_option['id'].':'
2495
                                        .$sub_option['display_text'];
2496
                                }
2497
                            }
2498
                        }
2499
                    }
2500
2501
                    $search_options['value'] = implode(';', $first_options);
2502
                    $search_options['dataInit'] = 'fill_second_select';
2503
2504
                    // First
2505
                    $column_model[] = [
2506
                        'name' => 'extra_'.$field['variable'],
2507
                        'index' => 'extra_'.$field['variable'],
2508
                        'width' => '100',
2509
                        'hidden' => 'true',
2510
                        'search' => 'true',
2511
                        'stype' => 'select',
2512
                        'searchoptions' => $search_options,
2513
                    ];
2514
                    $columns[] = $field['display_text'].' (1)';
2515
                    $rules[] = [
2516
                        'field' => 'extra_'.$field['variable'],
2517
                        'op' => 'cn',
2518
                    ];
2519
2520
                    // Second
2521
                    $search_options['value'] = $field['id'].':';
2522
                    $search_options['dataInit'] = 'register_second_select';
2523
2524
                    $column_model[] = [
2525
                        'name' => 'extra_'.$field['variable'].'_second',
2526
                        'index' => 'extra_'.$field['variable'].'_second',
2527
                        'width' => '100',
2528
                        'hidden' => 'true',
2529
                        'search' => 'true',
2530
                        'stype' => 'select',
2531
                        'searchoptions' => $search_options,
2532
                    ];
2533
                    $columns[] = $field['display_text'].' (2)';
2534
                    $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn'];
2535
                    continue;
2536
                } else {
2537
                    $search_options['value'] = $extraFieldOption->getFieldOptionsToString(
2538
                        $field['id'],
2539
                        false,
2540
                        'display_text'
2541
                    );
2542
                }
2543
                $column_model[] = [
2544
                    'name' => 'extra_'.$field['variable'],
2545
                    'index' => 'extra_'.$field['variable'],
2546
                    'width' => '100',
2547
                    'hidden' => 'true',
2548
                    'search' => 'true',
2549
                    'stype' => $type,
2550
                    'searchoptions' => $search_options,
2551
                ];
2552
                $columns[] = $field['display_text'];
2553
                $rules[] = [
2554
                    'field' => 'extra_'.$field['variable'],
2555
                    'op' => 'cn',
2556
                    'data' => '',
2557
                ];
2558
            }
2559
        }
2560
2561
        return $rules;
2562
    }
2563
2564
    public function processExtraFieldSearch($values, $form, $alias, $condition = 'OR')
2565
    {
2566
        // Parse params.
2567
        $fields = [];
2568
        foreach ($values as $key => $value) {
2569
            if ('extra_' !== substr($key, 0, 6) &&
2570
                '_extra_' !== substr($key, 0, 7)
2571
            ) {
2572
                continue;
2573
            }
2574
            if (!empty($value)) {
2575
                $fields[$key] = $value;
2576
            }
2577
        }
2578
2579
        $extraFieldsAll = $this->get_all(['visible_to_self = ? AND filter = ?' => [1, 1]], 'option_order');
2580
        $extraFieldsType = array_column($extraFieldsAll, 'field_type', 'variable');
2581
        $extraFields = array_column($extraFieldsAll, 'variable');
2582
        $filter = new stdClass();
2583
        $defaults = [];
2584
        foreach ($fields as $variable => $col) {
2585
            $variableNoExtra = str_replace('extra_', '', $variable);
2586
            if (isset($values[$variable]) && !empty($values[$variable]) &&
2587
                in_array($variableNoExtra, $extraFields)
2588
            ) {
2589
                $rule = new stdClass();
2590
                $rule->field = $variable;
2591
                $rule->op = 'in';
2592
                $data = $col;
2593
                if (is_array($data) && array_key_exists($variable, $data)) {
2594
                    $data = $col;
2595
                }
2596
                $rule->data = $data;
2597
                $filter->rules[] = $rule;
2598
                $filter->groupOp = 'AND';
2599
2600
                if (ExtraField::FIELD_TYPE_TAG == $extraFieldsType[$variableNoExtra]) {
2601
                    $tagElement = $form->getElement($variable);
2602
                    $tags = [];
2603
                    foreach ($values[$variable] as $tag) {
2604
                        $tag = Security::remove_XSS($tag);
2605
                        $tags[] = $tag;
2606
                        $tagElement->addOption(
2607
                            $tag,
2608
                            $tag
2609
                        );
2610
                    }
2611
                    $defaults[$variable] = $tags;
2612
                } else {
2613
                    if (is_array($data)) {
2614
                        $defaults[$variable] = array_map(['Security', 'remove_XSS'], $data);
2615
                    } else {
2616
                        $defaults[$variable] = Security::remove_XSS($data);
2617
                    }
2618
                }
2619
            }
2620
        }
2621
2622
        $result = $this->getExtraFieldRules($filter, 'extra_', $condition);
2623
        $conditionArray = $result['condition_array'];
2624
2625
        $whereCondition = '';
2626
        $extraCondition = '';
2627
        if (!empty($conditionArray)) {
2628
            $extraCondition = ' ( ';
2629
            $extraCondition .= implode(' AND ', $conditionArray);
2630
            $extraCondition .= ' ) ';
2631
        }
2632
        $whereCondition .= $extraCondition;
2633
        $conditions = $this->parseConditions(
2634
            [
2635
                'where' => $whereCondition,
2636
                'extra' => $result['extra_fields'],
2637
            ],
2638
            $alias
2639
        );
2640
2641
        return ['condition' => $conditions, 'fields' => $fields, 'defaults' => $defaults];
2642
    }
2643
2644
    /**
2645
     * @param $filters
2646
     * @param string $stringToSearch
2647
     *
2648
     * @return array
2649
     */
2650
    public function getExtraFieldRules($filters, $stringToSearch = 'extra_', $condition = 'OR')
2651
    {
2652
        $extraFields = [];
2653
        $conditionArray = [];
2654
2655
        // Getting double select if exists
2656
        $double_select = [];
2657
        if (is_object($filters) &&
2658
            property_exists($filters, 'rules') &&
2659
            is_array($filters->rules) &&
2660
            !empty($filters->rules)
2661
        ) {
2662
            foreach ($filters->rules as $rule) {
2663
                if (empty($rule)) {
2664
                    continue;
2665
                }
2666
                if (false === strpos($rule->field, '_second')) {
2667
                } else {
2668
                    $my_field = str_replace('_second', '', $rule->field);
2669
                    $double_select[$my_field] = $rule->data;
2670
                }
2671
            }
2672
2673
            foreach ($filters->rules as $rule) {
2674
                if (empty($rule)) {
2675
                    continue;
2676
                }
2677
                if (false === strpos($rule->field, $stringToSearch)) {
2678
                    // normal fields
2679
                    $field = $rule->field;
2680
                    if (isset($rule->data) && is_string($rule->data) && -1 != $rule->data) {
2681
                        $conditionArray[] = $this->get_where_clause($field, $rule->op, $rule->data);
2682
                    }
2683
                } else {
2684
                    // Extra fields
2685
                    $ruleField = Database::escapeField($rule->field);
2686
                    if (false === strpos($rule->field, '_second')) {
2687
                        //No _second
2688
                        $original_field = str_replace($stringToSearch, '', $rule->field);
2689
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2690
2691
                        switch ($field_option['field_type']) {
2692
                            case self::FIELD_TYPE_DOUBLE_SELECT:
2693
                            if (isset($double_select[$rule->field])) {
2694
                                $data = explode('#', $rule->data);
2695
                                $rule->data = $data[1].'::'.$double_select[$rule->field];
2696
                            } else {
2697
                                // only was sent 1 select
2698
                                if (is_string($rule->data)) {
2699
                                    $data = explode('#', $rule->data);
2700
                                    $rule->data = $data[1];
2701
                                }
2702
                            }
2703
2704
                            if (!isset($rule->data)) {
2705
                                $conditionArray[] = ' ('
2706
                                .$this->get_where_clause($rule->field, $rule->op, $rule->data)
2707
                                .') ';
2708
                                $extraFields[] = ['field' => $ruleField, 'id' => $field_option['id']];
2709
                            }
2710
                                break;
2711
                            case self::FIELD_TYPE_TAG:
2712
                            if (isset($rule->data)) {
2713
                                if (is_int($rule->data) && -1 == $rule->data) {
2714
                                    break;
2715
                                }
2716
2717
                                    // Where will be injected in the parseConditions()
2718
                                //$where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR');
2719
                                //$conditionArray[] = " ( $where ) ";
2720
                                $extraFields[] = [
2721
                                        'field' => $ruleField,
2722
                                'id' => $field_option['id'],
2723
                                'data' => $rule->data,
2724
                            ];
2725
                            }
2726
                                break;
2727
                            default:
2728
                                if (isset($rule->data)) {
2729
                                    if (is_int($rule->data) && -1 == $rule->data) {
2730
                                        break;
2731
                                    }
2732
                                    $where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR');
2733
                                    $conditionArray[] = " ( $where ) ";
2734
                                    $extraFields[] = [
2735
                                        'field' => $ruleField,
2736
                                        'id' => $field_option['id'],
2737
                                        'data' => $rule->data,
2738
                                    ];
2739
                                }
2740
                                break;
2741
                        }
2742
                    } else {
2743
                        $my_field = str_replace('_second', '', $rule->field);
2744
                        $original_field = str_replace($stringToSearch, '', $my_field);
2745
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2746
                        $extraFields[] = [
2747
                            'field' => $ruleField,
2748
                        'id' => $field_option['id'],
2749
                    ];
2750
                    }
2751
                }
2752
            }
2753
        }
2754
2755
        return ['extra_fields' => $extraFields, 'condition_array' => $conditionArray];
2756
    }
2757
2758
    /**
2759
     * @param $col
2760
     * @param $oper
2761
     * @param $val
2762
     * @param $conditionBetweenOptions
2763
     *
2764
     * @return string
2765
     */
2766
    public function get_where_clause($col, $oper, $val, $conditionBetweenOptions = 'OR')
2767
    {
2768
        $col = Database::escapeField($col);
2769
2770
        if (empty($col)) {
2771
            return '';
2772
        }
2773
        $conditionBetweenOptions = in_array($conditionBetweenOptions, ['OR', 'AND']) ? $conditionBetweenOptions : 'OR';
2774
        if ('bw' === $oper || 'bn' === $oper) {
2775
            $val .= '%';
2776
        }
2777
        if ('ew' === $oper || 'en' === $oper) {
2778
            $val = '%'.$val;
2779
        }
2780
        if ('cn' === $oper || 'nc' === $oper || 'in' === $oper || 'ni' === $oper) {
2781
            if (is_array($val)) {
2782
                $result = '"%'.implode(';', $val).'%"';
2783
                foreach ($val as $item) {
2784
                    $item = trim($item);
2785
                    $result .= ' '.$conditionBetweenOptions.' '.$col.' LIKE "%'.$item.'%"';
2786
                }
2787
                $val = $result;
2788
2789
                return " $col {$this->ops[$oper]} $val ";
2790
            } else {
2791
                if (is_string($val)) {
2792
                    $val = '%'.$val.'%';
2793
                } else {
2794
                    $val = '';
2795
                }
2796
            }
2797
        }
2798
        $val = \Database::escape_string($val);
2799
2800
        return " $col {$this->ops[$oper]} '$val' ";
2801
    }
2802
2803
    /**
2804
     * @param array  $options
2805
     * @param string $alias
2806
     *
2807
     * @return array
2808
     */
2809
    public function parseConditions($options, $alias = 's')
2810
    {
2811
        $inject_extra_fields = null;
2812
        $extraFieldOption = new ExtraFieldOption($this->type);
2813
        $double_fields = [];
2814
2815
        if (isset($options['extra'])) {
2816
            $extra_fields = $options['extra'];
2817
            if (!empty($extra_fields)) {
2818
                $counter = 1;
2819
                $extra_field_obj = new ExtraField($this->type);
2820
                foreach ($extra_fields as &$extra) {
2821
                    if (!isset($extra['id'])) {
2822
                        continue;
2823
                    }
2824
                    $extra_field_info = $extra_field_obj->get($extra['id']);
2825
                    if (empty($extra_field_info)) {
2826
                        continue;
2827
                    }
2828
                    $extra['extra_field_info'] = $extra_field_info;
2829
2830
                    switch ($extra_field_info['field_type']) {
2831
                        case self::FIELD_TYPE_SELECT:
2832
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2833
                            $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, ";
2834
                            break;
2835
                        case self::FIELD_TYPE_TAG:
2836
                            // If using OR
2837
                            // If using AND
2838
                            $newCounter = 1;
2839
                            $fields = [];
2840
                            $tagAlias = $extra['field'];
2841
                            foreach ($extra['data'] as $data) {
2842
                                $fields[] = "tag$counter$newCounter.tag";
2843
                                $newCounter++;
2844
                            }
2845
2846
                            if (!empty($fields)) {
2847
                                $tags = implode(' , " ", ', $fields);
2848
                                $inject_extra_fields .= " CONCAT($tags) as $tagAlias, ";
2849
                            }
2850
                            break;
2851
                        default:
2852
                            $inject_extra_fields .= " fv$counter.value as {$extra['field']}, ";
2853
                            break;
2854
                    }
2855
2856
                    if (isset($extra_fields_info[$extra['id']])) {
2857
                        $info = $extra_fields_info[$extra['id']];
2858
                    } else {
2859
                        $info = $this->get($extra['id']);
2860
                        $extra_fields_info[$extra['id']] = $info;
2861
                    }
2862
                    if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) {
2863
                        $double_fields[$info['id']] = $info;
2864
                    }
2865
                    $counter++;
2866
                }
2867
            }
2868
        }
2869
2870
        $options_by_double = [];
2871
        foreach ($double_fields as $double) {
2872
            $my_options = $extraFieldOption->get_field_options_by_field($double['id'], true);
2873
            $options_by_double['extra_'.$double['variable']] = $my_options;
2874
        }
2875
2876
        $field_value_to_join = [];
2877
        //filter can be all/any = and/or
2878
        $inject_joins = null;
2879
        $inject_where = null;
2880
        $where = null;
2881
2882
        // Removing double 1=1
2883
        if (!empty($options['extra']) && !empty($extra_fields)) {
2884
            // Removing double 1=1
2885
            if (empty($options['where'])) {
2886
                $options['where'] = ' 1 = 1 ';
2887
            }
2888
            $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
2889
            // Always OR
2890
            $counter = 1;
2891
            foreach ($extra_fields as $extra_info) {
2892
                $extra_field_info = $extra_info['extra_field_info'];
2893
                $inject_joins .= " INNER JOIN $this->table_field_values fv$counter
2894
                                       ON ($alias.".$this->primaryKey." = fv$counter.".$this->handler_id.') ';
2895
                // Add options
2896
                switch ($extra_field_info['field_type']) {
2897
                        case self::FIELD_TYPE_SELECT:
2898
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2899
                            $options['where'] = str_replace(
2900
                                $extra_info['field'],
2901
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value',
2902
                                $options['where']
2903
                            );
2904
                            $inject_joins .= "
2905
                                 INNER JOIN $this->table_field_options fvo$counter
2906
                                 ON (
2907
                                    fv$counter.field_id = fvo$counter.field_id AND
2908
                                    fv$counter.value = fvo$counter.option_value
2909
                                 )
2910
                                ";
2911
                            break;
2912
                        case self::FIELD_TYPE_TAG:
2913
                            $newCounter = 1;
2914
                            if (isset($extra_info['data']) && !empty($extra_info['data'])) {
2915
                                $whereTag = [];
2916
                                foreach ($extra_info['data'] as $data) {
2917
                                    $data = Database::escape_string($data);
2918
                                    $key = $counter.$newCounter;
2919
                                    $whereTag[] = ' tag'.$key.'.tag LIKE "%'.$data.'%" ';
2920
                                    $inject_joins .= "
2921
                                        INNER JOIN $this->table_field_rel_tag tag_rel$key
2922
                                        ON (
2923
                                            tag_rel$key.field_id = ".$extra_info['id']." AND
2924
                                            tag_rel$key.item_id = $alias.".$this->primaryKey."
2925
                                        )
2926
                                        INNER JOIN $this->table_field_tag tag$key
2927
                                        ON (tag$key.id = tag_rel$key.tag_id)
2928
                                    ";
2929
                                    $newCounter++;
2930
                                }
2931
                                if (!empty($whereTag)) {
2932
                                    $options['where'] .= ' AND  ('.implode(' AND ', $whereTag).') ';
2933
                                }
2934
                            }
2935
                            break;
2936
                        default:
2937
                            // text, textarea, etc
2938
                            $options['where'] = str_replace(
2939
                                $extra_info['field'],
2940
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value',
2941
                                $options['where']
2942
                            );
2943
                            break;
2944
                    }
2945
                $field_value_to_join[] = " fv$counter.$this->handler_id ";
2946
                $counter++;
2947
            }
2948
        }
2949
2950
        if (!empty($options['where'])) {
2951
            $where .= ' AND '.$options['where'];
2952
        }
2953
2954
        $order = '';
2955
        if (!empty($options['order'])) {
2956
            $order = ' ORDER BY '.$options['order'];
2957
        }
2958
        $limit = '';
2959
        if (!empty($options['limit'])) {
2960
            $limit = ' LIMIT '.$options['limit'];
2961
        }
2962
2963
        return [
2964
            'order' => $order,
2965
            'limit' => $limit,
2966
            'where' => $where,
2967
            'inject_where' => $inject_where,
2968
            'inject_joins' => $inject_joins,
2969
            'field_value_to_join' => $field_value_to_join,
2970
            'inject_extra_fields' => $inject_extra_fields,
2971
        ];
2972
    }
2973
2974
    /**
2975
     * Get the extra fields and their formatted values.
2976
     *
2977
     * @param int|string $itemId   The item ID (It could be a session_id, course_id or user_id)
2978
     * @param bool       $filter
2979
     * @param array      $onlyShow (list of extra fields variables to show)
2980
     *
2981
     * @return array The extra fields data
2982
     */
2983
    public function getDataAndFormattedValues($itemId, $filter = false, $onlyShow = [])
2984
    {
2985
        $valuesData = [];
2986
        $fields = $this->get_all();
2987
        $em = Database::getManager();
2988
        $repoTag = $em->getRepository(ExtraFieldRelTag::class);
2989
2990
        foreach ($fields as $field) {
2991
            if ('1' != $field['visible_to_self']) {
2992
                continue;
2993
            }
2994
2995
            if ($filter && 1 != $field['filter']) {
2996
                continue;
2997
            }
2998
2999
            if (!empty($onlyShow) && !in_array($field['variable'], $onlyShow)) {
3000
                continue;
3001
            }
3002
3003
            $valueAsArray = [];
3004
            $fieldValue = new ExtraFieldValue($this->type);
3005
            $valueData = $fieldValue->get_values_by_handler_and_field_id($itemId, $field['id'], true);
3006
3007
            $fieldType = (int) $field['field_type'];
3008
            if (self::FIELD_TYPE_TAG === $fieldType) {
3009
                $tags = $repoTag->findBy(['field' => $field['id'], 'itemId' => $itemId]);
3010
                if ($tags) {
3011
                    $data = [];
3012
                    /** @var ExtraFieldRelTag $tag */
3013
                    foreach ($tags as $extraFieldTag) {
3014
                        $tag = $extraFieldTag->getTag();
3015
                        $data[] = $tag->getTag();
3016
                    }
3017
                    $valueData = implode(',', $data);
3018
                    $valueAsArray = $data;
3019
                }
3020
            }
3021
3022
            if (!$valueData) {
3023
                continue;
3024
            }
3025
            $displayedValue = get_lang('None');
3026
            switch ($fieldType) {
3027
                case self::FIELD_TYPE_CHECKBOX:
3028
                    $displayedValue = get_lang('No');
3029
                    if (false !== $valueData && '1' == $valueData['value']) {
3030
                        $displayedValue = get_lang('Yes');
3031
                    }
3032
                    break;
3033
                case self::FIELD_TYPE_DATE:
3034
                    if (false !== $valueData && !empty($valueData['value'])) {
3035
                        $displayedValue = api_format_date($valueData['value'], DATE_FORMAT_LONG_NO_DAY);
3036
                    }
3037
                    break;
3038
                case self::FIELD_TYPE_TAG:
3039
                    if (!empty($valueData)) {
3040
                        $displayedValue = $valueData;
3041
                    }
3042
                    break;
3043
                case self::FIELD_TYPE_FILE:
3044
                case self::FIELD_TYPE_FILE_IMAGE:
3045
                    if (false === $valueData || empty($valueData['asset_id'])) {
3046
                        break;
3047
                    }
3048
                    $assetId = $valueData['asset_id'];
3049
                    $assetRepo = Container::getAssetRepository();
3050
                    /** @var Asset|null $asset */
3051
                    $asset = $assetRepo->find($assetId);
3052
3053
                    if (null === $asset) {
3054
                        break;
3055
                    }
3056
3057
                    $url = $assetRepo->getAssetUrl($asset);
3058
3059
                    if (self::FIELD_TYPE_FILE_IMAGE === $fieldType) {
3060
                        $image = Display::img(
3061
                            $url,
3062
                            $field['display_text'],
3063
                            ['width' => '300'],
3064
                            false
3065
                        );
3066
                        $displayedValue = Display::url(
3067
                            $image,
3068
                            $url,
3069
                            ['target' => '_blank']
3070
                        );
3071
                    } else {
3072
                        $displayedValue = Display::url(
3073
                            get_lang('Download'),
3074
                            $url,
3075
                            [
3076
                                'title' => $field['display_text'],
3077
                                'target' => '_blank',
3078
                                'class' => 'download_extra_field',
3079
                            ]
3080
                        );
3081
                    }
3082
                    break;
3083
                default:
3084
                    $displayedValue = $valueData['value'];
3085
                    break;
3086
            }
3087
3088
            $valuesData[] = [
3089
                'variable' => $field['variable'],
3090
                'text' => $field['display_text'],
3091
                'value' => $displayedValue,
3092
                'value_as_array' => $valueAsArray,
3093
            ];
3094
        }
3095
3096
        return $valuesData;
3097
    }
3098
3099
    /**
3100
     * @param int    $fieldId
3101
     * @param string $tag
3102
     *
3103
     * @return array
3104
     */
3105
    public function getAllUserPerTag($fieldId, $tag)
3106
    {
3107
        $tagRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3108
        $tag = Database::escape_string($tag);
3109
        $fieldId = (int) $fieldId;
3110
3111
        $sql = "SELECT user_id
3112
                FROM {$this->table_field_tag} f INNER JOIN $tagRelUserTable ft
3113
                ON tag_id = f.id
3114
                WHERE tag = '$tag' AND f.field_id = $fieldId;
3115
        ";
3116
3117
        $result = Database::query($sql);
3118
3119
        return Database::store_result($result, 'ASSOC');
3120
    }
3121
3122
    /**
3123
     * @param int $fieldId
3124
     * @param int $tagId
3125
     *
3126
     * @return array
3127
     */
3128
    public function getAllSkillPerTag($fieldId, $tagId)
3129
    {
3130
        $skillTable = Database::get_main_table(TABLE_MAIN_SKILL);
3131
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3132
        $fieldId = (int) $fieldId;
3133
        $tagId = (int) $tagId;
3134
3135
        $sql = "SELECT s.id
3136
                FROM $skillTable s INNER JOIN $tagRelExtraTable t
3137
                ON t.item_id = s.id
3138
                WHERE tag_id = $tagId AND t.field_id = $fieldId;
3139
        ";
3140
3141
        $result = Database::query($sql);
3142
        $result = Database::store_result($result, 'ASSOC');
3143
3144
        $skillList = [];
3145
        foreach ($result as $index => $value) {
3146
            $skillList[$value['id']] = $value['id'];
3147
        }
3148
3149
        return $skillList;
3150
    }
3151
3152
    /**
3153
     * @param string $from
3154
     * @param string $search
3155
     * @param array  $options
3156
     *
3157
     * @return array
3158
     */
3159
    public function searchOptionsFromTags($from, $search, $options)
3160
    {
3161
        $extraFieldInfo = $this->get_handler_field_info_by_field_variable(str_replace('extra_', '', $from));
3162
        $extraFieldInfoTag = $this->get_handler_field_info_by_field_variable(str_replace('extra_', '', $search));
3163
        if (empty($extraFieldInfo) || empty($extraFieldInfoTag)) {
3164
            return [];
3165
        }
3166
3167
        $id = $extraFieldInfo['id'];
3168
        $tagId = $extraFieldInfoTag['id'];
3169
3170
        $table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3171
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3172
        $tagTable = Database::get_main_table(TABLE_MAIN_TAG);
3173
        $optionsTable = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
3174
        $cleanOptions = [];
3175
        foreach ($options as $option) {
3176
            $cleanOptions[] = Database::escape_string($option);
3177
        }
3178
        $cleanOptions = array_filter($cleanOptions);
3179
3180
        if (empty($cleanOptions)) {
3181
            return [];
3182
        }
3183
3184
        $value = implode("','", $cleanOptions);
3185
3186
        $sql = "SELECT DISTINCT t.*, v.value, o.display_text
3187
                FROM $tagRelExtraTable te
3188
                INNER JOIN $tagTable t
3189
                ON (t.id = te.tag_id AND te.field_id = t.field_id AND te.field_id = $tagId)
3190
                INNER JOIN $table v
3191
                ON (te.item_id = v.item_id AND v.field_id = $id)
3192
                INNER JOIN $optionsTable o
3193
                ON (o.option_value = v.value)
3194
                WHERE v.value IN ('".$value."')
3195
                ORDER BY o.option_order, t.tag
3196
               ";
3197
        $result = Database::query($sql);
3198
3199
        return Database::store_result($result);
3200
    }
3201
3202
    public static function getExtraFieldTypesWithFiles(): array
3203
    {
3204
        return [self::FIELD_TYPE_FILE_IMAGE, self::FIELD_TYPE_FILE];
3205
    }
3206
3207
    /**
3208
     * @param \FormValidator $form
3209
     * @param int            $defaultValueId
3210
     * @param bool           $freezeElement
3211
     */
3212
    private function addSelectElement(FormValidator $form, array $fieldDetails, $defaultValueId, $freezeElement = false)
3213
    {
3214
        $get_lang_variables = false;
3215
        if (in_array(
3216
            $fieldDetails['variable'],
3217
            ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
3218
        )) {
3219
            $get_lang_variables = true;
3220
        }
3221
3222
        // Get extra field workflow
3223
        $addOptions = [];
3224
        $optionsExists = false;
3225
        $options = [];
3226
3227
        $optionList = [];
3228
        if (!empty($fieldDetails['options'])) {
3229
            foreach ($fieldDetails['options'] as $option_details) {
3230
                $optionList[$option_details['id']] = $option_details;
3231
                if ($get_lang_variables) {
3232
                    $options[$option_details['option_value']] = $option_details['display_text'];
3233
                } else {
3234
                    if ($optionsExists) {
3235
                        // Adding always the default value
3236
                        if ($option_details['id'] == $defaultValueId) {
3237
                            $options[$option_details['option_value']] = $option_details['display_text'];
3238
                        } else {
3239
                            if (isset($addOptions) && !empty($addOptions)) {
3240
                                // Parsing filters
3241
                                if (in_array($option_details['id'], $addOptions)) {
3242
                                    $options[$option_details['option_value']] = $option_details['display_text'];
3243
                                }
3244
                            }
3245
                        }
3246
                    } else {
3247
                        // Normal behaviour
3248
                        $options[$option_details['option_value']] = $option_details['display_text'];
3249
                    }
3250
                }
3251
            }
3252
3253
            // Setting priority message
3254
            if (isset($optionList[$defaultValueId])
3255
                && isset($optionList[$defaultValueId]['priority'])
3256
            ) {
3257
                if (!empty($optionList[$defaultValueId]['priority'])) {
3258
                    $priorityId = $optionList[$defaultValueId]['priority'];
3259
                    $option = new ExtraFieldOption($this->type);
3260
                    $messageType = $option->getPriorityMessageType($priorityId);
3261
                    $form->addElement(
3262
                        'label',
3263
                        null,
3264
                        Display::return_message(
3265
                            $optionList[$defaultValueId]['priority_message'],
3266
                            $messageType
3267
                        )
3268
                    );
3269
                }
3270
            }
3271
        }
3272
3273
        $select = $form->addSelect(
3274
            'extra_'.$fieldDetails['variable'],
3275
            $fieldDetails['display_text'],
3276
            [],
3277
            ['id' => 'extra_'.$fieldDetails['variable']]
3278
        );
3279
3280
        if (empty($defaultValueId)) {
3281
            $select->addOption(get_lang('Please select an option'), '');
3282
        }
3283
3284
        foreach ($options as $value => $text) {
3285
            if (empty($value)) {
3286
                $select->addOption($text, $value);
3287
                continue;
3288
            }
3289
3290
            $valueParts = explode('#', $text);
3291
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3292
3293
            $select->addOption(implode('', $valueParts), $value, ['data-value' => $dataValue]);
3294
        }
3295
3296
        if ($freezeElement) {
3297
            $form->freeze('extra_'.$fieldDetails['variable']);
3298
        }
3299
    }
3300
3301
    /**
3302
     * @param \FormValidator $form
3303
     * @param array          $fieldDetails
3304
     * @param array          $extraData
3305
     * @param bool           $freezeElement
3306
     *
3307
     * @return string JavaScript code
3308
     */
3309
    private function addDoubleSelectElement(FormValidator $form, $fieldDetails, $extraData, $freezeElement = false)
3310
    {
3311
        $firstSelectId = 'first_extra_'.$fieldDetails['variable'];
3312
        $secondSelectId = 'second_extra_'.$fieldDetails['variable'];
3313
3314
        $jqueryReadyContent = "
3315
            $('#$firstSelectId').on('change', function() {
3316
                var id = $(this).val();
3317
3318
                if (!id) {
3319
                    $('#$secondSelectId').empty().selectpicker('refresh');
3320
3321
                    return;
3322
                }
3323
3324
                $.getJSON(_p.web_ajax + 'extra_field.ajax.php?1=1&a=get_second_select_options', {
3325
                    'type': '{$this->type}',
3326
                    'field_id': {$fieldDetails['id']},
3327
                    'option_value_id': id
3328
                })
3329
                    .done(function(data) {
3330
                        $('#$secondSelectId').empty();
3331
                        $.each(data, function(index, value) {
3332
                            $('#second_extra_{$fieldDetails['variable']}').append(
3333
                                $('<option>', {value: index, text: value})
3334
                            );
3335
                        });
3336
                        $('#$secondSelectId').selectpicker('refresh');
3337
                    });
3338
            });
3339
        ";
3340
3341
        $firstId = null;
3342
        if (!empty($extraData)) {
3343
            if (isset($extraData['extra_'.$fieldDetails['variable']])) {
3344
                $firstId = $extraData['extra_'.$fieldDetails['variable']]['extra_'.$fieldDetails['variable']];
3345
            }
3346
        }
3347
3348
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3349
        $values = ['' => get_lang('Select')];
3350
3351
        $second_values = [];
3352
        if (!empty($options)) {
3353
            foreach ($options as $option) {
3354
                foreach ($option as $sub_option) {
3355
                    if ('0' == $sub_option['option_value']) {
3356
                        $values[$sub_option['id']] = $sub_option['display_text'];
3357
3358
                        continue;
3359
                    }
3360
3361
                    if ($firstId === $sub_option['option_value']) {
3362
                        $second_values[$sub_option['id']] = $sub_option['display_text'];
3363
                    }
3364
                }
3365
            }
3366
        }
3367
3368
        $form
3369
            ->defaultRenderer()
3370
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3371
        $group = [];
3372
        $group[] = $form->createElement(
3373
            'select',
3374
            'extra_'.$fieldDetails['variable'],
3375
            null,
3376
            $values,
3377
            ['id' => $firstSelectId]
3378
        );
3379
        $group[] = $form->createElement(
3380
            'select',
3381
            'extra_'.$fieldDetails['variable'].'_second',
3382
            null,
3383
            $second_values,
3384
            ['id' => $secondSelectId]
3385
        );
3386
        $form->addGroup(
3387
            $group,
3388
            'extra_'.$fieldDetails['variable'],
3389
            $fieldDetails['display_text']
3390
        );
3391
3392
        if ($freezeElement) {
3393
            $form->freeze('extra_'.$fieldDetails['variable']);
3394
        }
3395
3396
        return $jqueryReadyContent;
3397
    }
3398
3399
    /**
3400
     * @param \FormValidator $form
3401
     * @param bool           $freezeElement Optional
3402
     *
3403
     * @return string JavaScript code
3404
     */
3405
    private function addSelectWithTextFieldElement(
3406
        FormValidator $form,
3407
        array $fieldDetails,
3408
        $freezeElement = false
3409
    ) {
3410
        $firstSelectId = 'slct_extra_'.$fieldDetails['variable'];
3411
        $txtSelectId = 'txt_extra_'.$fieldDetails['variable'];
3412
3413
        $jqueryReadyContent = "
3414
            $('#$firstSelectId').on('change', function() {
3415
                var id = $(this).val();
3416
3417
                if (!id) {
3418
                    $('#$txtSelectId').val('');
3419
                }
3420
            });
3421
        ";
3422
3423
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3424
        $values = ['' => get_lang('Select')];
3425
3426
        if (!empty($options)) {
3427
            foreach ($options as $option) {
3428
                foreach ($option as $sub_option) {
3429
                    if ('0' != $sub_option['option_value']) {
3430
                        continue;
3431
                    }
3432
3433
                    $values[$sub_option['id']] = $sub_option['display_text'];
3434
                }
3435
            }
3436
        }
3437
3438
        $form
3439
            ->defaultRenderer()
3440
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3441
        $group = [];
3442
        $group[] = $form->createElement(
3443
            'select',
3444
            'extra_'.$fieldDetails['variable'],
3445
            null,
3446
            $values,
3447
            ['id' => $firstSelectId]
3448
        );
3449
        $group[] = $form->createElement(
3450
            'text',
3451
            'extra_'.$fieldDetails['variable'].'_second',
3452
            null,
3453
            ['id' => $txtSelectId]
3454
        );
3455
        $form->addGroup(
3456
            $group,
3457
            'extra_'.$fieldDetails['variable'],
3458
            $fieldDetails['display_text']
3459
        );
3460
3461
        if ($freezeElement) {
3462
            $form->freeze('extra_'.$fieldDetails['variable']);
3463
        }
3464
3465
        return $jqueryReadyContent;
3466
    }
3467
3468
    /**
3469
     * @param \FormValidator $form
3470
     * @param bool           $freezeElement
3471
     *
3472
     * @return string
3473
     */
3474
    private function addTripleSelectElement(
3475
        FormValidator $form,
3476
        array $fieldDetails,
3477
        array $extraData,
3478
        $freezeElement
3479
    ) {
3480
        $variable = $fieldDetails['variable'];
3481
        $id = $fieldDetails['id'];
3482
        $slctFirstId = "first_extra$variable";
3483
        $slctSecondId = "second_extra$variable";
3484
        $slctThirdId = "third_extra$variable";
3485
        $langSelect = get_lang('Select');
3486
3487
        $js = "
3488
            (function () {
3489
                var slctFirst = $('#$slctFirstId'),
3490
                    slctSecond = $('#$slctSecondId'),
3491
                    slctThird = $('#$slctThirdId');
3492
3493
                slctFirst.on('change', function () {
3494
                    slctSecond.empty().selectpicker('refresh');
3495
                    slctThird.empty().selectpicker('refresh');
3496
3497
                    var level = $(this).val();
3498
3499
                    if (!level) {
3500
                        return;
3501
                    }
3502
3503
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3504
                        'a': 'get_second_select_options',
3505
                        'type': '$this->type',
3506
                        'field_id': $id,
3507
                        'option_value_id': level
3508
                    })
3509
                        .done(function (data) {
3510
                            slctSecond.append(
3511
                                $('<option>', {value: '', text: '$langSelect'})
3512
                            );
3513
3514
                            $.each(data, function (index, value) {
3515
                                var valueParts = value.split('#'),
3516
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3517
3518
                                slctSecond.append(
3519
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3520
                                );
3521
                            });
3522
3523
                            slctSecond.selectpicker('refresh');
3524
                        });
3525
                });
3526
                slctSecond.on('change', function () {
3527
                    slctThird.empty().selectpicker('refresh');
3528
3529
                    var level = $(this).val();
3530
3531
                    if (!level) {
3532
                        return;
3533
                    }
3534
3535
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3536
                        'a': 'get_second_select_options',
3537
                        'type': '$this->type',
3538
                        'field_id': $id,
3539
                        'option_value_id': level
3540
                    })
3541
                        .done(function (data) {
3542
                            slctThird.append(
3543
                                $('<option>', {value: '', text: '$langSelect'})
3544
                            );
3545
3546
                            $.each(data, function (index, value) {
3547
                                var valueParts = value.split('#'),
3548
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3549
3550
                                slctThird.append(
3551
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3552
                                );
3553
                            });
3554
3555
                            slctThird.selectpicker('refresh');
3556
                        });
3557
                });
3558
            })();
3559
        ";
3560
3561
        $firstId = isset($extraData["extra_$variable"]["extra_$variable"])
3562
            ? $extraData["extra_$variable"]["extra_$variable"]
3563
            : '';
3564
        $secondId = isset($extraData["extra_$variable"]["extra_{$variable}_second"])
3565
            ? $extraData["extra_$variable"]["extra_{$variable}_second"]
3566
            : '';
3567
3568
        $options = $this->tripleSelectConvertArrayToOrderedArray($fieldDetails['options']);
3569
        $values1 = ['' => $langSelect];
3570
        $values2 = ['' => $langSelect];
3571
        $values3 = ['' => $langSelect];
3572
        $level1 = $this->getOptionsFromTripleSelect($options['level1'], 0);
3573
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], $firstId);
3574
        $level3 = $this->getOptionsFromTripleSelect($options['level3'], $secondId);
3575
        /** @var \HTML_QuickForm_select $slctFirst */
3576
        $slctFirst = $form->createElement('select', "extra_$variable", null, $values1, ['id' => $slctFirstId]);
3577
        /** @var \HTML_QuickForm_select $slctSecond */
3578
        $slctSecond = $form->createElement(
3579
            'select',
3580
            "extra_{$variable}_second",
3581
            null,
3582
            $values2,
3583
            ['id' => $slctSecondId]
3584
        );
3585
        /** @var \HTML_QuickForm_select $slctThird */
3586
        $slctThird = $form->createElement('select', "extra_{$variable}_third", null, $values3, ['id' => $slctThirdId]);
3587
3588
        foreach ($level1 as $item1) {
3589
            $valueParts = explode('#', $item1['display_text']);
3590
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3591
            $slctFirst->addOption(implode('', $valueParts), $item1['id'], ['data-value' => $dataValue]);
3592
        }
3593
3594
        foreach ($level2 as $item2) {
3595
            $valueParts = explode('#', $item2['display_text']);
3596
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3597
            $slctSecond->addOption(implode('', $valueParts), $item2['id'], ['data-value' => $dataValue]);
3598
        }
3599
3600
        foreach ($level3 as $item3) {
3601
            $valueParts = explode('#', $item3['display_text']);
3602
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3603
            $slctThird->addOption(implode('', $valueParts), $item3['id'], ['data-value' => $dataValue]);
3604
        }
3605
3606
        $form
3607
            ->defaultRenderer()
3608
            ->setGroupElementTemplate('<p>{element}</p>', "extra_$variable");
3609
        $form->addGroup([$slctFirst, $slctSecond, $slctThird], "extra_$variable", $fieldDetails['display_text']);
3610
3611
        if ($freezeElement) {
3612
            $form->freeze('extra_'.$fieldDetails['variable']);
3613
        }
3614
3615
        return $js;
3616
    }
3617
3618
    /**
3619
     * @param int $parentId
3620
     *
3621
     * @return array
3622
     */
3623
    private static function getOptionsFromTripleSelect(array $options, $parentId)
3624
    {
3625
        return array_filter(
3626
            $options,
3627
            function ($option) use ($parentId) {
3628
                return $option['option_value'] == $parentId;
3629
            }
3630
        );
3631
    }
3632
}
3633