Passed
Pull Request — 1.11.x (#4115)
by Angel Fernando Quiroz
09:36
created

ExtraField::set_extra_fields_in_form()   F

Complexity

Conditions 127
Paths 3

Size

Total Lines 792
Code Lines 508

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 127
eloc 508
c 0
b 0
f 0
nc 3
nop 16
dl 0
loc 792
rs 3.3333

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

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

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

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

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

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

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

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

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

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

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

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

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

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