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

ExtraField::parseConditions()   F

Complexity

Conditions 23
Paths 72

Size

Total Lines 156
Code Lines 108

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 23
eloc 108
c 0
b 0
f 0
nop 2
dl 0
loc 156
rs 3.3333
nc 72

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
7
use Chamilo\CoreBundle\Entity\Tag;
8
9
/**
10
 * Class ExtraField.
11
 */
12
class ExtraField extends Model
13
{
14
    public const FIELD_TYPE_TEXT = 1;
15
    public const FIELD_TYPE_TEXTAREA = 2;
16
    public const FIELD_TYPE_RADIO = 3;
17
    public const FIELD_TYPE_SELECT = 4;
18
    public const FIELD_TYPE_SELECT_MULTIPLE = 5;
19
    public const FIELD_TYPE_DATE = 6;
20
    public const FIELD_TYPE_DATETIME = 7;
21
    public const FIELD_TYPE_DOUBLE_SELECT = 8;
22
    public const FIELD_TYPE_DIVIDER = 9;
23
    public const FIELD_TYPE_TAG = 10;
24
    public const FIELD_TYPE_TIMEZONE = 11;
25
    public const FIELD_TYPE_SOCIAL_PROFILE = 12;
26
    public const FIELD_TYPE_CHECKBOX = 13;
27
    public const FIELD_TYPE_MOBILE_PHONE_NUMBER = 14;
28
    public const FIELD_TYPE_INTEGER = 15;
29
    public const FIELD_TYPE_FILE_IMAGE = 16;
30
    public const FIELD_TYPE_FLOAT = 17;
31
    public const FIELD_TYPE_FILE = 18;
32
    public const FIELD_TYPE_VIDEO_URL = 19;
33
    public const FIELD_TYPE_LETTERS_ONLY = 20;
34
    public const FIELD_TYPE_ALPHANUMERIC = 21;
35
    public const FIELD_TYPE_LETTERS_SPACE = 22;
36
    public const FIELD_TYPE_ALPHANUMERIC_SPACE = 23;
37
    public const FIELD_TYPE_GEOLOCALIZATION = 24;
38
    public const FIELD_TYPE_GEOLOCALIZATION_COORDINATES = 25;
39
    public const FIELD_TYPE_SELECT_WITH_TEXT_FIELD = 26;
40
    public const FIELD_TYPE_TRIPLE_SELECT = 27;
41
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