Passed
Push — master ( 5790ec...e60243 )
by Julito
09:33
created

FormValidator::addButton()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 19
nc 2
nop 8
dl 0
loc 32
rs 9.6333
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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

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