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

FormValidator::addButtonSave()   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
3
/* For licensing terms, see /license.txt */
4
5
/**
6
 * Class FormValidator
7
 * create/manipulate/validate user input.
8
 */
9
class FormValidator extends HTML_QuickForm
10
{
11
    public const LAYOUT_HORIZONTAL = 'horizontal';
12
    public const LAYOUT_INLINE = 'inline';
13
    public const LAYOUT_BOX = 'box';
14
    public const LAYOUT_BOX_NO_LABEL = 'box-no-label';
15
    public const LAYOUT_BOX_SEARCH = 'box-search';
16
    public const LAYOUT_GRID = 'grid';
17
18
    public $with_progress_bar = false;
19
    private $layout;
20
21
    /**
22
     * Constructor.
23
     *
24
     * @param string $name        Name of the form
25
     * @param string $method      (optional) Method ('post' (default) or 'get')
26
     * @param string $action      (optional) Action (default is $PHP_SELF)
27
     * @param string $target      (optional) Form's target defaults to '_self'
28
     * @param mixed  $attributes  (optional) Extra attributes for <form> tag
29
     * @param string $layout
30
     * @param bool   $trackSubmit (optional) Whether to track if the form was
31
     *                            submitted by adding a special hidden field (default = true)
32
     */
33
    public function __construct(
34
        $name,
35
        $method = 'post',
36
        $action = '',
37
        $target = '',
38
        $attributes = [],
39
        $layout = self::LAYOUT_HORIZONTAL,
40
        $trackSubmit = true
41
    ) {
42
        // Default form class.
43
        if (is_array($attributes) && !isset($attributes['class']) || empty($attributes)) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: (is_array($attributes) &...) || empty($attributes), Probably Intended Meaning: is_array($attributes) &&... || empty($attributes))
Loading history...
44
            $attributes['class'] = 'form-horizontal';
45
        }
46
47
        if (isset($attributes['class']) && false !== strpos($attributes['class'], 'form-search')) {
48
            $layout = 'inline';
49
        }
50
51
        $this->setLayout($layout);
52
53
        // Form template
54
        $formTemplate = $this->getFormTemplate();
55
56
        switch ($layout) {
57
            case self::LAYOUT_HORIZONTAL:
58
                $attributes['class'] = 'form-horizontal';
59
                break;
60
            case self::LAYOUT_INLINE:
61
                $attributes['class'] = 'form-inline';
62
                break;
63
            case self::LAYOUT_BOX:
64
                $attributes['class'] = 'form-inline-box';
65
                break;
66
            case self::LAYOUT_GRID:
67
                $attributes['class'] = 'form-grid';
68
                $formTemplate = $this->getGridFormTemplate();
69
                break;
70
        }
71
72
        parent::__construct($name, $method, $action, $target, $attributes, $trackSubmit);
73
74
        // Modify the default templates
75
        $renderer = &$this->defaultRenderer();
76
77
        $renderer->setFormTemplate($formTemplate);
78
79
        // Element template
80
        if (isset($attributes['class']) && 'form-inline' == $attributes['class']) {
81
            $elementTemplate = ' {label}  {element} ';
82
            $renderer->setElementTemplate($elementTemplate);
83
        } elseif (isset($attributes['class']) && 'form-search' == $attributes['class']) {
84
            $elementTemplate = ' {label}  {element} ';
85
            $renderer->setElementTemplate($elementTemplate);
86
        } else {
87
            $renderer->setElementTemplate($this->getDefaultElementTemplate());
88
89
            // Display a gray div in the buttons
90
            $templateSimple = '<div class="form-actions">{label} {element}</div>';
91
            $renderer->setElementTemplate($templateSimple, 'submit_in_actions');
92
93
            //Display a gray div in the buttons + makes the button available when scrolling
94
            $templateBottom = '<div class="form-actions bottom_actions bg-form">{label} {element}</div>';
95
            $renderer->setElementTemplate($templateBottom, 'submit_fixed_in_bottom');
96
            $renderer->setElementTemplate($templateSimple, 'buttons_in_action');
97
98
            $templateSimpleRight = '<div class="form-actions"> <div class="pull-right">{label} {element}</div></div>';
99
            $renderer->setElementTemplate($templateSimpleRight, 'buttons_in_action_right');
100
        }
101
102
        //Set Header template
103
        $renderer->setHeaderTemplate('<legend>{header}</legend>');
104
105
        //Set required field template
106
        $this->setRequiredNote(
107
            '<span class="form_required">*</span> <small>'.get_lang('Required field').'</small>'
108
        );
109
110
        $noteTemplate = <<<EOT
111
	<div class="form-group">
112
		<div class="col-sm-offset-2 col-sm-10">{requiredNote}</div>
113
	</div>
114
EOT;
115
        $renderer->setRequiredNoteTemplate($noteTemplate);
116
    }
117
118
    /**
119
     * @return string
120
     */
121
    public function getFormTemplate()
122
    {
123
        return '<form{attributes}>
124
        <fieldset>
125
            {content}
126
        </fieldset>
127
        {hidden}
128
        </form>';
129
    }
130
131
    /**
132
     * @return string
133
     */
134
    public function getGridFormTemplate()
135
    {
136
        return '
137
        <style>
138
            .form_list {
139
                display: grid;
140
                grid-template-columns:  repeat(auto-fill, minmax(300px, 1fr));;
141
                grid-gap: 10px 30px;
142
                gap: 10px 30px;
143
            }
144
            .form_list .input-group {
145
                display:block;
146
            }
147
        </style>
148
        <form{attributes}>
149
            <div class="form_list">
150
                {content}
151
            </div>
152
        {hidden}
153
        </form>';
154
    }
155
156
    /**
157
     * @todo this function should be added in the element class
158
     *
159
     * @return string
160
     */
161
    public function getDefaultElementTemplate()
162
    {
163
        return '
164
            <div class="form-group row {error_class}">
165
                <label {label-for} class="col-sm-2 col-form-label {extra_label_class}" >
166
                    <!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
167
                    {label}
168
                </label>
169
                <div class="col-sm-8">
170
                    {icon}
171
                    {element}
172
                    <!-- BEGIN label_2 -->
173
                        <p class="help-block">{label_2}</p>
174
                    <!-- END label_2 -->
175
176
                    <!-- BEGIN error -->
177
                        <span class="help-inline help-block">{error}</span>
178
                    <!-- END error -->
179
                </div>
180
                <div class="col-sm-2">
181
                    <!-- BEGIN label_3 -->
182
                        {label_3}
183
                    <!-- END label_3 -->
184
                </div>
185
            </div>';
186
    }
187
188
    /**
189
     * @return string
190
     */
191
    public function getLayout()
192
    {
193
        return $this->layout;
194
    }
195
196
    /**
197
     * @param string $layout
198
     */
199
    public function setLayout($layout)
200
    {
201
        $this->layout = $layout;
202
    }
203
204
    /**
205
     * Adds a text field to the form.
206
     * A trim-filter is attached to the field.
207
     *
208
     * @param string|array $label      The label for the form-element
209
     * @param string       $name       The element name
210
     * @param bool         $required   (optional)    Is the form-element required (default=true)
211
     * @param array        $attributes (optional)    List of attributes for the form-element
212
     *
213
     * @return HTML_QuickForm_text
214
     */
215
    public function addText($name, $label, $required = true, $attributes = [], $createElement = false)
216
    {
217
        if ($createElement) {
218
            $element = $this->createElement('text', $name, $label, $attributes);
219
        } else {
220
            $element = $this->addElement('text', $name, $label, $attributes);
221
        }
222
223
        $this->applyFilter($name, 'trim');
224
        if ($required) {
225
            $this->addRule($name, get_lang('Required field'), 'required');
226
        }
227
228
        return $element;
229
    }
230
231
    /**
232
     * Add hidden course params.
233
     */
234
    public function addCourseHiddenParams()
235
    {
236
        $this->addHidden('cid', api_get_course_id());
237
        $this->addHidden('sid', api_get_session_id());
238
    }
239
240
    /**
241
     * The "date_range_picker" element creates 2 hidden fields
242
     * "elementName" + "_start"  and "elementName" + "_end"
243
     * For example if the name is "range", you will have 2 new fields
244
     * when executing $form->getSubmitValues()
245
     * "range_start" and "range_end".
246
     *
247
     * @param string $name
248
     * @param string $label
249
     * @param bool   $required
250
     * @param array  $attributes
251
     */
252
    public function addDateRangePicker($name, $label, $required = true, $attributes = [])
253
    {
254
        $this->addElement('date_range_picker', $name, $label, $attributes);
255
        $this->addElement('hidden', $name.'_start');
256
        $this->addElement('hidden', $name.'_end');
257
258
        if ($required) {
259
            $this->addRule($name, get_lang('Required field'), 'required');
260
        }
261
    }
262
263
    /**
264
     * @param string $name
265
     * @param string $label
266
     * @param array  $attributes
267
     *
268
     * @return mixed
269
     */
270
    public function addSelectLanguage($name, $label, $options = [], $attributes = [])
271
    {
272
        return $this->addElement('SelectLanguage', $name, $label, $options, $attributes);
273
    }
274
275
    /**
276
     * @param string $name
277
     * @param string $label
278
     * @param array  $options
279
     * @param array  $attributes
280
     *
281
     * @throws Exception
282
     *
283
     * @return SelectAjax
284
     */
285
    public function addSelectAjax($name, $label, $options = [], $attributes = [])
286
    {
287
        if (!isset($attributes['url'])) {
288
            throw new \Exception('select_ajax needs an URL');
289
        }
290
291
        return $this->addElement(
292
            'select_ajax',
293
            $name,
294
            $label,
295
            $options,
296
            $attributes
297
        );
298
    }
299
300
    /**
301
     * @param string $name
302
     * @param string $label
303
     * @param array  $attributes
304
     *
305
     * @return DatePicker
306
     */
307
    public function addDatePicker($name, $label, $attributes = [])
308
    {
309
        return $this->addElement('DatePicker', $name, $label, $attributes);
310
    }
311
312
    /**
313
     * @param string       $name
314
     * @param string|array $label
315
     * @param array        $attributes
316
     *
317
     * @return DateTimePicker
318
     */
319
    public function addDateTimePicker($name, $label, $attributes = [])
320
    {
321
        return $this->addElement('DateTimePicker', $name, $label, $attributes);
322
    }
323
324
    /**
325
     * @param string       $name
326
     * @param string|array $label
327
     * @param array        $attributes
328
     *
329
     * @return DateTimeRangePicker
330
     */
331
    public function addDateTimeRangePicker($name, $label, $attributes = [])
332
    {
333
        return $this->addElement('DateTimeRangePicker', $name, $label, $attributes);
334
    }
335
336
    /**
337
     * @param string $name
338
     * @param string $value
339
     * @param array  $attributes
340
     */
341
    public function addHidden($name, $value, $attributes = [])
342
    {
343
        $this->addElement('hidden', $name, $value, $attributes);
344
    }
345
346
    /**
347
     * @param string       $name
348
     * @param string|array $label
349
     * @param array        $attributes
350
     * @param bool         $required
351
     *
352
     * @return HTML_QuickForm_textarea
353
     */
354
    public function addTextarea($name, $label, $attributes = [], $required = false)
355
    {
356
        $element = $this->addElement('textarea', $name, $label, $attributes);
357
358
        if ($required) {
359
            $this->addRule($name, get_lang('Required field'), 'required');
360
        }
361
362
        return $element;
363
    }
364
365
    /**
366
     * @param string $name
367
     * @param string $label
368
     * @param string $icon          font-awesome
369
     * @param string $style         default|primary|success|info|warning|danger|link
370
     * @param string $size          large|default|small|extra-small
371
     * @param string $class         Example plus is transformed to icon fa fa-plus
372
     * @param array  $attributes
373
     * @param bool   $createElement
374
     *
375
     * @return HTML_QuickForm_button
376
     */
377
    public function addButton(
378
        $name,
379
        $label,
380
        $icon = 'check',
381
        $style = 'default',
382
        $size = 'default',
383
        $class = null,
384
        $attributes = [],
385
        $createElement = false
386
    ) {
387
        if ($createElement) {
388
            return $this->createElement(
389
                'button',
390
                $name,
391
                $label,
392
                $icon,
393
                $style,
394
                $size,
395
                $class,
396
                $attributes
397
            );
398
        }
399
400
        return $this->addElement(
401
            'button',
402
            $name,
403
            $label,
404
            $icon,
405
            $style,
406
            $size,
407
            $class,
408
            $attributes
409
        );
410
    }
411
412
    /**
413
     * Returns a button with the primary color and a check mark.
414
     *
415
     * @param string $label         Text appearing on the button
416
     * @param string $name          Element name (for form treatment purposes)
417
     * @param bool   $createElement Whether to use the create or add method
418
     * @param array  $attributes
419
     *
420
     * @return HTML_QuickForm_button
421
     */
422
    public function addButtonSave($label, $name = 'submit', $createElement = false, $attributes = [])
423
    {
424
        return $this->addButton(
425
            $name,
426
            $label,
427
            'check',
428
            'primary',
429
            null,
430
            null,
431
            $attributes,
432
            $createElement
433
        );
434
    }
435
436
    /**
437
     * Returns a cancel button.
438
     *
439
     * @param string $label         Text appearing on the button
440
     * @param string $name          Element name (for form treatment purposes)
441
     * @param bool   $createElement Whether to use the create or add method
442
     *
443
     * @return HTML_QuickForm_button
444
     */
445
    public function addButtonCancel($label, $name = 'submit', $createElement = false)
446
    {
447
        return $this->addButton(
448
            $name,
449
            $label,
450
            'times',
451
            'danger',
452
            null,
453
            null,
454
            [],
455
            $createElement
456
        );
457
    }
458
459
    /**
460
     * Returns a button with the primary color and a "plus" icon.
461
     *
462
     * @param string $label         Text appearing on the button
463
     * @param string $name          Element name (for form treatment purposes)
464
     * @param bool   $createElement Whether to use the create or add method
465
     * @param array  $attributes    Additional attributes
466
     *
467
     * @return HTML_QuickForm_button
468
     */
469
    public function addButtonCreate($label, $name = 'submit', $createElement = false, $attributes = [])
470
    {
471
        return $this->addButton(
472
            $name,
473
            $label,
474
            'plus',
475
            'primary',
476
            null,
477
            null,
478
            $attributes,
479
            $createElement
480
        );
481
    }
482
483
    /**
484
     * Returns a button with the primary color and a pencil icon.
485
     *
486
     * @param string $label         Text appearing on the button
487
     * @param string $name          Element name (for form treatment purposes)
488
     * @param bool   $createElement Whether to use the create or add method
489
     *
490
     * @return HTML_QuickForm_button
491
     */
492
    public function addButtonUpdate($label, $name = 'submit', $createElement = false)
493
    {
494
        return $this->addButton(
495
            $name,
496
            $label,
497
            'pencil',
498
            'primary',
499
            null,
500
            null,
501
            [],
502
            $createElement
503
        );
504
    }
505
506
    /**
507
     * Returns a button with the danger color and a trash icon.
508
     *
509
     * @param string $label         Text appearing on the button
510
     * @param string $name          Element name (for form treatment purposes)
511
     * @param bool   $createElement Whether to use the create or add method
512
     *
513
     * @return HTML_QuickForm_button
514
     */
515
    public function addButtonDelete($label, $name = 'submit', $createElement = false)
516
    {
517
        return $this->addButton(
518
            $name,
519
            $label,
520
            'trash',
521
            'danger',
522
            null,
523
            null,
524
            [],
525
            $createElement
526
        );
527
    }
528
529
    /**
530
     * Returns a move style button.
531
     *
532
     * @param string $label         Text appearing on the button
533
     * @param string $name          Element name (for form treatment purposes)
534
     * @param bool   $createElement Whether to use the create or add method
535
     *
536
     * @return HTML_QuickForm_button
537
     */
538
    public function addButtonMove($label, $name = 'submit', $createElement = false)
539
    {
540
        return $this->addButton(
541
            $name,
542
            $label,
543
            'arrow-circle-right',
544
            'primary',
545
            null,
546
            null,
547
            [],
548
            $createElement
549
        );
550
    }
551
552
    /**
553
     * Returns a button with the primary color and a paper-plane icon.
554
     *
555
     * @param string $label         Text appearing on the button
556
     * @param string $name          Element name (for form treatment purposes)
557
     * @param bool   $createElement Whether to use the create or add method
558
     * @param array  $attributes
559
     *
560
     * @return HTML_QuickForm_button
561
     */
562
    public function addButtonSend($label, $name = 'submit', $createElement = false, $attributes = [])
563
    {
564
        return $this->addButton(
565
            $name,
566
            $label,
567
            'paper-plane',
568
            'primary',
569
            null,
570
            null,
571
            $attributes,
572
            $createElement
573
        );
574
    }
575
576
    /**
577
     * Returns a button with the default (grey?) color and a magnifier icon.
578
     *
579
     * @param string $label Text appearing on the button
580
     * @param string $name  Element name (for form treatment purposes)
581
     *
582
     * @return HTML_QuickForm_button
583
     */
584
    public function addButtonSearch($label = null, $name = 'submit')
585
    {
586
        if (empty($label)) {
587
            $label = get_lang('Search');
588
        }
589
590
        return $this->addButton($name, $label, 'search', 'primary');
591
    }
592
593
    /**
594
     * Returns a button with the primary color and a right-pointing arrow icon.
595
     *
596
     * @param string $label      Text appearing on the button
597
     * @param string $name       Element name (for form treatment purposes)
598
     * @param array  $attributes Additional attributes
599
     *
600
     * @return HTML_QuickForm_button
601
     */
602
    public function addButtonNext($label, $name = 'submit', $attributes = [])
603
    {
604
        return $this->addButton(
605
            $name,
606
            $label,
607
            'arrow-right',
608
            'primary',
609
            null,
610
            null,
611
            $attributes
612
        );
613
    }
614
615
    /**
616
     * Returns a button with the primary color and a check mark icon.
617
     *
618
     * @param string $label         Text appearing on the button
619
     * @param string $name          Element name (for form treatment purposes)
620
     * @param bool   $createElement Whether to use the create or add method
621
     *
622
     * @return HTML_QuickForm_button
623
     */
624
    public function addButtonImport($label, $name = 'submit', $createElement = false)
625
    {
626
        return $this->addButton(
627
            $name,
628
            $label,
629
            'check',
630
            'primary',
631
            null,
632
            null,
633
            [],
634
            $createElement
635
        );
636
    }
637
638
    /**
639
     * Returns a button with the primary color and a check-mark icon.
640
     *
641
     * @param string $label         Text appearing on the button
642
     * @param string $name          Element name (for form treatment purposes)
643
     * @param bool   $createElement Whether to use the create or add method
644
     *
645
     * @return HTML_QuickForm_button
646
     */
647
    public function addButtonExport($label, $name = 'submit', $createElement = false)
648
    {
649
        return $this->addButton(
650
            $name,
651
            $label,
652
            'check',
653
            'primary',
654
            null,
655
            null,
656
            [],
657
            $createElement
658
        );
659
    }
660
661
    /**
662
     * Shortcut to filter button.
663
     *
664
     * @param string $label         Text appearing on the button
665
     * @param string $name          Element name (for form treatment purposes)
666
     * @param bool   $createElement Whether to use the create or add method
667
     *
668
     * @return HTML_QuickForm_button
669
     */
670
    public function addButtonFilter($label, $name = 'submit', $createElement = false)
671
    {
672
        return $this->addButton(
673
            $name,
674
            $label,
675
            'filter',
676
            'primary',
677
            null,
678
            null,
679
            [],
680
            $createElement
681
        );
682
    }
683
684
    /**
685
     * Shortcut to reset button.
686
     *
687
     * @param string $label         Text appearing on the button
688
     * @param string $name          Element name (for form treatment purposes)
689
     * @param bool   $createElement Whether to use the create or add method
690
     *
691
     * @return HTML_QuickForm_button
692
     */
693
    public function addButtonReset($label, $name = 'reset', $createElement = false)
694
    {
695
        $icon = 'eraser';
696
        $style = 'default';
697
        $size = 'default';
698
        $class = null;
699
        $attributes = [];
700
701
        if ($createElement) {
702
            return $this->createElement(
703
                'reset',
704
                $name,
705
                $label,
706
                $icon,
707
                $style,
708
                $size,
709
                $class,
710
                $attributes
711
            );
712
        }
713
714
        return $this->addElement(
715
            'reset',
716
            $name,
717
            $label,
718
            $icon,
719
            $style,
720
            $size,
721
            $class,
722
            $attributes
723
        );
724
    }
725
726
    /**
727
     * Returns a button with the primary color and an upload icon.
728
     *
729
     * @param string $label         Text appearing on the button
730
     * @param string $name          Element name (for form treatment purposes)
731
     * @param bool   $createElement Whether to use the create or add method
732
     *
733
     * @return HTML_QuickForm_button
734
     */
735
    public function addButtonUpload($label, $name = 'submit', $createElement = false)
736
    {
737
        return $this->addButton(
738
            $name,
739
            $label,
740
            'upload',
741
            'primary',
742
            null,
743
            null,
744
            [],
745
            $createElement
746
        );
747
    }
748
749
    /**
750
     * Returns a button with the primary color and a download icon.
751
     *
752
     * @param string $label         Text appearing on the button
753
     * @param string $name          Element name (for form treatment purposes)
754
     * @param bool   $createElement Whether to use the create or add method
755
     *
756
     * @return HTML_QuickForm_button
757
     */
758
    public function addButtonDownload($label, $name = 'submit', $createElement = false)
759
    {
760
        return $this->addButton(
761
            $name,
762
            $label,
763
            'download',
764
            'primary',
765
            null,
766
            null,
767
            [],
768
            $createElement
769
        );
770
    }
771
772
    /**
773
     * Returns a button with the primary color and a magnifier icon.
774
     *
775
     * @param string $label         Text appearing on the button
776
     * @param string $name          Element name (for form treatment purposes)
777
     * @param bool   $createElement Whether to use the create or add method
778
     *
779
     * @return HTML_QuickForm_button
780
     */
781
    public function addButtonPreview($label, $name = 'submit', $createElement = false)
782
    {
783
        return $this->addButton(
784
            $name,
785
            $label,
786
            'search',
787
            'primary',
788
            null,
789
            null,
790
            [],
791
            $createElement
792
        );
793
    }
794
795
    /**
796
     * Returns a button with the primary color and a copy (double sheet) icon.
797
     *
798
     * @param string $label         Text appearing on the button
799
     * @param string $name          Element name (for form treatment purposes)
800
     * @param bool   $createElement Whether to use the create or add method
801
     *
802
     * @return HTML_QuickForm_button
803
     */
804
    public function addButtonCopy($label, $name = 'submit', $createElement = false)
805
    {
806
        return $this->addButton(
807
            $name,
808
            $label,
809
            'copy',
810
            'primary',
811
            null,
812
            null,
813
            [],
814
            $createElement
815
        );
816
    }
817
818
    /**
819
     * @param string $name
820
     * @param string $label
821
     * @param string $text
822
     * @param array  $attributes
823
     *
824
     * @return HTML_QuickForm_checkbox
825
     */
826
    public function addCheckBox($name, $label, $text = '', $attributes = [])
827
    {
828
        return $this->addElement('checkbox', $name, $label, $text, $attributes);
829
    }
830
831
    /**
832
     * @param string $name
833
     * @param string $label
834
     * @param array  $options
835
     * @param array  $attributes
836
     *
837
     * @return HTML_QuickForm_group
838
     */
839
    public function addCheckBoxGroup($name, $label, $options = [], $attributes = [])
840
    {
841
        $group = [];
842
        foreach ($options as $value => $text) {
843
            $attributes['value'] = $value;
844
            $group[] = $this->createElement(
845
                'checkbox',
846
                $value,
847
                null,
848
                $text,
849
                $attributes
850
            );
851
        }
852
853
        return $this->addGroup($group, $name, $label);
854
    }
855
856
    /**
857
     * @param string $name
858
     * @param string $label
859
     * @param array  $options
860
     * @param array  $attributes
861
     *
862
     * @return HTML_QuickForm_group
863
     */
864
    public function addRadio($name, $label, $options = [], $attributes = [])
865
    {
866
        $group = [];
867
        foreach ($options as $key => $value) {
868
            $group[] = $this->createElement('radio', null, null, $value, $key, $attributes);
869
        }
870
871
        return $this->addGroup($group, $name, $label);
872
    }
873
874
    /**
875
     * @param string $name
876
     * @param string $label
877
     * @param array  $options
878
     * @param array  $attributes
879
     *
880
     * @return HTML_QuickForm_select
881
     */
882
    public function addSelect($name, $label, $options = [], $attributes = [])
883
    {
884
        return $this->addElement('select', $name, $label, $options, $attributes);
885
    }
886
887
    /**
888
     * @param $name
889
     * @param $label
890
     * @param $collection
891
     * @param array  $attributes
892
     * @param bool   $addNoneOption
893
     * @param string $textCallable  set a function getStringValue() by default __toString()
894
     *
895
     * @return HTML_QuickForm_element
896
     */
897
    public function addSelectFromCollection(
898
        $name,
899
        $label,
900
        $collection,
901
        $attributes = [],
902
        $addNoneOption = false,
903
        $textCallable = ''
904
    ) {
905
        $options = [];
906
907
        if ($addNoneOption) {
908
            $options[0] = get_lang('None');
909
        }
910
911
        if (!empty($collection)) {
912
            foreach ($collection as $item) {
913
                $text = $item;
914
                if (!empty($textCallable)) {
915
                    $text = $item->$textCallable();
916
                }
917
                $options[$item->getId()] = $text;
918
            }
919
        }
920
921
        return $this->addElement('select', $name, $label, $options, $attributes);
922
    }
923
924
    /**
925
     * @param string $label
926
     * @param string $text
927
     * @param bool   $createElement
928
     *
929
     * @return HTML_QuickForm_Element
930
     */
931
    public function addLabel($label, $text, $createElement = false)
932
    {
933
        if ($createElement) {
934
            return $this->createElement(
935
                'label',
936
                $label,
937
                $text
938
            );
939
        }
940
941
        return $this->addElement('label', $label, $text);
942
    }
943
944
    /**
945
     * @param string $text
946
     */
947
    public function addHeader($text)
948
    {
949
        if (!empty($text)) {
950
            $this->addElement('header', $text);
951
        }
952
    }
953
954
    /**
955
     * @param string $name
956
     * @param string $label
957
     * @param array  $attributes
958
     *
959
     * @throws Exception if the file doesn't have an id
960
     *
961
     * @return HTML_QuickForm_file
962
     */
963
    public function addFile($name, $label, $attributes = [])
964
    {
965
        try {
966
            $element = $this->addElement('file', $name, $label, $attributes);
967
            if (isset($attributes['crop_image'])) {
968
                $id = $element->getAttribute('id');
969
                if (empty($id)) {
970
                    throw new Exception('If you use the crop functionality the element must have an id');
971
                }
972
                $this->addHtml(
973
                    '
974
                <div class="form-group row" id="'.$id.'-form-group" style="display: none;">
975
                    <div class="offset-md-2 col-sm-8">
976
                        <div class="card-cropper">
977
                            <div id="'.$id.'_crop_image" class="cropCanvas">
978
                                <img id="'.$id.'_preview_image">
979
                            </div>
980
                            <button class="btn btn-primary" type="button" name="cropButton" id="'.$id.'_crop_button">
981
                                <em class="fa fa-crop"></em> '.get_lang('Crop your picture').'
982
                            </button>
983
                        </div>
984
                    </div>
985
                </div>'
986
                );
987
                $this->addHidden($id.'_crop_result', '');
988
                $this->addHidden($id.'_crop_result_for_resource', '');
989
                $this->addHidden($id.'_crop_image_base_64', '');
990
            }
991
        } catch (HTML_Quick | Form_Error $e) {
992
            var_dump($e->getMessage());
0 ignored issues
show
Security Debugging Code introduced by
var_dump($e->getMessage()) looks like debug code. Are you sure you do not want to remove it?
Loading history...
993
        }
994
995
        return $element;
996
    }
997
998
    /**
999
     * @param string $snippet
1000
     */
1001
    public function addHtml($snippet)
1002
    {
1003
        if (empty($snippet)) {
1004
            return false;
1005
        }
1006
        $this->addElement('html', $snippet);
1007
1008
        return true;
1009
    }
1010
1011
    /**
1012
     * Draws a panel of options see the course_info/infocours.php page.
1013
     *
1014
     * @param string $name      internal name
1015
     * @param string $title     visible title
1016
     * @param array  $groupList list of group or elements
1017
     */
1018
    public function addPanelOption($name, $title, $groupList, $icon, $open = false, $parent)
1019
    {
1020
        $html = '<div class="card">';
1021
        $html .= '<div class="card-header" id="card_'.$name.'">';
1022
        $html .= '<h5 class="card-title">';
1023
        $html .= '<a role="button" class="'.(($open) ? 'collapse' : ' ').'"  data-toggle="collapse" data-target="#collapse_'.$name.'" aria-expanded="true" aria-controls="collapse_'.$name.'">';
1024
        if ($icon) {
1025
            $html .= Display::return_icon($icon, null, null, ICON_SIZE_SMALL);
1026
        }
1027
        $html .= $title;
1028
        $html .= '</a></h5></div>';
1029
        $html .= '<div id="collapse_'.$name.'" class="collapse '.(($open) ? 'show' : ' ').'" aria-labelledby="heading_'.$name.'" data-parent="#'.$parent.'">';
1030
        $html .= '<div class="card-body">';
1031
1032
        $this->addHtml($html);
1033
1034
        foreach ($groupList as $groupName => $group) {
1035
            // Add group array
1036
            if (!empty($groupName) && is_array($group)) {
1037
                $this->addGroup($group, '', $groupName);
1038
            }
1039
            // Add element
1040
            if ($group instanceof HTML_QuickForm_element) {
1041
                $this->addElement($group);
1042
            }
1043
        }
1044
1045
        $this->addHtml('</div></div></div>');
1046
    }
1047
1048
    /**
1049
     * Adds a HTML-editor to the form.
1050
     *
1051
     * @param string       $name
1052
     * @param string|array $label      The label for the form-element
1053
     * @param bool         $required   (optional) Is the form-element required (default=true)
1054
     * @param bool         $fullPage   (optional) When it is true, the editor loads completed html code for a full page
1055
     * @param array        $config     (optional) Configuration settings for the online editor
1056
     * @param array        $attributes
1057
     *
1058
     * @throws Exception
1059
     * @throws HTML_QuickForm_Error
1060
     */
1061
    public function addHtmlEditor(
1062
        $name,
1063
        $label,
1064
        $required = true,
1065
        $fullPage = false,
1066
        $config = [],
1067
        $attributes = []
1068
    ) {
1069
        $attributes = [];
1070
        $attributes['rows'] = isset($config['rows']) ? $config['rows'] : 15;
1071
        $attributes['cols'] = isset($config['cols']) ? $config['cols'] : 80;
1072
        $attributes['cols-size'] = isset($config['cols-size']) ? $config['cols-size'] : [];
1073
        $attributes['class'] = isset($config['class']) ? $config['class'] : [];
1074
        $attributes['id'] = isset($config['id']) ? $config['id'] : '';
1075
1076
        if (empty($attributes['id'])) {
1077
            $attributes['id'] = $name;
1078
        }
1079
1080
        $this->addElement('html_editor', $name, $label, $attributes, $config);
1081
        $this->applyFilter($name, 'trim');
1082
        if ($required) {
1083
            $this->addRule($name, get_lang('Required field'), 'required');
1084
        }
1085
1086
        /** @var HtmlEditor $element */
1087
        $element = $this->getElement($name);
1088
        $config['style'] = isset($config['style']) ? $config['style'] : false;
1089
        if ($fullPage) {
1090
            $config['fullPage'] = true;
1091
            // Adds editor_content.css in ckEditor
1092
            $config['style'] = true;
1093
        }
1094
1095
        if ($element->editor) {
1096
            $element->editor->processConfig($config);
1097
        }
1098
    }
1099
1100
    /**
1101
     * Adds a Google Maps Geolocalization field to the form.
1102
     *
1103
     * @param      $name
1104
     * @param      $label
1105
     * @param bool $hideGeoLocalizationDetails
1106
     */
1107
    public function addGeoLocationMapField($name, $label, $dataValue, $hideGeoLocalizationDetails = false)
1108
    {
1109
        $gMapsPlugin = GoogleMapsPlugin::create();
1110
        $geolocalization = 'true' === $gMapsPlugin->get('enable_api');
1111
1112
        if ($geolocalization && false === $gMapsPlugin->javascriptIncluded) {
1113
            $gmapsApiKey = $gMapsPlugin->get('api_key');
1114
            $url = '//maps.googleapis.com/maps/api/js?key='.$gmapsApiKey;
1115
            $this->addHtml('<script type="text/javascript" src="'.$url.'" ></script>');
1116
            $gMapsPlugin->javascriptIncluded = true;
1117
        }
1118
1119
        $this->addElement(
1120
            'text',
1121
            $name,
1122
            $label,
1123
            ['id' => $name]
1124
        );
1125
1126
        $this->addHidden(
1127
            $name.'_coordinates',
1128
            '',
1129
            ['id' => $name.'_coordinates']
1130
        );
1131
1132
        $this->applyFilter($name, 'stripslashes');
1133
        $this->applyFilter($name, 'trim');
1134
1135
        $this->addHtml(Extrafield::getLocalizationJavascript($name, $dataValue));
1136
1137
        if ($hideGeoLocalizationDetails) {
1138
            $this->addHtml('<div style="display:none">');
1139
        }
1140
1141
        $this->addHtml(
1142
            Extrafield::getLocalizationInput($name, $label)
1143
        );
1144
1145
        if ($hideGeoLocalizationDetails) {
1146
            $this->addHtml('</div>');
1147
        }
1148
    }
1149
1150
    /**
1151
     * @param string $name
1152
     * @param string $label
1153
     *
1154
     * @return mixed
1155
     */
1156
    public function addButtonAdvancedSettings($name, $label = '')
1157
    {
1158
        $label = !empty($label) ? $label : get_lang('Advanced settings');
1159
1160
        return $this->addElement('advanced_settings', $name, $label);
1161
    }
1162
1163
    /**
1164
     * Adds a progress loading image to the form.
1165
     */
1166
    public function addProgress($delay = 2, $label = '')
1167
    {
1168
        if (empty($label)) {
1169
            $label = get_lang('Please stand by...');
1170
        }
1171
        $this->with_progress_bar = true;
1172
        $id = $this->getAttribute('id');
1173
1174
        $this->updateAttributes("onsubmit=\"javascript: addProgress('".$id."')\"");
1175
        $this->addHtml('<script language="javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/upload.js" type="text/javascript"></script>');
1176
    }
1177
1178
    /**
1179
     * This function has been created for avoiding changes directly within QuickForm class.
1180
     * When we use it, the element is threated as 'required' to be dealt during validation.
1181
     *
1182
     * @param array  $elements The array of elements
1183
     * @param string $message  The message displayed
1184
     */
1185
    public function add_multiple_required_rule($elements, $message)
1186
    {
1187
        $this->_required[] = $elements[0];
1188
        $this->addRule($elements, $message, 'multiple_required');
1189
    }
1190
1191
    /**
1192
     * Displays the form.
1193
     * If an element in the form didn't validate, an error message is showed
1194
     * asking the user to complete the form.
1195
     */
1196
    public function display()
1197
    {
1198
        echo $this->returnForm();
1199
    }
1200
1201
    /**
1202
     * Returns the HTML code of the form.
1203
     *
1204
     * @return string $return_value HTML code of the form
1205
     */
1206
    public function returnForm()
1207
    {
1208
        $returnValue = '';
1209
1210
        /** @var HTML_QuickForm_element $element */
1211
        foreach ($this->_elements as &$element) {
1212
            $element->setLayout($this->getLayout());
1213
            $elementError = parent::getElementError($element->getName());
1214
            if (!is_null($elementError)) {
1215
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1216
                break;
1217
            }
1218
        }
1219
1220
        $returnValue .= parent::toHtml();
1221
        // Add div-element which is to hold the progress bar
1222
        $id = $this->getAttribute('id');
1223
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1224
            // @todo improve UI
1225
            $returnValue .= '<br />
1226
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1227
                <div class="wobblebar-loader"></div>
1228
            </div>
1229
            ';
1230
        }
1231
1232
        return $returnValue;
1233
    }
1234
1235
    /**
1236
     * Returns the HTML code of the form.
1237
     * If an element in the form didn't validate, an error message is showed
1238
     * asking the user to complete the form.
1239
     *
1240
     * @return string $return_value HTML code of the form
1241
     *
1242
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1243
     * @author Julio Montoya
1244
     *
1245
     * @deprecated use returnForm()
1246
     */
1247
    public function return_form()
1248
    {
1249
        return $this->returnForm();
1250
    }
1251
1252
    /**
1253
     * @return HTML_QuickForm_Renderer_Default
1254
     */
1255
    public static function getDefaultRenderer()
1256
    {
1257
        return
1258
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1259
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1260
    }
1261
1262
    /**
1263
     * Adds a input of type url to the form.
1264
     *
1265
     * @param string $name       The label for the form-element
1266
     * @param string $label      The element name
1267
     * @param bool   $required   Optional. Is the form-element required (default=true)
1268
     * @param array  $attributes Optional. List of attributes for the form-element
1269
     */
1270
    public function addUrl($name, $label, $required = true, $attributes = [])
1271
    {
1272
        $this->addElement('url', $name, $label, $attributes);
1273
        $this->applyFilter($name, 'trim');
1274
        $this->addRule($name, get_lang('Insert a valid URL'), 'url');
1275
1276
        if ($required) {
1277
            $this->addRule($name, get_lang('Required field'), 'required');
1278
        }
1279
    }
1280
1281
    /**
1282
     * Adds a text field for letters to the form.
1283
     * A trim-filter is attached to the field.
1284
     *
1285
     * @param string $name       The element name
1286
     * @param string $label      The label for the form-element
1287
     * @param bool   $required   Optional. Is the form-element required (default=true)
1288
     * @param array  $attributes Optional. List of attributes for the form-element
1289
     */
1290
    public function addTextLettersOnly(
1291
        $name,
1292
        $label,
1293
        $required = false,
1294
        $attributes = []
1295
    ) {
1296
        $attributes = array_merge(
1297
            $attributes,
1298
            [
1299
                'pattern' => '[a-zA-ZñÑ]+',
1300
                'title' => get_lang('Only letters'),
1301
            ]
1302
        );
1303
1304
        $this->addElement(
1305
            'text',
1306
            $name,
1307
            [
1308
                $label,
1309
                get_lang('Only letters'),
1310
            ],
1311
            $attributes
1312
        );
1313
1314
        $this->applyFilter($name, 'trim');
1315
1316
        if ($required) {
1317
            $this->addRule($name, get_lang('Required field'), 'required');
1318
        }
1319
1320
        $this->addRule(
1321
            $name,
1322
            get_lang('Only letters'),
1323
            'regex',
1324
            '/^[a-zA-ZñÑ]+$/'
1325
        );
1326
    }
1327
1328
    /**
1329
     * @param string $name
1330
     * @param string $label
1331
     * @param array  $attributes
1332
     * @param bool   $required
1333
     *
1334
     * @return HTML_QuickForm_element
1335
     */
1336
    public function addNumeric($name, $label, $attributes = [], $required = false)
1337
    {
1338
        $element = $this->addElement('Number', $name, $label, $attributes);
1339
1340
        if ($required) {
1341
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1342
        }
1343
1344
        return $element;
1345
    }
1346
1347
    /**
1348
     * Adds a text field for alphanumeric characters to the form.
1349
     * A trim-filter is attached to the field.
1350
     *
1351
     * @param string $name       The element name
1352
     * @param string $label      The label for the form-element
1353
     * @param bool   $required   Optional. Is the form-element required (default=true)
1354
     * @param array  $attributes Optional. List of attributes for the form-element
1355
     */
1356
    public function addTextAlphanumeric(
1357
        $name,
1358
        $label,
1359
        $required = false,
1360
        $attributes = []
1361
    ) {
1362
        $attributes = array_merge(
1363
            $attributes,
1364
            [
1365
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1366
                'title' => get_lang('Only lettersAndNumbers'),
1367
            ]
1368
        );
1369
1370
        $this->addElement(
1371
            'text',
1372
            $name,
1373
            [
1374
                $label,
1375
                get_lang('Only lettersAndNumbers'),
1376
            ],
1377
            $attributes
1378
        );
1379
1380
        $this->applyFilter($name, 'trim');
1381
1382
        if ($required) {
1383
            $this->addRule($name, get_lang('Required field'), 'required');
1384
        }
1385
1386
        $this->addRule(
1387
            $name,
1388
            get_lang('Only lettersAndNumbers'),
1389
            'regex',
1390
            '/^[a-zA-Z0-9ÑÑ]+$/'
1391
        );
1392
    }
1393
1394
    /**
1395
     * @param string $name
1396
     * @param $label
1397
     * @param bool  $required
1398
     * @param array $attributes
1399
     * @param bool  $allowNegative
1400
     * @param int   $minValue
1401
     * @param null  $maxValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $maxValue is correct as it would always require null to be passed?
Loading history...
1402
     */
1403
    public function addFloat(
1404
        $name,
1405
        $label,
1406
        $required = false,
1407
        $attributes = [],
1408
        $allowNegative = false,
1409
        $minValue = null,
1410
        $maxValue = null
1411
    ) {
1412
        $this->addElement(
1413
            'FloatNumber',
1414
            $name,
1415
            $label,
1416
            $attributes
1417
        );
1418
1419
        $this->applyFilter($name, 'trim');
1420
1421
        if ($required) {
1422
            $this->addRule($name, get_lang('Required field'), 'required');
1423
        }
1424
1425
        // Rule allows "," and "."
1426
        /*$this->addRule(
1427
            $name,
1428
            get_lang('Only numbers'),
1429
            'regex',
1430
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1431
        );*/
1432
1433
        if (false == $allowNegative) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1434
            $this->addRule(
1435
                $name,
1436
                get_lang('Negative value'),
1437
                'compare',
1438
                '>=',
1439
                'server',
1440
                false,
1441
                false,
1442
                0
1443
            );
1444
        }
1445
1446
        if (!is_null($minValue)) {
1447
            $this->addRule(
1448
                $name,
1449
                get_lang('Under the minimum.'),
1450
                'compare',
1451
                '>=',
1452
                'server',
1453
                false,
1454
                false,
1455
                $minValue
1456
            );
1457
        }
1458
1459
        if (!is_null($maxValue)) {
1460
            $this->addRule(
1461
                $name,
1462
                get_lang('Value exceeds score.'),
1463
                'compare',
1464
                '<=',
1465
                'server',
1466
                false,
1467
                false,
1468
                $maxValue
1469
            );
1470
        }
1471
    }
1472
1473
    /**
1474
     * Adds a text field for letters and spaces to the form.
1475
     * A trim-filter is attached to the field.
1476
     *
1477
     * @param string $name       The element name
1478
     * @param string $label      The label for the form-element
1479
     * @param bool   $required   Optional. Is the form-element required (default=true)
1480
     * @param array  $attributes Optional. List of attributes for the form-element
1481
     */
1482
    public function addTextLettersAndSpaces(
1483
        $name,
1484
        $label,
1485
        $required = false,
1486
        $attributes = []
1487
    ) {
1488
        $attributes = array_merge(
1489
            $attributes,
1490
            [
1491
                'pattern' => '[a-zA-ZñÑ\s]+',
1492
                'title' => get_lang('Only lettersAndSpaces'),
1493
            ]
1494
        );
1495
1496
        $this->addElement(
1497
            'text',
1498
            $name,
1499
            [
1500
                $label,
1501
                get_lang('Only lettersAndSpaces'),
1502
            ],
1503
            $attributes
1504
        );
1505
1506
        $this->applyFilter($name, 'trim');
1507
1508
        if ($required) {
1509
            $this->addRule($name, get_lang('Required field'), 'required');
1510
        }
1511
1512
        $this->addRule(
1513
            $name,
1514
            get_lang('Only lettersAndSpaces'),
1515
            'regex',
1516
            '/^[a-zA-ZñÑ\s]+$/'
1517
        );
1518
    }
1519
1520
    /**
1521
     * Adds a text field for alphanumeric and spaces characters to the form.
1522
     * A trim-filter is attached to the field.
1523
     *
1524
     * @param string $name       The element name
1525
     * @param string $label      The label for the form-element
1526
     * @param bool   $required   Optional. Is the form-element required (default=true)
1527
     * @param array  $attributes Optional. List of attributes for the form-element
1528
     */
1529
    public function addTextAlphanumericAndSpaces(
1530
        $name,
1531
        $label,
1532
        $required = false,
1533
        $attributes = []
1534
    ) {
1535
        $attributes = array_merge(
1536
            $attributes,
1537
            [
1538
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1539
                'title' => get_lang('Only lettersAndNumbersAndSpaces'),
1540
            ]
1541
        );
1542
1543
        $this->addElement(
1544
            'text',
1545
            $name,
1546
            [
1547
                $label,
1548
                get_lang('Only lettersAndNumbersAndSpaces'),
1549
            ],
1550
            $attributes
1551
        );
1552
1553
        $this->applyFilter($name, 'trim');
1554
1555
        if ($required) {
1556
            $this->addRule($name, get_lang('Required field'), 'required');
1557
        }
1558
1559
        $this->addRule(
1560
            $name,
1561
            get_lang('Only lettersAndNumbersAndSpaces'),
1562
            'regex',
1563
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1564
        );
1565
    }
1566
1567
    /**
1568
     * @param string $url
1569
     * @param string $urlToRedirect after upload redirect to this page
1570
     */
1571
    public function addMultipleUpload($url, $urlToRedirect = '')
1572
    {
1573
        $inputName = 'input_file_upload';
1574
        $this->addMultipleUploadJavascript($url, $inputName, $urlToRedirect);
1575
1576
        $this->addHtml('
1577
            <div class="description-upload">
1578
            '.get_lang('Click on the box below to select files from your computer (you can use CTRL + clic to select various files at a time), or drag and drop some files from your desktop directly over the box below. The system will handle the rest!').'
1579
            </div>
1580
            <span class="btn btn-success fileinput-button">
1581
                <i class="glyphicon glyphicon-plus"></i>
1582
                <span>'.get_lang('Add files').'</span>
1583
                <!-- The file input field used as target for the file upload widget -->
1584
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1585
            </span>
1586
            <div id="dropzone">
1587
                <div class="button-load">
1588
                '.get_lang('Click or drag and drop files here to upload them').'
1589
                </div>
1590
            </div>
1591
            <br />
1592
            <!-- The global progress bar -->
1593
            <div id="progress" class="progress">
1594
                <div class="progress-bar progress-bar-success"></div>
1595
            </div>
1596
            <div id="files" class="files"></div>
1597
        ');
1598
    }
1599
1600
    /**
1601
     * @param string $elementName
1602
     * @param string $groupName   if element is inside a group
1603
     *
1604
     * @throws Exception
1605
     */
1606
    public function addPasswordRule($elementName, $groupName = '')
1607
    {
1608
        if ('true' == api_get_setting('security.check_password')) {
1609
            $message = get_lang('this password  is too simple. Use a pass like this').': '.api_generate_password();
1610
1611
            if (!empty($groupName)) {
1612
                $groupObj = $this->getElement($groupName);
1613
1614
                if ($groupObj instanceof HTML_QuickForm_group) {
1615
                    $elementName = $groupObj->getElementName($elementName);
1616
1617
                    if (false === $elementName) {
1618
                        throw new Exception("The $groupName doesn't have the element $elementName");
1619
                    }
1620
1621
                    $this->_rules[$elementName][] = [
1622
                        'type' => 'callback',
1623
                        'format' => 'api_check_password',
1624
                        'message' => $message,
1625
                        'validation' => '',
1626
                        'reset' => false,
1627
                        'group' => $groupName,
1628
                    ];
1629
                }
1630
            } else {
1631
                $this->addRule(
1632
                    $elementName,
1633
                    $message,
1634
                    'callback',
1635
                    'api_check_password'
1636
                );
1637
            }
1638
        }
1639
    }
1640
1641
    /**
1642
     * Add an element with user ID and avatar to the form.
1643
     * It needs a Chamilo\CoreBundle\Entity\User as value. The exported value is the Chamilo\CoreBundle\Entity\User ID.
1644
     *
1645
     * @see \UserAvatar
1646
     *
1647
     * @param string $name
1648
     * @param string $label
1649
     * @param string $imageSize Optional. Small, medium or large image
1650
     * @param string $subtitle  Optional. The subtitle for the field
1651
     *
1652
     * @return \UserAvatar
1653
     */
1654
    public function addUserAvatar($name, $label, $imageSize = 'small', $subtitle = '')
1655
    {
1656
        return $this->addElement('UserAvatar', $name, $label, ['image_size' => $imageSize, 'sub_title' => $subtitle]);
1657
    }
1658
1659
    /**
1660
     * @param array $typeList
1661
     */
1662
    public function addEmailTemplate($typeList)
1663
    {
1664
        $mailManager = new MailTemplateManager();
1665
        foreach ($typeList as $type) {
1666
            $list = $mailManager->get_all(
1667
                ['where' => ['type = ? AND url_id = ?' => [$type, api_get_current_access_url_id()]]]
1668
            );
1669
1670
            $options = [get_lang('Select')];
1671
            $name = $type;
1672
            $defaultId = '';
1673
            foreach ($list as $item) {
1674
                $options[$item['id']] = $item['name'];
1675
                $name = $item['name'];
1676
                if (empty($defaultId)) {
1677
                    $defaultId = 1 == $item['default_template'] ? $item['id'] : '';
1678
                }
1679
            }
1680
1681
            $url = api_get_path(WEB_AJAX_PATH).'mail.ajax.php?a=select_option';
1682
            $typeNoDots = 'email_template_option_'.str_replace('.tpl', '', $type);
1683
            $this->addSelect(
1684
                'email_template_option['.$type.']',
1685
                $name,
1686
                $options,
1687
                ['id' => $typeNoDots]
1688
            );
1689
1690
            $templateNoDots = 'email_template_'.str_replace('.tpl', '', $type);
1691
            $templateNoDotsBlock = 'email_template_block_'.str_replace('.tpl', '', $type);
1692
            $this->addHtml('<div id="'.$templateNoDotsBlock.'" style="display:none">');
1693
            $this->addTextarea(
1694
                $templateNoDots,
1695
                get_lang('Preview'),
1696
                ['disabled' => 'disabled ', 'id' => $templateNoDots, 'rows' => '5']
1697
            );
1698
            $this->addHtml('</div>');
1699
1700
            $this->addHtml("<script>
1701
            $(function() {
1702
                var defaultValue = '$defaultId';
1703
                $('#$typeNoDots').val(defaultValue);
1704
                $('#$typeNoDots').selectpicker('render');
1705
                if (defaultValue != '') {
1706
                    var selected = $('#$typeNoDots option:selected').val();
1707
                    $.ajax({
1708
                        url: '$url' + '&id=' + selected+ '&template_name=$type',
1709
                        success: function (data) {
1710
                            $('#$templateNoDots').html(data);
1711
                            $('#$templateNoDotsBlock').show();
1712
                            return;
1713
                        },
1714
                    });
1715
                }
1716
1717
                $('#$typeNoDots').on('change', function(){
1718
                    var selected = $('#$typeNoDots option:selected').val();
1719
                    $.ajax({
1720
                        url: '$url' + '&id=' + selected,
1721
                        success: function (data) {
1722
                            $('#$templateNoDots').html(data);
1723
                            $('#$templateNoDotsBlock').show();
1724
                            return;
1725
                        },
1726
                    });
1727
                });
1728
            });
1729
            </script>");
1730
        }
1731
    }
1732
1733
    /**
1734
     * @param string $url           page that will handle the upload
1735
     * @param string $inputName
1736
     * @param string $urlToRedirect
1737
     */
1738
    private function addMultipleUploadJavascript($url, $inputName, $urlToRedirect = '')
1739
    {
1740
        $redirectCondition = '';
1741
        if (!empty($urlToRedirect)) {
1742
            $redirectCondition = "window.location.replace('$urlToRedirect'); ";
1743
        }
1744
        $icon = Display::return_icon('file_txt.gif');
1745
        $this->addHtml("
1746
        <script>
1747
        $(function () {
1748
            'use strict';
1749
            $('#".$this->getAttribute('id')."').submit(function() {
1750
                return false;
1751
            });
1752
1753
            $('#dropzone').on('click', function() {
1754
                $('#".$inputName."').click();
1755
            });
1756
1757
            var url = '".$url."';
1758
            var uploadButton = $('<button/>')
1759
                .addClass('btn btn-primary')
1760
                .prop('disabled', true)
1761
                .text('".addslashes(get_lang('Loading'))."')
1762
                .on('click', function () {
1763
                    var \$this = $(this),
1764
                    data = \$this.data();
1765
                    \$this
1766
                        .off('click')
1767
                        .text('".addslashes(get_lang('Cancel'))."')
1768
                        .on('click', function () {
1769
                            \$this.remove();
1770
                            data.abort();
1771
                        });
1772
                    data.submit().always(function () {
1773
                        \$this.remove();
1774
                    });
1775
                });
1776
1777
            $('#".$inputName."').fileupload({
1778
                url: url,
1779
                dataType: 'json',
1780
                // Enable image resizing, except for Android and Opera,
1781
                // which actually support image resizing, but fail to
1782
                // send Blob objects via XHR requests:
1783
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1784
                previewMaxWidth: 300,
1785
                previewMaxHeight: 169,
1786
                previewCrop: true,
1787
                dropzone: $('#dropzone'),
1788
            }).on('fileuploadadd', function (e, data) {
1789
                data.context = $('<div class=\"row\" />').appendTo('#files');
1790
                $.each(data.files, function (index, file) {
1791
                    var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);
1792
                    node.appendTo(data.context);
1793
                });
1794
            }).on('fileuploadprocessalways', function (e, data) {
1795
                var index = data.index,
1796
                    file = data.files[index],
1797
                    node = $(data.context.children()[index]);
1798
                if (file.preview) {
1799
                    data.context.prepend($('<div class=\"col-sm-4\">').html(file.preview));
1800
                } else {
1801
                    data.context.prepend($('<div class=\"col-sm-4\">').html('".$icon."'));
1802
                }
1803
                if (index + 1 === data.files.length) {
1804
                    data.context.find('button')
1805
                        .text('Upload')
1806
                        .prop('disabled', !!data.files.error);
1807
                }
1808
            }).on('fileuploadprogressall', function (e, data) {
1809
                var progress = parseInt(data.loaded / data.total * 100, 10);
1810
                $('#progress .progress-bar').css(
1811
                    'width',
1812
                    progress + '%'
1813
                );
1814
            }).on('fileuploaddone', function (e, data) {
1815
                $.each(data.result.files, function (index, file) {
1816
                    if (file.error) {
1817
                        var link = $('<div>')
1818
                            .attr({class : 'panel-image'})                            ;
1819
                        $(data.context.children()[index]).parent().wrap(link);
1820
                        // Update file name with new one from Chamilo
1821
                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1822
                        var message = $('<div class=\"col-sm-3\">').html(
1823
                            $('<span class=\"message-image-danger\"/>').text(file.error)
1824
                        );
1825
                        $(data.context.children()[index]).parent().append(message);
1826
1827
                        return;
1828
                    }
1829
                    if (file.url) {
1830
                        var link = $('<a>')
1831
                            .attr({target: '_blank', class : 'panel-image'})
1832
                            .prop('href', file.url);
1833
                        $(data.context.children()[index]).parent().wrap(link);
1834
                    }
1835
                    // Update file name with new one from Chamilo
1836
                    $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1837
                    var message = $('<div class=\"col-sm-3\">').html(
1838
                        $('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('File upload succeeded!'))."')
1839
                    );
1840
                    $(data.context.children()[index]).parent().append(message);
1841
                });
1842
                $('#dropzone').removeClass('hover');
1843
                ".$redirectCondition."
1844
            }).on('fileuploadfail', function (e, data) {
1845
                $.each(data.files, function (index) {
1846
                    var failedMessage = '".addslashes(get_lang('The file upload has failed.'))."';
1847
                    var error = $('<div class=\"col-sm-3\">').html(
1848
                        $('<span class=\"alert alert-danger\"/>').text(failedMessage)
1849
                    );
1850
                    $(data.context.children()[index]).parent().append(error);
1851
                });
1852
                $('#dropzone').removeClass('hover');
1853
            }).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');
1854
1855
            $('#dropzone').on('dragover', function (e) {
1856
                // dragleave callback implementation
1857
                $('#dropzone').addClass('hover');
1858
            });
1859
1860
            $('#dropzone').on('dragleave', function (e) {
1861
                $('#dropzone').removeClass('hover');
1862
            });
1863
            $('.fileinput-button').hide();
1864
        });
1865
        </script>");
1866
    }
1867
1868
    public function addEmailRule(string $element)
1869
    {
1870
        $this->addRule(
1871
            $element,
1872
            get_lang('The email address is not complete or contains some invalid characters'),
1873
            'email'
1874
        );
1875
    }
1876
}
1877
1878
/**
1879
 * Cleans HTML text filter.
1880
 *
1881
 * @param string $html HTML to clean
1882
 * @param int    $mode (optional)
1883
 *
1884
 * @return string The cleaned HTML
1885
 */
1886
function html_filter($html, $mode = NO_HTML)
1887
{
1888
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1889
    $cleaned_html = kses($html, $allowed_tags);
0 ignored issues
show
Bug introduced by
The function kses was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

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