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

1954
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1955
1956
    return $cleaned_html;
1957
}
1958
1959
function html_filter_teacher($html)
1960
{
1961
    return html_filter($html, TEACHER_HTML);
1962
}
1963
1964
function html_filter_student($html)
1965
{
1966
    return html_filter($html, STUDENT_HTML);
1967
}
1968
1969
function html_filter_teacher_fullpage($html)
1970
{
1971
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1972
}
1973
1974
function html_filter_student_fullpage($html)
1975
{
1976
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1977
}
1978
1979
/**
1980
 * Cleans mobile phone number text.
1981
 *
1982
 * @param string $mobilePhoneNumber Mobile phone number to clean
1983
 *
1984
 * @return string The cleaned mobile phone number
1985
 */
1986
function mobile_phone_number_filter($mobilePhoneNumber)
1987
{
1988
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1989
1990
    return ltrim($mobilePhoneNumber, '0');
1991
}
1992