Passed
Push — master ( 4671c2...3df10a )
by Julito
48:25
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
    /**
938
     * @param string $label
939
     * @param string $text
940
     * @param bool   $createElement
941
     *
942
     * @return HTML_QuickForm_Element
943
     */
944
    public function addLabel($label, $text, $createElement = false)
945
    {
946
        if ($createElement) {
947
            return $this->createElement(
948
                'label',
949
                $label,
950
                $text
951
            );
952
        }
953
954
        return $this->addElement('label', $label, $text);
955
    }
956
957
    /**
958
     * @param string $text
959
     */
960
    public function addHeader($text)
961
    {
962
        if (!empty($text)) {
963
            $this->addElement('header', $text);
964
        }
965
    }
966
967
    /**
968
     * @param string $name
969
     * @param string|array $label
970
     * @param array  $attributes
971
     *
972
     * @throws Exception if the file doesn't have an id
973
     *
974
     * @return HTML_QuickForm_file
975
     */
976
    public function addFile($name, $label, $attributes = [])
977
    {
978
        try {
979
            $element = $this->addElement('file', $name, $label, $attributes);
980
            if (isset($attributes['crop_image'])) {
981
                $id = $element->getAttribute('id');
982
                if (empty($id)) {
983
                    throw new Exception('If you use the crop functionality the element must have an id');
984
                }
985
                $this->addHtml(
986
                    '
987
                <div class="form-group row" id="'.$id.'-form-group" style="display: none;">
988
                    <div class="offset-md-2 col-sm-8">
989
                        <div class="card-cropper">
990
                            <div id="'.$id.'_crop_image" class="cropCanvas">
991
                                <img id="'.$id.'_preview_image">
992
                            </div>
993
                            <button class="btn btn-primary" type="button" name="cropButton" id="'.$id.'_crop_button">
994
                                <em class="fa fa-crop"></em> '.get_lang('Crop your picture').'
995
                            </button>
996
                        </div>
997
                    </div>
998
                </div>'
999
                );
1000
                $this->addHidden($id.'_crop_result', '');
1001
                $this->addHidden($id.'_crop_result_for_resource', '');
1002
                $this->addHidden($id.'_crop_image_base_64', '');
1003
            }
1004
        } catch (HTML_Quick | Form_Error $e) {
1005
            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...
1006
        }
1007
1008
        return $element;
1009
    }
1010
1011
    /**
1012
     * @param string $snippet
1013
     */
1014
    public function addHtml($snippet)
1015
    {
1016
        if (empty($snippet)) {
1017
            return false;
1018
        }
1019
        $this->addElement('html', $snippet);
1020
1021
        return true;
1022
    }
1023
1024
    /**
1025
     * Draws a panel of options see the course_info/infocours.php page.
1026
     *
1027
     * @param string $name      internal name
1028
     * @param string $title     visible title
1029
     * @param array  $groupList list of group or elements
1030
     */
1031
    public function addPanelOption($name, $title, $groupList, $icon, $open, $parent)
1032
    {
1033
        $html = '<div class="card">';
1034
        $html .= '<div class="card-header" id="card_'.$name.'">';
1035
        $html .= '<h5 class="card-title">';
1036
        $html .= '<a role="button" class="'.(($open) ? 'collapse' : ' ').'"  data-toggle="collapse" data-target="#collapse_'.$name.'" aria-expanded="true" aria-controls="collapse_'.$name.'">';
1037
        if ($icon) {
1038
            $html .= Display::return_icon($icon, null, null, ICON_SIZE_SMALL);
1039
        }
1040
        $html .= $title;
1041
        $html .= '</a></h5></div>';
1042
        $html .= '<div id="collapse_'.$name.'" class="collapse '.(($open) ? 'show' : ' ').'" aria-labelledby="heading_'.$name.'" data-parent="#'.$parent.'">';
1043
        $html .= '<div class="card-body">';
1044
1045
        $this->addHtml($html);
1046
1047
        foreach ($groupList as $groupName => $group) {
1048
            // Add group array
1049
            if (!empty($groupName) && is_array($group)) {
1050
                $this->addGroup($group, '', $groupName);
1051
            }
1052
            // Add element
1053
            if ($group instanceof HTML_QuickForm_element) {
1054
                $this->addElement($group);
1055
            }
1056
        }
1057
1058
        $this->addHtml('</div></div></div>');
1059
    }
1060
1061
    /**
1062
     * Adds a HTML-editor to the form.
1063
     *
1064
     * @param string       $name
1065
     * @param string|array $label      The label for the form-element
1066
     * @param bool         $required   (optional) Is the form-element required (default=true)
1067
     * @param bool         $fullPage   (optional) When it is true, the editor loads completed html code for a full page
1068
     * @param array        $config     (optional) Configuration settings for the online editor
1069
     * @param array        $attributes
1070
     *
1071
     * @throws Exception
1072
     * @throws HTML_QuickForm_Error
1073
     */
1074
    public function addHtmlEditor(
1075
        $name,
1076
        $label,
1077
        $required = true,
1078
        $fullPage = false,
1079
        $config = [],
1080
        $attributes = []
1081
    ) {
1082
        $attributes['rows'] = $config['rows'] ?? 15;
1083
        $attributes['cols'] = $config['cols'] ?? 80;
1084
        $attributes['cols-size'] = $config['cols-size'] ?? [];
1085
        $attributes['class'] = $config['class'] ?? [];
1086
        $cleanName = str_replace(['[', ']', '#'], '', $name);
1087
1088
        if (empty($attributes['id'])) {
1089
            $attributes['id'] = $cleanName;
1090
        }
1091
1092
        //$attributes['id'] = $config['id'] ?? 'editor_'.$cleanName;
1093
1094
        $this->addElement('html_editor', $name, $label, $attributes, $config);
1095
        $this->applyFilter($name, 'trim');
1096
        if ($required) {
1097
            $this->addRule($name, get_lang('Required field'), 'required');
1098
        }
1099
1100
        /** @var HtmlEditor $element */
1101
        $element = $this->getElement($name);
1102
        $config['style'] = $config['style'] ?? false;
1103
        if ($fullPage) {
1104
            $config['fullPage'] = true;
1105
            // Adds editor_content.css in ckEditor
1106
            $config['style'] = true;
1107
        }
1108
1109
        if ($element->editor) {
1110
            $element->editor->processConfig($config);
1111
        }
1112
    }
1113
1114
    /**
1115
     * Adds a Google Maps Geolocalization field to the form.
1116
     *
1117
     * @param      $name
1118
     * @param      $label
1119
     * @param bool $hideGeoLocalizationDetails
1120
     */
1121
    public function addGeoLocationMapField($name, $label, $dataValue, $hideGeoLocalizationDetails = false)
1122
    {
1123
        $gMapsPlugin = GoogleMapsPlugin::create();
1124
        $geolocalization = 'true' === $gMapsPlugin->get('enable_api');
1125
1126
        if ($geolocalization && false === $gMapsPlugin->javascriptIncluded) {
1127
            $gmapsApiKey = $gMapsPlugin->get('api_key');
1128
            $url = '//maps.googleapis.com/maps/api/js?key='.$gmapsApiKey;
1129
            $this->addHtml('<script type="text/javascript" src="'.$url.'" ></script>');
1130
            $gMapsPlugin->javascriptIncluded = true;
1131
        }
1132
1133
        $this->addElement(
1134
            'text',
1135
            $name,
1136
            $label,
1137
            ['id' => $name]
1138
        );
1139
1140
        $this->addHidden(
1141
            $name.'_coordinates',
1142
            '',
1143
            ['id' => $name.'_coordinates']
1144
        );
1145
1146
        $this->applyFilter($name, 'stripslashes');
1147
        $this->applyFilter($name, 'trim');
1148
1149
        $this->addHtml(Extrafield::getLocalizationJavascript($name, $dataValue));
1150
1151
        if ($hideGeoLocalizationDetails) {
1152
            $this->addHtml('<div style="display:none">');
1153
        }
1154
1155
        $this->addHtml(
1156
            Extrafield::getLocalizationInput($name, $label)
1157
        );
1158
1159
        if ($hideGeoLocalizationDetails) {
1160
            $this->addHtml('</div>');
1161
        }
1162
    }
1163
1164
    /**
1165
     * @param string       $name
1166
     * @param string|array $label
1167
     *
1168
     * @return mixed
1169
     */
1170
    public function addButtonAdvancedSettings($name, $label = null)
1171
    {
1172
        $label = !empty($label) ? $label : get_lang('Advanced settings');
1173
1174
        return $this->addElement('advanced_settings', $name, $label);
1175
    }
1176
1177
    /**
1178
     * Adds a progress loading image to the form.
1179
     */
1180
    public function addProgress($delay = 2, $label = '')
1181
    {
1182
        if (empty($label)) {
1183
            $label = get_lang('Please stand by...');
1184
        }
1185
        $this->with_progress_bar = true;
1186
        $id = $this->getAttribute('id');
1187
1188
        $this->updateAttributes("onsubmit=\"javascript: addProgress('".$id."')\"");
1189
        $this->addHtml('<script language="javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/upload.js" type="text/javascript"></script>');
1190
    }
1191
1192
    /**
1193
     * This function has been created for avoiding changes directly within QuickForm class.
1194
     * When we use it, the element is threated as 'required' to be dealt during validation.
1195
     *
1196
     * @param array  $elements The array of elements
1197
     * @param string $message  The message displayed
1198
     */
1199
    public function add_multiple_required_rule($elements, $message)
1200
    {
1201
        $this->_required[] = $elements[0];
1202
        $this->addRule($elements, $message, 'multiple_required');
1203
    }
1204
1205
    /**
1206
     * Displays the form.
1207
     * If an element in the form didn't validate, an error message is showed
1208
     * asking the user to complete the form.
1209
     */
1210
    public function display()
1211
    {
1212
        echo $this->returnForm();
1213
    }
1214
1215
    /**
1216
     * Returns the HTML code of the form.
1217
     *
1218
     * @return string $return_value HTML code of the form
1219
     */
1220
    public function returnForm()
1221
    {
1222
        $returnValue = '';
1223
        /** @var HTML_QuickForm_element $element */
1224
        foreach ($this->_elements as &$element) {
1225
            $element->setLayout($this->getLayout());
1226
            $elementError = parent::getElementError($element->getName());
1227
            if (!is_null($elementError)) {
1228
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1229
                break;
1230
            }
1231
        }
1232
1233
        $returnValue .= parent::toHtml();
1234
        // Add div-element which is to hold the progress bar
1235
        $id = $this->getAttribute('id');
1236
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1237
            // @todo improve UI
1238
            $returnValue .= '<br />
1239
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1240
                <div class="wobblebar-loader"></div>
1241
            </div>
1242
            ';
1243
        }
1244
1245
        return $returnValue;
1246
    }
1247
1248
    /**
1249
     * Returns the HTML code of the form.
1250
     * If an element in the form didn't validate, an error message is showed
1251
     * asking the user to complete the form.
1252
     *
1253
     * @return string $return_value HTML code of the form
1254
     *
1255
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1256
     * @author Julio Montoya
1257
     *
1258
     * @deprecated use returnForm()
1259
     */
1260
    public function return_form()
1261
    {
1262
        return $this->returnForm();
1263
    }
1264
1265
    /**
1266
     * @return HTML_QuickForm_Renderer_Default
1267
     */
1268
    public static function getDefaultRenderer()
1269
    {
1270
        return
1271
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1272
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1273
    }
1274
1275
    /**
1276
     * Adds a input of type url to the form.
1277
     *
1278
     * @param string $name       The label for the form-element
1279
     * @param string $label      The element name
1280
     * @param bool   $required   Optional. Is the form-element required (default=true)
1281
     * @param array  $attributes Optional. List of attributes for the form-element
1282
     */
1283
    public function addUrl($name, $label, $required = true, $attributes = [])
1284
    {
1285
        $this->addElement('url', $name, $label, $attributes);
1286
        $this->applyFilter($name, 'trim');
1287
        $this->addRule($name, get_lang('Insert a valid URL'), 'url');
1288
1289
        if ($required) {
1290
            $this->addRule($name, get_lang('Required field'), 'required');
1291
        }
1292
    }
1293
1294
    /**
1295
     * Adds a text field for letters to the form.
1296
     * A trim-filter is attached to the field.
1297
     *
1298
     * @param string $name       The element name
1299
     * @param string $label      The label for the form-element
1300
     * @param bool   $required   Optional. Is the form-element required (default=true)
1301
     * @param array  $attributes Optional. List of attributes for the form-element
1302
     */
1303
    public function addTextLettersOnly(
1304
        $name,
1305
        $label,
1306
        $required = false,
1307
        $attributes = []
1308
    ) {
1309
        $attributes = array_merge(
1310
            $attributes,
1311
            [
1312
                'pattern' => '[a-zA-ZñÑ]+',
1313
                'title' => get_lang('Only letters'),
1314
            ]
1315
        );
1316
1317
        $this->addElement(
1318
            'text',
1319
            $name,
1320
            [
1321
                $label,
1322
                get_lang('Only letters'),
1323
            ],
1324
            $attributes
1325
        );
1326
1327
        $this->applyFilter($name, 'trim');
1328
1329
        if ($required) {
1330
            $this->addRule($name, get_lang('Required field'), 'required');
1331
        }
1332
1333
        $this->addRule(
1334
            $name,
1335
            get_lang('Only letters'),
1336
            'regex',
1337
            '/^[a-zA-ZñÑ]+$/'
1338
        );
1339
    }
1340
1341
    /**
1342
     * @param string $name
1343
     * @param string $label
1344
     * @param array  $attributes
1345
     * @param bool   $required
1346
     *
1347
     * @return HTML_QuickForm_element
1348
     */
1349
    public function addNumeric($name, $label, $attributes = [], $required = false)
1350
    {
1351
        $element = $this->addElement('Number', $name, $label, $attributes);
1352
1353
        if ($required) {
1354
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1355
        }
1356
1357
        return $element;
1358
    }
1359
1360
    /**
1361
     * Adds a text field for alphanumeric characters to the form.
1362
     * A trim-filter is attached to the field.
1363
     *
1364
     * @param string $name       The element name
1365
     * @param string $label      The label for the form-element
1366
     * @param bool   $required   Optional. Is the form-element required (default=true)
1367
     * @param array  $attributes Optional. List of attributes for the form-element
1368
     */
1369
    public function addTextAlphanumeric(
1370
        $name,
1371
        $label,
1372
        $required = false,
1373
        $attributes = []
1374
    ) {
1375
        $attributes = array_merge(
1376
            $attributes,
1377
            [
1378
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1379
                'title' => get_lang('Only lettersAndNumbers'),
1380
            ]
1381
        );
1382
1383
        $this->addElement(
1384
            'text',
1385
            $name,
1386
            [
1387
                $label,
1388
                get_lang('Only lettersAndNumbers'),
1389
            ],
1390
            $attributes
1391
        );
1392
1393
        $this->applyFilter($name, 'trim');
1394
1395
        if ($required) {
1396
            $this->addRule($name, get_lang('Required field'), 'required');
1397
        }
1398
1399
        $this->addRule(
1400
            $name,
1401
            get_lang('Only lettersAndNumbers'),
1402
            'regex',
1403
            '/^[a-zA-Z0-9ÑÑ]+$/'
1404
        );
1405
    }
1406
1407
    /**
1408
     * @param string $name
1409
     * @param $label
1410
     * @param bool  $required
1411
     * @param array $attributes
1412
     * @param bool  $allowNegative
1413
     * @param int   $minValue
1414
     * @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...
1415
     */
1416
    public function addFloat(
1417
        $name,
1418
        $label,
1419
        $required = false,
1420
        $attributes = [],
1421
        $allowNegative = false,
1422
        $minValue = null,
1423
        $maxValue = null
1424
    ) {
1425
        $this->addElement(
1426
            'FloatNumber',
1427
            $name,
1428
            $label,
1429
            $attributes
1430
        );
1431
1432
        $this->applyFilter($name, 'trim');
1433
1434
        if ($required) {
1435
            $this->addRule($name, get_lang('Required field'), 'required');
1436
        }
1437
1438
        // Rule allows "," and "."
1439
        /*$this->addRule(
1440
            $name,
1441
            get_lang('Only numbers'),
1442
            'regex',
1443
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1444
        );*/
1445
1446
        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...
1447
            $this->addRule(
1448
                $name,
1449
                get_lang('Negative value'),
1450
                'compare',
1451
                '>=',
1452
                'server',
1453
                false,
1454
                false,
1455
                0
1456
            );
1457
        }
1458
1459
        if (!is_null($minValue)) {
1460
            $this->addRule(
1461
                $name,
1462
                get_lang('Under the minimum.'),
1463
                'compare',
1464
                '>=',
1465
                'server',
1466
                false,
1467
                false,
1468
                $minValue
1469
            );
1470
        }
1471
1472
        if (!is_null($maxValue)) {
1473
            $this->addRule(
1474
                $name,
1475
                get_lang('Value exceeds score.'),
1476
                'compare',
1477
                '<=',
1478
                'server',
1479
                false,
1480
                false,
1481
                $maxValue
1482
            );
1483
        }
1484
    }
1485
1486
    /**
1487
     * Adds a text field for letters and spaces to the form.
1488
     * A trim-filter is attached to the field.
1489
     *
1490
     * @param string $name       The element name
1491
     * @param string $label      The label for the form-element
1492
     * @param bool   $required   Optional. Is the form-element required (default=true)
1493
     * @param array  $attributes Optional. List of attributes for the form-element
1494
     */
1495
    public function addTextLettersAndSpaces(
1496
        $name,
1497
        $label,
1498
        $required = false,
1499
        $attributes = []
1500
    ) {
1501
        $attributes = array_merge(
1502
            $attributes,
1503
            [
1504
                'pattern' => '[a-zA-ZñÑ\s]+',
1505
                'title' => get_lang('Only lettersAndSpaces'),
1506
            ]
1507
        );
1508
1509
        $this->addElement(
1510
            'text',
1511
            $name,
1512
            [
1513
                $label,
1514
                get_lang('Only lettersAndSpaces'),
1515
            ],
1516
            $attributes
1517
        );
1518
1519
        $this->applyFilter($name, 'trim');
1520
1521
        if ($required) {
1522
            $this->addRule($name, get_lang('Required field'), 'required');
1523
        }
1524
1525
        $this->addRule(
1526
            $name,
1527
            get_lang('Only lettersAndSpaces'),
1528
            'regex',
1529
            '/^[a-zA-ZñÑ\s]+$/'
1530
        );
1531
    }
1532
1533
    /**
1534
     * Adds a text field for alphanumeric and spaces characters to the form.
1535
     * A trim-filter is attached to the field.
1536
     *
1537
     * @param string $name       The element name
1538
     * @param string $label      The label for the form-element
1539
     * @param bool   $required   Optional. Is the form-element required (default=true)
1540
     * @param array  $attributes Optional. List of attributes for the form-element
1541
     */
1542
    public function addTextAlphanumericAndSpaces(
1543
        $name,
1544
        $label,
1545
        $required = false,
1546
        $attributes = []
1547
    ) {
1548
        $attributes = array_merge(
1549
            $attributes,
1550
            [
1551
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1552
                'title' => get_lang('Only lettersAndNumbersAndSpaces'),
1553
            ]
1554
        );
1555
1556
        $this->addElement(
1557
            'text',
1558
            $name,
1559
            [
1560
                $label,
1561
                get_lang('Only lettersAndNumbersAndSpaces'),
1562
            ],
1563
            $attributes
1564
        );
1565
1566
        $this->applyFilter($name, 'trim');
1567
1568
        if ($required) {
1569
            $this->addRule($name, get_lang('Required field'), 'required');
1570
        }
1571
1572
        $this->addRule(
1573
            $name,
1574
            get_lang('Only lettersAndNumbersAndSpaces'),
1575
            'regex',
1576
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1577
        );
1578
    }
1579
1580
    /**
1581
     * @param string $url
1582
     * @param string $urlToRedirect after upload redirect to this page
1583
     */
1584
    public function addMultipleUpload($url, $urlToRedirect = '')
1585
    {
1586
        $inputName = 'input_file_upload';
1587
        $this->addMultipleUploadJavascript($url, $inputName, $urlToRedirect);
1588
1589
        $this->addHtml('
1590
            <div class="description-upload">
1591
            '.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!').'
1592
            </div>
1593
            <span class="btn btn-success fileinput-button">
1594
                <i class="glyphicon glyphicon-plus"></i>
1595
                <span>'.get_lang('Add files').'</span>
1596
                <!-- The file input field used as target for the file upload widget -->
1597
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1598
            </span>
1599
            <div id="dropzone">
1600
                <div class="button-load">
1601
                '.get_lang('Click or drag and drop files here to upload them').'
1602
                </div>
1603
            </div>
1604
            <br />
1605
            <!-- The global progress bar -->
1606
            <div id="progress" class="progress">
1607
                <div class="progress-bar progress-bar-success"></div>
1608
            </div>
1609
            <div id="files" class="files"></div>
1610
        ');
1611
    }
1612
1613
    /**
1614
     * @param string $elementName
1615
     * @param string $groupName   if element is inside a group
1616
     *
1617
     * @throws Exception
1618
     */
1619
    public function addPasswordRule($elementName, $groupName = '')
1620
    {
1621
        if ('true' == api_get_setting('security.check_password')) {
1622
            $message = get_lang('this password  is too simple. Use a pass like this').': '.api_generate_password();
1623
1624
            if (!empty($groupName)) {
1625
                $groupObj = $this->getElement($groupName);
1626
1627
                if ($groupObj instanceof HTML_QuickForm_group) {
1628
                    $elementName = $groupObj->getElementName($elementName);
1629
1630
                    if (false === $elementName) {
1631
                        throw new Exception("The $groupName doesn't have the element $elementName");
1632
                    }
1633
1634
                    $this->_rules[$elementName][] = [
1635
                        'type' => 'callback',
1636
                        'format' => 'api_check_password',
1637
                        'message' => $message,
1638
                        'validation' => '',
1639
                        'reset' => false,
1640
                        'group' => $groupName,
1641
                    ];
1642
                }
1643
            } else {
1644
                $this->addRule(
1645
                    $elementName,
1646
                    $message,
1647
                    'callback',
1648
                    'api_check_password'
1649
                );
1650
            }
1651
        }
1652
    }
1653
1654
    /**
1655
     * Add an element with user ID and avatar to the form.
1656
     * It needs a Chamilo\CoreBundle\Entity\User as value. The exported value is the Chamilo\CoreBundle\Entity\User ID.
1657
     *
1658
     * @see \UserAvatar
1659
     *
1660
     * @param string $name
1661
     * @param string $label
1662
     * @param string $imageSize Optional. Small, medium or large image
1663
     * @param string $subtitle  Optional. The subtitle for the field
1664
     *
1665
     * @return \UserAvatar
1666
     */
1667
    public function addUserAvatar($name, $label, $imageSize = 'small', $subtitle = '')
1668
    {
1669
        return $this->addElement('UserAvatar', $name, $label, ['image_size' => $imageSize, 'sub_title' => $subtitle]);
1670
    }
1671
1672
    /**
1673
     * @param array $typeList
1674
     */
1675
    public function addEmailTemplate($typeList)
1676
    {
1677
        $mailManager = new MailTemplateManager();
1678
        foreach ($typeList as $type) {
1679
            $list = $mailManager->get_all(
1680
                ['where' => ['type = ? AND url_id = ?' => [$type, api_get_current_access_url_id()]]]
1681
            );
1682
1683
            $options = [get_lang('Select')];
1684
            $name = $type;
1685
            $defaultId = '';
1686
            foreach ($list as $item) {
1687
                $options[$item['id']] = $item['name'];
1688
                $name = $item['name'];
1689
                if (empty($defaultId)) {
1690
                    $defaultId = 1 == $item['default_template'] ? $item['id'] : '';
1691
                }
1692
            }
1693
1694
            $url = api_get_path(WEB_AJAX_PATH).'mail.ajax.php?a=select_option';
1695
            $typeNoDots = 'email_template_option_'.str_replace('.tpl', '', $type);
1696
            $this->addSelect(
1697
                'email_template_option['.$type.']',
1698
                $name,
1699
                $options,
1700
                ['id' => $typeNoDots]
1701
            );
1702
1703
            $templateNoDots = 'email_template_'.str_replace('.tpl', '', $type);
1704
            $templateNoDotsBlock = 'email_template_block_'.str_replace('.tpl', '', $type);
1705
            $this->addHtml('<div id="'.$templateNoDotsBlock.'" style="display:none">');
1706
            $this->addTextarea(
1707
                $templateNoDots,
1708
                get_lang('Preview'),
1709
                ['disabled' => 'disabled ', 'id' => $templateNoDots, 'rows' => '5']
1710
            );
1711
            $this->addHtml('</div>');
1712
1713
            $this->addHtml("<script>
1714
            $(function() {
1715
                var defaultValue = '$defaultId';
1716
                $('#$typeNoDots').val(defaultValue);
1717
                $('#$typeNoDots').selectpicker('render');
1718
                if (defaultValue != '') {
1719
                    var selected = $('#$typeNoDots option:selected').val();
1720
                    $.ajax({
1721
                        url: '$url' + '&id=' + selected+ '&template_name=$type',
1722
                        success: function (data) {
1723
                            $('#$templateNoDots').html(data);
1724
                            $('#$templateNoDotsBlock').show();
1725
                            return;
1726
                        },
1727
                    });
1728
                }
1729
1730
                $('#$typeNoDots').on('change', function(){
1731
                    var selected = $('#$typeNoDots option:selected').val();
1732
                    $.ajax({
1733
                        url: '$url' + '&id=' + selected,
1734
                        success: function (data) {
1735
                            $('#$templateNoDots').html(data);
1736
                            $('#$templateNoDotsBlock').show();
1737
                            return;
1738
                        },
1739
                    });
1740
                });
1741
            });
1742
            </script>");
1743
        }
1744
    }
1745
1746
    /**
1747
     * Add email rule for an element.
1748
     */
1749
    public function addEmailRule(string $element)
1750
    {
1751
        $this->addRule(
1752
            $element,
1753
            get_lang('The email address is not complete or contains some invalid characters'),
1754
            'email'
1755
        );
1756
    }
1757
1758
    /**
1759
     * @param string $url           page that will handle the upload
1760
     * @param string $inputName
1761
     * @param string $urlToRedirect
1762
     */
1763
    private function addMultipleUploadJavascript($url, $inputName, $urlToRedirect = '')
1764
    {
1765
        $redirectCondition = '';
1766
        if (!empty($urlToRedirect)) {
1767
            $redirectCondition = "window.location.replace('$urlToRedirect'); ";
1768
        }
1769
        $icon = Display::return_icon('file_txt.gif');
1770
        $this->addHtml("
1771
        <script>
1772
        $(function () {
1773
            'use strict';
1774
            $('#".$this->getAttribute('id')."').submit(function() {
1775
                return false;
1776
            });
1777
1778
            $('#dropzone').on('click', function() {
1779
                $('#".$inputName."').click();
1780
            });
1781
1782
            var url = '".$url."';
1783
            var uploadButton = $('<button/>')
1784
                .addClass('btn btn-primary')
1785
                .prop('disabled', true)
1786
                .text('".addslashes(get_lang('Loading'))."')
1787
                .on('click', function () {
1788
                    var \$this = $(this),
1789
                    data = \$this.data();
1790
                    \$this
1791
                        .off('click')
1792
                        .text('".addslashes(get_lang('Cancel'))."')
1793
                        .on('click', function () {
1794
                            \$this.remove();
1795
                            data.abort();
1796
                        });
1797
                    data.submit().always(function () {
1798
                        \$this.remove();
1799
                    });
1800
                });
1801
1802
            $('#".$inputName."').fileupload({
1803
                url: url,
1804
                dataType: 'json',
1805
                // Enable image resizing, except for Android and Opera,
1806
                // which actually support image resizing, but fail to
1807
                // send Blob objects via XHR requests:
1808
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1809
                previewMaxWidth: 300,
1810
                previewMaxHeight: 169,
1811
                previewCrop: true,
1812
                dropzone: $('#dropzone'),
1813
            }).on('fileuploadadd', function (e, data) {
1814
                data.context = $('<div class=\"row\" />').appendTo('#files');
1815
                $.each(data.files, function (index, file) {
1816
                    var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);
1817
                    node.appendTo(data.context);
1818
                });
1819
            }).on('fileuploadprocessalways', function (e, data) {
1820
                var index = data.index,
1821
                    file = data.files[index],
1822
                    node = $(data.context.children()[index]);
1823
                if (file.preview) {
1824
                    data.context.prepend($('<div class=\"col-sm-4\">').html(file.preview));
1825
                } else {
1826
                    data.context.prepend($('<div class=\"col-sm-4\">').html('".$icon."'));
1827
                }
1828
                if (index + 1 === data.files.length) {
1829
                    data.context.find('button')
1830
                        .text('Upload')
1831
                        .prop('disabled', !!data.files.error);
1832
                }
1833
            }).on('fileuploadprogressall', function (e, data) {
1834
                var progress = parseInt(data.loaded / data.total * 100, 10);
1835
                $('#progress .progress-bar').css(
1836
                    'width',
1837
                    progress + '%'
1838
                );
1839
            }).on('fileuploaddone', function (e, data) {
1840
                $.each(data.result.files, function (index, file) {
1841
                    if (file.error) {
1842
                        var link = $('<div>')
1843
                            .attr({class : 'panel-image'})                            ;
1844
                        $(data.context.children()[index]).parent().wrap(link);
1845
                        // Update file name with new one from Chamilo
1846
                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1847
                        var message = $('<div class=\"col-sm-3\">').html(
1848
                            $('<span class=\"message-image-danger\"/>').text(file.error)
1849
                        );
1850
                        $(data.context.children()[index]).parent().append(message);
1851
1852
                        return;
1853
                    }
1854
                    if (file.url) {
1855
                        var link = $('<a>')
1856
                            .attr({target: '_blank', class : 'panel-image'})
1857
                            .prop('href', file.url);
1858
                        $(data.context.children()[index]).parent().wrap(link);
1859
                    }
1860
                    // Update file name with new one from Chamilo
1861
                    $(data.context.children()[index]).parent().find('.file_name').html(file.name);
1862
                    var message = $('<div class=\"col-sm-3\">').html(
1863
                        $('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('File upload succeeded!'))."')
1864
                    );
1865
                    $(data.context.children()[index]).parent().append(message);
1866
                });
1867
                $('#dropzone').removeClass('hover');
1868
                ".$redirectCondition."
1869
            }).on('fileuploadfail', function (e, data) {
1870
                $.each(data.files, function (index) {
1871
                    var failedMessage = '".addslashes(get_lang('The file upload has failed.'))."';
1872
                    var error = $('<div class=\"col-sm-3\">').html(
1873
                        $('<span class=\"alert alert-danger\"/>').text(failedMessage)
1874
                    );
1875
                    $(data.context.children()[index]).parent().append(error);
1876
                });
1877
                $('#dropzone').removeClass('hover');
1878
            }).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');
1879
1880
            $('#dropzone').on('dragover', function (e) {
1881
                // dragleave callback implementation
1882
                $('#dropzone').addClass('hover');
1883
            });
1884
1885
            $('#dropzone').on('dragleave', function (e) {
1886
                $('#dropzone').removeClass('hover');
1887
            });
1888
            $('.fileinput-button').hide();
1889
        });
1890
        </script>");
1891
    }
1892
}
1893
1894
/**
1895
 * Cleans HTML text filter.
1896
 *
1897
 * @param string $html HTML to clean
1898
 * @param int    $mode (optional)
1899
 *
1900
 * @return string The cleaned HTML
1901
 */
1902
function html_filter($html, $mode = NO_HTML)
1903
{
1904
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1905
    $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

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