Completed
Push — master ( 8b2aa0...562606 )
by Julito
09:06
created

FormValidator   F

Complexity

Total Complexity 140

Size/Duplication

Total Lines 1790
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 593
dl 0
loc 1790
rs 2
c 1
b 1
f 0
wmc 140

63 Methods

Rating   Name   Duplication   Size   Complexity  
A getDefaultElementTemplate() 0 3 1
A getFormTemplate() 0 3 1
A getLayout() 0 3 1
A setLayout() 0 3 1
A addText() 0 14 3
C __construct() 0 83 13
A addSelectLanguage() 0 3 1
A addCourseHiddenParams() 0 4 1
A addDateRangePicker() 0 8 2
A addDatePicker() 0 3 1
A addButtonImport() 0 11 1
A addButtonSearch() 0 7 2
A addButtonDelete() 0 11 1
A addLabel() 0 11 2
A addButtonMove() 0 11 1
A addButtonSend() 0 11 1
A addButtonNext() 0 10 1
A addSelectAjax() 0 12 2
A addHtml() 0 3 1
A addButtonFilter() 0 11 1
A addButtonDownload() 0 11 1
A addSelectFromCollection() 0 25 5
A addButtonCancel() 0 11 1
A addFile() 0 32 4
A addHeader() 0 4 2
A addButtonPreview() 0 11 1
A addRadio() 0 8 2
A addDateTimePicker() 0 3 1
A addButtonCopy() 0 11 1
A addButtonExport() 0 11 1
A addTextarea() 0 9 2
A addDateTimeRangePicker() 0 3 1
A addCheckBoxGroup() 0 15 2
A addButtonReset() 0 30 2
A addButtonUpdate() 0 11 1
B addPanelOption() 0 28 8
A addButtonUpload() 0 11 1
A addHidden() 0 3 1
A addSelect() 0 3 1
A addButton() 0 32 2
A addButtonSave() 0 11 1
A addButtonCreate() 0 11 1
A addCheckBox() 0 3 1
A getDefaultRenderer() 0 5 2
A addMultipleUpload() 0 18 1
B addEmailTemplate() 0 62 5
A addMultipleUploadJavascript() 0 109 2
A addUrl() 0 8 2
A addTextAlphanumeric() 0 35 2
A addProgress() 0 10 2
A addPasswordRule() 0 30 5
A addButtonAdvancedSettings() 0 5 2
A addFloat() 0 66 5
A addGeoLocationMapField() 0 40 5
F addHtmlEditor() 0 36 11
A addTextLettersAndSpaces() 0 35 2
A addTextAlphanumericAndSpaces() 0 35 2
A add_multiple_required_rule() 0 4 1
A return_form() 0 3 1
A addTextLettersOnly() 0 35 2
A returnForm() 0 30 5
A addUserAvatar() 0 3 1
A display() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like FormValidator often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormValidator, and based on these observations, apply Extract Interface, too.

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

1831
    $cleaned_html = /** @scrutinizer ignore-call */ kses($html, $allowed_tags);
Loading history...
1832
1833
    return $cleaned_html;
1834
}
1835
1836
function html_filter_teacher($html)
1837
{
1838
    return html_filter($html, TEACHER_HTML);
1839
}
1840
1841
function html_filter_student($html)
1842
{
1843
    return html_filter($html, STUDENT_HTML);
1844
}
1845
1846
function html_filter_teacher_fullpage($html)
1847
{
1848
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1849
}
1850
1851
function html_filter_student_fullpage($html)
1852
{
1853
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1854
}
1855
1856
/**
1857
 * Cleans mobile phone number text.
1858
 *
1859
 * @param string $mobilePhoneNumber Mobile phone number to clean
1860
 *
1861
 * @return string The cleaned mobile phone number
1862
 */
1863
function mobile_phone_number_filter($mobilePhoneNumber)
1864
{
1865
    $mobilePhoneNumber = str_replace(['+', '(', ')'], '', $mobilePhoneNumber);
1866
1867
    return ltrim($mobilePhoneNumber, '0');
1868
}
1869