Completed
Pull Request — 1.11.x (#1661)
by José
27:18
created

FormValidator::addTextAlphanumericAndSpaces()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 37
Code Lines 23

Duplication

Lines 37
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 23
nc 2
nop 4
dl 37
loc 37
rs 8.8571
c 0
b 0
f 0
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
    const LAYOUT_HORIZONTAL = 'horizontal';
11
    const LAYOUT_INLINE = 'inline';
12
    const LAYOUT_BOX = 'box';
13
    const LAYOUT_BOX_NO_LABEL = 'box-no-label';
14
15
    public $with_progress_bar = false;
16
    private $layout;
17
18
    /**
19
     * Constructor
20
     * @param string $name					Name of the form
21
     * @param string $method (optional			Method ('post' (default) or 'get')
22
     * @param string $action (optional			Action (default is $PHP_SELF)
23
     * @param string $target (optional			Form's target defaults to '_self'
24
     * @param mixed $attributes (optional)		Extra attributes for <form> tag
25
     * @param string $layout
26
     * @param bool $trackSubmit (optional)		Whether to track if the form was
27
     * submitted by adding a special hidden field (default = true)
28
     */
29
    public function __construct(
30
        $name,
31
        $method = 'post',
32
        $action = '',
33
        $target = '',
34
        $attributes = array(),
35
        $layout = self::LAYOUT_HORIZONTAL,
36
        $trackSubmit = true
37
    ) {
38
        // Default form class.
39
        if (is_array($attributes) && !isset($attributes['class']) || empty($attributes)) {
40
            $attributes['class'] = 'form-horizontal';
41
        }
42
43
        if (isset($attributes['class']) && strpos($attributes['class'], 'form-search') !== false) {
44
            $layout = 'inline';
45
        }
46
47
        $this->setLayout($layout);
48
49
        switch ($layout) {
50
            case self::LAYOUT_HORIZONTAL:
51
                $attributes['class'] = 'form-horizontal';
52
                break;
53
            case self::LAYOUT_INLINE:
54
            case self::LAYOUT_BOX:
55
                $attributes['class'] = 'form-inline';
56
                break;
57
        }
58
59
        parent::__construct($name, $method, $action, $target, $attributes, $trackSubmit);
60
61
        // Modify the default templates
62
        $renderer = & $this->defaultRenderer();
63
64
        // Form template
65
        $formTemplate = $this->getFormTemplate();
66
        $renderer->setFormTemplate($formTemplate);
67
68
        // Element template
69
        if (isset($attributes['class']) && $attributes['class'] == 'form-inline') {
70
            $elementTemplate = ' {label}  {element} ';
71
            $renderer->setElementTemplate($elementTemplate);
72
        } elseif (isset($attributes['class']) && $attributes['class'] == 'form-search') {
73
            $elementTemplate = ' {label}  {element} ';
74
            $renderer->setElementTemplate($elementTemplate);
75
        } else {
76
            $renderer->setElementTemplate($this->getDefaultElementTemplate());
77
78
            // Display a gray div in the buttons
79
            $templateSimple = '<div class="form-actions">{label} {element}</div>';
80
            $renderer->setElementTemplate($templateSimple, 'submit_in_actions');
81
82
            //Display a gray div in the buttons + makes the button available when scrolling
83
            $templateBottom = '<div class="form-actions bottom_actions bg-form">{label} {element}</div>';
84
            $renderer->setElementTemplate($templateBottom, 'submit_fixed_in_bottom');
85
86
            //When you want to group buttons use something like this
87
            /* $group = array();
88
              $group[] = $form->createElement('button', 'mark_all', get_lang('MarkAll'));
89
              $group[] = $form->createElement('button', 'unmark_all', get_lang('UnmarkAll'));
90
              $form->addGroup($group, 'buttons_in_action');
91
             */
92
            $renderer->setElementTemplate($templateSimple, 'buttons_in_action');
93
94
            $templateSimpleRight = '<div class="form-actions"> <div class="pull-right">{label} {element}</div></div>';
95
            $renderer->setElementTemplate($templateSimpleRight, 'buttons_in_action_right');
96
        }
97
98
        //Set Header template
99
        $renderer->setHeaderTemplate('<legend>{header}</legend>');
100
101
        //Set required field template
102
        $this->setRequiredNote('<span class="form_required">*</span> <small>' . get_lang('ThisFieldIsRequired') . '</small>');
103
        $noteTemplate = <<<EOT
104
	<div class="form-group">
105
		<div class="col-sm-offset-2 col-sm-10">{requiredNote}</div>
106
	</div>
107
EOT;
108
        $renderer->setRequiredNoteTemplate($noteTemplate);
109
    }
110
111
    /**
112
     * @return string
113
     */
114
    public function getFormTemplate()
115
    {
116
        return '<form{attributes}>
117
        <fieldset>
118
            {content}
119
        </fieldset>
120
        {hidden}
121
        </form>';
122
    }
123
124
    /**
125
     * @return string
126
     */
127
    public function getDefaultElementTemplate()
128
    {
129
        return '
130
            <div class="form-group {error_class}">
131
                <label {label-for} class="col-sm-2 control-label {extra_label_class}" >
132
                    <!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
133
                    {label}
134
                </label>
135
                <div class="col-sm-8">
136
                    {icon}
137
                    {element}
138
139
                    <!-- BEGIN label_2 -->
140
                        <p class="help-block">{label_2}</p>
141
                    <!-- END label_2 -->
142
143
                    <!-- BEGIN error -->
144
                        <span class="help-inline">{error}</span>
145
                    <!-- END error -->
146
                </div>
147
                <div class="col-sm-2">
148
                    <!-- BEGIN label_3 -->
149
                        {label_3}
150
                    <!-- END label_3 -->
151
                </div>
152
            </div>';
153
    }
154
155
    /**
156
     * @return string
157
     */
158
    public function getLayout()
159
    {
160
        return $this->layout;
161
    }
162
163
    /**
164
     * @param string $layout
165
     */
166
    public function setLayout($layout)
167
    {
168
        $this->layout = $layout;
169
    }
170
171
    /**
172
     * Adds a text field to the form.
173
     * A trim-filter is attached to the field.
174
     * @param string $label					The label for the form-element
175
     * @param string $name					The element name
176
     * @param bool   $required	(optional)	Is the form-element required (default=true)
177
     * @param array  $attributes (optional)	List of attributes for the form-element
178
     */
179
    public function addText($name, $label, $required = true, $attributes = array())
180
    {
181
        $this->addElement('text', $name, $label, $attributes);
182
        $this->applyFilter($name, 'trim');
183
        if ($required) {
184
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
185
        }
186
    }
187
188
    /**
189
     * The "date_range_picker" element creates 2 hidden fields
190
     * "elementName" + "_start"  and "elementName" + "_end"
191
     * For example if the name is "range", you will have 2 new fields
192
     * when executing $form->getSubmitValues()
193
     * "range_start" and "range_end"
194
     *
195
     * @param string $name
196
     * @param string $label
197
     * @param bool   $required
198
     * @param array  $attributes
199
     */
200 View Code Duplication
    public function addDateRangePicker($name, $label, $required = true, $attributes = array())
201
    {
202
        $this->addElement('date_range_picker', $name, $label, $attributes);
203
        $this->addElement('hidden', $name.'_start');
204
        $this->addElement('hidden', $name.'_end');
205
206
        if ($required) {
207
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
208
        }
209
    }
210
211
    /**
212
     * @param string $name
213
     * @param string $label
214
     * @param array $attributes
215
     *
216
     * @return mixed
217
     */
218
    public function addDatePicker($name, $label, $attributes = [])
219
    {
220
        return $this->addElement('DatePicker', $name, $label, $attributes);
221
    }
222
223
    /**
224
     * @param string $name
225
     * @param string $label
226
     * @param array $attributes
227
     *
228
     * @return mixed
229
     */
230
    public function addSelectLanguage($name, $label, $options = [], $attributes = [])
231
    {
232
        return $this->addElement('SelectLanguage', $name, $label, $options, $attributes);
233
    }
234
235
    /**
236
     * @param $name
237
     * @param $label
238
     * @param array $options
239
     * @param array $attributes
240
     * @throws
241
     */
242
    public function addSelectAjax($name, $label, $options = [], $attributes = [])
243
    {
244
        if (!isset($attributes['url'])) {
245
            throw new \Exception('select_ajax needs an URL');
246
        }
247
        $this->addElement(
248
            'select_ajax',
249
            $name,
250
            $label,
251
            $options,
252
            $attributes
253
        );
254
    }
255
256
    /**
257
     * @param string $name
258
     * @param string $label
259
     * @param array $attributes
260
     *
261
     * @return mixed
262
     */
263
    public function addDateTimePicker($name, $label, $attributes = [])
264
    {
265
        return $this->addElement('DateTimePicker', $name, $label, $attributes);
266
    }
267
268
    /**
269
     * @param string $name
270
     * @param string $value
271
     */
272
    public function addHidden($name, $value)
273
    {
274
        $this->addElement('hidden', $name, $value);
275
    }
276
277
    /**
278
     * @param string $name
279
     * @param string $label
280
     * @param array  $attributes
281
     *
282
     * @return HTML_QuickForm_textarea
283
     */
284
    public function addTextarea($name, $label, $attributes = array())
285
    {
286
        return $this->addElement('textarea', $name, $label, $attributes);
287
    }
288
289
    /**
290
     * @param string $name
291
     * @param string $label
292
     * @param string $icon font-awesome
293
     * @param string $style default|primary|success|info|warning|danger|link
294
     * @param string $size large|default|small|extra-small
295
     * @param string $class Example plus is transformed to icon fa fa-plus
296
     * @param array  $attributes
297
     *
298
     * @return HTML_QuickForm_button
299
     */
300
    public function addButton(
301
        $name,
302
        $label,
303
        $icon = 'check',
304
        $style = 'default',
305
        $size = 'default',
306
        $class = null,
307
        $attributes = array(),
308
        $createElement = false
309
    ) {
310
        if ($createElement) {
311
            return $this->createElement(
312
                'button',
313
                $name,
314
                $label,
315
                $icon,
316
                $style,
317
                $size,
318
                $class,
319
                $attributes
320
            );
321
        }
322
323
        return $this->addElement(
324
            'button',
325
            $name,
326
            $label,
327
            $icon,
328
            $style,
329
            $size,
330
            $class,
331
            $attributes
332
        );
333
    }
334
335
    /**
336
     * Returns a button with the primary color and a check mark
337
     * @param string $label Text appearing on the button
338
     * @param string $name Element name (for form treatment purposes)
339
     * @param bool $createElement Whether to use the create or add method
340
     *
341
     * @return HTML_QuickForm_button
342
     */
343
    public function addButtonSave($label, $name = 'submit', $createElement = false)
344
    {
345
        return $this->addButton(
346
            $name,
347
            $label,
348
            'check',
349
            'primary',
350
            null,
351
            null,
352
            array(),
353
            $createElement
354
        );
355
    }
356
357
    /**
358
     * Returns a cancel button
359
     * @param string $label Text appearing on the button
360
     * @param string $name Element name (for form treatment purposes)
361
     * @param bool $createElement Whether to use the create or add method
362
     *
363
     * @return HTML_QuickForm_button
364
     */
365
    public function addButtonCancel($label, $name = 'submit', $createElement = false)
366
    {
367
        return $this->addButton(
368
            $name,
369
            $label,
370
            'times',
371
            'danger',
372
            null,
373
            null,
374
            array(),
375
            $createElement
376
        );
377
    }
378
379
    /**
380
     * Returns a button with the primary color and a "plus" icon
381
     * @param string $label Text appearing on the button
382
     * @param string $name Element name (for form treatment purposes)
383
     * @param bool $createElement Whether to use the create or add method
384
     * @param array $attributes Additional attributes
385
     *
386
     * @return HTML_QuickForm_button
387
     */
388
    public function addButtonCreate($label, $name = 'submit', $createElement = false, $attributes = array())
389
    {
390
        return $this->addButton(
391
            $name,
392
            $label,
393
            'plus',
394
            'primary',
395
            null,
396
            null,
397
            $attributes,
398
            $createElement
399
        );
400
    }
401
402
    /**
403
     * Returns a button with the primary color and a pencil icon
404
     * @param string $label Text appearing on the button
405
     * @param string $name Element name (for form treatment purposes)
406
     * @param bool $createElement Whether to use the create or add method
407
     * @return HTML_QuickForm_button
408
     */
409
    public function addButtonUpdate($label, $name = 'submit', $createElement = false)
410
    {
411
        return $this->addButton(
412
            $name,
413
            $label,
414
            'pencil',
415
            'primary',
416
            null,
417
            null,
418
            array(),
419
            $createElement
420
        );
421
    }
422
423
    /**
424
     * Returns a button with the danger color and a trash icon
425
     * @param string $label Text appearing on the button
426
     * @param string $name Element name (for form treatment purposes)
427
     * @param bool $createElement Whether to use the create or add method
428
     *
429
     * @return HTML_QuickForm_button
430
     */
431
    public function addButtonDelete($label, $name = 'submit', $createElement = false)
432
    {
433
        return $this->addButton(
434
            $name,
435
            $label,
436
            'trash',
437
            'danger',
438
            null,
439
            null,
440
            array(),
441
            $createElement
442
        );
443
    }
444
445
    /**
446
     * Returns a button with the primary color and a paper-plane icon
447
     * @param string $label Text appearing on the button
448
     * @param string $name Element name (for form treatment purposes)
449
     * @param bool $createElement Whether to use the create or add method
450
     *
451
     * @return HTML_QuickForm_button
452
     */
453
    public function addButtonSend($label, $name = 'submit', $createElement = false, $attributes = array())
454
    {
455
        return $this->addButton(
456
            $name,
457
            $label,
458
            'paper-plane',
459
            'primary',
460
            null,
461
            null,
462
            $attributes,
463
            $createElement
464
        );
465
    }
466
467
    /**
468
     * Returns a button with the default (grey?) color and a magnifier icon
469
     * @param string $label Text appearing on the button
470
     * @param string $name Element name (for form treatment purposes)
471
     *
472
     * @return HTML_QuickForm_button
473
     */
474
    public function addButtonSearch($label = null, $name = 'submit')
475
    {
476
        if (empty($label)) {
477
            $label = get_lang('Search');
478
        }
479
480
        return $this->addButton($name, $label, 'search', 'default');
481
    }
482
483
    /**
484
     * Returns a button with the primary color and a right-pointing arrow icon
485
     * @param string $label Text appearing on the button
486
     * @param string $name Element name (for form treatment purposes)
487
     * @param array $attributes Additional attributes
488
     * @return HTML_QuickForm_button
489
     */
490
    public function addButtonNext($label, $name = 'submit', $attributes = array())
491
    {
492
        return $this->addButton($name, $label, 'arrow-right', 'primary', null, null, $attributes);
493
    }
494
495
    /**
496
     * Returns a button with the primary color and a check mark icon
497
     * @param string $label Text appearing on the button
498
     * @param string $name Element name (for form treatment purposes)
499
     * @param bool $createElement Whether to use the create or add method
500
     * @return HTML_QuickForm_button
501
     */
502
    public function addButtonImport($label, $name = 'submit', $createElement = false)
503
    {
504
        return $this->addButton(
505
            $name,
506
            $label,
507
            'check',
508
            'primary',
509
            null,
510
            null,
511
            array(),
512
            $createElement
513
        );
514
    }
515
516
    /**
517
     * Returns a button with the primary color and a check-mark icon
518
     * @param string $label Text appearing on the button
519
     * @param string $name Element name (for form treatment purposes)
520
     * @param bool $createElement Whether to use the create or add method
521
     * @return HTML_QuickForm_button
522
     */
523
    public function addButtonExport($label, $name = 'submit', $createElement = false)
524
    {
525
        return $this->addButton(
526
            $name,
527
            $label,
528
            'check',
529
            'primary',
530
            null,
531
            null,
532
            array(),
533
            $createElement
534
        );
535
    }
536
537
    /**
538
     * Shortcut to filter button
539
     * @param string $label Text appearing on the button
540
     * @param string $name Element name (for form treatment purposes)
541
     * @param bool $createElement Whether to use the create or add method
542
     * @return HTML_QuickForm_button
543
     */
544
    public function addButtonFilter($label, $name = 'submit', $createElement = false)
545
    {
546
        return $this->addButton(
547
            $name,
548
            $label,
549
            'filter',
550
            'primary',
551
            null,
552
            null,
553
            array(),
554
            $createElement
555
        );
556
    }
557
558
    /**
559
     * Shortcut to reset button
560
     * @param string $label Text appearing on the button
561
     * @param string $name Element name (for form treatment purposes)
562
     * @param bool $createElement Whether to use the create or add method
563
     * @return HTML_QuickForm_button
564
     */
565
    public function addButtonReset($label, $name = 'reset', $createElement = false)
566
    {
567
        $icon = 'eraser';
568
        $style = 'default';
569
        $size = 'default';
570
        $class = null;
571
        $attributes = array();
572
573
        if ($createElement) {
574
            return $this->createElement(
575
                'reset',
576
                $name,
577
                $label,
578
                $icon,
579
                $style,
580
                $size,
581
                $class,
582
                $attributes
583
            );
584
        }
585
586
        return $this->addElement(
587
            'reset',
588
            $name,
589
            $label,
590
            $icon,
591
            $style,
592
            $size,
593
            $class,
594
            $attributes
595
        );
596
    }
597
598
    /**
599
     * Returns a button with the primary color and an upload icon
600
     * @param string $label Text appearing on the button
601
     * @param string $name Element name (for form treatment purposes)
602
     * @param bool $createElement Whether to use the create or add method
603
     *
604
     * @return HTML_QuickForm_button
605
     */
606
    public function addButtonUpload($label, $name = 'submit', $createElement = false)
607
    {
608
        return $this->addButton(
609
            $name,
610
            $label,
611
            'upload',
612
            'primary',
613
            null,
614
            null,
615
            array(),
616
            $createElement
617
        );
618
    }
619
620
    /**
621
     * Returns a button with the primary color and a download icon
622
     * @param string $label Text appearing on the button
623
     * @param string $name Element name (for form treatment purposes)
624
     * @param bool $createElement Whether to use the create or add method
625
     *
626
     * @return HTML_QuickForm_button
627
     */
628
    public function addButtonDownload($label, $name = 'submit', $createElement = false)
629
    {
630
        return $this->addButton(
631
            $name,
632
            $label,
633
            'download',
634
            'primary',
635
            null,
636
            null,
637
            array(),
638
            $createElement
639
        );
640
    }
641
642
    /**
643
     * Returns a button with the primary color and a magnifier icon
644
     * @param string $label Text appearing on the button
645
     * @param string $name Element name (for form treatment purposes)
646
     * @param bool $createElement Whether to use the create or add method
647
     *
648
     * @return HTML_QuickForm_button
649
     */
650 View Code Duplication
    public function addButtonPreview($label, $name = 'submit', $createElement = false)
651
    {
652
        return $this->addButton(
653
            $name,
654
            $label,
655
            'search',
656
            'primary',
657
            null,
658
            null,
659
            array(),
660
            $createElement
661
        );
662
    }
663
664
    /**
665
     * Returns a button with the primary color and a copy (double sheet) icon
666
     * @param string $label Text appearing on the button
667
     * @param string $name Element name (for form treatment purposes)
668
     * @param bool $createElement Whether to use the create or add method
669
     *
670
     * @return HTML_QuickForm_button
671
     */
672 View Code Duplication
    public function addButtonCopy($label, $name = 'submit', $createElement = false)
673
    {
674
        return $this->addButton(
675
            $name,
676
            $label,
677
            'copy',
678
            'primary',
679
            null,
680
            null,
681
            array(),
682
            $createElement
683
        );
684
    }
685
686
    /**
687
     * @param string $name
688
     * @param string $label
689
     * @param string $text
690
     * @param array  $attributes
691
     *
692
     * @return HTML_QuickForm_checkbox
693
     */
694
    public function addCheckBox($name, $label, $text = '', $attributes = array())
695
    {
696
        return $this->addElement('checkbox', $name, $label, $text, $attributes);
697
    }
698
699
    /**
700
     * @param string $name
701
     * @param string $label
702
     * @param array  $options
703
     * @param array  $attributes
704
     *
705
     * @return HTML_QuickForm_group
706
     */
707 View Code Duplication
    public function addCheckBoxGroup($name, $label, $options = array(), $attributes = array())
708
    {
709
        $group = array();
710
        foreach ($options as $value => $text) {
711
            $attributes['value'] = $value;
712
            $group[] = $this->createElement('checkbox', $value, null, $text, $attributes);
713
        }
714
715
        return $this->addGroup($group, $name, $label);
716
    }
717
718
    /**
719
     * @param string $name
720
     * @param string $label
721
     * @param array  $options
722
     * @param array  $attributes
723
     *
724
     * @return HTML_QuickForm_radio
725
     */
726 View Code Duplication
    public function addRadio($name, $label, $options = array(), $attributes = array())
727
    {
728
        $group = array();
729
        foreach ($options as $key => $value) {
730
            $group[] = $this->createElement('radio', null, null, $value, $key, $attributes);
731
        }
732
733
        return $this->addGroup($group, $name, $label);
734
    }
735
736
    /**
737
     * @param string $name
738
     * @param string $label
739
     * @param array  $options
740
     * @param array  $attributes
741
     *
742
     * @return HTML_QuickForm_select
743
     */
744
    public function addSelect($name, $label, $options = array(), $attributes = array())
745
    {
746
        return $this->addElement('select', $name, $label, $options, $attributes);
747
    }
748
749
    /**
750
     * @param $name
751
     * @param $label
752
     * @param $collection
753
     * @param array $attributes
754
     * @param bool $addNoneOption
755
     * @param string $textCallable set a function getStringValue() by default __toString()
756
     *
757
     * @return HTML_QuickForm_element
758
     */
759
    public function addSelectFromCollection(
760
        $name,
761
        $label,
762
        $collection,
763
        $attributes = array(),
764
        $addNoneOption = false,
765
        $textCallable = ''
766
    ) {
767
        $options = [];
768
769
        if ($addNoneOption) {
770
            $options[0] = get_lang('None');
771
        }
772
773
        if (!empty($collection)) {
774
            foreach ($collection as $item) {
775
                $text = $item;
776
                if (!empty($textCallable)) {
777
                    $text = $item->$textCallable();
778
                }
779
                $options[$item->getId()] = $text;
780
            }
781
        }
782
        return $this->addElement('select', $name, $label, $options, $attributes);
783
    }
784
785
    /**
786
     * @param string $label
787
     * @param string $text
788
     *
789
     * @return HTML_QuickForm_label
790
     */
791
    public function addLabel($label, $text)
792
    {
793
        return $this->addElement('label', $label, $text);
794
    }
795
796
    /**
797
     * @param string $text
798
     */
799
    public function addHeader($text)
800
    {
801
        $this->addElement('header', $text);
802
    }
803
804
    /**
805
     * @param string $name
806
     * @param string $label
807
     * @param array  $attributes
808
     * @throws Exception if the file doesn't have an id
809
     */
810
    public function addFile($name, $label, $attributes = array())
811
    {
812
        $element = $this->addElement('file', $name, $label, $attributes);
813
        if (isset($attributes['crop_image'])) {
814
            $id = $element->getAttribute('id');
815
            if (empty($id)) {
816
                throw new Exception('If you use the crop functionality the element must have an id');
817
            }
818
            $this->addHtml('
819
                <div class="form-group">
820
                <label for="cropImage" id="'.$id.'_label_crop_image" class="col-sm-2 control-label"></label>
821
                <div class="col-sm-8">
822
                <div id="'.$id.'_crop_image" class="cropCanvas">
823
                <img id="'.$id.'_preview_image">
824
                </div>
825
                <div>
826
                <button class="btn btn-primary hidden" name="cropButton" id="'.$id.'_crop_button" >
827
                    <em class="fa fa-crop"></em> '.
828
                    get_lang('CropYourPicture').'
829
                </button>
830
                </div>
831
                </div>
832
                </div>'
833
            );
834
            $this->addHidden($id.'_crop_result', '');
835
            $this->addHidden($id.'_crop_image_base_64', '');
836
        }
837
    }
838
839
    /**
840
     * @param string $snippet
841
     */
842
    public function addHtml($snippet)
843
    {
844
        $this->addElement('html', $snippet);
845
    }
846
847
    /**
848
     * Adds a HTML-editor to the form
849
     * @param string $name
850
     * @param string $label The label for the form-element
851
     * @param bool   $required (optional) Is the form-element required (default=true)
852
     * @param bool   $fullPage (optional) When it is true, the editor loads completed html code for a full page.
853
     * @param array  $config (optional) Configuration settings for the online editor.
854
     * @param bool   $style
855
     */
856
    public function addHtmlEditor($name, $label, $required = true, $fullPage = false, $config = array(), $style = false)
857
    {
858
        $config['rows'] = isset($config['rows']) ? $config['rows'] : 15;
859
        $config['cols'] = isset($config['cols']) ? $config['cols'] : 80;
860
        $this->addElement('html_editor', $name, $label, $config, $style);
861
        $this->applyFilter($name, 'trim');
862
        if ($required) {
863
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
864
        }
865
866
        /** @var HtmlEditor $element */
867
        $element = $this->getElement($name);
868
869
        if ($style) {
870
            $config['style'] = true;
871
        }
872
        if ($fullPage) {
873
            $config['fullPage'] = true;
874
        }
875
876
        if ($element->editor) {
877
            $element->editor->processConfig($config);
878
        }
879
    }
880
881
    /**
882
     * Adds a Google Maps Geolocalization field to the form
883
     *
884
     * @param $name
885
     * @param $label
886
     */
887
    public function addGeoLocationMapField($name, $label)
888
    {
889
        $gMapsPlugin = GoogleMapsPlugin::create();
890
        $geolocalization = $gMapsPlugin->get('enable_api') === 'true';
891
892
        if ($geolocalization) {
893
            $gmapsApiKey = $gMapsPlugin->get('api_key');
894
            $this->addHtml('<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?key='. $gmapsApiKey . '" ></script>');
895
        }
896
        $this->addElement(
897
            'text',
898
            $name,
899
            $label,
900
            ['id' => $name]
901
        );
902
        $this->applyFilter($name, 'stripslashes');
903
        $this->applyFilter($name, 'trim');
904
        $this->addHtml('
905
                            <div class="form-group">
906
                                <label for="geolocalization_'.$name.'" class="col-sm-2 control-label"></label>
907
                                <div class="col-sm-8">
908
                                    <button class="null btn btn-default " id="geolocalization_'.$name.'" name="geolocalization_'.$name.'" type="submit"><em class="fa fa-map-marker"></em> '.get_lang('Geolocalization').'</button>
909
                                    <button class="null btn btn-default " id="myLocation_'.$name.'" name="myLocation_'.$name.'" type="submit"><em class="fa fa-crosshairs"></em> '.get_lang('MyLocation').'</button>
910
                                </div>
911
                            </div>
912
                        ');
913
914
        $this->addHtml('
915
                            <div class="form-group">
916
                                <label for="map_'.$name.'" class="col-sm-2 control-label">
917
                                    '.$label.' - '.get_lang('Map').'
918
                                </label>
919
                                <div class="col-sm-8">
920
                                    <div name="map_'.$name.'" id="map_'.$name.'" style="width:100%; height:300px;">
921
                                    </div>
922
                                </div>
923
                            </div>
924
                        ');
925
926
        $this->addHtml(
927
            '<script>
928
                $(document).ready(function() {
929
930
                    if (typeof google === "object") {
931
932
                        var address = $("#' . $name . '").val();
933
                        initializeGeo'.$name.'(address, false);
934
935
                        $("#geolocalization_'.$name.'").on("click", function() {
936
                            var address = $("#'.$name.'").val();
937
                            initializeGeo'.$name.'(address, false);
938
                            return false;
939
                        });
940
941
                        $("#myLocation_'.$name.'").on("click", function() {
942
                            myLocation'.$name.'();
943
                            return false;
944
                        });
945
946
                        $("#'.$name.'").keypress(function (event) {
947
                            if (event.which == 13) {
948
                                $("#geolocalization_'.$name.'").click();
949
                                return false;
950
                            }
951
                        });
952
953
                    } else {
954
                        $("#map_'.$name.'").html("<div class=\"alert alert-info\">' . get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap') . '</div>");
955
                    }
956
957
                });
958
959
                function myLocation'.$name.'() {
960
                    if (navigator.geolocation) {
961
                        var geoPosition = function(position) {
962
                            var lat = position.coords.latitude;
963
                            var lng = position.coords.longitude;
964
                            var latLng = new google.maps.LatLng(lat, lng);
965
                            initializeGeo'.$name.'(false, latLng)
966
                        };
967
968
                        var geoError = function(error) {
969
                            alert("Geocode ' . get_lang('Error') . ': " + error);
970
                        };
971
972
                        var geoOptions = {
973
                            enableHighAccuracy: true
974
                        };
975
976
                        navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
977
                    }
978
                }
979
980
                function initializeGeo'.$name.'(address, latLng) {
981
                    var geocoder = new google.maps.Geocoder();
982
                    var latlng = new google.maps.LatLng(-34.397, 150.644);
983
                    var myOptions = {
984
                        zoom: 15,
985
                        center: latlng,
986
                        mapTypeControl: true,
987
                        mapTypeControlOptions: {
988
                            style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
989
                        },
990
                        navigationControl: true,
991
                        mapTypeId: google.maps.MapTypeId.ROADMAP
992
                    };
993
994
                    map_'.$name.' = new google.maps.Map(document.getElementById("map_'.$name.'"), myOptions);
995
996
                    var parameter = address ? { "address": address } : latLng ? { "latLng": latLng } : false;
997
998
                    if (geocoder && parameter) {
999
                        geocoder.geocode(parameter, function(results, status) {
1000
                            if (status == google.maps.GeocoderStatus.OK) {
1001
                                if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
1002
                                    map_'.$name.'.setCenter(results[0].geometry.location);
1003
                                    if (!address) {
1004
                                        $("#'.$name.'").val(results[0].formatted_address);
1005
                                    }
1006
                                    var infowindow = new google.maps.InfoWindow({
1007
                                        content: "<b>" + $("#'.$name.'").val() + "</b>",
1008
                                        size: new google.maps.Size(150, 50)
1009
                                    });
1010
1011
                                    var marker = new google.maps.Marker({
1012
                                        position: results[0].geometry.location,
1013
                                        map: map_'.$name.',
1014
                                        title: $("#'.$name.'").val()
1015
                                    });
1016
                                    google.maps.event.addListener(marker, "click", function() {
1017
                                        infowindow.open(map_'.$name.', marker);
1018
                                    });
1019
                                } else {
1020
                                    alert("' . get_lang("NotFound") . '");
1021
                                }
1022
1023
                            } else {
1024
                                alert("Geocode ' . get_lang('Error') . ': ' . get_lang("AddressField") . ' ' . get_lang("NotFound") . '");
1025
                            }
1026
                        });
1027
                    }
1028
                }
1029
            </script>
1030
        ');
1031
1032
    }
1033
1034
    /**
1035
     * @param string $name
1036
     * @param string $label
1037
     *
1038
     * @return mixed
1039
     */
1040
    public function addButtonAdvancedSettings($name, $label = '')
1041
    {
1042
        $label = !empty($label) ? $label : get_lang('AdvancedParameters');
1043
1044
        return $this->addElement('advanced_settings', $name, $label);
1045
    }
1046
1047
    /**
1048
     * Adds a progress loading image to the form.
1049
     *
1050
     */
1051
    public function addProgress($delay = 2, $label = '')
1052
    {
1053
        if (empty($label)) {
1054
            $label = get_lang('PleaseStandBy');
1055
        }
1056
        $this->with_progress_bar = true;
1057
        $id = $this->getAttribute('id');
1058
1059
        $this->updateAttributes("onsubmit=\"javascript: addProgress('" . $id . "')\"");
1060
        $this->addHtml('<script language="javascript" src="' . api_get_path(WEB_LIBRARY_PATH) . 'javascript/upload.js" type="text/javascript"></script>');
1061
    }
1062
1063
    /**
1064
     * This function has been created for avoiding changes directly within QuickForm class.
1065
     * When we use it, the element is threated as 'required' to be dealt during validation.
1066
     * @param array $element The array of elements
0 ignored issues
show
Documentation introduced by
There is no parameter named $element. Did you maybe mean $elements?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
1067
     * @param string $message The message displayed
1068
     */
1069
    public function add_multiple_required_rule($elements, $message)
1070
    {
1071
        $this->_required[] = $elements[0];
1072
        $this->addRule($elements, $message, 'multiple_required');
1073
    }
1074
1075
    /**
1076
     * Displays the form.
1077
     * If an element in the form didn't validate, an error message is showed
1078
     * asking the user to complete the form.
1079
     */
1080
    public function display()
1081
    {
1082
        echo $this->returnForm();
1083
    }
1084
1085
    /**
1086
     * Returns the HTML code of the form.
1087
     * @return string $return_value HTML code of the form
1088
     */
1089
    public function returnForm()
1090
    {
1091
        $returnValue = '';
1092
1093
        /** @var HTML_QuickForm_element $element */
1094
        foreach ($this->_elements as $element) {
1095
            $elementError = parent::getElementError($element->getName());
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getElementError() instead of returnForm()). Are you sure this is correct? If so, you might want to change this to $this->getElementError().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
1096
            if (!is_null($elementError)) {
1097
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1098
                break;
1099
            }
1100
        }
1101
1102
        $returnValue .= parent::toHtml();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (toHtml() instead of returnForm()). Are you sure this is correct? If so, you might want to change this to $this->toHtml().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
1103
        // Add div-element which is to hold the progress bar
1104
        $id = $this->getAttribute('id');
1105
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1106
            $icon = Display::return_icon('progress_bar.gif');
1107
1108
            // @todo improve UI
1109
            $returnValue .= '<br />
1110
1111
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1112
                '.$icon.'
1113
            </div>
1114
            ';
1115
        }
1116
1117
        return $returnValue;
1118
    }
1119
1120
    /**
1121
     * Returns the HTML code of the form.
1122
     * If an element in the form didn't validate, an error message is showed
1123
     * asking the user to complete the form.
1124
     *
1125
     * @return string $return_value HTML code of the form
1126
     *
1127
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1128
     * @author Julio Montoya
1129
     * @deprecated use returnForm()
1130
     */
1131
    public function return_form()
1132
    {
1133
        return $this->returnForm();
1134
    }
1135
1136
    /**
1137
     * Create a form validator based on an array of form data:
1138
     *
1139
     *         array(
1140
     *             'name' => 'zombie_report_parameters',    //optional
1141
     *             'method' => 'GET',                       //optional
1142
     *             'items' => array(
1143
     *                 array(
1144
     *                     'name' => 'ceiling',
1145
     *                     'label' => 'Ceiling',            //optional
1146
     *                     'type' => 'date',
1147
     *                     'default' => date()              //optional
1148
     *                 ),
1149
     *                 array(
1150
     *                     'name' => 'active_only',
1151
     *                     'label' => 'ActiveOnly',
1152
     *                     'type' => 'checkbox',
1153
     *                     'default' => true
1154
     *                 ),
1155
     *                 array(
1156
     *                     'name' => 'submit_button',
1157
     *                     'type' => 'style_submit_button',
1158
     *                     'value' => get_lang('Search'),
1159
     *                     'attributes' => array('class' => 'search')
1160
     *                 )
1161
     *             )
1162
     *         );
1163
     *
1164
     * @param array $form_data
1165
     * @deprecated use normal FormValidator construct
1166
     *
1167
     * @return FormValidator
1168
     */
1169
    public static function create($form_data)
1170
    {
1171
        if (empty($form_data)) {
1172
            return null;
1173
        }
1174
        $form_name = isset($form_data['name']) ? $form_data['name'] : 'form';
1175
        $form_method = isset($form_data['method']) ? $form_data['method'] : 'POST';
1176
        $form_action = isset($form_data['action']) ? $form_data['action'] : '';
1177
        $form_target = isset($form_data['target']) ? $form_data['target'] : '';
1178
        $form_attributes = isset($form_data['attributes']) ? $form_data['attributes'] : null;
1179
        $form_track_submit = isset($form_data['track_submit']) ? $form_data['track_submit'] : true;
1180
        $reset = null;
1181
        $result = new FormValidator($form_name, $form_method, $form_action, $form_target, $form_attributes, $form_track_submit);
1182
1183
        $defaults = array();
1184
        foreach ($form_data['items'] as $item) {
1185
            $name = $item['name'];
1186
            $type = isset($item['type']) ? $item['type'] : 'text';
1187
            $label = isset($item['label']) ? $item['label'] : '';
1188
            if ($type == 'wysiwyg') {
1189
                $element = $result->addHtmlEditor($name, $label);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $element is correct as $result->addHtmlEditor($name, $label) (which targets FormValidator::addHtmlEditor()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
1190
            } else {
1191
                $element = $result->addElement($type, $name, $label);
1192
            }
1193
            if (isset($item['attributes'])) {
1194
                $attributes = $item['attributes'];
1195
                $element->setAttributes($attributes);
1196
            }
1197
            if (isset($item['value'])) {
1198
                $value = $item['value'];
1199
                $element->setValue($value);
1200
            }
1201
            if (isset($item['default'])) {
1202
                $defaults[$name] = $item['default'];
1203
            }
1204
            if (isset($item['rules'])) {
1205
                $rules = $item['rules'];
1206
                foreach ($rules as $rule) {
1207
                    $message = $rule['message'];
1208
                    $type = $rule['type'];
1209
                    $format = isset($rule['format']) ? $rule['format'] : null;
1210
                    $validation = isset($rule['validation']) ? $rule['validation'] : 'server';
1211
                    $force = isset($rule['force']) ? $rule['force'] : false;
1212
                    $result->addRule($name, $message, $type, $format, $validation, $reset, $force);
1213
                }
1214
            }
1215
        }
1216
        $result->setDefaults($defaults);
1217
1218
        return $result;
1219
    }
1220
1221
    /**
1222
     * @return HTML_QuickForm_Renderer_Default
1223
     */
1224
    public static function getDefaultRenderer()
1225
    {
1226
        return
1227
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1228
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1229
    }
1230
1231
    /**
1232
     * Adds a input of type url to the form.
1233
     * @param type $name The label for the form-element
1234
     * @param type $label The element name
1235
     * @param type $required Optional. Is the form-element required (default=true)
1236
     * @param type $attributes Optional. List of attributes for the form-element
1237
     */
1238 View Code Duplication
    public function addUrl($name, $label, $required = true, $attributes = array())
1239
    {
1240
        $this->addElement('url', $name, $label, $attributes);
1241
        $this->applyFilter($name, 'trim');
1242
        $this->addRule($name, get_lang('InsertAValidUrl'), 'url');
1243
1244
        if ($required) {
1245
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1246
        }
1247
    }
1248
1249
    /**
1250
     * Adds a text field for letters to the form.
1251
     * A trim-filter is attached to the field.
1252
     * @param string $name The element name
1253
     * @param string $label The label for the form-element
1254
     * @param bool $required Optional. Is the form-element required (default=true)
1255
     * @param array $attributes Optional. List of attributes for the form-element
1256
     */
1257 View Code Duplication
    public function addTextLettersOnly(
1258
        $name,
1259
        $label,
1260
        $required = false,
1261
        $attributes = []
1262
    ) {
1263
        $attributes = array_merge(
1264
            $attributes,
1265
            [
1266
                'pattern' => '[a-zA-ZñÑ]+',
1267
                'title' => get_lang('OnlyLetters')
1268
            ]
1269
        );
1270
1271
        $this->addElement(
1272
            'text',
1273
            $name,
1274
            [
1275
                $label,
1276
                get_lang('OnlyLetters')
1277
            ],
1278
            $attributes
1279
        );
1280
1281
        $this->applyFilter($name, 'trim');
1282
1283
        if ($required) {
1284
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1285
        }
1286
1287
        $this->addRule(
1288
            $name,
1289
            get_lang('OnlyLetters'),
1290
            'regex',
1291
            '/^[a-zA-ZñÑ]+$/'
1292
        );
1293
    }
1294
1295
    /**
1296
     * Adds a text field for alphanumeric characters to the form.
1297
     * A trim-filter is attached to the field.
1298
     * @param string $name The element name
1299
     * @param string $label The label for the form-element
1300
     * @param bool $required Optional. Is the form-element required (default=true)
1301
     * @param array $attributes Optional. List of attributes for the form-element
1302
     */
1303 View Code Duplication
    public function addTextAlphanumeric(
1304
        $name,
1305
        $label,
1306
        $required = false,
1307
        $attributes = []
1308
    ) {
1309
        $attributes = array_merge(
1310
            $attributes,
1311
            [
1312
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1313
                'title' => get_lang('OnlyLettersAndNumbers')
1314
            ]
1315
        );
1316
1317
        $this->addElement(
1318
            'text',
1319
            $name,
1320
            [
1321
                $label,
1322
                get_lang('OnlyLettersAndNumbers')
1323
            ],
1324
            $attributes
1325
        );
1326
1327
        $this->applyFilter($name, 'trim');
1328
1329
        if ($required) {
1330
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1331
        }
1332
1333
        $this->addRule(
1334
            $name,
1335
            get_lang('OnlyLettersAndNumbers'),
1336
            'regex',
1337
            '/^[a-zA-Z0-9ÑÑ]+$/'
1338
        );
1339
    }
1340
1341
    /**
1342
     * @param $name
1343
     * @param $label
1344
     * @param bool $required
1345
     * @param array $attributes
1346
     * @param bool $allowNegative
1347
     * @param null $minValue
1348
     * @param null $maxValue
1349
     */
1350
    public function addFloat(
1351
        $name,
1352
        $label,
1353
        $required = false,
1354
        $attributes = [],
1355
        $allowNegative = false,
1356
        $minValue = null,
1357
        $maxValue = null
1358
    ) {
1359
        $this->addElement(
1360
            'FloatNumber',
1361
            $name,
1362
            $label,
1363
            $attributes
1364
        );
1365
1366
        $this->applyFilter($name, 'trim');
1367
1368
        if ($required) {
1369
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1370
        }
1371
1372
        // Rule allows "," and "."
1373
        /*$this->addRule(
1374
            $name,
1375
            get_lang('OnlyNumbers'),
1376
            'regex',
1377
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1378
        );*/
1379
1380
        if ($allowNegative == false) {
1381
            $this->addRule(
1382
                $name,
1383
                get_lang('NegativeValue'),
1384
                'compare',
1385
                '>=',
1386
                'server',
1387
                false,
1388
                false,
1389
                0
1390
            );
1391
        }
1392
1393 View Code Duplication
        if (!is_null($minValue)) {
1394
            $this->addRule(
1395
                $name,
1396
                get_lang('UnderMin'),
1397
                'compare',
1398
                '>=',
1399
                'server',
1400
                false,
1401
                false,
1402
                $minValue
1403
            );
1404
        }
1405
1406 View Code Duplication
        if (!is_null($maxValue)) {
1407
            $this->addRule(
1408
                $name,
1409
                get_lang('OverMax'),
1410
                'compare',
1411
                '<=',
1412
                'server',
1413
                false,
1414
                false,
1415
                $maxValue
1416
            );
1417
        }
1418
    }
1419
1420
    /**
1421
     * Adds a text field for letters and spaces to the form.
1422
     * A trim-filter is attached to the field.
1423
     * @param string $name The element name
1424
     * @param string $label The label for the form-element
1425
     * @param bool $required Optional. Is the form-element required (default=true)
1426
     * @param array $attributes Optional. List of attributes for the form-element
1427
     */
1428 View Code Duplication
    public function addTextLettersAndSpaces(
1429
        $name,
1430
        $label,
1431
        $required = false,
1432
        $attributes = []
1433
    ) {
1434
        $attributes = array_merge(
1435
            $attributes,
1436
            [
1437
                'pattern' => '[a-zA-ZñÑ\s]+',
1438
                'title' => get_lang('OnlyLettersAndSpaces')
1439
            ]
1440
        );
1441
1442
        $this->addElement(
1443
            'text',
1444
            $name,
1445
            [
1446
                $label,
1447
                get_lang('OnlyLettersAndSpaces')
1448
            ],
1449
            $attributes
1450
        );
1451
1452
        $this->applyFilter($name, 'trim');
1453
1454
        if ($required) {
1455
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1456
        }
1457
1458
        $this->addRule(
1459
            $name,
1460
            get_lang('OnlyLettersAndSpaces'),
1461
            'regex',
1462
            '/^[a-zA-ZñÑ\s]+$/'
1463
        );
1464
    }
1465
1466
    /**
1467
     * Adds a text field for alphanumeric and spaces characters to the form.
1468
     * A trim-filter is attached to the field.
1469
     * @param string $name The element name
1470
     * @param string $label The label for the form-element
1471
     * @param bool $required Optional. Is the form-element required (default=true)
1472
     * @param array $attributes Optional. List of attributes for the form-element
1473
     */
1474 View Code Duplication
    public function addTextAlphanumericAndSpaces(
1475
        $name,
1476
        $label,
1477
        $required = false,
1478
        $attributes = []
1479
    ) {
1480
        $attributes = array_merge(
1481
            $attributes,
1482
            [
1483
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1484
                'title' => get_lang('OnlyLettersAndNumbersAndSpaces')
1485
            ]
1486
        );
1487
1488
        $this->addElement(
1489
            'text',
1490
            $name,
1491
            [
1492
                $label,
1493
                get_lang('OnlyLettersAndNumbersAndSpaces')
1494
            ],
1495
            $attributes
1496
        );
1497
1498
        $this->applyFilter($name, 'trim');
1499
1500
        if ($required) {
1501
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1502
        }
1503
1504
        $this->addRule(
1505
            $name,
1506
            get_lang('OnlyLettersAndNumbersAndSpaces'),
1507
            'regex',
1508
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1509
        );
1510
    }
1511
1512
    /**
1513
     * @param string $url
1514
     */
1515
    public function addMultipleUpload($url)
1516
    {
1517
        $inputName = 'input_file_upload';
1518
        $this->addMultipleUploadJavascript($url, $inputName);
1519
1520
        $this->addHtml('
1521
            <div class="description-upload">'.get_lang('ClickToSelectOrDragAndDropMultipleFilesOnTheUploadField').'</div>
1522
            <span class="btn btn-success fileinput-button">
1523
                <i class="glyphicon glyphicon-plus"></i>
1524
                <span>'.get_lang('AddFiles').'</span>
1525
                <!-- The file input field used as target for the file upload widget -->
1526
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1527
            </span>
1528
            <br />
1529
            <br />
1530
            <div id="dropzone">
1531
                <div class="button-load">
1532
                '.get_lang('UploadFiles').'
1533
                </div>
1534
            </div>
1535
1536
            <br />
1537
            <!-- The global progress bar -->
1538
            <div id="progress" class="progress">
1539
                <div class="progress-bar progress-bar-success"></div>
1540
            </div>
1541
            <div id="files" class="files"></div>
1542
        ');
1543
    }
1544
1545
    /**
1546
     *
1547
     * @param string $url page that will handle the upload
1548
     * @param string $inputName
1549
     */
1550
    private function addMultipleUploadJavascript($url, $inputName)
1551
    {
1552
        $icon = Display::return_icon('file_txt.gif');
1553
        $this->addHtml("
1554
        <script>
1555
        $(function () {
1556
            'use strict';
1557
            $('#".$this->getAttribute('id')."').submit(function() {
1558
                return false;
1559
            });
1560
1561
            $('#dropzone').on('click', function() {
1562
                $('#".$inputName."').click();
1563
            });
1564
1565
            var url = '".$url."';
1566
            var uploadButton = $('<button/>')
1567
                .addClass('btn btn-primary')
1568
                .prop('disabled', true)
1569
                .text('".addslashes(get_lang('Loading'))."')
1570
                .on('click', function () {
1571
                    var \$this = $(this),
1572
                    data = \$this.data();
1573
1574
                    \$this
1575
                        .off('click')
1576
                        .text('".addslashes(get_lang('Cancel'))."')
1577
                        .on('click', function () {
1578
                            \$this.remove();
1579
                            data.abort();
1580
                        });
1581
                    data.submit().always(function () {
1582
                        \$this.remove();
1583
                    });
1584
                });
1585
1586
            $('#".$inputName."').fileupload({
1587
                url: url,
1588
                dataType: 'json',
1589
                autoUpload: true,
1590
                // Enable image resizing, except for Android and Opera,
1591
                // which actually support image resizing, but fail to
1592
                // send Blob objects via XHR requests:
1593
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1594
                previewMaxWidth: 100,
1595
                previewMaxHeight: 100,
1596
                previewCrop: true,
1597
                dropzone: $('#dropzone')
1598
             }).on('fileuploadadd', function (e, data) {
1599
                data.context = $('<div class=\"row\" style=\"margin-bottom:35px\" />').appendTo('#files');
1600
                $.each(data.files, function (index, file) {
1601
                    var node = $('<div class=\"col-sm-5\">').text(file.name);                    
1602
                    node.appendTo(data.context);
1603
                }
1604
            );
1605
            
1606
            }).on('fileuploadprocessalways', function (e, data) {
1607
                var index = data.index,
1608
                    file = data.files[index],
1609
                    node = $(data.context.children()[index]);
1610
                if (file.preview) {
1611
                    data.context
1612
                        .prepend($('<div class=\"col-sm-2\">').html(file.preview))
1613
                    ;
1614
                } else {
1615
                    data.context
1616
                        .prepend($('<div class=\"col-sm-2\">').html('".$icon."'))
1617
                    ;
1618
                }
1619
                if (index + 1 === data.files.length) {
1620
                    data.context.find('button')
1621
                        .text('Upload')
1622
                        .prop('disabled', !!data.files.error);
1623
                }
1624
            }).on('fileuploadprogressall', function (e, data) {
1625
                var progress = parseInt(data.loaded / data.total * 100, 10);
1626
                $('#progress .progress-bar').css(
1627
                    'width',
1628
                    progress + '%'
1629
                );
1630
            }).on('fileuploaddone', function (e, data) {
1631
                $.each(data.result.files, function (index, file) {
1632
                    if (file.url) {
1633
                        var link = $('<a>')
1634
                            .attr('target', '_blank')
1635
                            .prop('href', file.url);
1636
                        $(data.context.children()[index]).parent().wrap(link);
1637
                        
1638
                        var successMessage = $('<div class=\"col-sm-3\">').html($('<span class=\"alert alert-success\"/>').text('" . addslashes(get_lang('UplUploadSucceeded')) . "'));
1639
                        $(data.context.children()[index]).parent().append(successMessage);
1640
                    } else if (file.error) {
1641
                        var error = $('<div class=\"col-sm-3\">').html($('<span class=\"alert alert-danger\"/>').text(file.error));
1642
                        $(data.context.children()[index]).parent().append(error);
1643
                    }
1644
                });
1645
            }).on('fileuploadfail', function (e, data) {
1646
                $.each(data.files, function (index) {
1647
                    var failedMessage = '" . addslashes(get_lang('UplUploadFailed')) . "';
1648
                    var error = $('<div class=\"col-sm-3\">').html($('<span class=\"alert alert-danger\"/>').text(failedMessage));
1649
                    $(data.context.children()[index]).parent().append(error);
1650
                });
1651
            }).prop('disabled', !$.support.fileInput)
1652
                .parent().addClass($.support.fileInput ? undefined : 'disabled');
1653
1654
            $('.fileinput-button').hide();
1655
1656
        });
1657
        </script>");
1658
    }
1659
}
1660
1661
/**
1662
 * Cleans HTML text filter
1663
 * @param string $html			HTML to clean
1664
 * @param int $mode (optional)
1665
 * @return string				The cleaned HTML
1666
 */
1667
function html_filter($html, $mode = NO_HTML)
1668
{
1669
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1670
    $cleaned_html = kses($html, $allowed_tags);
1671
    return $cleaned_html;
1672
}
1673
1674
function html_filter_teacher($html)
1675
{
1676
    return html_filter($html, TEACHER_HTML);
1677
}
1678
1679
function html_filter_student($html)
1680
{
1681
    return html_filter($html, STUDENT_HTML);
1682
}
1683
1684
function html_filter_teacher_fullpage($html)
1685
{
1686
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1687
}
1688
1689
function html_filter_student_fullpage($html)
1690
{
1691
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1692
}
1693
1694
/**
1695
 * Cleans mobile phone number text
1696
 * @param string $mobilePhoneNumber     Mobile phone number to clean
1697
 * @return string                       The cleaned mobile phone number
1698
 */
1699
function mobile_phone_number_filter($mobilePhoneNumber)
1700
{
1701
    $mobilePhoneNumber = str_replace(array('+', '(', ')'), '', $mobilePhoneNumber);
1702
1703
    return ltrim($mobilePhoneNumber, '0');
1704
}
1705