Completed
Push — master ( 024a20...a0a31d )
by Julito
09:32
created

ExtraField::set_extra_fields_in_form()   F

Complexity

Conditions 125
Paths 3

Size

Total Lines 787
Code Lines 503

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 125
eloc 503
c 0
b 0
f 0
nop 16
dl 0
loc 787
rs 3.3333
nc 3

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
7
use Chamilo\CoreBundle\Entity\Tag;
8
9
/**
10
 * Class ExtraField.
11
 */
12
class ExtraField extends Model
13
{
14
    public const FIELD_TYPE_TEXT = 1;
15
    public const FIELD_TYPE_TEXTAREA = 2;
16
    public const FIELD_TYPE_RADIO = 3;
17
    public const FIELD_TYPE_SELECT = 4;
18
    public const FIELD_TYPE_SELECT_MULTIPLE = 5;
19
    public const FIELD_TYPE_DATE = 6;
20
    public const FIELD_TYPE_DATETIME = 7;
21
    public const FIELD_TYPE_DOUBLE_SELECT = 8;
22
    public const FIELD_TYPE_DIVIDER = 9;
23
    public const FIELD_TYPE_TAG = 10;
24
    public const FIELD_TYPE_TIMEZONE = 11;
25
    public const FIELD_TYPE_SOCIAL_PROFILE = 12;
26
    public const FIELD_TYPE_CHECKBOX = 13;
27
    public const FIELD_TYPE_MOBILE_PHONE_NUMBER = 14;
28
    public const FIELD_TYPE_INTEGER = 15;
29
    public const FIELD_TYPE_FILE_IMAGE = 16;
30
    public const FIELD_TYPE_FLOAT = 17;
31
    public const FIELD_TYPE_FILE = 18;
32
    public const FIELD_TYPE_VIDEO_URL = 19;
33
    public const FIELD_TYPE_LETTERS_ONLY = 20;
34
    public const FIELD_TYPE_ALPHANUMERIC = 21;
35
    public const FIELD_TYPE_LETTERS_SPACE = 22;
36
    public const FIELD_TYPE_ALPHANUMERIC_SPACE = 23;
37
    public const FIELD_TYPE_GEOLOCALIZATION = 24;
38
    public const FIELD_TYPE_GEOLOCALIZATION_COORDINATES = 25;
39
    public const FIELD_TYPE_SELECT_WITH_TEXT_FIELD = 26;
40
    public const FIELD_TYPE_TRIPLE_SELECT = 27;
41
42
    public $columns = [
43
        'id',
44
        'field_type',
45
        'variable',
46
        'description',
47
        'display_text',
48
        'default_value',
49
        'field_order',
50
        'visible_to_self',
51
        'visible_to_others',
52
        'changeable',
53
        'filter',
54
        'extra_field_type',
55
        //Enable this when field_loggeable is introduced as a table field (2.0)
56
        //'field_loggeable',
57
        'created_at',
58
    ];
59
60
    public $ops = [
61
        'eq' => '=', //equal
62
        'ne' => '<>', //not equal
63
        'lt' => '<', //less than
64
        'le' => '<=', //less than or equal
65
        'gt' => '>', //greater than
66
        'ge' => '>=', //greater than or equal
67
        'bw' => 'LIKE', //begins with
68
        'bn' => 'NOT LIKE', //doesn't begin with
69
        'in' => 'LIKE', //is in
70
        'ni' => 'NOT LIKE', //is not in
71
        'ew' => 'LIKE', //ends with
72
        'en' => 'NOT LIKE', //doesn't end with
73
        'cn' => 'LIKE', //contains
74
        'nc' => 'NOT LIKE',  //doesn't contain
75
    ];
76
77
    public $type = 'user';
78
    public $pageName;
79
    public $pageUrl;
80
    public $extraFieldType = 0;
81
82
    public $table_field_options;
83
    public $table_field_values;
84
    public $table_field_tag;
85
    public $table_field_rel_tag;
86
87
    public $handler_id;
88
    public $primaryKey;
89
90
    /**
91
     * @param string $type
92
     */
93
    public function __construct($type)
94
    {
95
        parent::__construct();
96
97
        $this->type = $type;
98
        $this->table = Database::get_main_table(TABLE_EXTRA_FIELD);
99
        $this->table_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
100
        $this->table_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
101
        $this->table_field_tag = Database::get_main_table(TABLE_MAIN_TAG);
102
        $this->table_field_rel_tag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
103
104
        $this->handler_id = 'item_id';
105
106
        switch ($this->type) {
107
            case 'calendar_event':
108
                $this->extraFieldType = EntityExtraField::CALENDAR_FIELD_TYPE;
109
                break;
110
            case 'course':
111
                $this->extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
112
                $this->primaryKey = 'id';
113
                break;
114
            case 'user':
115
                $this->extraFieldType = EntityExtraField::USER_FIELD_TYPE;
116
                $this->primaryKey = 'id';
117
                break;
118
            case 'session':
119
                $this->extraFieldType = EntityExtraField::SESSION_FIELD_TYPE;
120
                $this->primaryKey = 'id';
121
                break;
122
            case 'exercise':
123
                $this->extraFieldType = EntityExtraField::EXERCISE_FIELD_TYPE;
124
                break;
125
            case 'question':
126
                $this->extraFieldType = EntityExtraField::QUESTION_FIELD_TYPE;
127
                break;
128
            case 'lp':
129
                $this->extraFieldType = EntityExtraField::LP_FIELD_TYPE;
130
                break;
131
            case 'lp_item':
132
                $this->extraFieldType = EntityExtraField::LP_ITEM_FIELD_TYPE;
133
                break;
134
            case 'skill':
135
                $this->extraFieldType = EntityExtraField::SKILL_FIELD_TYPE;
136
                break;
137
            case 'work':
138
                $this->extraFieldType = EntityExtraField::WORK_FIELD_TYPE;
139
                break;
140
            case 'career':
141
                $this->extraFieldType = EntityExtraField::CAREER_FIELD_TYPE;
142
                break;
143
            case 'user_certificate':
144
                $this->extraFieldType = EntityExtraField::USER_CERTIFICATE;
145
                break;
146
            case 'survey':
147
                $this->extraFieldType = EntityExtraField::SURVEY_FIELD_TYPE;
148
                break;
149
            case 'scheduled_announcement':
150
                $this->extraFieldType = EntityExtraField::SCHEDULED_ANNOUNCEMENT;
151
                break;
152
            case 'terms_and_condition':
153
                $this->extraFieldType = EntityExtraField::TERMS_AND_CONDITION_TYPE;
154
                break;
155
            case 'forum_category':
156
                $this->extraFieldType = EntityExtraField::FORUM_CATEGORY_TYPE;
157
                break;
158
            case 'forum_post':
159
                $this->extraFieldType = EntityExtraField::FORUM_POST_TYPE;
160
                break;
161
        }
162
163
        $this->pageUrl = 'extra_fields.php?type='.$this->type;
164
        // Example QuestionFields
165
        $this->pageName = get_lang(ucwords($this->type).'Fields');
166
    }
167
168
    /**
169
     * @return array
170
     */
171
    public static function getValidExtraFieldTypes()
172
    {
173
        $result = [
174
            'user',
175
            'course',
176
            'session',
177
            'question',
178
            'lp',
179
            'calendar_event',
180
            'lp_item',
181
            'skill',
182
            'work',
183
            'career',
184
            'user_certificate',
185
            'survey',
186
            'terms_and_condition',
187
            'forum_category',
188
            'forum_post',
189
            'exercise',
190
        ];
191
192
        if (api_get_configuration_value('allow_scheduled_announcements')) {
193
            $result[] = 'scheduled_announcement';
194
        }
195
196
        return $result;
197
    }
198
199
    /**
200
     * Converts a string like this:
201
     * France:Paris;Bretagne;Marseille;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
202
     * into
203
     * array(
204
     *   'France' =>
205
     *      array('Paris', 'Bretagne', 'Marseille'),
206
     *   'Belgique' =>
207
     *      array('Namur', 'Liège')
208
     * ), etc.
209
     *
210
     * @param string $string
211
     *
212
     * @return array
213
     */
214
    public static function extra_field_double_select_convert_string_to_array($string)
215
    {
216
        $options = explode('|', $string);
217
        $options_parsed = [];
218
        $id = 0;
219
220
        if (!empty($options)) {
221
            foreach ($options as $sub_options) {
222
                $options = explode(':', $sub_options);
223
                $sub_sub_options = isset($options[1]) ? explode(';', $options[1]) : [];
224
                $options_parsed[$id] = [
225
                    'label' => $options[0],
226
                    'options' => $sub_sub_options,
227
                ];
228
                $id++;
229
            }
230
        }
231
232
        return $options_parsed;
233
    }
234
235
    /**
236
     * @param $string
237
     *
238
     * @return array
239
     */
240
    public static function tripleSelectConvertStringToArray($string)
241
    {
242
        $options = [];
243
        foreach (explode('|', $string) as $i => $item0) {
244
            $level1 = explode('\\', $item0);
245
246
            foreach ($level1 as $j => $item1) {
247
                if (0 === $j) {
248
                    $options[] = ['label' => $item1, 'options' => []];
249
250
                    continue;
251
                }
252
253
                foreach (explode(':', $item1) as $k => $item2) {
254
                    if (0 === $k) {
255
                        $options[$i]['options'][] = ['label' => $item2, 'options' => []];
256
257
                        continue;
258
                    }
259
260
                    $options[$i]['options'][$j - 1]['options'][] = explode(';', $item2);
261
                }
262
            }
263
        }
264
265
        array_walk_recursive(
266
            $options,
267
            function (&$item) {
268
                $item = trim($item);
269
            }
270
        );
271
272
        return $options;
273
    }
274
275
    /**
276
     * @param array $options the result of the get_field_options_by_field() array
277
     *
278
     * @return string
279
     */
280
    public static function extra_field_double_select_convert_array_to_string($options)
281
    {
282
        $string = null;
283
        $optionsParsed = self::extra_field_double_select_convert_array_to_ordered_array($options);
284
285
        if (!empty($optionsParsed)) {
286
            foreach ($optionsParsed as $option) {
287
                foreach ($option as $key => $item) {
288
                    $string .= $item['display_text'];
289
                    if (0 == $key) {
290
                        $string .= ':';
291
                    } else {
292
                        if (isset($option[$key + 1])) {
293
                            $string .= ';';
294
                        }
295
                    }
296
                }
297
                $string .= '|';
298
            }
299
        }
300
301
        if (!empty($string)) {
302
            $string = substr($string, 0, strlen($string) - 1);
303
        }
304
305
        return $string;
306
    }
307
308
    /**
309
     * @param array $options The result of the get_field_options_by_field() array
310
     *
311
     * @return string
312
     */
313
    public static function extraFieldSelectWithTextConvertArrayToString(array $options)
314
    {
315
        $parsedOptions = self::extra_field_double_select_convert_array_to_ordered_array($options);
316
317
        if (empty($parsedOptions)) {
318
            return '';
319
        }
320
321
        $string = '';
322
        foreach ($parsedOptions as $options) {
323
            $option = current($options);
324
            $string .= $option['display_text'];
325
            $string .= '|';
326
        }
327
328
        return rtrim($string, '|');
329
    }
330
331
    /**
332
     * @return string
333
     */
334
    public static function tripleSelectConvertArrayToString(array $options)
335
    {
336
        $parsedOptions = self::tripleSelectConvertArrayToOrderedArray($options);
337
        $string = '';
338
        foreach ($parsedOptions['level1'] as $item1) {
339
            $string .= $item1['display_text'];
340
            $level2 = self::getOptionsFromTripleSelect($parsedOptions['level2'], $item1['id']);
341
342
            foreach ($level2 as $item2) {
343
                $string .= '\\'.$item2['display_text'].':';
344
                $level3 = self::getOptionsFromTripleSelect($parsedOptions['level3'], $item2['id']);
345
346
                $string .= implode(';', array_column($level3, 'display_text'));
347
            }
348
349
            $string .= '|';
350
        }
351
352
        return trim($string, '\\|;');
353
    }
354
355
    /**
356
     * @param string $variable
357
     * @param string $dataValue
358
     *
359
     * @return string
360
     */
361
    public static function getLocalizationJavascript($variable, $dataValue)
362
    {
363
        $dataValue = addslashes($dataValue);
364
        $html = "<script>
365
            $(function() {
366
                if (typeof google === 'object') {
367
                    var address = '$dataValue';
368
                    initializeGeo{$variable}(address, false);
369
370
                    $('#geolocalization_extra_{$variable}').on('click', function() {
371
                        var address = $('#{$variable}').val();
372
                        initializeGeo{$variable}(address, false);
373
                        return false;
374
                    });
375
376
                    $('#myLocation_extra_{$variable}').on('click', function() {
377
                        myLocation{$variable}();
378
                        return false;
379
                    });
380
381
                    // When clicking enter
382
                    $('#{$variable}').keypress(function(event) {
383
                        if (event.which == 13) {
384
                            $('#geolocalization_extra_{$variable}').click();
385
                            return false;
386
                        }
387
                    });
388
389
                    // On focus out update city
390
                    $('#{$variable}').focusout(function() {
391
                        $('#geolocalization_extra_{$variable}').click();
392
                        return false;
393
                    });
394
395
                    return;
396
                }
397
398
                $('#map_extra_{$variable}')
399
                    .html('<div class=\"alert alert-info\">"
400
            .addslashes(get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap'))
401
            ."</div>');
402
            });
403
404
            function myLocation{$variable}()
405
            {
406
                if (navigator.geolocation) {
407
                    var geoPosition = function(position) {
408
                        var lat = position.coords.latitude;
409
                        var lng = position.coords.longitude;
410
                        var latLng = new google.maps.LatLng(lat, lng);
411
                        initializeGeo{$variable}(false, latLng);
412
                    };
413
414
                    var geoError = function(error) {
415
                        alert('Geocode ".get_lang('Error').": ' + error);
416
                    };
417
418
                    var geoOptions = {
419
                        enableHighAccuracy: true
420
                    };
421
                    navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
422
                }
423
            }
424
425
            function initializeGeo{$variable}(address, latLng)
426
            {
427
                var geocoder = new google.maps.Geocoder();
428
                var latlng = new google.maps.LatLng(-34.397, 150.644);
429
                var myOptions = {
430
                    zoom: 15,
431
                    center: latlng,
432
                    mapTypeControl: true,
433
                    mapTypeControlOptions: {
434
                        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
435
                    },
436
                    navigationControl: true,
437
                    mapTypeId: google.maps.MapTypeId.ROADMAP
438
                };
439
440
                map_{$variable} = new google.maps.Map(
441
                    document.getElementById('map_extra_{$variable}'),
442
                    myOptions
443
                );
444
445
                var parameter = address ? {'address': address} : latLng ? {'latLng': latLng} : false;
446
447
                if (geocoder && parameter) {
448
                    geocoder.geocode(parameter, function(results, status) {
449
                        if (status == google.maps.GeocoderStatus.OK) {
450
                            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
451
                                map_{$variable}.setCenter(results[0].geometry.location);
452
453
                                // get city and country
454
                                var defaultAddress = results[0].formatted_address;
455
                                var city = '';
456
                                var country = '';
457
458
                                for (var i=0; i<results[0].address_components.length; i++) {
459
                                    if (results[0].address_components[i].types[0] == \"locality\") {
460
                                        //this is the object you are looking for City
461
                                        city = results[0].address_components[i];
462
                                    }
463
                                    /*if (results[j].address_components[i].types[0] == \"administrative_area_level_1\") {
464
                                        //this is the object you are looking for State
465
                                        region = results[0].address_components[i];
466
                                    }*/
467
                                    if (results[0].address_components[i].types[0] == \"country\") {
468
                                        //this is the object you are looking for
469
                                        country = results[0].address_components[i];
470
                                    }
471
                                }
472
473
                                if (city && city.long_name && country && country.long_name) {
474
                                    defaultAddress = city.long_name + ', ' + country.long_name;
475
                                }
476
                                $('#{$variable}').val(defaultAddress);
477
                                $('#{$variable}_coordinates').val(
478
                                    results[0].geometry.location.lat()+','+results[0].geometry.location.lng()
479
                                );
480
481
                                var infowindow = new google.maps.InfoWindow({
482
                                    content: '<b>' + $('#extra_{$variable}').val() + '</b>',
483
                                    size: new google.maps.Size(150, 50)
484
                                });
485
486
                                var marker = new google.maps.Marker({
487
                                    position: results[0].geometry.location,
488
                                    map: map_{$variable},
489
                                    title: $('#extra_{$variable}').val()
490
                                });
491
                                google.maps.event.addListener(marker, 'click', function() {
492
                                    infowindow.open(map_{$variable}, marker);
493
                                });
494
                            } else {
495
                                alert('".get_lang('NotFound')."');
496
                            }
497
                        } else {
498
                            alert('Geocode ".get_lang('Error').': '.get_lang('AddressField').' '.get_lang('NotFound')."');
499
                        }
500
                    });
501
                }
502
            }
503
            </script>";
504
505
        return $html;
506
    }
507
508
    /**
509
     * @param string $variable
510
     * @param string $text
511
     *
512
     * @return string
513
     */
514
    public static function getLocalizationInput($variable, $text)
515
    {
516
        $html = '
517
                <div class="form-group">
518
                    <label for="geolocalization_extra_'.$variable.'"
519
                        class="col-sm-2 control-label"></label>
520
                    <div class="col-sm-8">
521
                        <button class="btn btn-default"
522
                            id="geolocalization_extra_'.$variable.'"
523
                            name="geolocalization_extra_'.$variable.'"
524
                            type="submit">
525
                            <em class="fa fa-map-marker"></em> '.get_lang('SearchGeolocalization').'
526
                        </button>
527
                        <button class="btn btn-default" id="myLocation_extra_'.$variable.'"
528
                            name="myLocation_extra_'.$variable.'"
529
                            type="submit">
530
                            <em class="fa fa-crosshairs"></em> '.get_lang('MyLocation').'
531
                        </button>
532
                    </div>
533
                </div>
534
                <div class="form-group">
535
                    <label for="map_extra_'.$variable.'" class="col-sm-2 control-label">
536
                        '.$text.' - '.get_lang('Map').'
537
                    </label>
538
                    <div class="col-sm-8">
539
                        <div name="map_extra_'.$variable.'"
540
                            id="map_extra_'.$variable.'" style="width:100%; height:300px;">
541
                        </div>
542
                    </div>
543
                </div>
544
            ';
545
546
        return $html;
547
    }
548
549
    /**
550
     * @return int
551
     */
552
    public function get_count()
553
    {
554
        $em = Database::getManager();
555
        $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e');
556
        $query->select('count(e.id)');
557
        $query->where('e.extraFieldType = :type');
558
        $query->setParameter('type', $this->getExtraFieldType());
559
560
        return $query->getQuery()->getSingleScalarResult();
561
    }
562
563
    /**
564
     * @return int
565
     */
566
    public function getExtraFieldType()
567
    {
568
        return (int) $this->extraFieldType;
569
    }
570
571
    /**
572
     * @param string $sidx
573
     * @param string $sord
574
     * @param int    $start
575
     * @param int    $limit
576
     *
577
     * @return array
578
     */
579
    public function getAllGrid($sidx, $sord, $start, $limit)
580
    {
581
        switch ($sidx) {
582
            case 'field_order':
583
                $sidx = 'e.fieldOrder';
584
                break;
585
            case 'variable':
586
                $sidx = 'e.variable';
587
                break;
588
            case 'display_text':
589
                $sidx = 'e.displayText';
590
                break;
591
            case 'changeable':
592
                $sidx = 'e.changeable';
593
                break;
594
            case 'visible_to_self':
595
                $sidx = 'e.visibleToSelf';
596
                break;
597
            case 'visible_to_others':
598
                $sidx = 'e.visibleToOthers';
599
                break;
600
            case 'filter':
601
                $sidx = 'e.filter';
602
                break;
603
        }
604
        $em = Database::getManager();
605
        $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e');
606
        $query->select('e')
607
            ->where('e.extraFieldType = :type')
608
            ->setParameter('type', $this->getExtraFieldType())
609
            ->orderBy($sidx, $sord)
610
            ->setFirstResult($start)
611
            ->setMaxResults($limit);
612
613
        return $query->getQuery()->getArrayResult();
614
    }
615
616
    /**
617
     * Get all the field info for tags.
618
     *
619
     * @param string $variable
620
     *
621
     * @return array|bool
622
     */
623
    public function get_handler_field_info_by_tags($variable)
624
    {
625
        $variable = Database::escape_string($variable);
626
        $sql = "SELECT * FROM {$this->table}
627
                WHERE
628
                    variable = '$variable' AND
629
                    extra_field_type = $this->extraFieldType";
630
        $result = Database::query($sql);
631
        if (Database::num_rows($result)) {
632
            $row = Database::fetch_array($result, 'ASSOC');
633
                $row['display_text'] = $this->translateDisplayName(
634
                    $row['variable'],
635
                    $row['display_text']
636
                );
637
638
                // All the options of the field
639
            $sql = "SELECT * FROM $this->table_field_tag
640
                    WHERE field_id='".intval($row['id'])."'
641
                    ORDER BY id ASC";
642
                $result = Database::query($sql);
643
            while ($option = Database::fetch_array($result, 'ASSOC')) {
644
                    $row['options'][$option['id']] = $option;
645
                }
646
647
                return $row;
648
        } else {
649
            return false;
650
            }
651
        }
652
653
    /**
654
     * Translate the display text for a extra field.
655
     *
656
     * @param string $variable
657
     * @param string $defaultDisplayText
658
     *
659
     * @return string
660
     */
661
    public static function translateDisplayName($variable, $defaultDisplayText)
662
    {
663
        $camelCase = api_underscore_to_camel_case($variable);
664
665
        return isset($GLOBALS[$camelCase]) ? $GLOBALS[$camelCase] : $defaultDisplayText;
666
    }
667
668
    /**
669
     * @param int $fieldId
670
     *
671
     * @return array|bool
672
     */
673
    public function getFieldInfoByFieldId($fieldId)
674
    {
675
        $fieldId = (int) $fieldId;
676
        $sql = "SELECT * FROM {$this->table}
677
                WHERE
678
                    id = '$fieldId' AND
679
                    extra_field_type = $this->extraFieldType";
680
        $result = Database::query($sql);
681
        if (Database::num_rows($result)) {
682
            $row = Database::fetch_array($result, 'ASSOC');
683
684
            // All the options of the field
685
            $sql = "SELECT * FROM $this->table_field_options
686
                    WHERE field_id='".$fieldId."'
687
                    ORDER BY option_order ASC";
688
            $result = Database::query($sql);
689
            while ($option = Database::fetch_array($result)) {
690
                $row['options'][$option['id']] = $option;
691
            }
692
693
            return $row;
694
        } else {
695
            return false;
696
        }
697
    }
698
699
    /**
700
     * Add elements to a form.
701
     *
702
     * @param FormValidator $form                            The form object to which to attach this element
703
     * @param int           $itemId                          The item (course, user, session, etc) this extra_field is linked to
704
     * @param array         $exclude                         Variables of extra field to exclude
705
     * @param bool          $filter                          Whether to get only the fields with the "filter" flag set to 1 (true)
706
     *                                                       or not (false)
707
     * @param bool          $useTagAsSelect                  Whether to show tag fields as select drop-down or not
708
     * @param array         $showOnlyTheseFields             Limit the extra fields shown to just the list given here
709
     * @param array         $orderFields                     An array containing the names of the fields shown, in the right order
710
     * @param array         $extraData
711
     * @param bool          $orderDependingDefaults
712
     * @param bool          $adminPermissions
713
     * @param array         $separateExtraMultipleSelect
714
     * @param array         $customLabelsExtraMultipleSelect
715
     * @param bool          $addEmptyOptionSelects
716
     * @param array         $introductionTextList
717
     * @param array         $requiredFields
718
     * @param bool          $hideGeoLocalizationDetails
719
     *
720
     * @throws Exception
721
     *
722
     * @return array|bool If relevant, returns a one-element array with JS code to be added to the page HTML headers.
723
     *                    Returns false if the form object was not given
724
     */
725
    public function addElements(
726
        $form,
727
        $itemId = 0,
728
        $exclude = [],
729
        $filter = false,
730
        $useTagAsSelect = false,
731
        $showOnlyTheseFields = [],
732
        $orderFields = [],
733
        $extraData = [],
734
        $orderDependingDefaults = false,
735
        $adminPermissions = false,
736
        $separateExtraMultipleSelect = [],
737
        $customLabelsExtraMultipleSelect = [],
738
        $addEmptyOptionSelects = false,
739
        $introductionTextList = [],
740
        $requiredFields = [],
741
        $hideGeoLocalizationDetails = false,
742
        $help = false
743
    ) {
744
        if (empty($form)) {
745
            return false;
746
        }
747
748
        $itemId = (int) $itemId;
749
        $form->addHidden('item_id', $itemId);
750
        $extraData = false;
751
        if (!empty($itemId)) {
752
            $extraData = $this->get_handler_extra_data($itemId);
753
                if (!empty($showOnlyTheseFields)) {
754
                    $setData = [];
755
                    foreach ($showOnlyTheseFields as $variable) {
756
                        $extraName = 'extra_'.$variable;
757
                        if (in_array($extraName, array_keys($extraData))) {
758
                            $setData[$extraName] = $extraData[$extraName];
759
                        }
760
                    }
761
                    $form->setDefaults($setData);
762
                } else {
763
                    $form->setDefaults($extraData);
764
            }
765
        }
766
767
        $conditions = [];
768
        if ($filter) {
769
            $conditions = ['filter = ?' => 1];
770
        }
771
772
        $extraFields = $this->get_all($conditions, 'option_order');
773
        $extra = $this->set_extra_fields_in_form(
774
            $form,
775
            $extraData,
0 ignored issues
show
Bug introduced by
It seems like $extraData can also be of type false; however, parameter $extraData of ExtraField::set_extra_fields_in_form() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

775
            /** @scrutinizer ignore-type */ $extraData,
Loading history...
776
            $adminPermissions,
777
            $extraFields,
778
            $itemId,
779
            $exclude,
780
            $useTagAsSelect,
781
            $showOnlyTheseFields,
782
            $orderFields,
783
            $orderDependingDefaults,
784
            $separateExtraMultipleSelect,
785
            $customLabelsExtraMultipleSelect,
786
            $addEmptyOptionSelects,
787
            $introductionTextList,
788
            $hideGeoLocalizationDetails,
789
            $help
790
        );
791
792
        if (!empty($requiredFields)) {
793
            /** @var HTML_QuickForm_input $element */
794
            foreach ($form->getElements() as $element) {
795
                $name = str_replace('extra_', '', $element->getName());
796
                if (in_array($name, $requiredFields)) {
797
                    $form->setRequired($element);
798
                }
799
            }
800
        }
801
802
        return $extra;
803
    }
804
805
    /**
806
     * Return an array of all the extra fields available for this item.
807
     *
808
     * @param int $itemId (session_id, question_id, course id)
809
     *
810
     * @return array
811
     */
812
    public function get_handler_extra_data($itemId)
813
    {
814
        if (empty($itemId)) {
815
            return [];
816
        }
817
818
        $extra_data = [];
819
        $fields = $this->get_all();
820
        $field_values = new ExtraFieldValue($this->type);
821
822
        if (!empty($fields)) {
823
            foreach ($fields as $field) {
824
                $field_value = $field_values->get_values_by_handler_and_field_id(
825
                    $itemId,
826
                    $field['id']
827
                );
828
829
                if (self::FIELD_TYPE_TAG == $field['field_type']) {
830
                    $tags = UserManager::get_user_tags_to_string(
831
                        $itemId,
832
                        $field['id'],
833
                        false
834
                    );
835
                    $extra_data['extra_'.$field['variable']] = $tags;
836
837
                    continue;
838
                }
839
840
                if ($field_value) {
841
                    $variable = $field['variable'];
842
                    $field_value = $field_value['value'];
843
                    switch ($field['field_type']) {
844
                        case self::FIELD_TYPE_TAG:
845
                            $tags = UserManager::get_user_tags_to_string(
846
                                $itemId,
847
                                $field['id'],
848
                                false
849
                            );
850
851
                            $extra_data['extra_'.$field['variable']] = $tags;
852
                            break;
853
                        case self::FIELD_TYPE_DOUBLE_SELECT:
854
                        case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
855
                            $selected_options = explode('::', $field_value);
856
                            $firstOption = isset($selected_options[0]) ? $selected_options[0] : '';
857
                            $secondOption = isset($selected_options[1]) ? $selected_options[1] : '';
858
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $firstOption;
859
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable'].'_second'] = $secondOption;
860
861
                            break;
862
                        case self::FIELD_TYPE_SELECT_MULTIPLE:
863
                            $field_value = explode(';', $field_value);
864
                            $extra_data['extra_'.$field['variable']] = $field_value;
865
                            break;
866
                        case self::FIELD_TYPE_RADIO:
867
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $field_value;
868
                            break;
869
                        case self::FIELD_TYPE_TRIPLE_SELECT:
870
                            list($level1, $level2, $level3) = explode(';', $field_value);
871
872
                            $extra_data["extra_$variable"]["extra_$variable"] = $level1;
873
                            $extra_data["extra_$variable"]["extra_{$variable}_second"] = $level2;
874
                            $extra_data["extra_$variable"]["extra_{$variable}_third"] = $level3;
875
                            break;
876
                        default:
877
                            $extra_data['extra_'.$field['variable']] = $field_value;
878
                            break;
879
                    }
880
                } else {
881
                    // Set default values
882
                    if (isset($field['field_default_value']) &&
883
                        !empty($field['field_default_value'])
884
                    ) {
885
                        $extra_data['extra_'.$field['variable']] = $field['field_default_value'];
886
                    }
887
                }
888
            }
889
        }
890
891
        return $extra_data;
892
    }
893
894
    /**
895
     * Get an array of all the values from the extra_field and extra_field_options tables
896
     * based on the current object's type.
897
     *
898
     * @param array $conditions
899
     * @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...
900
     *
901
     * @return array
902
     */
903
    public function get_all($conditions = [], $order_field_options_by = null)
904
    {
905
        $conditions = Database::parse_conditions(['where' => $conditions]);
906
907
        if (empty($conditions)) {
908
            $conditions .= ' WHERE extra_field_type = '.$this->extraFieldType;
909
        } else {
910
            $conditions .= ' AND extra_field_type = '.$this->extraFieldType;
911
        }
912
913
        $sql = "SELECT * FROM $this->table
914
                $conditions
915
                ORDER BY field_order ASC
916
        ";
917
918
        $result = Database::query($sql);
919
        $extraFields = Database::store_result($result, 'ASSOC');
920
921
        $option = new ExtraFieldOption($this->type);
922
        if (!empty($extraFields)) {
923
            foreach ($extraFields as &$extraField) {
924
                $extraField['display_text'] = $this->translateDisplayName(
925
                    $extraField['variable'],
926
                    $extraField['display_text']
927
                );
928
                $extraField['options'] = $option->get_field_options_by_field(
929
                    $extraField['id'],
930
                    false,
931
                    $order_field_options_by
932
                );
933
            }
934
        }
935
936
        return $extraFields;
937
    }
938
939
    /**
940
     * Add an element that matches the given extra field to the given $form object.
941
     *
942
     * @param FormValidator $form                The form these fields are to be attached to
943
     * @param array         $extraData
944
     * @param bool          $adminPermissions    Whether the display is considered without edition limits (true) or not
945
     *                                           (false)
946
     * @param array         $extra
947
     * @param int           $itemId              The item (course, user, session, etc) this extra_field is attached to
948
     * @param array         $exclude             Extra fields to be skipped, by textual ID
949
     * @param bool          $useTagAsSelect      Whether to show tag fields as select drop-down or not
950
     * @param array         $showOnlyTheseFields Limit the extra fields shown to just the list given here
951
     * @param array         $orderFields         An array containing the names of the fields shown, in the right order
952
     *
953
     * @throws Exception
954
     *
955
     * @return array If relevant, returns a one-element array with JS code to be added to the page HTML headers
956
     */
957
    public function set_extra_fields_in_form(
958
        $form,
959
        $extraData,
960
        $adminPermissions = false,
961
        $extra = [],
962
        $itemId = null,
963
        $exclude = [],
964
        $useTagAsSelect = false,
965
        $showOnlyTheseFields = [],
966
        $orderFields = [],
967
        $orderDependingDefaults = false,
968
        $separateExtraMultipleSelect = [],
969
        $customLabelsExtraMultipleSelect = [],
970
        $addEmptyOptionSelects = false,
971
        $introductionTextList = [],
972
        $hideGeoLocalizationDetails = false,
973
        $help = false
974
    ) {
975
        $jquery_ready_content = null;
976
        if (!empty($extra)) {
977
            $newOrder = [];
978
            if (!empty($orderFields)) {
979
                foreach ($orderFields as $order) {
980
                    foreach ($extra as $field_details) {
981
                        if ($order == $field_details['variable']) {
982
                            $newOrder[] = $field_details;
983
                        }
984
                    }
985
                }
986
                $extra = $newOrder;
987
            }
988
989
            foreach ($extra as $field_details) {
990
                if (!empty($showOnlyTheseFields)) {
991
                    if (!in_array($field_details['variable'], $showOnlyTheseFields)) {
992
                        continue;
993
                    }
994
                }
995
996
                // Getting default value id if is set
997
                $defaultValueId = null;
998
                if (isset($field_details['options']) && !empty($field_details['options'])) {
999
                    $valueToFind = null;
1000
                    if (isset($field_details['field_default_value'])) {
1001
                        $valueToFind = $field_details['field_default_value'];
1002
                    }
1003
                    // If a value is found we override the default value
1004
                    if (isset($extraData['extra_'.$field_details['variable']])) {
1005
                        $valueToFind = $extraData['extra_'.$field_details['variable']];
1006
                    }
1007
1008
                    foreach ($field_details['options'] as $option) {
1009
                        if ($option['option_value'] == $valueToFind) {
1010
                            $defaultValueId = $option['id'];
1011
                        }
1012
                    }
1013
                }
1014
1015
                if (!$adminPermissions) {
1016
                    if (0 == $field_details['visible_to_self']) {
1017
                        continue;
1018
                    }
1019
1020
                    if (in_array($field_details['variable'], $exclude)) {
1021
                        continue;
1022
                    }
1023
                }
1024
1025
                if (!empty($introductionTextList) &&
1026
                    in_array($field_details['variable'], array_keys($introductionTextList))
1027
                ) {
1028
                    $form->addHtml($introductionTextList[$field_details['variable']]);
1029
                }
1030
1031
                $freezeElement = false;
1032
                if (!$adminPermissions) {
1033
                    $freezeElement = 0 == $field_details['visible_to_self'] || 0 == $field_details['changeable'];
1034
                }
1035
1036
                $translatedDisplayText = get_lang($field_details['display_text'], true);
1037
                $translatedDisplayHelpText = '';
1038
                if ($help) {
1039
                    $translatedDisplayHelpText .= get_lang($field_details['display_text'].'Help');
1040
                }
1041
                if (!empty($translatedDisplayText)) {
1042
                    if (!empty($translatedDisplayHelpText)) {
1043
                        // In this case, exceptionally, display_text is an array
1044
                        // which is then treated by display_form()
1045
                        $field_details['display_text'] = [$translatedDisplayText, $translatedDisplayHelpText];
1046
                    } else {
1047
                        // We have an helper text, use it
1048
                        $field_details['display_text'] = $translatedDisplayText;
1049
                    }
1050
                }
1051
1052
                switch ($field_details['field_type']) {
1053
                    case self::FIELD_TYPE_TEXT:
1054
                        $form->addElement(
1055
                            'text',
1056
                            'extra_'.$field_details['variable'],
1057
                            $field_details['display_text'],
1058
                            [
1059
                                'id' => 'extra_'.$field_details['variable'],
1060
                            ]
1061
                        );
1062
                        $form->applyFilter(
1063
                            'extra_'.$field_details['variable'],
1064
                            'stripslashes'
1065
                        );
1066
                        $form->applyFilter(
1067
                            'extra_'.$field_details['variable'],
1068
                            'trim'
1069
                        );
1070
                        if ($freezeElement) {
1071
                            $form->freeze('extra_'.$field_details['variable']);
1072
                        }
1073
                        break;
1074
                    case self::FIELD_TYPE_TEXTAREA:
1075
                        $form->addHtmlEditor(
1076
                            'extra_'.$field_details['variable'],
1077
                            $field_details['display_text'],
1078
                            false,
1079
                            false,
1080
                            [
1081
                                'ToolbarSet' => 'Profile',
1082
                                'Width' => '100%',
1083
                                'Height' => '130',
1084
                                'id' => 'extra_'.$field_details['variable'],
1085
                            ]
1086
                        );
1087
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1088
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1089
                        if ($freezeElement) {
1090
                            $form->freeze('extra_'.$field_details['variable']);
1091
                        }
1092
                        break;
1093
                    case self::FIELD_TYPE_RADIO:
1094
                        $group = [];
1095
                        if (isset($field_details['options']) &&
1096
                            !empty($field_details['options'])
1097
                        ) {
1098
                            foreach ($field_details['options'] as $option_details) {
1099
                                $options[$option_details['option_value']] = $option_details['display_text'];
1100
                                $group[] = $form->createElement(
1101
                                    'radio',
1102
                                    'extra_'.$field_details['variable'],
1103
                                    $option_details['option_value'],
1104
                                    $option_details['display_text'].'<br />',
1105
                                    $option_details['option_value']
1106
                                );
1107
                            }
1108
                        }
1109
                        $form->addGroup(
1110
                            $group,
1111
                            'extra_'.$field_details['variable'],
1112
                            $field_details['display_text']
1113
                        );
1114
                        if ($freezeElement) {
1115
                            $form->freeze('extra_'.$field_details['variable']);
1116
                        }
1117
                        break;
1118
                    case self::FIELD_TYPE_CHECKBOX:
1119
                        $group = [];
1120
                        if (isset($field_details['options']) &&
1121
                            !empty($field_details['options'])
1122
                        ) {
1123
                            foreach ($field_details['options'] as $option_details) {
1124
                                $options[$option_details['option_value']] = $option_details['display_text'];
1125
                                $group[] = $form->createElement(
1126
                                    'checkbox',
1127
                                    'extra_'.$field_details['variable'],
1128
                                    $option_details['option_value'],
1129
                                    $option_details['display_text'].'<br />',
1130
                                    $option_details['option_value']
1131
                                );
1132
                            }
1133
                        } else {
1134
                            $fieldVariable = "extra_{$field_details['variable']}";
1135
                            $checkboxAttributes = [];
1136
                            if (is_array($extraData) &&
1137
                                array_key_exists($fieldVariable, $extraData)
1138
                            ) {
1139
                                if (!empty($extraData[$fieldVariable])) {
1140
                                    $checkboxAttributes['checked'] = 1;
1141
                                }
1142
                            }
1143
1144
                            if (empty($checkboxAttributes) &&
1145
                                isset($field_details['default_value']) && empty($extraData)) {
1146
                                if (1 == $field_details['default_value']) {
1147
                                    $checkboxAttributes['checked'] = 1;
1148
                                }
1149
                            }
1150
1151
                            // We assume that is a switch on/off with 1 and 0 as values
1152
                            $group[] = $form->createElement(
1153
                                'checkbox',
1154
                                'extra_'.$field_details['variable'],
1155
                                null,
1156
                                //$field_details['display_text'].'<br />',
1157
                                get_lang('Yes'),
1158
                                $checkboxAttributes
1159
                            );
1160
                        }
1161
1162
                        $form->addGroup(
1163
                            $group,
1164
                            'extra_'.$field_details['variable'],
1165
                            $field_details['display_text']
1166
                        );
1167
                        if ($freezeElement) {
1168
                            $form->freeze('extra_'.$field_details['variable']);
1169
                        }
1170
                        break;
1171
                    case self::FIELD_TYPE_SELECT:
1172
                        $this->addSelectElement($form, $field_details, $defaultValueId, $freezeElement);
1173
                        break;
1174
                    case self::FIELD_TYPE_SELECT_MULTIPLE:
1175
                        $options = [];
1176
                        if (empty($defaultValueId)) {
1177
                            $options[''] = get_lang('Please select an option');
1178
                        }
1179
                        foreach ($field_details['options'] as $optionDetails) {
1180
                            $options[$optionDetails['option_value']] = $optionDetails['display_text'];
1181
                        }
1182
                        $form->addElement(
1183
                            'select',
1184
                            'extra_'.$field_details['variable'],
1185
                            $field_details['display_text'],
1186
                            $options,
1187
                            [
1188
                                'multiple' => 'multiple',
1189
                                'id' => 'extra_'.$field_details['variable'],
1190
                            ]
1191
                        );
1192
                        if ($freezeElement) {
1193
                            $form->freeze('extra_'.$field_details['variable']);
1194
                        }
1195
                        break;
1196
                    case self::FIELD_TYPE_DATE:
1197
                        $form->addDatePicker('extra_'.$field_details['variable'], $field_details['display_text']);
1198
                        if ($freezeElement) {
1199
                            $form->freeze('extra_'.$field_details['variable']);
1200
                        }
1201
                        break;
1202
                    case self::FIELD_TYPE_DATETIME:
1203
                        $form->addDateTimePicker(
1204
                            'extra_'.$field_details['variable'],
1205
                            $field_details['display_text']
1206
                        );
1207
1208
                        $defaults['extra_'.$field_details['variable']] = api_get_local_time();
1209
                        if (!isset($form->_defaultValues['extra_'.$field_details['variable']])) {
1210
                            $form->setDefaults($defaults);
1211
                        }
1212
                        if ($freezeElement) {
1213
                            $form->freeze('extra_'.$field_details['variable']);
1214
                        }
1215
                        break;
1216
                    case self::FIELD_TYPE_DOUBLE_SELECT:
1217
                        $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

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

1886
        /** @scrutinizer ignore-call */ 
1887
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1887
        $params = $this->clean_parameters($params);
1888
        $params['extra_field_type'] = $this->extraFieldType;
1889
1890
        if ($fieldInfo) {
1891
            return $fieldInfo['id'];
1892
        } else {
1893
            $id = parent::save($params, $show_query);
1894
            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...
1895
                $fieldOption = new ExtraFieldOption($this->type);
1896
                $params['field_id'] = $id;
1897
                $fieldOption->save($params);
1898
            }
1899
1900
            return $id;
1901
        }
1902
    }
1903
1904
    /**
1905
     * @param string $variable
1906
     *
1907
     * @return array|bool
1908
     */
1909
    public function get_handler_field_info_by_field_variable($variable)
1910
    {
1911
        $variable = Database::escape_string($variable);
1912
        $sql = "SELECT * FROM {$this->table}
1913
                WHERE
1914
                    variable = '$variable' AND
1915
                    extra_field_type = $this->extraFieldType";
1916
        $result = Database::query($sql);
1917
        if (Database::num_rows($result)) {
1918
            $row = Database::fetch_array($result, 'ASSOC');
1919
            if ($row) {
1920
                $row['display_text'] = $this->translateDisplayName(
1921
                    $row['variable'],
1922
                    $row['display_text']
1923
                );
1924
1925
                // All the options of the field
1926
                $sql = "SELECT * FROM $this->table_field_options
1927
                    WHERE field_id='".intval($row['id'])."'
1928
                    ORDER BY option_order ASC";
1929
                $result = Database::query($sql);
1930
                while ($option = Database::fetch_array($result)) {
1931
                    $row['options'][$option['id']] = $option;
1932
                }
1933
1934
                return $row;
1935
            }
1936
        }
1937
1938
        return false;
1939
    }
1940
1941
    /**
1942
     * @param array $params
1943
     *
1944
     * @return array
1945
     */
1946
    public function clean_parameters($params)
1947
    {
1948
        if (!isset($params['variable']) || empty($params['variable'])) {
1949
            $params['variable'] = $params['display_text'];
1950
        }
1951
1952
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
1953
1954
        if (!isset($params['field_order'])) {
1955
            $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

1955
            /** @scrutinizer ignore-call */ 
1956
            $max_order = self::get_max_field_order();
Loading history...
1956
            $params['field_order'] = $max_order;
1957
        } else {
1958
            $params['field_order'] = (int) $params['field_order'];
1959
        }
1960
1961
        return $params;
1962
    }
1963
1964
    /**
1965
     * @return int
1966
     */
1967
    public function get_max_field_order()
1968
    {
1969
        $sql = "SELECT MAX(field_order)
1970
                FROM {$this->table}
1971
                WHERE
1972
                    extra_field_type = '.$this->extraFieldType.'";
1973
        $res = Database::query($sql);
1974
1975
        $order = 0;
1976
        if (Database::num_rows($res) > 0) {
1977
            $row = Database::fetch_row($res);
1978
            $order = $row[0] + 1;
1979
        }
1980
1981
        return $order;
1982
    }
1983
1984
    /**
1985
     * {@inheritdoc}
1986
     */
1987
    public function update($params, $showQuery = false)
1988
    {
1989
        $params = $this->clean_parameters($params);
1990
        if (isset($params['id'])) {
1991
            $fieldOption = new ExtraFieldOption($this->type);
1992
            $params['field_id'] = $params['id'];
1993
            if (empty($params['field_type'])) {
1994
                $params['field_type'] = $this->type;
1995
            }
1996
            $fieldOption->save($params, $showQuery);
1997
        }
1998
1999
        return parent::update($params, $showQuery);
2000
    }
2001
2002
    /**
2003
     * @param $id
2004
     *
2005
     * @return bool
2006
     */
2007
    public function delete($id)
2008
    {
2009
        $em = Database::getManager();
2010
        $items = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy(['field' => $id]);
2011
        if ($items) {
2012
            foreach ($items as $item) {
2013
                $em->remove($item);
2014
            }
2015
            $em->flush();
2016
        }
2017
        $field_option = new ExtraFieldOption($this->type);
2018
        $field_option->delete_all_options_by_field_id($id);
2019
2020
        $session_field_values = new ExtraFieldValue($this->type);
2021
        $session_field_values->delete_all_values_by_field_id($id);
2022
2023
        return parent::delete($id);
2024
    }
2025
2026
    /**
2027
     * @param $breadcrumb
2028
     * @param $action
2029
     */
2030
    public function setupBreadcrumb(&$breadcrumb, $action)
2031
    {
2032
        if ('add' === $action) {
2033
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2034
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Add')];
2035
        } elseif ('edit' === $action) {
2036
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
2037
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')];
2038
        } else {
2039
            $breadcrumb[] = ['url' => '#', 'name' => $this->pageName];
2040
        }
2041
    }
2042
2043
    /**
2044
     * Displays the title + grid.
2045
     */
2046
    public function display()
2047
    {
2048
        // action links
2049
        echo '<div class="actions">';
2050
        echo '<a href="../admin/index.php">';
2051
        echo Display::return_icon(
2052
            'back.png',
2053
            get_lang('Back to').' '.get_lang('Administration'),
2054
            '',
2055
            ICON_SIZE_MEDIUM
2056
        );
2057
        echo '</a>';
2058
        echo '<a href="'.api_get_self().'?action=add&type='.$this->type.'">';
2059
        echo Display::return_icon(
2060
            'add_user_fields.png',
2061
            get_lang('Add'),
2062
            '',
2063
            ICON_SIZE_MEDIUM
2064
        );
2065
        echo '</a>';
2066
        echo '</div>';
2067
        echo Display::grid_html($this->type.'_fields');
2068
    }
2069
2070
    /**
2071
     * @return array
2072
     */
2073
    public function getJqgridColumnNames()
2074
    {
2075
        return [
2076
            get_lang('Name'),
2077
            get_lang('Field label'),
2078
            get_lang('Type'),
2079
            get_lang('Can change'),
2080
            get_lang('Visible to self'),
2081
            get_lang('Visible to others'),
2082
            get_lang('Filter'),
2083
            get_lang('Order'),
2084
            get_lang('Detail'),
2085
        ];
2086
    }
2087
2088
    /**
2089
     * @return array
2090
     */
2091
    public function getJqgridColumnModel()
2092
    {
2093
        return [
2094
            [
2095
                'name' => 'display_text',
2096
                'index' => 'display_text',
2097
                'width' => '140',
2098
                'align' => 'left',
2099
            ],
2100
            [
2101
                'name' => 'variable',
2102
                'index' => 'variable',
2103
                'width' => '90',
2104
                'align' => 'left',
2105
                'sortable' => 'true',
2106
            ],
2107
            [
2108
                'name' => 'field_type',
2109
                'index' => 'field_type',
2110
                'width' => '70',
2111
                'align' => 'left',
2112
                'sortable' => 'true',
2113
            ],
2114
            [
2115
                'name' => 'changeable',
2116
                'index' => 'changeable',
2117
                'width' => '35',
2118
                'align' => 'left',
2119
                'sortable' => 'true',
2120
            ],
2121
            [
2122
                'name' => 'visible_to_self',
2123
                'index' => 'visible_to_self',
2124
                'width' => '45',
2125
                'align' => 'left',
2126
                'sortable' => 'true',
2127
            ],
2128
            [
2129
                'name' => 'visible_to_others',
2130
                'index' => 'visible_to_others',
2131
                'width' => '35',
2132
                'align' => 'left',
2133
                'sortable' => 'true',
2134
            ],
2135
            [
2136
                'name' => 'filter',
2137
                'index' => 'filter',
2138
                'width' => '30',
2139
                'align' => 'left',
2140
                'sortable' => 'true',
2141
            ],
2142
            [
2143
                'name' => 'field_order',
2144
                'index' => 'field_order',
2145
                'width' => '25',
2146
                'align' => 'left',
2147
                'sortable' => 'true',
2148
            ],
2149
            [
2150
                'name' => 'actions',
2151
                'index' => 'actions',
2152
                'width' => '40',
2153
                'align' => 'left',
2154
                'formatter' => 'action_formatter',
2155
                'sortable' => 'false',
2156
            ],
2157
        ];
2158
    }
2159
2160
    /**
2161
     * @param string $url
2162
     * @param string $action
2163
     *
2164
     * @return FormValidator
2165
     */
2166
    public function return_form($url, $action)
2167
    {
2168
        $form = new FormValidator($this->type.'_field', 'post', $url);
2169
2170
        $form->addElement('hidden', 'type', $this->type);
2171
        $id = isset($_GET['id']) ? (int) $_GET['id'] : null;
2172
        $form->addElement('hidden', 'id', $id);
2173
2174
        // Setting the form elements
2175
        $header = get_lang('Add');
2176
        $defaults = [];
2177
2178
        if ('edit' === $action) {
2179
            $header = get_lang('Edit');
2180
            // Setting the defaults
2181
            $defaults = $this->get($id, false);
2182
        }
2183
2184
        $form->addElement('header', $header);
2185
2186
        if ('edit' === $action) {
2187
            $translateUrl = api_get_path(WEB_CODE_PATH).'extrafield/translate.php?'
2188
                .http_build_query(['extra_field' => $id]);
2189
            $translateButton = Display::toolbarButton(get_lang('Translate this term'), $translateUrl, 'language', 'link');
2190
2191
            $form->addText(
2192
                'display_text',
2193
                [get_lang('Name'), $translateButton]
2194
            );
2195
        } else {
2196
            $form->addElement('text', 'display_text', get_lang('Name'));
2197
        }
2198
2199
        $form->addHtmlEditor('description', get_lang('Description'), false);
2200
2201
        // Field type
2202
        $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

2202
        /** @scrutinizer ignore-call */ 
2203
        $types = self::get_field_types();
Loading history...
2203
2204
        $form->addElement(
2205
            'select',
2206
            'field_type',
2207
            get_lang('Field type'),
2208
            $types,
2209
            ['id' => 'field_type']
2210
        );
2211
        $form->addElement('label', get_lang('Example'), '<div id="example">-</div>');
2212
        $form->addElement('text', 'variable', get_lang('Field label'), ['class' => 'span5']);
2213
        $form->addElement(
2214
            'text',
2215
            'field_options',
2216
            get_lang('Possible values'),
2217
            ['id' => 'field_options', 'class' => 'span6']
2218
        );
2219
2220
        $fieldWithOptions = [
2221
            self::FIELD_TYPE_RADIO,
2222
            self::FIELD_TYPE_SELECT_MULTIPLE,
2223
            self::FIELD_TYPE_SELECT,
2224
            self::FIELD_TYPE_TAG,
2225
            self::FIELD_TYPE_DOUBLE_SELECT,
2226
            self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD,
2227
            self::FIELD_TYPE_TRIPLE_SELECT,
2228
        ];
2229
2230
        if ('edit' == $action) {
2231
            if (in_array($defaults['field_type'], $fieldWithOptions)) {
2232
                $url = Display::url(
2233
                    get_lang('Edit extra field options'),
2234
                    'extra_field_options.php?type='.$this->type.'&field_id='.$id
2235
                );
2236
                $form->addElement('label', null, $url);
2237
2238
                if (self::FIELD_TYPE_SELECT == $defaults['field_type']) {
2239
                    $urlWorkFlow = Display::url(
2240
                        get_lang('Edit this field\'s workflow'),
2241
                        'extra_field_workflow.php?type='.$this->type.'&field_id='.$id
2242
                    );
2243
                    $form->addElement('label', null, $urlWorkFlow);
2244
                }
2245
2246
                $form->freeze('field_options');
2247
            }
2248
        }
2249
        $form->addElement(
2250
            'text',
2251
            'default_value',
2252
            get_lang('Default value'),
2253
            ['id' => 'default_value']
2254
        );
2255
2256
        $group = [];
2257
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('Yes'), 1);
2258
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('No'), 0);
2259
        $form->addGroup($group, '', get_lang('Visible to self'), null, false);
2260
2261
        $group = [];
2262
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('Yes'), 1);
2263
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('No'), 0);
2264
        $form->addGroup($group, '', get_lang('Visible to others'), null, false);
2265
2266
        $group = [];
2267
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('Yes'), 1);
2268
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('No'), 0);
2269
        $form->addGroup($group, '', get_lang('Can change'), null, false);
2270
2271
        $group = [];
2272
        $group[] = $form->createElement('radio', 'filter', null, get_lang('Yes'), 1);
2273
        $group[] = $form->createElement('radio', 'filter', null, get_lang('No'), 0);
2274
        $form->addGroup($group, '', get_lang('Filter'), null, false);
2275
2276
        /* Enable this when field_loggeable is introduced as a table field (2.0)
2277
        $group   = array();
2278
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('Yes'), 1);
2279
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('No'), 0);
2280
        $form->addGroup($group, '', get_lang('Field changes should be logged'), '', false);
2281
        */
2282
2283
        $form->addElement('text', 'field_order', get_lang('Order'));
2284
2285
        if ('edit' == $action) {
2286
            $option = new ExtraFieldOption($this->type);
2287
            $defaults['field_options'] = $option->get_field_options_by_field_to_string($id);
2288
            $form->addButtonUpdate(get_lang('Edit'));
2289
        } else {
2290
            $defaults['visible_to_self'] = 0;
2291
            $defaults['visible_to_others'] = 0;
2292
            $defaults['changeable'] = 0;
2293
            $defaults['filter'] = 0;
2294
            $form->addButtonCreate(get_lang('Add'));
2295
        }
2296
2297
        /*if (!empty($defaults['created_at'])) {
2298
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
2299
        }
2300
        if (!empty($defaults['updated_at'])) {
2301
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
2302
        }*/
2303
        $form->setDefaults($defaults);
2304
2305
        // Setting the rules
2306
        $form->addRule('display_text', get_lang('Required field'), 'required');
2307
        $form->addRule('field_type', get_lang('Required field'), 'required');
2308
2309
        return $form;
2310
    }
2311
2312
    /**
2313
     * Gets an element.
2314
     *
2315
     * @param int  $id
2316
     * @param bool $translateDisplayText Optional
2317
     *
2318
     * @return array
2319
     */
2320
    public function get($id, $translateDisplayText = true)
2321
    {
2322
        $info = parent::get($id);
2323
2324
        if ($translateDisplayText) {
2325
            $info['display_text'] = self::translateDisplayName($info['variable'], $info['display_text']);
2326
        }
2327
2328
        return $info;
2329
    }
2330
2331
    /**
2332
     * @param $token
2333
     *
2334
     * @return string
2335
     */
2336
    public function getJqgridActionLinks($token)
2337
    {
2338
        //With this function we can add actions to the jgrid (edit, delete, etc)
2339
        $editIcon = Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL);
2340
        $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2341
        $confirmMessage = addslashes(
2342
            api_htmlentities(get_lang("Please confirm your choice"), ENT_QUOTES)
2343
        );
2344
2345
        $editButton = <<<JAVASCRIPT
2346
            <a href="?action=edit&type={$this->type}&id=' + options.rowId + '" class="btn btn-link btn-xs">\
2347
                $editIcon\
2348
            </a>
2349
JAVASCRIPT;
2350
        $deleteButton = <<<JAVASCRIPT
2351
            <a \
2352
                    onclick="if (!confirm(\'$confirmMessage\')) {return false;}" \
2353
                href="?sec_token=$token&type={$this->type}&id=' + options.rowId + '&action=delete" \
2354
                class="btn btn-link btn-xs">\
2355
                $deleteIcon\
2356
            </a>
2357
JAVASCRIPT;
2358
2359
        return "function action_formatter(cellvalue, options, rowObject) {        
2360
            return '$editButton $deleteButton';
2361
        }";
2362
    }
2363
2364
    /**
2365
     * @param array $columns
2366
     * @param array $column_model
2367
     * @param array $extraFields
2368
     *
2369
     * @return array
2370
     */
2371
    public function getRules(&$columns, &$column_model, $extraFields = [], $checkExtraFieldExistence = false)
2372
    {
2373
        $fields = $this->get_all(
2374
            [
2375
                'visible_to_self = ? AND filter = ?' => [1, 1],
2376
            ],
2377
            'display_text'
2378
        );
2379
        $extraFieldOption = new ExtraFieldOption($this->type);
2380
2381
        $rules = [];
2382
        if (!empty($fields)) {
2383
            foreach ($fields as $field) {
2384
                $search_options = [];
2385
                $type = 'text';
2386
                if (in_array($field['field_type'], [self::FIELD_TYPE_SELECT, self::FIELD_TYPE_DOUBLE_SELECT])) {
2387
                    $type = 'select';
2388
                    $search_options['sopt'] = ['eq', 'ne']; //equal not equal
2389
                } else {
2390
                    $search_options['sopt'] = ['cn', 'nc']; //contains not contains
2391
                }
2392
2393
                $search_options['searchhidden'] = 'true';
2394
                $search_options['defaultValue'] = isset($search_options['field_default_value'])
2395
                    ? $search_options['field_default_value']
2396
                    : null;
2397
2398
                if (self::FIELD_TYPE_DOUBLE_SELECT == $field['field_type']) {
2399
                    // Add 2 selects
2400
                    $options = $extraFieldOption->get_field_options_by_field($field['id']);
2401
                    $options = self::extra_field_double_select_convert_array_to_ordered_array($options);
2402
2403
                    $first_options = [];
2404
                    if (!empty($options)) {
2405
                        foreach ($options as $option) {
2406
                            foreach ($option as $sub_option) {
2407
                                if (0 == $sub_option['option_value']) {
2408
                                    $first_options[] = $sub_option['field_id'].'#'.$sub_option['id'].':'
2409
                                        .$sub_option['display_text'];
2410
                                }
2411
                            }
2412
                        }
2413
                    }
2414
2415
                    $search_options['value'] = implode(';', $first_options);
2416
                    $search_options['dataInit'] = 'fill_second_select';
2417
2418
                    // First
2419
                    $column_model[] = [
2420
                        'name' => 'extra_'.$field['variable'],
2421
                        'index' => 'extra_'.$field['variable'],
2422
                        'width' => '100',
2423
                        'hidden' => 'true',
2424
                        'search' => 'true',
2425
                        'stype' => 'select',
2426
                        'searchoptions' => $search_options,
2427
                    ];
2428
                    $columns[] = $field['display_text'].' (1)';
2429
                    $rules[] = [
2430
                        'field' => 'extra_'.$field['variable'],
2431
                        'op' => 'cn',
2432
                    ];
2433
2434
                    // Second
2435
                    $search_options['value'] = $field['id'].':';
2436
                    $search_options['dataInit'] = 'register_second_select';
2437
2438
                    $column_model[] = [
2439
                        'name' => 'extra_'.$field['variable'].'_second',
2440
                        'index' => 'extra_'.$field['variable'].'_second',
2441
                        'width' => '100',
2442
                        'hidden' => 'true',
2443
                        'search' => 'true',
2444
                        'stype' => 'select',
2445
                        'searchoptions' => $search_options,
2446
                    ];
2447
                    $columns[] = $field['display_text'].' (2)';
2448
                    $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn'];
2449
                    continue;
2450
                } else {
2451
                    $search_options['value'] = $extraFieldOption->getFieldOptionsToString(
2452
                        $field['id'],
2453
                        false,
2454
                        'display_text'
2455
                    );
2456
                }
2457
                $column_model[] = [
2458
                    'name' => 'extra_'.$field['variable'],
2459
                    'index' => 'extra_'.$field['variable'],
2460
                    'width' => '100',
2461
                    'hidden' => 'true',
2462
                    'search' => 'true',
2463
                    'stype' => $type,
2464
                    'searchoptions' => $search_options,
2465
                ];
2466
                $columns[] = $field['display_text'];
2467
                $rules[] = [
2468
                    'field' => 'extra_'.$field['variable'],
2469
                    'op' => 'cn',
2470
                    'data' => '',
2471
                ];
2472
            }
2473
        }
2474
2475
        return $rules;
2476
    }
2477
2478
    public function processExtraFieldSearch($values, $form, $alias, $condition = 'OR')
2479
    {
2480
        // Parse params.
2481
        $fields = [];
2482
        foreach ($values as $key => $value) {
2483
            if (substr($key, 0, 6) !== 'extra_' && substr($key, 0, 7) !== '_extra_') {
2484
                continue;
2485
            }
2486
            if (!empty($value)) {
2487
                $fields[$key] = $value;
2488
            }
2489
        }
2490
2491
        $extraFieldsAll = $this->get_all(
2492
            ['visible_to_self = ? AND filter = ?' => [1, 1]],
2493
            'option_order'
2494
        );
2495
        $extraFieldsType = array_column($extraFieldsAll, 'field_type', 'variable');
2496
        $extraFields = array_column($extraFieldsAll, 'variable');
2497
        $filter = new stdClass();
2498
        $defaults = [];
2499
        foreach ($fields as $variable => $col) {
2500
            $variableNoExtra = str_replace('extra_', '', $variable);
2501
            if (isset($values[$variable]) && !empty($values[$variable]) &&
2502
                in_array($variableNoExtra, $extraFields)
2503
            ) {
2504
                $rule = new stdClass();
2505
                $rule->field = $variable;
2506
                $rule->op = 'in';
2507
                $data = $col;
2508
                if (is_array($data) && array_key_exists($variable, $data)) {
2509
                    $data = $col;
2510
                }
2511
                $rule->data = $data;
2512
                $filter->rules[] = $rule;
2513
                $filter->groupOp = 'AND';
2514
2515
                if ($extraFieldsType[$variableNoExtra] == ExtraField::FIELD_TYPE_TAG) {
2516
                    $tagElement = $form->getElement($variable);
2517
                    $tags = [];
2518
                    foreach ($values[$variable] as $tag) {
2519
                        $tag = Security::remove_XSS($tag);
2520
                        $tags[] = $tag;
2521
                        $tagElement->addOption(
2522
                            $tag,
2523
                            $tag
2524
                        );
2525
                    }
2526
                    $defaults[$variable] = $tags;
2527
                } else {
2528
                    if (is_array($data)) {
2529
                        $defaults[$variable] = array_map(['Security', 'remove_XSS'], $data);
2530
                    } else {
2531
                        $defaults[$variable] = Security::remove_XSS($data);
2532
                    }
2533
                }
2534
            }
2535
        }
2536
2537
        $result = $this->getExtraFieldRules($filter, 'extra_', $condition);
2538
2539
        $conditionArray = $result['condition_array'];
2540
2541
        $whereCondition = '';
2542
        $extraCondition = '';
2543
        if (!empty($conditionArray)) {
2544
            $extraCondition = ' ( ';
2545
            $extraCondition .= implode(' AND ', $conditionArray);
2546
            $extraCondition .= ' ) ';
2547
        }
2548
        $whereCondition .= $extraCondition;
2549
        $conditions = $this->parseConditions(
2550
            [
2551
                'where' => $whereCondition,
2552
                'extra' => $result['extra_fields'],
2553
            ],
2554
            $alias
2555
        );
2556
2557
        return ['condition' => $conditions, 'fields' => $fields, 'defaults' => $defaults];
2558
    }
2559
2560
    /**
2561
     * @param $filters
2562
     * @param string $stringToSearch
2563
     *
2564
     * @return array
2565
     */
2566
    public function getExtraFieldRules($filters, $stringToSearch = 'extra_', $condition = 'OR')
2567
    {
2568
        $extra_fields = [];
2569
        $condition_array = [];
2570
2571
        // Getting double select if exists
2572
        $double_select = [];
2573
        if (is_object($filters) &&
2574
            property_exists($filters, 'rules') &&
2575
            is_array($filters->rules) &&
2576
            !empty($filters->rules)
2577
        ) {
2578
        foreach ($filters->rules as $rule) {
2579
            if (empty($rule)) {
2580
                continue;
2581
            }
2582
            if (false === strpos($rule->field, '_second')) {
2583
            } else {
2584
                $my_field = str_replace('_second', '', $rule->field);
2585
                $double_select[$my_field] = $rule->data;
2586
            }
2587
        }
2588
2589
        foreach ($filters->rules as $rule) {
2590
            if (empty($rule)) {
2591
                continue;
2592
            }
2593
            if (false === strpos($rule->field, $stringToSearch)) {
2594
                // normal fields
2595
                $field = $rule->field;
2596
                if (isset($rule->data) && is_string($rule->data) && -1 != $rule->data) {
2597
                    $condition_array[] = $this->get_where_clause($field, $rule->op, $rule->data);
2598
                }
2599
            } else {
2600
                // Extra fields
2601
                if (false === strpos($rule->field, '_second')) {
2602
                    //No _second
2603
                    $original_field = str_replace($stringToSearch, '', $rule->field);
2604
                    $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2605
2606
                    if (self::FIELD_TYPE_DOUBLE_SELECT == $field_option['field_type']) {
2607
                        if (isset($double_select[$rule->field])) {
2608
                            $data = explode('#', $rule->data);
2609
                            $rule->data = $data[1].'::'.$double_select[$rule->field];
2610
                        } else {
2611
                            // only was sent 1 select
2612
                            if (is_string($rule->data)) {
2613
                                $data = explode('#', $rule->data);
2614
                                $rule->data = $data[1];
2615
                            }
2616
                        }
2617
2618
                        if (!isset($rule->data)) {
2619
                            $condition_array[] = ' ('
2620
                                .$this->get_where_clause($rule->field, $rule->op, $rule->data)
2621
                                .') ';
2622
                            $extra_fields[] = ['field' => $rule->field, 'id' => $field_option['id']];
2623
                        }
2624
                    } else {
2625
                        if (isset($rule->data)) {
2626
                            if (isset($rule->data) && is_int($rule->data) && -1 == $rule->data) {
2627
                                continue;
2628
                            }
2629
                            /*var_dump($rule->data);
2630
                            foreach ($rule->data as $option) {
2631
                            }*/
2632
                            $where = $this->get_where_clause($rule->field, $rule->op, $rule->data, 'OR');
2633
                            $condition_array[] = " ( $where ) ";
2634
2635
                            $extra_fields[] = [
2636
                                'field' => $rule->field,
2637
                                'id' => $field_option['id'],
2638
                                'data' => $rule->data,
2639
                            ];
2640
                        }
2641
                    }
2642
                } else {
2643
                    $my_field = str_replace('_second', '', $rule->field);
2644
                    $original_field = str_replace($stringToSearch, '', $my_field);
2645
                    $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2646
                    $extra_fields[] = [
2647
                        'field' => $rule->field,
2648
                        'id' => $field_option['id'],
2649
                    ];
2650
                }
2651
            }
2652
        }
2653
        }
2654
2655
        /*var_dump(
2656
            [
2657
                'extra_fields' => $extra_fields,
2658
                'condition_array' => $condition_array,
2659
            ]
2660
        );*/
2661
2662
        return [
2663
            'extra_fields' => $extra_fields,
2664
            'condition_array' => $condition_array,
2665
        ];
2666
    }
2667
2668
    /**
2669
     * @param $col
2670
     * @param $oper
2671
     * @param $val
2672
     * @param $conditionBetweenOptions
2673
     *
2674
     * @return string
2675
     */
2676
    public function get_where_clause($col, $oper, $val, $conditionBetweenOptions = 'OR')
2677
    {
2678
        if (empty($col)) {
2679
            return '';
2680
        }
2681
        $conditionBetweenOptions = in_array($conditionBetweenOptions, ['OR', 'AND']) ? $conditionBetweenOptions : 'OR';
2682
        if ('bw' === $oper || 'bn' === $oper) {
2683
            $val .= '%';
2684
        }
2685
        if ('ew' === $oper || 'en' === $oper) {
2686
            $val = '%'.$val;
2687
        }
2688
        if ('cn' === $oper || 'nc' === $oper || 'in' === $oper || 'ni' === $oper) {
2689
            if (is_array($val)) {
2690
                $result = '"%'.implode(';', $val).'%"';
2691
                foreach ($val as $item) {
2692
                    $item = trim($item);
2693
                    $result .= ' '.$conditionBetweenOptions.' '.$col.' LIKE "%'.$item.'%"';
2694
                }
2695
                $val = $result;
2696
2697
                return " $col {$this->ops[$oper]} $val ";
2698
            } else {
2699
                if (is_string($val)) {
2700
                    $val = '%'.$val.'%';
2701
                } else {
2702
                    $val = '';
2703
                }
2704
            }
2705
        }
2706
        $val = \Database::escape_string($val);
2707
2708
        return " $col {$this->ops[$oper]} '$val' ";
2709
    }
2710
2711
    /**
2712
     * @param array  $options
2713
     * @param string $alias
2714
     *
2715
     * @return array
2716
     */
2717
    public function parseConditions($options, $alias = 's')
2718
    {
2719
        $inject_extra_fields = null;
2720
        $extraFieldOption = new ExtraFieldOption($this->type);
2721
        $double_fields = [];
2722
2723
        if (isset($options['extra'])) {
2724
            $extra_fields = $options['extra'];
2725
            if (!empty($extra_fields)) {
2726
                $counter = 1;
2727
                $extra_field_obj = new ExtraField($this->type);
2728
                foreach ($extra_fields as &$extra) {
2729
                    if (!isset($extra['id'])) {
2730
                        continue;
2731
                    }
2732
                    $extra_field_info = $extra_field_obj->get($extra['id']);
2733
                    if (empty($extra_field_info)) {
2734
                        continue;
2735
                    }
2736
                    $extra['extra_field_info'] = $extra_field_info;
2737
2738
                    switch ($extra_field_info['field_type']) {
2739
                        case self::FIELD_TYPE_SELECT:
2740
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2741
                            $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, ";
2742
                            break;
2743
                        case  self::FIELD_TYPE_TAG:
2744
                            // If using OR
2745
                            //$inject_extra_fields .= " tag$counter.tag as {$extra['field']}, ";
2746
                            // If using AND
2747
                            $newCounter = 1;
2748
                            $fields = [];
2749
                            $tagAlias = $extra['field'];
2750
                            foreach ($extra['data'] as $data) {
2751
                                $fields[] = "tag$counter$newCounter.tag";
2752
                                $newCounter++;
2753
                            }
2754
                            $tags = implode(' , " ", ', $fields);
2755
                            $inject_extra_fields .= " CONCAT($tags) as $tagAlias, ";
2756
                            break;
2757
                        default:
2758
                            $inject_extra_fields .= " fv$counter.value as {$extra['field']}, ";
2759
                            break;
2760
                    }
2761
2762
                    if (isset($extra_fields_info[$extra['id']])) {
2763
                        $info = $extra_fields_info[$extra['id']];
2764
                    } else {
2765
                        $info = $this->get($extra['id']);
2766
                        $extra_fields_info[$extra['id']] = $info;
2767
                    }
2768
                    if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) {
2769
                        $double_fields[$info['id']] = $info;
2770
                    }
2771
                    $counter++;
2772
                }
2773
            }
2774
        }
2775
2776
        $options_by_double = [];
2777
        foreach ($double_fields as $double) {
2778
            $my_options = $extraFieldOption->get_field_options_by_field($double['id'], true);
2779
            $options_by_double['extra_'.$double['variable']] = $my_options;
2780
        }
2781
2782
        $field_value_to_join = [];
2783
        //filter can be all/any = and/or
2784
        $inject_joins = null;
2785
        $inject_where = null;
2786
        $where = null;
2787
2788
        if (!empty($options['where'])) {
2789
            if (!empty($options['extra'])) {
2790
                // Removing double 1=1
2791
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
2792
                // Always OR
2793
                $counter = 1;
2794
                foreach ($extra_fields as $extra_info) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extra_fields does not seem to be defined for all execution paths leading up to this point.
Loading history...
2795
                    $extra_field_info = $extra_info['extra_field_info'];
2796
                    $inject_joins .= " INNER JOIN $this->table_field_values fv$counter
2797
                                       ON ($alias.".$this->primaryKey." = fv$counter.".$this->handler_id.') ';
2798
                    // Add options
2799
                    switch ($extra_field_info['field_type']) {
2800
                        case self::FIELD_TYPE_SELECT:
2801
                        case self::FIELD_TYPE_DOUBLE_SELECT:
2802
                            $options['where'] = str_replace(
2803
                                $extra_info['field'],
2804
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value',
2805
                                $options['where']
2806
                            );
2807
                            $inject_joins .= "
2808
                                 INNER JOIN $this->table_field_options fvo$counter
2809
                                 ON (
2810
                                    fv$counter.field_id = fvo$counter.field_id AND
2811
                                    fv$counter.value = fvo$counter.option_value
2812
                                 )
2813
                                ";
2814
                            break;
2815
                        case  self::FIELD_TYPE_TAG:
2816
                            /*$options['where'] = str_replace(
2817
                                $extra_info['field'],
2818
                                'tag'.$counter.'.tag ',
2819
                                $options['where']
2820
                            );*/
2821
                            $newCounter = 1;
2822
                            $whereTag = [];
2823
                            foreach ($extra['data'] as $data) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extra does not seem to be defined for all execution paths leading up to this point.
Loading history...
2824
                                $data = Database::escape_string($data);
2825
                                $key = $counter.$newCounter;
2826
                                $whereTag[] = ' tag'.$key.'.tag LIKE "%'.$data.'%" ';
2827
                                $inject_joins .= "
2828
                                    INNER JOIN $this->table_field_rel_tag tag_rel$key
2829
                                    ON (
2830
                                        tag_rel$key.field_id = ".$extra_info['id']." AND
2831
                                        tag_rel$key.item_id = $alias.".$this->primaryKey."
2832
                                    )
2833
                                    INNER JOIN $this->table_field_tag tag$key
2834
                                    ON (tag$key.id = tag_rel$key.tag_id)
2835
                                ";
2836
                                $newCounter++;
2837
                            }
2838
                            $options['where'] = ' ('.implode(' AND ', $whereTag).') ';
2839
                            break;
2840
                        default:
2841
                            // text, textarea, etc
2842
                            $options['where'] = str_replace(
2843
                                $extra_info['field'],
2844
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value',
2845
                                $options['where']
2846
                            );
2847
                            break;
2848
                    }
2849
                    $field_value_to_join[] = " fv$counter.$this->handler_id ";
2850
                    $counter++;
2851
                }
2852
            }
2853
            $where .= ' AND '.$options['where'];
2854
        }
2855
2856
        $order = null;
2857
        if (!empty($options['order'])) {
2858
            $order = ' ORDER BY '.$options['order'];
2859
        }
2860
        $limit = null;
2861
        if (!empty($options['limit'])) {
2862
            $limit = ' LIMIT '.$options['limit'];
2863
        }
2864
2865
        return [
2866
            'order' => $order,
2867
            'limit' => $limit,
2868
            'where' => $where,
2869
            'inject_where' => $inject_where,
2870
            'inject_joins' => $inject_joins,
2871
            'field_value_to_join' => $field_value_to_join,
2872
            'inject_extra_fields' => $inject_extra_fields,
2873
        ];
2874
    }
2875
2876
    /**
2877
     * Get the extra fields and their formatted values.
2878
     *
2879
     * @param int|string $itemId The item ID (It could be a session_id, course_id or user_id)
2880
     * @param bool       $filter
2881
     * @param array      $onlyShow (list of extra fields variables to show)
2882
     *
2883
     * @return array The extra fields data
2884
     */
2885
    public function getDataAndFormattedValues($itemId, $filter = false, $onlyShow = [])
2886
    {
2887
        $valuesData = [];
2888
        $fields = $this->get_all();
2889
        $em = Database::getManager();
2890
2891
        $repoTag = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
2892
2893
        foreach ($fields as $field) {
2894
            if ('1' != $field['visible_to_self']) {
2895
                continue;
2896
            }
2897
2898
            if ($filter && $field['filter'] != 1) {
2899
                continue;
2900
            }
2901
2902
            if (!empty($onlyShow) && !in_array($field['variable'], $onlyShow)) {
2903
                continue;
2904
            }
2905
2906
            $valueAsArray = [];
2907
            $fieldValue = new ExtraFieldValue($this->type);
2908
            $valueData = $fieldValue->get_values_by_handler_and_field_id(
2909
                $itemId,
0 ignored issues
show
Bug introduced by
It seems like $itemId can also be of type string; however, parameter $item_id of ExtraFieldValue::get_val..._handler_and_field_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

2909
                /** @scrutinizer ignore-type */ $itemId,
Loading history...
2910
                $field['id'],
2911
                true
2912
            );
2913
            if (ExtraField::FIELD_TYPE_TAG == $field['field_type']) {
2914
                $tags = $repoTag->findBy(['fieldId' => $field['id'], 'itemId' => $itemId]);
2915
                if ($tags) {
2916
                    /** @var \Chamilo\CoreBundle\Entity\ExtraFieldRelTag $tag */
2917
                    $data = [];
2918
                    foreach ($tags as $extraFieldTag) {
2919
                        /** @var \Chamilo\CoreBundle\Entity\Tag $tag */
2920
                        $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
2921
                        $data[] = $tag->getTag();
2922
                    }
2923
                    $valueData = implode(',', $data);
2924
                    $valueAsArray = $data;
2925
                }
2926
            }
2927
2928
            if (!$valueData) {
2929
                continue;
2930
            }
2931
            $displayedValue = get_lang('None');
2932
2933
            switch ($field['field_type']) {
2934
                case self::FIELD_TYPE_CHECKBOX:
2935
                    if (false !== $valueData && '1' == $valueData['value']) {
2936
                        $displayedValue = get_lang('Yes');
2937
                    } else {
2938
                        $displayedValue = get_lang('No');
2939
                    }
2940
                    break;
2941
                case self::FIELD_TYPE_DATE:
2942
                    if (false !== $valueData && !empty($valueData['value'])) {
2943
                        $displayedValue = api_format_date($valueData['value'], DATE_FORMAT_LONG_NO_DAY);
2944
                    }
2945
                    break;
2946
                case self::FIELD_TYPE_TAG:
2947
                    if (!empty($valueData)) {
2948
                        $displayedValue = $valueData;
2949
                    }
2950
                    break;
2951
                case self::FIELD_TYPE_FILE_IMAGE:
2952
                    if (false === $valueData || empty($valueData['value'])) {
2953
                        break;
2954
                    }
2955
2956
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
2957
                        break;
2958
                    }
2959
2960
                    $image = Display::img(
2961
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2962
                        $field['display_text'],
2963
                        ['width' => '300']
2964
                    );
2965
2966
                    $displayedValue = Display::url(
2967
                        $image,
2968
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2969
                        ['target' => '_blank']
2970
                    );
2971
                    break;
2972
                case self::FIELD_TYPE_FILE:
2973
                    if (false === $valueData || empty($valueData['value'])) {
2974
                        break;
2975
                    }
2976
2977
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
2978
                        break;
2979
                    }
2980
2981
                    $displayedValue = Display::url(
2982
                        get_lang('Download'),
2983
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2984
                        [
2985
                            'title' => $field['display_text'],
2986
                            'target' => '_blank',
2987
                            'class' => 'download_extra_field',
2988
                        ]
2989
                    );
2990
                    break;
2991
                default:
2992
                    $displayedValue = $valueData['value'];
2993
                    break;
2994
            }
2995
2996
            $valuesData[] = [
2997
                'variable' => $field['variable'],
2998
                'text' => $field['display_text'],
2999
                'value' => $displayedValue,
3000
                'value_as_array' => $valueAsArray,
3001
            ];
3002
        }
3003
3004
        return $valuesData;
3005
    }
3006
3007
    /**
3008
     * @param int    $fieldId
3009
     * @param string $tag
3010
     *
3011
     * @return array
3012
     */
3013
    public function getAllUserPerTag($fieldId, $tag)
3014
    {
3015
        $tagRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
3016
        $tag = Database::escape_string($tag);
3017
        $fieldId = (int) $fieldId;
3018
3019
        $sql = "SELECT user_id 
3020
                FROM {$this->table_field_tag} f INNER JOIN $tagRelUserTable ft 
3021
                ON tag_id = f.id 
3022
                WHERE tag = '$tag' AND f.field_id = $fieldId;
3023
        ";
3024
3025
        $result = Database::query($sql);
3026
3027
        return Database::store_result($result, 'ASSOC');
3028
    }
3029
3030
    /**
3031
     * @param int $fieldId
3032
     * @param int $tagId
3033
     *
3034
     * @return array
3035
     */
3036
    public function getAllSkillPerTag($fieldId, $tagId)
3037
    {
3038
        $skillTable = Database::get_main_table(TABLE_MAIN_SKILL);
3039
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3040
        $fieldId = (int) $fieldId;
3041
        $tagId = (int) $tagId;
3042
3043
        $sql = "SELECT s.id
3044
                FROM $skillTable s INNER JOIN $tagRelExtraTable t
3045
                ON t.item_id = s.id
3046
                WHERE tag_id = $tagId AND t.field_id = $fieldId;
3047
        ";
3048
3049
        $result = Database::query($sql);
3050
        $result = Database::store_result($result, 'ASSOC');
3051
3052
        $skillList = [];
3053
        foreach ($result as $index => $value) {
3054
            $skillList[$value['id']] = $value['id'];
3055
        }
3056
3057
        return $skillList;
3058
    }
3059
3060
    /**
3061
     * @param string $from
3062
     * @param string $search
3063
     * @param array  $options
3064
     *
3065
     * @return array
3066
     */
3067
    public function searchOptionsFromTags($from, $search, $options)
3068
    {
3069
        $extraFieldInfo = $this->get_handler_field_info_by_field_variable(
3070
            str_replace('extra_', '', $from)
3071
        );
3072
        $extraFieldInfoTag = $this->get_handler_field_info_by_field_variable(
3073
            str_replace('extra_', '', $search)
3074
        );
3075
3076
        if (empty($extraFieldInfo) || empty($extraFieldInfoTag)) {
3077
            return [];
3078
        }
3079
3080
        $id = $extraFieldInfo['id'];
3081
        $tagId = $extraFieldInfoTag['id'];
3082
3083
        $table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
3084
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
3085
        $tagTable = Database::get_main_table(TABLE_MAIN_TAG);
3086
        $optionsTable = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
3087
3088
        $sql = "SELECT DISTINCT t.*, v.value, o.display_text
3089
                FROM $tagRelExtraTable te 
3090
                INNER JOIN $tagTable t
3091
                ON (t.id = te.tag_id AND te.field_id = t.field_id AND te.field_id = $tagId) 
3092
                INNER JOIN $table v
3093
                ON (te.item_id = v.item_id AND v.field_id = $id)
3094
                INNER JOIN $optionsTable o
3095
                ON (o.option_value = v.value)
3096
                WHERE v.value IN ('".implode("','", $options)."')                           
3097
                ORDER BY o.option_order, t.tag
3098
               ";
3099
3100
        $result = Database::query($sql);
3101
        $result = Database::store_result($result);
3102
3103
        return $result;
3104
    }
3105
3106
    /**
3107
     * @param \FormValidator $form
3108
     * @param int            $defaultValueId
3109
     * @param bool           $freezeElement
3110
     */
3111
    private function addSelectElement(FormValidator $form, array $fieldDetails, $defaultValueId, $freezeElement = false)
3112
    {
3113
        $get_lang_variables = false;
3114
        if (in_array(
3115
            $fieldDetails['variable'],
3116
            ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
3117
        )) {
3118
            $get_lang_variables = true;
3119
        }
3120
3121
        // Get extra field workflow
3122
        $addOptions = [];
3123
        $optionsExists = false;
3124
        $options = [];
3125
3126
        $optionList = [];
3127
        if (!empty($fieldDetails['options'])) {
3128
            foreach ($fieldDetails['options'] as $option_details) {
3129
                $optionList[$option_details['id']] = $option_details;
3130
                if ($get_lang_variables) {
3131
                    $options[$option_details['option_value']] = $option_details['display_text'];
3132
                } else {
3133
                    if ($optionsExists) {
3134
                        // Adding always the default value
3135
                        if ($option_details['id'] == $defaultValueId) {
3136
                            $options[$option_details['option_value']] = $option_details['display_text'];
3137
                        } else {
3138
                            if (isset($addOptions) && !empty($addOptions)) {
3139
                                // Parsing filters
3140
                                if (in_array($option_details['id'], $addOptions)) {
3141
                                    $options[$option_details['option_value']] = $option_details['display_text'];
3142
                                }
3143
                            }
3144
                        }
3145
                    } else {
3146
                        // Normal behaviour
3147
                        $options[$option_details['option_value']] = $option_details['display_text'];
3148
                    }
3149
                }
3150
            }
3151
3152
            // Setting priority message
3153
            if (isset($optionList[$defaultValueId])
3154
                && isset($optionList[$defaultValueId]['priority'])
3155
            ) {
3156
                if (!empty($optionList[$defaultValueId]['priority'])) {
3157
                    $priorityId = $optionList[$defaultValueId]['priority'];
3158
                    $option = new ExtraFieldOption($this->type);
3159
                    $messageType = $option->getPriorityMessageType($priorityId);
3160
                    $form->addElement(
3161
                        'label',
3162
                        null,
3163
                        Display::return_message(
3164
                            $optionList[$defaultValueId]['priority_message'],
3165
                            $messageType
3166
                        )
3167
                    );
3168
                }
3169
            }
3170
        }
3171
3172
        /** @var \HTML_QuickForm_select $slct */
3173
        $slct = $form->addElement(
3174
            'select',
3175
            'extra_'.$fieldDetails['variable'],
3176
            $fieldDetails['display_text'],
3177
            [],
3178
            ['id' => 'extra_'.$fieldDetails['variable']]
3179
        );
3180
3181
        if (empty($defaultValueId)) {
3182
            $slct->addOption(get_lang('Please select an option'), '');
3183
        }
3184
3185
        foreach ($options as $value => $text) {
3186
            if (empty($value)) {
3187
                $slct->addOption($text, $value);
3188
                continue;
3189
            }
3190
3191
            $valueParts = explode('#', $text);
3192
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3193
3194
            $slct->addOption(implode('', $valueParts), $value, ['data-value' => $dataValue]);
3195
        }
3196
3197
        if ($freezeElement) {
3198
            $form->freeze('extra_'.$fieldDetails['variable']);
3199
        }
3200
    }
3201
3202
    /**
3203
     * @param \FormValidator $form
3204
     * @param array          $fieldDetails
3205
     * @param array          $extraData
3206
     * @param bool           $freezeElement
3207
     *
3208
     * @return string JavaScript code
3209
     */
3210
    private function addDoubleSelectElement(FormValidator $form, $fieldDetails, $extraData, $freezeElement = false)
3211
    {
3212
        $firstSelectId = 'first_extra_'.$fieldDetails['variable'];
3213
        $secondSelectId = 'second_extra_'.$fieldDetails['variable'];
3214
3215
        $jqueryReadyContent = "
3216
            $('#$firstSelectId').on('change', function() {
3217
                var id = $(this).val();
3218
3219
                if (!id) {
3220
                    $('#$secondSelectId').empty().selectpicker('refresh');
3221
                    
3222
                    return;
3223
                }
3224
3225
                $.getJSON(_p.web_ajax + 'extra_field.ajax.php?1=1&a=get_second_select_options', {
3226
                    'type': '{$this->type}',
3227
                    'field_id': {$fieldDetails['id']},
3228
                    'option_value_id': id
3229
                })
3230
                    .done(function(data) {
3231
                        $('#$secondSelectId').empty();
3232
                        $.each(data, function(index, value) {
3233
                            $('#second_extra_{$fieldDetails['variable']}').append(
3234
                                $('<option>', {value: index, text: value})
3235
                            );
3236
                        });
3237
                        $('#$secondSelectId').selectpicker('refresh');
3238
                    });
3239
            });
3240
        ";
3241
3242
        $firstId = null;
3243
        if (!empty($extraData)) {
3244
            if (isset($extraData['extra_'.$fieldDetails['variable']])) {
3245
                $firstId = $extraData['extra_'.$fieldDetails['variable']]['extra_'.$fieldDetails['variable']];
3246
            }
3247
        }
3248
3249
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3250
        $values = ['' => get_lang('Select')];
3251
3252
        $second_values = [];
3253
        if (!empty($options)) {
3254
            foreach ($options as $option) {
3255
                foreach ($option as $sub_option) {
3256
                    if ('0' == $sub_option['option_value']) {
3257
                        $values[$sub_option['id']] = $sub_option['display_text'];
3258
3259
                        continue;
3260
                    }
3261
3262
                    if ($firstId === $sub_option['option_value']) {
3263
                        $second_values[$sub_option['id']] = $sub_option['display_text'];
3264
                    }
3265
                }
3266
            }
3267
        }
3268
3269
        $form
3270
            ->defaultRenderer()
3271
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3272
        $group = [];
3273
        $group[] = $form->createElement(
3274
            'select',
3275
            'extra_'.$fieldDetails['variable'],
3276
            null,
3277
            $values,
3278
            ['id' => $firstSelectId]
3279
        );
3280
        $group[] = $form->createElement(
3281
            'select',
3282
            'extra_'.$fieldDetails['variable'].'_second',
3283
            null,
3284
            $second_values,
3285
            ['id' => $secondSelectId]
3286
        );
3287
        $form->addGroup(
3288
            $group,
3289
            'extra_'.$fieldDetails['variable'],
3290
            $fieldDetails['display_text']
3291
        );
3292
3293
        if ($freezeElement) {
3294
            $form->freeze('extra_'.$fieldDetails['variable']);
3295
        }
3296
3297
        return $jqueryReadyContent;
3298
    }
3299
3300
    /**
3301
     * @param \FormValidator $form
3302
     * @param bool           $freezeElement Optional
3303
     *
3304
     * @return string JavaScript code
3305
     */
3306
    private function addSelectWithTextFieldElement(
3307
        FormValidator $form,
3308
        array $fieldDetails,
3309
        $freezeElement = false
3310
    ) {
3311
        $firstSelectId = 'slct_extra_'.$fieldDetails['variable'];
3312
        $txtSelectId = 'txt_extra_'.$fieldDetails['variable'];
3313
3314
        $jqueryReadyContent = "
3315
            $('#$firstSelectId').on('change', function() {
3316
                var id = $(this).val();
3317
3318
                if (!id) {
3319
                    $('#$txtSelectId').val('');
3320
                }
3321
            });
3322
        ";
3323
3324
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3325
        $values = ['' => get_lang('Select')];
3326
3327
        if (!empty($options)) {
3328
            foreach ($options as $option) {
3329
                foreach ($option as $sub_option) {
3330
                    if ('0' != $sub_option['option_value']) {
3331
                        continue;
3332
                    }
3333
3334
                    $values[$sub_option['id']] = $sub_option['display_text'];
3335
                }
3336
            }
3337
        }
3338
3339
        $form
3340
            ->defaultRenderer()
3341
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3342
        $group = [];
3343
        $group[] = $form->createElement(
3344
            'select',
3345
            'extra_'.$fieldDetails['variable'],
3346
            null,
3347
            $values,
3348
            ['id' => $firstSelectId]
3349
        );
3350
        $group[] = $form->createElement(
3351
            'text',
3352
            'extra_'.$fieldDetails['variable'].'_second',
3353
            null,
3354
            ['id' => $txtSelectId]
3355
        );
3356
        $form->addGroup(
3357
            $group,
3358
            'extra_'.$fieldDetails['variable'],
3359
            $fieldDetails['display_text']
3360
        );
3361
3362
        if ($freezeElement) {
3363
            $form->freeze('extra_'.$fieldDetails['variable']);
3364
        }
3365
3366
        return $jqueryReadyContent;
3367
    }
3368
3369
    /**
3370
     * @param \FormValidator $form
3371
     * @param bool           $freezeElement
3372
     *
3373
     * @return string
3374
     */
3375
    private function addTripleSelectElement(
3376
        FormValidator $form,
3377
        array $fieldDetails,
3378
        array $extraData,
3379
        $freezeElement
3380
    ) {
3381
        $variable = $fieldDetails['variable'];
3382
        $id = $fieldDetails['id'];
3383
        $slctFirstId = "first_extra$variable";
3384
        $slctSecondId = "second_extra$variable";
3385
        $slctThirdId = "third_extra$variable";
3386
        $langSelect = get_lang('Select');
3387
3388
        $js = "
3389
            (function () {
3390
                var slctFirst = $('#$slctFirstId'),
3391
                    slctSecond = $('#$slctSecondId'),
3392
                    slctThird = $('#$slctThirdId');
3393
                    
3394
                slctFirst.on('change', function () {
3395
                    slctSecond.empty().selectpicker('refresh');
3396
                    slctThird.empty().selectpicker('refresh');
3397
    
3398
                    var level = $(this).val();
3399
    
3400
                    if (!level) {
3401
                        return;
3402
                    }
3403
    
3404
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3405
                        'a': 'get_second_select_options',
3406
                        'type': '$this->type',
3407
                        'field_id': $id,
3408
                        'option_value_id': level
3409
                    })
3410
                        .done(function (data) {
3411
                            slctSecond.append(
3412
                                $('<option>', {value: '', text: '$langSelect'})
3413
                            );
3414
3415
                            $.each(data, function (index, value) {
3416
                                var valueParts = value.split('#'),
3417
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3418
3419
                                slctSecond.append(
3420
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3421
                                );
3422
                            });
3423
    
3424
                            slctSecond.selectpicker('refresh');
3425
                        });
3426
                });
3427
                slctSecond.on('change', function () {
3428
                    slctThird.empty().selectpicker('refresh');
3429
    
3430
                    var level = $(this).val();
3431
                    
3432
                    if (!level) {
3433
                        return;
3434
                    }
3435
                    
3436
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3437
                        'a': 'get_second_select_options',
3438
                        'type': '$this->type',
3439
                        'field_id': $id,
3440
                        'option_value_id': level
3441
                    })
3442
                        .done(function (data) {
3443
                            slctThird.append(
3444
                                $('<option>', {value: '', text: '$langSelect'})
3445
                            );
3446
3447
                            $.each(data, function (index, value) {
3448
                                var valueParts = value.split('#'),
3449
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3450
3451
                                slctThird.append(
3452
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3453
                                );
3454
                            });
3455
    
3456
                            slctThird.selectpicker('refresh');
3457
                        });
3458
                });
3459
            })();
3460
        ";
3461
3462
        $firstId = isset($extraData["extra_$variable"]["extra_$variable"])
3463
            ? $extraData["extra_$variable"]["extra_$variable"]
3464
            : '';
3465
        $secondId = isset($extraData["extra_$variable"]["extra_{$variable}_second"])
3466
            ? $extraData["extra_$variable"]["extra_{$variable}_second"]
3467
            : '';
3468
3469
        $options = $this->tripleSelectConvertArrayToOrderedArray($fieldDetails['options']);
3470
        $values1 = ['' => $langSelect];
3471
        $values2 = ['' => $langSelect];
3472
        $values3 = ['' => $langSelect];
3473
        $level1 = $this->getOptionsFromTripleSelect($options['level1'], 0);
3474
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], $firstId);
0 ignored issues
show
Bug introduced by
It seems like $firstId can also be of type string; however, parameter $parentId of ExtraField::getOptionsFromTripleSelect() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

3474
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], /** @scrutinizer ignore-type */ $firstId);
Loading history...
3475
        $level3 = $this->getOptionsFromTripleSelect($options['level3'], $secondId);
3476
        /** @var \HTML_QuickForm_select $slctFirst */
3477
        $slctFirst = $form->createElement('select', "extra_$variable", null, $values1, ['id' => $slctFirstId]);
3478
        /** @var \HTML_QuickForm_select $slctFirst */
3479
        $slctSecond = $form->createElement(
3480
            'select',
3481
            "extra_{$variable}_second",
3482
            null,
3483
            $values2,
3484
            ['id' => $slctSecondId]
3485
        );
3486
        /** @var \HTML_QuickForm_select $slctFirst */
3487
        $slctThird = $form->createElement('select', "extra_{$variable}_third", null, $values3, ['id' => $slctThirdId]);
3488
3489
        foreach ($level1 as $item1) {
3490
            $valueParts = explode('#', $item1['display_text']);
3491
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3492
            $slctFirst->addOption(implode('', $valueParts), $item1['id'], ['data-value' => $dataValue]);
3493
        }
3494
3495
        foreach ($level2 as $item2) {
3496
            $valueParts = explode('#', $item2['display_text']);
3497
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3498
            $slctSecond->addOption(implode('', $valueParts), $item2['id'], ['data-value' => $dataValue]);
3499
        }
3500
3501
        foreach ($level3 as $item3) {
3502
            $valueParts = explode('#', $item3['display_text']);
3503
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3504
            $slctThird->addOption(implode('', $valueParts), $item3['id'], ['data-value' => $dataValue]);
3505
        }
3506
3507
        $form
3508
            ->defaultRenderer()
3509
            ->setGroupElementTemplate('<p>{element}</p>', "extra_$variable");
3510
        $form->addGroup([$slctFirst, $slctSecond, $slctThird], "extra_$variable", $fieldDetails['display_text']);
3511
3512
        if ($freezeElement) {
3513
            $form->freeze('extra_'.$fieldDetails['variable']);
3514
        }
3515
3516
        return $js;
3517
    }
3518
3519
    /**
3520
     * @param int $parentId
3521
     *
3522
     * @return array
3523
     */
3524
    private static function getOptionsFromTripleSelect(array $options, $parentId)
3525
    {
3526
        return array_filter(
3527
            $options,
3528
            function ($option) use ($parentId) {
3529
                return $option['option_value'] == $parentId;
3530
            }
3531
        );
3532
    }
3533
}
3534