Issues (865)

Security Analysis    4 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (1)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (2)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/components/class-aui-component-input.php (2 issues)

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
		global $aui_bs5;
23
24
		$defaults = array(
25
			'type'                     => 'text',
26
			'name'                     => '',
27
			'class'                    => '',
28
			'wrap_class'               => '',
29
			'id'                       => '',
30
			'placeholder'              => '',
31
			'title'                    => '',
32
			'value'                    => '',
33
			'required'                 => false,
34
			'size'                     => '', // sm, lg, small, large
35
			'clear_icon'               => '', // true will show a clear icon, can't be used with input_group_right
36
			'with_hidden'              => false, // Append hidden field for single checkbox.
37
			'label'                    => '',
38
			'label_after'              => false,
39
			'label_class'              => '',
40
			'label_col'                => '2',
41
			'label_type'               => '', // top, horizontal, empty = hidden
42
			'label_force_left'         => false, // used to force checkbox label left when using horizontal
43
			// sets the label type, default: hidden. Options: hidden, top, horizontal, floating
44
			'help_text'                => '',
45
			'validation_text'          => '',
46
			'validation_pattern'       => '',
47
			'no_wrap'                  => false,
48
			'input_group_right'        => '',
49
			'input_group_left'         => '',
50
			'input_group_right_inside' => false,
51
			// forces the input group inside the input
52
			'input_group_left_inside'  => false,
53
			// forces the input group inside the input
54
			'form_group_class'         => '',
55
			'step'                     => '',
56
			'switch'                   => false,
57
			// to show checkbox as a switch
58
			'checked'                  => false,
59
			// set a checkbox or radio as selected
60
			'password_toggle'          => true,
61
			// toggle view/hide password
62
			'element_require'          => '',
63
			// [%element_id%] == "1"
64
			'extra_attributes'         => array(),
65
			// an array of extra attributes
66
			'wrap_attributes'          => array()
67
		);
68
69
		/**
70
		 * Parse incoming $args into an array and merge it with $defaults
71
		 */
72
		$args   = wp_parse_args( $args, $defaults );
73
		$output = '';
74
		if ( ! empty( $args['type'] ) ) {
75
			// hidden label option needs to be empty
76
			$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
77
78
			$type = sanitize_html_class( $args['type'] );
79
80
			$help_text   = '';
81
			$label       = '';
82
			$label_after = $args['label_after'];
83
			$label_args  = array(
84
				'title'      => $args['label'],
85
				'for'        => $args['id'],
86
				'class'      => $args['label_class'] . " ",
87
				'label_type' => $args['label_type'],
88
				'label_col'  => $args['label_col']
89
			);
90
91
			// floating labels need label after
92
			if ( $args['label_type'] == 'floating' && $type != 'checkbox' ) {
93
				$label_after         = true;
94
				$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
95
			}
96
97
			// size
98
			$size = '';
99
			if ( $args['size'] == 'lg' || $args['size'] == 'large' ) {
100
				$size = 'lg';
101
				$args['class'] .= ' form-control-lg';
102
			}elseif ( $args['size'] == 'sm' || $args['size'] == 'small' ) {
103
				$size = 'sm';
104
				$args['class'] .= ' form-control-sm';
105
			}
106
107
			// clear function
108
			$clear_function = 'jQuery(this).parent().parent().find(\'input\').val(\'\');';
109
110
			// Some special sauce for files
111
			if ( $type == 'file' ) {
112
				$label_after = true; // if type file we need the label after
113
				$args['class'] .= ' custom-file-input ';
114
			} elseif ( $type == 'checkbox' ) {
115
				$label_after = true; // if type file we need the label after
116
				$args['class'] .= $aui_bs5 ? ' form-check-input c-pointer ' : ' custom-control-input c-pointer ';
117
			} elseif ( $type == 'datepicker' || $type == 'timepicker' ) {
118
				$orig_type = $type;
0 ignored issues
show
The assignment to $orig_type is dead and can be removed.
Loading history...
119
				$type = 'text';
120
				$args['class'] .= ' bg-initial '; // @todo not sure why we have this?
121
				$clear_function .= "jQuery(this).parent().parent().find('input[name=\'" . esc_attr( $args['name'] ) . "\']').trigger('change');";
122
123
				$args['extra_attributes']['data-aui-init'] = 'flatpickr';
124
125
				// Disable native datetime inputs.
126
				$disable_mobile_attr = isset( $args['extra_attributes']['data-disable-mobile'] ) ? $args['extra_attributes']['data-disable-mobile'] : 'true';
127
				$disable_mobile_attr = apply_filters( 'aui_flatpickr_disable_disable_mobile_attr', $disable_mobile_attr, $args );
128
129
				$args['extra_attributes']['data-disable-mobile'] = $disable_mobile_attr;
130
131
				// set a way to clear field if empty
132
				if ( $args['input_group_right'] === '' && $args['clear_icon'] !== false ) {
133
					$args['input_group_right_inside'] = true;
134
					$args['clear_icon'] = true;
135
				}
136
137
				// enqueue the script
138
				$aui_settings = AyeCode_UI_Settings::instance();
139
				$aui_settings->enqueue_flatpickr();
140
			} else if ( $type == 'iconpicker' ) {
141
				$type = 'text';
142
143
				// Validate FA icon.
144
				$args['value'] = AUI_Component_Helper::sanitize_fa_icon( $args['value'], $args );
145
146
				$args['extra_attributes']['data-aui-init'] = 'iconpicker';
147
				$args['extra_attributes']['data-placement'] = 'bottomRight';
148
149
				$args['input_group_right'] = '<span class="input-group-addon input-group-text c-pointer"></span>';
150
151
				// Enqueue the script
152
				$aui_settings = AyeCode_UI_Settings::instance();
153
				$aui_settings->enqueue_iconpicker();
154
			}
155
156
			if ( $type == 'checkbox' && ( ( ! empty( $args['name'] ) && strpos( $args['name'], '[' ) === false ) || ! empty( $args['with_hidden'] ) ) ) {
157
				$output .= '<input type="hidden" name="' . esc_attr( $args['name'] ) . '" value="0" />';
158
			}
159
160
			// allow clear icon
161
			if ( $args['input_group_right'] === '' && $args['clear_icon'] ) {
162
				$font_size = $size == 'sm' ? '1.3' : ( $size == 'lg' ? '1.65' : '1.5' );
163
				$args['input_group_right_inside'] = true;
164
				$align_class = $aui_bs5 ? ' h-100 py-0' : '';
165
				$args['input_group_right'] = '<span class="input-group-text aui-clear-input c-pointer bg-initial border-0 px-2 d-none ' . $align_class . '" onclick="' . $clear_function . '"><span style="font-size: ' . $font_size . 'rem" aria-hidden="true" class="' . ( $aui_bs5 ? 'btn-close' : 'close' ) . '">' . ( $aui_bs5 ? '' : '&times;' ) . '</span></span>';
166
			}
167
168
			// open/type
169
			$output .= '<input type="' . $type . '" ';
170
171
			// name
172
			if ( ! empty( $args['name'] ) ) {
173
				$output .= ' name="' . esc_attr( $args['name'] ) . '" ';
174
			}
175
176
			// id
177
			if ( ! empty( $args['id'] ) ) {
178
				$output .= ' id="' . sanitize_html_class( $args['id'] ) . '" ';
179
			}
180
181
			// placeholder
182
			if ( isset( $args['placeholder'] ) && '' != $args['placeholder'] ) {
183
				$output .= ' placeholder="' . esc_attr( $args['placeholder'] ) . '" ';
184
			}
185
186
			// title
187
			if ( ! empty( $args['title'] ) ) {
188
				$output .= ' title="' . esc_attr( $args['title'] ) . '" ';
189
			}
190
191
			// value
192
			if ( ! empty( $args['value'] ) ) {
193
				$output .= AUI_Component_Helper::value( $args['value'] );
194
			}
195
196
			// checked, for radio and checkboxes
197
			if ( ( $type == 'checkbox' || $type == 'radio' ) && $args['checked'] ) {
198
				$output .= ' checked ';
199
			}
200
201
			// validation text
202
			if ( ! empty( $args['validation_text'] ) ) {
203
				$output .= ' oninvalid="setCustomValidity(\'' . esc_attr( addslashes( $args['validation_text'] ) ) . '\')" ';
204
				$output .= ' onchange="try{setCustomValidity(\'\')}catch(e){}" ';
205
			}
206
207
			// validation_pattern
208
			if ( ! empty( $args['validation_pattern'] ) ) {
209
				$output .= ' pattern="' . esc_attr( $args['validation_pattern'] ) . '" ';
210
			}
211
212
			// step (for numbers)
213
			if ( ! empty( $args['step'] ) ) {
214
				$output .= ' step="' . $args['step'] . '" ';
215
			}
216
217
			// required
218
			if ( ! empty( $args['required'] ) ) {
219
				$output .= ' required ';
220
			}
221
222
			// class
223
			$class = ! empty( $args['class'] ) ? AUI_Component_Helper::esc_classes( $args['class'] ) : '';
224
			$output .= $aui_bs5 &&  $type == 'checkbox' ? ' class="' . $class . '" ' : ' class="form-control ' . $class . '" ';
225
226
			// data-attributes
227
			$output .= AUI_Component_Helper::data_attributes( $args );
228
229
			// extra attributes
230
			if ( ! empty( $args['extra_attributes'] ) ) {
231
				$output .= AUI_Component_Helper::extra_attributes( $args['extra_attributes'] );
232
			}
233
234
			// close
235
			$output .= '>';
236
237
			// help text
238
			if ( ! empty( $args['help_text'] ) ) {
239
				$help_text = AUI_Component_Helper::help_text( $args['help_text'] );
240
			}
241
242
			// label
243
			if ( ! empty( $args['label'] ) ) {
244
				$label_base_class = '';
245
				if ( $type == 'file' ) {
246
					$label_base_class = ' custom-file-label';
247
				} elseif ( $type == 'checkbox' ) {
248
					if ( ! empty( $args['label_force_left'] ) ) {
249
						$label_args['title'] = wp_kses_post( $args['help_text'] );
250
						$help_text = '';
251
						//$label_args['class'] .= ' d-inline ';
252
						$args['wrap_class'] .= ' align-items-center ';
253
					}else{
254
255
					}
256
257
					$label_base_class = $aui_bs5 ? ' form-check-label' : ' custom-control-label';
258
				}
259
				$label_args['class'] .= $label_base_class;
260
				$temp_label_args = $label_args;
261
				if(! empty( $args['label_force_left'] )){$temp_label_args['class'] = $label_base_class." text-muted";}
262
				$label = self::label( $temp_label_args, $type );
263
			}
264
265
266
267
268
			// set help text in the correct position
269
			if ( $label_after ) {
270
				$output .= $label . $help_text;
271
			}
272
273
			// some input types need a separate wrap
274
			if ( $type == 'file' ) {
275
				$output = self::wrap( array(
276
					'content' => $output,
277
					'class'   => $aui_bs5 ? 'mb-3 custom-file' : 'form-group custom-file'
278
				) );
279
			} elseif ( $type == 'checkbox' ) {
280
281
				$label_args['title'] = $args['label'];
282
				$label_col = AUI_Component_Helper::get_column_class( $args['label_col'], 'label' );
283
				$label = !empty( $args['label_force_left'] ) ? self::label( $label_args, 'cb' ) : '<div class="' . $label_col . ' col-form-label"></div>';
284
				$switch_size_class = $args['switch'] && !is_bool( $args['switch'] ) ? ' custom-switch-'.esc_attr( $args['switch'] ) : '';
285
				if ( $aui_bs5 ) {
286
					$wrap_class = $args['switch'] ? 'form-check form-switch' . $switch_size_class : 'form-check';
287
				}else{
288
					$wrap_class = $args['switch'] ? 'custom-switch' . $switch_size_class :  'custom-checkbox' ;
289
				}
290
				if ( ! empty( $args['label_force_left'] ) ) {
291
					$wrap_class .= $aui_bs5 ? '' : ' d-flex align-content-center';
292
					$label = str_replace(array("form-check-label","custom-control-label"),"", self::label( $label_args, 'cb' ) );
293
				}
294
				$output     = self::wrap( array(
295
					'content' => $output,
296
					'class'   => $aui_bs5 ? $wrap_class : 'custom-control ' . $wrap_class
297
				) );
298
299
				if ( $args['label_type'] == 'horizontal' ) {
300
					$input_col = AUI_Component_Helper::get_column_class( $args['label_col'], 'input' );
301
					$output    = $label . '<div class="' . $input_col . '">' . $output . '</div>';
302
				}
303
			} elseif ( $type == 'password' && $args['password_toggle'] && ! $args['input_group_right'] ) {
304
305
306
				// allow password field to toggle view
307
				$args['input_group_right'] = '<span class="input-group-text c-pointer px-3" 
308
onclick="var $el = jQuery(this).find(\'i\');$el.toggleClass(\'fa-eye fa-eye-slash\');
309
var $eli = jQuery(this).parent().parent().find(\'input\');
310
if($el.hasClass(\'fa-eye\'))
311
{$eli.attr(\'type\',\'text\');}
312
else{$eli.attr(\'type\',\'password\');}"
313
><i class="far fa-fw fa-eye-slash"></i></span>';
314
			}
315
316
			// input group wraps
317
			if ( $args['input_group_left'] || $args['input_group_right'] ) {
318
				$w100 = strpos( $args['class'], 'w-100' ) !== false ? ' w-100' : '';
319
				$group_size = $size == 'lg' ? ' input-group-lg' : '';
320
				$group_size = !$group_size && $size == 'sm' ? ' input-group-sm' : $group_size;
321
322
				if ( $args['input_group_left'] ) {
323
					$output = self::wrap( array(
324
						'content'                 => $output,
325
						'class'                   => $args['input_group_left_inside'] ? 'input-group-inside position-relative' . $w100 . $group_size : 'input-group' . $group_size,
326
						'input_group_left'        => $args['input_group_left'],
327
						'input_group_left_inside' => $args['input_group_left_inside']
328
					) );
329
				}
330
				if ( $args['input_group_right'] ) {
331
					$output = self::wrap( array(
332
						'content'                  => $output,
333
						'class'                    => $args['input_group_right_inside'] ? 'input-group-inside position-relative' . $w100 . $group_size : 'input-group' . $group_size,
334
						'input_group_right'        => $args['input_group_right'],
335
						'input_group_right_inside' => $args['input_group_right_inside']
336
					) );
337
				}
338
339
			}
340
341
			if ( ! $label_after ) {
342
				$output .= $help_text;
343
			}
344
345
346
			if ( $args['label_type'] == 'horizontal' && $type != 'checkbox' ) {
347
				$output = self::wrap( array(
348
					'content' => $output,
349
					'class'   => AUI_Component_Helper::get_column_class( $args['label_col'], 'input' )
350
				) );
351
			}
352
353
			if ( ! $label_after ) {
354
				$output = $label . $output;
355
			}
356
357
			// wrap
358
			if ( ! $args['no_wrap'] ) {
359
				if ( ! empty( $args['form_group_class'] ) ) {
360
					$fg_class = esc_attr( $args['form_group_class'] );
361
				}else{
362
					$fg_class = $aui_bs5 ? 'mb-3' : 'form-group';
363
				}
364
				$form_group_class = $args['label_type'] == 'floating' && $type != 'checkbox' ? 'form-label-group' : $fg_class;
365
				$wrap_class       = $args['label_type'] == 'horizontal' ? $form_group_class . ' row' : $form_group_class;
366
				$wrap_class       = ! empty( $args['wrap_class'] ) ? $wrap_class . " " . $args['wrap_class'] : $wrap_class;
367
				$output           = self::wrap( array(
368
					'content'         => $output,
369
					'class'           => $wrap_class,
370
					'element_require' => $args['element_require'],
371
					'argument_id'     => $args['id'],
372
					'wrap_attributes' => $args['wrap_attributes'],
373
				) );
374
			}
375
		}
376
377
		return $output;
378
	}
379
380
	public static function label( $args = array(), $type = '' ) {
381
		global $aui_bs5;
382
383
		$defaults = array(
384
			'title'      => 'div',
385
			'for'        => '',
386
			'class'      => '',
387
			'label_type' => '', // empty = hidden, top, horizontal
388
			'label_col'  => '',
389
		);
390
391
		/**
392
		 * Parse incoming $args into an array and merge it with $defaults
393
		 */
394
		$args   = wp_parse_args( $args, $defaults );
395
		$output = '';
396
397
		if ( $args['title'] ) {
398
			// maybe hide labels //@todo set a global option for visibility class
399
			if ( $type == 'file' || $type == 'checkbox' || $type == 'radio' || ! empty( $args['label_type'] ) ) {
400
				$class = $args['class'];
401
			} else {
402
				$class = 'sr-only ' . ( $aui_bs5 ? 'visually-hidden ' : '' ) . $args['class'];
403
			}
404
405
			// maybe horizontal
406
			if ( $args['label_type'] == 'horizontal' && $type != 'checkbox' ) {
407
				$class .= ' ' . AUI_Component_Helper::get_column_class( $args['label_col'], 'label' ) . ' col-form-label ' . $type;
408
			}
409
410
			if ( $aui_bs5 ) {
411
				$class .= ' form-label';
412
			}
413
414
			// open
415
			$output .= '<label';
416
417
			// for
418
			if ( ! empty( $args['for'] ) ) {
419
				$output .= ' for="' . esc_attr( $args['for'] ) . '"';
420
			}
421
422
			// class
423
			$class = $class ? AUI_Component_Helper::esc_classes( $class ) : '';
424
			$output .= $class != "" ? ' class="' . $class . '"' : '';
425
426
			// close
427
			$output .= '>';
428
429
			// title, don't escape fully as can contain html
430
			if ( ! empty( $args['title'] ) ) {
431
				$output .= wp_kses_post( $args['title'] );
432
			}
433
434
			// close wrap
435
			$output .= '</label>';
436
		}
437
438
		return $output;
439
	}
440
441
	/**
442
	 * Wrap some content in a HTML wrapper.
443
	 *
444
	 * @param array $args
445
	 *
446
	 * @return string
447
	 */
448
	public static function wrap( $args = array() ) {
449
		global $aui_bs5;
450
		$defaults = array(
451
			'type'                     => 'div',
452
			'class'                    => $aui_bs5 ? 'mb-3' : 'form-group',
453
			'content'                  => '',
454
			'input_group_left'         => '',
455
			'input_group_right'        => '',
456
			'input_group_left_inside'  => false,
457
			'input_group_right_inside' => false,
458
			'element_require'          => '',
459
			'argument_id'              => '',
460
			'wrap_attributes'          => array()
461
		);
462
463
		/**
464
		 * Parse incoming $args into an array and merge it with $defaults
465
		 */
466
		$args   = wp_parse_args( $args, $defaults );
467
		$output = '';
468
		if ( $args['type'] ) {
469
470
			// open
471
			$output .= '<' . sanitize_html_class( $args['type'] );
472
473
			// element require
474
			if ( ! empty( $args['element_require'] ) ) {
475
				$output .= AUI_Component_Helper::element_require( $args['element_require'] );
476
				$args['class'] .= " aui-conditional-field";
477
			}
478
479
			// argument_id
480
			if ( ! empty( $args['argument_id'] ) ) {
481
				$output .= ' data-argument="' . esc_attr( $args['argument_id'] ) . '"';
482
			}
483
484
			// class
485
			$class = ! empty( $args['class'] ) ? AUI_Component_Helper::esc_classes( $args['class'] ) : '';
486
			$output .= ' class="' . $class . '" ';
487
488
			// Attributes
489
			if ( ! empty( $args['wrap_attributes'] ) ) {
490
				$output .= AUI_Component_Helper::extra_attributes( $args['wrap_attributes'] );
491
			}
492
493
			// close wrap
494
			$output .= '>';
495
496
497
			// Input group left
498
			if ( ! empty( $args['input_group_left'] ) ) {
499
				$position_class   = ! empty( $args['input_group_left_inside'] ) ? 'position-absolute h-100' : '';
500
				$input_group_left = strpos( $args['input_group_left'], '<' ) !== false ? $args['input_group_left'] : '<span class="input-group-text">' . $args['input_group_left'] . '</span>';
501
				$output .= $aui_bs5 ? $input_group_left : '<div class="input-group-prepend ' . $position_class . '">' . $input_group_left . '</div>';
502
//				$output .= '<div class="input-group-prepend ' . $position_class . '">' . $input_group_left . '</div>';
503
			}
504
505
			// content
506
			$output .= $args['content'];
507
508
			// Input group right
509
			if ( ! empty( $args['input_group_right'] ) ) {
510
				$position_class    = ! empty( $args['input_group_right_inside'] ) ? 'position-absolute h-100' : '';
511
				$input_group_right = strpos( $args['input_group_right'], '<' ) !== false ? $args['input_group_right'] : '<span class="input-group-text">' . $args['input_group_right'] . '</span>';
512
				$output .= $aui_bs5 ? str_replace( 'input-group-text','input-group-text top-0 end-0', $input_group_right ) : '<div class="input-group-append ' . $position_class . '" style="top:0;right:0;">' . $input_group_right . '</div>';
513
//				$output .= '<div class="input-group-append ' . $position_class . '" style="top:0;right:0;">' . $input_group_right . '</div>';
514
			}
515
516
517
			// close wrap
518
			$output .= '</' . sanitize_html_class( $args['type'] ) . '>';
519
520
521
		} else {
522
			$output = $args['content'];
523
		}
524
525
		return $output;
526
	}
527
528
	/**
529
	 * Build the component.
530
	 *
531
	 * @param array $args
532
	 *
533
	 * @return string The rendered component.
534
	 */
535
	public static function textarea( $args = array() ) {
536
		global $aui_bs5;
537
538
		$defaults = array(
539
			'name'               => '',
540
			'class'              => '',
541
			'wrap_class'         => '',
542
			'id'                 => '',
543
			'placeholder'        => '',
544
			'title'              => '',
545
			'value'              => '',
546
			'required'           => false,
547
			'label'              => '',
548
			'label_after'        => false,
549
			'label_class'        => '',
550
			'label_type'         => '',
551
			'label_col'          => '',
552
			// sets the label type, default: hidden. Options: hidden, top, horizontal, floating
553
			'input_group_right'        => '',
554
			'input_group_left'         => '',
555
			'input_group_right_inside' => false,
556
			'form_group_class'      => '',
557
			'help_text'          => '',
558
			'validation_text'    => '',
559
			'validation_pattern' => '',
560
			'no_wrap'            => false,
561
			'rows'               => '',
562
			'wysiwyg'            => false,
563
			'allow_tags'         => false,
564
			// Allow HTML tags
565
			'element_require'    => '',
566
			// [%element_id%] == "1"
567
			'extra_attributes'   => array(),
568
			// an array of extra attributes
569
			'wrap_attributes'    => array(),
570
		);
571
572
		/**
573
		 * Parse incoming $args into an array and merge it with $defaults
574
		 */
575
		$args   = wp_parse_args( $args, $defaults );
576
		$output = '';
577
		$label = '';
578
579
		// hidden label option needs to be empty
580
		$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
581
582
		// floating labels don't work with wysiwyg so set it as top
583
		if ( $args['label_type'] == 'floating' && ! empty( $args['wysiwyg'] ) ) {
584
			$args['label_type'] = 'top';
585
		}
586
587
		$label_after = $args['label_after'];
588
589
		// floating labels need label after
590
		if ( $args['label_type'] == 'floating' && empty( $args['wysiwyg'] ) ) {
591
			$label_after         = true;
592
			$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
593
		}
594
595
		// label
596
		if ( ! empty( $args['label'] ) && is_array( $args['label'] ) ) {
597
		} elseif ( ! empty( $args['label'] ) && ! $label_after ) {
598
			$label_args = array(
599
				'title'      => $args['label'],
600
				'for'        => $args['id'],
601
				'class'      => $args['label_class'] . " ",
602
				'label_type' => $args['label_type'],
603
				'label_col'  => $args['label_col']
604
			);
605
			$label .= self::label( $label_args );
606
		}
607
608
		// maybe horizontal label
609
		if ( $args['label_type'] == 'horizontal' ) {
610
			$input_col = AUI_Component_Helper::get_column_class( $args['label_col'], 'input' );
611
			$label .= '<div class="' . $input_col . '">';
612
		}
613
614
		if ( ! empty( $args['wysiwyg'] ) ) {
615
			ob_start();
616
			$content   = $args['value'];
617
			$editor_id = ! empty( $args['id'] ) ? sanitize_html_class( $args['id'] ) : 'wp_editor';
618
			$settings  = array(
619
				'textarea_rows' => ! empty( absint( $args['rows'] ) ) ? absint( $args['rows'] ) : 4,
620
				'quicktags'     => false,
621
				'media_buttons' => false,
622
				'editor_class'  => 'form-control',
623
				'textarea_name' => ! empty( $args['name'] ) ? sanitize_html_class( $args['name'] ) : sanitize_html_class( $args['id'] ),
624
				'teeny'         => true,
625
			);
626
627
			// maybe set settings if array
628
			if ( is_array( $args['wysiwyg'] ) ) {
629
				$settings = wp_parse_args( $args['wysiwyg'], $settings );
630
			}
631
632
			wp_editor( $content, $editor_id, $settings );
633
			$output .= ob_get_clean();
634
		} else {
635
636
			// open
637
			$output .= '<textarea ';
638
639
			// name
640
			if ( ! empty( $args['name'] ) ) {
641
				$output .= ' name="' . esc_attr( $args['name'] ) . '" ';
642
			}
643
644
			// id
645
			if ( ! empty( $args['id'] ) ) {
646
				$output .= ' id="' . sanitize_html_class( $args['id'] ) . '" ';
647
			}
648
649
			// placeholder
650
			if ( isset( $args['placeholder'] ) && '' != $args['placeholder'] ) {
651
				$output .= ' placeholder="' . esc_attr( $args['placeholder'] ) . '" ';
652
			}
653
654
			// title
655
			if ( ! empty( $args['title'] ) ) {
656
				$output .= ' title="' . esc_attr( $args['title'] ) . '" ';
657
			}
658
659
			// validation text
660
			if ( ! empty( $args['validation_text'] ) ) {
661
				$output .= ' oninvalid="setCustomValidity(\'' . esc_attr( addslashes( $args['validation_text'] ) ) . '\')" ';
662
				$output .= ' onchange="try{setCustomValidity(\'\')}catch(e){}" ';
663
			}
664
665
			// validation_pattern
666
			if ( ! empty( $args['validation_pattern'] ) ) {
667
				$output .= ' pattern="' . esc_attr( $args['validation_pattern'] ) . '" ';
668
			}
669
670
			// required
671
			if ( ! empty( $args['required'] ) ) {
672
				$output .= ' required ';
673
			}
674
675
			// rows
676
			if ( ! empty( $args['rows'] ) ) {
677
				$output .= ' rows="' . absint( $args['rows'] ) . '" ';
678
			}
679
680
681
			// class
682
			$class = ! empty( $args['class'] ) ? $args['class'] : '';
683
			$output .= ' class="form-control ' . $class . '" ';
684
685
			// extra attributes
686
			if ( ! empty( $args['extra_attributes'] ) ) {
687
				$output .= AUI_Component_Helper::extra_attributes( $args['extra_attributes'] );
688
			}
689
690
			// close tag
691
			$output .= '>';
692
693
			// value
694
			if ( ! empty( $args['value'] ) ) {
695
				if ( ! empty( $args['allow_tags'] ) ) {
696
					$output .= AUI_Component_Helper::sanitize_html_field( $args['value'], $args ); // Sanitize HTML.
697
				} else {
698
					$output .= AUI_Component_Helper::sanitize_textarea_field( $args['value'] );
699
				}
700
			}
701
702
			// closing tag
703
			$output .= '</textarea>';
704
705
706
			// input group wraps
707
			if ( $args['input_group_left'] || $args['input_group_right'] ) {
708
				$w100 = strpos( $args['class'], 'w-100' ) !== false ? ' w-100' : '';
709
				if ( $args['input_group_left'] ) {
710
					$output = self::wrap( array(
711
						'content'                 => $output,
712
						'class'                   => $args['input_group_left_inside'] ? 'input-group-inside position-relative' . $w100 : 'input-group',
713
						'input_group_left'        => $args['input_group_left'],
714
						'input_group_left_inside' => $args['input_group_left_inside']
715
					) );
716
				}
717
				if ( $args['input_group_right'] ) {
718
					$output = self::wrap( array(
719
						'content'                  => $output,
720
						'class'                    => $args['input_group_right_inside'] ? 'input-group-inside position-relative' . $w100 : 'input-group',
721
						'input_group_right'        => $args['input_group_right'],
722
						'input_group_right_inside' => $args['input_group_right_inside']
723
					) );
724
				}
725
726
			}
727
728
729
		}
730
731
		if ( ! empty( $args['label'] ) && $label_after ) {
732
			$label_args = array(
733
				'title'      => $args['label'],
734
				'for'        => $args['id'],
735
				'class'      => $args['label_class'] . " ",
736
				'label_type' => $args['label_type'],
737
				'label_col'  => $args['label_col']
738
			);
739
			$output .= self::label( $label_args );
740
		}
741
742
		// help text
743
		if ( ! empty( $args['help_text'] ) ) {
744
			$output .= AUI_Component_Helper::help_text( $args['help_text'] );
745
		}
746
747
		if ( ! $label_after ) {
748
			$output = $label . $output;
749
		}
750
751
		// maybe horizontal label
752
		if ( $args['label_type'] == 'horizontal' ) {
753
			$output .= '</div>';
754
		}
755
756
757
		// wrap
758
		if ( ! $args['no_wrap'] ) {
759
			if ( ! empty( $args['form_group_class'] ) ) {
760
				$fg_class = esc_attr( $args['form_group_class'] );
761
			}else{
762
				$fg_class = $aui_bs5 ? 'mb-3' : 'form-group';
763
			}
764
			$form_group_class = $args['label_type'] == 'floating' ? 'form-label-group' : $fg_class;
765
			$wrap_class       = $args['label_type'] == 'horizontal' ? $form_group_class . ' row' : $form_group_class;
766
			$wrap_class       = ! empty( $args['wrap_class'] ) ? $wrap_class . " " . $args['wrap_class'] : $wrap_class;
767
			$output           = self::wrap( array(
768
				'content'         => $output,
769
				'class'           => $wrap_class,
770
				'element_require' => $args['element_require'],
771
				'argument_id'     => $args['id'],
772
				'wrap_attributes' => $args['wrap_attributes'],
773
			) );
774
		}
775
776
777
		return $output;
778
	}
779
780
	/**
781
	 * Build the component.
782
	 *
783
	 * @param array $args
784
	 *
785
	 * @return string The rendered component.
786
	 */
787
	public static function select( $args = array() ) {
788
		global $aui_bs5, $aui_has_select2, $aui_select2_enqueued;
789
790
		$defaults = array(
791
			'class'            => '',
792
			'wrap_class'       => '',
793
			'id'               => '',
794
			'title'            => '',
795
			'value'            => '',
796
			// can be an array or a string
797
			'required'         => false,
798
			'label'            => '',
799
			'label_after'      => false,
800
			'label_type'       => '',
801
			'label_col'        => '',
802
			// sets the label type, default: hidden. Options: hidden, top, horizontal, floating
803
			'label_class'      => '',
804
			'help_text'        => '',
805
			'placeholder'      => '',
806
			'options'          => array(),
807
			// array or string
808
			'icon'             => '',
809
			'multiple'         => false,
810
			'select2'          => false,
811
			'no_wrap'          => false,
812
			'input_group_right' => '',
813
			'input_group_left' => '',
814
			'input_group_right_inside' => false, // forces the input group inside the input
815
			'input_group_left_inside' => false, // forces the input group inside the input
816
			'form_group_class'  => '',
817
			'element_require'  => '',
818
			// [%element_id%] == "1"
819
			'extra_attributes' => array(),
820
			// an array of extra attributes
821
			'wrap_attributes'  => array(),
822
		);
823
824
		/**
825
		 * Parse incoming $args into an array and merge it with $defaults
826
		 */
827
		$args   = wp_parse_args( $args, $defaults );
828
		$output = '';
829
830
		// for now lets hide floating labels
831
		if ( $args['label_type'] == 'floating' ) {
832
			$args['label_type'] = 'hidden';
833
		}
834
835
		// hidden label option needs to be empty
836
		$args['label_type'] = $args['label_type'] == 'hidden' ? '' : $args['label_type'];
837
838
839
		$label_after = $args['label_after'];
840
841
		// floating labels need label after
842
		if ( $args['label_type'] == 'floating' ) {
843
			$label_after         = true;
844
			$args['placeholder'] = ' '; // set the placeholder not empty so the floating label works.
845
		}
846
847
		// Maybe setup select2
848
		$is_select2 = false;
849
		if ( ! empty( $args['select2'] ) ) {
850
			$args['class'] .= ' aui-select2';
851
			$is_select2 = true;
852
		} elseif ( strpos( $args['class'], 'aui-select2' ) !== false ) {
853
			$is_select2 = true;
854
		}
855
856
		if ( $is_select2 && ! $aui_has_select2 ) {
857
			$aui_has_select2 = true;
858
			$conditional_select2 = apply_filters( 'aui_is_conditional_select2', true );
859
860
			// Enqueue the script,
861
			if ( empty( $aui_select2_enqueued ) && $conditional_select2 === true ) {
862
				$aui_select2_enqueued = true;
863
864
				$aui_settings = AyeCode_UI_Settings::instance();
865
				$aui_settings->enqueue_select2();
866
			}
867
		}
868
869
		// select2 tags
870
		if ( ! empty( $args['select2'] ) && $args['select2'] === 'tags' ) { // triple equals needed here for some reason
871
			$args['data-tags']             = 'true';
872
			$args['data-token-separators'] = "[',']";
873
			$args['multiple']              = true;
874
		}
875
876
		// select2 placeholder
877
		if ( $is_select2 && isset( $args['placeholder'] ) && '' != $args['placeholder'] && empty( $args['data-placeholder'] ) ) {
878
			$args['data-placeholder'] = esc_attr( $args['placeholder'] );
879
			$args['data-allow-clear'] = isset( $args['data-allow-clear'] ) ? (bool) $args['data-allow-clear'] : true;
880
		}
881
882
		// Set hidden input to save empty value for multiselect.
883
		if ( ! empty( $args['multiple'] ) && ! empty( $args['name'] ) ) {
884
			$output .= '<input type="hidden" ' . AUI_Component_Helper::name( $args['name'] ) . ' value="" data-ignore-rule/>';
885
		}
886
887
		// open/type
888
		$output .= '<select ';
889
890
		// style
891
		if ( $is_select2 && !($args['input_group_left'] || $args['input_group_right'])) {
892
			$output .= " style='width:100%;' ";
893
		}
894
895
		// element require
896
		if ( ! empty( $args['element_require'] ) ) {
897
			$output .= AUI_Component_Helper::element_require( $args['element_require'] );
898
			$args['class'] .= " aui-conditional-field";
899
		}
900
901
		// class
902
		$class = ! empty( $args['class'] ) ? $args['class'] : '';
903
		$select_class = $aui_bs5 ? 'form-select ' : 'custom-select ';
904
		$output .= AUI_Component_Helper::class_attr( $select_class . $class );
905
906
		// name
907
		if ( ! empty( $args['name'] ) ) {
908
			$output .= AUI_Component_Helper::name( $args['name'], $args['multiple'] );
909
		}
910
911
		// id
912
		if ( ! empty( $args['id'] ) ) {
913
			$output .= AUI_Component_Helper::id( $args['id'] );
914
		}
915
916
		// title
917
		if ( ! empty( $args['title'] ) ) {
918
			$output .= AUI_Component_Helper::title( $args['title'] );
919
		}
920
921
		// data-attributes
922
		$output .= AUI_Component_Helper::data_attributes( $args );
923
924
		// aria-attributes
925
		$output .= AUI_Component_Helper::aria_attributes( $args );
926
927
		// extra attributes
928
		if ( ! empty( $args['extra_attributes'] ) ) {
929
			$output .= AUI_Component_Helper::extra_attributes( $args['extra_attributes'] );
930
		}
931
932
		// required
933
		if ( ! empty( $args['required'] ) ) {
934
			$output .= ' required';
935
		}
936
937
		// multiple
938
		if ( ! empty( $args['multiple'] ) ) {
939
			$output .= ' multiple';
940
		}
941
942
		// close opening tag
943
		$output .= '>';
944
945
		// placeholder
946
		if ( isset( $args['placeholder'] ) && '' != $args['placeholder'] && ! $is_select2 ) {
947
			$output .= '<option value="" disabled selected hidden>' . esc_attr( $args['placeholder'] ) . '</option>';
948
		} elseif ( $is_select2 && ! empty( $args['placeholder'] ) ) {
949
			$output .= "<option></option>"; // select2 needs an empty select to fill the placeholder
950
		}
951
952
		// Options
953
		if ( ! empty( $args['options'] ) ) {
954
955
			if ( ! is_array( $args['options'] ) ) {
956
				$output .= $args['options']; // not the preferred way but an option
957
			} else {
958
				foreach ( $args['options'] as $val => $name ) {
959
					$selected = '';
960
					if ( is_array( $name ) ) {
961
						if ( isset( $name['optgroup'] ) && ( $name['optgroup'] == 'start' || $name['optgroup'] == 'end' ) ) {
962
							$option_label = isset( $name['label'] ) ? $name['label'] : '';
963
964
							$output .= $name['optgroup'] == 'start' ? '<optgroup label="' . esc_attr( $option_label ) . '">' : '</optgroup>';
965
						} else {
966
							$option_label = isset( $name['label'] ) ? $name['label'] : '';
967
							$option_value = isset( $name['value'] ) ? $name['value'] : '';
968
							$extra_attributes = !empty($name['extra_attributes']) ? AUI_Component_Helper::extra_attributes( $name['extra_attributes'] ) : '';
969
							if ( ! empty( $args['multiple'] ) && ! empty( $args['value'] ) && is_array( $args['value'] ) ) {
970
								$selected = in_array( $option_value, stripslashes_deep( $args['value'] ) ) ? "selected" : "";
0 ignored issues
show
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

970
								$selected = in_array( $option_value, /** @scrutinizer ignore-type */ stripslashes_deep( $args['value'] ) ) ? "selected" : "";
Loading history...
971
							} elseif ( ! empty( $args['value'] ) ) {
972
								$selected = selected( $option_value, stripslashes_deep( $args['value'] ), false );
973
							} elseif ( empty( $args['value'] ) && $args['value'] === $option_value ) {
974
								$selected = selected( $option_value, $args['value'], false );
975
							}
976
977
							$output .= '<option value="' . esc_attr( $option_value ) . '" ' . $selected . ' '.$extra_attributes .'>' . $option_label . '</option>';
978
						}
979
					} else {
980
						if ( ! empty( $args['value'] ) ) {
981
							if ( is_array( $args['value'] ) ) {
982
								$selected = in_array( $val, $args['value'] ) ? 'selected="selected"' : '';
983
							} elseif ( ! empty( $args['value'] ) ) {
984
								$selected = selected( $args['value'], $val, false );
985
							}
986
						} elseif ( $args['value'] === $val ) {
987
							$selected = selected( $args['value'], $val, false );
988
						}
989
						$output .= '<option value="' . esc_attr( $val ) . '" ' . $selected . '>' . esc_attr( $name ) . '</option>';
990
					}
991
				}
992
			}
993
994
		}
995
996
		// closing tag
997
		$output .= '</select>';
998
999
		$label = '';
1000
		$help_text = '';
1001
		// label
1002
		if ( ! empty( $args['label'] ) && is_array( $args['label'] ) ) {
1003
		} elseif ( ! empty( $args['label'] ) && ! $label_after ) {
1004
			$label_args = array(
1005
				'title'      => $args['label'],
1006
				'for'        => $args['id'],
1007
				'class'      => $args['label_class'] . " ",
1008
				'label_type' => $args['label_type'],
1009
				'label_col'  => $args['label_col']
1010
			);
1011
			$label = self::label( $label_args );
1012
		}
1013
1014
		// help text
1015
		if ( ! empty( $args['help_text'] ) ) {
1016
			$help_text = AUI_Component_Helper::help_text( $args['help_text'] );
1017
		}
1018
1019
		// input group wraps
1020
		if ( $args['input_group_left'] || $args['input_group_right'] ) {
1021
			$w100 = strpos( $args['class'], 'w-100' ) !== false ? ' w-100' : '';
1022
			if ( $args['input_group_left'] ) {
1023
				$output = self::wrap( array(
1024
					'content'                 => $output,
1025
					'class'                   => $args['input_group_left_inside'] ? 'input-group-inside position-relative' . $w100 : 'input-group',
1026
					'input_group_left'        => $args['input_group_left'],
1027
					'input_group_left_inside' => $args['input_group_left_inside']
1028
				) );
1029
			}
1030
			if ( $args['input_group_right'] ) {
1031
				$output = self::wrap( array(
1032
					'content'                  => $output,
1033
					'class'                    => $args['input_group_right_inside'] ? 'input-group-inside position-relative' . $w100 : 'input-group',
1034
					'input_group_right'        => $args['input_group_right'],
1035
					'input_group_right_inside' => $args['input_group_right_inside']
1036
				) );
1037
			}
1038
1039
		}
1040
1041
		if ( ! $label_after ) {
1042
			$output .= $help_text;
1043
		}
1044
1045
1046
		if ( $args['label_type'] == 'horizontal' ) {
1047
			$output = self::wrap( array(
1048
				'content' => $output,
1049
				'class'   => AUI_Component_Helper::get_column_class( $args['label_col'], 'input' )
1050
			) );
1051
		}
1052
1053
		if ( ! $label_after ) {
1054
			$output = $label . $output;
1055
		}
1056
1057
		// maybe horizontal label
1058
//		if ( $args['label_type'] == 'horizontal' ) {
1059
//			$output .= '</div>';
1060
//		}
1061
1062
1063
		// wrap
1064
		if ( ! $args['no_wrap'] ) {
1065
			if ( ! empty( $args['form_group_class'] ) ) {
1066
				$fg_class = esc_attr( $args['form_group_class'] );
1067
			}else{
1068
				$fg_class = $aui_bs5 ? 'mb-3' : 'form-group';
1069
			}
1070
			$wrap_class = $args['label_type'] == 'horizontal' ? $fg_class . ' row' : $fg_class;
1071
			$wrap_class = ! empty( $args['wrap_class'] ) ? $wrap_class . " " . $args['wrap_class'] : $wrap_class;
1072
			$output     = self::wrap( array(
1073
				'content'         => $output,
1074
				'class'           => $wrap_class,
1075
				'element_require' => $args['element_require'],
1076
				'argument_id'     => $args['id'],
1077
				'wrap_attributes' => $args['wrap_attributes'],
1078
			) );
1079
		}
1080
1081
1082
		return $output;
1083
	}
1084
1085
	/**
1086
	 * Build the component.
1087
	 *
1088
	 * @param array $args
1089
	 *
1090
	 * @return string The rendered component.
1091
	 */
1092
	public static function radio( $args = array() ) {
1093
		global $aui_bs5;
1094
1095
		$defaults = array(
1096
			'class'            => '',
1097
			'wrap_class'       => '',
1098
			'id'               => '',
1099
			'title'            => '',
1100
			'horizontal'       => false,
1101
			// sets the lable horizontal
1102
			'value'            => '',
1103
			'label'            => '',
1104
			'label_class'      => '',
1105
			'label_type'       => '',
1106
			'label_col'        => '',
1107
			// sets the label type, default: hidden. Options: hidden, top, horizontal, floating
1108
			'help_text'        => '',
1109
			'inline'           => true,
1110
			'required'         => false,
1111
			'options'          => array(),
1112
			'icon'             => '',
1113
			'no_wrap'          => false,
1114
			'element_require'  => '',
1115
			// [%element_id%] == "1"
1116
			'extra_attributes' => array(),
1117
			// an array of extra attributes
1118
			'wrap_attributes'  => array()
1119
		);
1120
1121
		/**
1122
		 * Parse incoming $args into an array and merge it with $defaults
1123
		 */
1124
		$args = wp_parse_args( $args, $defaults );
1125
1126
		// for now lets use horizontal for floating
1127
		if ( $args['label_type'] == 'floating' ) {
1128
			$args['label_type'] = 'horizontal';
1129
		}
1130
1131
		$label_args = array(
1132
			'title'      => $args['label'],
1133
			'class'      => $args['label_class'] . " pt-0 ",
1134
			'label_type' => $args['label_type'],
1135
			'label_col'  => $args['label_col']
1136
		);
1137
1138
		if ( $args['label_type'] == 'top' || $args['label_type'] == 'hidden' ) {
1139
			$label_args['class'] .= 'd-block ';
1140
1141
			if ( $args['label_type'] == 'hidden' ) {
1142
				$label_args['class'] .= 'sr-only ' . ( $aui_bs5 ? 'visually-hidden ' : '' );
1143
			}
1144
		}
1145
1146
		$output = '';
1147
1148
		// label before
1149
		if ( ! empty( $args['label'] ) ) {
1150
			$output .= self::label( $label_args, 'radio' );
1151
		}
1152
1153
		// maybe horizontal label
1154
		if ( $args['label_type'] == 'horizontal' ) {
1155
			$input_col = AUI_Component_Helper::get_column_class( $args['label_col'], 'input' );
1156
			$output .= '<div class="' . $input_col . '">';
1157
		}
1158
1159
		if ( ! empty( $args['options'] ) ) {
1160
			$count = 0;
1161
			foreach ( $args['options'] as $value => $label ) {
1162
				$option_args            = $args;
1163
				$option_args['value']   = $value;
1164
				$option_args['label']   = $label;
1165
				$option_args['checked'] = $value == $args['value'] ? true : false;
1166
				$output .= self::radio_option( $option_args, $count );
1167
				$count ++;
1168
			}
1169
		}
1170
1171
		// help text
1172
		$help_text = ! empty( $args['help_text'] ) ? AUI_Component_Helper::help_text( $args['help_text'] ) : '';
1173
		$output .= $help_text;
1174
1175
		// maybe horizontal label
1176
		if ( $args['label_type'] == 'horizontal' ) {
1177
			$output .= '</div>';
1178
		}
1179
1180
		// wrap
1181
		$fg_class = $aui_bs5 ? 'mb-3' : 'form-group';
1182
		$wrap_class = $args['label_type'] == 'horizontal' ? $fg_class . ' row' : $fg_class;
1183
		$wrap_class = ! empty( $args['wrap_class'] ) ? $wrap_class . " " . $args['wrap_class'] : $wrap_class;
1184
		$output     = self::wrap( array(
1185
			'content'         => $output,
1186
			'class'           => $wrap_class,
1187
			'element_require' => $args['element_require'],
1188
			'argument_id'     => $args['id'],
1189
			'wrap_attributes' => $args['wrap_attributes'],
1190
		) );
1191
1192
1193
		return $output;
1194
	}
1195
1196
	/**
1197
	 * Build the component.
1198
	 *
1199
	 * @param array $args
1200
	 *
1201
	 * @return string The rendered component.
1202
	 */
1203
	public static function radio_option( $args = array(), $count = '' ) {
1204
		$defaults = array(
1205
			'class'            => '',
1206
			'id'               => '',
1207
			'title'            => '',
1208
			'value'            => '',
1209
			'required'         => false,
1210
			'inline'           => true,
1211
			'label'            => '',
1212
			'options'          => array(),
1213
			'icon'             => '',
1214
			'no_wrap'          => false,
1215
			'extra_attributes' => array() // an array of extra attributes
1216
		);
1217
1218
		/**
1219
		 * Parse incoming $args into an array and merge it with $defaults
1220
		 */
1221
		$args = wp_parse_args( $args, $defaults );
1222
1223
		$output = '';
1224
1225
		// open/type
1226
		$output .= '<input type="radio"';
1227
1228
		// class
1229
		$output .= ' class="form-check-input" ';
1230
1231
		// name
1232
		if ( ! empty( $args['name'] ) ) {
1233
			$output .= AUI_Component_Helper::name( $args['name'] );
1234
		}
1235
1236
		// id
1237
		if ( ! empty( $args['id'] ) ) {
1238
			$output .= AUI_Component_Helper::id( $args['id'] . $count );
1239
		}
1240
1241
		// title
1242
		if ( ! empty( $args['title'] ) ) {
1243
			$output .= AUI_Component_Helper::title( $args['title'] );
1244
		}
1245
1246
		// value
1247
		if ( isset( $args['value'] ) ) {
1248
			$output .= AUI_Component_Helper::value( $args['value'] );
1249
		}
1250
1251
		// checked, for radio and checkboxes
1252
		if ( $args['checked'] ) {
1253
			$output .= ' checked ';
1254
		}
1255
1256
		// data-attributes
1257
		$output .= AUI_Component_Helper::data_attributes( $args );
1258
1259
		// aria-attributes
1260
		$output .= AUI_Component_Helper::aria_attributes( $args );
1261
1262
		// extra attributes
1263
		if ( ! empty( $args['extra_attributes'] ) ) {
1264
			$output .= AUI_Component_Helper::extra_attributes( $args['extra_attributes'] );
1265
		}
1266
1267
		// required
1268
		if ( ! empty( $args['required'] ) ) {
1269
			$output .= ' required';
1270
		}
1271
1272
		// close opening tag
1273
		$output .= '>';
1274
1275
		// label
1276
		if ( ! empty( $args['label'] ) && is_array( $args['label'] ) ) {
1277
		} elseif ( ! empty( $args['label'] ) ) {
1278
			$output .= self::label( array(
1279
				'title' => $args['label'],
1280
				'for'   => $args['id'] . $count,
1281
				'class' => 'form-check-label'
1282
			), 'radio' );
1283
		}
1284
1285
		// wrap
1286
		if ( ! $args['no_wrap'] ) {
1287
			$wrap_class = $args['inline'] ? 'form-check form-check-inline' : 'form-check';
1288
1289
			// Unique wrap class
1290
			$uniq_class = 'fwrap';
1291
			if ( ! empty( $args['name'] ) ) {
1292
				$uniq_class .= '-' . $args['name'];
1293
			} else if ( ! empty( $args['id'] ) ) {
1294
				$uniq_class .= '-' . $args['id'];
1295
			}
1296
1297
			if ( isset( $args['value'] ) || $args['value'] !== "" ) {
1298
				$uniq_class .= '-' . $args['value'];
1299
			} else {
1300
				$uniq_class .= '-' . $count;
1301
			}
1302
			$wrap_class .= ' ' . sanitize_html_class( $uniq_class );
1303
1304
			$output = self::wrap( array(
1305
				'content' => $output,
1306
				'class'   => $wrap_class
1307
			) );
1308
		}
1309
1310
		return $output;
1311
	}
1312
1313
}