ExtraField   F
last analyzed

Complexity

Total Complexity 465

Size/Duplication

Total Lines 3666
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 2
Metric Value
wmc 465
eloc 2012
dl 0
loc 3666
rs 0.8
c 4
b 0
f 2

55 Methods

Rating   Name   Duplication   Size   Complexity  
F set_extra_fields_in_form() 0 807 129
A display() 0 22 1
A save() 0 17 3
A getFieldInfoByFieldId() 0 23 3
A get_count() 0 9 1
B getAllGrid() 0 35 8
A get_all_extra_field_by_type() 0 16 2
A getJqgridColumnNames() 0 12 1
A getLocalizationInput() 0 33 1
A setupBreadcrumb() 0 10 3
B addElements() 0 78 10
C get_handler_extra_data() 0 80 16
B extra_field_double_select_convert_array_to_string() 0 26 7
A extraFieldSelectWithTextConvertArrayToString() 0 16 3
A clean_parameters() 0 16 4
A get_handler_field_info_by_tags() 0 28 3
A tripleSelectConvertStringToArray() 0 33 6
A getValidExtraFieldTypes() 0 37 3
A get_extra_fields_by_handler() 0 40 5
A getExtraFieldType() 0 3 1
A delete() 0 17 3
D __construct() 0 94 25
A update() 0 13 3
A get_all() 0 34 4
A translateDisplayName() 0 5 2
A getLocalizationJavascript() 0 145 1
A tripleSelectConvertArrayToString() 0 19 3
A get_handler_field_info_by_field_variable() 0 27 4
A extra_field_double_select_convert_array_to_ordered_array() 0 14 4
A get_field_types() 0 3 1
A get_max_field_order() 0 15 2
A tripleSelectConvertArrayToOrderedArray() 0 15 3
A getHandlerEntityByFieldVariable() 0 5 1
A get_field_type_by_id() 0 8 2
A extra_field_double_select_convert_string_to_array() 0 19 4
A getJqgridColumnModel() 0 65 1
A getAllSkillPerTag() 0 22 2
A getAllUserPerTag() 0 15 1
C get_where_clause() 0 36 14
B addDoubleSelectElement() 0 88 9
D addSelectElement() 0 88 18
C getRules() 0 105 10
A getOptionsFromTripleSelect() 0 6 1
A getDefaultValueByFieldId() 0 11 2
A searchOptionsFromTags() 0 49 5
C return_form() 0 149 8
F parseConditions() 0 162 29
C processExtraFieldSearch() 0 78 15
D getExtraFieldRules() 0 105 26
C addTripleSelectElement() 0 142 10
A get() 0 9 2
A getAllValuesByFieldId() 0 25 6
B addSelectWithTextFieldElement() 0 61 6
A getJqgridActionLinks() 0 25 1
D getDataAndFormattedValues() 0 120 27

How to fix   Complexity   

Complex Class

Complex classes like ExtraField often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ExtraField, and based on these observations, apply Extract Interface, too.

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

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

1938
        /** @scrutinizer ignore-call */ 
1939
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
1939
        $params = $this->clean_parameters($params);
1940
        $params['extra_field_type'] = $this->extraFieldType;
1941
1942
        if ($fieldInfo) {
1943
            return $fieldInfo['id'];
1944
        } else {
1945
            $id = parent::save($params, $show_query);
1946
            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...
1947
                $fieldOption = new ExtraFieldOption($this->type);
1948
                $params['field_id'] = $id;
1949
                $fieldOption->save($params);
1950
            }
1951
1952
            return $id;
1953
        }
1954
    }
1955
1956
    /**
1957
     * Gets the set of values of an extra_field searching for the variable name.
1958
     *
1959
     * Example:
1960
     * <code>
1961
     * <?php
1962
     * $extraField = new ExtraField('lp_item');
1963
     * $extraFieldArray =  $extraField->get_handler_field_info_by_field_variable('authorlpitem');
1964
     * echo "<pre>".var_export($extraFieldArray,true)."</pre>";
1965
     * ?>
1966
     * </code>
1967
     *
1968
     * @param string $variable
1969
     *
1970
     * @return array|bool
1971
     */
1972
    public function get_handler_field_info_by_field_variable($variable)
1973
    {
1974
        $variable = Database::escape_string($variable);
1975
        $sql = "SELECT * FROM {$this->table}
1976
                WHERE
1977
                    variable = '$variable' AND
1978
                    extra_field_type = $this->extraFieldType";
1979
        $result = Database::query($sql);
1980
        if (Database::num_rows($result)) {
1981
            $row = Database::fetch_array($result, 'ASSOC');
1982
            if ($row) {
1983
                $row['display_text'] = self::translateDisplayName($row['variable'], $row['display_text']);
1984
1985
                // All the options of the field
1986
                $sql = "SELECT * FROM $this->table_field_options
1987
                    WHERE field_id='".intval($row['id'])."'
1988
                    ORDER BY option_order ASC";
1989
                $result = Database::query($sql);
1990
                while ($option = Database::fetch_array($result)) {
1991
                    $row['options'][$option['id']] = $option;
1992
                }
1993
1994
                return $row;
1995
            }
1996
        }
1997
1998
        return false;
1999
    }
2000
2001
    public function getHandlerEntityByFieldVariable(string $variable)
2002
    {
2003
        return Database::getManager()
2004
            ->getRepository('ChamiloCoreBundle:ExtraField')
2005
            ->findOneBy(['variable' => $variable, 'extraFieldType' => $this->extraFieldType]);
2006
    }
2007
2008
    /**
2009
     * @param array $params
2010
     *
2011
     * @return array
2012
     */
2013
    public function clean_parameters($params)
2014
    {
2015
        if (!isset($params['variable']) || empty($params['variable'])) {
2016
            $params['variable'] = $params['display_text'];
2017
        }
2018
2019
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
2020
2021
        if (!isset($params['field_order'])) {
2022
            $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

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

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