Completed
Push — 1.11.x ( 52e70d...c40020 )
by
unknown
01:55 queued 48s
created

ExtraField::addElements()   C

Complexity

Conditions 14
Paths 121

Size

Total Lines 90
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 51
c 0
b 0
f 0
dl 0
loc 90
rs 6.0916
cc 14
nc 121
nop 17

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

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

1977
        /** @scrutinizer ignore-call */ 
1978
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1978
        $params = $this->clean_parameters($params);
1979
        $params['extra_field_type'] = $this->extraFieldType;
1980
1981
        if ($fieldInfo) {
1982
            return $fieldInfo['id'];
1983
        } else {
1984
            $id = parent::save($params, $show_query);
1985
            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...
1986
                $fieldOption = new ExtraFieldOption($this->type);
1987
                $params['field_id'] = $id;
1988
                $fieldOption->save($params);
1989
            }
1990
1991
            return $id;
1992
        }
1993
    }
1994
1995
    /**
1996
     * Gets the set of values of an extra_field searching for the variable name.
1997
     *
1998
     * Example:
1999
     * <code>
2000
     * <?php
2001
     * $extraField = new ExtraField('lp_item');
2002
     * $extraFieldArray =  $extraField->get_handler_field_info_by_field_variable('authorlpitem');
2003
     * echo "<pre>".var_export($extraFieldArray,true)."</pre>";
2004
     * ?>
2005
     * </code>
2006
     *
2007
     * @param string $variable
2008
     *
2009
     * @return array|bool
2010
     */
2011
    public function get_handler_field_info_by_field_variable($variable)
2012
    {
2013
        $variable = Database::escape_string($variable);
2014
        $sql = "SELECT * FROM {$this->table}
2015
                WHERE
2016
                    variable = '$variable' AND
2017
                    extra_field_type = $this->extraFieldType";
2018
        $result = Database::query($sql);
2019
        if (Database::num_rows($result)) {
2020
            $row = Database::fetch_array($result, 'ASSOC');
2021
            if ($row) {
2022
                $row['display_text'] = self::translateDisplayName($row['variable'], $row['display_text']);
2023
2024
                // All the options of the field
2025
                $sql = "SELECT * FROM $this->table_field_options
2026
                    WHERE field_id='".intval($row['id'])."'
2027
                    ORDER BY option_order ASC";
2028
                $result = Database::query($sql);
2029
                while ($option = Database::fetch_array($result)) {
2030
                    $row['options'][$option['id']] = $option;
2031
                }
2032
2033
                return $row;
2034
            }
2035
        }
2036
2037
        return false;
2038
    }
2039
2040
    public function getHandlerEntityByFieldVariable(string $variable)
2041
    {
2042
        return Database::getManager()
2043
            ->getRepository('ChamiloCoreBundle:ExtraField')
2044
            ->findOneBy(['variable' => $variable, 'extraFieldType' => $this->extraFieldType]);
2045
    }
2046
2047
    /**
2048
     * @param array $params
2049
     *
2050
     * @return array
2051
     */
2052
    public function clean_parameters($params)
2053
    {
2054
        if (!isset($params['variable']) || empty($params['variable'])) {
2055
            $params['variable'] = $params['display_text'];
2056
        }
2057
2058
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
2059
2060
        if (!isset($params['field_order'])) {
2061
            $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

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

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