Completed
Push — master ( 9b8b24...6e1754 )
by Julito
58:58
created

FormValidator::addButton()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 32
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* 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(
103
            '<span class="form_required">*</span> <small>'.get_lang('ThisFieldIsRequired').'</small>'
104
        );
105
106
        $noteTemplate = <<<EOT
107
	<div class="form-group">
108
		<div class="col-sm-offset-2 col-sm-10">{requiredNote}</div>
109
	</div>
110
EOT;
111
        $renderer->setRequiredNoteTemplate($noteTemplate);
112
    }
113
114
    /**
115
     * @return string
116
     */
117
    public function getFormTemplate()
118
    {
119
        return '<form{attributes}>
120
        <fieldset>
121
            {content}
122
        </fieldset>
123
        {hidden}
124
        </form>';
125
    }
126
127
    /**
128
     * @todo this function should be added in the element class
129
     * @return string
130
     */
131
    public function getDefaultElementTemplate()
132
    {
133
        return '
134
            <div class="form-group {error_class}">
135
                <label {label-for} class="col-sm-2 control-label {extra_label_class}" >
136
                    <!-- BEGIN required --><span class="form_required">*</span><!-- END required -->
137
                    {label}
138
                </label>
139
                <div class="col-sm-8">
140
                    {icon}
141
                    {element}
142
143
                    <!-- BEGIN label_2 -->
144
                        <p class="help-block">{label_2}</p>
145
                    <!-- END label_2 -->
146
147
                    <!-- BEGIN error -->
148
                        <span class="help-inline help-block">{error}</span>
149
                    <!-- END error -->
150
                </div>
151
                <div class="col-sm-2">
152
                    <!-- BEGIN label_3 -->
153
                        {label_3}
154
                    <!-- END label_3 -->
155
                </div>
156
            </div>';
157
    }
158
159
    /**
160
     * @return string
161
     */
162
    public function getLayout()
163
    {
164
        return $this->layout;
165
    }
166
167
    /**
168
     * @param string $layout
169
     */
170
    public function setLayout($layout)
171
    {
172
        $this->layout = $layout;
173
    }
174
175
    /**
176
     * Adds a text field to the form.
177
     * A trim-filter is attached to the field.
178
     * @param string $label The label for the form-element
179
     * @param string $name The element name
180
     * @param bool $required (optional)    Is the form-element required (default=true)
181
     * @param array $attributes (optional)    List of attributes for the form-element
182
     * @return HTML_QuickForm_text
183
     */
184
    public function addText($name, $label, $required = true, $attributes = array())
185
    {
186
        $element = $this->addElement('text', $name, $label, $attributes);
187
        $this->applyFilter($name, 'trim');
188
        if ($required) {
189
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
190
        }
191
192
        return $element;
193
    }
194
195
    /**
196
     * The "date_range_picker" element creates 2 hidden fields
197
     * "elementName" + "_start"  and "elementName" + "_end"
198
     * For example if the name is "range", you will have 2 new fields
199
     * when executing $form->getSubmitValues()
200
     * "range_start" and "range_end"
201
     *
202
     * @param string $name
203
     * @param string $label
204
     * @param bool   $required
205
     * @param array  $attributes
206
     */
207
    public function addDateRangePicker($name, $label, $required = true, $attributes = array())
208
    {
209
        $this->addElement('date_range_picker', $name, $label, $attributes);
210
        $this->addElement('hidden', $name.'_start');
211
        $this->addElement('hidden', $name.'_end');
212
213
        if ($required) {
214
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
215
        }
216
    }
217
218
    /**
219
     * @param string $name
220
     * @param string $label
221
     * @param array $attributes
222
     *
223
     * @return mixed
224
     */
225
    public function addDatePicker($name, $label, $attributes = [])
226
    {
227
        return $this->addElement('DatePicker', $name, $label, $attributes);
228
    }
229
230
    /**
231
     * @param string $name
232
     * @param string $label
233
     * @param array $attributes
234
     *
235
     * @return mixed
236
     */
237
    public function addSelectLanguage($name, $label, $options = [], $attributes = [])
238
    {
239
        return $this->addElement('SelectLanguage', $name, $label, $options, $attributes);
240
    }
241
242
    /**
243
     * @param string $name
244
     * @param string $label
245
     * @param array $options
246
     * @param array $attributes
247
     * @throws
248
     */
249
    public function addSelectAjax($name, $label, $options = [], $attributes = [])
250
    {
251
        if (!isset($attributes['url'])) {
252
            throw new \Exception('select_ajax needs an URL');
253
        }
254
        $this->addElement(
255
            'select_ajax',
256
            $name,
257
            $label,
258
            $options,
259
            $attributes
260
        );
261
    }
262
263
    /**
264
     * @param string $name
265
     * @param string $label
266
     * @param array $attributes
267
     *
268
     * @return mixed
269
     */
270
    public function addDateTimePicker($name, $label, $attributes = [])
271
    {
272
        return $this->addElement('DateTimePicker', $name, $label, $attributes);
273
    }
274
275
    /**
276
     * @param string $name
277
     * @param string $value
278
     */
279
    public function addHidden($name, $value)
280
    {
281
        $this->addElement('hidden', $name, $value);
282
    }
283
284
    /**
285
     * @param string $name
286
     * @param string $label
287
     * @param array  $attributes
288
     *
289
     * @return HTML_QuickForm_textarea
290
     */
291
    public function addTextarea($name, $label, $attributes = array())
292
    {
293
        return $this->addElement('textarea', $name, $label, $attributes);
294
    }
295
296
    /**
297
     * @param string $name
298
     * @param string $label
299
     * @param string $icon font-awesome
300
     * @param string $style default|primary|success|info|warning|danger|link
301
     * @param string $size large|default|small|extra-small
302
     * @param string $class Example plus is transformed to icon fa fa-plus
303
     * @param array  $attributes
304
     *
305
     * @return HTML_QuickForm_button
306
     */
307
    public function addButton(
308
        $name,
309
        $label,
310
        $icon = 'check',
311
        $style = 'default',
312
        $size = 'default',
313
        $class = null,
314
        $attributes = array(),
315
        $createElement = false
316
    ) {
317
        if ($createElement) {
318
            return $this->createElement(
319
                'button',
320
                $name,
321
                $label,
322
                $icon,
323
                $style,
324
                $size,
325
                $class,
326
                $attributes
327
            );
328
        }
329
330
        return $this->addElement(
331
            'button',
332
            $name,
333
            $label,
334
            $icon,
335
            $style,
336
            $size,
337
            $class,
338
            $attributes
339
        );
340
    }
341
342
    /**
343
     * Returns a button with the primary color and a check mark
344
     * @param string $label Text appearing on the button
345
     * @param string $name Element name (for form treatment purposes)
346
     * @param bool $createElement Whether to use the create or add method
347
     *
348
     * @return HTML_QuickForm_button
349
     */
350
    public function addButtonSave($label, $name = 'submit', $createElement = false)
351
    {
352
        return $this->addButton(
353
            $name,
354
            $label,
355
            'check',
356
            'primary',
357
            null,
358
            null,
359
            array(),
360
            $createElement
361
        );
362
    }
363
364
    /**
365
     * Returns a cancel button
366
     * @param string $label Text appearing on the button
367
     * @param string $name Element name (for form treatment purposes)
368
     * @param bool $createElement Whether to use the create or add method
369
     *
370
     * @return HTML_QuickForm_button
371
     */
372
    public function addButtonCancel($label, $name = 'submit', $createElement = false)
373
    {
374
        return $this->addButton(
375
            $name,
376
            $label,
377
            'times',
378
            'danger',
379
            null,
380
            null,
381
            array(),
382
            $createElement
383
        );
384
    }
385
386
    /**
387
     * Returns a button with the primary color and a "plus" icon
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 Additional attributes
392
     *
393
     * @return HTML_QuickForm_button
394
     */
395
    public function addButtonCreate($label, $name = 'submit', $createElement = false, $attributes = array())
396
    {
397
        return $this->addButton(
398
            $name,
399
            $label,
400
            'plus',
401
            'primary',
402
            null,
403
            null,
404
            $attributes,
405
            $createElement
406
        );
407
    }
408
409
    /**
410
     * Returns a button with the primary color and a pencil icon
411
     * @param string $label Text appearing on the button
412
     * @param string $name Element name (for form treatment purposes)
413
     * @param bool $createElement Whether to use the create or add method
414
     * @return HTML_QuickForm_button
415
     */
416
    public function addButtonUpdate($label, $name = 'submit', $createElement = false)
417
    {
418
        return $this->addButton(
419
            $name,
420
            $label,
421
            'pencil',
422
            'primary',
423
            null,
424
            null,
425
            array(),
426
            $createElement
427
        );
428
    }
429
430
    /**
431
     * Returns a button with the danger color and a trash icon
432
     * @param string $label Text appearing on the button
433
     * @param string $name Element name (for form treatment purposes)
434
     * @param bool $createElement Whether to use the create or add method
435
     *
436
     * @return HTML_QuickForm_button
437
     */
438
    public function addButtonDelete($label, $name = 'submit', $createElement = false)
439
    {
440
        return $this->addButton(
441
            $name,
442
            $label,
443
            'trash',
444
            'danger',
445
            null,
446
            null,
447
            array(),
448
            $createElement
449
        );
450
    }
451
452
    /**
453
     * Returns a move style button
454
     * @param string $label Text appearing on the button
455
     * @param string $name Element name (for form treatment purposes)
456
     * @param bool $createElement Whether to use the create or add method
457
     *
458
     * @return HTML_QuickForm_button
459
     */
460
    public function addButtonMove($label, $name = 'submit', $createElement = false)
461
    {
462
        return $this->addButton(
463
            $name,
464
            $label,
465
            'arrow-circle-right',
466
            'primary',
467
            null,
468
            null,
469
            array(),
470
            $createElement
471
        );
472
    }
473
474
    /**
475
     * Returns a button with the primary color and a paper-plane icon
476
     * @param string $label Text appearing on the button
477
     * @param string $name Element name (for form treatment purposes)
478
     * @param bool $createElement Whether to use the create or add method
479
     * @param array $attributes
480
     *
481
     * @return HTML_QuickForm_button
482
     */
483
    public function addButtonSend($label, $name = 'submit', $createElement = false, $attributes = [])
484
    {
485
        return $this->addButton(
486
            $name,
487
            $label,
488
            'paper-plane',
489
            'primary',
490
            null,
491
            null,
492
            $attributes,
493
            $createElement
494
        );
495
    }
496
497
    /**
498
     * Returns a button with the default (grey?) color and a magnifier icon
499
     * @param string $label Text appearing on the button
500
     * @param string $name Element name (for form treatment purposes)
501
     *
502
     * @return HTML_QuickForm_button
503
     */
504
    public function addButtonSearch($label = null, $name = 'submit')
505
    {
506
        if (empty($label)) {
507
            $label = get_lang('Search');
508
        }
509
510
        return $this->addButton($name, $label, 'search', 'default');
511
    }
512
513
    /**
514
     * Returns a button with the primary color and a right-pointing arrow icon
515
     * @param string $label Text appearing on the button
516
     * @param string $name Element name (for form treatment purposes)
517
     * @param array $attributes Additional attributes
518
     * @return HTML_QuickForm_button
519
     */
520
    public function addButtonNext($label, $name = 'submit', $attributes = [])
521
    {
522
        return $this->addButton(
523
            $name,
524
            $label,
525
            'arrow-right',
526
            'primary',
527
            null,
528
            null,
529
            $attributes
530
        );
531
    }
532
533
    /**
534
     * Returns a button with the primary color and a check mark icon
535
     * @param string $label Text appearing on the button
536
     * @param string $name Element name (for form treatment purposes)
537
     * @param bool $createElement Whether to use the create or add method
538
     * @return HTML_QuickForm_button
539
     */
540
    public function addButtonImport($label, $name = 'submit', $createElement = false)
541
    {
542
        return $this->addButton(
543
            $name,
544
            $label,
545
            'check',
546
            'primary',
547
            null,
548
            null,
549
            array(),
550
            $createElement
551
        );
552
    }
553
554
    /**
555
     * Returns a button with the primary color and a check-mark icon
556
     * @param string $label Text appearing on the button
557
     * @param string $name Element name (for form treatment purposes)
558
     * @param bool $createElement Whether to use the create or add method
559
     * @return HTML_QuickForm_button
560
     */
561
    public function addButtonExport($label, $name = 'submit', $createElement = false)
562
    {
563
        return $this->addButton(
564
            $name,
565
            $label,
566
            'check',
567
            'primary',
568
            null,
569
            null,
570
            array(),
571
            $createElement
572
        );
573
    }
574
575
    /**
576
     * Shortcut to filter button
577
     * @param string $label Text appearing on the button
578
     * @param string $name Element name (for form treatment purposes)
579
     * @param bool $createElement Whether to use the create or add method
580
     * @return HTML_QuickForm_button
581
     */
582
    public function addButtonFilter($label, $name = 'submit', $createElement = false)
583
    {
584
        return $this->addButton(
585
            $name,
586
            $label,
587
            'filter',
588
            'primary',
589
            null,
590
            null,
591
            array(),
592
            $createElement
593
        );
594
    }
595
596
    /**
597
     * Shortcut to reset button
598
     * @param string $label Text appearing on the button
599
     * @param string $name Element name (for form treatment purposes)
600
     * @param bool $createElement Whether to use the create or add method
601
     * @return HTML_QuickForm_button
602
     */
603
    public function addButtonReset($label, $name = 'reset', $createElement = false)
604
    {
605
        $icon = 'eraser';
606
        $style = 'default';
607
        $size = 'default';
608
        $class = null;
609
        $attributes = array();
610
611
        if ($createElement) {
612
            return $this->createElement(
613
                'reset',
614
                $name,
615
                $label,
616
                $icon,
617
                $style,
618
                $size,
619
                $class,
620
                $attributes
621
            );
622
        }
623
624
        return $this->addElement(
625
            'reset',
626
            $name,
627
            $label,
628
            $icon,
629
            $style,
630
            $size,
631
            $class,
632
            $attributes
633
        );
634
    }
635
636
    /**
637
     * Returns a button with the primary color and an upload icon
638
     * @param string $label Text appearing on the button
639
     * @param string $name Element name (for form treatment purposes)
640
     * @param bool $createElement Whether to use the create or add method
641
     *
642
     * @return HTML_QuickForm_button
643
     */
644
    public function addButtonUpload($label, $name = 'submit', $createElement = false)
645
    {
646
        return $this->addButton(
647
            $name,
648
            $label,
649
            'upload',
650
            'primary',
651
            null,
652
            null,
653
            array(),
654
            $createElement
655
        );
656
    }
657
658
    /**
659
     * Returns a button with the primary color and a download icon
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 addButtonDownload($label, $name = 'submit', $createElement = false)
667
    {
668
        return $this->addButton(
669
            $name,
670
            $label,
671
            'download',
672
            'primary',
673
            null,
674
            null,
675
            array(),
676
            $createElement
677
        );
678
    }
679
680
    /**
681
     * Returns a button with the primary color and a magnifier icon
682
     * @param string $label Text appearing on the button
683
     * @param string $name Element name (for form treatment purposes)
684
     * @param bool $createElement Whether to use the create or add method
685
     *
686
     * @return HTML_QuickForm_button
687
     */
688
    public function addButtonPreview($label, $name = 'submit', $createElement = false)
689
    {
690
        return $this->addButton(
691
            $name,
692
            $label,
693
            'search',
694
            'primary',
695
            null,
696
            null,
697
            array(),
698
            $createElement
699
        );
700
    }
701
702
    /**
703
     * Returns a button with the primary color and a copy (double sheet) icon
704
     * @param string $label Text appearing on the button
705
     * @param string $name Element name (for form treatment purposes)
706
     * @param bool $createElement Whether to use the create or add method
707
     *
708
     * @return HTML_QuickForm_button
709
     */
710
    public function addButtonCopy($label, $name = 'submit', $createElement = false)
711
    {
712
        return $this->addButton(
713
            $name,
714
            $label,
715
            'copy',
716
            'primary',
717
            null,
718
            null,
719
            array(),
720
            $createElement
721
        );
722
    }
723
724
    /**
725
     * @param string $name
726
     * @param string $label
727
     * @param string $text
728
     * @param array  $attributes
729
     *
730
     * @return HTML_QuickForm_checkbox
731
     */
732
    public function addCheckBox($name, $label, $text = '', $attributes = [])
733
    {
734
        return $this->addElement('checkbox', $name, $label, $text, $attributes);
735
    }
736
737
    /**
738
     * @param string $name
739
     * @param string $label
740
     * @param array  $options
741
     * @param array  $attributes
742
     *
743
     * @return HTML_QuickForm_group
744
     */
745
    public function addCheckBoxGroup($name, $label, $options = array(), $attributes = array())
746
    {
747
        $group = array();
748
        foreach ($options as $value => $text) {
749
            $attributes['value'] = $value;
750
            $group[] = $this->createElement(
751
                'checkbox',
752
                $value,
753
                null,
754
                $text,
755
                $attributes
756
            );
757
        }
758
759
        return $this->addGroup($group, $name, $label);
760
    }
761
762
    /**
763
     * @param string $name
764
     * @param string $label
765
     * @param array  $options
766
     * @param array  $attributes
767
     *
768
     * @return HTML_QuickForm_group
769
     */
770
    public function addRadio($name, $label, $options = [], $attributes = [])
771
    {
772
        $group = array();
773
        foreach ($options as $key => $value) {
774
            $group[] = $this->createElement('radio', null, null, $value, $key, $attributes);
775
        }
776
777
        return $this->addGroup($group, $name, $label);
778
    }
779
780
    /**
781
     * @param string $name
782
     * @param string $label
783
     * @param array  $options
784
     * @param array  $attributes
785
     *
786
     * @return HTML_QuickForm_select
787
     */
788
    public function addSelect($name, $label, $options = [], $attributes = [])
789
    {
790
        return $this->addElement('select', $name, $label, $options, $attributes);
791
    }
792
793
    /**
794
     * @param $name
795
     * @param $label
796
     * @param $collection
797
     * @param array $attributes
798
     * @param bool $addNoneOption
799
     * @param string $textCallable set a function getStringValue() by default __toString()
800
     *
801
     * @return HTML_QuickForm_element
802
     */
803
    public function addSelectFromCollection(
804
        $name,
805
        $label,
806
        $collection,
807
        $attributes = array(),
808
        $addNoneOption = false,
809
        $textCallable = ''
810
    ) {
811
        $options = [];
812
813
        if ($addNoneOption) {
814
            $options[0] = get_lang('None');
815
        }
816
817
        if (!empty($collection)) {
818
            foreach ($collection as $item) {
819
                $text = $item;
820
                if (!empty($textCallable)) {
821
                    $text = $item->$textCallable();
822
                }
823
                $options[$item->getId()] = $text;
824
            }
825
        }
826
        return $this->addElement('select', $name, $label, $options, $attributes);
827
    }
828
829
    /**
830
     * @param string $label
831
     * @param string $text
832
     *
833
     * @return HTML_QuickForm_label
834
     */
835
    public function addLabel($label, $text)
836
    {
837
        return $this->addElement('label', $label, $text);
838
    }
839
840
    /**
841
     * @param string $text
842
     */
843
    public function addHeader($text)
844
    {
845
        $this->addElement('header', $text);
846
    }
847
848
    /**
849
     * @param string $name
850
     * @param string $label
851
     * @param array  $attributes
852
     * @throws Exception if the file doesn't have an id
853
     */
854
    public function addFile($name, $label, $attributes = array())
855
    {
856
        $element = $this->addElement('file', $name, $label, $attributes);
857
        if (isset($attributes['crop_image'])) {
858
            $id = $element->getAttribute('id');
859
            if (empty($id)) {
860
                throw new Exception('If you use the crop functionality the element must have an id');
861
            }
862
            $this->addHtml('
863
                <div class="form-group" id="'.$id.'-form-group" style="display: none;">
864
                    <div class="col-sm-offset-2 col-sm-8">
865
                        <div id="'.$id.'_crop_image" class="cropCanvas thumbnail">
866
                            <img id="'.$id.'_preview_image">
867
                        </div>
868
                        <button class="btn btn-primary" type="button" name="cropButton" id="'.$id.'_crop_button">
869
                            <em class="fa fa-crop"></em> '.get_lang('CropYourPicture').'
870
                        </button>
871
                    </div>
872
                </div>'
873
            );
874
            $this->addHidden($id.'_crop_result', '');
875
            $this->addHidden($id.'_crop_image_base_64', '');
876
        }
877
    }
878
879
    /**
880
     * @param string $snippet
881
     */
882
    public function addHtml($snippet)
883
    {
884
        $this->addElement('html', $snippet);
885
    }
886
887
    /**
888
     * Adds a HTML-editor to the form
889
     * @param string $name
890
     * @param string $label The label for the form-element
891
     * @param bool   $required (optional) Is the form-element required (default=true)
892
     * @param bool   $fullPage (optional) When it is true, the editor loads completed html code for a full page.
893
     * @param array  $config (optional) Configuration settings for the online editor.
894
     * @param bool   $style
895
     */
896
    public function addHtmlEditor(
897
        $name,
898
        $label,
899
        $required = true,
900
        $fullPage = false,
901
        $config = [],
902
        $style = false
903
    ) {
904
        $attributes = [];
905
        $attributes['rows'] = isset($config['rows']) ? $config['rows'] : 15;
906
        $attributes['cols'] = isset($config['cols']) ? $config['cols'] : 80;
907
        $attributes['cols-size'] = isset($config['cols-size']) ? $config['cols-size'] : [];
908
        $attributes['class'] = isset($config['class']) ? $config['class'] : [];
909
910
        $this->addElement('html_editor', $name, $label, $attributes, $config);
911
        $this->applyFilter($name, 'trim');
912
        if ($required) {
913
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
914
        }
915
916
        /** @var HtmlEditor $element */
917
        $element = $this->getElement($name);
918
919
        if ($style) {
920
            $config['style'] = true;
921
        }
922
        if ($fullPage) {
923
            $config['fullPage'] = true;
924
        }
925
926
        if ($element->editor) {
927
            $element->editor->processConfig($config);
928
        }
929
    }
930
931
    /**
932
     * Adds a Google Maps Geolocalization field to the form
933
     *
934
     * @param $name
935
     * @param $label
936
     */
937
    public function addGeoLocationMapField($name, $label)
938
    {
939
        $gMapsPlugin = GoogleMapsPlugin::create();
940
        $geolocalization = $gMapsPlugin->get('enable_api') === 'true';
941
942
        if ($geolocalization) {
943
            $gmapsApiKey = $gMapsPlugin->get('api_key');
944
            $this->addHtml(
945
                '<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?key='.$gmapsApiKey.'" ></script>'
946
            );
947
        }
948
        $this->addElement(
949
            'text',
950
            $name,
951
            $label,
952
            ['id' => $name]
953
        );
954
        $this->applyFilter($name, 'stripslashes');
955
        $this->applyFilter($name, 'trim');
956
        $this->addHtml('
957
            <div class="form-group">
958
                <label for="geolocalization_'.$name.'" class="col-sm-2 control-label"></label>
959
                <div class="col-sm-8">
960
                    <button class="null btn btn-default " id="geolocalization_'.$name.'" name="geolocalization_'.$name.'" type="submit">
961
                        <em class="fa fa-map-marker"></em> '.get_lang('Geolocalization').'
962
                    </button>
963
                    <button class="null btn btn-default " id="myLocation_'.$name.'" name="myLocation_'.$name.'" type="submit">
964
                    <em class="fa fa-crosshairs"></em> 
965
                    '.get_lang('MyLocation').'
966
                    </button>
967
                </div>
968
            </div>
969
        ');
970
971
        $this->addHtml('
972
            <div class="form-group">
973
                <label for="map_'.$name.'" class="col-sm-2 control-label">
974
                    '.$label.' - '.get_lang('Map').'
975
                </label>
976
                <div class="col-sm-8">
977
                    <div name="map_'.$name.'" id="map_'.$name.'" style="width:100%; height:300px;">
978
                    </div>
979
                </div>
980
            </div>
981
        ');
982
983
        $this->addHtml('<script>
984
            $(document).ready(function() {
985
                if (typeof google === "object") {
986
                    var address = $("#' . $name.'").val();
987
                    initializeGeo'.$name.'(address, false);
988
989
                    $("#geolocalization_'.$name.'").on("click", function() {
990
                        var address = $("#'.$name.'").val();
991
                        initializeGeo'.$name.'(address, false);
992
                        return false;
993
                    });
994
995
                    $("#myLocation_'.$name.'").on("click", function() {
996
                        myLocation'.$name.'();
997
                        return false;
998
                    });
999
1000
                    $("#'.$name.'").keypress(function (event) {
1001
                        if (event.which == 13) {
1002
                            $("#geolocalization_'.$name.'").click();
1003
                            return false;
1004
                        }
1005
                    });
1006
                } else {
1007
                    $("#map_'.$name.'").html("<div class=\"alert alert-info\">'.get_lang('YouNeedToActivateTheGoogleMapsPluginInAdminPlatformToSeeTheMap').'</div>");
1008
                }
1009
            });
1010
1011
            function myLocation'.$name.'() {
1012
                if (navigator.geolocation) {
1013
                    var geoPosition = function(position) {
1014
                        var lat = position.coords.latitude;
1015
                        var lng = position.coords.longitude;
1016
                        var latLng = new google.maps.LatLng(lat, lng);
1017
                        initializeGeo'.$name.'(false, latLng)
1018
                    };
1019
1020
                    var geoError = function(error) {
1021
                        alert("Geocode ' . get_lang('Error').': " + error);
1022
                    };
1023
1024
                    var geoOptions = {
1025
                        enableHighAccuracy: true
1026
                    };
1027
                    navigator.geolocation.getCurrentPosition(geoPosition, geoError, geoOptions);
1028
                }
1029
            }
1030
1031
            function initializeGeo'.$name.'(address, latLng) {
1032
                var geocoder = new google.maps.Geocoder();
1033
                var latlng = new google.maps.LatLng(-34.397, 150.644);
1034
                var myOptions = {
1035
                    zoom: 15,
1036
                    center: latlng,
1037
                    mapTypeControl: true,
1038
                    mapTypeControlOptions: {
1039
                        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
1040
                    },
1041
                    navigationControl: true,
1042
                    mapTypeId: google.maps.MapTypeId.ROADMAP
1043
                };
1044
1045
                map_'.$name.' = new google.maps.Map(document.getElementById("map_'.$name.'"), myOptions);
1046
1047
                var parameter = address ? { "address": address } : latLng ? { "latLng": latLng } : false;
1048
1049
                if (geocoder && parameter) {
1050
                    geocoder.geocode(parameter, function(results, status) {
1051
                        if (status == google.maps.GeocoderStatus.OK) {
1052
                            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
1053
                                map_'.$name.'.setCenter(results[0].geometry.location);
1054
                                if (!address) {
1055
                                    $("#'.$name.'").val(results[0].formatted_address);
1056
                                }
1057
                                var infowindow = new google.maps.InfoWindow({
1058
                                    content: "<b>" + $("#'.$name.'").val() + "</b>",
1059
                                    size: new google.maps.Size(150, 50)
1060
                                });
1061
1062
                                var marker = new google.maps.Marker({
1063
                                    position: results[0].geometry.location,
1064
                                    map: map_'.$name.',
1065
                                    title: $("#'.$name.'").val()
1066
                                });
1067
                                google.maps.event.addListener(marker, "click", function() {
1068
                                    infowindow.open(map_'.$name.', marker);
1069
                                });
1070
                            } else {
1071
                                alert("' . get_lang("NotFound").'");
1072
                            }
1073
                        } else {
1074
                            alert("Geocode ' . get_lang('Error').': '.get_lang("AddressField").' '.get_lang("NotFound").'");
1075
                        }
1076
                    });
1077
                }
1078
            }
1079
        </script>
1080
        ');
1081
    }
1082
1083
    /**
1084
     * @param string $name
1085
     * @param string $label
1086
     *
1087
     * @return mixed
1088
     */
1089
    public function addButtonAdvancedSettings($name, $label = '')
1090
    {
1091
        $label = !empty($label) ? $label : get_lang('AdvancedParameters');
1092
1093
        return $this->addElement('advanced_settings', $name, $label);
1094
    }
1095
1096
    /**
1097
     * Adds a progress loading image to the form.
1098
     *
1099
     */
1100
    public function addProgress($delay = 2, $label = '')
1101
    {
1102
        if (empty($label)) {
1103
            $label = get_lang('PleaseStandBy');
1104
        }
1105
        $this->with_progress_bar = true;
1106
        $id = $this->getAttribute('id');
1107
1108
        $this->updateAttributes("onsubmit=\"javascript: addProgress('".$id."')\"");
1109
        $this->addHtml('<script language="javascript" src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/upload.js" type="text/javascript"></script>');
1110
    }
1111
1112
    /**
1113
     * This function has been created for avoiding changes directly within QuickForm class.
1114
     * When we use it, the element is threated as 'required' to be dealt during validation.
1115
     * @param array $elements The array of elements
1116
     * @param string $message The message displayed
1117
     */
1118
    public function add_multiple_required_rule($elements, $message)
1119
    {
1120
        $this->_required[] = $elements[0];
1121
        $this->addRule($elements, $message, 'multiple_required');
1122
    }
1123
1124
    /**
1125
     * Displays the form.
1126
     * If an element in the form didn't validate, an error message is showed
1127
     * asking the user to complete the form.
1128
     */
1129
    public function display()
1130
    {
1131
        echo $this->returnForm();
1132
    }
1133
1134
    /**
1135
     * Returns the HTML code of the form.
1136
     * @return string $return_value HTML code of the form
1137
     */
1138
    public function returnForm()
1139
    {
1140
        $returnValue = '';
1141
1142
        /** @var HTML_QuickForm_element $element */
1143
        foreach ($this->_elements as $element) {
1144
            $elementError = parent::getElementError($element->getName());
1145
            if (!is_null($elementError)) {
1146
                $returnValue .= Display::return_message($elementError, 'warning').'<br />';
1147
                break;
1148
            }
1149
        }
1150
1151
        $returnValue .= parent::toHtml();
1152
        // Add div-element which is to hold the progress bar
1153
        $id = $this->getAttribute('id');
1154
        if (isset($this->with_progress_bar) && $this->with_progress_bar) {
1155
            // Deprecated
1156
            // $icon = Display::return_icon('progress_bar.gif');
1157
1158
            // @todo improve UI
1159
            $returnValue .= '<br />
1160
1161
            <div id="loading_div_'.$id.'" class="loading_div" style="display:none;margin-left:40%; margin-top:10px; height:50px;">
1162
                <div class="wobblebar-loader"></div>
1163
            </div>
1164
            ';
1165
        }
1166
1167
        return $returnValue;
1168
    }
1169
1170
    /**
1171
     * Returns the HTML code of the form.
1172
     * If an element in the form didn't validate, an error message is showed
1173
     * asking the user to complete the form.
1174
     *
1175
     * @return string $return_value HTML code of the form
1176
     *
1177
     * @author Patrick Cool <[email protected]>, Ghent University, august 2006
1178
     * @author Julio Montoya
1179
     * @deprecated use returnForm()
1180
     */
1181
    public function return_form()
1182
    {
1183
        return $this->returnForm();
1184
    }
1185
1186
    /**
1187
     * Create a form validator based on an array of form data:
1188
     *
1189
     *         array(
1190
     *             'name' => 'zombie_report_parameters',    //optional
1191
     *             'method' => 'GET',                       //optional
1192
     *             'items' => array(
1193
     *                 array(
1194
     *                     'name' => 'ceiling',
1195
     *                     'label' => 'Ceiling',            //optional
1196
     *                     'type' => 'date',
1197
     *                     'default' => date()              //optional
1198
     *                 ),
1199
     *                 array(
1200
     *                     'name' => 'active_only',
1201
     *                     'label' => 'ActiveOnly',
1202
     *                     'type' => 'checkbox',
1203
     *                     'default' => true
1204
     *                 ),
1205
     *                 array(
1206
     *                     'name' => 'submit_button',
1207
     *                     'type' => 'style_submit_button',
1208
     *                     'value' => get_lang('Search'),
1209
     *                     'attributes' => array('class' => 'search')
1210
     *                 )
1211
     *             )
1212
     *         );
1213
     *
1214
     * @param array $form_data
1215
     * @deprecated use normal FormValidator construct
1216
     *
1217
     * @return FormValidator
1218
     */
1219
    public static function create($form_data)
1220
    {
1221
        if (empty($form_data)) {
1222
            return null;
1223
        }
1224
        $form_name = isset($form_data['name']) ? $form_data['name'] : 'form';
1225
        $form_method = isset($form_data['method']) ? $form_data['method'] : 'POST';
1226
        $form_action = isset($form_data['action']) ? $form_data['action'] : '';
1227
        $form_target = isset($form_data['target']) ? $form_data['target'] : '';
1228
        $form_attributes = isset($form_data['attributes']) ? $form_data['attributes'] : null;
1229
        $form_track_submit = isset($form_data['track_submit']) ? $form_data['track_submit'] : true;
1230
        $reset = null;
1231
        $result = new FormValidator($form_name, $form_method, $form_action, $form_target, $form_attributes, $form_track_submit);
0 ignored issues
show
Bug introduced by
It seems like $form_track_submit can also be of type true; however, parameter $layout of FormValidator::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1231
        $result = new FormValidator($form_name, $form_method, $form_action, $form_target, $form_attributes, /** @scrutinizer ignore-type */ $form_track_submit);
Loading history...
1232
1233
        $defaults = array();
1234
        foreach ($form_data['items'] as $item) {
1235
            $name = $item['name'];
1236
            $type = isset($item['type']) ? $item['type'] : 'text';
1237
            $label = isset($item['label']) ? $item['label'] : '';
1238
            if ($type == 'wysiwyg') {
1239
                $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) targeting 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...
1240
            } else {
1241
                $element = $result->addElement($type, $name, $label);
1242
            }
1243
            if (isset($item['attributes'])) {
1244
                $attributes = $item['attributes'];
1245
                $element->setAttributes($attributes);
1246
            }
1247
            if (isset($item['value'])) {
1248
                $value = $item['value'];
1249
                $element->setValue($value);
1250
            }
1251
            if (isset($item['default'])) {
1252
                $defaults[$name] = $item['default'];
1253
            }
1254
            if (isset($item['rules'])) {
1255
                $rules = $item['rules'];
1256
                foreach ($rules as $rule) {
1257
                    $message = $rule['message'];
1258
                    $type = $rule['type'];
1259
                    $format = isset($rule['format']) ? $rule['format'] : null;
1260
                    $validation = isset($rule['validation']) ? $rule['validation'] : 'server';
1261
                    $force = isset($rule['force']) ? $rule['force'] : false;
1262
                    $result->addRule($name, $message, $type, $format, $validation, $reset, $force);
1263
                }
1264
            }
1265
        }
1266
        $result->setDefaults($defaults);
1267
1268
        return $result;
1269
    }
1270
1271
    /**
1272
     * @return HTML_QuickForm_Renderer_Default
1273
     */
1274
    public static function getDefaultRenderer()
1275
    {
1276
        return
1277
            isset($GLOBALS['_HTML_QuickForm_default_renderer']) ?
1278
                $GLOBALS['_HTML_QuickForm_default_renderer'] : null;
1279
    }
1280
1281
    /**
1282
     * Adds a input of type url to the form.
1283
     * @param string $name The label for the form-element
1284
     * @param string $label The element name
1285
     * @param bool $required Optional. Is the form-element required (default=true)
1286
     * @param array $attributes Optional. List of attributes for the form-element
1287
     */
1288
    public function addUrl($name, $label, $required = true, $attributes = [])
1289
    {
1290
        $this->addElement('url', $name, $label, $attributes);
1291
        $this->applyFilter($name, 'trim');
1292
        $this->addRule($name, get_lang('InsertAValidUrl'), 'url');
1293
1294
        if ($required) {
1295
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1296
        }
1297
    }
1298
1299
    /**
1300
     * Adds a text field for letters to the form.
1301
     * A trim-filter is attached to the field.
1302
     * @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 addTextLettersOnly(
1308
        $name,
1309
        $label,
1310
        $required = false,
1311
        $attributes = []
1312
    ) {
1313
        $attributes = array_merge(
1314
            $attributes,
1315
            [
1316
                'pattern' => '[a-zA-ZñÑ]+',
1317
                'title' => get_lang('OnlyLetters')
1318
            ]
1319
        );
1320
1321
        $this->addElement(
1322
            'text',
1323
            $name,
1324
            [
1325
                $label,
1326
                get_lang('OnlyLetters')
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('OnlyLetters'),
1340
            'regex',
1341
            '/^[a-zA-ZñÑ]+$/'
1342
        );
1343
    }
1344
1345
    /**
1346
     * Adds a text field for alphanumeric characters to the form.
1347
     * A trim-filter is attached to the field.
1348
     * @param string $name The element name
1349
     * @param string $label The label for the form-element
1350
     * @param bool $required Optional. Is the form-element required (default=true)
1351
     * @param array $attributes Optional. List of attributes for the form-element
1352
     */
1353
    public function addTextAlphanumeric(
1354
        $name,
1355
        $label,
1356
        $required = false,
1357
        $attributes = []
1358
    ) {
1359
        $attributes = array_merge(
1360
            $attributes,
1361
            [
1362
                'pattern' => '[a-zA-Z0-9ñÑ]+',
1363
                'title' => get_lang('OnlyLettersAndNumbers')
1364
            ]
1365
        );
1366
1367
        $this->addElement(
1368
            'text',
1369
            $name,
1370
            [
1371
                $label,
1372
                get_lang('OnlyLettersAndNumbers')
1373
            ],
1374
            $attributes
1375
        );
1376
1377
        $this->applyFilter($name, 'trim');
1378
1379
        if ($required) {
1380
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1381
        }
1382
1383
        $this->addRule(
1384
            $name,
1385
            get_lang('OnlyLettersAndNumbers'),
1386
            'regex',
1387
            '/^[a-zA-Z0-9ÑÑ]+$/'
1388
        );
1389
    }
1390
1391
    /**
1392
     * @param string $name
1393
     * @param $label
1394
     * @param bool $required
1395
     * @param array $attributes
1396
     * @param bool $allowNegative
1397
     * @param integer $minValue
1398
     * @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...
1399
     */
1400
    public function addFloat(
1401
        $name,
1402
        $label,
1403
        $required = false,
1404
        $attributes = [],
1405
        $allowNegative = false,
1406
        $minValue = null,
1407
        $maxValue = null
1408
    ) {
1409
        $this->addElement(
1410
            'FloatNumber',
1411
            $name,
1412
            $label,
1413
            $attributes
1414
        );
1415
1416
        $this->applyFilter($name, 'trim');
1417
1418
        if ($required) {
1419
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1420
        }
1421
1422
        // Rule allows "," and "."
1423
        /*$this->addRule(
1424
            $name,
1425
            get_lang('OnlyNumbers'),
1426
            'regex',
1427
            '/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|(^-?\d\d*\,\d*$)|(^-?\,\d\d*$)/'
1428
        );*/
1429
1430
        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...
1431
            $this->addRule(
1432
                $name,
1433
                get_lang('NegativeValue'),
1434
                'compare',
1435
                '>=',
1436
                'server',
1437
                false,
1438
                false,
1439
                0
1440
            );
1441
        }
1442
1443
        if (!is_null($minValue)) {
1444
            $this->addRule(
1445
                $name,
1446
                get_lang('UnderMin'),
1447
                'compare',
1448
                '>=',
1449
                'server',
1450
                false,
1451
                false,
1452
                $minValue
1453
            );
1454
        }
1455
1456
        if (!is_null($maxValue)) {
1457
            $this->addRule(
1458
                $name,
1459
                get_lang('OverMax'),
1460
                'compare',
1461
                '<=',
1462
                'server',
1463
                false,
1464
                false,
1465
                $maxValue
1466
            );
1467
        }
1468
    }
1469
1470
    /**
1471
     * Adds a text field for letters and spaces to the form.
1472
     * A trim-filter is attached to the field.
1473
     * @param string $name The element name
1474
     * @param string $label The label for the form-element
1475
     * @param bool $required Optional. Is the form-element required (default=true)
1476
     * @param array $attributes Optional. List of attributes for the form-element
1477
     */
1478
    public function addTextLettersAndSpaces(
1479
        $name,
1480
        $label,
1481
        $required = false,
1482
        $attributes = []
1483
    ) {
1484
        $attributes = array_merge(
1485
            $attributes,
1486
            [
1487
                'pattern' => '[a-zA-ZñÑ\s]+',
1488
                'title' => get_lang('OnlyLettersAndSpaces')
1489
            ]
1490
        );
1491
1492
        $this->addElement(
1493
            'text',
1494
            $name,
1495
            [
1496
                $label,
1497
                get_lang('OnlyLettersAndSpaces')
1498
            ],
1499
            $attributes
1500
        );
1501
1502
        $this->applyFilter($name, 'trim');
1503
1504
        if ($required) {
1505
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1506
        }
1507
1508
        $this->addRule(
1509
            $name,
1510
            get_lang('OnlyLettersAndSpaces'),
1511
            'regex',
1512
            '/^[a-zA-ZñÑ\s]+$/'
1513
        );
1514
    }
1515
1516
    /**
1517
     * Adds a text field for alphanumeric and spaces characters to the form.
1518
     * A trim-filter is attached to the field.
1519
     * @param string $name The element name
1520
     * @param string $label The label for the form-element
1521
     * @param bool $required Optional. Is the form-element required (default=true)
1522
     * @param array $attributes Optional. List of attributes for the form-element
1523
     */
1524
    public function addTextAlphanumericAndSpaces(
1525
        $name,
1526
        $label,
1527
        $required = false,
1528
        $attributes = []
1529
    ) {
1530
        $attributes = array_merge(
1531
            $attributes,
1532
            [
1533
                'pattern' => '[a-zA-Z0-9ñÑ\s]+',
1534
                'title' => get_lang('OnlyLettersAndNumbersAndSpaces')
1535
            ]
1536
        );
1537
1538
        $this->addElement(
1539
            'text',
1540
            $name,
1541
            [
1542
                $label,
1543
                get_lang('OnlyLettersAndNumbersAndSpaces')
1544
            ],
1545
            $attributes
1546
        );
1547
1548
        $this->applyFilter($name, 'trim');
1549
1550
        if ($required) {
1551
            $this->addRule($name, get_lang('ThisFieldIsRequired'), 'required');
1552
        }
1553
1554
        $this->addRule(
1555
            $name,
1556
            get_lang('OnlyLettersAndNumbersAndSpaces'),
1557
            'regex',
1558
            '/^[a-zA-Z0-9ñÑ\s]+$/'
1559
        );
1560
    }
1561
1562
    /**
1563
     * @param string $url
1564
     * @param string $urlToRedirect after upload redirect to this page
1565
     */
1566
    public function addMultipleUpload($url, $urlToRedirect = '')
1567
    {
1568
        $inputName = 'input_file_upload';
1569
        $this->addMultipleUploadJavascript($url, $inputName, $urlToRedirect);
1570
1571
        $this->addHtml('
1572
            <div class="description-upload">
1573
            '.get_lang('ClickToSelectOrDragAndDropMultipleFilesOnTheUploadField').'
1574
            </div>
1575
            <span class="btn btn-success fileinput-button">
1576
                <i class="glyphicon glyphicon-plus"></i>
1577
                <span>'.get_lang('AddFiles').'</span>
1578
                <!-- The file input field used as target for the file upload widget -->
1579
                <input id="'.$inputName.'" type="file" name="files[]" multiple>
1580
            </span>
1581
            <div id="dropzone">
1582
                <div class="button-load">
1583
                '.get_lang('UploadFiles').'
1584
                </div>
1585
            </div>
1586
            <br />
1587
            <!-- The global progress bar -->
1588
            <div id="progress" class="progress">
1589
                <div class="progress-bar progress-bar-success"></div>
1590
            </div>
1591
            <div id="files" class="files"></div>
1592
        ');
1593
    }
1594
1595
    /**
1596
     *
1597
     * @param string $url page that will handle the upload
1598
     * @param string $inputName
1599
     * @param string $urlToRedirect
1600
     */
1601
    private function addMultipleUploadJavascript($url, $inputName, $urlToRedirect = '')
1602
    {
1603
        $redirectCondition = '';
1604
        if (!empty($urlToRedirect)) {
1605
            $redirectCondition = "window.location.replace('$urlToRedirect'); ";
1606
        }
1607
        $icon = Display::return_icon('file_txt.gif');
1608
        $this->addHtml("
1609
        <script>
1610
        $(function () {
1611
            'use strict';
1612
            $('#".$this->getAttribute('id')."').submit(function() {
1613
                return false;
1614
            });
1615
1616
            $('#dropzone').on('click', function() {
1617
                $('#".$inputName."').click();
1618
            });
1619
1620
            var url = '".$url."';
1621
            var uploadButton = $('<button/>')
1622
                .addClass('btn btn-primary')
1623
                .prop('disabled', true)
1624
                .text('".addslashes(get_lang('Loading'))."')
1625
                .on('click', function () {
1626
                    var \$this = $(this),
1627
                    data = \$this.data();
1628
1629
                    \$this
1630
                        .off('click')
1631
                        .text('".addslashes(get_lang('Cancel'))."')
1632
                        .on('click', function () {
1633
                            \$this.remove();
1634
                            data.abort();
1635
                        });
1636
                    data.submit().always(function () {
1637
                        \$this.remove();
1638
                    });
1639
                });               
1640
                
1641
            $('#".$inputName."').fileupload({
1642
                url: url,
1643
                dataType: 'json',
1644
                // Enable image resizing, except for Android and Opera,
1645
                // which actually support image resizing, but fail to
1646
                // send Blob objects via XHR requests:
1647
                disableImageResize: /Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),
1648
                previewMaxWidth: 50,
1649
                previewMaxHeight: 50,
1650
                previewCrop: true,
1651
                dropzone: $('#dropzone'),                                
1652
            }).on('fileuploadadd', function (e, data) {
1653
                data.context = $('<div class=\"row\" />').appendTo('#files');
1654
                $.each(data.files, function (index, file) {
1655
                    var node = $('<div class=\"col-sm-5 file_name\">').text(file.name);                    
1656
                    node.appendTo(data.context);
1657
                });
1658
            }).on('fileuploadprocessalways', function (e, data) {
1659
                var index = data.index,
1660
                    file = data.files[index],
1661
                    node = $(data.context.children()[index]);
1662
                if (file.preview) {
1663
                    data.context
1664
                        .prepend($('<div class=\"col-sm-2\">').html(file.preview))
1665
                    ;
1666
                } else {
1667
                    data.context
1668
                        .prepend($('<div class=\"col-sm-2\">').html('".$icon."'))
1669
                    ;
1670
                }
1671
                if (index + 1 === data.files.length) {
1672
                    data.context.find('button')
1673
                        .text('Upload')
1674
                        .prop('disabled', !!data.files.error);
1675
                }
1676
            }).on('fileuploadprogressall', function (e, data) {
1677
                var progress = parseInt(data.loaded / data.total * 100, 10);
1678
                $('#progress .progress-bar').css(
1679
                    'width',
1680
                    progress + '%'
1681
                );
1682
            }).on('fileuploaddone', function (e, data) {
1683
                $.each(data.result.files, function (index, file) {
1684
                    if (file.url) {
1685
                        var link = $('<a>')
1686
                            .attr({target: '_blank', class : 'panel-image'})
1687
                            .prop('href', file.url);
1688
                        $(data.context.children()[index]).parent().wrap(link);
1689
                        // Update file name with new one from Chamilo
1690
                        $(data.context.children()[index]).parent().find('.file_name').html(file.name);                        
1691
                        var successMessage = $('<div class=\"col-sm-3\">').html($('<span class=\"message-image-success\"/>').text('".addslashes(get_lang('UplUploadSucceeded'))."'));
1692
                        $(data.context.children()[index]).parent().append(successMessage);                    
1693
                    } else if (file.error) {
1694
                        var error = $('<div class=\"col-sm-3\">').html($('<span class=\"message-image-danger\"/>').text(file.error));
1695
                        $(data.context.children()[index]).parent().append(error);                        
1696
                    }
1697
                });                
1698
                $('#dropzone').removeClass('hover');                
1699
                ".$redirectCondition."
1700
            }).on('fileuploadfail', function (e, data) {
1701
                $.each(data.files, function (index) {
1702
                    var failedMessage = '" . addslashes(get_lang('UplUploadFailed'))."';
1703
                    var error = $('<div class=\"col-sm-3\">').html($('<span class=\"alert alert-danger\"/>').text(failedMessage));
1704
                    $(data.context.children()[index]).parent().append(error);
1705
                });
1706
                $('#dropzone').removeClass('hover');
1707
            }).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');            
1708
            
1709
            $('#dropzone').on('dragover', function (e) {
1710
                // dragleave callback implementation                
1711
                $('#dropzone').addClass('hover');
1712
            });
1713
            
1714
            $('#dropzone').on('dragleave', function (e) {                
1715
                $('#dropzone').removeClass('hover');
1716
            });
1717
            $('.fileinput-button').hide();
1718
        });
1719
        </script>");
1720
    }
1721
1722
    /**
1723
     * @param string $elementName
1724
     * @param string $groupName if element is inside a group
1725
     * @throws Exception
1726
     */
1727
    public function addPasswordRule($elementName, $groupName = '')
1728
    {
1729
        // Constant defined in old config/profile.conf.php
1730
        if (CHECK_PASS_EASY_TO_FIND === true) {
1731
            $message = get_lang('PassTooEasy').': '.api_generate_password();
1732
1733
            if (!empty($groupName)) {
1734
                $groupObj = $this->getElement($groupName);
1735
1736
                if ($groupObj instanceof HTML_QuickForm_group) {
1737
                    $elementName = $groupObj->getElementName($elementName);
1738
1739
                    if ($elementName === false) {
1740
                        throw new Exception("The $groupName doesn't have the element $elementName");
1741
                    }
1742
1743
                    $this->_rules[$elementName][] = array(
1744
                        'type' => 'callback',
1745
                        'format' => 'api_check_password',
1746
                        'message' => $message,
1747
                        'validation' => '',
1748
                        'reset' => false,
1749
                        'group' => $groupName
1750
                    );
1751
                }
1752
            } else {
1753
                $this->addRule(
1754
                    $elementName,
1755
                    $message,
1756
                    'callback',
1757
                    'api_check_password'
1758
                );
1759
            }
1760
        }
1761
    }
1762
1763
    /**
1764
     * Add an element with user ID and avatar to the form.
1765
     * It needs a Chamilo\UserBundle\Entity\User as value. The exported value is the Chamilo\UserBundle\Entity\User ID
1766
     * @see \UserAvatar
1767
     * @param string $name
1768
     * @param string $label
1769
     * @param string $imageSize Optional. Small, medium or large image
1770
     * @param string $subtitle Optional. The subtitle for the field
1771
     * @return \UserAvatar
1772
     */
1773
    public function addUserAvatar($name, $label, $imageSize = 'small', $subtitle = '')
1774
    {
1775
        return $this->addElement('UserAvatar', $name, $label, ['image_size' => $imageSize, 'sub_title' => $subtitle]);
1776
    }
1777
}
1778
1779
/**
1780
 * Cleans HTML text filter
1781
 * @param string $html HTML to clean
1782
 * @param int $mode (optional)
1783
 * @return string The cleaned HTML
1784
 */
1785
function html_filter($html, $mode = NO_HTML)
1786
{
1787
    $allowed_tags = HTML_QuickForm_Rule_HTML::get_allowed_tags($mode);
1788
    $cleaned_html = kses($html, $allowed_tags);
1789
    return $cleaned_html;
1790
}
1791
1792
function html_filter_teacher($html)
1793
{
1794
    return html_filter($html, TEACHER_HTML);
1795
}
1796
1797
function html_filter_student($html)
1798
{
1799
    return html_filter($html, STUDENT_HTML);
1800
}
1801
1802
function html_filter_teacher_fullpage($html)
1803
{
1804
    return html_filter($html, TEACHER_HTML_FULLPAGE);
1805
}
1806
1807
function html_filter_student_fullpage($html)
1808
{
1809
    return html_filter($html, STUDENT_HTML_FULLPAGE);
1810
}
1811
1812
/**
1813
 * Cleans mobile phone number text
1814
 * @param string $mobilePhoneNumber Mobile phone number to clean
1815
 * @return string The cleaned mobile phone number
1816
 */
1817
function mobile_phone_number_filter($mobilePhoneNumber)
1818
{
1819
    $mobilePhoneNumber = str_replace(array('+', '(', ')'), '', $mobilePhoneNumber);
1820
1821
    return ltrim($mobilePhoneNumber, '0');
1822
}
1823