Passed
Push — master ( 2c1297...2ffb1a )
by Julito
10:51
created

FormValidator::addButtonCreate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 4
dl 0
loc 11
rs 9.9666
c 0
b 0
f 0
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