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

1902
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1903
1904
    return $cleaned_html;
1905
}
1906
1907
function html_filter_teacher($html)
1908
{
1909
    return html_filter($html, TEACHER_HTML);
1910
}
1911
1912
function html_filter_student($html)
1913
{
1914
    return html_filter($html, STUDENT_HTML);
1915
}
1916
1917
function html_filter_teacher_fullpage($html)
1918
{
1919
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1920
}
1921
1922
function html_filter_student_fullpage($html)
1923
{
1924
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1925
}
1926
1927
/**
1928
 * Cleans mobile phone number text.
1929
 *
1930
 * @param string $mobilePhoneNumber Mobile phone number to clean
1931
 *
1932
 * @return string The cleaned mobile phone number
1933
 */
1934
function mobile_phone_number_filter($mobilePhoneNumber)
1935
{
1936
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1937
1938
    return ltrim($mobilePhoneNumber, '0');
1939
}
1940