Passed
Push — 1.11.x ( b99403...e54d88 )
by Julito
11:24
created

ExtraField::addElements()   B

Complexity

Conditions 10
Paths 13

Size

Total Lines 78
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 43
c 0
b 0
f 0
nc 13
nop 17
dl 0
loc 78
rs 7.6666

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
6
use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
7
use Chamilo\CoreBundle\Entity\Tag;
8
9
/**
10
 * Class ExtraField.
11
 */
12
class ExtraField extends Model
13
{
14
    const FIELD_TYPE_TEXT = 1;
15
    const FIELD_TYPE_TEXTAREA = 2;
16
    const FIELD_TYPE_RADIO = 3;
17
    const FIELD_TYPE_SELECT = 4;
18
    const FIELD_TYPE_SELECT_MULTIPLE = 5;
19
    const FIELD_TYPE_DATE = 6;
20
    const FIELD_TYPE_DATETIME = 7;
21
    const FIELD_TYPE_DOUBLE_SELECT = 8;
22
    const FIELD_TYPE_DIVIDER = 9;
23
    const FIELD_TYPE_TAG = 10;
24
    const FIELD_TYPE_TIMEZONE = 11;
25
    const FIELD_TYPE_SOCIAL_PROFILE = 12;
26
    const FIELD_TYPE_CHECKBOX = 13;
27
    const FIELD_TYPE_MOBILE_PHONE_NUMBER = 14;
28
    const FIELD_TYPE_INTEGER = 15;
29
    const FIELD_TYPE_FILE_IMAGE = 16;
30
    const FIELD_TYPE_FLOAT = 17;
31
    const FIELD_TYPE_FILE = 18;
32
    const FIELD_TYPE_VIDEO_URL = 19;
33
    const FIELD_TYPE_LETTERS_ONLY = 20;
34
    const FIELD_TYPE_ALPHANUMERIC = 21;
35
    const FIELD_TYPE_LETTERS_SPACE = 22;
36
    const FIELD_TYPE_ALPHANUMERIC_SPACE = 23;
37
    const FIELD_TYPE_GEOLOCALIZATION = 24;
38
    const FIELD_TYPE_GEOLOCALIZATION_COORDINATES = 25;
39
    const FIELD_TYPE_SELECT_WITH_TEXT_FIELD = 26;
40
    const FIELD_TYPE_TRIPLE_SELECT = 27;
41
    public $columns = [
42
        'id',
43
        'field_type',
44
        'variable',
45
        'display_text',
46
        'default_value',
47
        'field_order',
48
        'visible_to_self',
49
        'visible_to_others',
50
        'changeable',
51
        'filter',
52
        'extra_field_type',
53
        //Enable this when field_loggeable is introduced as a table field (2.0)
54
        //'field_loggeable',
55
        'created_at',
56
    ];
57
58
    public $ops = [
59
        'eq' => '=', //equal
60
        'ne' => '<>', //not equal
61
        'lt' => '<', //less than
62
        'le' => '<=', //less than or equal
63
        'gt' => '>', //greater than
64
        'ge' => '>=', //greater than or equal
65
        'bw' => 'LIKE', //begins with
66
        'bn' => 'NOT LIKE', //doesn't begin with
67
        'in' => 'LIKE', //is in
68
        'ni' => 'NOT LIKE', //is not in
69
        'ew' => 'LIKE', //ends with
70
        'en' => 'NOT LIKE', //doesn't end with
71
        'cn' => 'LIKE', //contains
72
        'nc' => 'NOT LIKE',  //doesn't contain
73
    ];
74
75
    public $type = 'user';
76
    public $pageName;
77
    public $pageUrl;
78
    public $extraFieldType = 0;
79
80
    public $table_field_options;
81
    public $table_field_values;
82
    public $table_field_tag;
83
    public $table_field_rel_tag;
84
85
    public $handler_id;
86
    public $primaryKey;
87
88
    /**
89
     * @param string $type
90
     */
91
    public function __construct($type)
92
    {
93
        parent::__construct();
94
95
        $this->type = $type;
96
        $this->table = Database::get_main_table(TABLE_EXTRA_FIELD);
97
        $this->table_field_options = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
98
        $this->table_field_values = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
99
        $this->table_field_tag = Database::get_main_table(TABLE_MAIN_TAG);
100
        $this->table_field_rel_tag = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
101
102
        $this->handler_id = 'item_id';
103
104
        switch ($this->type) {
105
            case 'calendar_event':
106
                $this->extraFieldType = EntityExtraField::CALENDAR_FIELD_TYPE;
107
                break;
108
            case 'course':
109
                $this->extraFieldType = EntityExtraField::COURSE_FIELD_TYPE;
110
                $this->primaryKey = 'id';
111
                break;
112
            case 'user':
113
                $this->extraFieldType = EntityExtraField::USER_FIELD_TYPE;
114
                $this->primaryKey = 'id';
115
                break;
116
            case 'session':
117
                $this->extraFieldType = EntityExtraField::SESSION_FIELD_TYPE;
118
                $this->primaryKey = 'id';
119
                break;
120
            case 'exercise':
121
                $this->extraFieldType = EntityExtraField::EXERCISE_FIELD_TYPE;
122
                break;
123
            case 'question':
124
                $this->extraFieldType = EntityExtraField::QUESTION_FIELD_TYPE;
125
                break;
126
            case 'lp':
127
                $this->extraFieldType = EntityExtraField::LP_FIELD_TYPE;
128
                break;
129
            case 'lp_item':
130
                $this->extraFieldType = EntityExtraField::LP_ITEM_FIELD_TYPE;
131
                break;
132
            case 'skill':
133
                $this->extraFieldType = EntityExtraField::SKILL_FIELD_TYPE;
134
                break;
135
            case 'work':
136
                $this->extraFieldType = EntityExtraField::WORK_FIELD_TYPE;
137
                break;
138
            case 'career':
139
                $this->extraFieldType = EntityExtraField::CAREER_FIELD_TYPE;
140
                break;
141
            case 'user_certificate':
142
                $this->extraFieldType = EntityExtraField::USER_CERTIFICATE;
143
                break;
144
            case 'survey':
145
                $this->extraFieldType = EntityExtraField::SURVEY_FIELD_TYPE;
146
                break;
147
            case 'scheduled_announcement':
148
                $this->extraFieldType = EntityExtraField::SCHEDULED_ANNOUNCEMENT;
149
                break;
150
            case 'terms_and_condition':
151
                $this->extraFieldType = EntityExtraField::TERMS_AND_CONDITION_TYPE;
152
                break;
153
            case 'forum_category':
154
                $this->extraFieldType = EntityExtraField::FORUM_CATEGORY_TYPE;
155
                break;
156
            case 'forum_post':
157
                $this->extraFieldType = EntityExtraField::FORUM_POST_TYPE;
158
                break;
159
        }
160
161
        $this->pageUrl = 'extra_fields.php?type='.$this->type;
162
        // Example QuestionFields
163
        $this->pageName = get_lang(ucwords($this->type).'Fields');
164
    }
165
166
    /**
167
     * @return int
168
     */
169
    public function getExtraFieldType()
170
    {
171
        return (int) $this->extraFieldType;
172
    }
173
174
    /**
175
     * @return array
176
     */
177
    public static function getValidExtraFieldTypes()
178
    {
179
        $result = [
180
            'user',
181
            'course',
182
            'session',
183
            'question',
184
            'lp',
185
            'calendar_event',
186
            'lp_item',
187
            'skill',
188
            'work',
189
            'career',
190
            'user_certificate',
191
            'survey',
192
            'terms_and_condition',
193
            'forum_category',
194
            'forum_post',
195
            'exercise',
196
        ];
197
198
        if (api_get_configuration_value('allow_scheduled_announcements')) {
199
            $result[] = 'scheduled_announcement';
200
        }
201
202
        return $result;
203
    }
204
205
    /**
206
     * @return int
207
     */
208
    public function get_count()
209
    {
210
        $em = Database::getManager();
211
        $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e');
212
        $query->select('count(e.id)');
213
        $query->where('e.extraFieldType = :type');
214
        $query->setParameter('type', $this->getExtraFieldType());
215
216
        return $query->getQuery()->getSingleScalarResult();
217
    }
218
219
    /**
220
     * @param string $sidx
221
     * @param string $sord
222
     * @param int    $start
223
     * @param int    $limit
224
     *
225
     * @return array
226
     */
227
    public function getAllGrid($sidx, $sord, $start, $limit)
228
    {
229
        switch ($sidx) {
230
            case 'field_order':
231
                $sidx = 'e.fieldOrder';
232
                break;
233
            case 'variable':
234
                $sidx = 'e.variable';
235
                break;
236
            case 'display_text':
237
                $sidx = 'e.displayText';
238
                break;
239
            case 'changeable':
240
                $sidx = 'e.changeable';
241
                break;
242
            case 'visible_to_self':
243
                $sidx = 'e.visibleToSelf';
244
                break;
245
            case 'visible_to_others':
246
                $sidx = 'e.visibleToOthers';
247
                break;
248
            case 'filter':
249
                $sidx = 'e.filter';
250
                break;
251
        }
252
        $em = Database::getManager();
253
        $query = $em->getRepository('ChamiloCoreBundle:ExtraField')->createQueryBuilder('e');
254
        $query->select('e')
255
            ->where('e.extraFieldType = :type')
256
            ->setParameter('type', $this->getExtraFieldType())
257
            ->orderBy($sidx, $sord)
258
            ->setFirstResult($start)
259
            ->setMaxResults($limit);
260
261
        return $query->getQuery()->getArrayResult();
262
    }
263
264
    /**
265
     * Get an array of all the values from the extra_field and extra_field_options tables
266
     * based on the current object's type.
267
     *
268
     * @param array $conditions
269
     * @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...
270
     *
271
     * @return array
272
     */
273
    public function get_all($conditions = [], $order_field_options_by = null)
274
    {
275
        $conditions = Database::parse_conditions(['where' => $conditions]);
276
277
        if (empty($conditions)) {
278
            $conditions .= ' WHERE extra_field_type = '.$this->extraFieldType;
279
        } else {
280
            $conditions .= ' AND extra_field_type = '.$this->extraFieldType;
281
        }
282
283
        $sql = "SELECT * FROM $this->table
284
                $conditions
285
                ORDER BY field_order ASC
286
        ";
287
288
        $result = Database::query($sql);
289
        $extraFields = Database::store_result($result, 'ASSOC');
290
291
        $option = new ExtraFieldOption($this->type);
292
        if (!empty($extraFields)) {
293
            foreach ($extraFields as &$extraField) {
294
                $extraField['display_text'] = $this->translateDisplayName(
295
                    $extraField['variable'],
296
                    $extraField['display_text']
297
                );
298
                $extraField['options'] = $option->get_field_options_by_field(
299
                    $extraField['id'],
300
                    false,
301
                    $order_field_options_by
302
                );
303
            }
304
        }
305
306
        return $extraFields;
307
    }
308
309
    /**
310
     * @param string $variable
311
     *
312
     * @return array|bool
313
     */
314
    public function get_handler_field_info_by_field_variable($variable)
315
    {
316
        $variable = Database::escape_string($variable);
317
        $sql = "SELECT * FROM {$this->table}
318
                WHERE
319
                    variable = '$variable' AND
320
                    extra_field_type = $this->extraFieldType";
321
        $result = Database::query($sql);
322
        if (Database::num_rows($result)) {
323
            $row = Database::fetch_array($result, 'ASSOC');
324
            if ($row) {
325
                $row['display_text'] = $this->translateDisplayName(
326
                    $row['variable'],
327
                    $row['display_text']
328
                );
329
330
                // All the options of the field
331
                $sql = "SELECT * FROM $this->table_field_options
332
                    WHERE field_id='".intval($row['id'])."'
333
                    ORDER BY option_order ASC";
334
                $result = Database::query($sql);
335
                while ($option = Database::fetch_array($result)) {
336
                    $row['options'][$option['id']] = $option;
337
                }
338
339
                return $row;
340
            }
341
        }
342
343
        return false;
344
    }
345
346
    /**
347
     * Get all the field info for tags.
348
     *
349
     * @param string $variable
350
     *
351
     * @return array|bool
352
     */
353
    public function get_handler_field_info_by_tags($variable)
354
    {
355
        $variable = Database::escape_string($variable);
356
        $sql = "SELECT * FROM {$this->table}
357
                WHERE
358
                    variable = '$variable' AND
359
                    extra_field_type = $this->extraFieldType";
360
        $result = Database::query($sql);
361
        if (Database::num_rows($result)) {
362
            $row = Database::fetch_array($result, 'ASSOC');
363
            $row['display_text'] = $this->translateDisplayName(
364
                $row['variable'],
365
                $row['display_text']
366
            );
367
368
            // All the tags of the field
369
            $sql = "SELECT * FROM $this->table_field_tag
370
                    WHERE field_id='".intval($row['id'])."'
371
                    ORDER BY id ASC";
372
            $result = Database::query($sql);
373
            while ($option = Database::fetch_array($result, 'ASSOC')) {
374
                $row['options'][$option['id']] = $option;
375
            }
376
377
            return $row;
378
        } else {
379
            return false;
380
        }
381
    }
382
383
    /**
384
     * @param int $fieldId
385
     *
386
     * @return array|bool
387
     */
388
    public function getFieldInfoByFieldId($fieldId)
389
    {
390
        $fieldId = (int) $fieldId;
391
        $sql = "SELECT * FROM {$this->table}
392
                WHERE
393
                    id = '$fieldId' AND
394
                    extra_field_type = $this->extraFieldType";
395
        $result = Database::query($sql);
396
        if (Database::num_rows($result)) {
397
            $row = Database::fetch_array($result, 'ASSOC');
398
399
            // All the options of the field
400
            $sql = "SELECT * FROM $this->table_field_options
401
                    WHERE field_id='".$fieldId."'
402
                    ORDER BY option_order ASC";
403
            $result = Database::query($sql);
404
            while ($option = Database::fetch_array($result)) {
405
                $row['options'][$option['id']] = $option;
406
            }
407
408
            return $row;
409
        } else {
410
            return false;
411
        }
412
    }
413
414
    /**
415
     * @return int
416
     */
417
    public function get_max_field_order()
418
    {
419
        $sql = "SELECT MAX(field_order)
420
                FROM {$this->table}
421
                WHERE
422
                    extra_field_type = '.$this->extraFieldType.'";
423
        $res = Database::query($sql);
424
425
        $order = 0;
426
        if (Database::num_rows($res) > 0) {
427
            $row = Database::fetch_row($res);
428
            $order = $row[0] + 1;
429
        }
430
431
        return $order;
432
    }
433
434
    /**
435
     * @param string $handler
436
     *
437
     * @return array
438
     */
439
    public static function get_extra_fields_by_handler($handler)
440
    {
441
        $types = [];
442
        $types[self::FIELD_TYPE_TEXT] = get_lang('FieldTypeText');
443
        $types[self::FIELD_TYPE_TEXTAREA] = get_lang('FieldTypeTextarea');
444
        $types[self::FIELD_TYPE_RADIO] = get_lang('FieldTypeRadio');
445
        $types[self::FIELD_TYPE_SELECT] = get_lang('FieldTypeSelect');
446
        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
447
        $types[self::FIELD_TYPE_DATE] = get_lang('FieldTypeDate');
448
        $types[self::FIELD_TYPE_DATETIME] = get_lang('FieldTypeDatetime');
449
        $types[self::FIELD_TYPE_DOUBLE_SELECT] = get_lang('FieldTypeDoubleSelect');
450
        $types[self::FIELD_TYPE_DIVIDER] = get_lang('FieldTypeDivider');
451
        $types[self::FIELD_TYPE_TAG] = get_lang('FieldTypeTag');
452
        $types[self::FIELD_TYPE_TIMEZONE] = get_lang('FieldTypeTimezone');
453
        $types[self::FIELD_TYPE_SOCIAL_PROFILE] = get_lang('FieldTypeSocialProfile');
454
        $types[self::FIELD_TYPE_MOBILE_PHONE_NUMBER] = get_lang('FieldTypeMobilePhoneNumber');
455
        $types[self::FIELD_TYPE_CHECKBOX] = get_lang('FieldTypeCheckbox');
456
        $types[self::FIELD_TYPE_INTEGER] = get_lang('FieldTypeInteger');
457
        $types[self::FIELD_TYPE_FILE_IMAGE] = get_lang('FieldTypeFileImage');
458
        $types[self::FIELD_TYPE_FLOAT] = get_lang('FieldTypeFloat');
459
        $types[self::FIELD_TYPE_FILE] = get_lang('FieldTypeFile');
460
        $types[self::FIELD_TYPE_VIDEO_URL] = get_lang('FieldTypeVideoUrl');
461
        $types[self::FIELD_TYPE_LETTERS_ONLY] = get_lang('FieldTypeOnlyLetters');
462
        $types[self::FIELD_TYPE_ALPHANUMERIC] = get_lang('FieldTypeAlphanumeric');
463
        $types[self::FIELD_TYPE_LETTERS_SPACE] = get_lang('FieldTypeLettersSpaces');
464
        $types[self::FIELD_TYPE_ALPHANUMERIC_SPACE] = get_lang('FieldTypeAlphanumericSpaces');
465
        $types[self::FIELD_TYPE_GEOLOCALIZATION] = get_lang('Geolocalization');
466
        $types[self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES] = get_lang('GeolocalizationCoordinates');
467
        $types[self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD] = get_lang('FieldTypeSelectWithTextField');
468
        $types[self::FIELD_TYPE_TRIPLE_SELECT] = get_lang('FieldTypeTripleSelect');
469
470
        switch ($handler) {
471
            case 'course':
472
            case 'session':
473
            case 'user':
474
            case 'skill':
475
                break;
476
        }
477
478
        return $types;
479
    }
480
481
    /**
482
     * Add elements to a form.
483
     *
484
     * @param FormValidator $form                            The form object to which to attach this element
485
     * @param int           $itemId                          The item (course, user, session, etc) this extra_field is linked to
486
     * @param array         $exclude                         Variables of extra field to exclude
487
     * @param bool          $filter                          Whether to get only the fields with the "filter" flag set to 1 (true) or not (false)
488
     * @param bool          $useTagAsSelect                  Whether to show tag fields as select drop-down or not
489
     * @param array         $showOnlyTheseFields             Limit the extra fields shown to just the list given here
490
     * @param array         $orderFields                     An array containing the names of the fields shown, in the right order
491
     * @param array         $extraData
492
     * @param bool          $orderDependingDefaults
493
     * @param bool          $adminPermissions
494
     * @param array         $separateExtraMultipleSelect
495
     * @param array         $customLabelsExtraMultipleSelect
496
     * @param bool          $addEmptyOptionSelects
497
     * @param array         $introductionTextList
498
     * @param array         $requiredFields
499
     * @param bool          $hideGeoLocalizationDetails
500
     *
501
     * @throws Exception
502
     *
503
     * @return array|bool If relevant, returns a one-element array with JS code to be added to the page HTML headers.
504
     *                    Returns false if the form object was not given
505
     */
506
    public function addElements(
507
        $form,
508
        $itemId = 0,
509
        $exclude = [],
510
        $filter = false,
511
        $useTagAsSelect = false,
512
        $showOnlyTheseFields = [],
513
        $orderFields = [],
514
        $extraData = [],
515
        $orderDependingDefaults = false,
516
        $adminPermissions = false,
517
        $separateExtraMultipleSelect = [],
518
        $customLabelsExtraMultipleSelect = [],
519
        $addEmptyOptionSelects = false,
520
        $introductionTextList = [],
521
        $requiredFields = [],
522
        $hideGeoLocalizationDetails = false,
523
        $help = false
524
    ) {
525
        if (empty($form)) {
526
            return false;
527
        }
528
529
        $itemId = (int) $itemId;
530
        $form->addHidden('item_id', $itemId);
531
        $extraData = false;
532
        if (!empty($itemId)) {
533
            $extraData = $this->get_handler_extra_data($itemId);
534
            if (!empty($showOnlyTheseFields)) {
535
                $setData = [];
536
                foreach ($showOnlyTheseFields as $variable) {
537
                    $extraName = 'extra_'.$variable;
538
                    if (in_array($extraName, array_keys($extraData))) {
539
                        $setData[$extraName] = $extraData[$extraName];
540
                    }
541
                }
542
                $form->setDefaults($setData);
543
            } else {
544
                $form->setDefaults($extraData);
545
            }
546
        }
547
548
        $conditions = [];
549
        if ($filter) {
550
            $conditions = ['filter = ?' => 1];
551
        }
552
553
        $extraFields = $this->get_all($conditions, 'option_order');
554
        $extra = $this->set_extra_fields_in_form(
555
            $form,
556
            $extraData,
0 ignored issues
show
Bug introduced by
It seems like $extraData can also be of type false; however, parameter $extraData of ExtraField::set_extra_fields_in_form() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

556
            /** @scrutinizer ignore-type */ $extraData,
Loading history...
557
            $adminPermissions,
558
            $extraFields,
559
            $itemId,
560
            $exclude,
561
            $useTagAsSelect,
562
            $showOnlyTheseFields,
563
            $orderFields,
564
            $orderDependingDefaults,
565
            $separateExtraMultipleSelect,
566
            $customLabelsExtraMultipleSelect,
567
            $addEmptyOptionSelects,
568
            $introductionTextList,
569
            $hideGeoLocalizationDetails,
570
            $help
571
        );
572
573
        if (!empty($requiredFields)) {
574
            /** @var HTML_QuickForm_input $element */
575
            foreach ($form->getElements() as $element) {
576
                $name = str_replace('extra_', '', $element->getName());
577
                if (in_array($name, $requiredFields)) {
578
                    $form->setRequired($element);
579
                }
580
            }
581
        }
582
583
        return $extra;
584
    }
585
586
    /**
587
     * Return an array of all the extra fields available for this item.
588
     *
589
     * @param int $itemId (session_id, question_id, course id)
590
     *
591
     * @return array
592
     */
593
    public function get_handler_extra_data($itemId)
594
    {
595
        if (empty($itemId)) {
596
            return [];
597
        }
598
599
        $extra_data = [];
600
        $fields = $this->get_all();
601
        $field_values = new ExtraFieldValue($this->type);
602
603
        if (!empty($fields)) {
604
            foreach ($fields as $field) {
605
                $field_value = $field_values->get_values_by_handler_and_field_id(
606
                    $itemId,
607
                    $field['id']
608
                );
609
610
                if (self::FIELD_TYPE_TAG == $field['field_type']) {
611
                    $tags = UserManager::get_user_tags_to_string(
612
                        $itemId,
613
                        $field['id'],
614
                        false
615
                    );
616
                    $extra_data['extra_'.$field['variable']] = $tags;
617
618
                    continue;
619
                }
620
621
                if ($field_value) {
622
                    $variable = $field['variable'];
623
                    $field_value = $field_value['value'];
624
                    switch ($field['field_type']) {
625
                        case self::FIELD_TYPE_TAG:
626
                            $tags = UserManager::get_user_tags_to_string(
627
                                $itemId,
628
                                $field['id'],
629
                                false
630
                            );
631
632
                            $extra_data['extra_'.$field['variable']] = $tags;
633
                            break;
634
                        case self::FIELD_TYPE_DOUBLE_SELECT:
635
                        case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
636
                            $selected_options = explode('::', $field_value);
637
                            $firstOption = isset($selected_options[0]) ? $selected_options[0] : '';
638
                            $secondOption = isset($selected_options[1]) ? $selected_options[1] : '';
639
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $firstOption;
640
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable'].'_second'] = $secondOption;
641
642
                            break;
643
                        case self::FIELD_TYPE_SELECT_MULTIPLE:
644
                            $field_value = explode(';', $field_value);
645
                            $extra_data['extra_'.$field['variable']] = $field_value;
646
                            break;
647
                        case self::FIELD_TYPE_RADIO:
648
                            $extra_data['extra_'.$field['variable']]['extra_'.$field['variable']] = $field_value;
649
                            break;
650
                        case self::FIELD_TYPE_TRIPLE_SELECT:
651
                            list($level1, $level2, $level3) = explode(';', $field_value);
652
653
                            $extra_data["extra_$variable"]["extra_$variable"] = $level1;
654
                            $extra_data["extra_$variable"]["extra_{$variable}_second"] = $level2;
655
                            $extra_data["extra_$variable"]["extra_{$variable}_third"] = $level3;
656
                            break;
657
                        default:
658
                            $extra_data['extra_'.$field['variable']] = $field_value;
659
                            break;
660
                    }
661
                } else {
662
                    // Set default values
663
                    if (isset($field['field_default_value']) &&
664
                        !empty($field['field_default_value'])
665
                    ) {
666
                        $extra_data['extra_'.$field['variable']] = $field['field_default_value'];
667
                    }
668
                }
669
            }
670
        }
671
672
        return $extra_data;
673
    }
674
675
    /**
676
     * @param string $type
677
     *
678
     * @return array
679
     */
680
    public function get_all_extra_field_by_type($type)
681
    {
682
        // all the information of the field
683
        $sql = "SELECT * FROM {$this->table}
684
                WHERE
685
                    field_type = '".Database::escape_string($type)."' AND
686
                    extra_field_type = $this->extraFieldType
687
                ";
688
        $result = Database::query($sql);
689
690
        $return = [];
691
        while ($row = Database::fetch_array($result)) {
692
            $return[] = $row['id'];
693
        }
694
695
        return $return;
696
    }
697
698
    /**
699
     * @return array
700
     */
701
    public function get_field_types()
702
    {
703
        return $this->get_extra_fields_by_handler($this->type);
704
    }
705
706
    /**
707
     * @param int $id
708
     */
709
    public function get_field_type_by_id($id)
710
    {
711
        $types = $this->get_field_types();
712
        if (isset($types[$id])) {
713
            return $types[$id];
714
        }
715
716
        return null;
717
    }
718
719
    /**
720
     * Converts a string like this:
721
     * France:Paris;Bretagne;Marseille;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
722
     * into
723
     * array(
724
     *   'France' =>
725
     *      array('Paris', 'Bretagne', 'Marseille'),
726
     *   'Belgique' =>
727
     *      array('Namur', 'Liège')
728
     * ), etc.
729
     *
730
     * @param string $string
731
     *
732
     * @return array
733
     */
734
    public static function extra_field_double_select_convert_string_to_array($string)
735
    {
736
        $options = explode('|', $string);
737
        $options_parsed = [];
738
        $id = 0;
739
740
        if (!empty($options)) {
741
            foreach ($options as $sub_options) {
742
                $options = explode(':', $sub_options);
743
                $sub_sub_options = isset($options[1]) ? explode(';', $options[1]) : [];
744
                $options_parsed[$id] = [
745
                    'label' => $options[0],
746
                    'options' => $sub_sub_options,
747
                ];
748
                $id++;
749
            }
750
        }
751
752
        return $options_parsed;
753
    }
754
755
    /**
756
     * @param $string
757
     *
758
     * @return array
759
     */
760
    public static function tripleSelectConvertStringToArray($string)
761
    {
762
        $options = [];
763
        foreach (explode('|', $string) as $i => $item0) {
764
            $level1 = explode('\\', $item0);
765
766
            foreach ($level1 as $j => $item1) {
767
                if (0 === $j) {
768
                    $options[] = ['label' => $item1, 'options' => []];
769
770
                    continue;
771
                }
772
773
                foreach (explode(':', $item1) as $k => $item2) {
774
                    if (0 === $k) {
775
                        $options[$i]['options'][] = ['label' => $item2, 'options' => []];
776
777
                        continue;
778
                    }
779
780
                    $options[$i]['options'][$j - 1]['options'][] = explode(';', $item2);
781
                }
782
            }
783
        }
784
785
        array_walk_recursive($options, function (&$item) {
786
            $item = trim($item);
787
        });
788
789
        return $options;
790
    }
791
792
    /**
793
     * @param array $options
794
     *
795
     * @return array
796
     */
797
    public static function extra_field_double_select_convert_array_to_ordered_array($options)
798
    {
799
        $optionsParsed = [];
800
        if (!empty($options)) {
801
            foreach ($options as $option) {
802
                if (0 == $option['option_value']) {
803
                    $optionsParsed[$option['id']][] = $option;
804
                } else {
805
                    $optionsParsed[$option['option_value']][] = $option;
806
                }
807
            }
808
        }
809
810
        return $optionsParsed;
811
    }
812
813
    /**
814
     * @return array
815
     */
816
    public static function tripleSelectConvertArrayToOrderedArray(array $options)
817
    {
818
        $level1 = self::getOptionsFromTripleSelect($options, 0);
819
        $level2 = [];
820
        $level3 = [];
821
822
        foreach ($level1 as $item1) {
823
            $level2 += self::getOptionsFromTripleSelect($options, $item1['id']);
824
        }
825
826
        foreach ($level2 as $item2) {
827
            $level3 += self::getOptionsFromTripleSelect($options, $item2['id']);
828
        }
829
830
        return ['level1' => $level1, 'level2' => $level2, 'level3' => $level3];
831
    }
832
833
    /**
834
     * @param array $options the result of the get_field_options_by_field() array
835
     *
836
     * @return string
837
     */
838
    public static function extra_field_double_select_convert_array_to_string($options)
839
    {
840
        $string = null;
841
        $optionsParsed = self::extra_field_double_select_convert_array_to_ordered_array($options);
842
843
        if (!empty($optionsParsed)) {
844
            foreach ($optionsParsed as $option) {
845
                foreach ($option as $key => $item) {
846
                    $string .= $item['display_text'];
847
                    if (0 == $key) {
848
                        $string .= ':';
849
                    } else {
850
                        if (isset($option[$key + 1])) {
851
                            $string .= ';';
852
                        }
853
                    }
854
                }
855
                $string .= '|';
856
            }
857
        }
858
859
        if (!empty($string)) {
860
            $string = substr($string, 0, strlen($string) - 1);
861
        }
862
863
        return $string;
864
    }
865
866
    /**
867
     * @param array $options The result of the get_field_options_by_field() array
868
     *
869
     * @return string
870
     */
871
    public static function extraFieldSelectWithTextConvertArrayToString(array $options)
872
    {
873
        $parsedOptions = self::extra_field_double_select_convert_array_to_ordered_array($options);
874
875
        if (empty($parsedOptions)) {
876
            return '';
877
        }
878
879
        $string = '';
880
        foreach ($parsedOptions as $options) {
881
            $option = current($options);
882
            $string .= $option['display_text'];
883
            $string .= '|';
884
        }
885
886
        return rtrim($string, '|');
887
    }
888
889
    /**
890
     * @return string
891
     */
892
    public static function tripleSelectConvertArrayToString(array $options)
893
    {
894
        $parsedOptions = self::tripleSelectConvertArrayToOrderedArray($options);
895
        $string = '';
896
        foreach ($parsedOptions['level1'] as $item1) {
897
            $string .= $item1['display_text'];
898
            $level2 = self::getOptionsFromTripleSelect($parsedOptions['level2'], $item1['id']);
899
900
            foreach ($level2 as $item2) {
901
                $string .= '\\'.$item2['display_text'].':';
902
                $level3 = self::getOptionsFromTripleSelect($parsedOptions['level3'], $item2['id']);
903
904
                $string .= implode(';', array_column($level3, 'display_text'));
905
            }
906
907
            $string .= '|';
908
        }
909
910
        return trim($string, '\\|;');
911
    }
912
913
    /**
914
     * @param array $params
915
     *
916
     * @return array
917
     */
918
    public function clean_parameters($params)
919
    {
920
        if (!isset($params['variable']) || empty($params['variable'])) {
921
            $params['variable'] = $params['display_text'];
922
        }
923
924
        $params['variable'] = trim(strtolower(str_replace(' ', '_', $params['variable'])));
925
926
        if (!isset($params['field_order'])) {
927
            $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

927
            /** @scrutinizer ignore-call */ 
928
            $max_order = self::get_max_field_order();
Loading history...
928
            $params['field_order'] = $max_order;
929
        } else {
930
            $params['field_order'] = (int) $params['field_order'];
931
        }
932
933
        return $params;
934
    }
935
936
    /**
937
     * @param array $params
938
     * @param bool  $show_query
939
     *
940
     * @return int|bool
941
     */
942
    public function save($params, $show_query = false)
943
    {
944
        $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

944
        /** @scrutinizer ignore-call */ 
945
        $fieldInfo = self::get_handler_field_info_by_field_variable($params['variable']);
Loading history...
945
        $params = $this->clean_parameters($params);
946
        $params['extra_field_type'] = $this->extraFieldType;
947
948
        if ($fieldInfo) {
949
            return $fieldInfo['id'];
950
        } else {
951
            $id = parent::save($params, $show_query);
952
            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...
953
                $fieldOption = new ExtraFieldOption($this->type);
954
                $params['field_id'] = $id;
955
                $fieldOption->save($params);
956
            }
957
958
            return $id;
959
        }
960
    }
961
962
    /**
963
     * {@inheritdoc}
964
     */
965
    public function update($params, $showQuery = false)
966
    {
967
        $params = $this->clean_parameters($params);
968
        if (isset($params['id'])) {
969
            $fieldOption = new ExtraFieldOption($this->type);
970
            $params['field_id'] = $params['id'];
971
            if (empty($params['field_type'])) {
972
                $params['field_type'] = $this->type;
973
            }
974
            $fieldOption->save($params, $showQuery);
975
        }
976
977
        return parent::update($params, $showQuery);
978
    }
979
980
    /**
981
     * @param $id
982
     *
983
     * @return bool
984
     */
985
    public function delete($id)
986
    {
987
        $em = Database::getManager();
988
        $items = $em->getRepository('ChamiloCoreBundle:ExtraFieldSavedSearch')->findBy(['field' => $id]);
989
        if ($items) {
990
            foreach ($items as $item) {
991
                $em->remove($item);
992
            }
993
            $em->flush();
994
        }
995
        $field_option = new ExtraFieldOption($this->type);
996
        $field_option->delete_all_options_by_field_id($id);
997
998
        $session_field_values = new ExtraFieldValue($this->type);
999
        $session_field_values->delete_all_values_by_field_id($id);
1000
1001
        return parent::delete($id);
1002
    }
1003
1004
    /**
1005
     * Add an element that matches the given extra field to the given $form object.
1006
     *
1007
     * @param FormValidator $form                The form these fields are to be attached to
1008
     * @param array         $extraData
1009
     * @param bool          $adminPermissions    Whether the display is considered without edition limits (true) or not (false)
1010
     * @param array         $extra
1011
     * @param int           $itemId              The item (course, user, session, etc) this extra_field is attached to
1012
     * @param array         $exclude             Extra fields to be skipped, by textual ID
1013
     * @param bool          $useTagAsSelect      Whether to show tag fields as select drop-down or not
1014
     * @param array         $showOnlyTheseFields Limit the extra fields shown to just the list given here
1015
     * @param array         $orderFields         An array containing the names of the fields shown, in the right order
1016
     *
1017
     * @throws Exception
1018
     *
1019
     * @return array If relevant, returns a one-element array with JS code to be added to the page HTML headers
1020
     */
1021
    public function set_extra_fields_in_form(
1022
        $form,
1023
        $extraData,
1024
        $adminPermissions = false,
1025
        $extra = [],
1026
        $itemId = null,
1027
        $exclude = [],
1028
        $useTagAsSelect = false,
1029
        $showOnlyTheseFields = [],
1030
        $orderFields = [],
1031
        $orderDependingDefaults = false,
1032
        $separateExtraMultipleSelect = [],
1033
        $customLabelsExtraMultipleSelect = [],
1034
        $addEmptyOptionSelects = false,
1035
        $introductionTextList = [],
1036
        $hideGeoLocalizationDetails = false,
1037
        $help = false
1038
    ) {
1039
        $jquery_ready_content = null;
1040
        if (!empty($extra)) {
1041
            $newOrder = [];
1042
            if (!empty($orderFields)) {
1043
                foreach ($orderFields as $order) {
1044
                    foreach ($extra as $field_details) {
1045
                        if ($order == $field_details['variable']) {
1046
                            $newOrder[] = $field_details;
1047
                        }
1048
                    }
1049
                }
1050
                $extra = $newOrder;
1051
            }
1052
1053
            foreach ($extra as $field_details) {
1054
                if (!empty($showOnlyTheseFields)) {
1055
                    if (!in_array($field_details['variable'], $showOnlyTheseFields)) {
1056
                        continue;
1057
                    }
1058
                }
1059
1060
                // Getting default value id if is set
1061
                $defaultValueId = null;
1062
                if (isset($field_details['options']) && !empty($field_details['options'])) {
1063
                    $valueToFind = null;
1064
                    if (isset($field_details['field_default_value'])) {
1065
                        $valueToFind = $field_details['field_default_value'];
1066
                    }
1067
                    // If a value is found we override the default value
1068
                    if (isset($extraData['extra_'.$field_details['variable']])) {
1069
                        $valueToFind = $extraData['extra_'.$field_details['variable']];
1070
                    }
1071
1072
                    foreach ($field_details['options'] as $option) {
1073
                        if ($option['option_value'] == $valueToFind) {
1074
                            $defaultValueId = $option['id'];
1075
                        }
1076
                    }
1077
                }
1078
1079
                if (!$adminPermissions) {
1080
                    if (0 == $field_details['visible_to_self']) {
1081
                        continue;
1082
                    }
1083
1084
                    if (in_array($field_details['variable'], $exclude)) {
1085
                        continue;
1086
                    }
1087
                }
1088
1089
                if (!empty($introductionTextList) &&
1090
                    in_array($field_details['variable'], array_keys($introductionTextList))
1091
                ) {
1092
                    $form->addHtml($introductionTextList[$field_details['variable']]);
1093
                }
1094
1095
                $freezeElement = false;
1096
                if (!$adminPermissions) {
1097
                    $freezeElement = 0 == $field_details['visible_to_self'] || 0 == $field_details['changeable'];
1098
                }
1099
1100
                $translatedDisplayText = get_lang($field_details['display_text'], true);
1101
                $translatedDisplayHelpText = '';
1102
                if ($help) {
1103
                    $translatedDisplayHelpText .= get_lang($field_details['display_text'].'Help');
1104
                }
1105
                if (!empty($translatedDisplayText)) {
1106
                    if (!empty($translatedDisplayHelpText)) {
1107
                        // In this case, exceptionally, display_text is an array
1108
                        // which is then treated by display_form()
1109
                        $field_details['display_text'] = [$translatedDisplayText, $translatedDisplayHelpText];
1110
                    } else {
1111
                        // We have an helper text, use it
1112
                        $field_details['display_text'] = $translatedDisplayText;
1113
                    }
1114
                }
1115
1116
                switch ($field_details['field_type']) {
1117
                    case self::FIELD_TYPE_TEXT:
1118
                        $form->addElement(
1119
                            'text',
1120
                            'extra_'.$field_details['variable'],
1121
                            $field_details['display_text'],
1122
                            [
1123
                                'id' => 'extra_'.$field_details['variable'],
1124
                            ]
1125
                        );
1126
                        $form->applyFilter(
1127
                            'extra_'.$field_details['variable'],
1128
                            'stripslashes'
1129
                        );
1130
                        $form->applyFilter(
1131
                            'extra_'.$field_details['variable'],
1132
                            'trim'
1133
                        );
1134
                        if ($freezeElement) {
1135
                            $form->freeze('extra_'.$field_details['variable']);
1136
                        }
1137
                        break;
1138
                    case self::FIELD_TYPE_TEXTAREA:
1139
                        $form->addHtmlEditor(
1140
                            'extra_'.$field_details['variable'],
1141
                            $field_details['display_text'],
1142
                            false,
1143
                            false,
1144
                            [
1145
                                'ToolbarSet' => 'Profile',
1146
                                'Width' => '100%',
1147
                                'Height' => '130',
1148
                                'id' => 'extra_'.$field_details['variable'],
1149
                            ]
1150
                        );
1151
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1152
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1153
                        if ($freezeElement) {
1154
                            $form->freeze('extra_'.$field_details['variable']);
1155
                        }
1156
                        break;
1157
                    case self::FIELD_TYPE_RADIO:
1158
                        $group = [];
1159
                        if (isset($field_details['options']) &&
1160
                            !empty($field_details['options'])
1161
                        ) {
1162
                            foreach ($field_details['options'] as $option_details) {
1163
                                $options[$option_details['option_value']] = $option_details['display_text'];
1164
                                $group[] = $form->createElement(
1165
                                    'radio',
1166
                                    'extra_'.$field_details['variable'],
1167
                                    $option_details['option_value'],
1168
                                    $option_details['display_text'].'<br />',
1169
                                    $option_details['option_value']
1170
                                );
1171
                            }
1172
                        }
1173
                        $form->addGroup(
1174
                            $group,
1175
                            'extra_'.$field_details['variable'],
1176
                            $field_details['display_text']
1177
                        );
1178
                        if ($freezeElement) {
1179
                            $form->freeze('extra_'.$field_details['variable']);
1180
                        }
1181
                        break;
1182
                    case self::FIELD_TYPE_CHECKBOX:
1183
                        $group = [];
1184
                        if (isset($field_details['options']) &&
1185
                            !empty($field_details['options'])
1186
                        ) {
1187
                            foreach ($field_details['options'] as $option_details) {
1188
                                $options[$option_details['option_value']] = $option_details['display_text'];
1189
                                $group[] = $form->createElement(
1190
                                    'checkbox',
1191
                                    'extra_'.$field_details['variable'],
1192
                                    $option_details['option_value'],
1193
                                    $option_details['display_text'].'<br />',
1194
                                    $option_details['option_value']
1195
                                );
1196
                            }
1197
                        } else {
1198
                            $fieldVariable = "extra_{$field_details['variable']}";
1199
                            $checkboxAttributes = [];
1200
                            if (is_array($extraData) &&
1201
                                array_key_exists($fieldVariable, $extraData)
1202
                            ) {
1203
                                if (!empty($extraData[$fieldVariable])) {
1204
                                    $checkboxAttributes['checked'] = 1;
1205
                                }
1206
                            }
1207
1208
                            if (empty($checkboxAttributes) &&
1209
                                isset($field_details['default_value']) && empty($extraData)) {
1210
                                if (1 == $field_details['default_value']) {
1211
                                    $checkboxAttributes['checked'] = 1;
1212
                                }
1213
                            }
1214
1215
                            // We assume that is a switch on/off with 1 and 0 as values
1216
                            $group[] = $form->createElement(
1217
                                'checkbox',
1218
                                'extra_'.$field_details['variable'],
1219
                                null,
1220
                                //$field_details['display_text'].'<br />',
1221
                                get_lang('Yes'),
1222
                                $checkboxAttributes
1223
                            );
1224
                        }
1225
1226
                        $form->addGroup(
1227
                            $group,
1228
                            'extra_'.$field_details['variable'],
1229
                            $field_details['display_text']
1230
                        );
1231
                        if ($freezeElement) {
1232
                            $form->freeze('extra_'.$field_details['variable']);
1233
                        }
1234
                        break;
1235
                    case self::FIELD_TYPE_SELECT:
1236
                        $this->addSelectElement($form, $field_details, $defaultValueId, $freezeElement);
1237
                        break;
1238
                    case self::FIELD_TYPE_SELECT_MULTIPLE:
1239
                        $options = [];
1240
                        if (empty($defaultValueId)) {
1241
                            $options[''] = get_lang('SelectAnOption');
1242
                        }
1243
                        foreach ($field_details['options'] as $optionDetails) {
1244
                            $options[$optionDetails['option_value']] = $optionDetails['display_text'];
1245
                        }
1246
                        $form->addElement(
1247
                            'select',
1248
                            'extra_'.$field_details['variable'],
1249
                            $field_details['display_text'],
1250
                            $options,
1251
                            [
1252
                                'multiple' => 'multiple',
1253
                                'id' => 'extra_'.$field_details['variable'],
1254
                            ]
1255
                        );
1256
                        if ($freezeElement) {
1257
                            $form->freeze('extra_'.$field_details['variable']);
1258
                        }
1259
                        break;
1260
                    case self::FIELD_TYPE_DATE:
1261
                        $form->addDatePicker('extra_'.$field_details['variable'], $field_details['display_text']);
1262
                        if ($freezeElement) {
1263
                            $form->freeze('extra_'.$field_details['variable']);
1264
                        }
1265
                        break;
1266
                    case self::FIELD_TYPE_DATETIME:
1267
                        $form->addDateTimePicker(
1268
                            'extra_'.$field_details['variable'],
1269
                            $field_details['display_text']
1270
                        );
1271
1272
                        $defaults['extra_'.$field_details['variable']] = api_get_local_time();
1273
                        if (!isset($form->_defaultValues['extra_'.$field_details['variable']])) {
1274
                            $form->setDefaults($defaults);
1275
                        }
1276
                        if ($freezeElement) {
1277
                            $form->freeze('extra_'.$field_details['variable']);
1278
                        }
1279
                        break;
1280
                    case self::FIELD_TYPE_DOUBLE_SELECT:
1281
                        $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

1281
                        $jquery_ready_content .= self::/** @scrutinizer ignore-call */ addDoubleSelectElement(
Loading history...
1282
                            $form,
1283
                            $field_details,
1284
                            $extraData,
1285
                            $freezeElement
1286
                        );
1287
                        break;
1288
                    case self::FIELD_TYPE_DIVIDER:
1289
                        $form->addHtml('
1290
                            <div class="form-group ">
1291
                                <div class="col-sm-12">
1292
                                    <div class="panel-separator">
1293
                                       <h4 id="'.$field_details['variable'].'" class="form-separator">'
1294
                                            .$field_details['display_text'].'
1295
                                       </h4>
1296
                                    </div>
1297
                                </div>
1298
                            </div>
1299
                        ');
1300
                        break;
1301
                    case self::FIELD_TYPE_TAG:
1302
                        $variable = $field_details['variable'];
1303
                        $field_id = $field_details['id'];
1304
                        $separateValue = 0;
1305
                        if (isset($separateExtraMultipleSelect[$field_details['variable']])) {
1306
                            $separateValue = $separateExtraMultipleSelect[$field_details['variable']];
1307
                        }
1308
1309
                        $selectedOptions = [];
1310
                        if ($separateValue > 0) {
1311
                            $em = Database::getManager();
1312
                            $fieldTags = $em
1313
                                ->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1314
                                ->findBy(
1315
                                    [
1316
                                        'fieldId' => $field_id,
1317
                                        'itemId' => $itemId,
1318
                                    ]
1319
                                );
1320
                            // ofaj
1321
1322
                            for ($i = 0; $i < $separateValue; $i++) {
1323
                                $tagsSelect = $form->addElement(
1324
                                    'select',
1325
                                    'extra_'.$field_details['variable'].'['.$i.']',
1326
                                    $customLabelsExtraMultipleSelect[$field_details['variable']][$i], //$field_details['display_text'],
1327
                                    null,
1328
                                    ['id' => 'extra_'.$field_details['variable'].'_'.$i]
1329
                                );
1330
1331
                                if ($addEmptyOptionSelects) {
1332
                                    $tagsSelect->addOption(
1333
                                        '',
1334
                                        ''
1335
                                    );
1336
                                }
1337
1338
                                foreach ($fieldTags as $fieldTag) {
1339
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1340
1341
                                    if (empty($tag)) {
1342
                                        continue;
1343
                                    }
1344
1345
                                    $tagsSelect->addOption(
1346
                                        $tag->getTag(),
1347
                                        $tag->getTag()
1348
                                    );
1349
                                }
1350
                            }
1351
                        } else {
1352
                            $tagsSelect = $form->addSelect(
1353
                                "extra_{$field_details['variable']}",
1354
                                $field_details['display_text'],
1355
                                [],
1356
                                ['style' => 'width: 100%;']
1357
                            );
1358
1359
                            if (false === $useTagAsSelect) {
1360
                                $tagsSelect->setAttribute('class', null);
1361
                            }
1362
1363
                            $tagsSelect->setAttribute(
1364
                                'id',
1365
                                "extra_{$field_details['variable']}"
1366
                            );
1367
                            $tagsSelect->setMultiple(true);
1368
1369
                            $selectedOptions = [];
1370
                            if ('user' === $this->type) {
1371
                                // The magic should be here
1372
                                $user_tags = UserManager::get_user_tags(
1373
                                    $itemId,
1374
                                    $field_details['id']
1375
                                );
1376
1377
                                if (is_array($user_tags) && count($user_tags) > 0) {
1378
                                    foreach ($user_tags as $tag) {
1379
                                        if (empty($tag['tag'])) {
1380
                                            continue;
1381
                                        }
1382
                                        $tagsSelect->addOption(
1383
                                            $tag['tag'],
1384
                                            $tag['tag'],
1385
                                            [
1386
                                                'selected' => 'selected',
1387
                                                'class' => 'selected',
1388
                                            ]
1389
                                        );
1390
                                        $selectedOptions[] = $tag['tag'];
1391
                                    }
1392
                                }
1393
                                $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
1394
                            } else {
1395
                                $em = Database::getManager();
1396
                                $fieldTags = $em->getRepository(
1397
                                    'ChamiloCoreBundle:ExtraFieldRelTag'
1398
                                )
1399
                                ->findBy(
1400
                                    [
1401
                                        'fieldId' => $field_id,
1402
                                        'itemId' => $itemId,
1403
                                    ]
1404
                                );
1405
1406
                                /** @var ExtraFieldRelTag $fieldTag */
1407
                                foreach ($fieldTags as $fieldTag) {
1408
                                    /** @var Tag $tag */
1409
                                    $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1410
1411
                                    if (empty($tag)) {
1412
                                        continue;
1413
                                    }
1414
                                    $tagsSelect->addOption(
1415
                                        $tag->getTag(),
1416
                                        $tag->getTag()
1417
                                    );
1418
                                    $selectedOptions[] = $tag->getTag();
1419
                                }
1420
1421
                                if (!empty($extraData) && isset($extraData['extra_'.$field_details['variable']])) {
1422
                                    $data = $extraData['extra_'.$field_details['variable']];
1423
                                    if (!empty($data)) {
1424
                                        foreach ($data as $option) {
1425
                                            $tagsSelect->addOption(
1426
                                                $option,
1427
                                                $option
1428
                                            );
1429
                                        }
1430
                                    }
1431
                                }
1432
1433
                                if ($useTagAsSelect) {
1434
                                    $fieldTags = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag')
1435
                                        ->findBy(
1436
                                            [
1437
                                                'fieldId' => $field_id,
1438
                                            ]
1439
                                        );
1440
                                    $tagsAdded = [];
1441
                                    foreach ($fieldTags as $fieldTag) {
1442
                                        $tag = $em->find('ChamiloCoreBundle:Tag', $fieldTag->getTagId());
1443
1444
                                        if (empty($tag)) {
1445
                                            continue;
1446
                                        }
1447
1448
                                        $tagText = $tag->getTag();
1449
1450
                                        if (in_array($tagText, $tagsAdded)) {
1451
                                            continue;
1452
                                        }
1453
1454
                                        $tagsSelect->addOption(
1455
                                            $tag->getTag(),
1456
                                            $tag->getTag(),
1457
                                            []
1458
                                        );
1459
1460
                                        $tagsAdded[] = $tagText;
1461
                                    }
1462
                                }
1463
                                $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php';
1464
                            }
1465
1466
                            $form->setDefaults(
1467
                                [
1468
                                    'extra_'.$field_details['variable'] => $selectedOptions,
1469
                                ]
1470
                            );
1471
1472
                            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...
1473
                                $jquery_ready_content .= "
1474
                                $('#extra_$variable').select2({
1475
                                    ajax: {
1476
                                        url: '$url?a=search_tags&field_id=$field_id&type={$this->type}',
1477
                                        processResults: function (data) {
1478
                                            return {
1479
                                                results: data.items
1480
                                            }
1481
                                        }
1482
                                    },
1483
                                    cache: false,
1484
                                    tags: true,
1485
                                    tokenSeparators: [','],
1486
                                    placeholder: '".get_lang('StartToType')."'
1487
                                });
1488
                            ";
1489
                            }
1490
                        }
1491
1492
                        break;
1493
                    case self::FIELD_TYPE_TIMEZONE:
1494
                        $form->addElement(
1495
                            'select',
1496
                            'extra_'.$field_details['variable'],
1497
                            $field_details['display_text'],
1498
                            api_get_timezones(),
1499
                            ''
1500
                        );
1501
                        if ($freezeElement) {
1502
                            $form->freeze('extra_'.$field_details['variable']);
1503
                        }
1504
                        break;
1505
                    case self::FIELD_TYPE_SOCIAL_PROFILE:
1506
                        // get the social network's favicon
1507
                        $extra_data_variable = isset($extraData['extra_'.$field_details['variable']])
1508
                            ? $extraData['extra_'.$field_details['variable']]
1509
                            : null;
1510
                        $field_default_value = isset($field_details['field_default_value'])
1511
                            ? $field_details['field_default_value']
1512
                            : null;
1513
                        $icon_path = UserManager::get_favicon_from_url(
1514
                            $extra_data_variable,
1515
                            $field_default_value
1516
                        );
1517
                        // special hack for hi5
1518
                        $leftpad = '1.7';
1519
                        $top = '0.4';
1520
                        $domain = parse_url($icon_path, PHP_URL_HOST);
1521
                        if ('www.hi5.com' === $domain || 'hi5.com' === $domain) {
1522
                            $leftpad = '3';
1523
                            $top = '0';
1524
                        }
1525
                        // print the input field
1526
                        $form->addElement(
1527
                            'text',
1528
                            'extra_'.$field_details['variable'],
1529
                            $field_details['display_text'],
1530
                            [
1531
                                'size' => 60,
1532
                                'size' => implode(
1533
                                    '; ',
1534
                                    [
1535
                                        "background-image: url('$icon_path')",
1536
                                        'background-repeat: no-repeat',
1537
                                        "background-position: 0.4em {$top}em",
1538
                                        "padding-left: {$leftpad}em",
1539
                                    ]
1540
                                ),
1541
                            ]
1542
                        );
1543
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1544
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1545
                        if ($freezeElement) {
1546
                            $form->freeze('extra_'.$field_details['variable']);
1547
                        }
1548
                        break;
1549
                    case self::FIELD_TYPE_MOBILE_PHONE_NUMBER:
1550
                        $form->addElement(
1551
                            'text',
1552
                            'extra_'.$field_details['variable'],
1553
                            $field_details['display_text'].' ('.get_lang('CountryDialCode').')',
1554
                            ['size' => 40, 'placeholder' => '(xx)xxxxxxxxx']
1555
                        );
1556
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1557
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1558
                        $form->applyFilter('extra_'.$field_details['variable'], 'mobile_phone_number_filter');
1559
                        $form->addRule(
1560
                            'extra_'.$field_details['variable'],
1561
                            get_lang('MobilePhoneNumberWrong'),
1562
                            'mobile_phone_number'
1563
                        );
1564
                        if ($freezeElement) {
1565
                            $form->freeze('extra_'.$field_details['variable']);
1566
                        }
1567
                        break;
1568
                    case self::FIELD_TYPE_INTEGER:
1569
                        $form->addElement(
1570
                            'number',
1571
                            'extra_'.$field_details['variable'],
1572
                            $field_details['display_text'],
1573
                            ['class' => 'span1', 'step' => 1]
1574
                        );
1575
1576
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1577
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1578
                        $form->applyFilter('extra_'.$field_details['variable'], 'intval');
1579
1580
                        if ($freezeElement) {
1581
                            $form->freeze('extra_'.$field_details['variable']);
1582
                        }
1583
                        break;
1584
                    case self::FIELD_TYPE_FILE_IMAGE:
1585
                        $fieldVariable = "extra_{$field_details['variable']}";
1586
                        $fieldTexts = [
1587
                            $field_details['display_text'],
1588
                        ];
1589
1590
                        if (is_array($extraData) && array_key_exists($fieldVariable, $extraData)) {
1591
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1592
                                $fieldTexts[] = Display::img(
1593
                                    api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1594
                                    $field_details['display_text'],
1595
                                    ['width' => '300']
1596
                                );
1597
                            }
1598
                        }
1599
1600
                        if ('Image' === $fieldTexts[0]) {
1601
                            $fieldTexts[0] = get_lang($fieldTexts[0]);
1602
                        }
1603
1604
                        $form->addFile(
1605
                            $fieldVariable,
1606
                            $fieldTexts,
1607
                            ['accept' => 'image/*', 'id' => 'extra_image', 'crop_image' => 'true']
1608
                        );
1609
1610
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1611
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1612
1613
                        $allowedPictureTypes = ['jpg', 'jpeg', 'png', 'gif'];
1614
                        $form->addRule(
1615
                            'extra_'.$field_details['variable'],
1616
                            get_lang('OnlyImagesAllowed').' ('.implode(',', $allowedPictureTypes).')',
1617
                            'filetype',
1618
                            $allowedPictureTypes
1619
                        );
1620
1621
                        if ($freezeElement) {
1622
                            $form->freeze('extra_'.$field_details['variable']);
1623
                        }
1624
                        break;
1625
                    case self::FIELD_TYPE_FLOAT:
1626
                        $form->addElement(
1627
                            'number',
1628
                            'extra_'.$field_details['variable'],
1629
                            $field_details['display_text'],
1630
                            ['class' => 'span1', 'step' => '0.01']
1631
                        );
1632
1633
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1634
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1635
                        $form->applyFilter('extra_'.$field_details['variable'], 'floatval');
1636
1637
                        if ($freezeElement) {
1638
                            $form->freeze('extra_'.$field_details['variable']);
1639
                        }
1640
                        break;
1641
                    case self::FIELD_TYPE_FILE:
1642
                        $fieldVariable = "extra_{$field_details['variable']}";
1643
                        $fieldTexts = [
1644
                            $field_details['display_text'],
1645
                        ];
1646
1647
                        if (is_array($extraData) &&
1648
                            array_key_exists($fieldVariable, $extraData)
1649
                        ) {
1650
                            if (file_exists(api_get_path(SYS_UPLOAD_PATH).$extraData[$fieldVariable])) {
1651
                                $linkToDelete = '';
1652
                                $divItemId = $field_details['variable'];
1653
                                if (api_is_platform_admin()) {
1654
                                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?type='.$this->type;
1655
                                    $url .= '&a=delete_file&field_id='.$field_details['id'].'&item_id='.$itemId;
1656
1657
                                    $deleteId = $field_details['variable'].'_delete';
1658
                                    $form->addHtml("
1659
                                        <script>
1660
                                            $(function() {
1661
                                                $('#".$deleteId."').on('click', function() {
1662
                                                    $.ajax({
1663
                                                        type: 'GET',
1664
                                                        url: '".$url."',
1665
                                                        success: function(result) {
1666
                                                            if (result == 1) {
1667
                                                                $('#".$divItemId."').html('".get_lang('Deleted')."');
1668
                                                            }
1669
                                                        }
1670
                                                    });
1671
                                                });
1672
                                            });
1673
                                        </script>
1674
                                    ");
1675
1676
                                    $linkToDelete = '&nbsp;'.Display::url(
1677
                                        Display::return_icon('delete.png', get_lang('Delete')),
1678
                                        'javascript:void(0)',
1679
                                        ['id' => $deleteId]
1680
                                    );
1681
                                }
1682
                                $fieldTexts[] = '<div id="'.$divItemId.'">'.Display::url(
1683
                                    basename($extraData[$fieldVariable]),
1684
                                    api_get_path(WEB_UPLOAD_PATH).$extraData[$fieldVariable],
1685
                                    [
1686
                                        'title' => $field_details['display_text'],
1687
                                        'target' => '_blank',
1688
                                    ]
1689
                                ).$linkToDelete.'</div>';
1690
                            }
1691
                        }
1692
1693
                        $form->addElement(
1694
                            'file',
1695
                            $fieldVariable,
1696
                            $fieldTexts,
1697
                            []
1698
                        );
1699
1700
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1701
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');
1702
1703
                        if ($freezeElement) {
1704
                            $form->freeze('extra_'.$field_details['variable']);
1705
                        }
1706
                        break;
1707
                    case self::FIELD_TYPE_VIDEO_URL:
1708
                        $form->addUrl(
1709
                            "extra_{$field_details['variable']}",
1710
                            $field_details['display_text'],
1711
                            false,
1712
                            ['placeholder' => 'https://']
1713
                        );
1714
                        if ($freezeElement) {
1715
                            $form->freeze('extra_'.$field_details['variable']);
1716
                        }
1717
                        break;
1718
                    case self::FIELD_TYPE_LETTERS_ONLY:
1719
                        $form->addTextLettersOnly(
1720
                            "extra_{$field_details['variable']}",
1721
                            $field_details['display_text']
1722
                        );
1723
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1724
1725
                        if ($freezeElement) {
1726
                            $form->freeze('extra_'.$field_details['variable']);
1727
                        }
1728
                        break;
1729
                    case self::FIELD_TYPE_ALPHANUMERIC:
1730
                        $form->addTextAlphanumeric(
1731
                            "extra_{$field_details['variable']}",
1732
                            $field_details['display_text']
1733
                        );
1734
                        $form->applyFilter(
1735
                            'extra_'.$field_details['variable'],
1736
                            'stripslashes'
1737
                        );
1738
                        if ($freezeElement) {
1739
                            $form->freeze('extra_'.$field_details['variable']);
1740
                        }
1741
                        break;
1742
                    case self::FIELD_TYPE_LETTERS_SPACE:
1743
                        $form->addTextLettersAndSpaces(
1744
                            "extra_{$field_details['variable']}",
1745
                            $field_details['display_text']
1746
                        );
1747
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1748
1749
                        if ($freezeElement) {
1750
                            $form->freeze('extra_'.$field_details['variable']);
1751
                        }
1752
                        break;
1753
                    case self::FIELD_TYPE_ALPHANUMERIC_SPACE:
1754
                        $form->addTextAlphanumericAndSpaces(
1755
                            "extra_{$field_details['variable']}",
1756
                            $field_details['display_text']
1757
                        );
1758
                        $form->applyFilter(
1759
                            'extra_'.$field_details['variable'],
1760
                            'stripslashes'
1761
                        );
1762
                        if ($freezeElement) {
1763
                            $form->freeze('extra_'.$field_details['variable']);
1764
                        }
1765
                        break;
1766
                    case self::FIELD_TYPE_GEOLOCALIZATION_COORDINATES:
1767
                    case self::FIELD_TYPE_GEOLOCALIZATION:
1768
                        $dataValue = isset($extraData['extra_'.$field_details['variable']])
1769
                            ? $extraData['extra_'.$field_details['variable']]
1770
                            : '';
1771
1772
                        $form->addGeoLocationMapField(
1773
                            'extra_'.$field_details['variable'],
1774
                            $field_details['display_text'],
1775
                            $dataValue,
1776
                            $hideGeoLocalizationDetails
1777
                        );
1778
1779
                        /*$form->addElement(
1780
                            'text',
1781
                            'extra_'.$field_details['variable'],
1782
                            $field_details['display_text'],
1783
                            ['id' => 'extra_'.$field_details['variable']]
1784
                        );
1785
                        $form->addHidden(
1786
                            'extra_'.$field_details['variable'].'_coordinates',
1787
                            '',
1788
                            ['id' => 'extra_'.$field_details['variable'].'_coordinates']
1789
                        );
1790
1791
                        $form->applyFilter('extra_'.$field_details['variable'], 'stripslashes');
1792
                        $form->applyFilter('extra_'.$field_details['variable'], 'trim');*/
1793
1794
                        if ($freezeElement) {
1795
                            $form->freeze('extra_'.$field_details['variable']);
1796
                        }
1797
                        break;
1798
                    case self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD:
1799
                        $jquery_ready_content .= $this->addSelectWithTextFieldElement(
1800
                            $form,
1801
                            $field_details,
1802
                            $freezeElement
1803
                        );
1804
                        break;
1805
                    case self::FIELD_TYPE_TRIPLE_SELECT:
1806
                        $jquery_ready_content .= $this->addTripleSelectElement(
1807
                            $form,
1808
                            $field_details,
1809
                            is_array($extraData) ? $extraData : [],
1810
                            $freezeElement
1811
                        );
1812
                        break;
1813
                }
1814
            }
1815
        }
1816
1817
        $return = [];
1818
        $return['jquery_ready_content'] = $jquery_ready_content;
1819
1820
        return $return;
1821
    }
1822
1823
    /**
1824
     * @param $breadcrumb
1825
     * @param $action
1826
     */
1827
    public function setupBreadcrumb(&$breadcrumb, $action)
1828
    {
1829
        if ('add' === $action) {
1830
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
1831
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Add')];
1832
        } elseif ('edit' === $action) {
1833
            $breadcrumb[] = ['url' => $this->pageUrl, 'name' => $this->pageName];
1834
            $breadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')];
1835
        } else {
1836
            $breadcrumb[] = ['url' => '#', 'name' => $this->pageName];
1837
        }
1838
    }
1839
1840
    /**
1841
     * Displays the title + grid.
1842
     */
1843
    public function display()
1844
    {
1845
        // action links
1846
        echo '<div class="actions">';
1847
        echo '<a href="../admin/index.php">';
1848
        echo Display::return_icon(
1849
            'back.png',
1850
            get_lang('BackTo').' '.get_lang('PlatformAdmin'),
1851
            '',
1852
            ICON_SIZE_MEDIUM
1853
        );
1854
        echo '</a>';
1855
        echo '<a href="'.api_get_self().'?action=add&type='.$this->type.'">';
1856
        echo Display::return_icon(
1857
            'add_user_fields.png',
1858
            get_lang('Add'),
1859
            '',
1860
            ICON_SIZE_MEDIUM
1861
        );
1862
        echo '</a>';
1863
        echo '</div>';
1864
        echo Display::grid_html($this->type.'_fields');
1865
    }
1866
1867
    /**
1868
     * @return array
1869
     */
1870
    public function getJqgridColumnNames()
1871
    {
1872
        return [
1873
            get_lang('Name'),
1874
            get_lang('FieldLabel'),
1875
            get_lang('Type'),
1876
            get_lang('FieldChangeability'),
1877
            get_lang('VisibleToSelf'),
1878
            get_lang('VisibleToOthers'),
1879
            get_lang('Filter'),
1880
            get_lang('FieldOrder'),
1881
            get_lang('Actions'),
1882
        ];
1883
    }
1884
1885
    /**
1886
     * @return array
1887
     */
1888
    public function getJqgridColumnModel()
1889
    {
1890
        return [
1891
            [
1892
                'name' => 'display_text',
1893
                'index' => 'display_text',
1894
                'width' => '140',
1895
                'align' => 'left',
1896
            ],
1897
            [
1898
                'name' => 'variable',
1899
                'index' => 'variable',
1900
                'width' => '90',
1901
                'align' => 'left',
1902
                'sortable' => 'true',
1903
            ],
1904
            [
1905
                'name' => 'field_type',
1906
                'index' => 'field_type',
1907
                'width' => '70',
1908
                'align' => 'left',
1909
                'sortable' => 'true',
1910
            ],
1911
            [
1912
                'name' => 'changeable',
1913
                'index' => 'changeable',
1914
                'width' => '35',
1915
                'align' => 'left',
1916
                'sortable' => 'true',
1917
            ],
1918
            [
1919
                'name' => 'visible_to_self',
1920
                'index' => 'visible_to_self',
1921
                'width' => '45',
1922
                'align' => 'left',
1923
                'sortable' => 'true',
1924
            ],
1925
            [
1926
                'name' => 'visible_to_others',
1927
                'index' => 'visible_to_others',
1928
                'width' => '35',
1929
                'align' => 'left',
1930
                'sortable' => 'true',
1931
            ],
1932
            [
1933
                'name' => 'filter',
1934
                'index' => 'filter',
1935
                'width' => '30',
1936
                'align' => 'left',
1937
                'sortable' => 'true',
1938
            ],
1939
            [
1940
                'name' => 'field_order',
1941
                'index' => 'field_order',
1942
                'width' => '25',
1943
                'align' => 'left',
1944
                'sortable' => 'true',
1945
            ],
1946
            [
1947
                'name' => 'actions',
1948
                'index' => 'actions',
1949
                'width' => '40',
1950
                'align' => 'left',
1951
                'formatter' => 'action_formatter',
1952
                'sortable' => 'false',
1953
            ],
1954
        ];
1955
    }
1956
1957
    /**
1958
     * @param string $url
1959
     * @param string $action
1960
     *
1961
     * @return FormValidator
1962
     */
1963
    public function return_form($url, $action)
1964
    {
1965
        $form = new FormValidator($this->type.'_field', 'post', $url);
1966
1967
        $form->addElement('hidden', 'type', $this->type);
1968
        $id = isset($_GET['id']) ? (int) $_GET['id'] : null;
1969
        $form->addElement('hidden', 'id', $id);
1970
1971
        // Setting the form elements
1972
        $header = get_lang('Add');
1973
        $defaults = [];
1974
1975
        if ('edit' === $action) {
1976
            $header = get_lang('Modify');
1977
            // Setting the defaults
1978
            $defaults = $this->get($id, false);
1979
        }
1980
1981
        $form->addElement('header', $header);
1982
1983
        if ('edit' === $action) {
1984
            $translateUrl = api_get_path(WEB_CODE_PATH).'extrafield/translate.php?'
1985
                .http_build_query(['extra_field' => $id]);
1986
            $translateButton = Display::toolbarButton(get_lang('TranslateThisTerm'), $translateUrl, 'language', 'link');
1987
1988
            $form->addText(
1989
                'display_text',
1990
                [get_lang('Name'), $translateButton]
1991
            );
1992
        } else {
1993
            $form->addElement('text', 'display_text', get_lang('Name'));
1994
        }
1995
1996
        // Field type
1997
        $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

1997
        /** @scrutinizer ignore-call */ 
1998
        $types = self::get_field_types();
Loading history...
1998
1999
        $form->addElement(
2000
            'select',
2001
            'field_type',
2002
            get_lang('FieldType'),
2003
            $types,
2004
            ['id' => 'field_type']
2005
        );
2006
        $form->addElement('label', get_lang('Example'), '<div id="example">-</div>');
2007
        $form->addElement('text', 'variable', get_lang('FieldLabel'), ['class' => 'span5']);
2008
        $form->addElement(
2009
            'text',
2010
            'field_options',
2011
            get_lang('FieldPossibleValues'),
2012
            ['id' => 'field_options', 'class' => 'span6']
2013
        );
2014
2015
        $fieldWithOptions = [
2016
            self::FIELD_TYPE_RADIO,
2017
            self::FIELD_TYPE_SELECT_MULTIPLE,
2018
            self::FIELD_TYPE_SELECT,
2019
            self::FIELD_TYPE_TAG,
2020
            self::FIELD_TYPE_DOUBLE_SELECT,
2021
            self::FIELD_TYPE_SELECT_WITH_TEXT_FIELD,
2022
            self::FIELD_TYPE_TRIPLE_SELECT,
2023
        ];
2024
2025
        if ('edit' == $action) {
2026
            if (in_array($defaults['field_type'], $fieldWithOptions)) {
2027
                $url = Display::url(
2028
                    get_lang('EditExtraFieldOptions'),
2029
                    'extra_field_options.php?type='.$this->type.'&field_id='.$id
2030
                );
2031
                $form->addElement('label', null, $url);
2032
2033
                if (self::FIELD_TYPE_SELECT == $defaults['field_type']) {
2034
                    $urlWorkFlow = Display::url(
2035
                        get_lang('EditExtraFieldWorkFlow'),
2036
                        'extra_field_workflow.php?type='.$this->type.'&field_id='.$id
2037
                    );
2038
                    $form->addElement('label', null, $urlWorkFlow);
2039
                }
2040
2041
                $form->freeze('field_options');
2042
            }
2043
        }
2044
        $form->addElement(
2045
            'text',
2046
            'default_value',
2047
            get_lang('FieldDefaultValue'),
2048
            ['id' => 'default_value']
2049
        );
2050
2051
        $group = [];
2052
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('Yes'), 1);
2053
        $group[] = $form->createElement('radio', 'visible_to_self', null, get_lang('No'), 0);
2054
        $form->addGroup($group, '', get_lang('VisibleToSelf'), null, false);
2055
2056
        $group = [];
2057
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('Yes'), 1);
2058
        $group[] = $form->createElement('radio', 'visible_to_others', null, get_lang('No'), 0);
2059
        $form->addGroup($group, '', get_lang('VisibleToOthers'), null, false);
2060
2061
        $group = [];
2062
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('Yes'), 1);
2063
        $group[] = $form->createElement('radio', 'changeable', null, get_lang('No'), 0);
2064
        $form->addGroup($group, '', get_lang('FieldChangeability'), null, false);
2065
2066
        $group = [];
2067
        $group[] = $form->createElement('radio', 'filter', null, get_lang('Yes'), 1);
2068
        $group[] = $form->createElement('radio', 'filter', null, get_lang('No'), 0);
2069
        $form->addGroup($group, '', get_lang('FieldFilter'), null, false);
2070
2071
        /* Enable this when field_loggeable is introduced as a table field (2.0)
2072
        $group   = array();
2073
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('Yes'), 1);
2074
        $group[] = $form->createElement('radio', 'field_loggeable', null, get_lang('No'), 0);
2075
        $form->addGroup($group, '', get_lang('FieldLoggeable'), '', false);
2076
        */
2077
2078
        $form->addElement('text', 'field_order', get_lang('FieldOrder'));
2079
2080
        if ('edit' == $action) {
2081
            $option = new ExtraFieldOption($this->type);
2082
            $defaults['field_options'] = $option->get_field_options_by_field_to_string($id);
2083
            $form->addButtonUpdate(get_lang('Modify'));
2084
        } else {
2085
            $defaults['visible_to_self'] = 0;
2086
            $defaults['visible_to_others'] = 0;
2087
            $defaults['changeable'] = 0;
2088
            $defaults['filter'] = 0;
2089
            $form->addButtonCreate(get_lang('Add'));
2090
        }
2091
2092
        /*if (!empty($defaults['created_at'])) {
2093
            $defaults['created_at'] = api_convert_and_format_date($defaults['created_at']);
2094
        }
2095
        if (!empty($defaults['updated_at'])) {
2096
            $defaults['updated_at'] = api_convert_and_format_date($defaults['updated_at']);
2097
        }*/
2098
        $form->setDefaults($defaults);
2099
2100
        // Setting the rules
2101
        $form->addRule('display_text', get_lang('ThisFieldIsRequired'), 'required');
2102
        $form->addRule('field_type', get_lang('ThisFieldIsRequired'), 'required');
2103
2104
        return $form;
2105
    }
2106
2107
    /**
2108
     * @param $token
2109
     *
2110
     * @return string
2111
     */
2112
    public function getJqgridActionLinks($token)
2113
    {
2114
        //With this function we can add actions to the jgrid (edit, delete, etc)
2115
        $editIcon = Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL);
2116
        $deleteIcon = Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL);
2117
        $confirmMessage = addslashes(
2118
            api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES)
2119
        );
2120
2121
        $editButton = <<<JAVASCRIPT
2122
            <a href="?action=edit&type={$this->type}&id=' + options.rowId + '" class="btn btn-link btn-xs">\
2123
                $editIcon\
2124
            </a>
2125
JAVASCRIPT;
2126
        $deleteButton = <<<JAVASCRIPT
2127
            <a \
2128
                onclick="if (!confirm(\'$confirmMessage\')) {return false;}" \
2129
                href="?sec_token=$token&type={$this->type}&id=' + options.rowId + '&action=delete" \
2130
                class="btn btn-link btn-xs">\
2131
                $deleteIcon\
2132
            </a>
2133
JAVASCRIPT;
2134
2135
        return "function action_formatter(cellvalue, options, rowObject) {
2136
            return '$editButton $deleteButton';
2137
        }";
2138
    }
2139
2140
    /**
2141
     * @param array $columns
2142
     * @param array $column_model
2143
     * @param array $extraFields
2144
     *
2145
     * @return array
2146
     */
2147
    public function getRules(&$columns, &$column_model, $extraFields = [], $checkExtraFieldExistence = false)
2148
    {
2149
        $fields = $this->get_all(
2150
            [
2151
                'visible_to_self = ? AND filter = ?' => [1, 1],
2152
            ],
2153
            'display_text'
2154
        );
2155
        $extraFieldOption = new ExtraFieldOption($this->type);
2156
2157
        $rules = [];
2158
        if (!empty($fields)) {
2159
            foreach ($fields as $field) {
2160
                $search_options = [];
2161
                $type = 'text';
2162
                if (in_array($field['field_type'], [self::FIELD_TYPE_SELECT, self::FIELD_TYPE_DOUBLE_SELECT])) {
2163
                    $type = 'select';
2164
                    $search_options['sopt'] = ['eq', 'ne']; //equal not equal
2165
                } else {
2166
                    $search_options['sopt'] = ['cn', 'nc']; //contains not contains
2167
                }
2168
2169
                $search_options['searchhidden'] = 'true';
2170
                $search_options['defaultValue'] = isset($search_options['field_default_value'])
2171
                    ? $search_options['field_default_value']
2172
                    : null;
2173
2174
                if (self::FIELD_TYPE_DOUBLE_SELECT == $field['field_type']) {
2175
                    // Add 2 selects
2176
                    $options = $extraFieldOption->get_field_options_by_field($field['id']);
2177
                    $options = self::extra_field_double_select_convert_array_to_ordered_array($options);
2178
2179
                    $first_options = [];
2180
                    if (!empty($options)) {
2181
                        foreach ($options as $option) {
2182
                            foreach ($option as $sub_option) {
2183
                                if (0 == $sub_option['option_value']) {
2184
                                    $first_options[] = $sub_option['field_id'].'#'.$sub_option['id'].':'
2185
                                        .$sub_option['display_text'];
2186
                                }
2187
                            }
2188
                        }
2189
                    }
2190
2191
                    $search_options['value'] = implode(';', $first_options);
2192
                    $search_options['dataInit'] = 'fill_second_select';
2193
2194
                    // First
2195
                    $column_model[] = [
2196
                        'name' => 'extra_'.$field['variable'],
2197
                        'index' => 'extra_'.$field['variable'],
2198
                        'width' => '100',
2199
                        'hidden' => 'true',
2200
                        'search' => 'true',
2201
                        'stype' => 'select',
2202
                        'searchoptions' => $search_options,
2203
                    ];
2204
                    $columns[] = $field['display_text'].' (1)';
2205
                    $rules[] = [
2206
                        'field' => 'extra_'.$field['variable'],
2207
                        'op' => 'cn',
2208
                    ];
2209
2210
                    // Second
2211
                    $search_options['value'] = $field['id'].':';
2212
                    $search_options['dataInit'] = 'register_second_select';
2213
2214
                    $column_model[] = [
2215
                        'name' => 'extra_'.$field['variable'].'_second',
2216
                        'index' => 'extra_'.$field['variable'].'_second',
2217
                        'width' => '100',
2218
                        'hidden' => 'true',
2219
                        'search' => 'true',
2220
                        'stype' => 'select',
2221
                        'searchoptions' => $search_options,
2222
                    ];
2223
                    $columns[] = $field['display_text'].' (2)';
2224
                    $rules[] = ['field' => 'extra_'.$field['variable'].'_second', 'op' => 'cn'];
2225
                    continue;
2226
                } else {
2227
                    $search_options['value'] = $extraFieldOption->getFieldOptionsToString(
2228
                        $field['id'],
2229
                        false,
2230
                        'display_text'
2231
                    );
2232
                }
2233
                $column_model[] = [
2234
                    'name' => 'extra_'.$field['variable'],
2235
                    'index' => 'extra_'.$field['variable'],
2236
                    'width' => '100',
2237
                    'hidden' => 'true',
2238
                    'search' => 'true',
2239
                    'stype' => $type,
2240
                    'searchoptions' => $search_options,
2241
                ];
2242
                $columns[] = $field['display_text'];
2243
                $rules[] = [
2244
                    'field' => 'extra_'.$field['variable'],
2245
                    'op' => 'cn',
2246
                    'data' => '',
2247
                ];
2248
            }
2249
        }
2250
2251
        return $rules;
2252
    }
2253
2254
    public function processExtraFieldSearch($values, $form, $alias)
2255
    {
2256
        // Parse params.
2257
        $fields = [];
2258
        foreach ($values as $key => $value) {
2259
            if (substr($key, 0, 6) !== 'extra_' && substr($key, 0, 7) !== '_extra_') {
2260
                continue;
2261
            }
2262
            if (!empty($value)) {
2263
                $fields[$key] = $value;
2264
            }
2265
        }
2266
2267
        $extraFieldsAll = $this->get_all(
2268
            ['visible_to_self = ? AND filter = ?' => [1, 1]],
2269
            'option_order'
2270
        );
2271
        $extraFieldsType = array_column($extraFieldsAll, 'field_type', 'variable');
2272
        $extraFields = array_column($extraFieldsAll, 'variable');
2273
        $filter = new stdClass();
2274
        $defaults = [];
2275
        foreach ($fields as $variable => $col) {
2276
            $variableNoExtra = str_replace('extra_', '', $variable);
2277
            if (isset($values[$variable]) && !empty($values[$variable]) &&
2278
                in_array($variableNoExtra, $extraFields)
2279
            ) {
2280
                $rule = new stdClass();
2281
                $rule->field = $variable;
2282
                $rule->op = 'in';
2283
                $data = $col;
2284
                if (is_array($data) && array_key_exists($variable, $data)) {
2285
                    $data = $col;
2286
                }
2287
                $rule->data = $data;
2288
                $filter->rules[] = $rule;
2289
                $filter->groupOp = 'AND';
2290
2291
                if ($extraFieldsType[$variableNoExtra] == ExtraField::FIELD_TYPE_TAG) {
2292
                    $tagElement = $form->getElement($variable);
2293
                    $tags = [];
2294
                    foreach ($values[$variable] as $tag) {
2295
                        $tag = Security::remove_XSS($tag);
2296
                        $tags[] = $tag;
2297
                        $tagElement->addOption(
2298
                            $tag,
2299
                            $tag
2300
                        );
2301
                    }
2302
                    $defaults[$variable] = $tags;
2303
                } else {
2304
                    if (is_array($data)) {
2305
                        $defaults[$variable] = array_map(['Security', 'remove_XSS'], $data);
2306
                    } else {
2307
                        $defaults[$variable] = Security::remove_XSS($data);
2308
                    }
2309
                }
2310
            }
2311
        }
2312
2313
        $result = $this->getExtraFieldRules($filter);
2314
        $conditionArray = $result['condition_array'];
2315
2316
        $whereCondition = '';
2317
        $extraCondition = '';
2318
        if (!empty($conditionArray)) {
2319
            $extraCondition = ' ( ';
2320
            $extraCondition .= implode(' AND ', $conditionArray);
2321
            $extraCondition .= ' ) ';
2322
        }
2323
        $whereCondition .= $extraCondition;
2324
        $conditions = $this->parseConditions(
2325
            [
2326
                'where' => $whereCondition,
2327
                'extra' => $result['extra_fields'],
2328
            ],
2329
            $alias
2330
        );
2331
2332
        return ['condition' => $conditions, 'fields' => $fields, 'defaults' => $defaults];
2333
    }
2334
2335
2336
    /**
2337
     * @param array $options
2338
     *
2339
     * @return array
2340
     */
2341
    public function parseConditions($options, $alias = 's')
2342
    {
2343
        $inject_extra_fields = null;
2344
        $extraFieldOption = new ExtraFieldOption($this->type);
2345
        $double_fields = [];
2346
2347
        if (isset($options['extra'])) {
2348
            $extra_fields = $options['extra'];
2349
            if (!empty($extra_fields)) {
2350
                $counter = 1;
2351
                $extra_field_obj = new ExtraField($this->type);
2352
                foreach ($extra_fields as &$extra) {
2353
                    if (!isset($extra['id'])) {
2354
                        continue;
2355
                    }
2356
                    $extra_field_info = $extra_field_obj->get($extra['id']);
2357
                    if (empty($extra_field_info)) {
2358
                        continue;
2359
                    }
2360
                    $extra['extra_field_info'] = $extra_field_info;
2361
2362
                    if (isset($extra_field_info['field_type']) &&
2363
                        in_array(
2364
                            $extra_field_info['field_type'],
2365
                            [
2366
                                self::FIELD_TYPE_SELECT,
2367
                                self::FIELD_TYPE_SELECT,
2368
                                self::FIELD_TYPE_DOUBLE_SELECT,
2369
                            ]
2370
                        )
2371
                    ) {
2372
                        $inject_extra_fields .= " fvo$counter.display_text as {$extra['field']}, ";
2373
                    } elseif ($extra_field_info['field_type'] == self::FIELD_TYPE_TAG) {
2374
                        $inject_extra_fields .= " tag$counter.tag as {$extra['field']}, ";
2375
                    } else {
2376
                        $inject_extra_fields .= " fv$counter.value as {$extra['field']}, ";
2377
                    }
2378
2379
                    if (isset($extra_fields_info[$extra['id']])) {
2380
                        $info = $extra_fields_info[$extra['id']];
2381
                    } else {
2382
                        $info = $this->get($extra['id']);
2383
                        $extra_fields_info[$extra['id']] = $info;
2384
                    }
2385
                    if (isset($info['field_type']) && self::FIELD_TYPE_DOUBLE_SELECT == $info['field_type']) {
2386
                        $double_fields[$info['id']] = $info;
2387
                    }
2388
                    $counter++;
2389
                }
2390
            }
2391
        }
2392
2393
        $options_by_double = [];
2394
        foreach ($double_fields as $double) {
2395
            $my_options = $extraFieldOption->get_field_options_by_field($double['id'], true);
2396
            $options_by_double['extra_'.$double['variable']] = $my_options;
2397
        }
2398
2399
        $field_value_to_join = [];
2400
        //filter can be all/any = and/or
2401
        $inject_joins = null;
2402
        $inject_where = null;
2403
        $where = null;
2404
2405
        if (!empty($options['where'])) {
2406
            if (!empty($options['extra'])) {
2407
                // Removing double 1=1
2408
                $options['where'] = str_replace(' 1 = 1  AND', '', $options['where']);
2409
                // Always OR
2410
                $counter = 1;
2411
                foreach ($extra_fields as $extra_info) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $extra_fields does not seem to be defined for all execution paths leading up to this point.
Loading history...
2412
                    $extra_field_info = $extra_info['extra_field_info'];
2413
                    $inject_joins .= " INNER JOIN $this->table_field_values fv$counter
2414
                                       ON ($alias.".$this->primaryKey." = fv$counter.".$this->handler_id.') ';
2415
                    // Add options
2416
                    if (isset($extra_field_info['field_type']) &&
2417
                        in_array(
2418
                            $extra_field_info['field_type'],
2419
                            [
2420
                                self::FIELD_TYPE_SELECT,
2421
                                self::FIELD_TYPE_SELECT,
2422
                                self::FIELD_TYPE_DOUBLE_SELECT,
2423
                            ]
2424
                        )
2425
                    ) {
2426
                        $options['where'] = str_replace(
2427
                            $extra_info['field'],
2428
                            'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fvo'.$counter.'.option_value',
2429
                            $options['where']
2430
                        );
2431
                        $inject_joins .= "
2432
                             INNER JOIN $this->table_field_options fvo$counter
2433
                             ON (
2434
                                fv$counter.field_id = fvo$counter.field_id AND
2435
                                fv$counter.value = fvo$counter.option_value
2436
                             )
2437
                            ";
2438
                    } else {
2439
                        if (isset($extra_field_info['field_type']) &&
2440
                            self::FIELD_TYPE_TAG == $extra_field_info['field_type']
2441
                        ) {
2442
                            $options['where'] = str_replace(
2443
                                $extra_info['field'],
2444
                                'tag'.$counter.'.tag ',
2445
                                $options['where']
2446
                            );
2447
2448
                            $inject_joins .= "
2449
                                INNER JOIN $this->table_field_rel_tag tag_rel$counter
2450
                                ON (
2451
                                    tag_rel$counter.field_id = ".$extra_info['id']." AND
2452
                                    tag_rel$counter.item_id = $alias.".$this->primaryKey."
2453
                                )
2454
                                INNER JOIN $this->table_field_tag tag$counter
2455
                                ON (tag$counter.id = tag_rel$counter.tag_id)
2456
                            ";
2457
                        } else {
2458
                            // text, textarea, etc
2459
                            $options['where'] = str_replace(
2460
                                $extra_info['field'],
2461
                                'fv'.$counter.'.field_id = '.$extra_info['id'].' AND fv'.$counter.'.value',
2462
                                $options['where']
2463
                            );
2464
                        }
2465
                    }
2466
2467
                    $field_value_to_join[] = " fv$counter.$this->handler_id ";
2468
                    $counter++;
2469
                }
2470
                if (!empty($field_value_to_join)) {
2471
                    //$inject_where .= " AND $alias.id = ".implode(' = ', $field_value_to_join);
2472
                }
2473
            }
2474
            $where .= ' AND '.$options['where'];
2475
        }
2476
2477
        $order = null;
2478
        if (!empty($options['order'])) {
2479
            $order = ' ORDER BY '.$options['order'];
2480
        }
2481
        $limit = null;
2482
        if (!empty($options['limit'])) {
2483
            $limit = ' LIMIT '.$options['limit'];
2484
        }
2485
2486
        return [
2487
            'order' => $order,
2488
            'limit' => $limit,
2489
            'where' => $where,
2490
            'inject_where' => $inject_where,
2491
            'inject_joins' => $inject_joins,
2492
            'field_value_to_join' => $field_value_to_join,
2493
            'inject_extra_fields' => $inject_extra_fields,
2494
        ];
2495
    }
2496
2497
    //@todo move this in the display_class or somewhere else
2498
2499
    /**
2500
     * @param $col
2501
     * @param $oper
2502
     * @param $val
2503
     *
2504
     * @return string
2505
     */
2506
    public function get_where_clause($col, $oper, $val)
2507
    {
2508
        if (empty($col)) {
2509
            return '';
2510
        }
2511
        if ('bw' === $oper || 'bn' === $oper) {
2512
            $val .= '%';
2513
        }
2514
        if ('ew' === $oper || 'en' === $oper) {
2515
            $val = '%'.$val;
2516
        }
2517
        if ('cn' === $oper || 'nc' === $oper || 'in' === $oper || 'ni' === $oper) {
2518
            if (is_array($val)) {
2519
                $result = '"%'.implode(';', $val).'%"';
2520
                foreach ($val as $item) {
2521
                    $item = trim($item);
2522
                    $result .= ' OR '.$col.' LIKE "%'.$item.'%"';
2523
                }
2524
                $val = $result;
2525
2526
                return " $col {$this->ops[$oper]} $val ";
2527
            } else {
2528
                if (is_string($val)) {
2529
                    $val = '%'.$val.'%';
2530
                } else {
2531
                    $val = '';
2532
                }
2533
            }
2534
        }
2535
        $val = \Database::escape_string($val);
2536
2537
        return " $col {$this->ops[$oper]} '$val' ";
2538
    }
2539
2540
    /**
2541
     * @param $filters
2542
     * @param string $stringToSearch
2543
     *
2544
     * @return array
2545
     */
2546
    public function getExtraFieldRules($filters, $stringToSearch = 'extra_')
2547
    {
2548
        $extra_fields = [];
2549
        $condition_array = [];
2550
2551
        // Getting double select if exists
2552
        $double_select = [];
2553
        if (is_object($filters)
2554
            && property_exists($filters, 'rules')
2555
            && is_array($filters->rules)
2556
            && !empty($filters->rules)
2557
        ) {
2558
            foreach ($filters->rules as $rule) {
2559
                if (empty($rule)) {
2560
                    continue;
2561
                }
2562
                if (false === strpos($rule->field, '_second')) {
2563
                } else {
2564
                    $my_field = str_replace('_second', '', $rule->field);
2565
                    $double_select[$my_field] = $rule->data;
2566
                }
2567
            }
2568
2569
            foreach ($filters->rules as $rule) {
2570
                if (empty($rule)) {
2571
                    continue;
2572
                }
2573
                if (false === strpos($rule->field, $stringToSearch)) {
2574
                    // normal fields
2575
                    $field = $rule->field;
2576
                    if (isset($rule->data) && is_string($rule->data) && -1 != $rule->data) {
2577
                        $condition_array[] = $this->get_where_clause($field, $rule->op, $rule->data);
2578
                    }
2579
                } else {
2580
                    // Extra fields
2581
                    if (false === strpos($rule->field, '_second')) {
2582
                        // No _second
2583
                        $original_field = str_replace($stringToSearch, '', $rule->field);
2584
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2585
2586
                        if (self::FIELD_TYPE_DOUBLE_SELECT == $field_option['field_type']) {
2587
                            if (isset($double_select[$rule->field])) {
2588
                                $data = explode('#', $rule->data);
2589
                                $rule->data = $data[1].'::'.$double_select[$rule->field];
2590
                            } else {
2591
                                // only was sent 1 select
2592
                                if (is_string($rule->data)) {
2593
                                    $data = explode('#', $rule->data);
2594
                                    $rule->data = $data[1];
2595
                                }
2596
                            }
2597
2598
                            if (!isset($rule->data)) {
2599
                                $condition_array[] = ' ('
2600
                                    .$this->get_where_clause($rule->field, $rule->op, $rule->data)
2601
                                    .') ';
2602
                                $extra_fields[] = ['field' => $rule->field, 'id' => $field_option['id']];
2603
                            }
2604
                        } else {
2605
                            if (isset($rule->data)) {
2606
                                if (isset($rule->data) && is_int($rule->data) && -1 == $rule->data) {
2607
                                    continue;
2608
                                }
2609
                                $condition_array[] = ' ('
2610
                                    .$this->get_where_clause($rule->field, $rule->op, $rule->data)
2611
                                    .') ';
2612
                                $extra_fields[] = [
2613
                                    'field' => $rule->field,
2614
                                    'id' => $field_option['id'],
2615
                                    'data' => $rule->data,
2616
                                ];
2617
                            }
2618
                        }
2619
                    } else {
2620
                        $my_field = str_replace('_second', '', $rule->field);
2621
                        $original_field = str_replace($stringToSearch, '', $my_field);
2622
                        $field_option = $this->get_handler_field_info_by_field_variable($original_field);
2623
                        $extra_fields[] = [
2624
                            'field' => $rule->field,
2625
                            'id' => $field_option['id'],
2626
                        ];
2627
                    }
2628
                }
2629
            }
2630
        }
2631
2632
        return [
2633
            'extra_fields' => $extra_fields,
2634
            'condition_array' => $condition_array,
2635
        ];
2636
    }
2637
2638
    /**
2639
     * Get the extra fields and their formatted values.
2640
     *
2641
     * @param int|string $itemId   The item ID (It could be a session_id, course_id or user_id)
2642
     * @param bool       $filter
2643
     * @param array      $onlyShow (list of extra fields variables to show)
2644
     *
2645
     * @return array The extra fields data
2646
     */
2647
    public function getDataAndFormattedValues($itemId, $filter = false, $onlyShow = [])
2648
    {
2649
        $valuesData = [];
2650
        $fields = $this->get_all();
2651
        $em = Database::getManager();
2652
2653
        $repoTag = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
2654
2655
        foreach ($fields as $field) {
2656
            if ('1' != $field['visible_to_self']) {
2657
                continue;
2658
            }
2659
2660
            if ($filter && $field['filter'] != 1) {
2661
                continue;
2662
            }
2663
2664
            if (!empty($onlyShow) && !in_array($field['variable'], $onlyShow)) {
2665
                continue;
2666
            }
2667
2668
            $valueAsArray = [];
2669
            $fieldValue = new ExtraFieldValue($this->type);
2670
            $valueData = $fieldValue->get_values_by_handler_and_field_id(
2671
                $itemId,
0 ignored issues
show
Bug introduced by
It seems like $itemId can also be of type string; however, parameter $item_id of ExtraFieldValue::get_val..._handler_and_field_id() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

2671
                /** @scrutinizer ignore-type */ $itemId,
Loading history...
2672
                $field['id'],
2673
                true
2674
            );
2675
            if (ExtraField::FIELD_TYPE_TAG == $field['field_type']) {
2676
                $tags = $repoTag->findBy(['fieldId' => $field['id'], 'itemId' => $itemId]);
2677
                if ($tags) {
2678
                    /** @var ExtraFieldRelTag $tag */
2679
                    $data = [];
2680
                    foreach ($tags as $extraFieldTag) {
2681
                        /** @var Tag $tag */
2682
                        $tag = $em->find('ChamiloCoreBundle:Tag', $extraFieldTag->getTagId());
2683
                        $data[] = $tag->getTag();
2684
                    }
2685
                    $valueData = implode(',', $data);
2686
                    $valueAsArray = $data;
2687
                }
2688
            }
2689
2690
            if (!$valueData) {
2691
                continue;
2692
            }
2693
            $displayedValue = get_lang('None');
2694
2695
            switch ($field['field_type']) {
2696
                case self::FIELD_TYPE_CHECKBOX:
2697
                    if (false !== $valueData && '1' == $valueData['value']) {
2698
                        $displayedValue = get_lang('Yes');
2699
                    } else {
2700
                        $displayedValue = get_lang('No');
2701
                    }
2702
                    break;
2703
                case self::FIELD_TYPE_DATE:
2704
                    if (false !== $valueData && !empty($valueData['value'])) {
2705
                        $displayedValue = api_format_date($valueData['value'], DATE_FORMAT_LONG_NO_DAY);
2706
                    }
2707
                    break;
2708
                case self::FIELD_TYPE_TAG:
2709
                    if (!empty($valueData)) {
2710
                        $displayedValue = $valueData;
2711
                    }
2712
                    break;
2713
                case self::FIELD_TYPE_FILE_IMAGE:
2714
                    if (false === $valueData || empty($valueData['value'])) {
2715
                        break;
2716
                    }
2717
2718
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
2719
                        break;
2720
                    }
2721
2722
                    $image = Display::img(
2723
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2724
                        $field['display_text'],
2725
                        ['width' => '300']
2726
                    );
2727
2728
                    $displayedValue = Display::url(
2729
                        $image,
2730
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2731
                        ['target' => '_blank']
2732
                    );
2733
                    break;
2734
                case self::FIELD_TYPE_FILE:
2735
                    if (false === $valueData || empty($valueData['value'])) {
2736
                        break;
2737
                    }
2738
2739
                    if (!file_exists(api_get_path(SYS_UPLOAD_PATH).$valueData['value'])) {
2740
                        break;
2741
                    }
2742
2743
                    $displayedValue = Display::url(
2744
                        get_lang('Download'),
2745
                        api_get_path(WEB_UPLOAD_PATH).$valueData['value'],
2746
                        [
2747
                            'title' => $field['display_text'],
2748
                            'target' => '_blank',
2749
                            'class' => 'download_extra_field',
2750
                        ]
2751
                    );
2752
                    break;
2753
                default:
2754
                    $displayedValue = $valueData['value'];
2755
                    break;
2756
            }
2757
2758
            $valuesData[] = [
2759
                'variable' => $field['variable'],
2760
                'text' => $field['display_text'],
2761
                'value' => $displayedValue,
2762
                'value_as_array' => $valueAsArray,
2763
            ];
2764
        }
2765
2766
        return $valuesData;
2767
    }
2768
2769
    /**
2770
     * Gets an element.
2771
     *
2772
     * @param int  $id
2773
     * @param bool $translateDisplayText Optional
2774
     *
2775
     * @return array
2776
     */
2777
    public function get($id, $translateDisplayText = true)
2778
    {
2779
        $info = parent::get($id);
2780
2781
        if ($translateDisplayText) {
2782
            $info['display_text'] = self::translateDisplayName($info['variable'], $info['display_text']);
2783
        }
2784
2785
        return $info;
2786
    }
2787
2788
    /**
2789
     * Translate the display text for a extra field.
2790
     *
2791
     * @param string $variable
2792
     * @param string $defaultDisplayText
2793
     *
2794
     * @return string
2795
     */
2796
    public static function translateDisplayName($variable, $defaultDisplayText)
2797
    {
2798
        $camelCase = api_underscore_to_camel_case($variable);
2799
2800
        return isset($GLOBALS[$camelCase]) ? $GLOBALS[$camelCase] : $defaultDisplayText;
2801
    }
2802
2803
    /**
2804
     * @param int    $fieldId
2805
     * @param string $tag
2806
     *
2807
     * @return array
2808
     */
2809
    public function getAllUserPerTag($fieldId, $tag)
2810
    {
2811
        $tagRelUserTable = Database::get_main_table(TABLE_MAIN_USER_REL_TAG);
2812
        $tag = Database::escape_string($tag);
2813
        $fieldId = (int) $fieldId;
2814
2815
        $sql = "SELECT user_id
2816
                FROM {$this->table_field_tag} f INNER JOIN $tagRelUserTable ft
2817
                ON tag_id = f.id
2818
                WHERE tag = '$tag' AND f.field_id = $fieldId;
2819
        ";
2820
2821
        $result = Database::query($sql);
2822
2823
        return Database::store_result($result, 'ASSOC');
2824
    }
2825
2826
    /**
2827
     * @param int $fieldId
2828
     * @param int $tagId
2829
     *
2830
     * @return array
2831
     */
2832
    public function getAllSkillPerTag($fieldId, $tagId)
2833
    {
2834
        $skillTable = Database::get_main_table(TABLE_MAIN_SKILL);
2835
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
2836
        $fieldId = (int) $fieldId;
2837
        $tagId = (int) $tagId;
2838
2839
        $sql = "SELECT s.id
2840
                FROM $skillTable s INNER JOIN $tagRelExtraTable t
2841
                ON t.item_id = s.id
2842
                WHERE tag_id = $tagId AND t.field_id = $fieldId;
2843
        ";
2844
2845
        $result = Database::query($sql);
2846
        $result = Database::store_result($result, 'ASSOC');
2847
2848
        $skillList = [];
2849
        foreach ($result as $index => $value) {
2850
            $skillList[$value['id']] = $value['id'];
2851
        }
2852
2853
        return $skillList;
2854
    }
2855
2856
    /**
2857
     * @param string $from
2858
     * @param string $search
2859
     * @param array  $options
2860
     *
2861
     * @return array
2862
     */
2863
    public function searchOptionsFromTags($from, $search, $options)
2864
    {
2865
        $extraFieldInfo = $this->get_handler_field_info_by_field_variable(
2866
            str_replace('extra_', '', $from)
2867
        );
2868
        $extraFieldInfoTag = $this->get_handler_field_info_by_field_variable(
2869
            str_replace('extra_', '', $search)
2870
        );
2871
2872
        if (empty($extraFieldInfo) || empty($extraFieldInfoTag)) {
2873
            return [];
2874
        }
2875
2876
        $id = $extraFieldInfo['id'];
2877
        $tagId = $extraFieldInfoTag['id'];
2878
2879
        $table = Database::get_main_table(TABLE_EXTRA_FIELD_VALUES);
2880
        $tagRelExtraTable = Database::get_main_table(TABLE_MAIN_EXTRA_FIELD_REL_TAG);
2881
        $tagTable = Database::get_main_table(TABLE_MAIN_TAG);
2882
        $optionsTable = Database::get_main_table(TABLE_EXTRA_FIELD_OPTIONS);
2883
2884
        $sql = "SELECT DISTINCT t.*, v.value, o.display_text
2885
                FROM $tagRelExtraTable te
2886
                INNER JOIN $tagTable t
2887
                ON (t.id = te.tag_id AND te.field_id = t.field_id AND te.field_id = $tagId)
2888
                INNER JOIN $table v
2889
                ON (te.item_id = v.item_id AND v.field_id = $id)
2890
                INNER JOIN $optionsTable o
2891
                ON (o.option_value = v.value)
2892
                WHERE v.value IN ('".implode("','", $options)."')
2893
                ORDER BY o.option_order, t.tag
2894
               ";
2895
2896
        $result = Database::query($sql);
2897
        $result = Database::store_result($result);
2898
2899
        return $result;
2900
    }
2901
2902
    /**
2903
     * @param string $variable
2904
     * @param string $dataValue
2905
     *
2906
     * @return string
2907
     */
2908
    public static function getLocalizationJavascript($variable, $dataValue)
2909
    {
2910
        $dataValue = addslashes($dataValue);
2911
        $html = "<script>
2912
            $(function() {
2913
                if (typeof google === 'object') {
2914
                    var address = '$dataValue';
2915
                    initializeGeo{$variable}(address, false);
2916
2917
                    $('#geolocalization_extra_{$variable}').on('click', function() {
2918
                        var address = $('#{$variable}').val();
2919
                        initializeGeo{$variable}(address, false);
2920
                        return false;
2921
                    });
2922
2923
                    $('#myLocation_extra_{$variable}').on('click', function() {
2924
                        myLocation{$variable}();
2925
                        return false;
2926
                    });
2927
2928
                    // When clicking enter
2929
                    $('#{$variable}').keypress(function(event) {
2930
                        if (event.which == 13) {
2931
                            $('#geolocalization_extra_{$variable}').click();
2932
                            return false;
2933
                        }
2934
                    });
2935
2936
                    // On focus out update city
2937
                    $('#{$variable}').focusout(function() {
2938
                        $('#geolocalization_extra_{$variable}').click();
2939
                        return false;
2940
                    });
2941
2942
                    return;
2943
                }
2944
2945
                $('#map_extra_{$variable}')
2946
                    .html('<div class=\"alert alert-info\">"
2947
                .addslashes(get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap'))
2948
                ."</div>');
2949
            });
2950
2951
            function myLocation{$variable}()
2952
            {
2953
                if (navigator.geolocation) {
2954
                    var geoPosition = function(position) {
2955
                        var lat = position.coords.latitude;
2956
                        var lng = position.coords.longitude;
2957
                        var latLng = new google.maps.LatLng(lat, lng);
2958
                        initializeGeo{$variable}(false, latLng);
2959
                    };
2960
2961
                    var geoError = function(error) {
2962
                        alert('Geocode ".get_lang('Error').": ' + error);
2963
                    };
2964
2965
                    var geoOptions = {
2966
                        enableHighAccuracy: true
2967
                    };
2968
                    navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
2969
                }
2970
            }
2971
2972
            function initializeGeo{$variable}(address, latLng)
2973
            {
2974
                var geocoder = new google.maps.Geocoder();
2975
                var latlng = new google.maps.LatLng(-34.397, 150.644);
2976
                var myOptions = {
2977
                    zoom: 15,
2978
                    center: latlng,
2979
                    mapTypeControl: true,
2980
                    mapTypeControlOptions: {
2981
                        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
2982
                    },
2983
                    navigationControl: true,
2984
                    mapTypeId: google.maps.MapTypeId.ROADMAP
2985
                };
2986
2987
                map_{$variable} = new google.maps.Map(
2988
                    document.getElementById('map_extra_{$variable}'),
2989
                    myOptions
2990
                );
2991
2992
                var parameter = address ? {'address': address} : latLng ? {'latLng': latLng} : false;
2993
2994
                if (geocoder && parameter) {
2995
                    geocoder.geocode(parameter, function(results, status) {
2996
                        if (status == google.maps.GeocoderStatus.OK) {
2997
                            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
2998
                                map_{$variable}.setCenter(results[0].geometry.location);
2999
3000
                                // get city and country
3001
                                var defaultAddress = results[0].formatted_address;
3002
                                var city = '';
3003
                                var country = '';
3004
3005
                                for (var i=0; i<results[0].address_components.length; i++) {
3006
                                    if (results[0].address_components[i].types[0] == \"locality\") {
3007
                                        //this is the object you are looking for City
3008
                                        city = results[0].address_components[i];
3009
                                    }
3010
                                    /*if (results[j].address_components[i].types[0] == \"administrative_area_level_1\") {
3011
                                        //this is the object you are looking for State
3012
                                        region = results[0].address_components[i];
3013
                                    }*/
3014
                                    if (results[0].address_components[i].types[0] == \"country\") {
3015
                                        //this is the object you are looking for
3016
                                        country = results[0].address_components[i];
3017
                                    }
3018
                                }
3019
3020
                                if (city && city.long_name && country && country.long_name) {
3021
                                    defaultAddress = city.long_name + ', ' + country.long_name;
3022
                                }
3023
                                $('#{$variable}').val(defaultAddress);
3024
                                $('#{$variable}_coordinates').val(
3025
                                    results[0].geometry.location.lat()+','+results[0].geometry.location.lng()
3026
                                );
3027
3028
                                var infowindow = new google.maps.InfoWindow({
3029
                                    content: '<b>' + $('#extra_{$variable}').val() + '</b>',
3030
                                    size: new google.maps.Size(150, 50)
3031
                                });
3032
3033
                                var marker = new google.maps.Marker({
3034
                                    position: results[0].geometry.location,
3035
                                    map: map_{$variable},
3036
                                    title: $('#extra_{$variable}').val()
3037
                                });
3038
                                google.maps.event.addListener(marker, 'click', function() {
3039
                                    infowindow.open(map_{$variable}, marker);
3040
                                });
3041
                            } else {
3042
                                alert('".get_lang('NotFound')."');
3043
                            }
3044
                        } else {
3045
                            alert('Geocode ".get_lang('Error').': '.get_lang('AddressField').' '.get_lang('NotFound')."');
3046
                        }
3047
                    });
3048
                }
3049
            }
3050
            </script>";
3051
3052
        return $html;
3053
    }
3054
3055
    /**
3056
     * @param string $variable
3057
     * @param string $text
3058
     *
3059
     * @return string
3060
     */
3061
    public static function getLocalizationInput($variable, $text)
3062
    {
3063
        $html = '
3064
                <div class="form-group">
3065
                    <label for="geolocalization_extra_'.$variable.'"
3066
                        class="col-sm-2 control-label"></label>
3067
                    <div class="col-sm-8">
3068
                        <button class="btn btn-default"
3069
                            id="geolocalization_extra_'.$variable.'"
3070
                            name="geolocalization_extra_'.$variable.'"
3071
                            type="submit">
3072
                            <em class="fa fa-map-marker"></em> '.get_lang('SearchGeolocalization').'
3073
                        </button>
3074
                        <button class="btn btn-default" id="myLocation_extra_'.$variable.'"
3075
                            name="myLocation_extra_'.$variable.'"
3076
                            type="submit">
3077
                            <em class="fa fa-crosshairs"></em> '.get_lang('MyLocation').'
3078
                        </button>
3079
                    </div>
3080
                </div>
3081
                <div class="form-group">
3082
                    <label for="map_extra_'.$variable.'" class="col-sm-2 control-label">
3083
                        '.$text.' - '.get_lang('Map').'
3084
                    </label>
3085
                    <div class="col-sm-8">
3086
                        <div name="map_extra_'.$variable.'"
3087
                            id="map_extra_'.$variable.'" style="width:100%; height:300px;">
3088
                        </div>
3089
                    </div>
3090
                </div>
3091
            ';
3092
3093
        return $html;
3094
    }
3095
3096
    /**
3097
     * @param int $parentId
3098
     *
3099
     * @return array
3100
     */
3101
    private static function getOptionsFromTripleSelect(array $options, $parentId)
3102
    {
3103
        return array_filter(
3104
            $options,
3105
            function ($option) use ($parentId) {
3106
                return $option['option_value'] == $parentId;
3107
            }
3108
        );
3109
    }
3110
3111
    /**
3112
     * @param \FormValidator $form
3113
     * @param int            $defaultValueId
3114
     * @param bool           $freezeElement
3115
     */
3116
    private function addSelectElement(FormValidator $form, array $fieldDetails, $defaultValueId, $freezeElement = false)
3117
    {
3118
        $get_lang_variables = false;
3119
        if (in_array(
3120
            $fieldDetails['variable'],
3121
            ['mail_notify_message', 'mail_notify_invitation', 'mail_notify_group_message']
3122
        )) {
3123
            $get_lang_variables = true;
3124
        }
3125
3126
        // Get extra field workflow
3127
        $addOptions = [];
3128
        $optionsExists = false;
3129
        $options = [];
3130
3131
        $optionList = [];
3132
        if (!empty($fieldDetails['options'])) {
3133
            foreach ($fieldDetails['options'] as $option_details) {
3134
                $optionList[$option_details['id']] = $option_details;
3135
                if ($get_lang_variables) {
3136
                    $options[$option_details['option_value']] = $option_details['display_text'];
3137
                } else {
3138
                    if ($optionsExists) {
3139
                        // Adding always the default value
3140
                        if ($option_details['id'] == $defaultValueId) {
3141
                            $options[$option_details['option_value']] = $option_details['display_text'];
3142
                        } else {
3143
                            if (isset($addOptions) && !empty($addOptions)) {
3144
                                // Parsing filters
3145
                                if (in_array($option_details['id'], $addOptions)) {
3146
                                    $options[$option_details['option_value']] = $option_details['display_text'];
3147
                                }
3148
                            }
3149
                        }
3150
                    } else {
3151
                        // Normal behaviour
3152
                        $options[$option_details['option_value']] = $option_details['display_text'];
3153
                    }
3154
                }
3155
            }
3156
3157
            // Setting priority message
3158
            if (isset($optionList[$defaultValueId])
3159
                && isset($optionList[$defaultValueId]['priority'])
3160
            ) {
3161
                if (!empty($optionList[$defaultValueId]['priority'])) {
3162
                    $priorityId = $optionList[$defaultValueId]['priority'];
3163
                    $option = new ExtraFieldOption($this->type);
3164
                    $messageType = $option->getPriorityMessageType($priorityId);
3165
                    $form->addElement(
3166
                        'label',
3167
                        null,
3168
                        Display::return_message(
3169
                            $optionList[$defaultValueId]['priority_message'],
3170
                            $messageType
3171
                        )
3172
                    );
3173
                }
3174
            }
3175
        }
3176
3177
        /** @var \HTML_QuickForm_select $slct */
3178
        $slct = $form->addElement(
3179
            'select',
3180
            'extra_'.$fieldDetails['variable'],
3181
            $fieldDetails['display_text'],
3182
            [],
3183
            ['id' => 'extra_'.$fieldDetails['variable']]
3184
        );
3185
3186
        if (empty($defaultValueId)) {
3187
            $slct->addOption(get_lang('SelectAnOption'), '');
3188
        }
3189
3190
        foreach ($options as $value => $text) {
3191
            if (empty($value)) {
3192
                $slct->addOption($text, $value);
3193
                continue;
3194
            }
3195
3196
            $valueParts = explode('#', $text);
3197
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3198
3199
            $slct->addOption(implode('', $valueParts), $value, ['data-value' => $dataValue]);
3200
        }
3201
3202
        /* Enable this when field_loggeable is introduced as a table field (2.0)
3203
        if ($optionsExists && $field_details['field_loggeable'] && !empty($defaultValueId)) {
3204
3205
            $form->addElement(
3206
                'textarea',
3207
                'extra_' . $field_details['variable'] . '_comment',
3208
                $field_details['display_text'] . ' ' . get_lang('Comment')
3209
            );
3210
3211
            $extraFieldValue = new ExtraFieldValue($this->type);
3212
            $repo = $app['orm.em']->getRepository($extraFieldValue->entityName);
3213
            $repoLog = $app['orm.em']->getRepository('Gedmo\Loggable\Entity\LogEntry');
3214
            $newEntity = $repo->findOneBy(
3215
                array(
3216
                    $this->handlerEntityId => $itemId,
3217
                    'fieldId' => $field_details['id']
3218
                )
3219
            );
3220
            // @todo move this in a function inside the class
3221
            if ($newEntity) {
3222
                $logs = $repoLog->getLogEntries($newEntity);
3223
                if (!empty($logs)) {
3224
                    $html = '<b>' . get_lang('LatestChanges') . '</b><br /><br />';
3225
3226
                    $table = new HTML_Table(array('class' => 'data_table'));
3227
                    $table->setHeaderContents(0, 0, get_lang('Value'));
3228
                    $table->setHeaderContents(0, 1, get_lang('Comment'));
3229
                    $table->setHeaderContents(0, 2, get_lang('ModifyDate'));
3230
                    $table->setHeaderContents(0, 3, get_lang('Username'));
3231
                    $row = 1;
3232
                    foreach ($logs as $log) {
3233
                        $column = 0;
3234
                        $data = $log->getData();
3235
                        $fieldValue = isset($data['fieldValue']) ? $data['fieldValue'] : null;
3236
                        $comment = isset($data['comment']) ? $data['comment'] : null;
3237
3238
                        $table->setCellContents($row, $column, $fieldValue);
3239
                        $column++;
3240
                        $table->setCellContents($row, $column, $comment);
3241
                        $column++;
3242
                        $table->setCellContents($row, $column, api_get_local_time($log->getLoggedAt()->format('Y-m-d H:i:s')));
3243
                        $column++;
3244
                        $table->setCellContents($row, $column, $log->getUsername());
3245
                        $row++;
3246
                    }
3247
                    $form->addElement('label', null, $html.$table->toHtml());
3248
                }
3249
            }
3250
        }
3251
        */
3252
3253
        if ($freezeElement) {
3254
            $form->freeze('extra_'.$fieldDetails['variable']);
3255
        }
3256
    }
3257
3258
    /**
3259
     * @param \FormValidator $form
3260
     * @param array          $fieldDetails
3261
     * @param array          $extraData
3262
     * @param bool           $freezeElement
3263
     *
3264
     * @return string JavaScript code
3265
     */
3266
    private function addDoubleSelectElement(FormValidator $form, $fieldDetails, $extraData, $freezeElement = false)
3267
    {
3268
        $firstSelectId = 'first_extra_'.$fieldDetails['variable'];
3269
        $secondSelectId = 'second_extra_'.$fieldDetails['variable'];
3270
3271
        $jqueryReadyContent = "
3272
            $('#$firstSelectId').on('change', function() {
3273
                var id = $(this).val();
3274
3275
                if (!id) {
3276
                    $('#$secondSelectId').empty().selectpicker('refresh');
3277
3278
                    return;
3279
                }
3280
3281
                $.getJSON(_p.web_ajax + 'extra_field.ajax.php?1=1&a=get_second_select_options', {
3282
                    'type': '{$this->type}',
3283
                    'field_id': {$fieldDetails['id']},
3284
                    'option_value_id': id
3285
                })
3286
                    .done(function(data) {
3287
                        $('#$secondSelectId').empty();
3288
                        $.each(data, function(index, value) {
3289
                            $('#second_extra_{$fieldDetails['variable']}').append(
3290
                                $('<option>', {value: index, text: value})
3291
                            );
3292
                        });
3293
                        $('#$secondSelectId').selectpicker('refresh');
3294
                    });
3295
            });
3296
        ";
3297
3298
        $firstId = null;
3299
        if (!empty($extraData)) {
3300
            if (isset($extraData['extra_'.$fieldDetails['variable']])) {
3301
                $firstId = $extraData['extra_'.$fieldDetails['variable']]['extra_'.$fieldDetails['variable']];
3302
            }
3303
        }
3304
3305
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3306
        $values = ['' => get_lang('Select')];
3307
3308
        $second_values = [];
3309
        if (!empty($options)) {
3310
            foreach ($options as $option) {
3311
                foreach ($option as $sub_option) {
3312
                    if ('0' == $sub_option['option_value']) {
3313
                        $values[$sub_option['id']] = $sub_option['display_text'];
3314
3315
                        continue;
3316
                    }
3317
3318
                    if ($firstId === $sub_option['option_value']) {
3319
                        $second_values[$sub_option['id']] = $sub_option['display_text'];
3320
                    }
3321
                }
3322
            }
3323
        }
3324
3325
        $form
3326
            ->defaultRenderer()
3327
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3328
        $group = [];
3329
        $group[] = $form->createElement(
3330
            'select',
3331
            'extra_'.$fieldDetails['variable'],
3332
            null,
3333
            $values,
3334
            ['id' => $firstSelectId]
3335
        );
3336
        $group[] = $form->createElement(
3337
            'select',
3338
            'extra_'.$fieldDetails['variable'].'_second',
3339
            null,
3340
            $second_values,
3341
            ['id' => $secondSelectId]
3342
        );
3343
        $form->addGroup(
3344
            $group,
3345
            'extra_'.$fieldDetails['variable'],
3346
            $fieldDetails['display_text']
3347
        );
3348
3349
        if ($freezeElement) {
3350
            $form->freeze('extra_'.$fieldDetails['variable']);
3351
        }
3352
3353
        return $jqueryReadyContent;
3354
    }
3355
3356
    /**
3357
     * @param \FormValidator $form
3358
     * @param bool           $freezeElement Optional
3359
     *
3360
     * @return string JavaScript code
3361
     */
3362
    private function addSelectWithTextFieldElement(
3363
        FormValidator $form,
3364
        array $fieldDetails,
3365
        $freezeElement = false
3366
    ) {
3367
        $firstSelectId = 'slct_extra_'.$fieldDetails['variable'];
3368
        $txtSelectId = 'txt_extra_'.$fieldDetails['variable'];
3369
3370
        $jqueryReadyContent = "
3371
            $('#$firstSelectId').on('change', function() {
3372
                var id = $(this).val();
3373
3374
                if (!id) {
3375
                    $('#$txtSelectId').val('');
3376
                }
3377
            });
3378
        ";
3379
3380
        $options = $this->extra_field_double_select_convert_array_to_ordered_array($fieldDetails['options']);
3381
        $values = ['' => get_lang('Select')];
3382
3383
        if (!empty($options)) {
3384
            foreach ($options as $option) {
3385
                foreach ($option as $sub_option) {
3386
                    if ('0' != $sub_option['option_value']) {
3387
                        continue;
3388
                    }
3389
3390
                    $values[$sub_option['id']] = $sub_option['display_text'];
3391
                }
3392
            }
3393
        }
3394
3395
        $form
3396
            ->defaultRenderer()
3397
            ->setGroupElementTemplate('<p>{element}</p>', 'extra_'.$fieldDetails['variable']);
3398
        $group = [];
3399
        $group[] = $form->createElement(
3400
            'select',
3401
            'extra_'.$fieldDetails['variable'],
3402
            null,
3403
            $values,
3404
            ['id' => $firstSelectId]
3405
        );
3406
        $group[] = $form->createElement(
3407
            'text',
3408
            'extra_'.$fieldDetails['variable'].'_second',
3409
            null,
3410
            ['id' => $txtSelectId]
3411
        );
3412
        $form->addGroup(
3413
            $group,
3414
            'extra_'.$fieldDetails['variable'],
3415
            $fieldDetails['display_text']
3416
        );
3417
3418
        if ($freezeElement) {
3419
            $form->freeze('extra_'.$fieldDetails['variable']);
3420
        }
3421
3422
        return $jqueryReadyContent;
3423
    }
3424
3425
    /**
3426
     * @param \FormValidator $form
3427
     * @param bool           $freezeElement
3428
     *
3429
     * @return string
3430
     */
3431
    private function addTripleSelectElement(
3432
        FormValidator $form,
3433
        array $fieldDetails,
3434
        array $extraData,
3435
        $freezeElement
3436
    ) {
3437
        $variable = $fieldDetails['variable'];
3438
        $id = $fieldDetails['id'];
3439
        $slctFirstId = "first_extra$variable";
3440
        $slctSecondId = "second_extra$variable";
3441
        $slctThirdId = "third_extra$variable";
3442
        $langSelect = get_lang('Select');
3443
3444
        $js = "
3445
            (function () {
3446
                var slctFirst = $('#$slctFirstId'),
3447
                    slctSecond = $('#$slctSecondId'),
3448
                    slctThird = $('#$slctThirdId');
3449
3450
                slctFirst.on('change', function () {
3451
                    slctSecond.empty().selectpicker('refresh');
3452
                    slctThird.empty().selectpicker('refresh');
3453
3454
                    var level = $(this).val();
3455
3456
                    if (!level) {
3457
                        return;
3458
                    }
3459
3460
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3461
                        'a': 'get_second_select_options',
3462
                        'type': '$this->type',
3463
                        'field_id': $id,
3464
                        'option_value_id': level
3465
                    })
3466
                        .done(function (data) {
3467
                            slctSecond.append(
3468
                                $('<option>', {value: '', text: '$langSelect'})
3469
                            );
3470
3471
                            $.each(data, function (index, value) {
3472
                                var valueParts = value.split('#'),
3473
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3474
3475
                                slctSecond.append(
3476
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3477
                                );
3478
                            });
3479
3480
                            slctSecond.selectpicker('refresh');
3481
                        });
3482
                });
3483
                slctSecond.on('change', function () {
3484
                    slctThird.empty().selectpicker('refresh');
3485
3486
                    var level = $(this).val();
3487
3488
                    if (!level) {
3489
                        return;
3490
                    }
3491
3492
                    $.getJSON(_p.web_ajax + 'extra_field.ajax.php', {
3493
                        'a': 'get_second_select_options',
3494
                        'type': '$this->type',
3495
                        'field_id': $id,
3496
                        'option_value_id': level
3497
                    })
3498
                        .done(function (data) {
3499
                            slctThird.append(
3500
                                $('<option>', {value: '', text: '$langSelect'})
3501
                            );
3502
3503
                            $.each(data, function (index, value) {
3504
                                var valueParts = value.split('#'),
3505
                                    dataValue = valueParts.length > 1 ? valueParts.shift() : '';
3506
3507
                                slctThird.append(
3508
                                    $('<option>', {value: index, text: valueParts.join(''), 'data-value': dataValue})
3509
                                );
3510
                            });
3511
3512
                            slctThird.selectpicker('refresh');
3513
                        });
3514
                });
3515
            })();
3516
        ";
3517
3518
        $firstId = isset($extraData["extra_$variable"]["extra_$variable"])
3519
            ? $extraData["extra_$variable"]["extra_$variable"]
3520
            : '';
3521
        $secondId = isset($extraData["extra_$variable"]["extra_{$variable}_second"])
3522
            ? $extraData["extra_$variable"]["extra_{$variable}_second"]
3523
            : '';
3524
3525
        $options = $this->tripleSelectConvertArrayToOrderedArray($fieldDetails['options']);
3526
        $values1 = ['' => $langSelect];
3527
        $values2 = ['' => $langSelect];
3528
        $values3 = ['' => $langSelect];
3529
        $level1 = $this->getOptionsFromTripleSelect($options['level1'], 0);
3530
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], $firstId);
0 ignored issues
show
Bug introduced by
It seems like $firstId can also be of type string; however, parameter $parentId of ExtraField::getOptionsFromTripleSelect() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

3530
        $level2 = $this->getOptionsFromTripleSelect($options['level2'], /** @scrutinizer ignore-type */ $firstId);
Loading history...
3531
        $level3 = $this->getOptionsFromTripleSelect($options['level3'], $secondId);
3532
        /** @var \HTML_QuickForm_select $slctFirst */
3533
        $slctFirst = $form->createElement('select', "extra_$variable", null, $values1, ['id' => $slctFirstId]);
3534
        /** @var \HTML_QuickForm_select $slctFirst */
3535
        $slctSecond = $form->createElement('select', "extra_{$variable}_second", null, $values2, ['id' => $slctSecondId]);
3536
        /** @var \HTML_QuickForm_select $slctFirst */
3537
        $slctThird = $form->createElement('select', "extra_{$variable}_third", null, $values3, ['id' => $slctThirdId]);
3538
3539
        foreach ($level1 as $item1) {
3540
            $valueParts = explode('#', $item1['display_text']);
3541
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3542
            $slctFirst->addOption(implode('', $valueParts), $item1['id'], ['data-value' => $dataValue]);
3543
        }
3544
3545
        foreach ($level2 as $item2) {
3546
            $valueParts = explode('#', $item2['display_text']);
3547
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3548
            $slctSecond->addOption(implode('', $valueParts), $item2['id'], ['data-value' => $dataValue]);
3549
        }
3550
3551
        foreach ($level3 as $item3) {
3552
            $valueParts = explode('#', $item3['display_text']);
3553
            $dataValue = count($valueParts) > 1 ? array_shift($valueParts) : '';
3554
            $slctThird->addOption(implode('', $valueParts), $item3['id'], ['data-value' => $dataValue]);
3555
        }
3556
3557
        $form
3558
            ->defaultRenderer()
3559
            ->setGroupElementTemplate('<p>{element}</p>', "extra_$variable");
3560
        $form->addGroup([$slctFirst, $slctSecond, $slctThird], "extra_$variable", $fieldDetails['display_text']);
3561
3562
        if ($freezeElement) {
3563
            $form->freeze('extra_'.$fieldDetails['variable']);
3564
        }
3565
3566
        return $js;
3567
    }
3568
}
3569