Passed
Push — master ( e739b7...1cdc43 )
by Julito
10:11
created

FormValidator   F

Complexity

Total Complexity 136

Size/Duplication

Total Lines 1771
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 587
dl 0
loc 1771
rs 2
c 1
b 1
f 0
wmc 136

62 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultElementTemplate() 0 3 1
A getFormTemplate() 0 3 1
A getLayout() 0 3 1
A setLayout() 0 3 1
A addSelectLanguage() 0 3 1
A addDatePicker() 0 3 1
A addDateTimePicker() 0 3 1
A addSelectAjax() 0 11 2
A addText() 0 14 3
A addDateRangePicker() 0 8 2
A addTextarea() 0 9 2
A addDateTimeRangePicker() 0 3 1
A addHidden() 0 3 1
A addButton() 0 32 2
A addButtonImport() 0 11 1
A addButtonSearch() 0 7 2
A addButtonDelete() 0 11 1
A addLabel() 0 11 2
A addButtonMove() 0 11 1
A addButtonSend() 0 11 1
A addButtonNext() 0 10 1
A addButtonFilter() 0 11 1
A addButtonDownload() 0 11 1
A addSelectFromCollection() 0 25 5
A addButtonCancel() 0 11 1
A addHeader() 0 3 1
A addButtonPreview() 0 11 1
A addRadio() 0 8 2
A addButtonCopy() 0 11 1
A addButtonExport() 0 11 1
A addCheckBoxGroup() 0 15 2
A addButtonReset() 0 30 2
A addButtonUpdate() 0 11 1
A addButtonUpload() 0 11 1
A addSelect() 0 3 1
C __construct() 0 83 13
A addButtonCreate() 0 11 1
A addCheckBox() 0 3 1
A addHtml() 0 3 1
A addProgress() 0 10 2
A addFile() 0 32 4
A addButtonAdvancedSettings() 0 5 2
A addGeoLocationMapField() 0 40 5
A add_multiple_required_rule() 0 4 1
B addPanelOption() 0 28 8
A display() 0 3 1
A getDefaultRenderer() 0 5 2
A addMultipleUpload() 0 18 1
B addEmailTemplate() 0 62 5
A addMultipleUploadJavascript() 0 109 2
A addUrl() 0 8 2
A addTextAlphanumeric() 0 35 2
A addPasswordRule() 0 30 5
A addFloat() 0 66 5
A addTextLettersAndSpaces() 0 35 2
A addTextAlphanumericAndSpaces() 0 35 2
A return_form() 0 3 1
A addTextLettersOnly() 0 35 2
A returnForm() 0 30 5
A addUserAvatar() 0 3 1
A addButtonSave() 0 11 1
C addHtmlEditor() 0 31 9

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * Class FormValidator
6
 * create/manipulate/validate user input.
7
 */
8
class FormValidator extends HTML_QuickForm
9
{
10
    public const LAYOUT_HORIZONTAL = 'horizontal';
11
    public const LAYOUT_INLINE = 'inline';
12
    public const LAYOUT_BOX = 'box';
13
    public const LAYOUT_BOX_NO_LABEL = 'box-no-label';
14
    public const LAYOUT_BOX_SEARCH = 'box-search';
15
16
    public $with_progress_bar = false;
17
    private $layout;
18
19
    /**
20
     * Constructor.
21
     *
22
     * @param string $name        Name of the form
23
     * @param string $method      (optional) Method ('post' (default) or 'get')
24
     * @param string $action      (optional) Action (default is $PHP_SELF)
25
     * @param string $target      (optional) Form's target defaults to '_self'
26
     * @param mixed  $attributes  (optional) Extra attributes for <form> tag
27
     * @param string $layout
28
     * @param bool   $trackSubmit (optional) Whether to track if the form was
29
     *                            submitted by adding a special hidden field (default = true)
30
     */
31
    public function __construct(
32
        $name,
33
        $method = 'post',
34
        $action = '',
35
        $target = '',
36
        $attributes = [],
37
        $layout = self::LAYOUT_HORIZONTAL,
38
        $trackSubmit = true
39
    ) {
40
        // Default form class.
41
        if (is_array($attributes) && !isset($attributes['class']) || empty($attributes)) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (is_array($attributes) &...) || empty($attributes), Probably Intended Meaning: is_array($attributes) &&... || empty($attributes))
Loading history...
42
            $attributes['class'] = 'form-horizontal';
43
        }
44
45
        if (isset($attributes['class']) && strpos($attributes['class'], 'form-search') !== false) {
46
            $layout = 'inline';
47
        }
48
49
        $this->setLayout($layout);
50
51
        switch ($layout) {
52
            case self::LAYOUT_HORIZONTAL:
53
                $attributes['class'] = 'form-horizontal';
54
                break;
55
            case self::LAYOUT_INLINE:
56
            case self::LAYOUT_BOX:
57
                $attributes['class'] = 'form-inline';
58
                break;
59
        }
60
61
        parent::__construct($name, $method, $action, $target, $attributes, $trackSubmit);
62
63
        // Modify the default templates
64
        $renderer = &$this->defaultRenderer();
65
66
        // Form template
67
        $formTemplate = $this->getFormTemplate();
68
        $renderer->setFormTemplate($formTemplate);
69
70
        // Element template
71
        if (isset($attributes['class']) && $attributes['class'] == 'form-inline') {
72
            $elementTemplate = ' {label}  {element} ';
73
            $renderer->setElementTemplate($elementTemplate);
74
        } elseif (isset($attributes['class']) && $attributes['class'] == 'form-search') {
75
            $elementTemplate = ' {label}  {element} ';
76
            $renderer->setElementTemplate($elementTemplate);
77
        } else {
78
            $renderer->setElementTemplate($this->getDefaultElementTemplate());
79
80
            // Display a gray div in the buttons
81
            $templateSimple = '<div class="form-actions">{label} {element}</div>';
82
            $renderer->setElementTemplate($templateSimple, 'submit_in_actions');
83
84
            //Display a gray div in the buttons + makes the button available when scrolling
85
            $templateBottom = '<div class="form-actions bottom_actions bg-form">{label} {element}</div>';
86
            $renderer->setElementTemplate($templateBottom, 'submit_fixed_in_bottom');
87
88
            //When you want to group buttons use something like this
89
            /* $group = array();
90
              $group[] = $form->createElement('button', 'mark_all', get_lang('MarkAll'));
91
              $group[] = $form->createElement('button', 'unmark_all', get_lang('UnmarkAll'));
92
              $form->addGroup($group, 'buttons_in_action');
93
             */
94
            $renderer->setElementTemplate($templateSimple, 'buttons_in_action');
95
96
            $templateSimpleRight = '<div class="form-actions"> <div class="pull-right">{label} {element}</div></div>';
97
            $renderer->setElementTemplate($templateSimpleRight, 'buttons_in_action_right');
98
        }
99
100
        //Set Header template
101
        $renderer->setHeaderTemplate('<legend>{header}</legend>');
102
103
        //Set required field template
104
        $this->setRequiredNote(
105
            '<span class="form_required">*</span> <small>'.get_lang('ThisFieldIsRequired').'</small>'
106
        );
107
108
        $noteTemplate = <<<EOT
109
	<div class="form-group">
110
		<div class="col-sm-offset-2 col-sm-10">{requiredNote}</div>
111
	</div>
112
EOT;
113
        $renderer->setRequiredNoteTemplate($noteTemplate);
114
    }
115
116
    /**
117
     * @return string
118
     */
119
    public function getFormTemplate()
120
    {
121
        return '<form{attributes}>
122
        <fieldset>
123
            {content}
124
        </fieldset>
125
        {hidden}
126
        </form>';
127
    }
128
129
    /**
130
     * @todo this function should be added in the element class
131
     *
132
     * @return string
133
     */
134
    public function getDefaultElementTemplate()
135
    {
136
        return '
137
            <div class="form-group row {error_class}">
138
                <label {label-for} class="col-sm-2 col-form-label {extra_label_class}" >
139
                    <!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
140
                    {label}
141
                </label>
142
                <div class="col-sm-8">
143
                    {icon}
144
                    {element}
145
                    <!-- BEGIN label_2 -->
146
                        <p class="help-block">{label_2}</p>
147
                    <!-- END label_2 -->
148
149
                    <!-- BEGIN error -->
150
                        <span class="help-inline help-block">{error}</span>
151
                    <!-- END error -->
152
                </div>
153
                <div class="col-sm-2">
154
                    <!-- BEGIN label_3 -->
155
                        {label_3}
156
                    <!-- END label_3 -->
157
                </div>
158
            </div>';
159
    }
160
161
    /**
162
     * @return string
163
     */
164
    public function getLayout()
165
    {
166
        return $this->layout;
167
    }
168
169
    /**
170
     * @param string $layout
171
     */
172
    public function setLayout($layout)
173
    {
174
        $this->layout = $layout;
175
    }
176
177
    /**
178
     * Adds a text field to the form.
179
     * A trim-filter is attached to the field.
180
     *
181
     * @param string|array $label      The label for the form-element
182
     * @param string       $name       The element name
183
     * @param bool         $required   (optional)    Is the form-element required (default=true)
184
     * @param array        $attributes (optional)    List of attributes for the form-element
185
     *
186
     * @return HTML_QuickForm_text
187
     */
188
    public function addText($name, $label, $required = true, $attributes = [], $createElement = false)
189
    {
190
        if ($createElement) {
191
            $element = $this->createElement('text', $name, $label, $attributes);
192
        } else {
193
            $element = $this->addElement('text', $name, $label, $attributes);
194
        }
195
196
        $this->applyFilter($name, 'trim');
197
        if ($required) {
198
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
199
        }
200
201
        return $element;
202
    }
203
204
    /**
205
     * The "date_range_picker" element creates 2 hidden fields
206
     * "elementName" + "_start"  and "elementName" + "_end"
207
     * For example if the name is "range", you will have 2 new fields
208
     * when executing $form->getSubmitValues()
209
     * "range_start" and "range_end".
210
     *
211
     * @param string $name
212
     * @param string $label
213
     * @param bool   $required
214
     * @param array  $attributes
215
     */
216
    public function addDateRangePicker($name, $label, $required = true, $attributes = [])
217
    {
218
        $this->addElement('date_range_picker', $name, $label, $attributes);
219
        $this->addElement('hidden', $name.'_start');
220
        $this->addElement('hidden', $name.'_end');
221
222
        if ($required) {
223
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
224
        }
225
    }
226
227
    /**
228
     * @param string $name
229
     * @param string $label
230
     * @param array  $attributes
231
     *
232
     * @return mixed
233
     */
234
    public function addDatePicker($name, $label, $attributes = [])
235
    {
236
        return $this->addElement('DatePicker', $name, $label, $attributes);
237
    }
238
239
    /**
240
     * @param string $name
241
     * @param string $label
242
     * @param array  $attributes
243
     *
244
     * @return mixed
245
     */
246
    public function addSelectLanguage($name, $label, $options = [], $attributes = [])
247
    {
248
        return $this->addElement('SelectLanguage', $name, $label, $options, $attributes);
249
    }
250
251
    /**
252
     * @param string $name
253
     * @param string $label
254
     * @param array  $options
255
     * @param array  $attributes
256
     *
257
     * @throws
258
     */
259
    public function addSelectAjax($name, $label, $options = [], $attributes = [])
260
    {
261
        if (!isset($attributes['url'])) {
262
            throw new \Exception('select_ajax needs an URL');
263
        }
264
        $this->addElement(
265
            'select_ajax',
266
            $name,
267
            $label,
268
            $options,
269
            $attributes
270
        );
271
    }
272
273
    /**
274
     * @param string       $name
275
     * @param string|array $label
276
     * @param array        $attributes
277
     *
278
     * @return DateTimePicker
279
     */
280
    public function addDateTimePicker($name, $label, $attributes = [])
281
    {
282
        return $this->addElement('DateTimePicker', $name, $label, $attributes);
283
    }
284
285
    /**
286
     * @param string       $name
287
     * @param string|array $label
288
     * @param array        $attributes
289
     *
290
     * @return DateTimeRangePicker
291
     */
292
    public function addDateTimeRangePicker($name, $label, $attributes = [])
293
    {
294
        return $this->addElement('DateTimeRangePicker', $name, $label, $attributes);
295
    }
296
297
    /**
298
     * @param string $name
299
     * @param string $value
300
     * @param array  $attributes
301
     */
302
    public function addHidden($name, $value, $attributes = [])
303
    {
304
        $this->addElement('hidden', $name, $value, $attributes);
305
    }
306
307
    /**
308
     * @param string       $name
309
     * @param string|array $label
310
     * @param array        $attributes
311
     * @param bool         $required
312
     *
313
     * @return HTML_QuickForm_textarea
314
     */
315
    public function addTextarea($name, $label, $attributes = [], $required = false)
316
    {
317
        $element = $this->addElement('textarea', $name, $label, $attributes);
318
319
        if ($required) {
320
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
321
        }
322
323
        return $element;
324
    }
325
326
    /**
327
     * @param string $name
328
     * @param string $label
329
     * @param string $icon          font-awesome
330
     * @param string $style         default|primary|success|info|warning|danger|link
331
     * @param string $size          large|default|small|extra-small
332
     * @param string $class         Example plus is transformed to icon fa fa-plus
333
     * @param array  $attributes
334
     * @param bool   $createElement
335
     *
336
     * @return HTML_QuickForm_button
337
     */
338
    public function addButton(
339
        $name,
340
        $label,
341
        $icon = 'check',
342
        $style = 'default',
343
        $size = 'default',
344
        $class = null,
345
        $attributes = [],
346
        $createElement = false
347
    ) {
348
        if ($createElement) {
349
            return $this->createElement(
350
                'button',
351
                $name,
352
                $label,
353
                $icon,
354
                $style,
355
                $size,
356
                $class,
357
                $attributes
358
            );
359
        }
360
361
        return $this->addElement(
362
            'button',
363
            $name,
364
            $label,
365
            $icon,
366
            $style,
367
            $size,
368
            $class,
369
            $attributes
370
        );
371
    }
372
373
    /**
374
     * Returns a button with the primary color and a check mark.
375
     *
376
     * @param string $label         Text appearing on the button
377
     * @param string $name          Element name (for form treatment purposes)
378
     * @param bool   $createElement Whether to use the create or add method
379
     * @param array  $attributes
380
     *
381
     * @return HTML_QuickForm_button
382
     */
383
    public function addButtonSave($label, $name = 'submit', $createElement = false, $attributes = [])
384
    {
385
        return $this->addButton(
386
            $name,
387
            $label,
388
            'check',
389
            'primary',
390
            null,
391
            null,
392
            $attributes,
393
            $createElement
394
        );
395
    }
396
397
    /**
398
     * Returns a cancel button.
399
     *
400
     * @param string $label         Text appearing on the button
401
     * @param string $name          Element name (for form treatment purposes)
402
     * @param bool   $createElement Whether to use the create or add method
403
     *
404
     * @return HTML_QuickForm_button
405
     */
406
    public function addButtonCancel($label, $name = 'submit', $createElement = false)
407
    {
408
        return $this->addButton(
409
            $name,
410
            $label,
411
            'times',
412
            'danger',
413
            null,
414
            null,
415
            [],
416
            $createElement
417
        );
418
    }
419
420
    /**
421
     * Returns a button with the primary color and a "plus" icon.
422
     *
423
     * @param string $label         Text appearing on the button
424
     * @param string $name          Element name (for form treatment purposes)
425
     * @param bool   $createElement Whether to use the create or add method
426
     * @param array  $attributes    Additional attributes
427
     *
428
     * @return HTML_QuickForm_button
429
     */
430
    public function addButtonCreate($label, $name = 'submit', $createElement = false, $attributes = [])
431
    {
432
        return $this->addButton(
433
            $name,
434
            $label,
435
            'plus',
436
            'primary',
437
            null,
438
            null,
439
            $attributes,
440
            $createElement
441
        );
442
    }
443
444
    /**
445
     * Returns a button with the primary color and a pencil icon.
446
     *
447
     * @param string $label         Text appearing on the button
448
     * @param string $name          Element name (for form treatment purposes)
449
     * @param bool   $createElement Whether to use the create or add method
450
     *
451
     * @return HTML_QuickForm_button
452
     */
453
    public function addButtonUpdate($label, $name = 'submit', $createElement = false)
454
    {
455
        return $this->addButton(
456
            $name,
457
            $label,
458
            'pencil',
459
            'primary',
460
            null,
461
            null,
462
            [],
463
            $createElement
464
        );
465
    }
466
467
    /**
468
     * Returns a button with the danger color and a trash icon.
469
     *
470
     * @param string $label         Text appearing on the button
471
     * @param string $name          Element name (for form treatment purposes)
472
     * @param bool   $createElement Whether to use the create or add method
473
     *
474
     * @return HTML_QuickForm_button
475
     */
476
    public function addButtonDelete($label, $name = 'submit', $createElement = false)
477
    {
478
        return $this->addButton(
479
            $name,
480
            $label,
481
            'trash',
482
            'danger',
483
            null,
484
            null,
485
            [],
486
            $createElement
487
        );
488
    }
489
490
    /**
491
     * Returns a move style button.
492
     *
493
     * @param string $label         Text appearing on the button
494
     * @param string $name          Element name (for form treatment purposes)
495
     * @param bool   $createElement Whether to use the create or add method
496
     *
497
     * @return HTML_QuickForm_button
498
     */
499
    public function addButtonMove($label, $name = 'submit', $createElement = false)
500
    {
501
        return $this->addButton(
502
            $name,
503
            $label,
504
            'arrow-circle-right',
505
            'primary',
506
            null,
507
            null,
508
            [],
509
            $createElement
510
        );
511
    }
512
513
    /**
514
     * Returns a button with the primary color and a paper-plane icon.
515
     *
516
     * @param string $label         Text appearing on the button
517
     * @param string $name          Element name (for form treatment purposes)
518
     * @param bool   $createElement Whether to use the create or add method
519
     * @param array  $attributes
520
     *
521
     * @return HTML_QuickForm_button
522
     */
523
    public function addButtonSend($label, $name = 'submit', $createElement = false, $attributes = [])
524
    {
525
        return $this->addButton(
526
            $name,
527
            $label,
528
            'paper-plane',
529
            'primary',
530
            null,
531
            null,
532
            $attributes,
533
            $createElement
534
        );
535
    }
536
537
    /**
538
     * Returns a button with the default (grey?) color and a magnifier icon.
539
     *
540
     * @param string $label Text appearing on the button
541
     * @param string $name  Element name (for form treatment purposes)
542
     *
543
     * @return HTML_QuickForm_button
544
     */
545
    public function addButtonSearch($label = null, $name = 'submit')
546
    {
547
        if (empty($label)) {
548
            $label = get_lang('Search');
549
        }
550
551
        return $this->addButton($name, $label, 'search', 'primary');
552
    }
553
554
    /**
555
     * Returns a button with the primary color and a right-pointing arrow icon.
556
     *
557
     * @param string $label      Text appearing on the button
558
     * @param string $name       Element name (for form treatment purposes)
559
     * @param array  $attributes Additional attributes
560
     *
561
     * @return HTML_QuickForm_button
562
     */
563
    public function addButtonNext($label, $name = 'submit', $attributes = [])
564
    {
565
        return $this->addButton(
566
            $name,
567
            $label,
568
            'arrow-right',
569
            'primary',
570
            null,
571
            null,
572
            $attributes
573
        );
574
    }
575
576
    /**
577
     * Returns a button with the primary color and a check mark icon.
578
     *
579
     * @param string $label         Text appearing on the button
580
     * @param string $name          Element name (for form treatment purposes)
581
     * @param bool   $createElement Whether to use the create or add method
582
     *
583
     * @return HTML_QuickForm_button
584
     */
585
    public function addButtonImport($label, $name = 'submit', $createElement = false)
586
    {
587
        return $this->addButton(
588
            $name,
589
            $label,
590
            'check',
591
            'primary',
592
            null,
593
            null,
594
            [],
595
            $createElement
596
        );
597
    }
598
599
    /**
600
     * Returns a button with the primary color and a check-mark icon.
601
     *
602
     * @param string $label         Text appearing on the button
603
     * @param string $name          Element name (for form treatment purposes)
604
     * @param bool   $createElement Whether to use the create or add method
605
     *
606
     * @return HTML_QuickForm_button
607
     */
608
    public function addButtonExport($label, $name = 'submit', $createElement = false)
609
    {
610
        return $this->addButton(
611
            $name,
612
            $label,
613
            'check',
614
            'primary',
615
            null,
616
            null,
617
            [],
618
            $createElement
619
        );
620
    }
621
622
    /**
623
     * Shortcut to filter button.
624
     *
625
     * @param string $label         Text appearing on the button
626
     * @param string $name          Element name (for form treatment purposes)
627
     * @param bool   $createElement Whether to use the create or add method
628
     *
629
     * @return HTML_QuickForm_button
630
     */
631
    public function addButtonFilter($label, $name = 'submit', $createElement = false)
632
    {
633
        return $this->addButton(
634
            $name,
635
            $label,
636
            'filter',
637
            'primary',
638
            null,
639
            null,
640
            [],
641
            $createElement
642
        );
643
    }
644
645
    /**
646
     * Shortcut to reset button.
647
     *
648
     * @param string $label         Text appearing on the button
649
     * @param string $name          Element name (for form treatment purposes)
650
     * @param bool   $createElement Whether to use the create or add method
651
     *
652
     * @return HTML_QuickForm_button
653
     */
654
    public function addButtonReset($label, $name = 'reset', $createElement = false)
655
    {
656
        $icon = 'eraser';
657
        $style = 'default';
658
        $size = 'default';
659
        $class = null;
660
        $attributes = [];
661
662
        if ($createElement) {
663
            return $this->createElement(
664
                'reset',
665
                $name,
666
                $label,
667
                $icon,
668
                $style,
669
                $size,
670
                $class,
671
                $attributes
672
            );
673
        }
674
675
        return $this->addElement(
676
            'reset',
677
            $name,
678
            $label,
679
            $icon,
680
            $style,
681
            $size,
682
            $class,
683
            $attributes
684
        );
685
    }
686
687
    /**
688
     * Returns a button with the primary color and an upload icon.
689
     *
690
     * @param string $label         Text appearing on the button
691
     * @param string $name          Element name (for form treatment purposes)
692
     * @param bool   $createElement Whether to use the create or add method
693
     *
694
     * @return HTML_QuickForm_button
695
     */
696
    public function addButtonUpload($label, $name = 'submit', $createElement = false)
697
    {
698
        return $this->addButton(
699
            $name,
700
            $label,
701
            'upload',
702
            'primary',
703
            null,
704
            null,
705
            [],
706
            $createElement
707
        );
708
    }
709
710
    /**
711
     * Returns a button with the primary color and a download icon.
712
     *
713
     * @param string $label         Text appearing on the button
714
     * @param string $name          Element name (for form treatment purposes)
715
     * @param bool   $createElement Whether to use the create or add method
716
     *
717
     * @return HTML_QuickForm_button
718
     */
719
    public function addButtonDownload($label, $name = 'submit', $createElement = false)
720
    {
721
        return $this->addButton(
722
            $name,
723
            $label,
724
            'download',
725
            'primary',
726
            null,
727
            null,
728
            [],
729
            $createElement
730
        );
731
    }
732
733
    /**
734
     * Returns a button with the primary color and a magnifier icon.
735
     *
736
     * @param string $label         Text appearing on the button
737
     * @param string $name          Element name (for form treatment purposes)
738
     * @param bool   $createElement Whether to use the create or add method
739
     *
740
     * @return HTML_QuickForm_button
741
     */
742
    public function addButtonPreview($label, $name = 'submit', $createElement = false)
743
    {
744
        return $this->addButton(
745
            $name,
746
            $label,
747
            'search',
748
            'primary',
749
            null,
750
            null,
751
            [],
752
            $createElement
753
        );
754
    }
755
756
    /**
757
     * Returns a button with the primary color and a copy (double sheet) icon.
758
     *
759
     * @param string $label         Text appearing on the button
760
     * @param string $name          Element name (for form treatment purposes)
761
     * @param bool   $createElement Whether to use the create or add method
762
     *
763
     * @return HTML_QuickForm_button
764
     */
765
    public function addButtonCopy($label, $name = 'submit', $createElement = false)
766
    {
767
        return $this->addButton(
768
            $name,
769
            $label,
770
            'copy',
771
            'primary',
772
            null,
773
            null,
774
            [],
775
            $createElement
776
        );
777
    }
778
779
    /**
780
     * @param string $name
781
     * @param string $label
782
     * @param string $text
783
     * @param array  $attributes
784
     *
785
     * @return HTML_QuickForm_checkbox
786
     */
787
    public function addCheckBox($name, $label, $text = '', $attributes = [])
788
    {
789
        return $this->addElement('checkbox', $name, $label, $text, $attributes);
790
    }
791
792
    /**
793
     * @param string $name
794
     * @param string $label
795
     * @param array  $options
796
     * @param array  $attributes
797
     *
798
     * @return HTML_QuickForm_group
799
     */
800
    public function addCheckBoxGroup($name, $label, $options = [], $attributes = [])
801
    {
802
        $group = [];
803
        foreach ($options as $value => $text) {
804
            $attributes['value'] = $value;
805
            $group[] = $this->createElement(
806
                'checkbox',
807
                $value,
808
                null,
809
                $text,
810
                $attributes
811
            );
812
        }
813
814
        return $this->addGroup($group, $name, $label);
815
    }
816
817
    /**
818
     * @param string $name
819
     * @param string $label
820
     * @param array  $options
821
     * @param array  $attributes
822
     *
823
     * @return HTML_QuickForm_group
824
     */
825
    public function addRadio($name, $label, $options = [], $attributes = [])
826
    {
827
        $group = [];
828
        foreach ($options as $key => $value) {
829
            $group[] = $this->createElement('radio', null, null, $value, $key, $attributes);
830
        }
831
832
        return $this->addGroup($group, $name, $label);
833
    }
834
835
    /**
836
     * @param string $name
837
     * @param string $label
838
     * @param array  $options
839
     * @param array  $attributes
840
     *
841
     * @return HTML_QuickForm_select
842
     */
843
    public function addSelect($name, $label, $options = [], $attributes = [])
844
    {
845
        return $this->addElement('select', $name, $label, $options, $attributes);
846
    }
847
848
    /**
849
     * @param $name
850
     * @param $label
851
     * @param $collection
852
     * @param array  $attributes
853
     * @param bool   $addNoneOption
854
     * @param string $textCallable  set a function getStringValue() by default __toString()
855
     *
856
     * @return HTML_QuickForm_element
857
     */
858
    public function addSelectFromCollection(
859
        $name,
860
        $label,
861
        $collection,
862
        $attributes = [],
863
        $addNoneOption = false,
864
        $textCallable = ''
865
    ) {
866
        $options = [];
867
868
        if ($addNoneOption) {
869
            $options[0] = get_lang('None');
870
        }
871
872
        if (!empty($collection)) {
873
            foreach ($collection as $item) {
874
                $text = $item;
875
                if (!empty($textCallable)) {
876
                    $text = $item->$textCallable();
877
                }
878
                $options[$item->getId()] = $text;
879
            }
880
        }
881
882
        return $this->addElement('select', $name, $label, $options, $attributes);
883
    }
884
885
    /**
886
     * @param string $label
887
     * @param string $text
888
     * @param bool   $createElement
889
     *
890
     * @return HTML_QuickForm_Element
891
     */
892
    public function addLabel($label, $text, $createElement = false)
893
    {
894
        if ($createElement) {
895
            return $this->createElement(
896
                'label',
897
                $label,
898
                $text
899
            );
900
        }
901
902
        return $this->addElement('label', $label, $text);
903
    }
904
905
    /**
906
     * @param string $text
907
     */
908
    public function addHeader($text)
909
    {
910
        $this->addElement('header', $text);
911
    }
912
913
    /**
914
     * @param string $name
915
     * @param string $label
916
     * @param array  $attributes
917
     *
918
     * @throws Exception if the file doesn't have an id
919
     *
920
     * @return HTML_QuickForm_file
921
     */
922
    public function addFile($name, $label, $attributes = [])
923
    {
924
        try {
925
            $element = $this->addElement('file', $name, $label, $attributes);
926
            if (isset($attributes['crop_image'])) {
927
                $id = $element->getAttribute('id');
928
                if (empty($id)) {
929
                    throw new Exception('If you use the crop functionality the element must have an id');
930
                }
931
                $this->addHtml(
932
                    '
933
                <div class="form-group row" id="'.$id.'-form-group" style="display: none;">
934
                    <div class="offset-md-2 col-sm-8">
935
                        <div class="card-cropper">
936
                            <div id="'.$id.'_crop_image" class="cropCanvas">
937
                                <img id="'.$id.'_preview_image">
938
                            </div>
939
                            <button class="btn btn-primary" type="button" name="cropButton" id="'.$id.'_crop_button">
940
                                <em class="fa fa-crop"></em> '.get_lang('CropYourPicture').'
941
                            </button>
942
                        </div>
943
                    </div>
944
                </div>'
945
                );
946
                $this->addHidden($id.'_crop_result', '');
947
                $this->addHidden($id.'_crop_image_base_64', '');
948
            }
949
        } catch (HTML_Quick | Form_Error $e) {
950
            var_dump($e->getMessage());
0 ignored issues
show
Security Debugging Code introduced by
var_dump($e->getMessage()) looks like debug code. Are you sure you do not want to remove it?
Loading history...
951
        }
952
953
        return $element;
954
    }
955
956
    /**
957
     * @param string $snippet
958
     */
959
    public function addHtml($snippet)
960
    {
961
        $this->addElement('html', $snippet);
962
    }
963
964
    /**
965
     * Draws a panel of options see the course_info/infocours.php page.
966
     *
967
     * @param string $name      internal name
968
     * @param string $title     visible title
969
     * @param array  $groupList list of group or elements
970
     */
971
    public function addPanelOption($name, $title, $groupList, $icon, $open = false, $parent)
972
    {
973
        $html = '<div class="card">';
974
        $html .= '<div class="card-header" id="card_'.$name.'">';
975
        $html .= '<h5 class="card-title">';
976
        $html .= '<a role="button" class="'.(($open) ? 'collapse' : ' ').'"  data-toggle="collapse" data-target="#collapse_'.$name.'" aria-expanded="true" aria-controls="collapse_'.$name.'">';
977
        if ($icon) {
978
            $html .= Display::return_icon($icon, null, null, ICON_SIZE_SMALL);
979
        }
980
        $html .= $title;
981
        $html .= '</a></h5></div>';
982
        $html .= '<div id="collapse_'.$name.'" class="collapse '.(($open) ? 'show' : ' ').'" aria-labelledby="heading_'.$name.'" data-parent="#'.$parent.'">';
983
        $html .= '<div class="card-body">';
984
985
        $this->addHtml($html);
986
987
        foreach ($groupList as $groupName => $group) {
988
            // Add group array
989
            if (!empty($groupName) && is_array($group)) {
990
                $this->addGroup($group, '', $groupName);
991
            }
992
            // Add element
993
            if ($group instanceof HTML_QuickForm_element) {
994
                $this->addElement($group);
995
            }
996
        }
997
998
        $this->addHtml('</div></div></div>');
999
    }
1000
1001
    /**
1002
     * Adds a HTML-editor to the form.
1003
     *
1004
     * @param string       $name
1005
     * @param string|array $label      The label for the form-element
1006
     * @param bool         $required   (optional) Is the form-element required (default=true)
1007
     * @param bool         $fullPage   (optional) When it is true, the editor loads completed html code for a full page
1008
     * @param array        $config     (optional) Configuration settings for the online editor
1009
     * @param array        $attributes
1010
     *
1011
     * @throws Exception
1012
     * @throws HTML_QuickForm_Error
1013
     */
1014
    public function addHtmlEditor(
1015
        $name,
1016
        $label,
1017
        $required = true,
1018
        $fullPage = false,
1019
        $config = [],
1020
        $attributes = []
1021
    ) {
1022
        $attributes = [];
1023
        $attributes['rows'] = isset($config['rows']) ? $config['rows'] : 15;
1024
        $attributes['cols'] = isset($config['cols']) ? $config['cols'] : 80;
1025
        $attributes['cols-size'] = isset($config['cols-size']) ? $config['cols-size'] : [];
1026
        $attributes['class'] = isset($config['class']) ? $config['class'] : [];
1027
1028
        $this->addElement('html_editor', $name, $label, $attributes, $config);
1029
        $this->applyFilter($name, 'trim');
1030
        if ($required) {
1031
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1032
        }
1033
1034
        /** @var HtmlEditor $element */
1035
        $element = $this->getElement($name);
1036
        $config['style'] = isset($config['style']) ? $config['style'] : false;
1037
        if ($fullPage) {
1038
            $config['fullPage'] = true;
1039
            // Adds editor_content.css in ckEditor
1040
            $config['style'] = true;
1041
        }
1042
1043
        if ($element->editor) {
1044
            $element->editor->processConfig($config);
1045
        }
1046
    }
1047
1048
    /**
1049
     * Adds a Google Maps Geolocalization field to the form.
1050
     *
1051
     * @param      $name
1052
     * @param      $label
1053
     * @param bool $hideGeoLocalizationDetails
1054
     */
1055
    public function addGeoLocationMapField($name, $label, $dataValue, $hideGeoLocalizationDetails = false)
1056
    {
1057
        $gMapsPlugin = GoogleMapsPlugin::create();
1058
        $geolocalization = $gMapsPlugin->get('enable_api') === 'true';
1059
1060
        if ($geolocalization && $gMapsPlugin->javascriptIncluded === false) {
1061
            $gmapsApiKey = $gMapsPlugin->get('api_key');
1062
            $url = '//maps.googleapis.com/maps/api/js?key='.$gmapsApiKey;
1063
            $this->addHtml('<script type="text/javascript" src="'.$url.'" ></script>');
1064
            $gMapsPlugin->javascriptIncluded = true;
1065
        }
1066
1067
        $this->addElement(
1068
            'text',
1069
            $name,
1070
            $label,
1071
            ['id' => $name]
1072
        );
1073
1074
        $this->addHidden(
1075
            $name.'_coordinates',
1076
            '',
1077
            ['id' => $name.'_coordinates']
1078
        );
1079
1080
        $this->applyFilter($name, 'stripslashes');
1081
        $this->applyFilter($name, 'trim');
1082
1083
        $this->addHtml(Extrafield::getLocalizationJavascript($name, $dataValue));
1084
1085
        if ($hideGeoLocalizationDetails) {
1086
            $this->addHtml('<div style="display:none">');
1087
        }
1088
1089
        $this->addHtml(
1090
            Extrafield::getLocalizationInput($name, $label)
1091
        );
1092
1093
        if ($hideGeoLocalizationDetails) {
1094
            $this->addHtml('</div>');
1095
        }
1096
    }
1097
1098
    /**
1099
     * @param string $name
1100
     * @param string $label
1101
     *
1102
     * @return mixed
1103
     */
1104
    public function addButtonAdvancedSettings($name, $label = '')
1105
    {
1106
        $label = !empty($label) ? $label : get_lang('AdvancedParameters');
1107
1108
        return $this->addElement('advanced_settings', $name, $label);
1109
    }
1110
1111
    /**
1112
     * Adds a progress loading image to the form.
1113
     */
1114
    public function addProgress($delay = 2, $label = '')
1115
    {
1116
        if (empty($label)) {
1117
            $label = get_lang('PleaseStandBy');
1118
        }
1119
        $this->with_progress_bar = true;
1120
        $id = $this->getAttribute('id');
1121
1122
        $this->updateAttributes("onsubmit=\"javascript: addProgress('".$id."')\"");
1123
        $this->addHtml('<script language="javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/upload.js" type="text/javascript"></script>');
1124
    }
1125
1126
    /**
1127
     * This function has been created for avoiding changes directly within QuickForm class.
1128
     * When we use it, the element is threated as 'required' to be dealt during validation.
1129
     *
1130
     * @param array  $elements The array of elements
1131
     * @param string $message  The message displayed
1132
     */
1133
    public function add_multiple_required_rule($elements, $message)
1134
    {
1135
        $this->_required[] = $elements[0];
0 ignored issues
show
Bug Best Practice introduced by
The property _required does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
1136
        $this->addRule($elements, $message, 'multiple_required');
1137
    }
1138
1139
    /**
1140
     * Displays the form.
1141
     * If an element in the form didn't validate, an error message is showed
1142
     * asking the user to complete the form.
1143
     */
1144
    public function display()
1145
    {
1146
        echo $this->returnForm();
1147
    }
1148
1149
    /**
1150
     * Returns the HTML code of the form.
1151
     *
1152
     * @return string $return_value HTML code of the form
1153
     */
1154
    public function returnForm()
1155
    {
1156
        $returnValue = '';
1157
1158
        /** @var HTML_QuickForm_element $element */
1159
        foreach ($this->_elements as $element) {
1160
            $elementError = parent::getElementError($element->getName());
1161
            if (!is_null($elementError)) {
1162
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1163
                break;
1164
            }
1165
        }
1166
1167
        $returnValue .= parent::toHtml();
1168
        // Add div-element which is to hold the progress bar
1169
        $id = $this->getAttribute('id');
1170
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1171
            // Deprecated
1172
            // $icon = Display::return_icon('progress_bar.gif');
1173
1174
            // @todo improve UI
1175
            $returnValue .= '<br />
1176
1177
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1178
                <div class="wobblebar-loader"></div>
1179
            </div>
1180
            ';
1181
        }
1182
1183
        return $returnValue;
1184
    }
1185
1186
    /**
1187
     * Returns the HTML code of the form.
1188
     * If an element in the form didn't validate, an error message is showed
1189
     * asking the user to complete the form.
1190
     *
1191
     * @return string $return_value HTML code of the form
1192
     *
1193
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1194
     * @author Julio Montoya
1195
     *
1196
     * @deprecated use returnForm()
1197
     */
1198
    public function return_form()
1199
    {
1200
        return $this->returnForm();
1201
    }
1202
1203
    /**
1204
     * @return HTML_QuickForm_Renderer_Default
1205
     */
1206
    public static function getDefaultRenderer()
1207
    {
1208
        return
1209
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1210
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1211
    }
1212
1213
    /**
1214
     * Adds a input of type url to the form.
1215
     *
1216
     * @param string $name       The label for the form-element
1217
     * @param string $label      The element name
1218
     * @param bool   $required   Optional. Is the form-element required (default=true)
1219
     * @param array  $attributes Optional. List of attributes for the form-element
1220
     */
1221
    public function addUrl($name, $label, $required = true, $attributes = [])
1222
    {
1223
        $this->addElement('url', $name, $label, $attributes);
1224
        $this->applyFilter($name, 'trim');
1225
        $this->addRule($name, get_lang('InsertAValidUrl'), 'url');
1226
1227
        if ($required) {
1228
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1229
        }
1230
    }
1231
1232
    /**
1233
     * Adds a text field for letters to the form.
1234
     * A trim-filter is attached to the field.
1235
     *
1236
     * @param string $name       The element name
1237
     * @param string $label      The label for the form-element
1238
     * @param bool   $required   Optional. Is the form-element required (default=true)
1239
     * @param array  $attributes Optional. List of attributes for the form-element
1240
     */
1241
    public function addTextLettersOnly(
1242
        $name,
1243
        $label,
1244
        $required = false,
1245
        $attributes = []
1246
    ) {
1247
        $attributes = array_merge(
1248
            $attributes,
1249
            [
1250
                'pattern' => '[a-zA-ZñÑ]+',
1251
                'title' => get_lang('OnlyLetters'),
1252
            ]
1253
        );
1254
1255
        $this->addElement(
1256
            'text',
1257
            $name,
1258
            [
1259
                $label,
1260
                get_lang('OnlyLetters'),
1261
            ],
1262
            $attributes
1263
        );
1264
1265
        $this->applyFilter($name, 'trim');
1266
1267
        if ($required) {
1268
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1269
        }
1270
1271
        $this->addRule(
1272
            $name,
1273
            get_lang('OnlyLetters'),
1274
            'regex',
1275
            '/^[a-zA-ZñÑ]+$/'
1276
        );
1277
    }
1278
1279
    /**
1280
     * Adds a text field for alphanumeric characters to the form.
1281
     * A trim-filter is attached to the field.
1282
     *
1283
     * @param string $name       The element name
1284
     * @param string $label      The label for the form-element
1285
     * @param bool   $required   Optional. Is the form-element required (default=true)
1286
     * @param array  $attributes Optional. List of attributes for the form-element
1287
     */
1288
    public function addTextAlphanumeric(
1289
        $name,
1290
        $label,
1291
        $required = false,
1292
        $attributes = []
1293
    ) {
1294
        $attributes = array_merge(
1295
            $attributes,
1296
            [
1297
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1298
                'title' => get_lang('OnlyLettersAndNumbers'),
1299
            ]
1300
        );
1301
1302
        $this->addElement(
1303
            'text',
1304
            $name,
1305
            [
1306
                $label,
1307
                get_lang('OnlyLettersAndNumbers'),
1308
            ],
1309
            $attributes
1310
        );
1311
1312
        $this->applyFilter($name, 'trim');
1313
1314
        if ($required) {
1315
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1316
        }
1317
1318
        $this->addRule(
1319
            $name,
1320
            get_lang('OnlyLettersAndNumbers'),
1321
            'regex',
1322
            '/^[a-zA-Z0-9ÑÑ]+$/'
1323
        );
1324
    }
1325
1326
    /**
1327
     * @param string $name
1328
     * @param $label
1329
     * @param bool  $required
1330
     * @param array $attributes
1331
     * @param bool  $allowNegative
1332
     * @param int   $minValue
1333
     * @param null  $maxValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $maxValue is correct as it would always require null to be passed?
Loading history...
1334
     */
1335
    public function addFloat(
1336
        $name,
1337
        $label,
1338
        $required = false,
1339
        $attributes = [],
1340
        $allowNegative = false,
1341
        $minValue = null,
1342
        $maxValue = null
1343
    ) {
1344
        $this->addElement(
1345
            'FloatNumber',
1346
            $name,
1347
            $label,
1348
            $attributes
1349
        );
1350
1351
        $this->applyFilter($name, 'trim');
1352
1353
        if ($required) {
1354
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1355
        }
1356
1357
        // Rule allows "," and "."
1358
        /*$this->addRule(
1359
            $name,
1360
            get_lang('OnlyNumbers'),
1361
            'regex',
1362
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1363
        );*/
1364
1365
        if ($allowNegative == false) {
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...
1366
            $this->addRule(
1367
                $name,
1368
                get_lang('NegativeValue'),
1369
                'compare',
1370
                '>=',
1371
                'server',
1372
                false,
1373
                false,
1374
                0
1375
            );
1376
        }
1377
1378
        if (!is_null($minValue)) {
1379
            $this->addRule(
1380
                $name,
1381
                get_lang('UnderMin'),
1382
                'compare',
1383
                '>=',
1384
                'server',
1385
                false,
1386
                false,
1387
                $minValue
1388
            );
1389
        }
1390
1391
        if (!is_null($maxValue)) {
1392
            $this->addRule(
1393
                $name,
1394
                get_lang('OverMax'),
1395
                'compare',
1396
                '<=',
1397
                'server',
1398
                false,
1399
                false,
1400
                $maxValue
1401
            );
1402
        }
1403
    }
1404
1405
    /**
1406
     * Adds a text field for letters and spaces to the form.
1407
     * A trim-filter is attached to the field.
1408
     *
1409
     * @param string $name       The element name
1410
     * @param string $label      The label for the form-element
1411
     * @param bool   $required   Optional. Is the form-element required (default=true)
1412
     * @param array  $attributes Optional. List of attributes for the form-element
1413
     */
1414
    public function addTextLettersAndSpaces(
1415
        $name,
1416
        $label,
1417
        $required = false,
1418
        $attributes = []
1419
    ) {
1420
        $attributes = array_merge(
1421
            $attributes,
1422
            [
1423
                'pattern' => '[a-zA-ZñÑ\s]+',
1424
                'title' => get_lang('OnlyLettersAndSpaces'),
1425
            ]
1426
        );
1427
1428
        $this->addElement(
1429
            'text',
1430
            $name,
1431
            [
1432
                $label,
1433
                get_lang('OnlyLettersAndSpaces'),
1434
            ],
1435
            $attributes
1436
        );
1437
1438
        $this->applyFilter($name, 'trim');
1439
1440
        if ($required) {
1441
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1442
        }
1443
1444
        $this->addRule(
1445
            $name,
1446
            get_lang('OnlyLettersAndSpaces'),
1447
            'regex',
1448
            '/^[a-zA-ZñÑ\s]+$/'
1449
        );
1450
    }
1451
1452
    /**
1453
     * Adds a text field for alphanumeric and spaces characters to the form.
1454
     * A trim-filter is attached to the field.
1455
     *
1456
     * @param string $name       The element name
1457
     * @param string $label      The label for the form-element
1458
     * @param bool   $required   Optional. Is the form-element required (default=true)
1459
     * @param array  $attributes Optional. List of attributes for the form-element
1460
     */
1461
    public function addTextAlphanumericAndSpaces(
1462
        $name,
1463
        $label,
1464
        $required = false,
1465
        $attributes = []
1466
    ) {
1467
        $attributes = array_merge(
1468
            $attributes,
1469
            [
1470
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1471
                'title' => get_lang('OnlyLettersAndNumbersAndSpaces'),
1472
            ]
1473
        );
1474
1475
        $this->addElement(
1476
            'text',
1477
            $name,
1478
            [
1479
                $label,
1480
                get_lang('OnlyLettersAndNumbersAndSpaces'),
1481
            ],
1482
            $attributes
1483
        );
1484
1485
        $this->applyFilter($name, 'trim');
1486
1487
        if ($required) {
1488
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1489
        }
1490
1491
        $this->addRule(
1492
            $name,
1493
            get_lang('OnlyLettersAndNumbersAndSpaces'),
1494
            'regex',
1495
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1496
        );
1497
    }
1498
1499
    /**
1500
     * @param string $url
1501
     * @param string $urlToRedirect after upload redirect to this page
1502
     */
1503
    public function addMultipleUpload($url, $urlToRedirect = '')
1504
    {
1505
        $inputName = 'input_file_upload';
1506
        $this->addMultipleUploadJavascript($url, $inputName, $urlToRedirect);
1507
1508
        $this->addHtml('
1509
            <div class="description-upload">
1510
            '.get_lang('ClickToSelectOrDragAndDropMultipleFilesOnTheUploadField').'
1511
            </div>
1512
            <span class="btn btn-success fileinput-button">
1513
                <i class="glyphicon glyphicon-plus"></i>
1514
                <span>'.get_lang('AddFiles').'</span>
1515
                <!-- The file input field used as target for the file upload widget -->
1516
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1517
            </span>
1518
            <div id="dropzone">
1519
                <div class="button-load">
1520
                '.get_lang('UploadFiles').'
1521
                </div>
1522
            </div>
1523
            <br />
1524
            <!-- The global progress bar -->
1525
            <div id="progress" class="progress">
1526
                <div class="progress-bar progress-bar-success"></div>
1527
            </div>
1528
            <div id="files" class="files"></div>
1529
        ');
1530
    }
1531
1532
    /**
1533
     * @param string $elementName
1534
     * @param string $groupName   if element is inside a group
1535
     *
1536
     * @throws Exception
1537
     */
1538
    public function addPasswordRule($elementName, $groupName = '')
1539
    {
1540
        if (api_get_setting('security.check_password') == 'true') {
1541
            $message = get_lang('PassTooEasy').': '.api_generate_password();
1542
1543
            if (!empty($groupName)) {
1544
                $groupObj = $this->getElement($groupName);
1545
1546
                if ($groupObj instanceof HTML_QuickForm_group) {
1547
                    $elementName = $groupObj->getElementName($elementName);
1548
1549
                    if ($elementName === false) {
1550
                        throw new Exception("The $groupName doesn't have the element $elementName");
1551
                    }
1552
1553
                    $this->_rules[$elementName][] = [
0 ignored issues
show
Bug Best Practice introduced by
The property _rules does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
1554
                        'type' => 'callback',
1555
                        'format' => 'api_check_password',
1556
                        'message' => $message,
1557
                        'validation' => '',
1558
                        'reset' => false,
1559
                        'group' => $groupName,
1560
                    ];
1561
                }
1562
            } else {
1563
                $this->addRule(
1564
                    $elementName,
1565
                    $message,
1566
                    'callback',
1567
                    'api_check_password'
1568
                );
1569
            }
1570
        }
1571
    }
1572
1573
    /**
1574
     * Add an element with user ID and avatar to the form.
1575
     * It needs a Chamilo\UserBundle\Entity\User as value. The exported value is the Chamilo\UserBundle\Entity\User ID.
1576
     *
1577
     * @see \UserAvatar
1578
     *
1579
     * @param string $name
1580
     * @param string $label
1581
     * @param string $imageSize Optional. Small, medium or large image
1582
     * @param string $subtitle  Optional. The subtitle for the field
1583
     *
1584
     * @return \UserAvatar
1585
     */
1586
    public function addUserAvatar($name, $label, $imageSize = 'small', $subtitle = '')
1587
    {
1588
        return $this->addElement('UserAvatar', $name, $label, ['image_size' => $imageSize, 'sub_title' => $subtitle]);
1589
    }
1590
1591
    /**
1592
     * @param array $typeList
1593
     */
1594
    public function addEmailTemplate($typeList)
1595
    {
1596
        $mailManager = new MailTemplateManager();
1597
        foreach ($typeList as $type) {
1598
            $list = $mailManager->get_all(
1599
                ['where' => ['type = ? AND url_id = ?' => [$type, api_get_current_access_url_id()]]]
1600
            );
1601
1602
            $options = [get_lang('Select')];
1603
            $name = $type;
1604
            $defaultId = '';
1605
            foreach ($list as $item) {
1606
                $options[$item['id']] = $item['name'];
1607
                $name = $item['name'];
1608
                if (empty($defaultId)) {
1609
                    $defaultId = $item['default_template'] == 1 ? $item['id'] : '';
1610
                }
1611
            }
1612
1613
            $url = api_get_path(WEB_AJAX_PATH).'mail.ajax.php?a=select_option';
1614
            $typeNoDots = 'email_template_option_'.str_replace('.tpl', '', $type);
1615
            $this->addSelect(
1616
                'email_template_option['.$type.']',
1617
                $name,
1618
                $options,
1619
                ['id' => $typeNoDots]
1620
            );
1621
1622
            $templateNoDots = 'email_template_'.str_replace('.tpl', '', $type);
1623
            $templateNoDotsBlock = 'email_template_block_'.str_replace('.tpl', '', $type);
1624
            $this->addHtml('<div id="'.$templateNoDotsBlock.'" style="display:none">');
1625
            $this->addTextarea(
1626
                $templateNoDots,
1627
                get_lang('Preview'),
1628
                ['disabled' => 'disabled ', 'id' => $templateNoDots, 'rows' => '5']
1629
            );
1630
            $this->addHtml('</div>');
1631
1632
            $this->addHtml("<script>            
1633
            $(function() {
1634
                var defaultValue = '$defaultId';
1635
                $('#$typeNoDots').val(defaultValue);
1636
                $('#$typeNoDots').selectpicker('render');
1637
                if (defaultValue != '') {
1638
                    var selected = $('#$typeNoDots option:selected').val();                    
1639
                    $.ajax({ 
1640
                        url: '$url' + '&id=' + selected+ '&template_name=$type',
1641
                        success: function (data) {
1642
                            $('#$templateNoDots').html(data);
1643
                            $('#$templateNoDotsBlock').show();
1644
                            return;
1645
                        }, 
1646
                    });
1647
                }
1648
                                
1649
                $('#$typeNoDots').on('change', function(){                    
1650
                    var selected = $('#$typeNoDots option:selected').val();                    
1651
                    $.ajax({ 
1652
                        url: '$url' + '&id=' + selected,
1653
                        success: function (data) {
1654
                            $('#$templateNoDots').html(data);
1655
                            $('#$templateNoDotsBlock').show();
1656
                            return;
1657
                        }, 
1658
                    });
1659
                });
1660
            });
1661
            </script>");
1662
        }
1663
    }
1664
1665
    /**
1666
     * @param string $url           page that will handle the upload
1667
     * @param string $inputName
1668
     * @param string $urlToRedirect
1669
     */
1670
    private function addMultipleUploadJavascript($url, $inputName, $urlToRedirect = '')
1671
    {
1672
        $redirectCondition = '';
1673
        if (!empty($urlToRedirect)) {
1674
            $redirectCondition = "window.location.replace('$urlToRedirect'); ";
1675
        }
1676
        $icon = Display::return_icon('file_txt.gif');
1677
        $this->addHtml("
1678
        <script>
1679
        $(function () {
1680
            'use strict';
1681
            $('#".$this->getAttribute('id')."').submit(function() {
1682
                return false;
1683
            });
1684
1685
            $('#dropzone').on('click', function() {
1686
                $('#".$inputName."').click();
1687
            });
1688
1689
            var url = '".$url."';
1690
            var uploadButton = $('<button/>')
1691
                .addClass('btn btn-primary')
1692
                .prop('disabled', true)
1693
                .text('".addslashes(get_lang('Loading'))."')
1694
                .on('click', function () {
1695
                    var \$this = $(this),
1696
                    data = \$this.data();
1697
                    \$this
1698
                        .off('click')
1699
                        .text('".addslashes(get_lang('Cancel'))."')
1700
                        .on('click', function () {
1701
                            \$this.remove();
1702
                            data.abort();
1703
                        });
1704
                    data.submit().always(function () {
1705
                        \$this.remove();
1706
                    });
1707
                });               
1708
                
1709
            $('#".$inputName."').fileupload({
1710
                url: url,
1711
                dataType: 'json',
1712
                // Enable image resizing, except for Android and Opera,
1713
                // which actually support image resizing, but fail to
1714
                // send Blob objects via XHR requests:
1715
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1716
                previewMaxWidth: 300,
1717
                previewMaxHeight: 169,
1718
                previewCrop: true,
1719
                dropzone: $('#dropzone'),                                
1720
            }).on('fileuploadadd', function (e, data) {                
1721
                data.context = $('<div class=\"row\" />').appendTo('#files');
1722
                $.each(data.files, function (index, file) {
1723
                    var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);                    
1724
                    node.appendTo(data.context);
1725
                });
1726
            }).on('fileuploadprocessalways', function (e, data) {
1727
                var index = data.index,
1728
                    file = data.files[index],
1729
                    node = $(data.context.children()[index]);
1730
                if (file.preview) {
1731
                    data.context.prepend($('<div class=\"col-sm-4\">').html(file.preview));
1732
                } else {
1733
                    data.context.prepend($('<div class=\"col-sm-4\">').html('".$icon."'));
1734
                }
1735
                if (index + 1 === data.files.length) {
1736
                    data.context.find('button')
1737
                        .text('Upload')
1738
                        .prop('disabled', !!data.files.error);
1739
                }
1740
            }).on('fileuploadprogressall', function (e, data) {
1741
                var progress = parseInt(data.loaded / data.total * 100, 10);
1742
                $('#progress .progress-bar').css(
1743
                    'width',
1744
                    progress + '%'
1745
                );
1746
            }).on('fileuploaddone', function (e, data) {
1747
                $.each(data.result.files, function (index, file) {
1748
                    if (file.error) {
1749
                        var link = $('<div>')
1750
                            .attr({class : 'panel-image'})                            ;
1751
                        $(data.context.children()[index]).parent().wrap(link);
1752
                        // Update file name with new one from Chamilo
1753
                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1754
                        var message = $('<div class=\"col-sm-3\">').html(
1755
                            $('<span class=\"message-image-danger\"/>').text(file.error)
1756
                        );
1757
                        $(data.context.children()[index]).parent().append(message);
1758
1759
                        return;
1760
                    }
1761
                    if (file.url) {
1762
                        var link = $('<a>')
1763
                            .attr({target: '_blank', class : 'panel-image'})
1764
                            .prop('href', file.url);
1765
                        $(data.context.children()[index]).parent().wrap(link);
1766
                    }
1767
                    // Update file name with new one from Chamilo
1768
                    $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1769
                    var message = $('<div class=\"col-sm-3\">').html(
1770
                        $('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('UplUploadSucceeded'))."')
1771
                    );
1772
                    $(data.context.children()[index]).parent().append(message);
1773
                });                
1774
                $('#dropzone').removeClass('hover');                
1775
                ".$redirectCondition."
1776
            }).on('fileuploadfail', function (e, data) {
1777
                $.each(data.files, function (index) {
1778
                    var failedMessage = '".addslashes(get_lang('UplUploadFailed'))."';
1779
                    var error = $('<div class=\"col-sm-3\">').html(
1780
                        $('<span class=\"alert alert-danger\"/>').text(failedMessage)
1781
                    );
1782
                    $(data.context.children()[index]).parent().append(error);
1783
                });
1784
                $('#dropzone').removeClass('hover');
1785
            }).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');           
1786
            
1787
            $('#dropzone').on('dragover', function (e) {
1788
                // dragleave callback implementation                
1789
                $('#dropzone').addClass('hover');
1790
            });
1791
            
1792
            $('#dropzone').on('dragleave', function (e) {                
1793
                $('#dropzone').removeClass('hover');
1794
            });
1795
            $('.fileinput-button').hide();
1796
        });
1797
        </script>");
1798
    }
1799
}
1800
1801
/**
1802
 * Cleans HTML text filter.
1803
 *
1804
 * @param string $html HTML to clean
1805
 * @param int    $mode (optional)
1806
 *
1807
 * @return string The cleaned HTML
1808
 */
1809
function html_filter($html, $mode = NO_HTML)
1810
{
1811
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1812
    $cleaned_html = kses($html, $allowed_tags);
0 ignored issues
show
Bug introduced by
The function kses was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

1812
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1813
1814
    return $cleaned_html;
1815
}
1816
1817
function html_filter_teacher($html)
1818
{
1819
    return html_filter($html, TEACHER_HTML);
1820
}
1821
1822
function html_filter_student($html)
1823
{
1824
    return html_filter($html, STUDENT_HTML);
1825
}
1826
1827
function html_filter_teacher_fullpage($html)
1828
{
1829
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1830
}
1831
1832
function html_filter_student_fullpage($html)
1833
{
1834
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1835
}
1836
1837
/**
1838
 * Cleans mobile phone number text.
1839
 *
1840
 * @param string $mobilePhoneNumber Mobile phone number to clean
1841
 *
1842
 * @return string The cleaned mobile phone number
1843
 */
1844
function mobile_phone_number_filter($mobilePhoneNumber)
1845
{
1846
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1847
1848
    return ltrim($mobilePhoneNumber, '0');
1849
}
1850