Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

main/inc/lib/formvalidator/FormValidator.class.php (1 issue)

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

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