Passed
Pull Request — 1.11.x (#4119)
by Angel Fernando Quiroz
13:03
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
     * @param array $params
1985
     *
1986
     * @return array
1987
     */
1988
    public function clean_parameters($params)
1989
    {
1990
        if (!isset($params['variable']) || empty($params['variable'])) {
1991
            $params['variable'] = $params['display_text'];
1992
        }
1993
1994
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
1995
1996
        if (!isset($params['field_order'])) {
1997
            $max_order = self::get_max_field_order();
0 ignored issues
show
Bug Best Practice introduced by
The method ExtraField::get_max_field_order() is not static, but was called statically. ( Ignorable by Annotation )

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

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

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

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