Passed
Push — 1.11.x ( 421461...81886b )
by Yannick
11:09
created

ExtraField::set_extra_fields_in_form()   F

Complexity

Conditions 129
Paths 3

Size

Total Lines 807
Code Lines 519

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 519
dl 0
loc 807
rs 3.3333
c 0
b 0
f 0
cc 129
nc 3
nop 16

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

1259
                        $jquery_ready_content .= self::/** @scrutinizer ignore-call */ addDoubleSelectElement(
Loading history...
1260
                            $form,
1261
                            $field_details,
1262
                            $extraData,
1263
                            $freezeElement
1264
                        );
1265
                        break;
1266
                    case self::FIELD_TYPE_DIVIDER:
1267
                        $form->addHtml(
1268
                            '
1269
                            <div class="form-group ">
1270
                                <div class="col-sm-12">
1271
                                    <div class="panel-separator">
1272
                                       <h4 id="'.$field_details['variable'].'" class="form-separator">'
1273
                            .$field_details['display_text'].'
1274
                                       </h4>
1275
                                    </div>
1276
                                </div>
1277
                            </div>
1278
                        '
1279
                        );
1280
                        break;
1281
                    case self::FIELD_TYPE_TAG:
1282
                        $variable = $field_details['variable'];
1283
                        $field_id = $field_details['id'];
1284
                        $separateValue = 0;
1285
                        if (isset($separateExtraMultipleSelect[$field_details['variable']])) {
1286
                            $separateValue = $separateExtraMultipleSelect[$field_details['variable']];
1287
                        }
1288
1289
                        $selectedOptions = [];
1290
                        if ($separateValue > 0) {
1291
                            $em = Database::getManager();
1292
                            $fieldTags = $em
1293
                                ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1294
                                ->findBy(
1295
                                    [
1296
                                        'fieldId' => $field_id,
1297
                                        'itemId' => $itemId,
1298
                                    ]
1299
                                );
1300
                            // ofaj
1301
1302
                            for ($i = 0; $i < $separateValue; $i++) {
1303
                                $tagsSelect = $form->addElement(
1304
                                    'select',
1305
                                    'extra_'.$field_details['variable'].'['.$i.']',
1306
                                    $customLabelsExtraMultipleSelect[$field_details['variable']][$i],
1307
                                    null,
1308
                                    ['id' => 'extra_'.$field_details['variable'].'_'.$i]
1309
                                );
1310
1311
                                if ($addEmptyOptionSelects) {
1312
                                    $tagsSelect->addOption(
1313
                                        '',
1314
                                        ''
1315
                                    );
1316
                                }
1317
1318
                                foreach ($fieldTags as $fieldTag) {
1319
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1320
1321
                                    if (empty($tag)) {
1322
                                        continue;
1323
                                    }
1324
1325
                                    $tagsSelect->addOption(
1326
                                        $tag->getTag(),
1327
                                        $tag->getTag()
1328
                                    );
1329
                                }
1330
                            }
1331
                        } else {
1332
                            $tagsSelect = $form->addSelect(
1333
                                "extra_{$field_details['variable']}",
1334
                                $field_details['display_text'],
1335
                                [],
1336
                                ['style' => 'width: 100%;']
1337
                            );
1338
1339
                            if (false === $useTagAsSelect) {
1340
                                $tagsSelect->setAttribute('class', null);
1341
                            }
1342
1343
                            $tagsSelect->setAttribute(
1344
                                'id',
1345
                                "extra_{$field_details['variable']}"
1346
                            );
1347
                            $tagsSelect->setMultiple(true);
1348
1349
                            $selectedOptions = [];
1350
                            if ('user' === $this->type) {
1351
                                // The magic should be here
1352
                                $user_tags = UserManager::get_user_tags(
1353
                                    $itemId,
1354
                                    $field_details['id']
1355
                                );
1356
1357
                                if (is_array($user_tags) && count($user_tags) > 0) {
1358
                                    foreach ($user_tags as $tag) {
1359
                                        if (empty($tag['tag'])) {
1360
                                            continue;
1361
                                        }
1362
                                        $tagsSelect->addOption(
1363
                                            $tag['tag'],
1364
                                            $tag['tag'],
1365
                                            [
1366
                                                'selected' => 'selected',
1367
                                                'class' => 'selected',
1368
                                            ]
1369
                                        );
1370
                                        $selectedOptions[] = $tag['tag'];
1371
                                    }
1372
                                }
1373
                                $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
1374
                            } else {
1375
                                $em = Database::getManager();
1376
                                $fieldTags = $em->getRepository(
1377
                                    'ChamiloCoreBundle:ExtraFieldRelTag'
1378
                                )
1379
                                    ->findBy(
1380
                                        [
1381
                                            'fieldId' => $field_id,
1382
                                            'itemId' => $itemId,
1383
                                        ]
1384
                                    );
1385
1386
                                /** @var ExtraFieldRelTag $fieldTag */
1387
                                foreach ($fieldTags as $fieldTag) {
1388
                                    /** @var Tag $tag */
1389
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1390
1391
                                    if (empty($tag)) {
1392
                                        continue;
1393
                                    }
1394
                                    $tagsSelect->addOption(
1395
                                        $tag->getTag(),
1396
                                        $tag->getTag()
1397
                                    );
1398
                                    $selectedOptions[] = $tag->getTag();
1399
                                }
1400
1401
                                if (!empty($extraData) && isset($extraData['extra_'.$field_details['variable']])) {
1402
                                    $data = $extraData['extra_'.$field_details['variable']];
1403
                                    if (!empty($data)) {
1404
                                        foreach ($data as $option) {
1405
                                            $tagsSelect->addOption(
1406
                                                $option,
1407
                                                $option
1408
                                            );
1409
                                        }
1410
                                    }
1411
                                }
1412
1413
                                if ($useTagAsSelect) {
1414
                                    $fieldTags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1415
                                        ->findBy(
1416
                                            [
1417
                                                'fieldId' => $field_id,
1418
                                            ]
1419
                                        );
1420
                                    $tagsAdded = [];
1421
                                    foreach ($fieldTags as $fieldTag) {
1422
                                        $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1423
1424
                                        if (empty($tag)) {
1425
                                            continue;
1426
                                        }
1427
1428
                                        $tagText = $tag->getTag();
1429
1430
                                        if (in_array($tagText, $tagsAdded)) {
1431
                                            continue;
1432
                                        }
1433
1434
                                        $tagsSelect->addOption(
1435
                                            $tag->getTag(),
1436
                                            $tag->getTag(),
1437
                                            []
1438
                                        );
1439
1440
                                        $tagsAdded[] = $tagText;
1441
                                    }
1442
                                }
1443
                                $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
1444
                            }
1445
1446
                            $allowAsTags = 'true';
1447
1448
                            if ('portfolio' === $this->type) {
1449
                                $allowAsTags = 'false';
1450
                            }
1451
1452
                            $form->setDefaults(
1453
                                [
1454
                                    'extra_'.$field_details['variable'] => $selectedOptions,
1455
                                ]
1456
                            );
1457
1458
                            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...
1459
                                $jquery_ready_content .= "
1460
                                $('#extra_$variable').select2({
1461
                                    ajax: {
1462
                                        url: '$url?a=search_tags&field_id=$field_id&type={$this->type}',
1463
                                        processResults: function (data) {
1464
                                            return {
1465
                                                results: data.items
1466
                                            }
1467
                                        }
1468
                                    },
1469
                                    cache: false,
1470
                                    tags: $allowAsTags,
1471
                                    tokenSeparators: [','],
1472
                                    placeholder: '".get_lang('StartToType')."'
1473
                                });
1474
                            ";
1475
                            }
1476
                        }
1477
1478
                        break;
1479
                    case self::FIELD_TYPE_TIMEZONE:
1480
                        $form->addElement(
1481
                            'select',
1482
                            'extra_'.$field_details['variable'],
1483
                            $field_details['display_text'],
1484
                            api_get_timezones(),
1485
                            ''
1486
                        );
1487
                        if ($freezeElement) {
1488
                            $form->freeze('extra_'.$field_details['variable']);
1489
                        }
1490
                        break;
1491
                    case self::FIELD_TYPE_SOCIAL_PROFILE:
1492
                        // get the social network's favicon
1493
                        $extra_data_variable = isset($extraData['extra_'.$field_details['variable']])
1494
                            ? $extraData['extra_'.$field_details['variable']]
1495
                            : null;
1496
                        $field_default_value = isset($field_details['field_default_value'])
1497
                            ? $field_details['field_default_value']
1498
                            : null;
1499
                        $icon_path = UserManager::get_favicon_from_url(
1500
                            $extra_data_variable,
1501
                            $field_default_value
1502
                        );
1503
                        // special hack for hi5
1504
                        $leftpad = '1.7';
1505
                        $top = '0.4';
1506
                        $domain = parse_url($icon_path, PHP_URL_HOST);
1507
                        if ('www.hi5.com' === $domain || 'hi5.com' === $domain) {
1508
                            $leftpad = '3';
1509
                            $top = '0';
1510
                        }
1511
                        // print the input field
1512
                        $form->addElement(
1513
                            'text',
1514
                            'extra_'.$field_details['variable'],
1515
                            $field_details['display_text'],
1516
                            [
1517
                                'size' => 60,
1518
                                'size' => implode(
1519
                                    '; ',
1520
                                    [
1521
                                        "background-image: url('$icon_path')",
1522
                                        'background-repeat: no-repeat',
1523
                                        "background-position: 0.4em {$top}em",
1524
                                        "padding-left: {$leftpad}em",
1525
                                    ]
1526
                                ),
1527
                            ]
1528
                        );
1529
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1530
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1531
                        $form->applyFilter('extra_'.$field_details['variable'], 'html_filter');
1532
                        if ($freezeElement) {
1533
                            $form->freeze('extra_'.$field_details['variable']);
1534
                        }
1535
                        break;
1536
                    case self::FIELD_TYPE_MOBILE_PHONE_NUMBER:
1537
                        $form->addElement(
1538
                            'text',
1539
                            'extra_'.$field_details['variable'],
1540
                            $field_details['display_text'].' ('.get_lang('CountryDialCode').')',
1541
                            ['size' => 40, 'placeholder' => '(xx)xxxxxxxxx']
1542
                        );
1543
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1544
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1545
                        $form->applyFilter('extra_'.$field_details['variable'], 'mobile_phone_number_filter');
1546
                        $form->applyFilter('extra_'.$field_details['variable'], 'html_filter');
1547
                        $form->addRule(
1548
                            'extra_'.$field_details['variable'],
1549
                            get_lang('MobilePhoneNumberWrong'),
1550
                            'mobile_phone_number'
1551
                        );
1552
                        if ($freezeElement) {
1553
                            $form->freeze('extra_'.$field_details['variable']);
1554
                        }
1555
                        break;
1556
                    case self::FIELD_TYPE_INTEGER:
1557
                        $form->addElement(
1558
                            'number',
1559
                            'extra_'.$field_details['variable'],
1560
                            $field_details['display_text'],
1561
                            ['class' => 'span1', 'step' => 1]
1562
                        );
1563
1564
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1565
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1566
                        $form->applyFilter('extra_'.$field_details['variable'], 'intval');
1567
1568
                        if ($freezeElement) {
1569
                            $form->freeze('extra_'.$field_details['variable']);
1570
                        }
1571
                        break;
1572
                    case self::FIELD_TYPE_FILE_IMAGE:
1573
                        $fieldVariable = "extra_{$field_details['variable']}";
1574
                        $fieldTexts = [
1575
                            $field_details['display_text'],
1576
                        ];
1577
1578
                        if (is_array($extraData) && array_key_exists($fieldVariable, $extraData)) {
1579
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1580
                                $fieldTexts[] = Display::img(
1581
                                    api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1582
                                    $field_details['display_text'],
1583
                                    ['width' => '300']
1584
                                );
1585
                            }
1586
                        }
1587
1588
                        if ('Image' === $fieldTexts[0]) {
1589
                            $fieldTexts[0] = get_lang($fieldTexts[0]);
1590
                        }
1591
1592
                        $form->addFile(
1593
                            $fieldVariable,
1594
                            $fieldTexts,
1595
                            ['accept' => 'image/*', 'id' => 'extra_image', 'crop_image' => 'true']
1596
                        );
1597
1598
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1599
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1600
1601
                        $allowedPictureTypes = ['jpg', 'jpeg', 'png', 'gif'];
1602
                        $form->addRule(
1603
                            'extra_'.$field_details['variable'],
1604
                            get_lang('OnlyImagesAllowed').' ('.implode(',', $allowedPictureTypes).')',
1605
                            'filetype',
1606
                            $allowedPictureTypes
1607
                        );
1608
1609
                        if ($freezeElement) {
1610
                            $form->freeze('extra_'.$field_details['variable']);
1611
                        }
1612
                        break;
1613
                    case self::FIELD_TYPE_FLOAT:
1614
                        $form->addElement(
1615
                            'number',
1616
                            'extra_'.$field_details['variable'],
1617
                            $field_details['display_text'],
1618
                            ['class' => 'span1', 'step' => '0.01']
1619
                        );
1620
1621
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1622
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1623
                        $form->applyFilter('extra_'.$field_details['variable'], 'floatval');
1624
1625
                        if ($freezeElement) {
1626
                            $form->freeze('extra_'.$field_details['variable']);
1627
                        }
1628
                        break;
1629
                    case self::FIELD_TYPE_FILE:
1630
                        $fieldVariable = "extra_{$field_details['variable']}";
1631
                        $fieldTexts = [
1632
                            $field_details['display_text'],
1633
                        ];
1634
1635
                        if (is_array($extraData) &&
1636
                            array_key_exists($fieldVariable, $extraData)
1637
                        ) {
1638
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1639
                                $linkToDelete = '';
1640
                                $divItemId = $field_details['variable'];
1641
                                if (api_is_platform_admin()) {
1642
                                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?type='.$this->type;
1643
                                    $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId;
1644
1645
                                    $deleteId = $field_details['variable'].'_delete';
1646
                                    $form->addHtml(
1647
                                        "
1648
                                        <script>
1649
                                            $(function() {
1650
                                                $('#".$deleteId."').on('click', function() {
1651
                                                    $.ajax({
1652
                                                        type: 'GET',
1653
                                                        url: '".$url."',
1654
                                                        success: function(result) {
1655
                                                            if (result == 1) {
1656
                                                                $('#".$divItemId."').html('".get_lang('Deleted')."');
1657
                                                            }
1658
                                                        }
1659
                                                    });
1660
                                                });
1661
                                            });
1662
                                        </script>
1663
                                    "
1664
                                    );
1665
1666
                                    $linkToDelete = '&nbsp;'.Display::url(
1667
                                            Display::return_icon('delete.png', get_lang('Delete')),
1668
                                            'javascript:void(0)',
1669
                                            ['id' => $deleteId]
1670
                                        );
1671
                                }
1672
                                $fieldTexts[] = '<div id="'.$divItemId.'">'.Display::url(
1673
                                        basename($extraData[$fieldVariable]),
1674
                                        api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1675
                                        [
1676
                                            'title' => $field_details['display_text'],
1677
                                            'target' => '_blank',
1678
                                        ]
1679
                                    ).$linkToDelete.'</div>';
1680
                            }
1681
                        }
1682
1683
                        $form->addElement(
1684
                            'file',
1685
                            $fieldVariable,
1686
                            $fieldTexts,
1687
                            []
1688
                        );
1689
1690
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1691
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1692
1693
                        if ($freezeElement) {
1694
                            $form->freeze('extra_'.$field_details['variable']);
1695
                        }
1696
                        break;
1697
                    case self::FIELD_TYPE_VIDEO_URL:
1698
                        $form->addUrl(
1699
                            "extra_{$field_details['variable']}",
1700
                            $field_details['display_text'],
1701
                            false,
1702
                            ['placeholder' => 'https://']
1703
                        );
1704
                        if ($freezeElement) {
1705
                            $form->freeze('extra_'.$field_details['variable']);
1706
                        }
1707
                        break;
1708
                    case self::FIELD_TYPE_LETTERS_ONLY:
1709
                        $form->addTextLettersOnly(
1710
                            "extra_{$field_details['variable']}",
1711
                            $field_details['display_text']
1712
                        );
1713
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1714
1715
                        if ($freezeElement) {
1716
                            $form->freeze('extra_'.$field_details['variable']);
1717
                        }
1718
                        break;
1719
                    case self::FIELD_TYPE_ALPHANUMERIC:
1720
                        $form->addTextAlphanumeric(
1721
                            "extra_{$field_details['variable']}",
1722
                            $field_details['display_text']
1723
                        );
1724
                        $form->applyFilter(
1725
                            'extra_'.$field_details['variable'],
1726
                            'stripslashes'
1727
                        );
1728
                        if ($freezeElement) {
1729
                            $form->freeze('extra_'.$field_details['variable']);
1730
                        }
1731
                        break;
1732
                    case self::FIELD_TYPE_LETTERS_SPACE:
1733
                        $form->addTextLettersAndSpaces(
1734
                            "extra_{$field_details['variable']}",
1735
                            $field_details['display_text']
1736
                        );
1737
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1738
1739
                        if ($freezeElement) {
1740
                            $form->freeze('extra_'.$field_details['variable']);
1741
                        }
1742
                        break;
1743
                    case self::FIELD_TYPE_ALPHANUMERIC_SPACE:
1744
                        $form->addTextAlphanumericAndSpaces(
1745
                            "extra_{$field_details['variable']}",
1746
                            $field_details['display_text']
1747
                        );
1748
                        $form->applyFilter(
1749
                            'extra_'.$field_details['variable'],
1750
                            'stripslashes'
1751
                        );
1752
                        if ($freezeElement) {
1753
                            $form->freeze('extra_'.$field_details['variable']);
1754
                        }
1755
                        break;
1756
                    case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
1757
                    case self::FIELD_TYPE_GEOLOCALIZATION:
1758
                        $dataValue = isset($extraData['extra_'.$field_details['variable']])
1759
                            ? $extraData['extra_'.$field_details['variable']]
1760
                            : '';
1761
1762
                        $form->addGeoLocationMapField(
1763
                            'extra_'.$field_details['variable'],
1764
                            $field_details['display_text'],
1765
                            $dataValue,
1766
                            $hideGeoLocalizationDetails
1767
                        );
1768
1769
                        if ($freezeElement) {
1770
                            $form->freeze('extra_'.$field_details['variable']);
1771
                        }
1772
                        break;
1773
                    case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
1774
                        $jquery_ready_content .= $this->addSelectWithTextFieldElement(
1775
                            $form,
1776
                            $field_details,
1777
                            $freezeElement
1778
                        );
1779
                        break;
1780
                    case self::FIELD_TYPE_TRIPLE_SELECT:
1781
                        $jquery_ready_content .= $this->addTripleSelectElement(
1782
                            $form,
1783
                            $field_details,
1784
                            is_array($extraData) ? $extraData : [],
1785
                            $freezeElement
1786
                        );
1787
                        break;
1788
                }
1789
            }
1790
        }
1791
1792
        $return = [];
1793
        $return['jquery_ready_content'] = $jquery_ready_content;
1794
1795
        return $return;
1796
    }
1797
1798
    /**
1799
     * @param array $options
1800
     *
1801
     * @return array
1802
     */
1803
    public static function extra_field_double_select_convert_array_to_ordered_array($options)
1804
    {
1805
        $optionsParsed = [];
1806
        if (!empty($options)) {
1807
            foreach ($options as $option) {
1808
                if (0 == $option['option_value']) {
1809
                    $optionsParsed[$option['id']][] = $option;
1810
                } else {
1811
                    $optionsParsed[$option['option_value']][] = $option;
1812
                }
1813
            }
1814
        }
1815
1816
        return $optionsParsed;
1817
    }
1818
1819
    /**
1820
     * @return array
1821
     */
1822
    public static function tripleSelectConvertArrayToOrderedArray(array $options)
1823
    {
1824
        $level1 = self::getOptionsFromTripleSelect($options, 0);
1825
        $level2 = [];
1826
        $level3 = [];
1827
1828
        foreach ($level1 as $item1) {
1829
            $level2 += self::getOptionsFromTripleSelect($options, $item1['id']);
1830
        }
1831
1832
        foreach ($level2 as $item2) {
1833
            $level3 += self::getOptionsFromTripleSelect($options, $item2['id']);
1834
        }
1835
1836
        return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3];
1837
    }
1838
1839
    /**
1840
     * @param string $type
1841
     *
1842
     * @return array
1843
     */
1844
    public function get_all_extra_field_by_type($type)
1845
    {
1846
        // all the information of the field
1847
        $sql = "SELECT * FROM {$this->table}
1848
                WHERE
1849
                    field_type = '".Database::escape_string($type)."' AND
1850
                    extra_field_type = $this->extraFieldType
1851
                ";
1852
        $result = Database::query($sql);
1853
1854
        $return = [];
1855
        while ($row = Database::fetch_array($result)) {
1856
            $return[] = $row['id'];
1857
        }
1858
1859
        return $return;
1860
    }
1861
1862
    /**
1863
     * @param int $id
1864
     */
1865
    public function get_field_type_by_id($id)
1866
    {
1867
        $types = $this->get_field_types();
1868
        if (isset($types[$id])) {
1869
            return $types[$id];
1870
        }
1871
1872
        return null;
1873
    }
1874
1875
    /**
1876
     * @return array
1877
     */
1878
    public function get_field_types()
1879
    {
1880
        return $this->get_extra_fields_by_handler($this->type);
1881
    }
1882
1883
    /**
1884
     * @param string $handler
1885
     *
1886
     * @return array
1887
     */
1888
    public static function get_extra_fields_by_handler($handler)
1889
    {
1890
        $types = [];
1891
        $types[self::FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
1892
        $types[self::FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
1893
        $types[self::FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
1894
        $types[self::FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
1895
        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
1896
        $types[self::FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
1897
        $types[self::FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
1898
        $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
1899
        $types[self::FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
1900
        $types[self::FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
1901
        $types[self::FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
1902
        $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
1903
        $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
1904
        $types[self::FIELD_TYPE_CHECKBOX] = get_lang('FieldTypeCheckbox');
1905
        $types[self::FIELD_TYPE_INTEGER] = get_lang('FieldTypeInteger');
1906
        $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('FieldTypeFileImage');
1907
        $types[self::FIELD_TYPE_FLOAT] = get_lang('FieldTypeFloat');
1908
        $types[self::FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
1909
        $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('FieldTypeVideoUrl');
1910
        $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('FieldTypeOnlyLetters');
1911
        $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('FieldTypeAlphanumeric');
1912
        $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('FieldTypeLettersSpaces');
1913
        $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('FieldTypeAlphanumericSpaces');
1914
        $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization');
1915
        $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('GeolocalizationCoordinates');
1916
        $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('FieldTypeSelectWithTextField');
1917
        $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('FieldTypeTripleSelect');
1918
1919
        switch ($handler) {
1920
            case 'course':
1921
            case 'session':
1922
            case 'user':
1923
            case 'skill':
1924
                break;
1925
        }
1926
1927
        return $types;
1928
    }
1929
1930
    /**
1931
     * @param array $params
1932
     * @param bool  $show_query
1933
     *
1934
     * @return int|bool
1935
     */
1936
    public function save($params, $show_query = false)
1937
    {
1938
        $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

1938
        /** @scrutinizer ignore-call */ 
1939
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1939
        $params = $this->clean_parameters($params);
1940
        $params['extra_field_type'] = $this->extraFieldType;
1941
1942
        if ($fieldInfo) {
1943
            return $fieldInfo['id'];
1944
        } else {
1945
            $id = parent::save($params, $show_query);
1946
            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...
1947
                $fieldOption = new ExtraFieldOption($this->type);
1948
                $params['field_id'] = $id;
1949
                $fieldOption->save($params);
1950
            }
1951
1952
            return $id;
1953
        }
1954
    }
1955
1956
    /**
1957
     * Gets the set of values of an extra_field searching for the variable name.
1958
     *
1959
     * Example:
1960
     * <code>
1961
     * <?php
1962
     * $extraField = new ExtraField('lp_item');
1963
     * $extraFieldArray =  $extraField->get_handler_field_info_by_field_variable('authorlpitem');
1964
     * echo "<pre>".var_export($extraFieldArray,true)."</pre>";
1965
     * ?>
1966
     * </code>
1967
     *
1968
     * @param string $variable
1969
     *
1970
     * @return array|bool
1971
     */
1972
    public function get_handler_field_info_by_field_variable($variable)
1973
    {
1974
        $variable = Database::escape_string($variable);
1975
        $sql = "SELECT * FROM {$this->table}
1976
                WHERE
1977
                    variable = '$variable' AND
1978
                    extra_field_type = $this->extraFieldType";
1979
        $result = Database::query($sql);
1980
        if (Database::num_rows($result)) {
1981
            $row = Database::fetch_array($result, 'ASSOC');
1982
            if ($row) {
1983
                $row['display_text'] = self::translateDisplayName($row['variable'], $row['display_text']);
1984
1985
                // All the options of the field
1986
                $sql = "SELECT * FROM $this->table_field_options
1987
                    WHERE field_id='".intval($row['id'])."'
1988
                    ORDER BY option_order ASC";
1989
                $result = Database::query($sql);
1990
                while ($option = Database::fetch_array($result)) {
1991
                    $row['options'][$option['id']] = $option;
1992
                }
1993
1994
                return $row;
1995
            }
1996
        }
1997
1998
        return false;
1999
    }
2000
2001
    public function getHandlerEntityByFieldVariable(string $variable)
2002
    {
2003
        return Database::getManager()
2004
            ->getRepository('ChamiloCoreBundle:ExtraField')
2005
            ->findOneBy(['variable' => $variable, 'extraFieldType' => $this->extraFieldType]);
2006
    }
2007
2008
    /**
2009
     * @param array $params
2010
     *
2011
     * @return array
2012
     */
2013
    public function clean_parameters($params)
2014
    {
2015
        if (!isset($params['variable']) || empty($params['variable'])) {
2016
            $params['variable'] = $params['display_text'];
2017
        }
2018
2019
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
2020
2021
        if (!isset($params['field_order'])) {
2022
            $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

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

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