Passed
Push — 1.11.x ( c59910...58f0fa )
by
unknown
20:38 queued 09:36
created

ExtraField::set_extra_fields_in_form()   F

Complexity

Conditions 134
Paths 3

Size

Total Lines 828
Code Lines 533

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 533
c 1
b 0
f 1
dl 0
loc 828
rs 3.3333
cc 134
nc 3
nop 16

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
7
use Chamilo\CoreBundle\Entity\Tag;
8
9
/**
10
 * Class ExtraField.
11
 */
12
class ExtraField extends Model
13
{
14
    public const FIELD_TYPE_TEXT = 1;
15
    public const FIELD_TYPE_TEXTAREA = 2;
16
    public const FIELD_TYPE_RADIO = 3;
17
    public const FIELD_TYPE_SELECT = 4;
18
    public const FIELD_TYPE_SELECT_MULTIPLE = 5;
19
    public const FIELD_TYPE_DATE = 6;
20
    public const FIELD_TYPE_DATETIME = 7;
21
    public const FIELD_TYPE_DOUBLE_SELECT = 8;
22
    public const FIELD_TYPE_DIVIDER = 9;
23
    public const FIELD_TYPE_TAG = 10;
24
    public const FIELD_TYPE_TIMEZONE = 11;
25
    public const FIELD_TYPE_SOCIAL_PROFILE = 12;
26
    public const FIELD_TYPE_CHECKBOX = 13;
27
    public const FIELD_TYPE_MOBILE_PHONE_NUMBER = 14;
28
    public const FIELD_TYPE_INTEGER = 15;
29
    public const FIELD_TYPE_FILE_IMAGE = 16;
30
    public const FIELD_TYPE_FLOAT = 17;
31
    public const FIELD_TYPE_FILE = 18;
32
    public const FIELD_TYPE_VIDEO_URL = 19;
33
    public const FIELD_TYPE_LETTERS_ONLY = 20;
34
    public const FIELD_TYPE_ALPHANUMERIC = 21;
35
    public const FIELD_TYPE_LETTERS_SPACE = 22;
36
    public const FIELD_TYPE_ALPHANUMERIC_SPACE = 23;
37
    public const FIELD_TYPE_GEOLOCALIZATION = 24;
38
    public const FIELD_TYPE_GEOLOCALIZATION_COORDINATES = 25;
39
    public const FIELD_TYPE_SELECT_WITH_TEXT_FIELD = 26;
40
    public const FIELD_TYPE_TRIPLE_SELECT = 27;
41
    public $columns = [
42
        'id',
43
        'field_type',
44
        'variable',
45
        'display_text',
46
        'default_value',
47
        'field_order',
48
        'visible_to_self',
49
        'visible_to_others',
50
        'changeable',
51
        'filter',
52
        'extra_field_type',
53
        //Enable this when field_loggeable is introduced as a table field (2.0)
54
        //'field_loggeable',
55
        'created_at',
56
    ];
57
58
    public $ops = [
59
        'eq' => '=', //equal
60
        'ne' => '<>', //not equal
61
        'lt' => '<', //less than
62
        'le' => '<=', //less than or equal
63
        'gt' => '>', //greater than
64
        'ge' => '>=', //greater than or equal
65
        'bw' => 'LIKE', //begins with
66
        'bn' => 'NOT LIKE', //doesn't begin with
67
        'in' => 'LIKE', //is in
68
        'ni' => 'NOT LIKE', //is not in
69
        'ew' => 'LIKE', //ends with
70
        'en' => 'NOT LIKE', //doesn't end with
71
        'cn' => 'LIKE', //contains
72
        'nc' => 'NOT LIKE',  //doesn't contain
73
    ];
74
75
    public $type = 'user';
76
    public $pageName;
77
    public $pageUrl;
78
    public $extraFieldType = 0;
79
80
    public $table;
81
    public $table_field_options;
82
    public $table_field_values;
83
    public $table_field_tag;
84
    public $table_field_rel_tag;
85
86
    public $handler_id;
87
    public $primaryKey;
88
89
    /**
90
     * @param string $type
91
     */
92
    public function __construct($type)
93
    {
94
        parent::__construct();
95
96
        $this->type = $type;
97
        $this->table = Database::get_main_table(TABLE_EXTRA_FIELD);
98
        $this->table_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
99
        $this->table_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
100
        $this->table_field_tag = Database::get_main_table(TABLE_MAIN_TAG);
101
        $this->table_field_rel_tag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
102
103
        $this->handler_id = 'item_id';
104
105
        switch ($this->type) {
106
            case 'calendar_event':
107
                $this->extraFieldType = EntityExtraField::CALENDAR_FIELD_TYPE;
108
                break;
109
            case 'course':
110
                $this->extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
111
                $this->primaryKey = 'id';
112
                break;
113
            case 'user':
114
                $this->extraFieldType = EntityExtraField::USER_FIELD_TYPE;
115
                $this->primaryKey = 'id';
116
                break;
117
            case 'session':
118
                $this->extraFieldType = EntityExtraField::SESSION_FIELD_TYPE;
119
                $this->primaryKey = 'id';
120
                break;
121
            case 'exercise':
122
                $this->extraFieldType = EntityExtraField::EXERCISE_FIELD_TYPE;
123
                break;
124
            case 'question':
125
                $this->extraFieldType = EntityExtraField::QUESTION_FIELD_TYPE;
126
                break;
127
            case 'lp':
128
                $this->extraFieldType = EntityExtraField::LP_FIELD_TYPE;
129
                break;
130
            case 'lp_item':
131
                $this->extraFieldType = EntityExtraField::LP_ITEM_FIELD_TYPE;
132
                break;
133
            case 'skill':
134
                $this->extraFieldType = EntityExtraField::SKILL_FIELD_TYPE;
135
                break;
136
            case 'work':
137
                $this->extraFieldType = EntityExtraField::WORK_FIELD_TYPE;
138
                break;
139
            case 'career':
140
                $this->extraFieldType = EntityExtraField::CAREER_FIELD_TYPE;
141
                break;
142
            case 'user_certificate':
143
                $this->extraFieldType = EntityExtraField::USER_CERTIFICATE;
144
                break;
145
            case 'survey':
146
                $this->extraFieldType = EntityExtraField::SURVEY_FIELD_TYPE;
147
                break;
148
            case 'scheduled_announcement':
149
                $this->extraFieldType = EntityExtraField::SCHEDULED_ANNOUNCEMENT;
150
                break;
151
            case 'terms_and_condition':
152
                $this->extraFieldType = EntityExtraField::TERMS_AND_CONDITION_TYPE;
153
                break;
154
            case 'forum_category':
155
                $this->extraFieldType = EntityExtraField::FORUM_CATEGORY_TYPE;
156
                break;
157
            case 'forum_post':
158
                $this->extraFieldType = EntityExtraField::FORUM_POST_TYPE;
159
                break;
160
            case 'track_exercise':
161
                $this->extraFieldType = EntityExtraField::TRACK_EXERCISE_FIELD_TYPE;
162
                break;
163
            case 'portfolio':
164
                $this->extraFieldType = EntityExtraField::PORTFOLIO_TYPE;
165
                break;
166
            case 'lp_view':
167
                $this->extraFieldType = EntityExtraField::LP_VIEW_TYPE;
168
                break;
169
            case 'course_announcement':
170
                $this->extraFieldType = EntityExtraField::COURSE_ANNOUNCEMENT;
171
                break;
172
            case 'message':
173
                $this->extraFieldType = EntityExtraField::MESSAGE_TYPE;
174
                break;
175
            case 'document':
176
                $this->extraFieldType = EntityExtraField::DOCUMENT_TYPE;
177
                break;
178
            case 'attendance_calendar':
179
                $this->extraFieldType = EntityExtraField::ATTENDANCE_CALENDAR_TYPE;
180
                break;
181
            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 (in_array($extraName, array_keys($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
        if (!empty($requiredFields)) {
828
            /** @var HTML_QuickForm_input $element */
829
            foreach ($form->getElements() as $element) {
830
                $name = str_replace('extra_', '', $element->getName());
831
                if (in_array($name, $requiredFields)) {
832
                    $form->setRequired($element);
833
                }
834
            }
835
        }
836
837
        return $extra;
838
    }
839
840
    /**
841
     * Return an array of all the extra fields available for this item.
842
     *
843
     * @param int $itemId (session_id, question_id, course id)
844
     *
845
     * @return array
846
     */
847
    public function get_handler_extra_data($itemId)
848
    {
849
        if (empty($itemId)) {
850
            return [];
851
        }
852
853
        $extra_data = [];
854
        $fields = $this->get_all();
855
        $field_values = new ExtraFieldValue($this->type);
856
857
        if (!empty($fields)) {
858
            foreach ($fields as $field) {
859
                $field_value = $field_values->get_values_by_handler_and_field_id(
860
                    $itemId,
861
                    $field['id']
862
                );
863
864
                if (self::FIELD_TYPE_TAG == $field['field_type']) {
865
                    $tags = UserManager::get_user_tags_to_string(
866
                        $itemId,
867
                        $field['id'],
868
                        false
869
                    );
870
                    $extra_data['extra_'.$field['variable']] = $tags;
871
872
                    continue;
873
                }
874
875
                if ($field_value) {
876
                    $variable = $field['variable'];
877
                    $field_value = $field_value['value'];
878
                    switch ($field['field_type']) {
879
                        case self::FIELD_TYPE_TAG:
880
                            $tags = UserManager::get_user_tags_to_string(
881
                                $itemId,
882
                                $field['id'],
883
                                false
884
                            );
885
886
                            $extra_data['extra_'.$field['variable']] = $tags;
887
                            break;
888
                        case self::FIELD_TYPE_DOUBLE_SELECT:
889
                        case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
890
                            $selected_options = explode('::', $field_value);
891
                            $firstOption = isset($selected_options[0]) ? $selected_options[0] : '';
892
                            $secondOption = isset($selected_options[1]) ? $selected_options[1] : '';
893
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $firstOption;
894
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable'].'_second'] = $secondOption;
895
896
                            break;
897
                        case self::FIELD_TYPE_SELECT_MULTIPLE:
898
                            $field_value = explode(';', $field_value);
899
                            $extra_data['extra_'.$field['variable']] = $field_value;
900
                            break;
901
                        case self::FIELD_TYPE_RADIO:
902
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $field_value;
903
                            break;
904
                        case self::FIELD_TYPE_TRIPLE_SELECT:
905
                            [$level1, $level2, $level3] = explode(';', $field_value);
906
907
                            $extra_data["extra_$variable"]["extra_$variable"] = $level1;
908
                            $extra_data["extra_$variable"]["extra_{$variable}_second"] = $level2;
909
                            $extra_data["extra_$variable"]["extra_{$variable}_third"] = $level3;
910
                            break;
911
                        default:
912
                            $extra_data['extra_'.$field['variable']] = $field_value;
913
                            break;
914
                    }
915
                } else {
916
                    // Set default values
917
                    if (isset($field['field_default_value']) &&
918
                        !empty($field['field_default_value'])
919
                    ) {
920
                        $extra_data['extra_'.$field['variable']] = $field['field_default_value'];
921
                    }
922
                }
923
            }
924
        }
925
926
        return $extra_data;
927
    }
928
929
    /**
930
     * Get an array of all the values from the extra_field and extra_field_options tables
931
     * based on the current object's type.
932
     *
933
     * @param array $conditions
934
     * @param null  $order_field_options_by
935
     *
936
     * @return array
937
     */
938
    public function get_all($conditions = [], $order_field_options_by = null)
939
    {
940
        $conditions = Database::parse_conditions(['where' => $conditions]);
941
942
        if (empty($conditions)) {
943
            $conditions .= ' WHERE extra_field_type = '.$this->extraFieldType;
944
        } else {
945
            $conditions .= ' AND extra_field_type = '.$this->extraFieldType;
946
        }
947
948
        $sql = "SELECT * FROM $this->table
949
                $conditions
950
                ORDER BY field_order ASC
951
        ";
952
953
        $result = Database::query($sql);
954
        $extraFields = Database::store_result($result, 'ASSOC');
955
956
        $option = new ExtraFieldOption($this->type);
957
        if (!empty($extraFields)) {
958
            foreach ($extraFields as &$extraField) {
959
                $extraField['display_text'] = $this->translateDisplayName(
960
                    $extraField['variable'],
961
                    $extraField['display_text']
962
                );
963
                $extraField['options'] = $option->get_field_options_by_field(
964
                    $extraField['id'],
965
                    false,
966
                    $order_field_options_by
967
                );
968
            }
969
        }
970
971
        return $extraFields;
972
    }
973
974
    /**
975
     * Add an element that matches the given extra field to the given $form object.
976
     *
977
     * @param FormValidator $form                The form these fields are to be attached to
978
     * @param array         $extraData
979
     * @param bool          $adminPermissions    Whether the display is considered without edition limits (true) or not
980
     *                                           (false)
981
     * @param array         $extra
982
     * @param int           $itemId              The item (course, user, session, etc) this extra_field is attached to
983
     * @param array         $exclude             Extra fields to be skipped, by textual ID
984
     * @param bool          $useTagAsSelect      Whether to show tag fields as select drop-down or not
985
     * @param array         $showOnlyTheseFields Limit the extra fields shown to just the list given here
986
     * @param array         $orderFields         An array containing the names of the fields shown, in the right order
987
     *
988
     * @throws Exception
989
     *
990
     * @return array If relevant, returns a one-element array with JS code to be added to the page HTML headers
991
     */
992
    public function set_extra_fields_in_form(
993
        $form,
994
        $extraData,
995
        $adminPermissions = false,
996
        $extra = [],
997
        $itemId = null,
998
        $exclude = [],
999
        $useTagAsSelect = false,
1000
        $showOnlyTheseFields = [],
1001
        $orderFields = [],
1002
        $orderDependingDefaults = false,
1003
        $separateExtraMultipleSelect = [],
1004
        $customLabelsExtraMultipleSelect = [],
1005
        $addEmptyOptionSelects = false,
1006
        $introductionTextList = [],
1007
        $hideGeoLocalizationDetails = false,
1008
        $help = false
1009
    ) {
1010
        $jquery_ready_content = null;
1011
        if (!empty($extra)) {
1012
            $newOrder = [];
1013
            if (!empty($orderFields)) {
1014
                foreach ($orderFields as $order) {
1015
                    foreach ($extra as $field_details) {
1016
                        if ($order == $field_details['variable']) {
1017
                            $newOrder[] = $field_details;
1018
                        }
1019
                    }
1020
                }
1021
                $extra = $newOrder;
1022
            }
1023
1024
            foreach ($extra as $field_details) {
1025
                if (!empty($showOnlyTheseFields)) {
1026
                    if (!in_array($field_details['variable'], $showOnlyTheseFields)) {
1027
                        continue;
1028
                    }
1029
                }
1030
1031
                // Getting default value id if is set
1032
                $defaultValueId = null;
1033
                if (isset($field_details['options']) && !empty($field_details['options'])) {
1034
                    $valueToFind = null;
1035
                    if (isset($field_details['field_default_value'])) {
1036
                        $valueToFind = $field_details['field_default_value'];
1037
                    }
1038
                    // If a value is found we override the default value
1039
                    if (isset($extraData['extra_'.$field_details['variable']])) {
1040
                        $valueToFind = $extraData['extra_'.$field_details['variable']];
1041
                    }
1042
1043
                    foreach ($field_details['options'] as $option) {
1044
                        if ($option['option_value'] == $valueToFind) {
1045
                            $defaultValueId = $option['id'];
1046
                        }
1047
                    }
1048
                }
1049
1050
                if (!$adminPermissions) {
1051
                    if (0 == $field_details['visible_to_self']) {
1052
                        continue;
1053
                    }
1054
1055
                    if (in_array($field_details['variable'], $exclude)) {
1056
                        continue;
1057
                    }
1058
                }
1059
1060
                if (!empty($introductionTextList) &&
1061
                    in_array($field_details['variable'], array_keys($introductionTextList))
1062
                ) {
1063
                    $form->addHtml($introductionTextList[$field_details['variable']]);
1064
                }
1065
1066
                $freezeElement = false;
1067
                if (!$adminPermissions) {
1068
                    $freezeElement = 0 == $field_details['visible_to_self'] || 0 == $field_details['changeable'];
1069
                }
1070
1071
                $translatedDisplayText = get_lang($field_details['display_text'], true);
1072
                $translatedDisplayHelpText = '';
1073
                if ($help) {
1074
                    $translatedDisplayHelpText .= get_lang($field_details['display_text'].'Help');
1075
                }
1076
                if (!empty($translatedDisplayText)) {
1077
                    if (!empty($translatedDisplayHelpText)) {
1078
                        // In this case, exceptionally, display_text is an array
1079
                        // which is then treated by display_form()
1080
                        $field_details['display_text'] = [$translatedDisplayText, $translatedDisplayHelpText];
1081
                    } else {
1082
                        // We have an helper text, use it
1083
                        $field_details['display_text'] = $translatedDisplayText;
1084
                    }
1085
                }
1086
1087
                switch ($field_details['field_type']) {
1088
                    case self::FIELD_TYPE_TEXT:
1089
                        $form->addElement(
1090
                            'text',
1091
                            'extra_'.$field_details['variable'],
1092
                            $field_details['display_text'],
1093
                            [
1094
                                'id' => 'extra_'.$field_details['variable'],
1095
                            ]
1096
                        );
1097
                        $form->applyFilter(
1098
                            'extra_'.$field_details['variable'],
1099
                            'stripslashes'
1100
                        );
1101
                        $form->applyFilter(
1102
                            'extra_'.$field_details['variable'],
1103
                            'trim'
1104
                        );
1105
                        $form->applyFilter(
1106
                            'extra_'.$field_details['variable'],
1107
                            'html_filter'
1108
                        );
1109
                        if (isset($field_details['default_value'])) {
1110
                            $defaults['extra_'.$field_details['variable']] = $field_details['default_value'];
1111
                        }
1112
                        if (!isset($form->_defaultValues['extra_'.$field_details['variable']])) {
1113
                            $form->setDefaults($defaults);
1114
                        }
1115
                        if ($freezeElement) {
1116
                            $form->freeze('extra_'.$field_details['variable']);
1117
                        }
1118
                        break;
1119
                    case self::FIELD_TYPE_TEXTAREA:
1120
                        $form->addHtmlEditor(
1121
                            'extra_'.$field_details['variable'],
1122
                            $field_details['display_text'],
1123
                            false,
1124
                            false,
1125
                            [
1126
                                'ToolbarSet' => 'Profile',
1127
                                'Width' => '100%',
1128
                                'Height' => '130',
1129
                                'id' => 'extra_'.$field_details['variable'],
1130
                            ]
1131
                        );
1132
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1133
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1134
                        if ($freezeElement) {
1135
                            $form->freeze('extra_'.$field_details['variable']);
1136
                        }
1137
                        break;
1138
                    case self::FIELD_TYPE_RADIO:
1139
                        $group = [];
1140
                        if (isset($field_details['options']) &&
1141
                            !empty($field_details['options'])
1142
                        ) {
1143
                            foreach ($field_details['options'] as $option_details) {
1144
                                $options[$option_details['option_value']] = $option_details['display_text'];
1145
                                $group[] = $form->createElement(
1146
                                    'radio',
1147
                                    'extra_'.$field_details['variable'],
1148
                                    $option_details['option_value'],
1149
                                    $option_details['display_text'].'<br />',
1150
                                    $option_details['option_value']
1151
                                );
1152
                            }
1153
                        }
1154
                        $form->addGroup(
1155
                            $group,
1156
                            'extra_'.$field_details['variable'],
1157
                            $field_details['display_text']
1158
                        );
1159
                        if ($freezeElement) {
1160
                            $form->freeze('extra_'.$field_details['variable']);
1161
                        }
1162
                        break;
1163
                    case self::FIELD_TYPE_CHECKBOX:
1164
                        $group = [];
1165
                        if (isset($field_details['options']) &&
1166
                            !empty($field_details['options'])
1167
                        ) {
1168
                            foreach ($field_details['options'] as $option_details) {
1169
                                $options[$option_details['option_value']] = $option_details['display_text'];
1170
                                $group[] = $form->createElement(
1171
                                    'checkbox',
1172
                                    'extra_'.$field_details['variable'],
1173
                                    $option_details['option_value'],
1174
                                    $option_details['display_text'].'<br />',
1175
                                    $option_details['option_value']
1176
                                );
1177
                            }
1178
                        } else {
1179
                            $fieldVariable = "extra_{$field_details['variable']}";
1180
                            $checkboxAttributes = [];
1181
                            if (is_array($extraData) &&
1182
                                array_key_exists($fieldVariable, $extraData)
1183
                            ) {
1184
                                if (!empty($extraData[$fieldVariable])) {
1185
                                    $checkboxAttributes['checked'] = 1;
1186
                                }
1187
                            }
1188
1189
                            if (empty($checkboxAttributes) &&
1190
                                isset($field_details['default_value']) && empty($extraData)) {
1191
                                if (1 == $field_details['default_value']) {
1192
                                    $checkboxAttributes['checked'] = 1;
1193
                                }
1194
                            }
1195
1196
                            // We assume that is a switch on/off with 1 and 0 as values
1197
                            $group[] = $form->createElement(
1198
                                'checkbox',
1199
                                'extra_'.$field_details['variable'],
1200
                                null,
1201
                                get_lang('Yes'),
1202
                                $checkboxAttributes
1203
                            );
1204
                        }
1205
1206
                        $form->addGroup(
1207
                            $group,
1208
                            'extra_'.$field_details['variable'],
1209
                            $field_details['display_text']
1210
                        );
1211
                        if ($freezeElement) {
1212
                            $form->freeze('extra_'.$field_details['variable']);
1213
                        }
1214
                        break;
1215
                    case self::FIELD_TYPE_SELECT:
1216
                        $this->addSelectElement($form, $field_details, $defaultValueId, $freezeElement);
1217
                        break;
1218
                    case self::FIELD_TYPE_SELECT_MULTIPLE:
1219
                        $options = [];
1220
                        if (empty($defaultValueId)) {
1221
                            $options[''] = get_lang('SelectAnOption');
1222
                        }
1223
1224
                        if (isset($field_details['options']) && !empty($field_details['options'])) {
1225
                            foreach ($field_details['options'] as $optionDetails) {
1226
                                $options[$optionDetails['option_value']] = $optionDetails['display_text'];
1227
                            }
1228
                        }
1229
1230
                        $form->addElement(
1231
                            'select',
1232
                            'extra_'.$field_details['variable'],
1233
                            $field_details['display_text'],
1234
                            $options,
1235
                            [
1236
                                'multiple' => 'multiple',
1237
                                'id' => 'extra_'.$field_details['variable'],
1238
                            ]
1239
                        );
1240
                        if ($freezeElement) {
1241
                            $form->freeze('extra_'.$field_details['variable']);
1242
                        }
1243
                        break;
1244
                    case self::FIELD_TYPE_DATE:
1245
                        $form->addDatePicker('extra_'.$field_details['variable'], $field_details['display_text']);
1246
                        if ($freezeElement) {
1247
                            $form->freeze('extra_'.$field_details['variable']);
1248
                        }
1249
                        break;
1250
                    case self::FIELD_TYPE_DATETIME:
1251
                        $form->addDateTimePicker(
1252
                            'extra_'.$field_details['variable'],
1253
                            $field_details['display_text']
1254
                        );
1255
1256
                        $defaults = [];
1257
                        if (EntityExtraField::LP_ITEM_FIELD_TYPE !== (int) $field_details['extra_field_type']) {
1258
                            $defaults['extra_'.$field_details['variable']] = api_get_local_time();
1259
                        }
1260
                        if (!isset($form->_defaultValues['extra_'.$field_details['variable']])) {
1261
                            $form->setDefaults($defaults);
1262
                        }
1263
                        if ($freezeElement) {
1264
                            $form->freeze('extra_'.$field_details['variable']);
1265
                        }
1266
                        break;
1267
                    case self::FIELD_TYPE_DOUBLE_SELECT:
1268
                        $jquery_ready_content .= self::addDoubleSelectElement(
1269
                            $form,
1270
                            $field_details,
1271
                            $extraData,
1272
                            $freezeElement
1273
                        );
1274
                        break;
1275
                    case self::FIELD_TYPE_DIVIDER:
1276
                        $form->addHtml(
1277
                            '
1278
                            <div class="form-group ">
1279
                                <div class="col-sm-12">
1280
                                    <div class="panel-separator">
1281
                                       <h4 id="'.$field_details['variable'].'" class="form-separator">'
1282
                            .$field_details['display_text'].'
1283
                                       </h4>
1284
                                    </div>
1285
                                </div>
1286
                            </div>
1287
                        '
1288
                        );
1289
                        break;
1290
                    case self::FIELD_TYPE_TAG:
1291
                        $variable = $field_details['variable'];
1292
                        $field_id = $field_details['id'];
1293
                        $separateValue = 0;
1294
                        if (isset($separateExtraMultipleSelect[$field_details['variable']])) {
1295
                            $separateValue = $separateExtraMultipleSelect[$field_details['variable']];
1296
                        }
1297
1298
                        $selectedOptions = [];
1299
                        if ($separateValue > 0) {
1300
                            $em = Database::getManager();
1301
                            $fieldTags = $em
1302
                                ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1303
                                ->findBy(
1304
                                    [
1305
                                        'fieldId' => $field_id,
1306
                                        'itemId' => $itemId,
1307
                                    ]
1308
                                );
1309
                            // ofaj
1310
1311
                            for ($i = 0; $i < $separateValue; $i++) {
1312
                                $tagsSelect = $form->addElement(
1313
                                    'select',
1314
                                    'extra_'.$field_details['variable'].'['.$i.']',
1315
                                    $customLabelsExtraMultipleSelect[$field_details['variable']][$i],
1316
                                    null,
1317
                                    ['id' => 'extra_'.$field_details['variable'].'_'.$i]
1318
                                );
1319
1320
                                if ($addEmptyOptionSelects) {
1321
                                    $tagsSelect->addOption(
1322
                                        '',
1323
                                        ''
1324
                                    );
1325
                                }
1326
1327
                                foreach ($fieldTags as $fieldTag) {
1328
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1329
1330
                                    if (empty($tag)) {
1331
                                        continue;
1332
                                    }
1333
1334
                                    $tagsSelect->addOption(
1335
                                        $tag->getTag(),
1336
                                        $tag->getTag()
1337
                                    );
1338
                                }
1339
                            }
1340
                        } else {
1341
                            $tagsSelect = $form->addSelect(
1342
                                "extra_{$field_details['variable']}",
1343
                                $field_details['display_text'],
1344
                                [],
1345
                                ['style' => 'width: 100%;']
1346
                            );
1347
1348
                            if (false === $useTagAsSelect) {
1349
                                $tagsSelect->setAttribute('class', null);
1350
                            }
1351
1352
                            $tagsSelect->setAttribute(
1353
                                'id',
1354
                                "extra_{$field_details['variable']}"
1355
                            );
1356
                            $tagsSelect->setMultiple(true);
1357
1358
                            $selectedOptions = [];
1359
                            if ('user' === $this->type) {
1360
                                // The magic should be here
1361
                                $user_tags = UserManager::get_user_tags(
1362
                                    $itemId,
1363
                                    $field_details['id']
1364
                                );
1365
1366
                                if (is_array($user_tags) && count($user_tags) > 0) {
1367
                                    foreach ($user_tags as $tag) {
1368
                                        if (empty($tag['tag'])) {
1369
                                            continue;
1370
                                        }
1371
                                        $tagsSelect->addOption(
1372
                                            $tag['tag'],
1373
                                            $tag['tag'],
1374
                                            [
1375
                                                'selected' => 'selected',
1376
                                                'class' => 'selected',
1377
                                            ]
1378
                                        );
1379
                                        $selectedOptions[] = $tag['tag'];
1380
                                    }
1381
                                } else {
1382
                                    if (!empty($extraData) && isset($extraData['extra_'.$field_details['variable']])) {
1383
                                        $data = $extraData['extra_'.$field_details['variable']];
1384
                                        if (!empty($data)) {
1385
                                            foreach ($data as $option) {
1386
                                                $tagsSelect->addOption(
1387
                                                    $option,
1388
                                                    $option,
1389
                                                    [
1390
                                                        'selected' => 'selected',
1391
                                                        'class' => 'selected',
1392
                                                    ]
1393
                                                );
1394
                                                $selectedOptions[] = $option;
1395
                                            }
1396
                                        }
1397
                                    }
1398
                                }
1399
                                $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
1400
                            } else {
1401
                                $em = Database::getManager();
1402
                                $fieldTags = $em->getRepository(
1403
                                    'ChamiloCoreBundle:ExtraFieldRelTag'
1404
                                )
1405
                                    ->findBy(
1406
                                        [
1407
                                            'fieldId' => $field_id,
1408
                                            'itemId' => $itemId,
1409
                                        ]
1410
                                    );
1411
1412
                                /** @var ExtraFieldRelTag $fieldTag */
1413
                                foreach ($fieldTags as $fieldTag) {
1414
                                    /** @var Tag $tag */
1415
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1416
1417
                                    if (empty($tag)) {
1418
                                        continue;
1419
                                    }
1420
                                    $tagsSelect->addOption(
1421
                                        $tag->getTag(),
1422
                                        $tag->getTag()
1423
                                    );
1424
                                    $selectedOptions[] = $tag->getTag();
1425
                                }
1426
1427
                                if (!empty($extraData) && isset($extraData['extra_'.$field_details['variable']])) {
1428
                                    $data = $extraData['extra_'.$field_details['variable']];
1429
                                    if (!empty($data)) {
1430
                                        foreach ($data as $option) {
1431
                                            $tagsSelect->addOption(
1432
                                                $option,
1433
                                                $option
1434
                                            );
1435
                                        }
1436
                                    }
1437
                                }
1438
1439
                                if ($useTagAsSelect) {
1440
                                    $fieldTags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1441
                                        ->findBy(
1442
                                            [
1443
                                                'fieldId' => $field_id,
1444
                                            ]
1445
                                        );
1446
                                    $tagsAdded = [];
1447
                                    foreach ($fieldTags as $fieldTag) {
1448
                                        $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1449
1450
                                        if (empty($tag)) {
1451
                                            continue;
1452
                                        }
1453
1454
                                        $tagText = $tag->getTag();
1455
1456
                                        if (in_array($tagText, $tagsAdded)) {
1457
                                            continue;
1458
                                        }
1459
1460
                                        $tagsSelect->addOption(
1461
                                            $tag->getTag(),
1462
                                            $tag->getTag(),
1463
                                            []
1464
                                        );
1465
1466
                                        $tagsAdded[] = $tagText;
1467
                                    }
1468
                                }
1469
                                $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
1470
                            }
1471
1472
                            $allowAsTags = 'true';
1473
1474
                            if ('portfolio' === $this->type) {
1475
                                $allowAsTags = 'false';
1476
                            }
1477
1478
                            $form->setDefaults(
1479
                                [
1480
                                    'extra_'.$field_details['variable'] => $selectedOptions,
1481
                                ]
1482
                            );
1483
1484
                            if (false == $useTagAsSelect) {
1485
                                $jquery_ready_content .= "
1486
                                $('#extra_$variable').select2({
1487
                                    ajax: {
1488
                                        url: '$url?a=search_tags&field_id=$field_id&type={$this->type}',
1489
                                        processResults: function (data) {
1490
                                            return {
1491
                                                results: data.items
1492
                                            }
1493
                                        }
1494
                                    },
1495
                                    cache: false,
1496
                                    tags: $allowAsTags,
1497
                                    tokenSeparators: [','],
1498
                                    placeholder: '".get_lang('StartToType')."'
1499
                                });
1500
                            ";
1501
                            }
1502
                        }
1503
1504
                        break;
1505
                    case self::FIELD_TYPE_TIMEZONE:
1506
                        $form->addElement(
1507
                            'select',
1508
                            'extra_'.$field_details['variable'],
1509
                            $field_details['display_text'],
1510
                            api_get_timezones(),
1511
                            ''
1512
                        );
1513
                        if ($freezeElement) {
1514
                            $form->freeze('extra_'.$field_details['variable']);
1515
                        }
1516
                        break;
1517
                    case self::FIELD_TYPE_SOCIAL_PROFILE:
1518
                        // get the social network's favicon
1519
                        $extra_data_variable = isset($extraData['extra_'.$field_details['variable']])
1520
                            ? $extraData['extra_'.$field_details['variable']]
1521
                            : null;
1522
                        $field_default_value = isset($field_details['field_default_value'])
1523
                            ? $field_details['field_default_value']
1524
                            : null;
1525
                        $icon_path = UserManager::get_favicon_from_url(
1526
                            $extra_data_variable,
1527
                            $field_default_value
1528
                        );
1529
                        // special hack for hi5
1530
                        $leftpad = '1.7';
1531
                        $top = '0.4';
1532
                        $domain = parse_url($icon_path, PHP_URL_HOST);
1533
                        if ('www.hi5.com' === $domain || 'hi5.com' === $domain) {
1534
                            $leftpad = '3';
1535
                            $top = '0';
1536
                        }
1537
                        // print the input field
1538
                        $form->addElement(
1539
                            'text',
1540
                            'extra_'.$field_details['variable'],
1541
                            $field_details['display_text'],
1542
                            [
1543
                                'size' => 60,
1544
                                'size' => implode(
1545
                                    '; ',
1546
                                    [
1547
                                        "background-image: url('$icon_path')",
1548
                                        'background-repeat: no-repeat',
1549
                                        "background-position: 0.4em {$top}em",
1550
                                        "padding-left: {$leftpad}em",
1551
                                    ]
1552
                                ),
1553
                            ]
1554
                        );
1555
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1556
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1557
                        $form->applyFilter('extra_'.$field_details['variable'], 'html_filter');
1558
                        if ($freezeElement) {
1559
                            $form->freeze('extra_'.$field_details['variable']);
1560
                        }
1561
                        break;
1562
                    case self::FIELD_TYPE_MOBILE_PHONE_NUMBER:
1563
                        $form->addElement(
1564
                            'text',
1565
                            'extra_'.$field_details['variable'],
1566
                            $field_details['display_text'].' ('.get_lang('CountryDialCode').')',
1567
                            ['size' => 40, 'placeholder' => '(xx)xxxxxxxxx']
1568
                        );
1569
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1570
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1571
                        $form->applyFilter('extra_'.$field_details['variable'], 'mobile_phone_number_filter');
1572
                        $form->applyFilter('extra_'.$field_details['variable'], 'html_filter');
1573
                        $form->addRule(
1574
                            'extra_'.$field_details['variable'],
1575
                            get_lang('MobilePhoneNumberWrong'),
1576
                            'mobile_phone_number'
1577
                        );
1578
                        if ($freezeElement) {
1579
                            $form->freeze('extra_'.$field_details['variable']);
1580
                        }
1581
                        break;
1582
                    case self::FIELD_TYPE_INTEGER:
1583
                        $form->addElement(
1584
                            'number',
1585
                            'extra_'.$field_details['variable'],
1586
                            $field_details['display_text'],
1587
                            ['class' => 'span1', 'step' => 1]
1588
                        );
1589
1590
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1591
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1592
                        $form->applyFilter('extra_'.$field_details['variable'], 'intval');
1593
1594
                        if ($freezeElement) {
1595
                            $form->freeze('extra_'.$field_details['variable']);
1596
                        }
1597
                        break;
1598
                    case self::FIELD_TYPE_FILE_IMAGE:
1599
                        $fieldVariable = "extra_{$field_details['variable']}";
1600
                        $fieldTexts = [
1601
                            $field_details['display_text'],
1602
                        ];
1603
1604
                        if (is_array($extraData) && array_key_exists($fieldVariable, $extraData)) {
1605
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1606
                                $fieldTexts[] = Display::img(
1607
                                    api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1608
                                    $field_details['display_text'],
1609
                                    ['width' => '300']
1610
                                );
1611
                            }
1612
                        }
1613
1614
                        if ('Image' === $fieldTexts[0]) {
1615
                            $fieldTexts[0] = get_lang($fieldTexts[0]);
1616
                        }
1617
1618
                        $form->addFile(
1619
                            $fieldVariable,
1620
                            $fieldTexts,
1621
                            ['accept' => 'image/*', 'id' => 'extra_image', 'crop_image' => 'true']
1622
                        );
1623
1624
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1625
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1626
1627
                        $allowedPictureTypes = ['jpg', 'jpeg', 'png', 'gif'];
1628
                        $form->addRule(
1629
                            'extra_'.$field_details['variable'],
1630
                            get_lang('OnlyImagesAllowed').' ('.implode(',', $allowedPictureTypes).')',
1631
                            'filetype',
1632
                            $allowedPictureTypes
1633
                        );
1634
1635
                        if ($freezeElement) {
1636
                            $form->freeze('extra_'.$field_details['variable']);
1637
                        }
1638
                        break;
1639
                    case self::FIELD_TYPE_FLOAT:
1640
                        $form->addElement(
1641
                            'number',
1642
                            'extra_'.$field_details['variable'],
1643
                            $field_details['display_text'],
1644
                            ['class' => 'span1', 'step' => '0.01']
1645
                        );
1646
1647
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1648
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1649
                        $form->applyFilter('extra_'.$field_details['variable'], 'floatval');
1650
1651
                        if ($freezeElement) {
1652
                            $form->freeze('extra_'.$field_details['variable']);
1653
                        }
1654
                        break;
1655
                    case self::FIELD_TYPE_FILE:
1656
                        $fieldVariable = "extra_{$field_details['variable']}";
1657
                        $fieldTexts = [
1658
                            $field_details['display_text'],
1659
                        ];
1660
1661
                        if (is_array($extraData) &&
1662
                            array_key_exists($fieldVariable, $extraData)
1663
                        ) {
1664
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1665
                                $linkToDelete = '';
1666
                                $divItemId = $field_details['variable'];
1667
                                if (api_is_platform_admin()) {
1668
                                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?type='.$this->type;
1669
                                    $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId;
1670
1671
                                    $deleteId = $field_details['variable'].'_delete';
1672
                                    $form->addHtml(
1673
                                        "
1674
                                        <script>
1675
                                            $(function() {
1676
                                                $('#".$deleteId."').on('click', function() {
1677
                                                    $.ajax({
1678
                                                        type: 'GET',
1679
                                                        url: '".$url."',
1680
                                                        success: function(result) {
1681
                                                            if (result == 1) {
1682
                                                                $('#".$divItemId."').html('".get_lang('Deleted')."');
1683
                                                            }
1684
                                                        }
1685
                                                    });
1686
                                                });
1687
                                            });
1688
                                        </script>
1689
                                    "
1690
                                    );
1691
1692
                                    $linkToDelete = '&nbsp;'.Display::url(
1693
                                            Display::return_icon('delete.png', get_lang('Delete')),
1694
                                            'javascript:void(0)',
1695
                                            ['id' => $deleteId]
1696
                                        );
1697
                                }
1698
                                $fieldTexts[] = '<div id="'.$divItemId.'">'.Display::url(
1699
                                        basename($extraData[$fieldVariable]),
1700
                                        api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1701
                                        [
1702
                                            'title' => $field_details['display_text'],
1703
                                            'target' => '_blank',
1704
                                        ]
1705
                                    ).$linkToDelete.'</div>';
1706
                            }
1707
                        }
1708
1709
                        $form->addElement(
1710
                            'file',
1711
                            $fieldVariable,
1712
                            $fieldTexts,
1713
                            []
1714
                        );
1715
1716
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1717
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1718
1719
                        if ($freezeElement) {
1720
                            $form->freeze('extra_'.$field_details['variable']);
1721
                        }
1722
                        break;
1723
                    case self::FIELD_TYPE_VIDEO_URL:
1724
                        $form->addUrl(
1725
                            "extra_{$field_details['variable']}",
1726
                            $field_details['display_text'],
1727
                            false,
1728
                            ['placeholder' => 'https://']
1729
                        );
1730
                        if ($freezeElement) {
1731
                            $form->freeze('extra_'.$field_details['variable']);
1732
                        }
1733
                        break;
1734
                    case self::FIELD_TYPE_LETTERS_ONLY:
1735
                        $form->addTextLettersOnly(
1736
                            "extra_{$field_details['variable']}",
1737
                            $field_details['display_text']
1738
                        );
1739
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1740
1741
                        if ($freezeElement) {
1742
                            $form->freeze('extra_'.$field_details['variable']);
1743
                        }
1744
                        break;
1745
                    case self::FIELD_TYPE_ALPHANUMERIC:
1746
                        $form->addTextAlphanumeric(
1747
                            "extra_{$field_details['variable']}",
1748
                            $field_details['display_text']
1749
                        );
1750
                        $form->applyFilter(
1751
                            'extra_'.$field_details['variable'],
1752
                            'stripslashes'
1753
                        );
1754
                        if ($freezeElement) {
1755
                            $form->freeze('extra_'.$field_details['variable']);
1756
                        }
1757
                        break;
1758
                    case self::FIELD_TYPE_LETTERS_SPACE:
1759
                        $form->addTextLettersAndSpaces(
1760
                            "extra_{$field_details['variable']}",
1761
                            $field_details['display_text']
1762
                        );
1763
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1764
1765
                        if ($freezeElement) {
1766
                            $form->freeze('extra_'.$field_details['variable']);
1767
                        }
1768
                        break;
1769
                    case self::FIELD_TYPE_ALPHANUMERIC_SPACE:
1770
                        $form->addTextAlphanumericAndSpaces(
1771
                            "extra_{$field_details['variable']}",
1772
                            $field_details['display_text']
1773
                        );
1774
                        $form->applyFilter(
1775
                            'extra_'.$field_details['variable'],
1776
                            'stripslashes'
1777
                        );
1778
                        if ($freezeElement) {
1779
                            $form->freeze('extra_'.$field_details['variable']);
1780
                        }
1781
                        break;
1782
                    case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
1783
                    case self::FIELD_TYPE_GEOLOCALIZATION:
1784
                        $dataValue = isset($extraData['extra_'.$field_details['variable']])
1785
                            ? $extraData['extra_'.$field_details['variable']]
1786
                            : '';
1787
1788
                        $form->addGeoLocationMapField(
1789
                            'extra_'.$field_details['variable'],
1790
                            $field_details['display_text'],
1791
                            $dataValue,
1792
                            $hideGeoLocalizationDetails
1793
                        );
1794
1795
                        if ($freezeElement) {
1796
                            $form->freeze('extra_'.$field_details['variable']);
1797
                        }
1798
                        break;
1799
                    case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
1800
                        $jquery_ready_content .= $this->addSelectWithTextFieldElement(
1801
                            $form,
1802
                            $field_details,
1803
                            $freezeElement
1804
                        );
1805
                        break;
1806
                    case self::FIELD_TYPE_TRIPLE_SELECT:
1807
                        $jquery_ready_content .= $this->addTripleSelectElement(
1808
                            $form,
1809
                            $field_details,
1810
                            is_array($extraData) ? $extraData : [],
1811
                            $freezeElement
1812
                        );
1813
                        break;
1814
                }
1815
            }
1816
        }
1817
1818
        $return = [];
1819
        $return['jquery_ready_content'] = $jquery_ready_content;
1820
1821
        return $return;
1822
    }
1823
1824
    /**
1825
     * @param array $options
1826
     *
1827
     * @return array
1828
     */
1829
    public static function extra_field_double_select_convert_array_to_ordered_array($options)
1830
    {
1831
        $optionsParsed = [];
1832
        if (!empty($options)) {
1833
            foreach ($options as $option) {
1834
                if (0 == $option['option_value']) {
1835
                    $optionsParsed[$option['id']][] = $option;
1836
                } else {
1837
                    $optionsParsed[$option['option_value']][] = $option;
1838
                }
1839
            }
1840
        }
1841
1842
        return $optionsParsed;
1843
    }
1844
1845
    /**
1846
     * @return array
1847
     */
1848
    public static function tripleSelectConvertArrayToOrderedArray(array $options)
1849
    {
1850
        $level1 = self::getOptionsFromTripleSelect($options, 0);
1851
        $level2 = [];
1852
        $level3 = [];
1853
1854
        foreach ($level1 as $item1) {
1855
            $level2 += self::getOptionsFromTripleSelect($options, $item1['id']);
1856
        }
1857
1858
        foreach ($level2 as $item2) {
1859
            $level3 += self::getOptionsFromTripleSelect($options, $item2['id']);
1860
        }
1861
1862
        return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3];
1863
    }
1864
1865
    /**
1866
     * @param string $type
1867
     *
1868
     * @return array
1869
     */
1870
    public function get_all_extra_field_by_type($type)
1871
    {
1872
        // all the information of the field
1873
        $sql = "SELECT * FROM {$this->table}
1874
                WHERE
1875
                    field_type = '".Database::escape_string($type)."' AND
1876
                    extra_field_type = $this->extraFieldType
1877
                ";
1878
        $result = Database::query($sql);
1879
1880
        $return = [];
1881
        while ($row = Database::fetch_array($result)) {
1882
            $return[] = $row['id'];
1883
        }
1884
1885
        return $return;
1886
    }
1887
1888
    /**
1889
     * @param int $id
1890
     */
1891
    public function get_field_type_by_id($id)
1892
    {
1893
        $types = $this->get_field_types();
1894
        if (isset($types[$id])) {
1895
            return $types[$id];
1896
        }
1897
1898
        return null;
1899
    }
1900
1901
    /**
1902
     * @return array
1903
     */
1904
    public function get_field_types()
1905
    {
1906
        return $this->get_extra_fields_by_handler($this->type);
1907
    }
1908
1909
    /**
1910
     * @param string $handler
1911
     *
1912
     * @return array
1913
     */
1914
    public static function get_extra_fields_by_handler($handler)
1915
    {
1916
        $types = [];
1917
        $types[self::FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
1918
        $types[self::FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
1919
        $types[self::FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
1920
        $types[self::FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
1921
        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
1922
        $types[self::FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
1923
        $types[self::FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
1924
        $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
1925
        $types[self::FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
1926
        $types[self::FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
1927
        $types[self::FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
1928
        $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
1929
        $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
1930
        $types[self::FIELD_TYPE_CHECKBOX] = get_lang('FieldTypeCheckbox');
1931
        $types[self::FIELD_TYPE_INTEGER] = get_lang('FieldTypeInteger');
1932
        $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('FieldTypeFileImage');
1933
        $types[self::FIELD_TYPE_FLOAT] = get_lang('FieldTypeFloat');
1934
        $types[self::FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
1935
        $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('FieldTypeVideoUrl');
1936
        $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('FieldTypeOnlyLetters');
1937
        $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('FieldTypeAlphanumeric');
1938
        $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('FieldTypeLettersSpaces');
1939
        $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('FieldTypeAlphanumericSpaces');
1940
        $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization');
1941
        $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('GeolocalizationCoordinates');
1942
        $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('FieldTypeSelectWithTextField');
1943
        $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('FieldTypeTripleSelect');
1944
1945
        switch ($handler) {
1946
            case 'course':
1947
            case 'session':
1948
            case 'user':
1949
            case 'skill':
1950
                break;
1951
        }
1952
1953
        return $types;
1954
    }
1955
1956
    /**
1957
     * @param array $params
1958
     * @param bool  $show_query
1959
     *
1960
     * @return int|bool
1961
     */
1962
    public function save($params, $show_query = false)
1963
    {
1964
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
1965
        $params = $this->clean_parameters($params);
1966
        $params['extra_field_type'] = $this->extraFieldType;
1967
1968
        if ($fieldInfo) {
1969
            return $fieldInfo['id'];
1970
        } else {
1971
            $id = parent::save($params, $show_query);
1972
            if ($id) {
1973
                $fieldOption = new ExtraFieldOption($this->type);
1974
                $params['field_id'] = $id;
1975
                $fieldOption->save($params);
1976
            }
1977
1978
            return $id;
1979
        }
1980
    }
1981
1982
    /**
1983
     * Gets the set of values of an extra_field searching for the variable name.
1984
     *
1985
     * Example:
1986
     * <code>
1987
     * <?php
1988
     * $extraField = new ExtraField('lp_item');
1989
     * $extraFieldArray =  $extraField->get_handler_field_info_by_field_variable('authorlpitem');
1990
     * echo "<pre>".var_export($extraFieldArray,true)."</pre>";
1991
     * ?>
1992
     * </code>
1993
     *
1994
     * @param string $variable
1995
     *
1996
     * @return array|bool
1997
     */
1998
    public function get_handler_field_info_by_field_variable($variable)
1999
    {
2000
        $variable = Database::escape_string($variable);
2001
        $sql = "SELECT * FROM {$this->table}
2002
                WHERE
2003
                    variable = '$variable' AND
2004
                    extra_field_type = $this->extraFieldType";
2005
        $result = Database::query($sql);
2006
        if (Database::num_rows($result)) {
2007
            $row = Database::fetch_array($result, 'ASSOC');
2008
            if ($row) {
2009
                $row['display_text'] = self::translateDisplayName($row['variable'], $row['display_text']);
2010
2011
                // All the options of the field
2012
                $sql = "SELECT * FROM $this->table_field_options
2013
                    WHERE field_id='".intval($row['id'])."'
2014
                    ORDER BY option_order ASC";
2015
                $result = Database::query($sql);
2016
                while ($option = Database::fetch_array($result)) {
2017
                    $row['options'][$option['id']] = $option;
2018
                }
2019
2020
                return $row;
2021
            }
2022
        }
2023
2024
        return false;
2025
    }
2026
2027
    public function getHandlerEntityByFieldVariable(string $variable)
2028
    {
2029
        return Database::getManager()
2030
            ->getRepository('ChamiloCoreBundle:ExtraField')
2031
            ->findOneBy(['variable' => $variable, 'extraFieldType' => $this->extraFieldType]);
2032
    }
2033
2034
    /**
2035
     * @param array $params
2036
     *
2037
     * @return array
2038
     */
2039
    public function clean_parameters($params)
2040
    {
2041
        if (!isset($params['variable']) || empty($params['variable'])) {
2042
            $params['variable'] = $params['display_text'];
2043
        }
2044
2045
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
2046
2047
        if (!isset($params['field_order'])) {
2048
            $max_order = self::get_max_field_order();
2049
            $params['field_order'] = $max_order;
2050
        } else {
2051
            $params['field_order'] = (int) $params['field_order'];
2052
        }
2053
2054
        return $params;
2055
    }
2056
2057
    /**
2058
     * @return int
2059
     */
2060
    public function get_max_field_order()
2061
    {
2062
        $sql = "SELECT MAX(field_order)
2063
                FROM {$this->table}
2064
                WHERE
2065
                    extra_field_type = '.$this->extraFieldType.'";
2066
        $res = Database::query($sql);
2067
2068
        $order = 0;
2069
        if (Database::num_rows($res) > 0) {
2070
            $row = Database::fetch_row($res);
2071
            $order = $row[0] + 1;
2072
        }
2073
2074
        return $order;
2075
    }
2076
2077
    /**
2078
     * {@inheritdoc}
2079
     */
2080
    public function update($params, $showQuery = false)
2081
    {
2082
        $params = $this->clean_parameters($params);
2083
        if (isset($params['id'])) {
2084
            $fieldOption = new ExtraFieldOption($this->type);
2085
            $params['field_id'] = $params['id'];
2086
            if (empty($params['field_type'])) {
2087
                $params['field_type'] = $this->type;
2088
            }
2089
            $fieldOption->save($params, $showQuery);
2090
        }
2091
2092
        return parent::update($params, $showQuery);
2093
    }
2094
2095
    /**
2096
     * @param $id
2097
     *
2098
     * @return bool
2099
     */
2100
    public function delete($id)
2101
    {
2102
        $em = Database::getManager();
2103
        $items = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy(['field' => $id]);
2104
        if ($items) {
2105
            foreach ($items as $item) {
2106
                $em->remove($item);
2107
            }
2108
            $em->flush();
2109
        }
2110
        $field_option = new ExtraFieldOption($this->type);
2111
        $field_option->delete_all_options_by_field_id($id);
2112
2113
        $session_field_values = new ExtraFieldValue($this->type);
2114
        $session_field_values->delete_all_values_by_field_id($id);
2115
2116
        return parent::delete($id);
2117
    }
2118
2119
    /**
2120
     * @param $breadcrumb
2121
     * @param $action
2122
     */
2123
    public function setupBreadcrumb(&$breadcrumb, $action)
2124
    {
2125
        if ('add' === $action) {
2126
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2127
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Add')];
2128
        } elseif ('edit' === $action) {
2129
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2130
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')];
2131
        } else {
2132
            $breadcrumb[] = ['url' => '#', 'name' => $this->pageName];
2133
        }
2134
    }
2135
2136
    /**
2137
     * Displays the title + grid.
2138
     */
2139
    public function display()
2140
    {
2141
        // action links
2142
        echo '<div class="actions">';
2143
        echo '<a href="../admin/index.php">';
2144
        echo Display::return_icon(
2145
            'back.png',
2146
            get_lang('BackTo').' '.get_lang('PlatformAdmin'),
2147
            '',
2148
            ICON_SIZE_MEDIUM
2149
        );
2150
        echo '</a>';
2151
        echo '<a href="'.api_get_self().'?action=add&type='.$this->type.'">';
2152
        echo Display::return_icon(
2153
            'add_user_fields.png',
2154
            get_lang('Add'),
2155
            '',
2156
            ICON_SIZE_MEDIUM
2157
        );
2158
        echo '</a>';
2159
        echo '</div>';
2160
        echo Display::grid_html($this->type.'_fields');
2161
    }
2162
2163
    /**
2164
     * @return array
2165
     */
2166
    public function getJqgridColumnNames()
2167
    {
2168
        return [
2169
            get_lang('Name'),
2170
            get_lang('FieldLabel'),
2171
            get_lang('Type'),
2172
            get_lang('FieldChangeability'),
2173
            get_lang('VisibleToSelf'),
2174
            get_lang('VisibleToOthers'),
2175
            get_lang('Filter'),
2176
            get_lang('FieldOrder'),
2177
            get_lang('Actions'),
2178
        ];
2179
    }
2180
2181
    /**
2182
     * @return array
2183
     */
2184
    public function getJqgridColumnModel()
2185
    {
2186
        return [
2187
            [
2188
                'name' => 'display_text',
2189
                'index' => 'display_text',
2190
                'width' => '140',
2191
                'align' => 'left',
2192
            ],
2193
            [
2194
                'name' => 'variable',
2195
                'index' => 'variable',
2196
                'width' => '90',
2197
                'align' => 'left',
2198
                'sortable' => 'true',
2199
            ],
2200
            [
2201
                'name' => 'field_type',
2202
                'index' => 'field_type',
2203
                'width' => '70',
2204
                'align' => 'left',
2205
                'sortable' => 'true',
2206
            ],
2207
            [
2208
                'name' => 'changeable',
2209
                'index' => 'changeable',
2210
                'width' => '35',
2211
                'align' => 'left',
2212
                'sortable' => 'true',
2213
            ],
2214
            [
2215
                'name' => 'visible_to_self',
2216
                'index' => 'visible_to_self',
2217
                'width' => '45',
2218
                'align' => 'left',
2219
                'sortable' => 'true',
2220
            ],
2221
            [
2222
                'name' => 'visible_to_others',
2223
                'index' => 'visible_to_others',
2224
                'width' => '35',
2225
                'align' => 'left',
2226
                'sortable' => 'true',
2227
            ],
2228
            [
2229
                'name' => 'filter',
2230
                'index' => 'filter',
2231
                'width' => '30',
2232
                'align' => 'left',
2233
                'sortable' => 'true',
2234
            ],
2235
            [
2236
                'name' => 'field_order',
2237
                'index' => 'field_order',
2238
                'width' => '25',
2239
                'align' => 'left',
2240
                'sortable' => 'true',
2241
            ],
2242
            [
2243
                'name' => 'actions',
2244
                'index' => 'actions',
2245
                'width' => '40',
2246
                'align' => 'left',
2247
                'formatter' => 'action_formatter',
2248
                'sortable' => 'false',
2249
            ],
2250
        ];
2251
    }
2252
2253
    /**
2254
     * @param string $url
2255
     * @param string $action
2256
     *
2257
     * @return FormValidator
2258
     */
2259
    public function return_form($url, $action)
2260
    {
2261
        $form = new FormValidator($this->type.'_field', 'post', $url);
2262
2263
        $form->addHidden('type', $this->type);
2264
        $id = isset($_GET['id']) ? (int) $_GET['id'] : null;
2265
        $form->addHidden('id', $id);
2266
2267
        // Setting the form elements
2268
        $header = get_lang('Add');
2269
        $defaults = [];
2270
2271
        if ('edit' === $action) {
2272
            $header = get_lang('Modify');
2273
            // Setting the defaults
2274
            $defaults = $this->get($id, false);
2275
        }
2276
2277
        $form->addHeader($header);
2278
2279
        if ('edit' === $action) {
2280
            $translateUrl = api_get_path(WEB_CODE_PATH).'extrafield/translate.php?'
2281
                .http_build_query(['extra_field' => $id]);
2282
            $translateButton = Display::toolbarButton(get_lang('TranslateThisTerm'), $translateUrl, 'language', 'link');
2283
2284
            $form->addText(
2285
                'display_text',
2286
                [get_lang('Title'), $translateButton]
2287
            );
2288
        } else {
2289
            $form->addText('display_text', get_lang('Title'));
2290
        }
2291
2292
        // Field type
2293
        $types = self::get_field_types();
2294
2295
        $form->addElement(
2296
            'select',
2297
            'field_type',
2298
            get_lang('FieldType'),
2299
            $types,
2300
            ['id' => 'field_type']
2301
        );
2302
        $form->addLabel(get_lang('Example'), '<div id="example">-</div>');
2303
        $form->addElement(
2304
            'text',
2305
            'variable',
2306
            [
2307
                get_lang('SysId'),
2308
                get_lang('ExtraFieldIdComment'),
2309
            ]
2310
        );
2311
        $form->addElement(
2312
            'text',
2313
            'field_options',
2314
            get_lang('FieldPossibleValues'),
2315
            ['id' => 'field_options', 'class' => 'span6']
2316
        );
2317
2318
        $fieldWithOptions = [
2319
            self::FIELD_TYPE_RADIO,
2320
            self::FIELD_TYPE_SELECT_MULTIPLE,
2321
            self::FIELD_TYPE_SELECT,
2322
            self::FIELD_TYPE_TAG,
2323
            self::FIELD_TYPE_DOUBLE_SELECT,
2324
            self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD,
2325
            self::FIELD_TYPE_TRIPLE_SELECT,
2326
        ];
2327
2328
        if ('edit' == $action) {
2329
            if (in_array($defaults['field_type'], $fieldWithOptions)) {
2330
                $url = Display::url(
2331
                    get_lang('EditExtraFieldOptions'),
2332
                    'extra_field_options.php?type='.$this->type.'&field_id='.$id
2333
                );
2334
                $form->addLabel(null, $url);
2335
2336
                if (self::FIELD_TYPE_SELECT == $defaults['field_type']) {
2337
                    $urlWorkFlow = Display::url(
2338
                        get_lang('EditExtraFieldWorkFlow'),
2339
                        'extra_field_workflow.php?type='.$this->type.'&field_id='.$id
2340
                    );
2341
                    $form->addLabel(null, $urlWorkFlow);
2342
                }
2343
2344
                $form->freeze('field_options');
2345
            }
2346
        }
2347
        $form->addText(
2348
            'default_value',
2349
            get_lang('FieldDefaultValue'),
2350
            false,
2351
            ['id' => 'default_value']
2352
        );
2353
2354
        $group = [];
2355
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('Yes'), 1);
2356
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('No'), 0);
2357
        $form->addGroup($group, '', get_lang('VisibleToSelf'), null, false);
2358
2359
        $group = [];
2360
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('Yes'), 1);
2361
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('No'), 0);
2362
        $form->addGroup($group, '', get_lang('VisibleToOthers'), null, false);
2363
2364
        $group = [];
2365
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('Yes'), 1);
2366
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('No'), 0);
2367
        $form->addGroup($group, '', get_lang('FieldChangeability'), null, false);
2368
2369
        $group = [];
2370
        $group[] = $form->createElement('radio', 'filter', null, get_lang('Yes'), 1);
2371
        $group[] = $form->createElement('radio', 'filter', null, get_lang('No'), 0);
2372
        $form->addGroup($group, '', get_lang('FieldFilter'), null, false);
2373
2374
        /* Enable this when field_loggeable is introduced as a table field (2.0)
2375
        $group   = array();
2376
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('Yes'), 1);
2377
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('No'), 0);
2378
        $form->addGroup($group, '', get_lang('FieldLoggeable'), '', false);
2379
        */
2380
2381
        $form->addNumeric('field_order', get_lang('FieldOrder'), ['step' => 1, 'min' => 0]);
2382
2383
        if ('edit' == $action) {
2384
            $option = new ExtraFieldOption($this->type);
2385
            $defaults['field_options'] = $option->get_field_options_by_field_to_string($id);
2386
            $form->addButtonUpdate(get_lang('Modify'));
2387
        } else {
2388
            $defaults['visible_to_self'] = 0;
2389
            $defaults['visible_to_others'] = 0;
2390
            $defaults['changeable'] = 0;
2391
            $defaults['filter'] = 0;
2392
            $form->addButtonCreate(get_lang('Add'));
2393
        }
2394
2395
        /*if (!empty($defaults['created_at'])) {
2396
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
2397
        }
2398
        if (!empty($defaults['updated_at'])) {
2399
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
2400
        }*/
2401
        $form->setDefaults($defaults);
2402
2403
        // Setting the rules
2404
        $form->addRule('display_text', get_lang('ThisFieldIsRequired'), 'required');
2405
        $form->addRule('field_type', get_lang('ThisFieldIsRequired'), 'required');
2406
2407
        return $form;
2408
    }
2409
2410
    /**
2411
     * Gets an element.
2412
     *
2413
     * @param int  $id
2414
     * @param bool $translateDisplayText Optional
2415
     *
2416
     * @return array
2417
     */
2418
    public function get($id, $translateDisplayText = true)
2419
    {
2420
        $info = parent::get($id);
2421
2422
        if ($translateDisplayText) {
2423
            $info['display_text'] = self::translateDisplayName($info['variable'], $info['display_text']);
2424
        }
2425
2426
        return $info;
2427
    }
2428
2429
    /**
2430
     * @param $token
2431
     *
2432
     * @return string
2433
     */
2434
    public function getJqgridActionLinks($token)
2435
    {
2436
        //With this function we can add actions to the jgrid (edit, delete, etc)
2437
        $editIcon = Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL);
2438
        $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2439
        $confirmMessage = addslashes(
2440
            api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES)
2441
        );
2442
2443
        $editButton = <<<JAVASCRIPT
2444
            <a href="?action=edit&type={$this->type}&id=' + options.rowId + '" class="btn btn-link btn-xs">\
2445
                $editIcon\
2446
            </a>
2447
JAVASCRIPT;
2448
        $deleteButton = <<<JAVASCRIPT
2449
            <a \
2450
                onclick="if (!confirm(\'$confirmMessage\')) {return false;}" \
2451
                href="?sec_token=$token&type={$this->type}&id=' + options.rowId + '&action=delete" \
2452
                class="btn btn-link btn-xs">\
2453
                $deleteIcon\
2454
            </a>
2455
JAVASCRIPT;
2456
2457
        return "function action_formatter(cellvalue, options, rowObject) {
2458
            return '$editButton $deleteButton';
2459
        }";
2460
    }
2461
2462
    /**
2463
     * @param array $columns
2464
     * @param array $column_model
2465
     * @param array $extraFields
2466
     *
2467
     * @return array
2468
     */
2469
    public function getRules(&$columns, &$column_model, $extraFields = [], $checkExtraFieldExistence = false)
2470
    {
2471
        $fields = $this->get_all(
2472
            [
2473
                'visible_to_self = ? AND filter = ?' => [1, 1],
2474
            ],
2475
            'display_text'
2476
        );
2477
        $extraFieldOption = new ExtraFieldOption($this->type);
2478
2479
        $rules = [];
2480
        if (!empty($fields)) {
2481
            foreach ($fields as $field) {
2482
                $search_options = [];
2483
                $type = 'text';
2484
                if (in_array($field['field_type'], [self::FIELD_TYPE_SELECT, self::FIELD_TYPE_DOUBLE_SELECT])) {
2485
                    $type = 'select';
2486
                    $search_options['sopt'] = ['eq', 'ne']; //equal not equal
2487
                } else {
2488
                    $search_options['sopt'] = ['cn', 'nc']; //contains not contains
2489
                }
2490
2491
                $search_options['searchhidden'] = 'true';
2492
                $search_options['defaultValue'] = isset($search_options['field_default_value'])
2493
                    ? $search_options['field_default_value']
2494
                    : null;
2495
2496
                if (self::FIELD_TYPE_DOUBLE_SELECT == $field['field_type']) {
2497
                    // Add 2 selects
2498
                    $options = $extraFieldOption->get_field_options_by_field($field['id']);
2499
                    $options = self::extra_field_double_select_convert_array_to_ordered_array($options);
2500
2501
                    $first_options = [];
2502
                    if (!empty($options)) {
2503
                        foreach ($options as $option) {
2504
                            foreach ($option as $sub_option) {
2505
                                if (0 == $sub_option['option_value']) {
2506
                                    $first_options[] = $sub_option['field_id'].'#'.$sub_option['id'].':'
2507
                                        .$sub_option['display_text'];
2508
                                }
2509
                            }
2510
                        }
2511
                    }
2512
2513
                    $search_options['value'] = implode(';', $first_options);
2514
                    $search_options['dataInit'] = 'fill_second_select';
2515
2516
                    // First
2517
                    $column_model[] = [
2518
                        'name' => 'extra_'.$field['variable'],
2519
                        'index' => 'extra_'.$field['variable'],
2520
                        'width' => '100',
2521
                        'hidden' => 'true',
2522
                        'search' => 'true',
2523
                        'stype' => 'select',
2524
                        'searchoptions' => $search_options,
2525
                    ];
2526
                    $columns[] = $field['display_text'].' (1)';
2527
                    $rules[] = [
2528
                        'field' => 'extra_'.$field['variable'],
2529
                        'op' => 'cn',
2530
                    ];
2531
2532
                    // Second
2533
                    $search_options['value'] = $field['id'].':';
2534
                    $search_options['dataInit'] = 'register_second_select';
2535
2536
                    $column_model[] = [
2537
                        'name' => 'extra_'.$field['variable'].'_second',
2538
                        'index' => 'extra_'.$field['variable'].'_second',
2539
                        'width' => '100',
2540
                        'hidden' => 'true',
2541
                        'search' => 'true',
2542
                        'stype' => 'select',
2543
                        'searchoptions' => $search_options,
2544
                    ];
2545
                    $columns[] = $field['display_text'].' (2)';
2546
                    $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn'];
2547
                    continue;
2548
                } else {
2549
                    $search_options['value'] = $extraFieldOption->getFieldOptionsToString(
2550
                        $field['id'],
2551
                        false,
2552
                        'display_text'
2553
                    );
2554
                }
2555
                $column_model[] = [
2556
                    'name' => 'extra_'.$field['variable'],
2557
                    'index' => 'extra_'.$field['variable'],
2558
                    'width' => '100',
2559
                    'hidden' => 'true',
2560
                    'search' => 'true',
2561
                    'stype' => $type,
2562
                    'searchoptions' => $search_options,
2563
                ];
2564
                $columns[] = $field['display_text'];
2565
                $rules[] = [
2566
                    'field' => 'extra_'.$field['variable'],
2567
                    'op' => 'cn',
2568
                    'data' => '',
2569
                ];
2570
            }
2571
        }
2572
2573
        return $rules;
2574
    }
2575
2576
    public function processExtraFieldSearch($values, $form, $alias, $condition = 'OR')
2577
    {
2578
        // Parse params.
2579
        $fields = [];
2580
        foreach ($values as $key => $value) {
2581
            if (substr($key, 0, 6) !== 'extra_' &&
2582
                substr($key, 0, 7) !== '_extra_'
2583
            ) {
2584
                continue;
2585
            }
2586
            if (!empty($value)) {
2587
                $fields[$key] = $value;
2588
            }
2589
        }
2590
2591
        $extraFieldsAll = $this->get_all(['visible_to_self = ? AND filter = ?' => [1, 1]], 'option_order');
2592
        $extraFieldsType = array_column($extraFieldsAll, 'field_type', 'variable');
2593
        $extraFields = array_column($extraFieldsAll, 'variable');
2594
        $filter = new stdClass();
2595
        $defaults = [];
2596
        foreach ($fields as $variable => $col) {
2597
            $variableNoExtra = str_replace('extra_', '', $variable);
2598
            if (isset($values[$variable]) && !empty($values[$variable]) &&
2599
                in_array($variableNoExtra, $extraFields)
2600
            ) {
2601
                $rule = new stdClass();
2602
                $rule->field = $variable;
2603
                $rule->op = 'in';
2604
                $data = $col;
2605
                if (is_array($data) && array_key_exists($variable, $data)) {
2606
                    $data = $col;
2607
                }
2608
                $rule->data = $data;
2609
                $filter->rules[] = $rule;
2610
                $filter->groupOp = 'AND';
2611
2612
                if ($extraFieldsType[$variableNoExtra] == ExtraField::FIELD_TYPE_TAG) {
2613
                    $tagElement = $form->getElement($variable);
2614
                    $tags = [];
2615
                    foreach ($values[$variable] as $tag) {
2616
                        $tag = Security::remove_XSS($tag);
2617
                        $tags[] = $tag;
2618
                        $tagElement->addOption(
2619
                            $tag,
2620
                            $tag
2621
                        );
2622
                    }
2623
                    $defaults[$variable] = $tags;
2624
                } else {
2625
                    if (is_array($data)) {
2626
                        $defaults[$variable] = array_map(['Security', 'remove_XSS'], $data);
2627
                    } else {
2628
                        $defaults[$variable] = Security::remove_XSS($data);
2629
                    }
2630
                }
2631
            }
2632
        }
2633
2634
        $result = $this->getExtraFieldRules($filter, 'extra_', $condition);
2635
        $conditionArray = $result['condition_array'];
2636
2637
        $whereCondition = '';
2638
        $extraCondition = '';
2639
        if (!empty($conditionArray)) {
2640
            $extraCondition = ' ( ';
2641
            $extraCondition .= implode(' AND ', $conditionArray);
2642
            $extraCondition .= ' ) ';
2643
        }
2644
        $whereCondition .= $extraCondition;
2645
        $conditions = $this->parseConditions(
2646
            [
2647
                'where' => $whereCondition,
2648
                'extra' => $result['extra_fields'],
2649
            ],
2650
            $alias
2651
        );
2652
2653
        return ['condition' => $conditions, 'fields' => $fields, 'defaults' => $defaults];
2654
    }
2655
2656
    /**
2657
     * @param        $filters
2658
     * @param string $stringToSearch
2659
     *
2660
     * @return array
2661
     */
2662
    public function getExtraFieldRules($filters, $stringToSearch = 'extra_', $condition = 'OR')
2663
    {
2664
        $extraFields = [];
2665
        $conditionArray = [];
2666
2667
        // Getting double select if exists
2668
        $double_select = [];
2669
        if (is_object($filters) &&
2670
            property_exists($filters, 'rules') &&
2671
            is_array($filters->rules) &&
2672
            !empty($filters->rules)
2673
        ) {
2674
            foreach ($filters->rules as $rule) {
2675
                if (empty($rule)) {
2676
                    continue;
2677
                }
2678
                if (false === strpos($rule->field, '_second')) {
2679
                } else {
2680
                    $my_field = str_replace('_second', '', $rule->field);
2681
                    $double_select[$my_field] = $rule->data;
2682
                }
2683
            }
2684
2685
            foreach ($filters->rules as $rule) {
2686
                if (empty($rule)) {
2687
                    continue;
2688
                }
2689
                if (false === strpos($rule->field, $stringToSearch)) {
2690
                    // normal fields
2691
                    $field = $rule->field;
2692
                    if (isset($rule->data) && is_string($rule->data) && -1 != $rule->data) {
2693
                        $conditionArray[] = $this->get_where_clause($field, $rule->op, $rule->data);
2694
                    }
2695
                } else {
2696
                    // Extra fields
2697
                    $ruleField = Database::escapeField($rule->field);
2698
                    if (false === strpos($rule->field, '_second')) {
2699
                        // No _second
2700
                        $original_field = str_replace($stringToSearch, '', $rule->field);
2701
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2702
2703
                        switch ($field_option['field_type']) {
2704
                            case self::FIELD_TYPE_DOUBLE_SELECT:
2705
                                if (isset($double_select[$rule->field])) {
2706
                                    $data = explode('#', $rule->data);
2707
                                    $rule->data = $data[1].'::'.$double_select[$rule->field];
2708
                                } else {
2709
                                    // only was sent 1 select
2710
                                    if (is_string($rule->data)) {
2711
                                        $data = explode('#', $rule->data);
2712
                                        $rule->data = $data[1];
2713
                                    }
2714
                                }
2715
2716
                                if (!isset($rule->data)) {
2717
                                    $conditionArray[] = ' ('
2718
                                        .$this->get_where_clause($rule->field, $rule->op, $rule->data)
2719
                                        .') ';
2720
                                    $extraFields[] = ['field' => $ruleField, 'id' => $field_option['id']];
2721
                                }
2722
                                break;
2723
                            case self::FIELD_TYPE_TAG:
2724
                                if (isset($rule->data)) {
2725
                                    if (is_int($rule->data) && -1 == $rule->data) {
2726
                                        break;
2727
                                    }
2728
                                    // Where will be injected in the parseConditions()
2729
                                    //$where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR');
2730
                                    //$conditionArray[] = " ( $where ) ";
2731
                                    $extraFields[] = [
2732
                                        'field' => $ruleField,
2733
                                        'id' => $field_option['id'],
2734
                                        'data' => $rule->data,
2735
                                    ];
2736
                                }
2737
                                break;
2738
                            default:
2739
                                if (isset($rule->data)) {
2740
                                    if (is_int($rule->data) && -1 == $rule->data) {
2741
                                        break;
2742
                                    }
2743
                                    $where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR');
2744
                                    $conditionArray[] = " ( $where ) ";
2745
                                    $extraFields[] = [
2746
                                        'field' => $ruleField,
2747
                                        'id' => $field_option['id'],
2748
                                        'data' => $rule->data,
2749
                                    ];
2750
                                }
2751
                                break;
2752
                        }
2753
                    } else {
2754
                        $my_field = str_replace('_second', '', $rule->field);
2755
                        $original_field = str_replace($stringToSearch, '', $my_field);
2756
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2757
                        $extraFields[] = [
2758
                            'field' => $ruleField,
2759
                            'id' => $field_option['id'],
2760
                        ];
2761
                    }
2762
                }
2763
            }
2764
        }
2765
2766
        return ['extra_fields' => $extraFields, 'condition_array' => $conditionArray];
2767
    }
2768
2769
    /**
2770
     * @param $col
2771
     * @param $oper
2772
     * @param $val
2773
     * @param $conditionBetweenOptions
2774
     *
2775
     * @return string
2776
     */
2777
    public function get_where_clause($col, $oper, $val, $conditionBetweenOptions = 'OR')
2778
    {
2779
        $col = Database::escapeField($col);
2780
2781
        if (empty($col)) {
2782
            return '';
2783
        }
2784
2785
        $conditionBetweenOptions = in_array($conditionBetweenOptions, ['OR', 'AND']) ? $conditionBetweenOptions : 'OR';
2786
        if ('bw' === $oper || 'bn' === $oper) {
2787
            $val .= '%';
2788
        }
2789
        if ('ew' === $oper || 'en' === $oper) {
2790
            $val = '%'.$val;
2791
        }
2792
        if ('cn' === $oper || 'nc' === $oper || 'in' === $oper || 'ni' === $oper) {
2793
            if (is_array($val)) {
2794
                $result = '"%'.implode(';', $val).'%"';
2795
                foreach ($val as $item) {
2796
                    $item = trim($item);
2797
                    $result .= ' '.$conditionBetweenOptions.' '.$col.' LIKE "%'.$item.'%"';
2798
                }
2799
                $val = $result;
2800
2801
                return " $col {$this->ops[$oper]} $val ";
2802
            } else {
2803
                if (is_string($val)) {
2804
                    $val = '%'.$val.'%';
2805
                } else {
2806
                    $val = '';
2807
                }
2808
            }
2809
        }
2810
        $val = \Database::escape_string($val);
2811
2812
        return " $col {$this->ops[$oper]} '$val' ";
2813
    }
2814
2815
    /**
2816
     * @param array  $options
2817
     * @param string $alias
2818
     *
2819
     * @return array
2820
     */
2821
    public function parseConditions($options, $alias = 's')
2822
    {
2823
        $inject_extra_fields = null;
2824
        $extraFieldOption = new ExtraFieldOption($this->type);
2825
        $double_fields = [];
2826
2827
        if (isset($options['extra'])) {
2828
            $extra_fields = $options['extra'];
2829
            if (!empty($extra_fields)) {
2830
                $counter = 1;
2831
                $extra_field_obj = new ExtraField($this->type);
2832
                foreach ($extra_fields as &$extra) {
2833
                    if (!isset($extra['id'])) {
2834
                        continue;
2835
                    }
2836
                    $extra_field_info = $extra_field_obj->get($extra['id']);
2837
                    if (empty($extra_field_info)) {
2838
                        continue;
2839
                    }
2840
                    $extra['extra_field_info'] = $extra_field_info;
2841
2842
                    switch ($extra_field_info['field_type']) {
2843
                        case self::FIELD_TYPE_SELECT:
2844
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2845
                            $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, ";
2846
                            break;
2847
                        case self::FIELD_TYPE_TAG:
2848
                            // If using OR
2849
                            // If using AND
2850
                            $newCounter = 1;
2851
                            $fields = [];
2852
                            $tagAlias = $extra['field'];
2853
                            foreach ($extra['data'] as $data) {
2854
                                $fields[] = "tag$counter$newCounter.tag";
2855
                                $newCounter++;
2856
                            }
2857
2858
                            if (!empty($fields)) {
2859
                                $tags = implode(' , " ", ', $fields);
2860
                                $inject_extra_fields .= " CONCAT($tags) as $tagAlias, ";
2861
                            }
2862
                            break;
2863
                        default:
2864
                            $inject_extra_fields .= " fv$counter.value as {$extra['field']}, ";
2865
                            break;
2866
                    }
2867
2868
                    if (isset($extra_fields_info[$extra['id']])) {
2869
                        $info = $extra_fields_info[$extra['id']];
2870
                    } else {
2871
                        $info = $this->get($extra['id']);
2872
                        $extra_fields_info[$extra['id']] = $info;
2873
                    }
2874
                    if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) {
2875
                        $double_fields[$info['id']] = $info;
2876
                    }
2877
                    $counter++;
2878
                }
2879
            }
2880
        }
2881
2882
        $options_by_double = [];
2883
        foreach ($double_fields as $double) {
2884
            $my_options = $extraFieldOption->get_field_options_by_field($double['id'], true);
2885
            $options_by_double['extra_'.$double['variable']] = $my_options;
2886
        }
2887
2888
        $field_value_to_join = [];
2889
        //filter can be all/any = and/or
2890
        $inject_joins = null;
2891
        $inject_where = null;
2892
        $where = null;
2893
2894
        //if (!empty($options['where'])) {
2895
        if (!empty($options['extra']) && !empty($extra_fields)) {
2896
            // Removing double 1=1
2897
            if (empty($options['where'])) {
2898
                $options['where'] = ' 1 = 1 ';
2899
            }
2900
            $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
2901
            // Always OR
2902
            $counter = 1;
2903
            foreach ($extra_fields as $extra_info) {
2904
                $extra_field_info = $extra_info['extra_field_info'];
2905
                $inject_joins .= " INNER JOIN $this->table_field_values fv$counter
2906
                                       ON ($alias.".$this->primaryKey." = fv$counter.".$this->handler_id.') ';
2907
                // Add options
2908
                switch ($extra_field_info['field_type']) {
2909
                        case self::FIELD_TYPE_SELECT:
2910
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2911
                            $options['where'] = str_replace(
2912
                                $extra_info['field'],
2913
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value',
2914
                                $options['where']
2915
                            );
2916
                            $inject_joins .= "
2917
                                 INNER JOIN $this->table_field_options fvo$counter
2918
                                 ON (
2919
                                    fv$counter.field_id = fvo$counter.field_id AND
2920
                                    fv$counter.value = fvo$counter.option_value
2921
                                 )
2922
                                ";
2923
                            break;
2924
                        case self::FIELD_TYPE_TAG:
2925
                            $newCounter = 1;
2926
                            if (isset($extra_info['data']) && !empty($extra_info['data'])) {
2927
                                $whereTag = [];
2928
                                foreach ($extra_info['data'] as $data) {
2929
                                    $data = Database::escape_string($data);
2930
                                    $key = $counter.$newCounter;
2931
                                    $whereTag[] = ' tag'.$key.'.tag LIKE "%'.$data.'%" ';
2932
                                    $inject_joins .= "
2933
                                    INNER JOIN $this->table_field_rel_tag tag_rel$key
2934
                                    ON (
2935
                                        tag_rel$key.field_id = ".$extra_info['id']." AND
2936
                                        tag_rel$key.item_id = $alias.".$this->primaryKey."
2937
                                    )
2938
                                    INNER JOIN $this->table_field_tag tag$key
2939
                                    ON (tag$key.id = tag_rel$key.tag_id)
2940
                                ";
2941
                                    $newCounter++;
2942
                                }
2943
                                if (!empty($whereTag)) {
2944
                                    $options['where'] .= ' AND  ('.implode(' AND ', $whereTag).') ';
2945
                                }
2946
                            }
2947
                            break;
2948
                        default:
2949
                            // text, textarea, etc
2950
                            $options['where'] = str_replace(
2951
                                $extra_info['field'],
2952
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value',
2953
                                $options['where']
2954
                            );
2955
                            break;
2956
                    }
2957
                $field_value_to_join[] = " fv$counter.$this->handler_id ";
2958
                $counter++;
2959
            }
2960
        }
2961
2962
        if (!empty($options['where'])) {
2963
            $where .= ' AND '.$options['where'];
2964
        }
2965
2966
        $order = '';
2967
        if (!empty($options['order'])) {
2968
            $order = " ORDER BY ".$options['order']." ";
2969
        }
2970
        $limit = '';
2971
        if (!empty($options['limit'])) {
2972
            $limit = ' LIMIT '.$options['limit'];
2973
        }
2974
2975
        return [
2976
            'order' => $order,
2977
            'limit' => $limit,
2978
            'where' => $where,
2979
            'inject_where' => $inject_where,
2980
            'inject_joins' => $inject_joins,
2981
            'field_value_to_join' => $field_value_to_join,
2982
            'inject_extra_fields' => $inject_extra_fields,
2983
        ];
2984
    }
2985
2986
    /**
2987
     * Get the extra fields and their formatted values.
2988
     *
2989
     * @param int|string $itemId   The item ID (It could be a session_id, course_id or user_id)
2990
     * @param bool       $filter
2991
     * @param array      $onlyShow (list of extra fields variables to show)
2992
     *
2993
     * @return array The extra fields data
2994
     */
2995
    public function getDataAndFormattedValues($itemId, $filter = false, $onlyShow = [])
2996
    {
2997
        $valuesData = [];
2998
        $fields = $this->get_all();
2999
        $em = Database::getManager();
3000
3001
        $repoTag = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
3002
3003
        foreach ($fields as $field) {
3004
            if ('1' != $field['visible_to_self']) {
3005
                continue;
3006
            }
3007
3008
            if ($filter && $field['filter'] != 1) {
3009
                continue;
3010
            }
3011
3012
            if (!empty($onlyShow) && !in_array($field['variable'], $onlyShow)) {
3013
                continue;
3014
            }
3015
3016
            $valueAsArray = [];
3017
            $fieldValue = new ExtraFieldValue($this->type);
3018
            $valueData = $fieldValue->get_values_by_handler_and_field_id(
3019
                $itemId,
3020
                $field['id'],
3021
                true
3022
            );
3023
            if (ExtraField::FIELD_TYPE_TAG == $field['field_type']) {
3024
                $tags = $repoTag->findBy(['fieldId' => $field['id'], 'itemId' => $itemId]);
3025
                if ($tags) {
3026
                    /** @var ExtraFieldRelTag $tag */
3027
                    $data = [];
3028
                    foreach ($tags as $extraFieldTag) {
3029
                        /** @var Tag $tag */
3030
                        $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
3031
                        $data[] = $tag->getTag();
3032
                    }
3033
                    $valueData = implode(', ', $data);
3034
                    $valueAsArray = $data;
3035
                }
3036
            }
3037
3038
            if (!$valueData) {
3039
                continue;
3040
            }
3041
            $displayedValue = get_lang('None');
3042
3043
            switch ($field['field_type']) {
3044
                case self::FIELD_TYPE_CHECKBOX:
3045
                    if (false !== $valueData && '1' == $valueData['value']) {
3046
                        $displayedValue = get_lang('Yes');
3047
                    } else {
3048
                        $displayedValue = get_lang('No');
3049
                    }
3050
                    break;
3051
                case self::FIELD_TYPE_DATE:
3052
                    if (false !== $valueData && !empty($valueData['value'])) {
3053
                        $displayedValue = api_format_date($valueData['value'], DATE_FORMAT_LONG_NO_DAY);
3054
                    }
3055
                    break;
3056
                case self::FIELD_TYPE_TAG:
3057
                    if (!empty($valueData)) {
3058
                        $displayedValue = $valueData;
3059
                    }
3060
                    break;
3061
                case self::FIELD_TYPE_FILE_IMAGE:
3062
                    if (false === $valueData || empty($valueData['value'])) {
3063
                        break;
3064
                    }
3065
3066
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
3067
                        break;
3068
                    }
3069
3070
                    $image = Display::img(
3071
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
3072
                        $field['display_text'],
3073
                        ['width' => '300']
3074
                    );
3075
3076
                    $displayedValue = Display::url(
3077
                        $image,
3078
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
3079
                        ['target' => '_blank']
3080
                    );
3081
                    break;
3082
                case self::FIELD_TYPE_FILE:
3083
                    if (false === $valueData || empty($valueData['value'])) {
3084
                        break;
3085
                    }
3086
3087
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
3088
                        break;
3089
                    }
3090
3091
                    $displayedValue = Display::url(
3092
                        get_lang('Download'),
3093
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
3094
                        [
3095
                            'title' => $field['display_text'],
3096
                            'target' => '_blank',
3097
                            'class' => 'download_extra_field',
3098
                        ]
3099
                    );
3100
                    break;
3101
                default:
3102
                    $displayedValue = $valueData['value'];
3103
                    break;
3104
            }
3105
3106
            $valuesData[] = [
3107
                'variable' => $field['variable'],
3108
                'text' => $field['display_text'],
3109
                'value' => $displayedValue,
3110
                'value_as_array' => $valueAsArray,
3111
            ];
3112
        }
3113
3114
        return $valuesData;
3115
    }
3116
3117
    /**
3118
     * @param int    $fieldId
3119
     * @param string $tag
3120
     *
3121
     * @return array
3122
     */
3123
    public function getAllUserPerTag($fieldId, $tag)
3124
    {
3125
        $tagRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3126
        $tag = Database::escape_string($tag);
3127
        $fieldId = (int) $fieldId;
3128
3129
        $sql = "SELECT user_id
3130
                FROM {$this->table_field_tag} f INNER JOIN $tagRelUserTable ft
3131
                ON tag_id = f.id
3132
                WHERE tag = '$tag' AND f.field_id = $fieldId;
3133
        ";
3134
3135
        $result = Database::query($sql);
3136
3137
        return Database::store_result($result, 'ASSOC');
3138
    }
3139
3140
    /**
3141
     * @param int $fieldId
3142
     * @param int $tagId
3143
     *
3144
     * @return array
3145
     */
3146
    public function getAllSkillPerTag($fieldId, $tagId)
3147
    {
3148
        $skillTable = Database::get_main_table(TABLE_MAIN_SKILL);
3149
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3150
        $fieldId = (int) $fieldId;
3151
        $tagId = (int) $tagId;
3152
3153
        $sql = "SELECT s.id
3154
                FROM $skillTable s INNER JOIN $tagRelExtraTable t
3155
                ON t.item_id = s.id
3156
                WHERE tag_id = $tagId AND t.field_id = $fieldId;
3157
        ";
3158
3159
        $result = Database::query($sql);
3160
        $result = Database::store_result($result, 'ASSOC');
3161
3162
        $skillList = [];
3163
        foreach ($result as $index => $value) {
3164
            $skillList[$value['id']] = $value['id'];
3165
        }
3166
3167
        return $skillList;
3168
    }
3169
3170
    /**
3171
     * @param string $from
3172
     * @param string $search
3173
     * @param array  $options
3174
     *
3175
     * @return array
3176
     */
3177
    public function searchOptionsFromTags($from, $search, $options)
3178
    {
3179
        $extraFieldInfo = $this->get_handler_field_info_by_field_variable(
3180
            str_replace('extra_', '', $from)
3181
        );
3182
        $extraFieldInfoTag = $this->get_handler_field_info_by_field_variable(
3183
            str_replace('extra_', '', $search)
3184
        );
3185
3186
        if (empty($extraFieldInfo) || empty($extraFieldInfoTag)) {
3187
            return [];
3188
        }
3189
3190
        $id = $extraFieldInfo['id'];
3191
        $tagId = $extraFieldInfoTag['id'];
3192
3193
        $table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3194
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3195
        $tagTable = Database::get_main_table(TABLE_MAIN_TAG);
3196
        $optionsTable = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
3197
3198
        $cleanOptions = [];
3199
        foreach ($options as $option) {
3200
            $cleanOptions[] = Database::escape_string($option);
3201
        }
3202
        $cleanOptions = array_filter($cleanOptions);
3203
3204
        if (empty($cleanOptions)) {
3205
            return [];
3206
        }
3207
3208
        $value = implode("','", $cleanOptions);
3209
3210
        $sql = "SELECT DISTINCT t.*, v.value, o.display_text
3211
                FROM $tagRelExtraTable te
3212
                INNER JOIN $tagTable t
3213
                ON (t.id = te.tag_id AND te.field_id = t.field_id AND te.field_id = $tagId)
3214
                INNER JOIN $table v
3215
                ON (te.item_id = v.item_id AND v.field_id = $id)
3216
                INNER JOIN $optionsTable o
3217
                ON (o.option_value = v.value)
3218
                WHERE v.value IN ('".$value."')
3219
                ORDER BY o.option_order, t.tag
3220
               ";
3221
3222
        $result = Database::query($sql);
3223
        $result = Database::store_result($result);
3224
3225
        return $result;
3226
    }
3227
3228
    /**
3229
     * For one given field ID, get all the item_id + value.
3230
     *
3231
     * @return array
3232
     */
3233
    public function getAllValuesByFieldId(int $fieldId)
3234
    {
3235
        $type = $this->get_field_type_by_id($fieldId);
3236
        $sql = "SELECT item_id, value FROM ".$this->table_field_values." WHERE field_id = $fieldId";
3237
        $res = Database::query($sql);
3238
        $values = [];
3239
        if (Database::num_rows($res) > 0) {
3240
            while ($row = Database::fetch_array($res)) {
3241
                if (is_null($row['value'])) {
3242
                    // If the entry exists but is NULL, consider it an empty string (to reproduce the behaviour of UserManager::get_extra_user_data()
3243
                    $values[$row['item_id']] = '';
3244
                } else {
3245
                    if ($type == self::FIELD_TYPE_SELECT_MULTIPLE) {
3246
                        $values[$row['item_id']] = explode(';', $row['value']);
3247
                    } elseif (empty($row['value'])) {
3248
                        // Avoid "0" values when no value should be set
3249
                        $values[$row['item_id']] = null;
3250
                    } else {
3251
                        $values[$row['item_id']] = $row['value'];
3252
                    }
3253
                }
3254
            }
3255
        }
3256
3257
        return $values;
3258
    }
3259
3260
    /**
3261
     * Gets the default value for one specific field.
3262
     *
3263
     * @param int $fieldId Field ID
3264
     *
3265
     * @return mixed Default value for the field (could be null, or usually a string)
3266
     */
3267
    public function getDefaultValueByFieldId(int $fieldId)
3268
    {
3269
        $sql = "SELECT default_value FROM $this->table WHERE id = $fieldId";
3270
        $res = Database::query($sql);
3271
        if (Database::num_rows($res) > 0) {
3272
            $row = Database::fetch_array($res);
3273
3274
            return $row['default_value'];
3275
        }
3276
3277
        return null;
3278
    }
3279
3280
    /**
3281
     * @param \FormValidator $form
3282
     * @param int            $defaultValueId
3283
     * @param bool           $freezeElement
3284
     */
3285
    private function addSelectElement(FormValidator $form, array $fieldDetails, $defaultValueId, $freezeElement = false)
3286
    {
3287
        $get_lang_variables = false;
3288
        if (in_array(
3289
            $fieldDetails['variable'],
3290
            ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
3291
        )) {
3292
            $get_lang_variables = true;
3293
        }
3294
3295
        // Get extra field workflow
3296
        $addOptions = [];
3297
        $optionsExists = false;
3298
        $options = [];
3299
3300
        $optionList = [];
3301
        if (!empty($fieldDetails['options'])) {
3302
            foreach ($fieldDetails['options'] as $option_details) {
3303
                $optionList[$option_details['id']] = $option_details;
3304
                if ($get_lang_variables) {
3305
                    $options[$option_details['option_value']] = $option_details['display_text'];
3306
                } else {
3307
                    if ($optionsExists) {
3308
                        // Adding always the default value
3309
                        if ($option_details['id'] == $defaultValueId) {
3310
                            $options[$option_details['option_value']] = $option_details['display_text'];
3311
                        } else {
3312
                            if (isset($addOptions) && !empty($addOptions)) {
3313
                                // Parsing filters
3314
                                if (in_array($option_details['id'], $addOptions)) {
3315
                                    $options[$option_details['option_value']] = $option_details['display_text'];
3316
                                }
3317
                            }
3318
                        }
3319
                    } else {
3320
                        // Normal behaviour
3321
                        $options[$option_details['option_value']] = $option_details['display_text'];
3322
                    }
3323
                }
3324
            }
3325
3326
            // Setting priority message
3327
            if (isset($optionList[$defaultValueId])
3328
                && isset($optionList[$defaultValueId]['priority'])
3329
            ) {
3330
                if (!empty($optionList[$defaultValueId]['priority'])) {
3331
                    $priorityId = $optionList[$defaultValueId]['priority'];
3332
                    $option = new ExtraFieldOption($this->type);
3333
                    $messageType = $option->getPriorityMessageType($priorityId);
3334
                    $form->addElement(
3335
                        'label',
3336
                        null,
3337
                        Display::return_message(
3338
                            $optionList[$defaultValueId]['priority_message'],
3339
                            $messageType
3340
                        )
3341
                    );
3342
                }
3343
            }
3344
        }
3345
3346
        /** @var \HTML_QuickForm_select $slct */
3347
        $slct = $form->addElement(
3348
            'select',
3349
            'extra_'.$fieldDetails['variable'],
3350
            $fieldDetails['display_text'],
3351
            [],
3352
            ['id' => 'extra_'.$fieldDetails['variable']]
3353
        );
3354
3355
        if (empty($defaultValueId)) {
3356
            $slct->addOption(get_lang('SelectAnOption'), '');
3357
        }
3358
3359
        foreach ($options as $value => $text) {
3360
            if (empty($value)) {
3361
                $slct->addOption($text, $value);
3362
                continue;
3363
            }
3364
3365
            $valueParts = explode('#', $text);
3366
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3367
3368
            $slct->addOption(implode('', $valueParts), $value, ['data-value' => $dataValue]);
3369
        }
3370
3371
        if ($freezeElement) {
3372
            $form->freeze('extra_'.$fieldDetails['variable']);
3373
        }
3374
    }
3375
3376
    /**
3377
     * @param \FormValidator $form
3378
     * @param array          $fieldDetails
3379
     * @param array          $extraData
3380
     * @param bool           $freezeElement
3381
     *
3382
     * @return string JavaScript code
3383
     */
3384
    private function addDoubleSelectElement(FormValidator $form, $fieldDetails, $extraData, $freezeElement = false)
3385
    {
3386
        $firstSelectId = 'first_extra_'.$fieldDetails['variable'];
3387
        $secondSelectId = 'second_extra_'.$fieldDetails['variable'];
3388
3389
        $jqueryReadyContent = "
3390
            $('#$firstSelectId').on('change', function() {
3391
                var id = $(this).val();
3392
3393
                if (!id) {
3394
                    $('#$secondSelectId').empty().selectpicker('refresh');
3395
3396
                    return;
3397
                }
3398
3399
                $.getJSON(_p.web_ajax + 'extra_field.ajax.php?1=1&a=get_second_select_options', {
3400
                    'type': '{$this->type}',
3401
                    'field_id': {$fieldDetails['id']},
3402
                    'option_value_id': id
3403
                })
3404
                    .done(function(data) {
3405
                        $('#$secondSelectId').empty();
3406
                        $.each(data, function(index, value) {
3407
                            $('#second_extra_{$fieldDetails['variable']}').append(
3408
                                $('<option>', {value: index, text: value})
3409
                            );
3410
                        });
3411
                        $('#$secondSelectId').selectpicker('refresh');
3412
                    });
3413
            });
3414
        ";
3415
3416
        $firstId = null;
3417
        if (!empty($extraData)) {
3418
            if (isset($extraData['extra_'.$fieldDetails['variable']])) {
3419
                $firstId = $extraData['extra_'.$fieldDetails['variable']]['extra_'.$fieldDetails['variable']];
3420
            }
3421
        }
3422
3423
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3424
        $values = ['' => get_lang('Select')];
3425
3426
        $second_values = [];
3427
        if (!empty($options)) {
3428
            foreach ($options as $option) {
3429
                foreach ($option as $sub_option) {
3430
                    if ('0' == $sub_option['option_value']) {
3431
                        $values[$sub_option['id']] = $sub_option['display_text'];
3432
3433
                        continue;
3434
                    }
3435
3436
                    if ($firstId === $sub_option['option_value']) {
3437
                        $second_values[$sub_option['id']] = $sub_option['display_text'];
3438
                    }
3439
                }
3440
            }
3441
        }
3442
3443
        $form
3444
            ->defaultRenderer()
3445
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3446
        $group = [];
3447
        $group[] = $form->createElement(
3448
            'select',
3449
            'extra_'.$fieldDetails['variable'],
3450
            null,
3451
            $values,
3452
            ['id' => $firstSelectId]
3453
        );
3454
        $group[] = $form->createElement(
3455
            'select',
3456
            'extra_'.$fieldDetails['variable'].'_second',
3457
            null,
3458
            $second_values,
3459
            ['id' => $secondSelectId]
3460
        );
3461
        $form->addGroup(
3462
            $group,
3463
            'extra_'.$fieldDetails['variable'],
3464
            $fieldDetails['display_text']
3465
        );
3466
3467
        if ($freezeElement) {
3468
            $form->freeze('extra_'.$fieldDetails['variable']);
3469
        }
3470
3471
        return $jqueryReadyContent;
3472
    }
3473
3474
    /**
3475
     * @param \FormValidator $form
3476
     * @param bool           $freezeElement Optional
3477
     *
3478
     * @return string JavaScript code
3479
     */
3480
    private function addSelectWithTextFieldElement(
3481
        FormValidator $form,
3482
        array $fieldDetails,
3483
        $freezeElement = false
3484
    ) {
3485
        $firstSelectId = 'slct_extra_'.$fieldDetails['variable'];
3486
        $txtSelectId = 'txt_extra_'.$fieldDetails['variable'];
3487
3488
        $jqueryReadyContent = "
3489
            $('#$firstSelectId').on('change', function() {
3490
                var id = $(this).val();
3491
3492
                if (!id) {
3493
                    $('#$txtSelectId').val('');
3494
                }
3495
            });
3496
        ";
3497
3498
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3499
        $values = ['' => get_lang('Select')];
3500
3501
        if (!empty($options)) {
3502
            foreach ($options as $option) {
3503
                foreach ($option as $sub_option) {
3504
                    if ('0' == $sub_option['option_value']) {
3505
                        continue;
3506
                    }
3507
3508
                    $values[$sub_option['id']] = $sub_option['display_text'];
3509
                }
3510
            }
3511
        }
3512
3513
        $form
3514
            ->defaultRenderer()
3515
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3516
        $group = [];
3517
        $group[] = $form->createElement(
3518
            'select',
3519
            'extra_'.$fieldDetails['variable'],
3520
            null,
3521
            $values,
3522
            ['id' => $firstSelectId]
3523
        );
3524
        $group[] = $form->createElement(
3525
            'text',
3526
            'extra_'.$fieldDetails['variable'].'_second',
3527
            null,
3528
            ['id' => $txtSelectId]
3529
        );
3530
        $form->addGroup(
3531
            $group,
3532
            'extra_'.$fieldDetails['variable'],
3533
            $fieldDetails['display_text']
3534
        );
3535
3536
        if ($freezeElement) {
3537
            $form->freeze('extra_'.$fieldDetails['variable']);
3538
        }
3539
3540
        return $jqueryReadyContent;
3541
    }
3542
3543
    /**
3544
     * @param \FormValidator $form
3545
     * @param bool           $freezeElement
3546
     *
3547
     * @return string
3548
     */
3549
    private function addTripleSelectElement(
3550
        FormValidator $form,
3551
        array $fieldDetails,
3552
        array $extraData,
3553
        $freezeElement
3554
    ) {
3555
        $variable = $fieldDetails['variable'];
3556
        $id = $fieldDetails['id'];
3557
        $slctFirstId = "first_extra$variable";
3558
        $slctSecondId = "second_extra$variable";
3559
        $slctThirdId = "third_extra$variable";
3560
        $langSelect = get_lang('Select');
3561
3562
        $js = "
3563
            (function () {
3564
                var slctFirst = $('#$slctFirstId'),
3565
                    slctSecond = $('#$slctSecondId'),
3566
                    slctThird = $('#$slctThirdId');
3567
3568
                slctFirst.on('change', function () {
3569
                    slctSecond.empty().selectpicker('refresh');
3570
                    slctThird.empty().selectpicker('refresh');
3571
3572
                    var level = $(this).val();
3573
3574
                    if (!level) {
3575
                        return;
3576
                    }
3577
3578
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3579
                        'a': 'get_second_select_options',
3580
                        'type': '$this->type',
3581
                        'field_id': $id,
3582
                        'option_value_id': level
3583
                    })
3584
                        .done(function (data) {
3585
                            slctSecond.append(
3586
                                $('<option>', {value: '', text: '$langSelect'})
3587
                            );
3588
3589
                            $.each(data, function (index, value) {
3590
                                var valueParts = value.split('#'),
3591
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3592
3593
                                slctSecond.append(
3594
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3595
                                );
3596
                            });
3597
3598
                            slctSecond.selectpicker('refresh');
3599
                        });
3600
                });
3601
                slctSecond.on('change', function () {
3602
                    slctThird.empty().selectpicker('refresh');
3603
3604
                    var level = $(this).val();
3605
3606
                    if (!level) {
3607
                        return;
3608
                    }
3609
3610
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3611
                        'a': 'get_second_select_options',
3612
                        'type': '$this->type',
3613
                        'field_id': $id,
3614
                        'option_value_id': level
3615
                    })
3616
                        .done(function (data) {
3617
                            slctThird.append(
3618
                                $('<option>', {value: '', text: '$langSelect'})
3619
                            );
3620
3621
                            $.each(data, function (index, value) {
3622
                                var valueParts = value.split('#'),
3623
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3624
3625
                                slctThird.append(
3626
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3627
                                );
3628
                            });
3629
3630
                            slctThird.selectpicker('refresh');
3631
                        });
3632
                });
3633
            })();
3634
        ";
3635
3636
        $firstId = isset($extraData["extra_$variable"]["extra_$variable"])
3637
            ? $extraData["extra_$variable"]["extra_$variable"]
3638
            : '';
3639
        $secondId = isset($extraData["extra_$variable"]["extra_{$variable}_second"])
3640
            ? $extraData["extra_$variable"]["extra_{$variable}_second"]
3641
            : '';
3642
3643
        $options = $this->tripleSelectConvertArrayToOrderedArray($fieldDetails['options']);
3644
        $values1 = ['' => $langSelect];
3645
        $values2 = ['' => $langSelect];
3646
        $values3 = ['' => $langSelect];
3647
        $level1 = $this->getOptionsFromTripleSelect($options['level1'], 0);
3648
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], $firstId);
3649
        $level3 = $this->getOptionsFromTripleSelect($options['level3'], $secondId);
3650
        /** @var \HTML_QuickForm_select $slctFirst */
3651
        $slctFirst = $form->createElement('select', "extra_$variable", null, $values1, ['id' => $slctFirstId]);
3652
        /** @var \HTML_QuickForm_select $slctFirst */
3653
        $slctSecond = $form->createElement(
3654
            'select',
3655
            "extra_{$variable}_second",
3656
            null,
3657
            $values2,
3658
            ['id' => $slctSecondId]
3659
        );
3660
        /** @var \HTML_QuickForm_select $slctFirst */
3661
        $slctThird = $form->createElement('select', "extra_{$variable}_third", null, $values3, ['id' => $slctThirdId]);
3662
3663
        foreach ($level1 as $item1) {
3664
            $valueParts = explode('#', $item1['display_text']);
3665
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3666
            $slctFirst->addOption(implode('', $valueParts), $item1['id'], ['data-value' => $dataValue]);
3667
        }
3668
3669
        foreach ($level2 as $item2) {
3670
            $valueParts = explode('#', $item2['display_text']);
3671
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3672
            $slctSecond->addOption(implode('', $valueParts), $item2['id'], ['data-value' => $dataValue]);
3673
        }
3674
3675
        foreach ($level3 as $item3) {
3676
            $valueParts = explode('#', $item3['display_text']);
3677
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3678
            $slctThird->addOption(implode('', $valueParts), $item3['id'], ['data-value' => $dataValue]);
3679
        }
3680
3681
        $form
3682
            ->defaultRenderer()
3683
            ->setGroupElementTemplate('<p>{element}</p>', "extra_$variable");
3684
        $form->addGroup([$slctFirst, $slctSecond, $slctThird], "extra_$variable", $fieldDetails['display_text']);
3685
3686
        if ($freezeElement) {
3687
            $form->freeze('extra_'.$fieldDetails['variable']);
3688
        }
3689
3690
        return $js;
3691
    }
3692
3693
    /**
3694
     * @param int $parentId
3695
     *
3696
     * @return array
3697
     */
3698
    private static function getOptionsFromTripleSelect(array $options, $parentId)
3699
    {
3700
        return array_filter(
3701
            $options,
3702
            function ($option) use ($parentId) {
3703
                return $option['option_value'] == $parentId;
3704
            }
3705
        );
3706
    }
3707
}
3708