Passed
Push — master ( 190bd7...86c511 )
by Julito
09:39
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
/* 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
15
    public $with_progress_bar = false;
16
    private $layout;
17
18
    /**
19
     * Constructor.
20
     *
21
     * @param string $name        Name of the form
22
     * @param string $method      (optional) Method ('post' (default) or 'get')
23
     * @param string $action      (optional) Action (default is $PHP_SELF)
24
     * @param string $target      (optional) Form's target defaults to '_self'
25
     * @param mixed  $attributes  (optional) Extra attributes for <form> tag
26
     * @param string $layout
27
     * @param bool   $trackSubmit (optional) Whether to track if the form was
28
     *                            submitted by adding a special hidden field (default = true)
29
     */
30
    public function __construct(
31
        $name,
32
        $method = 'post',
33
        $action = '',
34
        $target = '',
35
        $attributes = [],
36
        $layout = self::LAYOUT_HORIZONTAL,
37
        $trackSubmit = true
38
    ) {
39
        // Default form class.
40
        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...
41
            $attributes['class'] = 'form-horizontal';
42
        }
43
44
        if (isset($attributes['class']) && strpos($attributes['class'], 'form-search') !== false) {
45
            $layout = 'inline';
46
        }
47
48
        $this->setLayout($layout);
49
50
        switch ($layout) {
51
            case self::LAYOUT_HORIZONTAL:
52
                $attributes['class'] = 'form-horizontal';
53
                break;
54
            case self::LAYOUT_INLINE:
55
            case self::LAYOUT_BOX:
56
                $attributes['class'] = 'form-inline';
57
                break;
58
        }
59
60
        parent::__construct($name, $method, $action, $target, $attributes, $trackSubmit);
61
62
        // Modify the default templates
63
        $renderer = &$this->defaultRenderer();
64
65
        // Form template
66
        $formTemplate = $this->getFormTemplate();
67
        $renderer->setFormTemplate($formTemplate);
68
69
        // Element template
70
        if (isset($attributes['class']) && $attributes['class'] == 'form-inline') {
71
            $elementTemplate = ' {label}  {element} ';
72
            $renderer->setElementTemplate($elementTemplate);
73
        } elseif (isset($attributes['class']) && $attributes['class'] == 'form-search') {
74
            $elementTemplate = ' {label}  {element} ';
75
            $renderer->setElementTemplate($elementTemplate);
76
        } else {
77
            $renderer->setElementTemplate($this->getDefaultElementTemplate());
78
79
            // Display a gray div in the buttons
80
            $templateSimple = '<div class="form-actions">{label} {element}</div>';
81
            $renderer->setElementTemplate($templateSimple, 'submit_in_actions');
82
83
            //Display a gray div in the buttons + makes the button available when scrolling
84
            $templateBottom = '<div class="form-actions bottom_actions bg-form">{label} {element}</div>';
85
            $renderer->setElementTemplate($templateBottom, 'submit_fixed_in_bottom');
86
87
            //When you want to group buttons use something like this
88
            /* $group = array();
89
              $group[] = $form->createElement('button', 'mark_all', get_lang('MarkAll'));
90
              $group[] = $form->createElement('button', 'unmark_all', get_lang('UnmarkAll'));
91
              $form->addGroup($group, 'buttons_in_action');
92
             */
93
            $renderer->setElementTemplate($templateSimple, 'buttons_in_action');
94
95
            $templateSimpleRight = '<div class="form-actions"> <div class="pull-right">{label} {element}</div></div>';
96
            $renderer->setElementTemplate($templateSimpleRight, 'buttons_in_action_right');
97
        }
98
99
        //Set Header template
100
        $renderer->setHeaderTemplate('<legend>{header}</legend>');
101
102
        //Set required field template
103
        $this->setRequiredNote(
104
            '<span class="form_required">*</span> <small>'.get_lang('ThisFieldIsRequired').'</small>'
105
        );
106
107
        $noteTemplate = <<<EOT
108
	<div class="form-group">
109
		<div class="col-sm-offset-2 col-sm-10">{requiredNote}</div>
110
	</div>
111
EOT;
112
        $renderer->setRequiredNoteTemplate($noteTemplate);
113
    }
114
115
    /**
116
     * @return string
117
     */
118
    public function getFormTemplate()
119
    {
120
        return '<form{attributes}>
121
        <fieldset>
122
            {content}
123
        </fieldset>
124
        {hidden}
125
        </form>';
126
    }
127
128
    /**
129
     * @todo this function should be added in the element class
130
     *
131
     * @return string
132
     */
133
    public function getDefaultElementTemplate()
134
    {
135
        return '
136
            <div class="form-group row {error_class}">
137
                <label {label-for} class="col-sm-2 col-form-label {extra_label_class}" >
138
                    <!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
139
                    {label}
140
                </label>
141
                <div class="col-sm-8">
142
                    {icon}
143
                    {element}
144
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 $label
276
     * @param array  $attributes
277
     *
278
     * @return mixed
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 $label
288
     * @param array  $attributes
289
     *
290
     * @return HTML_QuickForm_element
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 $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
     *
380
     * @return HTML_QuickForm_button
381
     */
382
    public function addButtonSave($label, $name = 'submit', $createElement = false)
383
    {
384
        return $this->addButton(
385
            $name,
386
            $label,
387
            'check',
388
            'primary',
389
            null,
390
            null,
391
            [],
392
            $createElement
393
        );
394
    }
395
396
    /**
397
     * Returns a cancel button.
398
     *
399
     * @param string $label         Text appearing on the button
400
     * @param string $name          Element name (for form treatment purposes)
401
     * @param bool   $createElement Whether to use the create or add method
402
     *
403
     * @return HTML_QuickForm_button
404
     */
405
    public function addButtonCancel($label, $name = 'submit', $createElement = false)
406
    {
407
        return $this->addButton(
408
            $name,
409
            $label,
410
            'times',
411
            'danger',
412
            null,
413
            null,
414
            [],
415
            $createElement
416
        );
417
    }
418
419
    /**
420
     * Returns a button with the primary color and a "plus" icon.
421
     *
422
     * @param string $label         Text appearing on the button
423
     * @param string $name          Element name (for form treatment purposes)
424
     * @param bool   $createElement Whether to use the create or add method
425
     * @param array  $attributes    Additional attributes
426
     *
427
     * @return HTML_QuickForm_button
428
     */
429
    public function addButtonCreate($label, $name = 'submit', $createElement = false, $attributes = [])
430
    {
431
        return $this->addButton(
432
            $name,
433
            $label,
434
            'plus',
435
            'primary',
436
            null,
437
            null,
438
            $attributes,
439
            $createElement
440
        );
441
    }
442
443
    /**
444
     * Returns a button with the primary color and a pencil icon.
445
     *
446
     * @param string $label         Text appearing on the button
447
     * @param string $name          Element name (for form treatment purposes)
448
     * @param bool   $createElement Whether to use the create or add method
449
     *
450
     * @return HTML_QuickForm_button
451
     */
452
    public function addButtonUpdate($label, $name = 'submit', $createElement = false)
453
    {
454
        return $this->addButton(
455
            $name,
456
            $label,
457
            'pencil',
458
            'primary',
459
            null,
460
            null,
461
            [],
462
            $createElement
463
        );
464
    }
465
466
    /**
467
     * Returns a button with the danger color and a trash icon.
468
     *
469
     * @param string $label         Text appearing on the button
470
     * @param string $name          Element name (for form treatment purposes)
471
     * @param bool   $createElement Whether to use the create or add method
472
     *
473
     * @return HTML_QuickForm_button
474
     */
475
    public function addButtonDelete($label, $name = 'submit', $createElement = false)
476
    {
477
        return $this->addButton(
478
            $name,
479
            $label,
480
            'trash',
481
            'danger',
482
            null,
483
            null,
484
            [],
485
            $createElement
486
        );
487
    }
488
489
    /**
490
     * Returns a move style button.
491
     *
492
     * @param string $label         Text appearing on the button
493
     * @param string $name          Element name (for form treatment purposes)
494
     * @param bool   $createElement Whether to use the create or add method
495
     *
496
     * @return HTML_QuickForm_button
497
     */
498
    public function addButtonMove($label, $name = 'submit', $createElement = false)
499
    {
500
        return $this->addButton(
501
            $name,
502
            $label,
503
            'arrow-circle-right',
504
            'primary',
505
            null,
506
            null,
507
            [],
508
            $createElement
509
        );
510
    }
511
512
    /**
513
     * Returns a button with the primary color and a paper-plane icon.
514
     *
515
     * @param string $label         Text appearing on the button
516
     * @param string $name          Element name (for form treatment purposes)
517
     * @param bool   $createElement Whether to use the create or add method
518
     * @param array  $attributes
519
     *
520
     * @return HTML_QuickForm_button
521
     */
522
    public function addButtonSend($label, $name = 'submit', $createElement = false, $attributes = [])
523
    {
524
        return $this->addButton(
525
            $name,
526
            $label,
527
            'paper-plane',
528
            'primary',
529
            null,
530
            null,
531
            $attributes,
532
            $createElement
533
        );
534
    }
535
536
    /**
537
     * Returns a button with the default (grey?) color and a magnifier icon.
538
     *
539
     * @param string $label Text appearing on the button
540
     * @param string $name  Element name (for form treatment purposes)
541
     *
542
     * @return HTML_QuickForm_button
543
     */
544
    public function addButtonSearch($label = null, $name = 'submit')
545
    {
546
        if (empty($label)) {
547
            $label = get_lang('Search');
548
        }
549
550
        return $this->addButton($name, $label, 'search', 'default');
551
    }
552
553
    /**
554
     * Returns a button with the primary color and a right-pointing arrow icon.
555
     *
556
     * @param string $label      Text appearing on the button
557
     * @param string $name       Element name (for form treatment purposes)
558
     * @param array  $attributes Additional attributes
559
     *
560
     * @return HTML_QuickForm_button
561
     */
562
    public function addButtonNext($label, $name = 'submit', $attributes = [])
563
    {
564
        return $this->addButton(
565
            $name,
566
            $label,
567
            'arrow-right',
568
            'primary',
569
            null,
570
            null,
571
            $attributes
572
        );
573
    }
574
575
    /**
576
     * Returns a button with the primary color and a check mark icon.
577
     *
578
     * @param string $label         Text appearing on the button
579
     * @param string $name          Element name (for form treatment purposes)
580
     * @param bool   $createElement Whether to use the create or add method
581
     *
582
     * @return HTML_QuickForm_button
583
     */
584
    public function addButtonImport($label, $name = 'submit', $createElement = false)
585
    {
586
        return $this->addButton(
587
            $name,
588
            $label,
589
            'check',
590
            'primary',
591
            null,
592
            null,
593
            [],
594
            $createElement
595
        );
596
    }
597
598
    /**
599
     * Returns a button with the primary color and a check-mark icon.
600
     *
601
     * @param string $label         Text appearing on the button
602
     * @param string $name          Element name (for form treatment purposes)
603
     * @param bool   $createElement Whether to use the create or add method
604
     *
605
     * @return HTML_QuickForm_button
606
     */
607
    public function addButtonExport($label, $name = 'submit', $createElement = false)
608
    {
609
        return $this->addButton(
610
            $name,
611
            $label,
612
            'check',
613
            'primary',
614
            null,
615
            null,
616
            [],
617
            $createElement
618
        );
619
    }
620
621
    /**
622
     * Shortcut to filter button.
623
     *
624
     * @param string $label         Text appearing on the button
625
     * @param string $name          Element name (for form treatment purposes)
626
     * @param bool   $createElement Whether to use the create or add method
627
     *
628
     * @return HTML_QuickForm_button
629
     */
630
    public function addButtonFilter($label, $name = 'submit', $createElement = false)
631
    {
632
        return $this->addButton(
633
            $name,
634
            $label,
635
            'filter',
636
            'primary',
637
            null,
638
            null,
639
            [],
640
            $createElement
641
        );
642
    }
643
644
    /**
645
     * Shortcut to reset button.
646
     *
647
     * @param string $label         Text appearing on the button
648
     * @param string $name          Element name (for form treatment purposes)
649
     * @param bool   $createElement Whether to use the create or add method
650
     *
651
     * @return HTML_QuickForm_button
652
     */
653
    public function addButtonReset($label, $name = 'reset', $createElement = false)
654
    {
655
        $icon = 'eraser';
656
        $style = 'default';
657
        $size = 'default';
658
        $class = null;
659
        $attributes = [];
660
661
        if ($createElement) {
662
            return $this->createElement(
663
                'reset',
664
                $name,
665
                $label,
666
                $icon,
667
                $style,
668
                $size,
669
                $class,
670
                $attributes
671
            );
672
        }
673
674
        return $this->addElement(
675
            'reset',
676
            $name,
677
            $label,
678
            $icon,
679
            $style,
680
            $size,
681
            $class,
682
            $attributes
683
        );
684
    }
685
686
    /**
687
     * Returns a button with the primary color and an upload icon.
688
     *
689
     * @param string $label         Text appearing on the button
690
     * @param string $name          Element name (for form treatment purposes)
691
     * @param bool   $createElement Whether to use the create or add method
692
     *
693
     * @return HTML_QuickForm_button
694
     */
695
    public function addButtonUpload($label, $name = 'submit', $createElement = false)
696
    {
697
        return $this->addButton(
698
            $name,
699
            $label,
700
            'upload',
701
            'primary',
702
            null,
703
            null,
704
            [],
705
            $createElement
706
        );
707
    }
708
709
    /**
710
     * Returns a button with the primary color and a download icon.
711
     *
712
     * @param string $label         Text appearing on the button
713
     * @param string $name          Element name (for form treatment purposes)
714
     * @param bool   $createElement Whether to use the create or add method
715
     *
716
     * @return HTML_QuickForm_button
717
     */
718
    public function addButtonDownload($label, $name = 'submit', $createElement = false)
719
    {
720
        return $this->addButton(
721
            $name,
722
            $label,
723
            'download',
724
            'primary',
725
            null,
726
            null,
727
            [],
728
            $createElement
729
        );
730
    }
731
732
    /**
733
     * Returns a button with the primary color and a magnifier icon.
734
     *
735
     * @param string $label         Text appearing on the button
736
     * @param string $name          Element name (for form treatment purposes)
737
     * @param bool   $createElement Whether to use the create or add method
738
     *
739
     * @return HTML_QuickForm_button
740
     */
741
    public function addButtonPreview($label, $name = 'submit', $createElement = false)
742
    {
743
        return $this->addButton(
744
            $name,
745
            $label,
746
            'search',
747
            'primary',
748
            null,
749
            null,
750
            [],
751
            $createElement
752
        );
753
    }
754
755
    /**
756
     * Returns a button with the primary color and a copy (double sheet) icon.
757
     *
758
     * @param string $label         Text appearing on the button
759
     * @param string $name          Element name (for form treatment purposes)
760
     * @param bool   $createElement Whether to use the create or add method
761
     *
762
     * @return HTML_QuickForm_button
763
     */
764
    public function addButtonCopy($label, $name = 'submit', $createElement = false)
765
    {
766
        return $this->addButton(
767
            $name,
768
            $label,
769
            'copy',
770
            'primary',
771
            null,
772
            null,
773
            [],
774
            $createElement
775
        );
776
    }
777
778
    /**
779
     * @param string $name
780
     * @param string $label
781
     * @param string $text
782
     * @param array  $attributes
783
     *
784
     * @return HTML_QuickForm_checkbox
785
     */
786
    public function addCheckBox($name, $label, $text = '', $attributes = [])
787
    {
788
        return $this->addElement('checkbox', $name, $label, $text, $attributes);
789
    }
790
791
    /**
792
     * @param string $name
793
     * @param string $label
794
     * @param array  $options
795
     * @param array  $attributes
796
     *
797
     * @return HTML_QuickForm_group
798
     */
799
    public function addCheckBoxGroup($name, $label, $options = [], $attributes = [])
800
    {
801
        $group = [];
802
        foreach ($options as $value => $text) {
803
            $attributes['value'] = $value;
804
            $group[] = $this->createElement(
805
                'checkbox',
806
                $value,
807
                null,
808
                $text,
809
                $attributes
810
            );
811
        }
812
813
        return $this->addGroup($group, $name, $label);
814
    }
815
816
    /**
817
     * @param string $name
818
     * @param string $label
819
     * @param array  $options
820
     * @param array  $attributes
821
     *
822
     * @return HTML_QuickForm_group
823
     */
824
    public function addRadio($name, $label, $options = [], $attributes = [])
825
    {
826
        $group = [];
827
        foreach ($options as $key => $value) {
828
            $group[] = $this->createElement('radio', null, null, $value, $key, $attributes);
829
        }
830
831
        return $this->addGroup($group, $name, $label);
832
    }
833
834
    /**
835
     * @param string $name
836
     * @param string $label
837
     * @param array  $options
838
     * @param array  $attributes
839
     *
840
     * @return HTML_QuickForm_select
841
     */
842
    public function addSelect($name, $label, $options = [], $attributes = [])
843
    {
844
        return $this->addElement('select', $name, $label, $options, $attributes);
845
    }
846
847
    /**
848
     * @param $name
849
     * @param $label
850
     * @param $collection
851
     * @param array  $attributes
852
     * @param bool   $addNoneOption
853
     * @param string $textCallable  set a function getStringValue() by default __toString()
854
     *
855
     * @return HTML_QuickForm_element
856
     */
857
    public function addSelectFromCollection(
858
        $name,
859
        $label,
860
        $collection,
861
        $attributes = [],
862
        $addNoneOption = false,
863
        $textCallable = ''
864
    ) {
865
        $options = [];
866
867
        if ($addNoneOption) {
868
            $options[0] = get_lang('None');
869
        }
870
871
        if (!empty($collection)) {
872
            foreach ($collection as $item) {
873
                $text = $item;
874
                if (!empty($textCallable)) {
875
                    $text = $item->$textCallable();
876
                }
877
                $options[$item->getId()] = $text;
878
            }
879
        }
880
881
        return $this->addElement('select', $name, $label, $options, $attributes);
882
    }
883
884
    /**
885
     * @param string $label
886
     * @param string $text
887
     * @param bool   $createElement
888
     *
889
     * @return HTML_QuickForm_Element
890
     */
891
    public function addLabel($label, $text, $createElement = false)
892
    {
893
        if ($createElement) {
894
            return $this->createElement(
895
                'label',
896
                $label,
897
                $text
898
            );
899
        }
900
901
        return $this->addElement('label', $label, $text);
902
    }
903
904
    /**
905
     * @param string $text
906
     */
907
    public function addHeader($text)
908
    {
909
        $this->addElement('header', $text);
910
    }
911
912
    /**
913
     * @param string $name
914
     * @param string $label
915
     * @param array  $attributes
916
     *
917
     * @throws Exception            if the file doesn't have an id
918
     * @throws HTML_QuickForm_Error
919
     */
920
    public function addFile($name, $label, $attributes = [])
921
    {
922
        try {
923
            $element = $this->addElement('file', $name, $label, $attributes);
924
            if (isset($attributes['crop_image'])) {
925
                $id = $element->getAttribute('id');
926
                if (empty($id)) {
927
                    throw new Exception('If you use the crop functionality the element must have an id');
928
                }
929
                $this->addHtml(
930
                    '
931
                <div class="form-group row" id="'.$id.'-form-group" style="display: none;">
932
                    <div class="offset-md-2 col-sm-8">
933
                        <div class="card-cropper">
934
                            <div id="'.$id.'_crop_image" class="cropCanvas">
935
                                <img id="'.$id.'_preview_image">
936
                            </div>
937
                            <button class="btn btn-primary" type="button" name="cropButton" id="'.$id.'_crop_button">
938
                                <em class="fa fa-crop"></em> '.get_lang('CropYourPicture').'
939
                            </button>
940
                        </div>
941
                    </div>
942
                </div>'
943
                );
944
                $this->addHidden($id.'_crop_result', '');
945
                $this->addHidden($id.'_crop_image_base_64', '');
946
            }
947
        } catch (HTML_Quick | Form_Error $e) {
948
            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...
949
        }
950
    }
951
952
    /**
953
     * @param string $snippet
954
     */
955
    public function addHtml($snippet)
956
    {
957
        $this->addElement('html', $snippet);
958
    }
959
960
    /**
961
     * Draws a panel of options see the course_info/infocours.php page.
962
     *
963
     * @param string $name      internal name
964
     * @param string $title     visible title
965
     * @param array  $groupList list of group or elements
966
     */
967
    public function addPanelOption($name, $title, $groupList, $icon, $open = false, $parent)
968
    {
969
        $html = '<div class="card">';
970
        $html .= '<div class="card-header" id="card_'.$name.'">';
971
        $html .= '<h5 class="card-title">';
972
        $html .= '<a role="button" class="'.(($open) ? 'collapse' : ' ').'"  data-toggle="collapse" data-target="#collapse_'.$name.'" aria-expanded="true" aria-controls="collapse_'.$name.'">';
973
        if ($icon) {
974
            $html .= Display::return_icon($icon, null, null, ICON_SIZE_SMALL);
975
        }
976
        $html .= $title;
977
        $html .= '</a></h5></div>';
978
        $html .= '<div id="collapse_'.$name.'" class="collapse '.(($open) ? 'show' : ' ').'" aria-labelledby="heading_'.$name.'" data-parent="#'.$parent.'">';
979
        $html .= '<div class="card-body">';
980
981
        $this->addHtml($html);
982
983
        foreach ($groupList as $groupName => $group) {
984
            // Add group array
985
            if (!empty($groupName) && is_array($group)) {
986
                $this->addGroup($group, '', $groupName);
987
            }
988
            // Add element
989
            if ($group instanceof HTML_QuickForm_element) {
990
                $this->addElement($group);
991
            }
992
        }
993
994
        $this->addHtml('</div></div></div>');
995
    }
996
997
    /**
998
     * Adds a HTML-editor to the form.
999
     *
1000
     * @param string $name
1001
     * @param string $label    The label for the form-element
1002
     * @param bool   $required (optional) Is the form-element required (default=true)
1003
     * @param bool   $fullPage (optional) When it is true, the editor loads completed html code for a full page
1004
     * @param array  $config   (optional) Configuration settings for the online editor
1005
     */
1006
    public function addHtmlEditor(
1007
        $name,
1008
        $label,
1009
        $required = true,
1010
        $fullPage = false,
1011
        $config = []
1012
    ) {
1013
        $attributes = [];
1014
        $attributes['rows'] = isset($config['rows']) ? $config['rows'] : 15;
1015
        $attributes['cols'] = isset($config['cols']) ? $config['cols'] : 80;
1016
        $attributes['cols-size'] = isset($config['cols-size']) ? $config['cols-size'] : [];
1017
        $attributes['class'] = isset($config['class']) ? $config['class'] : [];
1018
1019
        $this->addElement('html_editor', $name, $label, $attributes, $config);
1020
        $this->applyFilter($name, 'trim');
1021
        if ($required) {
1022
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1023
        }
1024
1025
        /** @var HtmlEditor $element */
1026
        $element = $this->getElement($name);
1027
        $config['style'] = false;
1028
        if ($fullPage) {
1029
            $config['fullPage'] = true;
1030
            // Adds editor.css in ckEditor
1031
            $config['style'] = true;
1032
        }
1033
1034
        if ($element->editor) {
1035
            $element->editor->processConfig($config);
1036
        }
1037
    }
1038
1039
    /**
1040
     * Adds a Google Maps Geolocalization field to the form.
1041
     *
1042
     * @param $name
1043
     * @param $label
1044
     */
1045
    public function addGeoLocationMapField($name, $label)
1046
    {
1047
        $gMapsPlugin = GoogleMapsPlugin::create();
1048
        $geolocalization = $gMapsPlugin->get('enable_api') === 'true';
1049
1050
        if ($geolocalization) {
1051
            $gmapsApiKey = $gMapsPlugin->get('api_key');
1052
            $url = '//maps.googleapis.com/maps/api/js?key='.$gmapsApiKey;
1053
            $this->addHtml('<script type="text/javascript" src="'.$url.'" ></script>');
1054
        }
1055
        $this->addElement(
1056
            'text',
1057
            $name,
1058
            $label,
1059
            ['id' => $name]
1060
        );
1061
        $this->applyFilter($name, 'stripslashes');
1062
        $this->applyFilter($name, 'trim');
1063
        $this->addHtml('
1064
            <div class="form-group">
1065
                <label for="geolocalization_'.$name.'" class="col-sm-2 control-label"></label>
1066
                <div class="col-sm-8">
1067
                    <button class="null btn btn-default" id="geolocalization_'.$name.'" name="geolocalization_'.$name.'" type="submit">
1068
                        <em class="fa fa-map-marker"></em> '.get_lang('Geolocalization').'
1069
                    </button>
1070
                    <button class="null btn btn-default" id="myLocation_'.$name.'" name="myLocation_'.$name.'" type="submit">
1071
                    <em class="fa fa-crosshairs"></em> 
1072
                    '.get_lang('MyLocation').'
1073
                    </button>
1074
                </div>
1075
            </div>
1076
        ');
1077
1078
        $this->addHtml('
1079
            <div class="form-group">
1080
                <label for="map_'.$name.'" class="col-sm-2 control-label">
1081
                    '.$label.' - '.get_lang('Map').'
1082
                </label>
1083
                <div class="col-sm-8">
1084
                    <div name="map_'.$name.'" id="map_'.$name.'" style="width:100%; height:300px;">
1085
                    </div>
1086
                </div>
1087
            </div>
1088
        ');
1089
1090
        $this->addHtml('<script>
1091
            $(function() {
1092
                if (typeof google === "object") {
1093
                    var address = $("#'.$name.'").val();
1094
                    initializeGeo'.$name.'(address, false);
1095
1096
                    $("#geolocalization_'.$name.'").on("click", function() {
1097
                        var address = $("#'.$name.'").val();
1098
                        initializeGeo'.$name.'(address, false);
1099
                        return false;
1100
                    });
1101
1102
                    $("#myLocation_'.$name.'").on("click", function() {
1103
                        myLocation'.$name.'();
1104
                        return false;
1105
                    });
1106
1107
                    $("#'.$name.'").keypress(function (event) {
1108
                        if (event.which == 13) {
1109
                            $("#geolocalization_'.$name.'").click();
1110
                            return false;
1111
                        }
1112
                    });
1113
                } else {
1114
                    $("#map_'.$name.'").html("<div class=\"alert alert-info\">'.get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap').'</div>");
1115
                }
1116
            });
1117
1118
            function myLocation'.$name.'() {
1119
                if (navigator.geolocation) {
1120
                    var geoPosition = function(position) {
1121
                        var lat = position.coords.latitude;
1122
                        var lng = position.coords.longitude;
1123
                        var latLng = new google.maps.LatLng(lat, lng);
1124
                        initializeGeo'.$name.'(false, latLng)
1125
                    };
1126
1127
                    var geoError = function(error) {
1128
                        alert("Geocode '.get_lang('Error').': " + error);
1129
                    };
1130
1131
                    var geoOptions = {
1132
                        enableHighAccuracy: true
1133
                    };
1134
                    navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
1135
                }
1136
            }
1137
1138
            function initializeGeo'.$name.'(address, latLng) {
1139
                var geocoder = new google.maps.Geocoder();
1140
                var latlng = new google.maps.LatLng(-34.397, 150.644);
1141
                var myOptions = {
1142
                    zoom: 15,
1143
                    center: latlng,
1144
                    mapTypeControl: true,
1145
                    mapTypeControlOptions: {
1146
                        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
1147
                    },
1148
                    navigationControl: true,
1149
                    mapTypeId: google.maps.MapTypeId.ROADMAP
1150
                };
1151
1152
                map_'.$name.' = new google.maps.Map(document.getElementById("map_'.$name.'"), myOptions);
1153
                var parameter = address ? { "address": address } : latLng ? { "latLng": latLng } : false;
1154
                if (geocoder && parameter) {
1155
                    geocoder.geocode(parameter, function(results, status) {
1156
                        if (status == google.maps.GeocoderStatus.OK) {
1157
                            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
1158
                                map_'.$name.'.setCenter(results[0].geometry.location);
1159
                                if (!address) {
1160
                                    $("#'.$name.'").val(results[0].formatted_address);
1161
                                }
1162
                                var infowindow = new google.maps.InfoWindow({
1163
                                    content: "<b>" + $("#'.$name.'").val() + "</b>",
1164
                                    size: new google.maps.Size(150, 50)
1165
                                });
1166
1167
                                var marker = new google.maps.Marker({
1168
                                    position: results[0].geometry.location,
1169
                                    map: map_'.$name.',
1170
                                    title: $("#'.$name.'").val()
1171
                                });
1172
                                google.maps.event.addListener(marker, "click", function() {
1173
                                    infowindow.open(map_'.$name.', marker);
1174
                                });
1175
                            } else {
1176
                                alert("'.get_lang("NotFound").'");
1177
                            }
1178
                        } else {
1179
                            alert("Geocode '.get_lang('Error').': '.get_lang("AddressField").' '.get_lang("NotFound").'");
1180
                        }
1181
                    });
1182
                }
1183
            }
1184
        </script>
1185
        ');
1186
    }
1187
1188
    /**
1189
     * @param string $name
1190
     * @param string $label
1191
     *
1192
     * @return mixed
1193
     */
1194
    public function addButtonAdvancedSettings($name, $label = '')
1195
    {
1196
        $label = !empty($label) ? $label : get_lang('AdvancedParameters');
1197
1198
        return $this->addElement('advanced_settings', $name, $label);
1199
    }
1200
1201
    /**
1202
     * Adds a progress loading image to the form.
1203
     */
1204
    public function addProgress($delay = 2, $label = '')
1205
    {
1206
        if (empty($label)) {
1207
            $label = get_lang('PleaseStandBy');
1208
        }
1209
        $this->with_progress_bar = true;
1210
        $id = $this->getAttribute('id');
1211
1212
        $this->updateAttributes("onsubmit=\"javascript: addProgress('".$id."')\"");
1213
        $this->addHtml('<script language="javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/upload.js" type="text/javascript"></script>');
1214
    }
1215
1216
    /**
1217
     * This function has been created for avoiding changes directly within QuickForm class.
1218
     * When we use it, the element is threated as 'required' to be dealt during validation.
1219
     *
1220
     * @param array  $elements The array of elements
1221
     * @param string $message  The message displayed
1222
     */
1223
    public function add_multiple_required_rule($elements, $message)
1224
    {
1225
        $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...
1226
        $this->addRule($elements, $message, 'multiple_required');
1227
    }
1228
1229
    /**
1230
     * Displays the form.
1231
     * If an element in the form didn't validate, an error message is showed
1232
     * asking the user to complete the form.
1233
     */
1234
    public function display()
1235
    {
1236
        echo $this->returnForm();
1237
    }
1238
1239
    /**
1240
     * Returns the HTML code of the form.
1241
     *
1242
     * @return string $return_value HTML code of the form
1243
     */
1244
    public function returnForm()
1245
    {
1246
        $returnValue = '';
1247
1248
        /** @var HTML_QuickForm_element $element */
1249
        foreach ($this->_elements as $element) {
1250
            $elementError = parent::getElementError($element->getName());
1251
            if (!is_null($elementError)) {
1252
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1253
                break;
1254
            }
1255
        }
1256
1257
        $returnValue .= parent::toHtml();
1258
        // Add div-element which is to hold the progress bar
1259
        $id = $this->getAttribute('id');
1260
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1261
            // Deprecated
1262
            // $icon = Display::return_icon('progress_bar.gif');
1263
1264
            // @todo improve UI
1265
            $returnValue .= '<br />
1266
1267
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1268
                <div class="wobblebar-loader"></div>
1269
            </div>
1270
            ';
1271
        }
1272
1273
        return $returnValue;
1274
    }
1275
1276
    /**
1277
     * Returns the HTML code of the form.
1278
     * If an element in the form didn't validate, an error message is showed
1279
     * asking the user to complete the form.
1280
     *
1281
     * @return string $return_value HTML code of the form
1282
     *
1283
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1284
     * @author Julio Montoya
1285
     *
1286
     * @deprecated use returnForm()
1287
     */
1288
    public function return_form()
1289
    {
1290
        return $this->returnForm();
1291
    }
1292
1293
    /**
1294
     * Create a form validator based on an array of form data:.
1295
     *
1296
     *         array(
1297
     *             'name' => 'zombie_report_parameters',    //optional
1298
     *             'method' => 'GET',                       //optional
1299
     *             'items' => array(
1300
     *                 array(
1301
     *                     'name' => 'ceiling',
1302
     *                     'label' => 'Ceiling',            //optional
1303
     *                     'type' => 'date',
1304
     *                     'default' => date()              //optional
1305
     *                 ),
1306
     *                 array(
1307
     *                     'name' => 'active_only',
1308
     *                     'label' => 'ActiveOnly',
1309
     *                     'type' => 'checkbox',
1310
     *                     'default' => true
1311
     *                 ),
1312
     *                 array(
1313
     *                     'name' => 'submit_button',
1314
     *                     'type' => 'style_submit_button',
1315
     *                     'value' => get_lang('Search'),
1316
     *                     'attributes' => array('class' => 'search')
1317
     *                 )
1318
     *             )
1319
     *         );
1320
     *
1321
     * @param array $form_data
1322
     *
1323
     * @deprecated use normal FormValidator construct
1324
     *
1325
     * @return FormValidator
1326
     */
1327
    public static function create($form_data)
1328
    {
1329
        if (empty($form_data)) {
1330
            return null;
1331
        }
1332
        $form_name = isset($form_data['name']) ? $form_data['name'] : 'form';
1333
        $form_method = isset($form_data['method']) ? $form_data['method'] : 'POST';
1334
        $form_action = isset($form_data['action']) ? $form_data['action'] : '';
1335
        $form_target = isset($form_data['target']) ? $form_data['target'] : '';
1336
        $form_attributes = isset($form_data['attributes']) ? $form_data['attributes'] : null;
1337
        $form_track_submit = isset($form_data['track_submit']) ? $form_data['track_submit'] : true;
1338
        $reset = null;
1339
        $result = new FormValidator($form_name, $form_method, $form_action, $form_target, $form_attributes, $form_track_submit);
0 ignored issues
show
Bug introduced by
It seems like $form_track_submit can also be of type true; however, parameter $layout of FormValidator::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

1339
        $result = new FormValidator($form_name, $form_method, $form_action, $form_target, $form_attributes, /** @scrutinizer ignore-type */ $form_track_submit);
Loading history...
1340
1341
        $defaults = [];
1342
        foreach ($form_data['items'] as $item) {
1343
            $name = $item['name'];
1344
            $type = isset($item['type']) ? $item['type'] : 'text';
1345
            $label = isset($item['label']) ? $item['label'] : '';
1346
            if ($type == 'wysiwyg') {
1347
                $element = $result->addHtmlEditor($name, $label);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $element is correct as $result->addHtmlEditor($name, $label) targeting FormValidator::addHtmlEditor() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1348
            } else {
1349
                $element = $result->addElement($type, $name, $label);
1350
            }
1351
            if (isset($item['attributes'])) {
1352
                $attributes = $item['attributes'];
1353
                $element->setAttributes($attributes);
1354
            }
1355
            if (isset($item['value'])) {
1356
                $value = $item['value'];
1357
                $element->setValue($value);
1358
            }
1359
            if (isset($item['default'])) {
1360
                $defaults[$name] = $item['default'];
1361
            }
1362
            if (isset($item['rules'])) {
1363
                $rules = $item['rules'];
1364
                foreach ($rules as $rule) {
1365
                    $message = $rule['message'];
1366
                    $type = $rule['type'];
1367
                    $format = isset($rule['format']) ? $rule['format'] : null;
1368
                    $validation = isset($rule['validation']) ? $rule['validation'] : 'server';
1369
                    $force = isset($rule['force']) ? $rule['force'] : false;
1370
                    $result->addRule($name, $message, $type, $format, $validation, $reset, $force);
1371
                }
1372
            }
1373
        }
1374
        $result->setDefaults($defaults);
1375
1376
        return $result;
1377
    }
1378
1379
    /**
1380
     * @return HTML_QuickForm_Renderer_Default
1381
     */
1382
    public static function getDefaultRenderer()
1383
    {
1384
        return
1385
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1386
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1387
    }
1388
1389
    /**
1390
     * Adds a input of type url to the form.
1391
     *
1392
     * @param string $name       The label for the form-element
1393
     * @param string $label      The element name
1394
     * @param bool   $required   Optional. Is the form-element required (default=true)
1395
     * @param array  $attributes Optional. List of attributes for the form-element
1396
     */
1397
    public function addUrl($name, $label, $required = true, $attributes = [])
1398
    {
1399
        $this->addElement('url', $name, $label, $attributes);
1400
        $this->applyFilter($name, 'trim');
1401
        $this->addRule($name, get_lang('InsertAValidUrl'), 'url');
1402
1403
        if ($required) {
1404
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1405
        }
1406
    }
1407
1408
    /**
1409
     * Adds a text field for letters to the form.
1410
     * A trim-filter is attached to the field.
1411
     *
1412
     * @param string $name       The element name
1413
     * @param string $label      The label for the form-element
1414
     * @param bool   $required   Optional. Is the form-element required (default=true)
1415
     * @param array  $attributes Optional. List of attributes for the form-element
1416
     */
1417
    public function addTextLettersOnly(
1418
        $name,
1419
        $label,
1420
        $required = false,
1421
        $attributes = []
1422
    ) {
1423
        $attributes = array_merge(
1424
            $attributes,
1425
            [
1426
                'pattern' => '[a-zA-ZñÑ]+',
1427
                'title' => get_lang('OnlyLetters'),
1428
            ]
1429
        );
1430
1431
        $this->addElement(
1432
            'text',
1433
            $name,
1434
            [
1435
                $label,
1436
                get_lang('OnlyLetters'),
1437
            ],
1438
            $attributes
1439
        );
1440
1441
        $this->applyFilter($name, 'trim');
1442
1443
        if ($required) {
1444
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1445
        }
1446
1447
        $this->addRule(
1448
            $name,
1449
            get_lang('OnlyLetters'),
1450
            'regex',
1451
            '/^[a-zA-ZñÑ]+$/'
1452
        );
1453
    }
1454
1455
    /**
1456
     * Adds a text field for alphanumeric characters to the form.
1457
     * A trim-filter is attached to the field.
1458
     *
1459
     * @param string $name       The element name
1460
     * @param string $label      The label for the form-element
1461
     * @param bool   $required   Optional. Is the form-element required (default=true)
1462
     * @param array  $attributes Optional. List of attributes for the form-element
1463
     */
1464
    public function addTextAlphanumeric(
1465
        $name,
1466
        $label,
1467
        $required = false,
1468
        $attributes = []
1469
    ) {
1470
        $attributes = array_merge(
1471
            $attributes,
1472
            [
1473
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1474
                'title' => get_lang('OnlyLettersAndNumbers'),
1475
            ]
1476
        );
1477
1478
        $this->addElement(
1479
            'text',
1480
            $name,
1481
            [
1482
                $label,
1483
                get_lang('OnlyLettersAndNumbers'),
1484
            ],
1485
            $attributes
1486
        );
1487
1488
        $this->applyFilter($name, 'trim');
1489
1490
        if ($required) {
1491
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1492
        }
1493
1494
        $this->addRule(
1495
            $name,
1496
            get_lang('OnlyLettersAndNumbers'),
1497
            'regex',
1498
            '/^[a-zA-Z0-9ÑÑ]+$/'
1499
        );
1500
    }
1501
1502
    /**
1503
     * @param string $name
1504
     * @param $label
1505
     * @param bool  $required
1506
     * @param array $attributes
1507
     * @param bool  $allowNegative
1508
     * @param int   $minValue
1509
     * @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...
1510
     */
1511
    public function addFloat(
1512
        $name,
1513
        $label,
1514
        $required = false,
1515
        $attributes = [],
1516
        $allowNegative = false,
1517
        $minValue = null,
1518
        $maxValue = null
1519
    ) {
1520
        $this->addElement(
1521
            'FloatNumber',
1522
            $name,
1523
            $label,
1524
            $attributes
1525
        );
1526
1527
        $this->applyFilter($name, 'trim');
1528
1529
        if ($required) {
1530
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1531
        }
1532
1533
        // Rule allows "," and "."
1534
        /*$this->addRule(
1535
            $name,
1536
            get_lang('OnlyNumbers'),
1537
            'regex',
1538
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1539
        );*/
1540
1541
        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...
1542
            $this->addRule(
1543
                $name,
1544
                get_lang('NegativeValue'),
1545
                'compare',
1546
                '>=',
1547
                'server',
1548
                false,
1549
                false,
1550
                0
1551
            );
1552
        }
1553
1554
        if (!is_null($minValue)) {
1555
            $this->addRule(
1556
                $name,
1557
                get_lang('UnderMin'),
1558
                'compare',
1559
                '>=',
1560
                'server',
1561
                false,
1562
                false,
1563
                $minValue
1564
            );
1565
        }
1566
1567
        if (!is_null($maxValue)) {
1568
            $this->addRule(
1569
                $name,
1570
                get_lang('OverMax'),
1571
                'compare',
1572
                '<=',
1573
                'server',
1574
                false,
1575
                false,
1576
                $maxValue
1577
            );
1578
        }
1579
    }
1580
1581
    /**
1582
     * Adds a text field for letters and spaces to the form.
1583
     * A trim-filter is attached to the field.
1584
     *
1585
     * @param string $name       The element name
1586
     * @param string $label      The label for the form-element
1587
     * @param bool   $required   Optional. Is the form-element required (default=true)
1588
     * @param array  $attributes Optional. List of attributes for the form-element
1589
     */
1590
    public function addTextLettersAndSpaces(
1591
        $name,
1592
        $label,
1593
        $required = false,
1594
        $attributes = []
1595
    ) {
1596
        $attributes = array_merge(
1597
            $attributes,
1598
            [
1599
                'pattern' => '[a-zA-ZñÑ\s]+',
1600
                'title' => get_lang('OnlyLettersAndSpaces'),
1601
            ]
1602
        );
1603
1604
        $this->addElement(
1605
            'text',
1606
            $name,
1607
            [
1608
                $label,
1609
                get_lang('OnlyLettersAndSpaces'),
1610
            ],
1611
            $attributes
1612
        );
1613
1614
        $this->applyFilter($name, 'trim');
1615
1616
        if ($required) {
1617
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1618
        }
1619
1620
        $this->addRule(
1621
            $name,
1622
            get_lang('OnlyLettersAndSpaces'),
1623
            'regex',
1624
            '/^[a-zA-ZñÑ\s]+$/'
1625
        );
1626
    }
1627
1628
    /**
1629
     * Adds a text field for alphanumeric and spaces characters to the form.
1630
     * A trim-filter is attached to the field.
1631
     *
1632
     * @param string $name       The element name
1633
     * @param string $label      The label for the form-element
1634
     * @param bool   $required   Optional. Is the form-element required (default=true)
1635
     * @param array  $attributes Optional. List of attributes for the form-element
1636
     */
1637
    public function addTextAlphanumericAndSpaces(
1638
        $name,
1639
        $label,
1640
        $required = false,
1641
        $attributes = []
1642
    ) {
1643
        $attributes = array_merge(
1644
            $attributes,
1645
            [
1646
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1647
                'title' => get_lang('OnlyLettersAndNumbersAndSpaces'),
1648
            ]
1649
        );
1650
1651
        $this->addElement(
1652
            'text',
1653
            $name,
1654
            [
1655
                $label,
1656
                get_lang('OnlyLettersAndNumbersAndSpaces'),
1657
            ],
1658
            $attributes
1659
        );
1660
1661
        $this->applyFilter($name, 'trim');
1662
1663
        if ($required) {
1664
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1665
        }
1666
1667
        $this->addRule(
1668
            $name,
1669
            get_lang('OnlyLettersAndNumbersAndSpaces'),
1670
            'regex',
1671
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1672
        );
1673
    }
1674
1675
    /**
1676
     * @param string $url
1677
     * @param string $urlToRedirect after upload redirect to this page
1678
     */
1679
    public function addMultipleUpload($url, $urlToRedirect = '')
1680
    {
1681
        $inputName = 'input_file_upload';
1682
        $this->addMultipleUploadJavascript($url, $inputName, $urlToRedirect);
1683
1684
        $this->addHtml('
1685
            <div class="description-upload">
1686
            '.get_lang('ClickToSelectOrDragAndDropMultipleFilesOnTheUploadField').'
1687
            </div>
1688
            <span class="btn btn-success fileinput-button">
1689
                <i class="glyphicon glyphicon-plus"></i>
1690
                <span>'.get_lang('AddFiles').'</span>
1691
                <!-- The file input field used as target for the file upload widget -->
1692
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1693
            </span>
1694
            <div id="dropzone">
1695
                <div class="button-load">
1696
                '.get_lang('UploadFiles').'
1697
                </div>
1698
            </div>
1699
            <br />
1700
            <!-- The global progress bar -->
1701
            <div id="progress" class="progress">
1702
                <div class="progress-bar progress-bar-success"></div>
1703
            </div>
1704
            <div id="files" class="files"></div>
1705
        ');
1706
    }
1707
1708
    /**
1709
     * @param string $elementName
1710
     * @param string $groupName   if element is inside a group
1711
     *
1712
     * @throws Exception
1713
     */
1714
    public function addPasswordRule($elementName, $groupName = '')
1715
    {
1716
        if (api_get_setting('security.check_password') == 'true') {
1717
            $message = get_lang('PassTooEasy').': '.api_generate_password();
1718
1719
            if (!empty($groupName)) {
1720
                $groupObj = $this->getElement($groupName);
1721
1722
                if ($groupObj instanceof HTML_QuickForm_group) {
1723
                    $elementName = $groupObj->getElementName($elementName);
1724
1725
                    if ($elementName === false) {
1726
                        throw new Exception("The $groupName doesn't have the element $elementName");
1727
                    }
1728
1729
                    $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...
1730
                        'type' => 'callback',
1731
                        'format' => 'api_check_password',
1732
                        'message' => $message,
1733
                        'validation' => '',
1734
                        'reset' => false,
1735
                        'group' => $groupName,
1736
                    ];
1737
                }
1738
            } else {
1739
                $this->addRule(
1740
                    $elementName,
1741
                    $message,
1742
                    'callback',
1743
                    'api_check_password'
1744
                );
1745
            }
1746
        }
1747
    }
1748
1749
    /**
1750
     * Add an element with user ID and avatar to the form.
1751
     * It needs a Chamilo\UserBundle\Entity\User as value. The exported value is the Chamilo\UserBundle\Entity\User ID.
1752
     *
1753
     * @see \UserAvatar
1754
     *
1755
     * @param string $name
1756
     * @param string $label
1757
     * @param string $imageSize Optional. Small, medium or large image
1758
     * @param string $subtitle  Optional. The subtitle for the field
1759
     *
1760
     * @return \UserAvatar
1761
     */
1762
    public function addUserAvatar($name, $label, $imageSize = 'small', $subtitle = '')
1763
    {
1764
        return $this->addElement('UserAvatar', $name, $label, ['image_size' => $imageSize, 'sub_title' => $subtitle]);
1765
    }
1766
1767
    /**
1768
     * @param string $url           page that will handle the upload
1769
     * @param string $inputName
1770
     * @param string $urlToRedirect
1771
     */
1772
    private function addMultipleUploadJavascript($url, $inputName, $urlToRedirect = '')
1773
    {
1774
        $redirectCondition = '';
1775
        if (!empty($urlToRedirect)) {
1776
            $redirectCondition = "window.location.replace('$urlToRedirect'); ";
1777
        }
1778
        $icon = Display::return_icon('file_txt.gif');
1779
        $this->addHtml("
1780
        <script>
1781
        $(function () {
1782
            'use strict';
1783
            $('#".$this->getAttribute('id')."').submit(function() {
1784
                return false;
1785
            });
1786
1787
            $('#dropzone').on('click', function() {
1788
                $('#".$inputName."').click();
1789
            });
1790
1791
            var url = '".$url."';
1792
            var uploadButton = $('<button/>')
1793
                .addClass('btn btn-primary')
1794
                .prop('disabled', true)
1795
                .text('".addslashes(get_lang('Loading'))."')
1796
                .on('click', function () {
1797
                    var \$this = $(this),
1798
                    data = \$this.data();
1799
                    \$this
1800
                        .off('click')
1801
                        .text('".addslashes(get_lang('Cancel'))."')
1802
                        .on('click', function () {
1803
                            \$this.remove();
1804
                            data.abort();
1805
                        });
1806
                    data.submit().always(function () {
1807
                        \$this.remove();
1808
                    });
1809
                });               
1810
                
1811
            $('#".$inputName."').fileupload({
1812
                url: url,
1813
                dataType: 'json',
1814
                // Enable image resizing, except for Android and Opera,
1815
                // which actually support image resizing, but fail to
1816
                // send Blob objects via XHR requests:
1817
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1818
                previewMaxWidth: 50,
1819
                previewMaxHeight: 50,
1820
                previewCrop: true,
1821
                dropzone: $('#dropzone'),                                
1822
            }).on('fileuploadadd', function (e, data) {                
1823
                data.context = $('<div class=\"row\" />').appendTo('#files');
1824
                $.each(data.files, function (index, file) {
1825
                    var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);                    
1826
                    node.appendTo(data.context);
1827
                });
1828
            }).on('fileuploadprocessalways', function (e, data) {
1829
                var index = data.index,
1830
                    file = data.files[index],
1831
                    node = $(data.context.children()[index]);
1832
                if (file.preview) {
1833
                    data.context.prepend($('<div class=\"col-sm-2\">').html(file.preview));
1834
                } else {
1835
                    data.context.prepend($('<div class=\"col-sm-2\">').html('".$icon."'));
1836
                }
1837
                if (index + 1 === data.files.length) {
1838
                    data.context.find('button')
1839
                        .text('Upload')
1840
                        .prop('disabled', !!data.files.error);
1841
                }
1842
            }).on('fileuploadprogressall', function (e, data) {
1843
                var progress = parseInt(data.loaded / data.total * 100, 10);
1844
                $('#progress .progress-bar').css(
1845
                    'width',
1846
                    progress + '%'
1847
                );
1848
            }).on('fileuploaddone', function (e, data) {
1849
                $.each(data.result.files, function (index, file) {
1850
                    if (file.error) {
1851
                        var link = $('<div>')
1852
                            .attr({class : 'panel-image'})                            ;
1853
                        $(data.context.children()[index]).parent().wrap(link);
1854
                        // Update file name with new one from Chamilo
1855
                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1856
                        var message = $('<div class=\"col-sm-3\">').html(
1857
                            $('<span class=\"message-image-danger\"/>').text(file.error)
1858
                        );
1859
                        $(data.context.children()[index]).parent().append(message);
1860
1861
                        return;
1862
                    }
1863
                    if (file.url) {
1864
                        var link = $('<a>')
1865
                            .attr({target: '_blank', class : 'panel-image'})
1866
                            .prop('href', file.url);
1867
                        $(data.context.children()[index]).parent().wrap(link);
1868
                    }
1869
                    // Update file name with new one from Chamilo
1870
                    $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1871
                    var message = $('<div class=\"col-sm-3\">').html(
1872
                        $('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('UplUploadSucceeded'))."')
1873
                    );
1874
                    $(data.context.children()[index]).parent().append(message);
1875
                });                
1876
                $('#dropzone').removeClass('hover');                
1877
                ".$redirectCondition."
1878
            }).on('fileuploadfail', function (e, data) {
1879
                $.each(data.files, function (index) {
1880
                    var failedMessage = '".addslashes(get_lang('UplUploadFailed'))."';
1881
                    var error = $('<div class=\"col-sm-3\">').html(
1882
                        $('<span class=\"alert alert-danger\"/>').text(failedMessage)
1883
                    );
1884
                    $(data.context.children()[index]).parent().append(error);
1885
                });
1886
                $('#dropzone').removeClass('hover');
1887
            }).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');           
1888
            
1889
            $('#dropzone').on('dragover', function (e) {
1890
                // dragleave callback implementation                
1891
                $('#dropzone').addClass('hover');
1892
            });
1893
            
1894
            $('#dropzone').on('dragleave', function (e) {                
1895
                $('#dropzone').removeClass('hover');
1896
            });
1897
            $('.fileinput-button').hide();
1898
        });
1899
        </script>");
1900
    }
1901
}
1902
1903
/**
1904
 * Cleans HTML text filter.
1905
 *
1906
 * @param string $html HTML to clean
1907
 * @param int    $mode (optional)
1908
 *
1909
 * @return string The cleaned HTML
1910
 */
1911
function html_filter($html, $mode = NO_HTML)
1912
{
1913
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1914
    $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

1914
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1915
1916
    return $cleaned_html;
1917
}
1918
1919
function html_filter_teacher($html)
1920
{
1921
    return html_filter($html, TEACHER_HTML);
1922
}
1923
1924
function html_filter_student($html)
1925
{
1926
    return html_filter($html, STUDENT_HTML);
1927
}
1928
1929
function html_filter_teacher_fullpage($html)
1930
{
1931
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1932
}
1933
1934
function html_filter_student_fullpage($html)
1935
{
1936
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1937
}
1938
1939
/**
1940
 * Cleans mobile phone number text.
1941
 *
1942
 * @param string $mobilePhoneNumber Mobile phone number to clean
1943
 *
1944
 * @return string The cleaned mobile phone number
1945
 */
1946
function mobile_phone_number_filter($mobilePhoneNumber)
1947
{
1948
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1949
1950
    return ltrim($mobilePhoneNumber, '0');
1951
}
1952