Passed
Pull Request — 1.11.x (#4119)
by Angel Fernando Quiroz
13:03
created

ExtraField::addSelectElement()   D

Complexity

Conditions 18
Paths 128

Size

Total Lines 88
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
eloc 52
c 0
b 0
f 0
nop 4
dl 0
loc 88
rs 4.6333
nc 128

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

1242
                        $jquery_ready_content .= self::/** @scrutinizer ignore-call */ addDoubleSelectElement(
Loading history...
1243
                            $form,
1244
                            $field_details,
1245
                            $extraData,
1246
                            $freezeElement
1247
                        );
1248
                        break;
1249
                    case self::FIELD_TYPE_DIVIDER:
1250
                        $form->addHtml(
1251
                            '
1252
                            <div class="form-group ">
1253
                                <div class="col-sm-12">
1254
                                    <div class="panel-separator">
1255
                                       <h4 id="'.$field_details['variable'].'" class="form-separator">'
1256
                            .$field_details['display_text'].'
1257
                                       </h4>
1258
                                    </div>
1259
                                </div>
1260
                            </div>
1261
                        '
1262
                        );
1263
                        break;
1264
                    case self::FIELD_TYPE_TAG:
1265
                        $variable = $field_details['variable'];
1266
                        $field_id = $field_details['id'];
1267
                        $separateValue = 0;
1268
                        if (isset($separateExtraMultipleSelect[$field_details['variable']])) {
1269
                            $separateValue = $separateExtraMultipleSelect[$field_details['variable']];
1270
                        }
1271
1272
                        $selectedOptions = [];
1273
                        if ($separateValue > 0) {
1274
                            $em = Database::getManager();
1275
                            $fieldTags = $em
1276
                                ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1277
                                ->findBy(
1278
                                    [
1279
                                        'fieldId' => $field_id,
1280
                                        'itemId' => $itemId,
1281
                                    ]
1282
                                );
1283
                            // ofaj
1284
1285
                            for ($i = 0; $i < $separateValue; $i++) {
1286
                                $tagsSelect = $form->addElement(
1287
                                    'select',
1288
                                    'extra_'.$field_details['variable'].'['.$i.']',
1289
                                    $customLabelsExtraMultipleSelect[$field_details['variable']][$i],
1290
                                    null,
1291
                                    ['id' => 'extra_'.$field_details['variable'].'_'.$i]
1292
                                );
1293
1294
                                if ($addEmptyOptionSelects) {
1295
                                    $tagsSelect->addOption(
1296
                                        '',
1297
                                        ''
1298
                                    );
1299
                                }
1300
1301
                                foreach ($fieldTags as $fieldTag) {
1302
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1303
1304
                                    if (empty($tag)) {
1305
                                        continue;
1306
                                    }
1307
1308
                                    $tagsSelect->addOption(
1309
                                        $tag->getTag(),
1310
                                        $tag->getTag()
1311
                                    );
1312
                                }
1313
                            }
1314
                        } else {
1315
                            $tagsSelect = $form->addSelect(
1316
                                "extra_{$field_details['variable']}",
1317
                                $field_details['display_text'],
1318
                                [],
1319
                                ['style' => 'width: 100%;']
1320
                            );
1321
1322
                            if (false === $useTagAsSelect) {
1323
                                $tagsSelect->setAttribute('class', null);
1324
                            }
1325
1326
                            $tagsSelect->setAttribute(
1327
                                'id',
1328
                                "extra_{$field_details['variable']}"
1329
                            );
1330
                            $tagsSelect->setMultiple(true);
1331
1332
                            $selectedOptions = [];
1333
                            if ('user' === $this->type) {
1334
                                // The magic should be here
1335
                                $user_tags = UserManager::get_user_tags(
1336
                                    $itemId,
1337
                                    $field_details['id']
1338
                                );
1339
1340
                                if (is_array($user_tags) && count($user_tags) > 0) {
1341
                                    foreach ($user_tags as $tag) {
1342
                                        if (empty($tag['tag'])) {
1343
                                            continue;
1344
                                        }
1345
                                        $tagsSelect->addOption(
1346
                                            $tag['tag'],
1347
                                            $tag['tag'],
1348
                                            [
1349
                                                'selected' => 'selected',
1350
                                                'class' => 'selected',
1351
                                            ]
1352
                                        );
1353
                                        $selectedOptions[] = $tag['tag'];
1354
                                    }
1355
                                }
1356
                                $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
1357
                            } else {
1358
                                $em = Database::getManager();
1359
                                $fieldTags = $em->getRepository(
1360
                                    'ChamiloCoreBundle:ExtraFieldRelTag'
1361
                                )
1362
                                    ->findBy(
1363
                                        [
1364
                                            'fieldId' => $field_id,
1365
                                            'itemId' => $itemId,
1366
                                        ]
1367
                                    );
1368
1369
                                /** @var ExtraFieldRelTag $fieldTag */
1370
                                foreach ($fieldTags as $fieldTag) {
1371
                                    /** @var Tag $tag */
1372
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1373
1374
                                    if (empty($tag)) {
1375
                                        continue;
1376
                                    }
1377
                                    $tagsSelect->addOption(
1378
                                        $tag->getTag(),
1379
                                        $tag->getTag()
1380
                                    );
1381
                                    $selectedOptions[] = $tag->getTag();
1382
                                }
1383
1384
                                if (!empty($extraData) && isset($extraData['extra_'.$field_details['variable']])) {
1385
                                    $data = $extraData['extra_'.$field_details['variable']];
1386
                                    if (!empty($data)) {
1387
                                        foreach ($data as $option) {
1388
                                            $tagsSelect->addOption(
1389
                                                $option,
1390
                                                $option
1391
                                            );
1392
                                        }
1393
                                    }
1394
                                }
1395
1396
                                if ($useTagAsSelect) {
1397
                                    $fieldTags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1398
                                        ->findBy(
1399
                                            [
1400
                                                'fieldId' => $field_id,
1401
                                            ]
1402
                                        );
1403
                                    $tagsAdded = [];
1404
                                    foreach ($fieldTags as $fieldTag) {
1405
                                        $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1406
1407
                                        if (empty($tag)) {
1408
                                            continue;
1409
                                        }
1410
1411
                                        $tagText = $tag->getTag();
1412
1413
                                        if (in_array($tagText, $tagsAdded)) {
1414
                                            continue;
1415
                                        }
1416
1417
                                        $tagsSelect->addOption(
1418
                                            $tag->getTag(),
1419
                                            $tag->getTag(),
1420
                                            []
1421
                                        );
1422
1423
                                        $tagsAdded[] = $tagText;
1424
                                    }
1425
                                }
1426
                                $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
1427
                            }
1428
1429
                            $form->setDefaults(
1430
                                [
1431
                                    'extra_'.$field_details['variable'] => $selectedOptions,
1432
                                ]
1433
                            );
1434
1435
                            if (false == $useTagAsSelect) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

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

Loading history...
1436
                                $jquery_ready_content .= "
1437
                                $('#extra_$variable').select2({
1438
                                    ajax: {
1439
                                        url: '$url?a=search_tags&field_id=$field_id&type={$this->type}',
1440
                                        processResults: function (data) {
1441
                                            return {
1442
                                                results: data.items
1443
                                            }
1444
                                        }
1445
                                    },
1446
                                    cache: false,
1447
                                    tags: true,
1448
                                    tokenSeparators: [','],
1449
                                    placeholder: '".get_lang('StartToType')."'
1450
                                });
1451
                            ";
1452
                            }
1453
                        }
1454
1455
                        break;
1456
                    case self::FIELD_TYPE_TIMEZONE:
1457
                        $form->addElement(
1458
                            'select',
1459
                            'extra_'.$field_details['variable'],
1460
                            $field_details['display_text'],
1461
                            api_get_timezones(),
1462
                            ''
1463
                        );
1464
                        if ($freezeElement) {
1465
                            $form->freeze('extra_'.$field_details['variable']);
1466
                        }
1467
                        break;
1468
                    case self::FIELD_TYPE_SOCIAL_PROFILE:
1469
                        // get the social network's favicon
1470
                        $extra_data_variable = isset($extraData['extra_'.$field_details['variable']])
1471
                            ? $extraData['extra_'.$field_details['variable']]
1472
                            : null;
1473
                        $field_default_value = isset($field_details['field_default_value'])
1474
                            ? $field_details['field_default_value']
1475
                            : null;
1476
                        $icon_path = UserManager::get_favicon_from_url(
1477
                            $extra_data_variable,
1478
                            $field_default_value
1479
                        );
1480
                        // special hack for hi5
1481
                        $leftpad = '1.7';
1482
                        $top = '0.4';
1483
                        $domain = parse_url($icon_path, PHP_URL_HOST);
1484
                        if ('www.hi5.com' === $domain || 'hi5.com' === $domain) {
1485
                            $leftpad = '3';
1486
                            $top = '0';
1487
                        }
1488
                        // print the input field
1489
                        $form->addElement(
1490
                            'text',
1491
                            'extra_'.$field_details['variable'],
1492
                            $field_details['display_text'],
1493
                            [
1494
                                'size' => 60,
1495
                                'size' => implode(
1496
                                    '; ',
1497
                                    [
1498
                                        "background-image: url('$icon_path')",
1499
                                        'background-repeat: no-repeat',
1500
                                        "background-position: 0.4em {$top}em",
1501
                                        "padding-left: {$leftpad}em",
1502
                                    ]
1503
                                ),
1504
                            ]
1505
                        );
1506
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1507
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1508
                        if ($freezeElement) {
1509
                            $form->freeze('extra_'.$field_details['variable']);
1510
                        }
1511
                        break;
1512
                    case self::FIELD_TYPE_MOBILE_PHONE_NUMBER:
1513
                        $form->addElement(
1514
                            'text',
1515
                            'extra_'.$field_details['variable'],
1516
                            $field_details['display_text'].' ('.get_lang('CountryDialCode').')',
1517
                            ['size' => 40, 'placeholder' => '(xx)xxxxxxxxx']
1518
                        );
1519
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1520
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1521
                        $form->applyFilter('extra_'.$field_details['variable'], 'mobile_phone_number_filter');
1522
                        $form->addRule(
1523
                            'extra_'.$field_details['variable'],
1524
                            get_lang('MobilePhoneNumberWrong'),
1525
                            'mobile_phone_number'
1526
                        );
1527
                        if ($freezeElement) {
1528
                            $form->freeze('extra_'.$field_details['variable']);
1529
                        }
1530
                        break;
1531
                    case self::FIELD_TYPE_INTEGER:
1532
                        $form->addElement(
1533
                            'number',
1534
                            'extra_'.$field_details['variable'],
1535
                            $field_details['display_text'],
1536
                            ['class' => 'span1', 'step' => 1]
1537
                        );
1538
1539
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1540
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1541
                        $form->applyFilter('extra_'.$field_details['variable'], 'intval');
1542
1543
                        if ($freezeElement) {
1544
                            $form->freeze('extra_'.$field_details['variable']);
1545
                        }
1546
                        break;
1547
                    case self::FIELD_TYPE_FILE_IMAGE:
1548
                        $fieldVariable = "extra_{$field_details['variable']}";
1549
                        $fieldTexts = [
1550
                            $field_details['display_text'],
1551
                        ];
1552
1553
                        if (is_array($extraData) && array_key_exists($fieldVariable, $extraData)) {
1554
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1555
                                $fieldTexts[] = Display::img(
1556
                                    api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1557
                                    $field_details['display_text'],
1558
                                    ['width' => '300']
1559
                                );
1560
                            }
1561
                        }
1562
1563
                        if ('Image' === $fieldTexts[0]) {
1564
                            $fieldTexts[0] = get_lang($fieldTexts[0]);
1565
                        }
1566
1567
                        $form->addFile(
1568
                            $fieldVariable,
1569
                            $fieldTexts,
1570
                            ['accept' => 'image/*', 'id' => 'extra_image', 'crop_image' => 'true']
1571
                        );
1572
1573
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1574
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1575
1576
                        $allowedPictureTypes = ['jpg', 'jpeg', 'png', 'gif'];
1577
                        $form->addRule(
1578
                            'extra_'.$field_details['variable'],
1579
                            get_lang('OnlyImagesAllowed').' ('.implode(',', $allowedPictureTypes).')',
1580
                            'filetype',
1581
                            $allowedPictureTypes
1582
                        );
1583
1584
                        if ($freezeElement) {
1585
                            $form->freeze('extra_'.$field_details['variable']);
1586
                        }
1587
                        break;
1588
                    case self::FIELD_TYPE_FLOAT:
1589
                        $form->addElement(
1590
                            'number',
1591
                            'extra_'.$field_details['variable'],
1592
                            $field_details['display_text'],
1593
                            ['class' => 'span1', 'step' => '0.01']
1594
                        );
1595
1596
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1597
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1598
                        $form->applyFilter('extra_'.$field_details['variable'], 'floatval');
1599
1600
                        if ($freezeElement) {
1601
                            $form->freeze('extra_'.$field_details['variable']);
1602
                        }
1603
                        break;
1604
                    case self::FIELD_TYPE_FILE:
1605
                        $fieldVariable = "extra_{$field_details['variable']}";
1606
                        $fieldTexts = [
1607
                            $field_details['display_text'],
1608
                        ];
1609
1610
                        if (is_array($extraData) &&
1611
                            array_key_exists($fieldVariable, $extraData)
1612
                        ) {
1613
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1614
                                $linkToDelete = '';
1615
                                $divItemId = $field_details['variable'];
1616
                                if (api_is_platform_admin()) {
1617
                                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?type='.$this->type;
1618
                                    $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId;
1619
1620
                                    $deleteId = $field_details['variable'].'_delete';
1621
                                    $form->addHtml(
1622
                                        "
1623
                                        <script>
1624
                                            $(function() {
1625
                                                $('#".$deleteId."').on('click', function() {
1626
                                                    $.ajax({
1627
                                                        type: 'GET',
1628
                                                        url: '".$url."',
1629
                                                        success: function(result) {
1630
                                                            if (result == 1) {
1631
                                                                $('#".$divItemId."').html('".get_lang('Deleted')."');
1632
                                                            }
1633
                                                        }
1634
                                                    });
1635
                                                });
1636
                                            });
1637
                                        </script>
1638
                                    "
1639
                                    );
1640
1641
                                    $linkToDelete = '&nbsp;'.Display::url(
1642
                                            Display::return_icon('delete.png', get_lang('Delete')),
1643
                                            'javascript:void(0)',
1644
                                            ['id' => $deleteId]
1645
                                        );
1646
                                }
1647
                                $fieldTexts[] = '<div id="'.$divItemId.'">'.Display::url(
1648
                                        basename($extraData[$fieldVariable]),
1649
                                        api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1650
                                        [
1651
                                            'title' => $field_details['display_text'],
1652
                                            'target' => '_blank',
1653
                                        ]
1654
                                    ).$linkToDelete.'</div>';
1655
                            }
1656
                        }
1657
1658
                        $form->addElement(
1659
                            'file',
1660
                            $fieldVariable,
1661
                            $fieldTexts,
1662
                            []
1663
                        );
1664
1665
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1666
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1667
1668
                        if ($freezeElement) {
1669
                            $form->freeze('extra_'.$field_details['variable']);
1670
                        }
1671
                        break;
1672
                    case self::FIELD_TYPE_VIDEO_URL:
1673
                        $form->addUrl(
1674
                            "extra_{$field_details['variable']}",
1675
                            $field_details['display_text'],
1676
                            false,
1677
                            ['placeholder' => 'https://']
1678
                        );
1679
                        if ($freezeElement) {
1680
                            $form->freeze('extra_'.$field_details['variable']);
1681
                        }
1682
                        break;
1683
                    case self::FIELD_TYPE_LETTERS_ONLY:
1684
                        $form->addTextLettersOnly(
1685
                            "extra_{$field_details['variable']}",
1686
                            $field_details['display_text']
1687
                        );
1688
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1689
1690
                        if ($freezeElement) {
1691
                            $form->freeze('extra_'.$field_details['variable']);
1692
                        }
1693
                        break;
1694
                    case self::FIELD_TYPE_ALPHANUMERIC:
1695
                        $form->addTextAlphanumeric(
1696
                            "extra_{$field_details['variable']}",
1697
                            $field_details['display_text']
1698
                        );
1699
                        $form->applyFilter(
1700
                            'extra_'.$field_details['variable'],
1701
                            'stripslashes'
1702
                        );
1703
                        if ($freezeElement) {
1704
                            $form->freeze('extra_'.$field_details['variable']);
1705
                        }
1706
                        break;
1707
                    case self::FIELD_TYPE_LETTERS_SPACE:
1708
                        $form->addTextLettersAndSpaces(
1709
                            "extra_{$field_details['variable']}",
1710
                            $field_details['display_text']
1711
                        );
1712
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1713
1714
                        if ($freezeElement) {
1715
                            $form->freeze('extra_'.$field_details['variable']);
1716
                        }
1717
                        break;
1718
                    case self::FIELD_TYPE_ALPHANUMERIC_SPACE:
1719
                        $form->addTextAlphanumericAndSpaces(
1720
                            "extra_{$field_details['variable']}",
1721
                            $field_details['display_text']
1722
                        );
1723
                        $form->applyFilter(
1724
                            'extra_'.$field_details['variable'],
1725
                            'stripslashes'
1726
                        );
1727
                        if ($freezeElement) {
1728
                            $form->freeze('extra_'.$field_details['variable']);
1729
                        }
1730
                        break;
1731
                    case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
1732
                    case self::FIELD_TYPE_GEOLOCALIZATION:
1733
                        $dataValue = isset($extraData['extra_'.$field_details['variable']])
1734
                            ? $extraData['extra_'.$field_details['variable']]
1735
                            : '';
1736
1737
                        $form->addGeoLocationMapField(
1738
                            'extra_'.$field_details['variable'],
1739
                            $field_details['display_text'],
1740
                            $dataValue,
1741
                            $hideGeoLocalizationDetails
1742
                        );
1743
1744
                        if ($freezeElement) {
1745
                            $form->freeze('extra_'.$field_details['variable']);
1746
                        }
1747
                        break;
1748
                    case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
1749
                        $jquery_ready_content .= $this->addSelectWithTextFieldElement(
1750
                            $form,
1751
                            $field_details,
1752
                            $freezeElement
1753
                        );
1754
                        break;
1755
                    case self::FIELD_TYPE_TRIPLE_SELECT:
1756
                        $jquery_ready_content .= $this->addTripleSelectElement(
1757
                            $form,
1758
                            $field_details,
1759
                            is_array($extraData) ? $extraData : [],
1760
                            $freezeElement
1761
                        );
1762
                        break;
1763
                }
1764
            }
1765
        }
1766
1767
        $return = [];
1768
        $return['jquery_ready_content'] = $jquery_ready_content;
1769
1770
        return $return;
1771
    }
1772
1773
    /**
1774
     * @param array $options
1775
     *
1776
     * @return array
1777
     */
1778
    public static function extra_field_double_select_convert_array_to_ordered_array($options)
1779
    {
1780
        $optionsParsed = [];
1781
        if (!empty($options)) {
1782
            foreach ($options as $option) {
1783
                if (0 == $option['option_value']) {
1784
                    $optionsParsed[$option['id']][] = $option;
1785
                } else {
1786
                    $optionsParsed[$option['option_value']][] = $option;
1787
                }
1788
            }
1789
        }
1790
1791
        return $optionsParsed;
1792
    }
1793
1794
    /**
1795
     * @return array
1796
     */
1797
    public static function tripleSelectConvertArrayToOrderedArray(array $options)
1798
    {
1799
        $level1 = self::getOptionsFromTripleSelect($options, 0);
1800
        $level2 = [];
1801
        $level3 = [];
1802
1803
        foreach ($level1 as $item1) {
1804
            $level2 += self::getOptionsFromTripleSelect($options, $item1['id']);
1805
        }
1806
1807
        foreach ($level2 as $item2) {
1808
            $level3 += self::getOptionsFromTripleSelect($options, $item2['id']);
1809
        }
1810
1811
        return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3];
1812
    }
1813
1814
    /**
1815
     * @param string $type
1816
     *
1817
     * @return array
1818
     */
1819
    public function get_all_extra_field_by_type($type)
1820
    {
1821
        // all the information of the field
1822
        $sql = "SELECT * FROM {$this->table}
1823
                WHERE
1824
                    field_type = '".Database::escape_string($type)."' AND
1825
                    extra_field_type = $this->extraFieldType
1826
                ";
1827
        $result = Database::query($sql);
1828
1829
        $return = [];
1830
        while ($row = Database::fetch_array($result)) {
1831
            $return[] = $row['id'];
1832
        }
1833
1834
        return $return;
1835
    }
1836
1837
    /**
1838
     * @param int $id
1839
     */
1840
    public function get_field_type_by_id($id)
1841
    {
1842
        $types = $this->get_field_types();
1843
        if (isset($types[$id])) {
1844
            return $types[$id];
1845
        }
1846
1847
        return null;
1848
    }
1849
1850
    /**
1851
     * @return array
1852
     */
1853
    public function get_field_types()
1854
    {
1855
        return $this->get_extra_fields_by_handler($this->type);
1856
    }
1857
1858
    /**
1859
     * @param string $handler
1860
     *
1861
     * @return array
1862
     */
1863
    public static function get_extra_fields_by_handler($handler)
1864
    {
1865
        $types = [];
1866
        $types[self::FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
1867
        $types[self::FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
1868
        $types[self::FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
1869
        $types[self::FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
1870
        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
1871
        $types[self::FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
1872
        $types[self::FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
1873
        $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
1874
        $types[self::FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
1875
        $types[self::FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
1876
        $types[self::FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
1877
        $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
1878
        $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
1879
        $types[self::FIELD_TYPE_CHECKBOX] = get_lang('FieldTypeCheckbox');
1880
        $types[self::FIELD_TYPE_INTEGER] = get_lang('FieldTypeInteger');
1881
        $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('FieldTypeFileImage');
1882
        $types[self::FIELD_TYPE_FLOAT] = get_lang('FieldTypeFloat');
1883
        $types[self::FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
1884
        $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('FieldTypeVideoUrl');
1885
        $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('FieldTypeOnlyLetters');
1886
        $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('FieldTypeAlphanumeric');
1887
        $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('FieldTypeLettersSpaces');
1888
        $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('FieldTypeAlphanumericSpaces');
1889
        $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization');
1890
        $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('GeolocalizationCoordinates');
1891
        $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('FieldTypeSelectWithTextField');
1892
        $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('FieldTypeTripleSelect');
1893
1894
        switch ($handler) {
1895
            case 'course':
1896
            case 'session':
1897
            case 'user':
1898
            case 'skill':
1899
                break;
1900
        }
1901
1902
        return $types;
1903
    }
1904
1905
    /**
1906
     * @param array $params
1907
     * @param bool  $show_query
1908
     *
1909
     * @return int|bool
1910
     */
1911
    public function save($params, $show_query = false)
1912
    {
1913
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_handler_...nfo_by_field_variable() is not static, but was called statically. ( Ignorable by Annotation )

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

1913
        /** @scrutinizer ignore-call */ 
1914
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1914
        $params = $this->clean_parameters($params);
1915
        $params['extra_field_type'] = $this->extraFieldType;
1916
1917
        if ($fieldInfo) {
1918
            return $fieldInfo['id'];
1919
        } else {
1920
            $id = parent::save($params, $show_query);
1921
            if ($id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type false|integer is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== false instead.

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

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

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

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1922
                $fieldOption = new ExtraFieldOption($this->type);
1923
                $params['field_id'] = $id;
1924
                $fieldOption->save($params);
1925
            }
1926
1927
            return $id;
1928
        }
1929
    }
1930
1931
    /**
1932
     * Gets the set of values of an extra_field searching for the variable name.
1933
     *
1934
     * Example:
1935
     * <code>
1936
     * <?php
1937
     * $extraField = new ExtraField('lp_item');
1938
     * $extraFieldArray =  $extraField->get_handler_field_info_by_field_variable('authorlpitem');
1939
     * echo "<pre>".var_export($extraFieldArray,true)."</pre>";
1940
     * ?>
1941
     * </code>
1942
     *
1943
     * @param string $variable
1944
     *
1945
     * @return array|bool
1946
     */
1947
    public function get_handler_field_info_by_field_variable($variable)
1948
    {
1949
        $variable = Database::escape_string($variable);
1950
        $sql = "SELECT * FROM {$this->table}
1951
                WHERE
1952
                    variable = '$variable' AND
1953
                    extra_field_type = $this->extraFieldType";
1954
        $result = Database::query($sql);
1955
        if (Database::num_rows($result)) {
1956
            $row = Database::fetch_array($result, 'ASSOC');
1957
            if ($row) {
1958
                $row['display_text'] = self::translateDisplayName($row['variable'], $row['display_text']);
1959
1960
                // All the options of the field
1961
                $sql = "SELECT * FROM $this->table_field_options
1962
                    WHERE field_id='".intval($row['id'])."'
1963
                    ORDER BY option_order ASC";
1964
                $result = Database::query($sql);
1965
                while ($option = Database::fetch_array($result)) {
1966
                    $row['options'][$option['id']] = $option;
1967
                }
1968
1969
                return $row;
1970
            }
1971
        }
1972
1973
        return false;
1974
    }
1975
1976
    public function getHandlerEntityByFieldVariable(string $variable)
1977
    {
1978
        return Database::getManager()
1979
            ->getRepository('ChamiloCoreBundle:ExtraField')
1980
            ->findOneBy(['variable' => $variable, 'extraFieldType' => $this->extraFieldType]);
1981
    }
1982
1983
    /**
1984
     * @param array $params
1985
     *
1986
     * @return array
1987
     */
1988
    public function clean_parameters($params)
1989
    {
1990
        if (!isset($params['variable']) || empty($params['variable'])) {
1991
            $params['variable'] = $params['display_text'];
1992
        }
1993
1994
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
1995
1996
        if (!isset($params['field_order'])) {
1997
            $max_order = self::get_max_field_order();
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_max_field_order() is not static, but was called statically. ( Ignorable by Annotation )

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

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

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

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