Passed
Push — master ( b00a91...fa75cc )
by Julito
09:42
created

FormValidator::addButton()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 19
nc 2
nop 8
dl 0
loc 32
rs 9.6333
c 0
b 0
f 0

How to fix   Many Parameters   

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

1889
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1890
1891
    return $cleaned_html;
1892
}
1893
1894
function html_filter_teacher($html)
1895
{
1896
    return html_filter($html, TEACHER_HTML);
1897
}
1898
1899
function html_filter_student($html)
1900
{
1901
    return html_filter($html, STUDENT_HTML);
1902
}
1903
1904
function html_filter_teacher_fullpage($html)
1905
{
1906
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1907
}
1908
1909
function html_filter_student_fullpage($html)
1910
{
1911
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1912
}
1913
1914
/**
1915
 * Cleans mobile phone number text.
1916
 *
1917
 * @param string $mobilePhoneNumber Mobile phone number to clean
1918
 *
1919
 * @return string The cleaned mobile phone number
1920
 */
1921
function mobile_phone_number_filter($mobilePhoneNumber)
1922
{
1923
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1924
1925
    return ltrim($mobilePhoneNumber, '0');
1926
}
1927