Passed
Push — master ( 30e673...96cf3c )
by Brian
06:42 queued 01:20
created

AUI_Component_Input   F

Complexity

Total Complexity 194

Size/Duplication

Total Lines 1022
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 520
dl 0
loc 1022
rs 2
c 1
b 0
f 1
wmc 194

7 Methods

Rating   Name   Duplication   Size   Complexity  
F input() 0 251 52
B label() 0 58 11
C wrap() 0 69 11
F textarea() 0 193 37
F select() 0 224 59
F radio_option() 0 89 13
C radio() 0 82 11

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * A component class for rendering a bootstrap alert.
9
 *
10
 * @since 1.0.0
11
 */
12
class AUI_Component_Input {
13
14
	/**
15
	 * Build the component.
16
	 *
17
	 * @param array $args
18
	 *
19
	 * @return string The rendered component.
20
	 */
21
	public static function input($args = array()){
22
		$defaults = array(
23
			'type'       => 'text',
24
			'name'       => '',
25
			'class'      => '',
26
			'wrap_class' => '',
27
			'id'         => '',
28
			'placeholder'=> '',
29
			'title'      => '',
30
			'value'      => '',
31
			'required'   => false,
32
			'label'      => '',
33
			'label_after'=> false,
34
			'label_class'=> '',
35
			'label_type' => '', // sets the label type, default: hidden. Options: hidden, top, horizontal, floating
36
			'help_text'  => '',
37
			'validation_text'   => '',
38
			'validation_pattern' => '',
39
			'no_wrap'    => false,
40
			'input_group_right' => '',
41
			'input_group_left' => '',
42
			'input_group_right_inside' => false, // forces the input group inside the input
43
			'input_group_left_inside' => false, // forces the input group inside the input
44
			'step'       => '',
45
			'switch'     => false, // to show checkbox as a switch
46
			'checked'   => false, // set a checkbox or radio as selected
47
			'password_toggle' => true, // toggle view/hide password
48
			'element_require'   => '', // [%element_id%] == "1"
49
			'extra_attributes'  => array() // an array of extra attributes
50
		);
51
52
		/**
53
		 * Parse incoming $args into an array and merge it with $defaults
54
		 */
55
		$args   = wp_parse_args( $args, $defaults );
56
		$output = '';
57
		if ( ! empty( $args['type'] ) ) {
58
			// hidden label option needs to be empty
59
			$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
60
61
			$type = sanitize_html_class( $args['type'] );
62
63
			$help_text = '';
64
			$label = '';
65
			$label_after = $args['label_after'];
66
			$label_args = array(
67
				'title'=> $args['label'],
68
				'for'=> $args['id'],
69
				'class' => $args['label_class']." ",
70
				'label_type' => $args['label_type']
71
			);
72
73
			// floating labels need label after
74
			if( $args['label_type'] == 'floating' && $type != 'checkbox' ){
75
				$label_after = true;
76
				$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
77
			}
78
79
			// Some special sauce for files
80
			if($type=='file' ){
81
				$label_after = true; // if type file we need the label after
82
				$args['class'] .= ' custom-file-input ';
83
			}elseif($type=='checkbox'){
84
				$label_after = true; // if type file we need the label after
85
				$args['class'] .= ' custom-control-input ';
86
			}elseif($type=='datepicker' || $type=='timepicker'){
87
				$type = 'text';
88
				//$args['class'] .= ' aui-flatpickr bg-initial ';
89
				$args['class'] .= ' bg-initial ';
90
91
				$args['extra_attributes']['data-aui-init'] = 'flatpickr';
92
				// enqueue the script
93
				$aui_settings = AyeCode_UI_Settings::instance();
94
				$aui_settings->enqueue_flatpickr();
95
			}
96
97
98
			// open/type
99
			$output .= '<input type="' . $type . '" ';
100
101
			// name
102
			if(!empty($args['name'])){
103
				$output .= ' name="'.esc_attr($args['name']).'" ';
104
			}
105
106
			// id
107
			if(!empty($args['id'])){
108
				$output .= ' id="'.sanitize_html_class($args['id']).'" ';
109
			}
110
111
			// placeholder
112
			if(isset($args['placeholder']) && '' != $args['placeholder'] ){
113
				$output .= ' placeholder="'.esc_attr($args['placeholder']).'" ';
114
			}
115
116
			// title
117
			if(!empty($args['title'])){
118
				$output .= ' title="'.esc_attr($args['title']).'" ';
119
			}
120
121
			// value
122
			if(!empty($args['value'])){
123
				$output .= ' value="'.sanitize_text_field($args['value']).'" ';
124
			}
125
126
			// checked, for radio and checkboxes
127
			if( ( $type == 'checkbox' || $type == 'radio' ) && $args['checked'] ){
128
				$output .= ' checked ';
129
			}
130
131
			// validation text
132
			if(!empty($args['validation_text'])){
133
				$output .= ' oninvalid="setCustomValidity(\''.esc_attr($args['validation_text']).'\')" ';
134
				$output .= ' onchange="try{setCustomValidity(\'\')}catch(e){}" ';
135
			}
136
137
			// validation_pattern
138
			if(!empty($args['validation_pattern'])){
139
				$output .= ' pattern="'.$args['validation_pattern'].'" ';
140
			}
141
142
			// step (for numbers)
143
			if(!empty($args['step'])){
144
				$output .= ' step="'.$args['step'].'" ';
145
			}
146
147
			// required
148
			if(!empty($args['required'])){
149
				$output .= ' required ';
150
			}
151
152
			// class
153
			$class = !empty($args['class']) ? AUI_Component_Helper::esc_classes( $args['class'] ) : '';
154
			$output .= ' class="form-control '.$class.'" ';
155
156
			// data-attributes
157
			$output .= AUI_Component_Helper::data_attributes($args);
158
159
			// extra attributes
160
			if(!empty($args['extra_attributes'])){
161
				$output .= AUI_Component_Helper::extra_attributes($args['extra_attributes']);
162
			}
163
164
			// close
165
			$output .= ' >';
166
167
168
			// label
169
			if(!empty($args['label'])){
170
				if($type == 'file'){$label_args['class'] .= 'custom-file-label';}
171
				elseif($type == 'checkbox'){$label_args['class'] .= 'custom-control-label';}
172
				$label = self::label( $label_args, $type );
173
			}
174
175
			// help text
176
			if(!empty($args['help_text'])){
177
				$help_text = AUI_Component_Helper::help_text($args['help_text']);
178
			}
179
180
181
			// set help text in the correct possition
182
			if($label_after){
183
				$output .= $label . $help_text;
184
			}
185
186
			// some input types need a separate wrap
187
			if($type == 'file') {
188
				$output = self::wrap( array(
189
					'content' => $output,
190
					'class'   => 'form-group custom-file'
191
				) );
192
			}elseif($type == 'checkbox'){
193
				$wrap_class = $args['switch'] ? 'custom-switch' : 'custom-checkbox';
194
				$output = self::wrap( array(
195
					'content' => $output,
196
					'class'   => 'custom-control '.$wrap_class
197
				) );
198
199
				if($args['label_type']=='horizontal'){
200
					$output = '<div class="col-sm-2 col-form-label"></div><div class="col-sm-10">' . $output . '</div>';
201
				}
202
			}elseif($type == 'password' && $args['password_toggle'] && !$args['input_group_right']){
203
204
205
				// allow password field to toggle view
206
				$args['input_group_right'] = '<span class="input-group-text c-pointer px-3" 
207
onclick="var $el = jQuery(this).find(\'i\');$el.toggleClass(\'fa-eye fa-eye-slash\');
208
var $eli = jQuery(this).parent().parent().find(\'input\');
209
if($el.hasClass(\'fa-eye\'))
210
{$eli.attr(\'type\',\'text\');}
211
else{$eli.attr(\'type\',\'password\');}"
212
><i class="far fa-fw fa-eye-slash"></i></span>';
213
			}
214
215
			// input group wraps
216
			if($args['input_group_left'] || $args['input_group_right']){
217
				$w100 = strpos($args['class'], 'w-100') !== false ? ' w-100' : '';
218
				if($args['input_group_left']){
219
					$output = self::wrap( array(
220
						'content' => $output,
221
						'class'   => $args['input_group_left_inside'] ? 'input-group-inside position-relative'.$w100  : 'input-group',
222
						'input_group_left' => $args['input_group_left'],
223
						'input_group_left_inside'    => $args['input_group_left_inside']
224
					) );
225
				}
226
				if($args['input_group_right']){
227
					$output = self::wrap( array(
228
						'content' => $output,
229
						'class'   => $args['input_group_right_inside'] ? 'input-group-inside position-relative'.$w100 : 'input-group',
230
						'input_group_right' => $args['input_group_right'],
231
						'input_group_right_inside'    => $args['input_group_right_inside']
232
					) );
233
				}
234
235
			}
236
237
			if(!$label_after){
238
				$output .= $help_text;
239
			}
240
241
242
			if($args['label_type']=='horizontal' && $type != 'checkbox'){
243
				$output = self::wrap( array(
244
					'content' => $output,
245
					'class'   => 'col-sm-10',
246
				) );
247
			}
248
249
			if(!$label_after){
250
				$output = $label . $output;
251
			}
252
253
			// wrap
254
			if(!$args['no_wrap']){
255
256
				$form_group_class = $args['label_type']=='floating' && $type != 'checkbox' ? 'form-label-group' : 'form-group';
257
				$wrap_class = $args['label_type']=='horizontal' ? $form_group_class . ' row' : $form_group_class;
258
				$wrap_class = !empty($args['wrap_class']) ? $wrap_class." ".$args['wrap_class'] : $wrap_class;
259
				$output = self::wrap(array(
260
					'content' => $output,
261
					'class'   => $wrap_class,
262
					'element_require'   => $args['element_require'],
263
					'argument_id'  => $args['id']
264
				));
265
			}
266
267
268
269
		}
270
271
		return $output;
272
	}
273
274
	/**
275
	 * Build the component.
276
	 *
277
	 * @param array $args
278
	 *
279
	 * @return string The rendered component.
280
	 */
281
	public static function textarea($args = array()){
282
		$defaults = array(
283
			'name'       => '',
284
			'class'      => '',
285
			'wrap_class' => '',
286
			'id'         => '',
287
			'placeholder'=> '',
288
			'title'      => '',
289
			'value'      => '',
290
			'required'   => false,
291
			'label'      => '',
292
			'label_after'=> false,
293
			'label_class'      => '',
294
			'label_type' => '', // sets the label type, default: hidden. Options: hidden, top, horizontal, floating
295
			'help_text'  => '',
296
			'validation_text'   => '',
297
			'validation_pattern' => '',
298
			'no_wrap'    => false,
299
			'rows'      => '',
300
			'wysiwyg'   => false,
301
			'allow_tags' => false, // Allow HTML tags
302
			'element_require'   => '', // [%element_id%] == "1"
303
			'extra_attributes'  => array(), // an array of extra attributes
304
		);
305
306
		/**
307
		 * Parse incoming $args into an array and merge it with $defaults
308
		 */
309
		$args   = wp_parse_args( $args, $defaults );
310
		$output = '';
311
312
		// hidden label option needs to be empty
313
		$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
314
315
		// floating labels don't work with wysiwyg so set it as top
316
		if($args['label_type'] == 'floating' && !empty($args['wysiwyg'])){
317
			$args['label_type'] = 'top';
318
		}
319
320
		$label_after = $args['label_after'];
321
322
		// floating labels need label after
323
		if( $args['label_type'] == 'floating' && empty($args['wysiwyg']) ){
324
			$label_after = true;
325
			$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
326
		}
327
328
		// label
329
		if(!empty($args['label']) && is_array($args['label'])){
330
		}elseif(!empty($args['label']) && !$label_after){
331
			$label_args = array(
332
				'title'=> $args['label'],
333
				'for'=> $args['id'],
334
				'class' => $args['label_class']." ",
335
				'label_type' => $args['label_type']
336
			);
337
			$output .= self::label( $label_args );
338
		}
339
340
		// maybe horizontal label
341
		if($args['label_type']=='horizontal'){
342
			$output .= '<div class="col-sm-10">';
343
		}
344
345
		if(!empty($args['wysiwyg'])){
346
			ob_start();
347
			$content = $args['value'];
348
			$editor_id = !empty($args['id']) ? sanitize_html_class($args['id']) : 'wp_editor';
349
			$settings = array(
350
				'textarea_rows' => !empty(absint($args['rows'])) ? absint($args['rows']) : 4,
351
				'quicktags'     => false,
352
				'media_buttons' => false,
353
				'editor_class'  => 'form-control',
354
				'textarea_name' => !empty($args['name']) ? sanitize_html_class($args['name']) : sanitize_html_class($args['id']),
355
				'teeny'         => true,
356
			);
357
358
			// maybe set settings if array
359
			if(is_array($args['wysiwyg'])){
360
				$settings  = wp_parse_args( $args['wysiwyg'], $settings );
361
			}
362
363
			wp_editor( $content, $editor_id, $settings );
364
			$output .= ob_get_clean();
365
		}else{
366
367
			// open
368
			$output .= '<textarea ';
369
370
			// name
371
			if(!empty($args['name'])){
372
				$output .= ' name="'.sanitize_html_class($args['name']).'" ';
373
			}
374
375
			// id
376
			if(!empty($args['id'])){
377
				$output .= ' id="'.sanitize_html_class($args['id']).'" ';
378
			}
379
380
			// placeholder
381
			if(isset($args['placeholder']) && '' != $args['placeholder']){
382
				$output .= ' placeholder="'.esc_attr($args['placeholder']).'" ';
383
			}
384
385
			// title
386
			if(!empty($args['title'])){
387
				$output .= ' title="'.esc_attr($args['title']).'" ';
388
			}
389
390
			// validation text
391
			if(!empty($args['validation_text'])){
392
				$output .= ' oninvalid="setCustomValidity(\''.esc_attr($args['validation_text']).'\')" ';
393
				$output .= ' onchange="try{setCustomValidity(\'\')}catch(e){}" ';
394
			}
395
396
			// validation_pattern
397
			if(!empty($args['validation_pattern'])){
398
				$output .= ' pattern="'.$args['validation_pattern'].'" ';
399
			}
400
401
			// required
402
			if(!empty($args['required'])){
403
				$output .= ' required ';
404
			}
405
406
			// rows
407
			if(!empty($args['rows'])){
408
				$output .= ' rows="'.absint($args['rows']).'" ';
409
			}
410
411
412
			// class
413
			$class = !empty($args['class']) ? $args['class'] : '';
414
			$output .= ' class="form-control '.$class.'" ';
415
416
			// extra attributes
417
			if(!empty($args['extra_attributes'])){
418
				$output .= AUI_Component_Helper::extra_attributes($args['extra_attributes']);
419
			}
420
421
			// close tag
422
			$output .= ' >';
423
424
			// value
425
			if ( ! empty( $args['value'] ) ) {
426
				if ( ! empty( $args['allow_tags'] ) ) {
427
					$output .= AUI_Component_Helper::sanitize_html_field( $args['value'], $args ); // Sanitize HTML.
428
				} else {
429
					$output .= sanitize_textarea_field( $args['value'] );
430
				}
431
			}
432
433
			// closing tag
434
			$output .= '</textarea>';
435
436
		}
437
438
		if(!empty($args['label']) && $label_after){
439
			$label_args = array(
440
				'title'=> $args['label'],
441
				'for'=> $args['id'],
442
				'class' => $args['label_class']." ",
443
				'label_type' => $args['label_type']
444
			);
445
			$output .= self::label( $label_args );
446
		}
447
448
		// help text
449
		if(!empty($args['help_text'])){
450
			$output .= AUI_Component_Helper::help_text($args['help_text']);
451
		}
452
453
		// maybe horizontal label
454
		if($args['label_type']=='horizontal'){
455
			$output .= '</div>';
456
		}
457
458
459
		// wrap
460
		if(!$args['no_wrap']){
461
			$form_group_class = $args['label_type']=='floating' ? 'form-label-group' : 'form-group';
462
			$wrap_class = $args['label_type']=='horizontal' ? $form_group_class . ' row' : $form_group_class;
463
			$wrap_class = !empty($args['wrap_class']) ? $wrap_class." ".$args['wrap_class'] : $wrap_class;
464
			$output = self::wrap(array(
465
				'content' => $output,
466
				'class'   => $wrap_class,
467
				'element_require'   => $args['element_require'],
468
				'argument_id'  => $args['id']
469
			));
470
		}
471
472
473
		return $output;
474
	}
475
476
	public static function label($args = array(), $type = ''){
477
		//<label for="exampleInputEmail1">Email address</label>
478
		$defaults = array(
479
			'title'       => 'div',
480
			'for'      => '',
481
			'class'      => '',
482
			'label_type'    => '', // empty = hidden, top, horizontal
483
		);
484
485
		/**
486
		 * Parse incoming $args into an array and merge it with $defaults
487
		 */
488
		$args   = wp_parse_args( $args, $defaults );
489
		$output = '';
490
491
		if($args['title']){
492
493
			// maybe hide labels //@todo set a global option for visibility class
494
			if($type == 'file' || $type == 'checkbox' || $type == 'radio' || !empty($args['label_type']) ){
495
				$class = $args['class'];
496
			}else{
497
				$class = 'sr-only '.$args['class'];
498
			}
499
500
			// maybe horizontal
501
			if($args['label_type']=='horizontal' && $type != 'checkbox'){
502
				$class .= ' col-sm-2 col-form-label';
503
			}
504
505
			// open
506
			$output .= '<label ';
507
508
			// for
509
			if(!empty($args['for'])){
510
				$output .= ' for="'.sanitize_text_field($args['for']).'" ';
511
			}
512
513
			// class
514
			$class = $class ? AUI_Component_Helper::esc_classes( $class ) : '';
515
			$output .= ' class="'.$class.'" ';
516
517
			// close
518
			$output .= '>';
519
520
521
			// title, don't escape fully as can contain html
522
			if(!empty($args['title'])){
523
				$output .= wp_kses_post($args['title']);
524
			}
525
526
			// close wrap
527
			$output .= '</label>';
528
529
530
		}
531
532
533
		return $output;
534
	}
535
536
	/**
537
	 * Wrap some content in a HTML wrapper.
538
	 *
539
	 * @param array $args
540
	 *
541
	 * @return string
542
	 */
543
	public static function wrap($args = array()){
544
		$defaults = array(
545
			'type'       => 'div',
546
			'class'      => 'form-group',
547
			'content'   => '',
548
			'input_group_left' => '',
549
			'input_group_right' => '',
550
			'input_group_left_inside' => false,
551
			'input_group_right_inside' => false,
552
			'element_require'   => '',
553
			'argument_id'   => '',
554
		);
555
556
		/**
557
		 * Parse incoming $args into an array and merge it with $defaults
558
		 */
559
		$args   = wp_parse_args( $args, $defaults );
560
		$output = '';
561
		if($args['type']){
562
563
			// open
564
			$output .= '<'.sanitize_html_class($args['type']);
565
566
			// element require
567
			if(!empty($args['element_require'])){
568
				$output .= AUI_Component_Helper::element_require($args['element_require']);
569
				$args['class'] .= " aui-conditional-field";
570
			}
571
572
			// argument_id
573
			if( !empty($args['argument_id']) ){
574
				$output .= ' data-argument="'.esc_attr($args['argument_id']).'"';
575
			}
576
577
			// class
578
			$class = !empty($args['class']) ? AUI_Component_Helper::esc_classes( $args['class'] ) : '';
579
			$output .= ' class="'.$class.'" ';
580
581
			// close wrap
582
			$output .= ' >';
583
584
585
			// Input group left
586
			if(!empty($args['input_group_left'])){
587
				$position_class = !empty($args['input_group_left_inside']) ? 'position-absolute h-100' : '';
588
				$input_group_left = strpos($args['input_group_left'], '<') !== false ? $args['input_group_left'] : '<span class="input-group-text">'.$args['input_group_left'].'</span>';
589
				$output .= '<div class="input-group-prepend '.$position_class.'">'.$input_group_left.'</div>';
590
			}
591
592
			// content
593
			$output .= $args['content'];
594
595
			// Input group right
596
			if(!empty($args['input_group_right'])){
597
				$position_class = !empty($args['input_group_left_inside']) ? 'position-absolute h-100' : '';
598
				$input_group_right = strpos($args['input_group_right'], '<') !== false ? $args['input_group_right'] : '<span class="input-group-text">'.$args['input_group_right'].'</span>';
599
				$output .= '<div class="input-group-append '.$position_class.'">'.$input_group_right.'</div>';
600
			}
601
602
603
			// close wrap
604
			$output .= '</'.sanitize_html_class($args['type']).'>';
605
606
607
		}else{
608
			$output = $args['content'];
609
		}
610
611
		return $output;
612
	}
613
614
	/**
615
	 * Build the component.
616
	 *
617
	 * @param array $args
618
	 *
619
	 * @return string The rendered component.
620
	 */
621
	public static function select($args = array()){
622
		$defaults = array(
623
			'class'      => '',
624
			'wrap_class' => '',
625
			'id'         => '',
626
			'title'      => '',
627
			'value'      => '', // can be an array or a string
628
			'required'   => false,
629
			'label'      => '',
630
			'label_after'=> false,
631
			'label_type' => '', // sets the label type, default: hidden. Options: hidden, top, horizontal, floating
632
			'label_class'      => '',
633
			'help_text'  => '',
634
			'placeholder'=> '',
635
			'options'    => array(), // array or string
636
			'icon'       => '',
637
			'multiple'   => false,
638
			'select2'    => false,
639
			'no_wrap'    => false,
640
			'element_require'   => '', // [%element_id%] == "1"
641
			'extra_attributes'  => array(), // an array of extra attributes
642
		);
643
644
		/**
645
		 * Parse incoming $args into an array and merge it with $defaults
646
		 */
647
		$args   = wp_parse_args( $args, $defaults );
648
		$output = '';
649
650
		// for now lets hide floating labels
651
		if( $args['label_type'] == 'floating' ){$args['label_type'] = 'hidden';}
652
653
		// hidden label option needs to be empty
654
		$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
655
656
657
		$label_after = $args['label_after'];
658
659
		// floating labels need label after
660
		if( $args['label_type'] == 'floating' ){
661
			$label_after = true;
662
			$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
663
		}
664
665
		// Maybe setup select2
666
		$is_select2 = false;
667
		if(!empty($args['select2'])){
668
			$args['class'] .= ' aui-select2';
669
			$is_select2 = true;
670
		}elseif( strpos($args['class'], 'aui-select2') !== false){
671
			$is_select2 = true;
672
		}
673
674
		// select2 tags
675
		if( !empty($args['select2']) && $args['select2'] === 'tags'){ // triple equals needed here for some reason
676
			$args['data-tags'] = 'true';
677
			$args['data-token-separators'] = "[',']";
678
			$args['multiple'] = true;
679
		}
680
681
		// select2 placeholder
682
		if($is_select2 && isset($args['placeholder']) && '' != $args['placeholder'] && empty($args['data-placeholder'])){
683
			$args['data-placeholder'] = esc_attr($args['placeholder']);
684
			$args['data-allow-clear'] = isset($args['data-allow-clear']) ? (bool) $args['data-allow-clear'] : true;
685
		}
686
687
		// label
688
		if(!empty($args['label']) && is_array($args['label'])){
689
		}elseif(!empty($args['label']) && !$label_after){
690
			$label_args = array(
691
				'title'=> $args['label'],
692
				'for'=> $args['id'],
693
				'class' => $args['label_class']." ",
694
				'label_type' => $args['label_type']
695
			);
696
			$output .= self::label($label_args);
697
		}
698
699
		// maybe horizontal label
700
		if($args['label_type']=='horizontal'){
701
			$output .= '<div class="col-sm-10">';
702
		}
703
704
		// open/type
705
		$output .= '<select ';
706
707
		// style
708
		if($is_select2){
709
			$output .= " style='width:100%;' ";
710
		}
711
712
		// element require
713
		if(!empty($args['element_require'])){
714
			$output .= AUI_Component_Helper::element_require($args['element_require']);
715
			$args['class'] .= " aui-conditional-field";
716
		}
717
718
		// class
719
		$class = !empty($args['class']) ? $args['class'] : '';
720
		$output .= AUI_Component_Helper::class_attr('custom-select '.$class);
721
722
		// name
723
		if(!empty($args['name'])){
724
			$output .= AUI_Component_Helper::name($args['name'],$args['multiple']);
725
		}
726
727
		// id
728
		if(!empty($args['id'])){
729
			$output .= AUI_Component_Helper::id($args['id']);
730
		}
731
732
		// title
733
		if(!empty($args['title'])){
734
			$output .= AUI_Component_Helper::title($args['title']);
735
		}
736
737
		// data-attributes
738
		$output .= AUI_Component_Helper::data_attributes($args);
739
740
		// aria-attributes
741
		$output .= AUI_Component_Helper::aria_attributes($args);
742
743
		// extra attributes
744
		if(!empty($args['extra_attributes'])){
745
			$output .= AUI_Component_Helper::extra_attributes($args['extra_attributes']);
746
		}
747
748
		// required
749
		if(!empty($args['required'])){
750
			$output .= ' required ';
751
		}
752
753
		// multiple
754
		if(!empty($args['multiple'])){
755
			$output .= ' multiple ';
756
		}
757
758
		// close opening tag
759
		$output .= ' >';
760
761
		// placeholder
762
		if(isset($args['placeholder']) && '' != $args['placeholder'] && !$is_select2){
763
			$output .= '<option value="" disabled selected hidden>'.esc_attr($args['placeholder']).'</option>';
764
		}elseif($is_select2 && !empty($args['placeholder'])){
765
			$output .= "<option></option>"; // select2 needs an empty select to fill the placeholder
766
		}
767
768
		// Options
769
		if(!empty($args['options'])){
770
771
			if(!is_array($args['options'])){
772
				$output .= $args['options']; // not the preferred way but an option
773
			}else{
774
				foreach($args['options'] as $val => $name){
775
					$selected = '';
776
					if(is_array($name)){
777
						if (isset($name['optgroup']) && ($name['optgroup'] == 'start' || $name['optgroup'] == 'end')) {
778
							$option_label = isset($name['label']) ? $name['label'] : '';
779
780
							$output .= $name['optgroup'] == 'start' ? '<optgroup label="' . esc_attr($option_label) . '">' : '</optgroup>';
781
						} else {
782
							$option_label = isset($name['label']) ? $name['label'] : '';
783
							$option_value = isset($name['value']) ? $name['value'] : '';
784
							if(!empty($args['multiple']) && !empty($args['value']) && is_array($args['value']) ){
785
								$selected = in_array($option_value, stripslashes_deep($args['value'])) ? "selected" : "";
0 ignored issues
show
Bug introduced by
It seems like stripslashes_deep($args['value']) can also be of type object; however, parameter $haystack of in_array() does only seem to accept array, 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

785
								$selected = in_array($option_value, /** @scrutinizer ignore-type */ stripslashes_deep($args['value'])) ? "selected" : "";
Loading history...
786
							} elseif(!empty($args['value'])) {
787
								$selected = selected($option_value,stripslashes_deep($args['value']), false);
788
							}
789
790
							$output .= '<option value="' . esc_attr($option_value) . '" ' . $selected . '>' . $option_label . '</option>';
791
						}
792
					}else{
793
						if(!empty($args['value'])){
794
							if(is_array($args['value'])){
795
								$selected = in_array($val,$args['value']) ? 'selected="selected"' : '';
796
							} elseif(!empty($args['value'])) {
797
								$selected = selected( $args['value'], $val, false);
798
							}
799
						}
800
						$output .= '<option value="'.esc_attr($val).'" '.$selected.'>'.esc_attr($name).'</option>';
801
					}
802
				}
803
			}
804
805
		}
806
807
		// closing tag
808
		$output .= '</select>';
809
810
		if(!empty($args['label']) && $label_after){
811
			$label_args = array(
812
				'title'=> $args['label'],
813
				'for'=> $args['id'],
814
				'class' => $args['label_class']." ",
815
				'label_type' => $args['label_type']
816
			);
817
			$output .= self::label($label_args);
818
		}
819
820
		// help text
821
		if(!empty($args['help_text'])){
822
			$output .= AUI_Component_Helper::help_text($args['help_text']);
823
		}
824
825
		// maybe horizontal label
826
		if($args['label_type']=='horizontal'){
827
			$output .= '</div>';
828
		}
829
830
831
		// wrap
832
		if(!$args['no_wrap']){
833
			$wrap_class = $args['label_type']=='horizontal' ? 'form-group row' : 'form-group';
834
			$wrap_class = !empty($args['wrap_class']) ? $wrap_class." ".$args['wrap_class'] : $wrap_class;
835
			$output = self::wrap(array(
836
				'content' => $output,
837
				'class'   => $wrap_class,
838
				'element_require'   => $args['element_require'],
839
				'argument_id'  => $args['id']
840
			));
841
		}
842
843
844
		return $output;
845
	}
846
847
	/**
848
	 * Build the component.
849
	 *
850
	 * @param array $args
851
	 *
852
	 * @return string The rendered component.
853
	 */
854
	public static function radio($args = array()){
855
		$defaults = array(
856
			'class'      => '',
857
			'wrap_class' => '',
858
			'id'         => '',
859
			'title'      => '',
860
			'horizontal' => false, // sets the lable horizontal
861
			'value'      => '',
862
			'label'      => '',
863
			'label_class'=> '',
864
			'label_type' => '', // sets the label type, default: hidden. Options: hidden, top, horizontal, floating
865
			'help_text'  => '',
866
			'inline'     => true,
867
			'required'   => false,
868
			'options'    => array(),
869
			'icon'       => '',
870
			'no_wrap'    => false,
871
			'element_require'   => '', // [%element_id%] == "1"
872
			'extra_attributes'  => array() // an array of extra attributes
873
		);
874
875
		/**
876
		 * Parse incoming $args into an array and merge it with $defaults
877
		 */
878
		$args   = wp_parse_args( $args, $defaults );
879
880
		// for now lets use horizontal for floating
881
		if( $args['label_type'] == 'floating' ){$args['label_type'] = 'horizontal';}
882
883
		$label_args = array(
884
			'title'=> $args['label'],
885
			'class' => $args['label_class']." pt-0 ",
886
			'label_type' => $args['label_type']
887
		);
888
889
		$output = '';
890
891
892
893
		// label before
894
		if(!empty($args['label'])){
895
			$output .= self::label( $label_args, 'radio' );
896
		}
897
898
		// maybe horizontal label
899
		if($args['label_type']=='horizontal'){
900
			$output .= '<div class="col-sm-10">';
901
		}
902
903
		if(!empty($args['options'])){
904
			$count = 0;
905
			foreach($args['options'] as $value => $label){
906
				$option_args = $args;
907
				$option_args['value'] = $value;
908
				$option_args['label'] = $label;
909
				$option_args['checked'] = $value == $args['value'] ? true : false;
910
				$output .= self::radio_option($option_args,$count);
911
				$count++;
912
			}
913
		}
914
915
		// help text
916
		$help_text = ! empty( $args['help_text'] ) ? AUI_Component_Helper::help_text( $args['help_text'] ) : '';
917
		$output .= $help_text;
918
919
		// maybe horizontal label
920
		if($args['label_type']=='horizontal'){
921
			$output .= '</div>';
922
		}
923
924
		// wrap
925
		$wrap_class = $args['label_type']=='horizontal' ? 'form-group row' : 'form-group';
926
		$wrap_class = !empty($args['wrap_class']) ? $wrap_class." ".$args['wrap_class'] : $wrap_class;
927
		$output = self::wrap(array(
928
			'content' => $output,
929
			'class'   => $wrap_class,
930
			'element_require'   => $args['element_require'],
931
			'argument_id'  => $args['id']
932
		));
933
934
935
		return $output;
936
	}
937
938
	/**
939
	 * Build the component.
940
	 *
941
	 * @param array $args
942
	 *
943
	 * @return string The rendered component.
944
	 */
945
	public static function radio_option($args = array(),$count = ''){
946
		$defaults = array(
947
			'class'      => '',
948
			'id'         => '',
949
			'title'      => '',
950
			'value'      => '',
951
			'required'   => false,
952
			'inline'     => true,
953
			'label'      => '',
954
			'options'    => array(),
955
			'icon'       => '',
956
			'no_wrap'    => false,
957
			'extra_attributes'  => array() // an array of extra attributes
958
		);
959
960
		/**
961
		 * Parse incoming $args into an array and merge it with $defaults
962
		 */
963
		$args   = wp_parse_args( $args, $defaults );
964
965
		$output = '';
966
967
		// open/type
968
		$output .= '<input type="radio"';
969
970
		// class
971
		$output .= ' class="form-check-input" ';
972
973
		// name
974
		if(!empty($args['name'])){
975
			$output .= AUI_Component_Helper::name($args['name']);
976
		}
977
978
		// id
979
		if(!empty($args['id'])){
980
			$output .= AUI_Component_Helper::id($args['id'].$count);
981
		}
982
983
		// title
984
		if(!empty($args['title'])){
985
			$output .= AUI_Component_Helper::title($args['title']);
986
		}
987
988
		// value
989
		if(isset($args['value'])){
990
			$output .= ' value="'.sanitize_text_field($args['value']).'" ';
991
		}
992
993
		// checked, for radio and checkboxes
994
		if( $args['checked'] ){
995
			$output .= ' checked ';
996
		}
997
998
		// data-attributes
999
		$output .= AUI_Component_Helper::data_attributes($args);
1000
1001
		// aria-attributes
1002
		$output .= AUI_Component_Helper::aria_attributes($args);
1003
1004
		// extra attributes
1005
		if(!empty($args['extra_attributes'])){
1006
			$output .= AUI_Component_Helper::extra_attributes($args['extra_attributes']);
1007
		}
1008
1009
		// required
1010
		if(!empty($args['required'])){
1011
			$output .= ' required ';
1012
		}
1013
1014
		// close opening tag
1015
		$output .= ' >';
1016
1017
		// label
1018
		if(!empty($args['label']) && is_array($args['label'])){
1019
		}elseif(!empty($args['label'])){
1020
			$output .= self::label(array('title'=>$args['label'],'for'=>$args['id'].$count,'class'=>'form-check-label'),'radio');
1021
		}
1022
1023
		// wrap
1024
		if(!$args['no_wrap']){
1025
			$wrap_class = $args['inline'] ? 'form-check form-check-inline' : 'form-check';
1026
			$output = self::wrap(array(
1027
				'content' => $output,
1028
				'class' => $wrap_class
1029
			));
1030
		}
1031
1032
1033
		return $output;
1034
	}
1035
1036
}