Completed
Push — issues/1038 ( 4de421...288e28 )
by Ravinder
20:47
created

Give_Fields_API::sort_fields()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 3
nop 2
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Fields API
5
 *
6
 * @package     Give
7
 * @subpackage  Classes/Give_Fields_API
8
 * @copyright   Copyright (c) 2016, WordImpress
9
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
10
 * @since       2.0
11
 */
12
class Give_Fields_API {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
13
	/**
14
	 * Instance.
15
	 *
16
	 * @since  2.0
17
	 * @access private
18
	 * @var Give_Fields_API
19
	 */
20
	static private $instance;
21
22
	/**
23
	 * The defaults for all elements
24
	 *
25
	 * @since  2.0
26
	 * @access static
27
	 */
28
	static $field_defaults = array(
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $field_defaults.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
29
		'type'                 => '',
30
		'id'                   => '',
31
		'data_type'            => '',
32
		'value'                => null,
33
		'required'             => false,
34
		'options'              => array(),
35
36
		// Set default value to field.
37
		'default'              => null,
38
39
		// Set checkbox value.
40
		'cbvalue'              => 'on',
41
42
		// Field with wrapper.
43
		'wrapper'              => true,
44
		'wrapper_type'         => 'p',
45
46
		// Add label, before and after field.
47
		'label'                => '',
48
		// By default label position is before but in case of radio field it will change to after.
49
		'label_position'       => 'before',
50
		'label_tooltip'        => '',
51
52
		// Show multiple fields in same row with in sub section.
53
		'sub_section_start'    => false,
54
		'sub_section_end'      => false,
55
56
		// Sortable.
57
		'sortable'             => false,
58
		'sortable-icon'        => false,
59
60
		// Set position of field.
61
		// By default it will set to zero but in case of submit type field it will change to 9999.
62
		'priority'             => 0,
63
64
		// Add custom attributes.
65
		'label_attributes'     => array(),
66
		'field_attributes'     => array(),
67
		'wrapper_attributes'   => array(),
68
		'ul_attributes'        => array(),
69
70
		// Show/Hide field in before/after modal view.
71
		'show_without_modal'   => false,
72
		'show_within_modal'    => true,
73
74
		// Params to edit field html.
75
		// They accept callback or string input.
76
		'before_field'         => '',
77
		'after_field'          => '',
78
		'before_field_wrapper' => '',
79
		'after_field_wrapper'  => '',
80
		'before_field_label'   => '',
81
		'after_field_label'    => '',
82
83
		// Manually render field.
84
		'callback'             => '',
85
	);
86
87
	/**
88
	 * The defaults for all sections.
89
	 *
90
	 * @since  2.0
91
	 * @access static
92
	 */
93
	static $section_defaults = array(
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $section_defaults.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
94
		'type'                 => 'section',
95
		'label'                => '',
96
		'id'                   => '',
97
		'label_attributes'     => array(),
98
		'section_attributes'   => array(),
99
100
		// Set position of field.
101
		'priority'             => 0,
102
103
		// Manually render section.
104
		'callback'             => '',
105
106
		// Params to edit field html.
107
		// They accept callback or string input.
108
		'before_field_wrapper' => '',
109
		'after_field_wrapper'  => '',
110
		'before_field_label'   => '',
111
		'after_field_label'    => '',
112
	);
113
114
	/**
115
	 * The defaults for all blocks.
116
	 *
117
	 * @since  2.0
118
	 * @access static
119
	 */
120
	static $block_defaults = array(
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $block_defaults.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
121
		'type'             => 'block',
122
		'label'            => '',
123
		'id'               => '',
124
		'label_attributes' => array(),
125
		'block_attributes' => array(),
126
127
		// Set position of field.
128
		'priority'         => 0,
129
130
		// Manually render section.
131
		'callback'         => '',
132
	);
133
134
135
	private function __construct() {
136
	}
137
138
139
	/**
140
	 * Get instance.
141
	 *
142
	 * @return static
143
	 */
144
	public static function get_instance() {
145
		if ( is_null( static::$instance ) ) {
0 ignored issues
show
Bug introduced by
Since $instance is declared private, accessing it with static will lead to errors in possible sub-classes; consider using self, or increasing the visibility of $instance to at least protected.

Let’s assume you have a class which uses late-static binding:

class YourClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return static::$someVariable;
    }
}

The code above will run fine in your PHP runtime. However, if you now create a sub-class and call the getSomeVariable() on that sub-class, you will receive a runtime error:

class YourSubClass extends YourClass { }

YourSubClass::getSomeVariable(); // Will cause an access error.

In the case above, it makes sense to update SomeClass to use self instead:

class SomeClass
{
    private static $someVariable;

    public static function getSomeVariable()
    {
        return self::$someVariable; // self works fine with private.
    }
}
Loading history...
146
			self::$instance = new static();
147
		}
148
149
		return self::$instance;
150
	}
151
152
	/**
153
	 * Initialize this module
154
	 *
155
	 * @since  2.0
156
	 * @access static
157
	 */
158
	public function init() {
159
		add_filter( 'give_form_api_render_form_tags', array( $this, 'render_tags' ), 10, 2 );
160
	}
161
162
163
	/**
164
	 * Render callback.
165
	 *
166
	 * @since  2.0
167
	 * @access public
168
	 *
169
	 * @param       $callback
170
	 * @param array $field
171
	 * @param null  $form
172
	 *
173
	 * @return string
174
	 */
175
	public static function render_callback( $callback, $field = array(), $form = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
176
		$field_html = '';
177
178
		if ( empty( $callback ) || ! self::is_callback( $callback ) ) {
179
			return $field_html;
180
		}
181
182
		// Process callback to get field html.
183
		if ( is_string( $callback ) && function_exists( "$callback" ) ) {
184
			$field_html = $callback( $field );
185
		} elseif ( is_array( $callback ) && method_exists( $callback[0], "$callback[1]" ) ) {
186
			$field_html = $callback[0]->$callback[1]( $field );
187
		}
188
189
		return $field_html;
190
	}
191
192
193
	/**
194
	 * Render custom field.
195
	 *
196
	 * @since  1.0
197
	 * @access private
198
	 *
199
	 * @param array $field
200
	 * @param array $form
201
	 *
202
	 * @return string
203
	 */
204
	private function render_custom_field( $field, $form = null ) {
205
		$field_html = '';
206
207
		if ( ! empty( $field['callback'] ) ) {
208
			$field = self::$instance->set_default_values( $field, $form );
209
210
			$callback   = $field['callback'];
211
			$field_html = self::render_callback( $callback, $field, $form );
212
		}
213
214
		return $field_html;
215
	}
216
217
218
	/**
219
	 * Render `{{form_fields}}` tag.
220
	 *
221
	 * @since  2.0
222
	 * @access private
223
	 *
224
	 * @param  string $form_html
225
	 * @param  array  $form
226
	 *
227
	 * @return string
228
	 */
229
	public function render_tags( $form_html, $form ) {
230
		// Bailout: If form does not contain any field.
231
		if ( empty( $form['fields'] ) ) {
232
			str_replace( '{{form_fields}}', '', $form_html );
233
234
			return $form_html;
235
		}
236
237
		$fields_html = '';
238
239
		// Set responsive fields.
240
		self::$instance->set_responsive_field( $form );
241
242
		// Sort field with field priority for frontenf appearance.
243
		$form['fields'] = self::$instance->sort_fields( $form['fields'], $form );
244
245
		// Render fields.
246
		foreach ( $form['fields'] as $key => $field ) {
247
			// Set default value.
248
			$field['id'] = empty( $field['id'] ) ? $key : $field['id'];
249
250
			// Render custom form with callback.
251
			if ( $field_html = self::$instance->render_custom_field( $field, $form ) ) {
252
				$fields_html .= $field_html;
253
			}
254
255
			switch ( true ) {
256
				// Block.
257
				case ( 'block' === self::get_field_type( $field ) ):
258
					$fields_html .= self::$instance->render_block( $field, $form );
259
					break;
260
261
				// Section.
262
				case ( 'section' === self::get_field_type( $field ) ):
263
					$fields_html .= self::$instance->render_section( $field, $form );
264
					break;
265
266
				// Field
267
				default:
268
					$fields_html .= self::render_tag( $field, $form );
269
			}
270
		}
271
272
		$form_html = str_replace( '{{form_fields}}', $fields_html, $form_html );
273
274
		return $form_html;
275
	}
276
277
278
	/**
279
	 * Render section.
280
	 *
281
	 * @since  2.0
282
	 * @access public
283
	 *
284
	 * @param array $section
285
	 * @param array $form
286
	 * @param array $args Helper argument to render section.
287
	 *
288
	 * @return string
289
	 */
290
	public static function render_section( $section, $form = null, $args = array() ) {
291
		// Set default values if necessary.
292
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
293
			$section = self::$instance->set_default_values( $section, $form );
294
		}
295
296
		ob_start();
297
298
		// Set before section html.
299
		$section['before_field_wrapper'] = self::is_callback( $section['before_field_wrapper'] )
300
			? self::render_callback( $section['before_field_wrapper'] )
301
			: $section['before_field_wrapper'];
302
303
		// Set after section html.
304
		$section['after_field_wrapper'] = self::is_callback( $section['after_field_wrapper'] )
305
			? self::render_callback( $section['after_field_wrapper'] )
306
			: $section['after_field_wrapper'];
307
308
		// Set before section legend html.
309
		$section['before_field_label'] = self::is_callback( $section['before_field_label'] )
310
			? self::render_callback( $section['before_field_label'] )
311
			: $section['before_field_label'];
312
313
		// Set after section legend html.
314
		$section['after_field_label'] = self::is_callback( $section['after_field_label'] )
315
			? self::render_callback( $section['after_field_label'] )
316
			: $section['after_field_label'];
317
318
		echo $section['before_field_wrapper'];
319
		?>
320
		<fieldset <?php echo self::$instance->get_attributes( $section['section_attributes'] ); ?>>
321
			<?php
322
			// Legend.
323
			if ( ! empty( $section['label'] ) ) {
324
				echo $section['before_field_label'];
325
				echo "<legend " . self::get_attributes( $section['label_attributes'] ) . ">{$section['label']}</legend>";
326
				echo $section['after_field_label'];
327
			};
328
329
			// Fields.
330
			foreach ( $section['fields'] as $key => $field ) {
331
				echo self::render_tag( $field, $form, array( 'set_default' => false ) );
332
			}
333
			?>
334
		</fieldset>
335
		<?php
336
		echo $section['after_field_wrapper'];
337
338
		$section_html = ob_get_clean();
339
340
		/**
341
		 * Filter the section html.
342
		 *
343
		 * @since 2.0
344
		 *
345
		 * @param string $section_html
346
		 * @param array  $field
347
		 * @param array  $form
348
		 */
349
		$section_html = apply_filters(
350
			"give_field_api_render_section",
351
			$section_html,
352
			$section,
353
			$form,
354
			$args
355
		);
356
357
		return $section_html;
358
	}
359
360
361
	/**
362
	 * Render block.
363
	 *
364
	 * @since  2.0
365
	 * @access public
366
	 *
367
	 * @param array $block
368
	 * @param array $form
369
	 * @param array $args Helper argument to render section.
370
	 *
371
	 * @return string
372
	 */
373
	public static function render_block( $block, $form = null, $args = array() ) {
374
		// Set default values if necessary.
375
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
376
			$block = self::$instance->set_default_values( $block, $form );
377
		}
378
379
		ob_start();
380
		?>
381
		<div <?php echo self::$instance->get_attributes( $block['block_attributes'] ); ?>>
382
			<?php
383
			// Fields.
384
			foreach ( $block['fields'] as $key => $field ) {
385
				echo array_key_exists( 'fields', $field )
386
					? self::render_section( $field, $form, array( 'set_default' => false ) )
387
					: self::render_tag( $field, $form, array( 'set_default' => false ) );
388
			}
389
			?>
390
		</div>
391
		<?php
392
		$block_html = ob_get_clean();
393
394
		/**
395
		 * Filter the block html.
396
		 *
397
		 * @since 2.0
398
		 *
399
		 * @param string $block_html
400
		 * @param array  $field
401
		 * @param array  $form
402
		 */
403
		$block_html = apply_filters(
404
			"give_field_api_render_block",
405
			$block_html,
406
			$block,
407
			$form,
408
			$args
409
		);
410
411
		return $block_html;
412
	}
413
414
	/**
415
	 * Render tag
416
	 *
417
	 * @since   2.0
418
	 * @access  public
419
	 *
420
	 * @param array $field
421
	 * @param array $form
422
	 * @param array $args Helper argument to render section.
423
	 *
424
	 * @return string
425
	 */
426
	public static function render_tag( $field, $form = null, $args = array() ) {
427
		// Enqueue scripts.
428
		Give_Form_API::enqueue_scripts();
429
430
		if ( ! empty( $field['sortable'] ) ) {
431
			wp_enqueue_script( 'jquery-ui-sortable' );
432
		}
433
434
		// Set default values if necessary.
435
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
436
			$field = self::$instance->set_default_values( $field, $form );
437
		}
438
439
		$field_html     = '';
440
		$functions_name = "render_{$field['type']}_field";
441
442
		if ( 'section' === self::$instance->get_field_type( $field ) ) {
443
			$field_html = self::$instance->render_section( $field, $form, array( 'set_default' => false ) );
444
445
		} elseif ( method_exists( self::$instance, $functions_name ) ) {
446
			$field_html = self::$instance->{$functions_name}( $field, $form, $args );
447
448
		}
449
450
		/**
451
		 * Filter the custom field type html.
452
		 * Developer can use this hook to render custom field type.
453
		 *
454
		 * @since 2.0
455
		 *
456
		 * @param string $field_html
457
		 * @param array  $field
458
		 * @param array  $form
459
		 */
460
		$field_html = apply_filters(
461
			"give_field_api_render_{$field['type']}_field",
462
			$field_html,
463
			$field,
464
			$form,
465
			$args
466
		);
467
468
		/**
469
		 * Filter the all field type html.
470
		 *
471
		 * @since 2.0
472
		 *
473
		 * @param string $field_html
474
		 * @param array  $field
475
		 * @param array  $form
476
		 */
477
		$field_html = apply_filters(
478
			"give_field_api_render_field",
479
			$field_html,
480
			$field,
481
			$form,
482
			$args
483
		);
484
485
		return $field_html;
486
	}
487
488
489
	/**
490
	 * Render text field.
491
	 *
492
	 * @since  2.0
493
	 * @access public
494
	 *
495
	 * @param  array $field
496
	 * @param  array $form
497
	 * @param  array $args
498
	 *
499
	 * @return string
500
	 */
501
	public static function render_text_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
502
		$field_wrapper                     = self::$instance->render_field_wrapper( $field );
503
		$field['field_attributes']['name'] = self::get_field_name( $field );
504
		$field['field_attributes']['type'] = $field['type'];
505
506
		if ( ! empty( $field['required'] ) ) {
507
			$field['field_attributes']['required']      = 'required';
508
			$field['field_attributes']['aria-required'] = 'true';
509
		}
510
511
		ob_start();
512
513
		echo '<input ' . self::$instance->get_attributes( $field['field_attributes'] ) . '>';
514
515
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
516
	}
517
518
	/**
519
	 * Render submit field.
520
	 *
521
	 * @since  2.0
522
	 * @access public
523
	 *
524
	 * @param  array $field
525
	 * @param  array $form
526
	 * @param  array $args
527
	 *
528
	 * @return string
529
	 */
530
	public static function render_submit_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
531
		return self::$instance->render_text_field( $field );
532
	}
533
534
	/**
535
	 * Render checkbox field.
536
	 *
537
	 * @since  2.0
538
	 * @access public
539
	 *
540
	 * @param  array $field
541
	 * @param  array $form
542
	 * @param  array $args
543
	 *
544
	 * @return string
545
	 */
546
	public static function render_checkbox_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
547
		return self::$instance->render_text_field( $field );
548
	}
549
550
	/**
551
	 * Render email field.
552
	 *
553
	 * @since  2.0
554
	 * @access public
555
	 *
556
	 * @param  array $field
557
	 * @param  array $form
558
	 * @param  array $args
559
	 *
560
	 * @return string
561
	 */
562
	public static function render_email_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
563
		return self::$instance->render_text_field( $field );
564
	}
565
566
	/**
567
	 * Render number field.
568
	 *
569
	 * @since  2.0
570
	 * @access public
571
	 *
572
	 * @param  array $field
573
	 * @param  array $form
574
	 * @param  array $args
575
	 *
576
	 * @return string
577
	 */
578
	public static function render_number_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
579
		return self::$instance->render_text_field( $field );
580
	}
581
582
	/**
583
	 * Render password field.
584
	 *
585
	 * @since  2.0
586
	 * @access public
587
	 *
588
	 * @param  array $field
589
	 * @param  array $form
590
	 * @param  array $args
591
	 *
592
	 * @return string
593
	 */
594
	public static function render_password_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
595
		return self::$instance->render_text_field( $field );
596
	}
597
598
	/**
599
	 * Render button field.
600
	 *
601
	 * @since  2.0
602
	 * @access public
603
	 *
604
	 * @param  array $field
605
	 * @param  array $form
606
	 * @param  array $args
607
	 *
608
	 * @return string
609
	 */
610
	public static function render_button_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
611
		return self::$instance->render_text_field( $field );
612
	}
613
614
	/**
615
	 * Render hidden field.
616
	 *
617
	 * @since  2.0
618
	 * @access public
619
	 *
620
	 * @param  array $field
621
	 * @param  array $form
622
	 * @param  array $args
623
	 *
624
	 * @return string
625
	 */
626
	public static function render_hidden_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
627
		$field['wrapper'] = false;
628
629
		return self::$instance->render_text_field( $field );
630
	}
631
632
	/**
633
	 * Render textarea field.
634
	 *
635
	 * @since  2.0
636
	 * @access public
637
	 *
638
	 * @param  array $field
639
	 * @param  array $form
640
	 * @param  array $args
641
	 *
642
	 * @return string
643
	 */
644
	public static function render_textarea_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
645
		$field_wrapper = self::$instance->render_field_wrapper( $field );
646
		ob_start();
647
		?>
648
		<textarea
649
				name="<?php echo self::get_field_name( $field ); ?>"
650
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
651
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
652
		><?php echo $field ['value']; ?></textarea>
653
654
655
		<?php
656
657
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
658
	}
659
660
	/**
661
	 * Render select field.
662
	 *
663
	 * @since  2.0
664
	 * @access public
665
	 *
666
	 * @param  array $field
667
	 * @param  array $form
668
	 * @param  array $args
669
	 *
670
	 * @return string
671
	 */
672
	public static function render_select_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
673
		$field_wrapper = self::$instance->render_field_wrapper( $field );
674
		ob_start();
675
676
		$options_html = '';
677
		foreach ( $field['options'] as $key => $option ) {
678
			$options_html .= '<option ' . self::get_attributes( $option['field_attributes'] ) . '>' . $option['label'] . '</option>';
679
		}
680
		?>
681
682
		<select
683
				name="<?php echo self::get_field_name( $field ); ?>"
684
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
685
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
686
		><?php echo $options_html; ?></select>
687
		<?php
688
689
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
690
	}
691
692
	/**
693
	 * Render multi select field.
694
	 *
695
	 * @since  2.0
696
	 * @access public
697
	 *
698
	 * @param  array $field
699
	 * @param  array $form
700
	 * @param  array $args
701
	 *
702
	 * @return string
703
	 */
704
	public static function render_multi_select_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
705
		$field['field_attributes'] = array_merge( $field['field_attributes'], array( 'multiple' => 'multiple' ) );
706
		$field['id']               = "{$field['id']}[]";
707
708
		return self::$instance->render_select_field( $field );
709
	}
710
711
	/**
712
	 * Render radio field.
713
	 *
714
	 * @since  2.0
715
	 * @access public
716
	 *
717
	 * @param  array $field
718
	 * @param  array $form
719
	 * @param  array $args
720
	 *
721
	 * @return string
722
	 */
723
	public static function render_radio_field( $field, $form = null, $args = array() ) {
724
		$field['wrapper_type'] = 'p' === $field['wrapper_type']
725
			? 'fieldset'
726
			: $field['wrapper_type'];
727
728
729
		$field_wrapper = self::$instance->render_field_wrapper( $field, $form, $args );
730
731
		ob_start();
732
733
		$id_base = $field['field_attributes']['id'];
734
		unset( $field['field_attributes']['id'] );
735
736
		$field['ul_attributes']['class'] = empty( $field['ul_attributes']['class'] )
737
			? 'give-radio-fields'
738
			: "give-radio-fields {$field['ul_attributes']['class']}";
739
740
		echo '<ul ' . self::get_attributes( $field['ul_attributes'] ) . '>';
741
		foreach ( $field['options'] as $key => $option ) :
742
			$option['label_position'] = ! empty( $option['label_position'] )
743
				? $option['label_position']
744
				: 'after';
745
746
			$option = wp_parse_args( $option, self::$field_defaults );
747
748
			$option['field_attributes']['type'] = $field['type'];
749
			$option['field_attributes']['name'] = self::get_field_name( $field );
750
751
			$option['field_attributes']['id'] = ! empty( $option['field_attributes']['id'] )
752
				? $option['field_attributes']['id']
753
				: "{$id_base}-{$key}-" . uniqid();
754
755
			$option['label_attributes']['for'] = ! empty( $option['label_attributes']['for'] )
756
				? $option['label_attributes']['for']
757
				: $option['field_attributes']['id'];
758
759
760
			$option['label_attributes']['class'] = empty( $option['label_attributes']['class'] )
761
				? 'give-label'
762
				: "give-label {$option['label_attributes']['class']}";
763
764
			?>
765
			<li>
766
				<?php
767
				echo str_replace(
768
					'{{form_field}}',
769
					'<input ' . self::$instance->get_attributes( $option['field_attributes'] ) . '>',
770
					self::get_field_template( $option, $form, $args )
771
				);
772
				?>
773
			</li>
774
			<?php
775
		endforeach;
776
		echo '</ul>';
777
778
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
779
	}
780
781
	/**
782
	 * Render multi checkbox field.
783
	 *
784
	 * Note:
785
	 * You can reorder checklist if sortable with help of give_reorder_array function.
786
	 *
787
	 * @since  2.0
788
	 * @access public
789
	 *
790
	 * @param  array $field
791
	 * @param  array $form
792
	 * @param  array $args
793
	 *
794
	 * @return string
795
	 */
796
	public static function render_multi_checkbox_field( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
797
		// Field wrapper.
798
		$field['wrapper_type'] = 'p' === $field['wrapper_type']
799
			? 'fieldset'
800
			: $field['wrapper_type'];
801
802
		// Field value.
803
		$field['value'] = is_array( $field['value'] )
804
			? $field['value']
805
			: array();
806
807
		// Field type.
808
		$field['field_attributes']['type'] = 'checkbox';
809
810
		// Field name.
811
		$field['field_attributes']['name'] = self::get_field_name( $field ) . '[]';
812
813
		$field_wrapper = self::$instance->render_field_wrapper( $field );
814
		ob_start();
815
816
		$id_base = $field['field_attributes']['id'];
817
		unset( $field['field_attributes']['id'] );
818
819
		// Set ul attributes.
820
		$field['ul_attributes']['class']                      = empty( $field['ul_attributes']['class'] )
821
			? 'give-checklist-fields'
822
			: "give-checklist-fields {$field['ul_attributes']['class']}";
823
		$field['ul_attributes']['data-give-sortable-list']    = absint( $field['sortable'] );
824
		$field['ul_attributes']['data-give-sortable-icon']    = absint( $field['sortable-icon'] );
825
826
		echo '<ul ' . self::get_attributes( $field['ul_attributes'] ) . '>';
827
828
		foreach ( $field['options'] as $key => $option ) :
829
			// Set basic values for field.
830
			$option = is_array( $option ) ? $option : array( 'label' => $option );
831
			$option['field_attributes']['id']                 = "give-{$id_base}-{$key}";
832
			$option['field_attributes']['data-give-required'] = ( $field['required'] ? 1 : 0 );
833
			$option['field_attributes']['value']              = empty( $option['field_attributes']['value'] )
834
				? $key
835
				: $option['field_attributes']['value'];
836
837
			// Check if field checked or not.
838
			if (
839
				! empty( $field['value'] ) && in_array( $key, $field['value'] )
840
				|| (
841
					( ! empty( $field['repeater_default_template'] ) || ! empty( $field['repeater_template'] ) )
842
					&& is_array( $option )
843
					&& ! empty( $option['checked'] )
844
				)
845
			) {
846
				$option['field_attributes']['checked'] = 'checked';
847
			}
848
849
			// Add extra attribute per checkbox.
850
			$option['field_attributes'] = is_array( $option ) && ! empty( $option['field_attributes'] )
851
				? array_merge( $field['field_attributes'], $option['field_attributes'] )
852
				: $field['field_attributes'];
853
854
			// Add field specific class.
855
			$option['field_attributes']['class'] = trim( "{$option['field_attributes']['class']} give-{$key}" );
856
			?>
857
			<li>
858
				<label class="give-label" for="<?php echo $option['field_attributes']['id']; ?>">
859
					<input <?php echo self::$instance->get_attributes( $option['field_attributes'] ); ?>><?php echo( ! is_array( $option ) ? $option : ( isset( $option['label'] ) ? $option['label'] : '' ) ); ?>
860
				</label>
861
			</li>
862
			<?php
863
		endforeach;
864
865
		echo '</ul>';
866
867
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
868
	}
869
870
871
	/**
872
	 * Render group field
873
	 *
874
	 * @since  2.0
875
	 * @access public
876
	 *
877
	 * @param  array $fields
878
	 * @param  array $form
879
	 * @param  array $args
880
	 *
881
	 * @return string
882
	 */
883
	public static function render_group_field( $fields, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
884
		// Bailout.
885
		if ( ! isset( $fields['fields'] ) || empty( $fields['fields'] ) ) {
886
			return '';
887
		}
888
889
		$group_numbering       = isset( $fields['options']['group_numbering'] ) ? (int) $fields['options']['group_numbering'] : 0;
890
		$close_tabs            = isset( $fields['options']['close_tabs'] ) ? (int) $fields['options']['close_tabs'] : 0;
891
		$repeater_field_values = $fields['value'];
892
		$header_title          = isset( $fields['options']['header_title'] )
893
			? $fields['options']['header_title']
894
			: esc_attr__( 'Group', 'give' );
895
896
		$add_default_donation_field = false;
897
898
		// Check if level is not created or we have to add default level.
899
		if ( is_array( $repeater_field_values ) && ( $fields_count = count( $repeater_field_values ) ) ) {
900
			$repeater_field_values = array_values( $repeater_field_values );
901
		} else {
902
			$fields_count               = 1;
903
			$add_default_donation_field = true;
904
		}
905
906
		$field_wrapper = self::$instance->render_field_wrapper( $fields );
907
908
		ob_start();
909
		?>
910
		<div class="give-repeatable-field-section" id="<?php echo "{$fields['id']}_field"; ?>"
911
			 data-group-numbering="<?php echo $group_numbering; ?>" data-close-tabs="<?php echo $close_tabs; ?>">
912
			<?php if ( ! empty( $fields['label'] ) ) : ?>
913
				<p class="give-repeater-field-name"><?php echo $fields['label']; ?></p>
914
			<?php endif; ?>
915
916
			<?php if ( ! empty( $fields['description'] ) ) : ?>
917
				<p class="give-repeater-field-description"><?php echo $fields['description']; ?></p>
918
			<?php endif; ?>
919
920
			<table class="give-repeatable-fields-section-wrapper" cellspacing="0">
921
				<tbody class="container"<?php echo " data-rf-row-count=\"{$fields_count}\""; ?>>
922
					<!--Repeater field group template-->
923
					<tr class="give-template give-row">
924
						<td class="give-repeater-field-wrap give-column" colspan="2">
925
							<div class="give-row-head give-move">
926
								<button type="button" class="give-toggle-btn">
927
									<span class="give-toggle-indicator"></span>
928
								</button>
929
								<span class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">-</span>
930
								<h2>
931
									<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
932
								</h2>
933
							</div>
934
							<div class="give-row-body">
935
								<?php
936
								foreach ( $fields['fields'] as $field_id => $field ) :
937
									$field['id']                = ! empty( $field['id'] ) ? $field['id'] : $field_id;
938
									$field['repeat']            = true;
939
									$field['repeater_template'] = true;
940
941
									$field['repeater_field_name']    = self::get_repeater_field_name( $field, $fields );
942
									$field['field_attributes']['id'] = str_replace( array( '[', ']' ), array(
943
										'_',
944
										'',
945
									), $field['repeater_field_name'] );
946
947
									echo self::render_tag( $field, $form );
948
								endforeach;
949
								?>
950
							</div>
951
						</td>
952
					</tr>
953
954
					<?php if ( ! empty( $repeater_field_values ) ) : ?>
955
						<!--Stored repeater field group-->
956
						<?php foreach ( $repeater_field_values as $index => $field_group ) : ?>
957
							<tr class="give-row">
958
								<td class="give-repeater-field-wrap give-column" colspan="2">
959
									<div class="give-row-head give-move">
960
										<button type="button" class="give-toggle-btn">
961
											<span class="give-toggle-indicator"></span>
962
										</button>
963
										<sapn class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">
964
											-
965
										</sapn>
966
										<h2>
967
											<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
968
										</h2>
969
									</div>
970
									<div class="give-row-body">
971
										<?php
972
										foreach ( $fields['fields'] as $field_id => $field ) :
973
											$field['id']     = ! empty( $field['id'] ) ? $field['id'] : $field_id;
974
											$field['repeat'] = true;
975
976
											$field['repeater_field_name']    = self::get_repeater_field_name( $field, $fields, $index );
977
											$field['value']                  = self::get_repeater_field_value( $field, $field_group, $fields );
978
											$field['field_attributes']['id'] = str_replace( array(
979
												'[',
980
												']',
981
											), array( '_', '', ), $field['repeater_field_name'] );
982
983
											echo self::render_tag( $field, $form );
984
										endforeach;
985
										?>
986
									</div>
987
								</td>
988
							</tr>
989
						<?php endforeach; ?>
990
991
					<?php elseif ( $add_default_donation_field ) : ?>
992
						<!--Default repeater field group-->
993
						<tr class="give-row">
994
							<td class="give-repeater-field-wrap give-column" colspan="2">
995
								<div class="give-row-head give-move">
996
									<button type="button" class="give-toggle-btn">
997
										<span class="give-toggle-indicator"></span>
998
									</button>
999
									<sapn class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">-
1000
									</sapn>
1001
									<h2>
1002
										<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
1003
									</h2>
1004
								</div>
1005
								<div class="give-row-body">
1006
									<?php
1007
									foreach ( $fields['fields'] as $field_id => $field ) :
1008
										$field['id']                        = ! empty( $field['id'] ) ? $field['id'] : $field_id;
1009
										$field['repeat']                    = true;
1010
										$field['repeater_default_template'] = true;
1011
1012
										$field['repeater_field_name']    = self::get_repeater_field_name( $field, $fields, 0 );
1013
										$field['field_attributes']['id'] = str_replace( array( '[', ']' ), array(
1014
											'_',
1015
											'',
1016
										), $field['repeater_field_name'] );
1017
1018
										echo self::render_tag( $field, $form );
1019
									endforeach;
1020
									?>
1021
								</div>
1022
							</td>
1023
						</tr>
1024
					<?php endif; ?>
1025
				</tbody>
1026
				<tfoot>
1027
					<tr>
1028
						<?php
1029
						$add_row_btn_title = isset( $fields['options']['add_button'] )
1030
							? $add_row_btn_title = $fields['options']['add_button']
1031
							: esc_html__( 'Add Row', 'give' );
1032
						?>
1033
						<td colspan="2" class="give-add-repeater-field-section-row-wrap">
1034
							<button class="button button-primary give-add-repeater-field-section-row"><?php echo $add_row_btn_title; ?></button>
1035
						</td>
1036
					</tr>
1037
				</tfoot>
1038
			</table>
1039
		</div>
1040
		<?php
1041
1042
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
1043
	}
1044
1045
1046
	/**
1047
	 * Render field
1048
	 *
1049
	 * @since  2.0
1050
	 * @access private
1051
	 *
1052
	 * @param  array $field
1053
	 * @param  array $form
1054
	 * @param  array $args
1055
	 *
1056
	 * @return string
1057
	 */
1058
	public static function get_field_template( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1059
		/**
1060
		 * Field Html template.
1061
		 */
1062
		// Set before field html.
1063
		$field['before_field'] = self::is_callback( $field['before_field'] )
1064
			? self::render_callback( $field['before_field'] )
1065
			: $field['before_field'];
1066
1067
		// Set after field html.
1068
		$field['after_field'] = self::is_callback( $field['after_field'] )
1069
			? self::render_callback( $field['after_field'] )
1070
			: $field['after_field'];
1071
1072
		$field_html = "{$field['before_field']}{{form_field}}{$field['after_field']}";
1073
1074
1075
		/**
1076
		 * Field html with label.
1077
		 */
1078
		switch ( $field['label_position'] ) {
1079
			case 'after':
1080
				$field['before_field_label'] = empty( $field['before_field_label'] )
1081
					? $field_html
1082
					: "{$field_html} {$field['before_field_label']}";
1083
				break;
1084
1085
			case 'inside':
1086
				$field['label'] = empty( $field['label'] )
1087
					? $field_html
1088
					: "{$field_html}  {$field['label']}";
1089
				break;
1090
1091
			//case 'before':
1092
			default:
1093
				$field['after_field_label'] = empty( $field['after_field_label'] )
1094
					? $field_html
1095
					: "{$field['after_field_label']} {$field_html}";
1096
1097
		}
1098
1099
1100
		$field_html = trim( self::$instance->render_field_label( $field ) );
1101
1102
		return $field_html;
1103
	}
1104
1105
1106
	/**
1107
	 * Render wrapper
1108
	 *
1109
	 * @since  2.0
1110
	 * @access private
1111
	 *
1112
	 * @param  array $field
1113
	 * @param  array $form
1114
	 * @param  array $args
1115
	 *
1116
	 * @return string
1117
	 */
1118
	public static function render_field_wrapper( $field, $form = null, $args = array() ) {
1119
		/**
1120
		 * Get field template.
1121
		 */
1122
		$field_html = self::get_field_template( $field, $form, $args );
1123
1124
		/**
1125
		 * Field with label html with wrapper.
1126
		 */
1127
		ob_start();
1128
1129
		// Set before wrapper html.
1130
		$field['before_field_wrapper'] = self::is_callback( $field['before_field_wrapper'] )
1131
			? self::render_callback( $field['before_field_wrapper'] )
1132
			: $field['before_field_wrapper'];
1133
1134
		echo $field['before_field_wrapper'];
1135
1136
		if ( $field['wrapper'] ) :
1137
1138
1139
			echo '<' . $field['wrapper_type'] . ' ' . self::$instance->get_attributes( $field['wrapper_attributes'] ) . '>';
1140
			echo $field_html;
1141
			echo "</{$field['wrapper_type']}>";
1142
1143
		else :
1144
			echo $field_html;
1145
		endif;
1146
1147
		// Set after wrapper html.
1148
		$field['after_field_wrapper'] = self::is_callback( $field['after_field_wrapper'] )
1149
			? self::render_callback( $field['after_field_wrapper'] )
1150
			: $field['after_field_wrapper'];
1151
1152
		echo $field['after_field_wrapper'];
1153
1154
		$field_html = ob_get_clean();
1155
1156
		return $field_html;
1157
	}
1158
1159
1160
	/**
1161
	 * Render label
1162
	 *
1163
	 * @since  2.0
1164
	 * @access private
1165
	 *
1166
	 * @param  array $field
1167
	 * @param  array $form
1168
	 * @param  array $args
1169
	 *
1170
	 * @return string
1171
	 */
1172
	public function render_field_label( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1173
		ob_start();
1174
		$label_type = ( 'fieldset' === $field['wrapper_type'] ? 'legend' : 'label' );
1175
1176
		$field['label_attributes']['for'] = $field['field_attributes']['id'];
1177
1178
		// Set before label html.
1179
		$field['before_field_label'] = self::is_callback( $field['before_field_label'] )
1180
			? self::render_callback( $field['before_field_label'] )
1181
			: $field['before_field_label'];
1182
		echo $field['before_field_label'];
1183
		?>
1184
		<?php if ( ! empty( $field['label'] ) ) : ?>
1185
1186
			<<?php echo $label_type; ?><?php echo ' '. self::get_attributes( $field['label_attributes'] ); ?>>
1187
			<?php echo $field['label']; ?>
1188
1189
			<?php if ( $field['required'] ) : ?>
1190
				<span class="give-required-indicator">*</span>
1191
			<?php endif; ?>
1192
1193
			<?php if ( $field['label_tooltip'] ) : ?>
1194
				<span class="give-tooltip give-icon give-icon-question" data-tooltip="<?php echo $field['label_tooltip'] ?>"></span>
1195
			<?php endif; ?>
1196
			</<?php echo $label_type; ?>>
1197
1198
		<?php endif; ?>
1199
		<?php
1200
		// Set after label html.
1201
		$field['after_field_label'] = self::is_callback( $field['after_field_label'] )
1202
			? self::render_callback( $field['after_field_label'] )
1203
			: $field['after_field_label'];
1204
		echo $field['after_field_label'];
1205
1206
		return ob_get_clean();
1207
	}
1208
1209
	/**
1210
	 * Get field attribute string from field arguments.
1211
	 *
1212
	 * @since  2.0
1213
	 * @access private
1214
	 *
1215
	 * @param array $attributes
1216
	 *
1217
	 * @return array|string
1218
	 */
1219
	private static function get_attributes( $attributes ) {
1220
		$field_attributes_val = '';
1221
1222
		if ( ! empty( $attributes ) ) {
1223
			foreach ( $attributes as $attribute_name => $attribute_val ) {
1224
				$field_attributes_val[] = "{$attribute_name}=\"{$attribute_val}\"";
1225
			}
1226
		}
1227
1228
		if ( ! empty( $field_attributes_val ) ) {
1229
			$field_attributes_val = implode( ' ', $field_attributes_val );
1230
		}
1231
1232
		return $field_attributes_val;
1233
	}
1234
1235
	/**
1236
	 * Set default values for fields
1237
	 *
1238
	 * @since  1.0
1239
	 * @access private
1240
	 *
1241
	 * @param array $field
1242
	 * @param array $form
1243
	 * @param array $args
1244
	 *
1245
	 * @return array
1246
	 */
1247
	public static function set_default_values( $field, $form = null, $args = array() ) {
1248
		/**
1249
		 * Filter the field before set default values.
1250
		 *
1251
		 * @since 2.0
1252
		 *
1253
		 * @param array $field
1254
		 * @param array $form
1255
		 */
1256
		$field = ! empty( $args['fire_filter'] )
1257
			? apply_filters( 'give_field_api_pre_set_default_values', $field, $form )
1258
			: $field;
1259
1260
		switch ( self::$instance->get_field_type( $field ) ) {
1261
			case 'block':
1262
				// Set default values for block.
1263
				$field = wp_parse_args( $field, self::$block_defaults );
1264
1265
				// Set block id.
1266
				$field['field_attributes']['id'] = ! isset( $field['field_attributes']['id'] )
1267
					? "give-{$field['id']}-field"
1268
					: $field['field_attributes']['id'];
1269
1270
				// Set wrapper class.
1271
				$field['block_attributes']['class'] = empty( $field['block_attributes']['class'] )
1272
					? "give-block-wrap js-give-block-wrap give-block-{$field['id']}"
1273
					: trim( "give-block-wrap js-give-block-wrap give-block-{$field['id']} {$field['block_attributes']['class']}" );
1274
1275
				foreach ( $field['fields'] as $key => $single_field ) {
1276
					$single_field['id']      = ! empty( $single_field['id'] )
1277
						? $single_field['id']
1278
						: $key;
1279
					$field['fields'][ $key ] = self::$instance->set_default_values( $single_field, $form, array( 'fire_filter' => false ) );
1280
				}
1281
1282
				break;
1283
1284
			case 'section':
1285
				// Set default values for block.
1286
				$field = wp_parse_args( $field, self::$section_defaults );
1287
1288
				// Set section id.
1289
				$field['field_attributes']['id'] = ! isset( $field['field_attributes']['id'] )
1290
					? "give-{$field['id']}-field"
1291
					: $field['field_attributes']['id'];
1292
1293
				// Set wrapper class.
1294
				$field['section_attributes']['class'] = empty( $field['section_attributes']['class'] )
1295
					? 'give-section-wrap'
1296
					: trim( "give-section-wrap {$field['section_attributes']['class']}" );
1297
1298
				foreach ( $field['fields'] as $key => $single_field ) {
1299
					$single_field['id']      = ! empty( $single_field['id'] )
1300
						? $single_field['id']
1301
						: $key;
1302
					$field['fields'][ $key ] = self::$instance->set_default_values( $single_field, $form, array( 'fire_filter' => false ) );
1303
				}
1304
1305
				break;
1306
1307
			default:
1308
				// Set default values for field or section.
1309
				$field = wp_parse_args( $field, self::$field_defaults );
1310
1311
				// Set default class for label.
1312
				$field['label_attributes']['class'] = empty( $field['label_attributes']['class'] )
1313
					? 'give-label'
1314
					: trim( "give-label {$field['label_attributes']['class']}" );
1315
1316
				// Set field id.
1317
				$field['field_attributes']['id'] = ! isset( $field['field_attributes']['id'] )
1318
					? "give-{$field['id']}-field"
1319
					: $field['field_attributes']['id'];
1320
1321
				// Set field class.
1322
				$field['field_attributes']['class'] = empty( $field['field_attributes']['class'] )
1323
					? "give-field js-give-field"
1324
					: trim( "give-field js-give-field {$field['field_attributes']['class']}" );
1325
1326
				// Set wrapper class.
1327
				$field['wrapper_attributes']['class'] = empty( $field['wrapper_attributes']['class'] )
1328
					? "give-field-wrap {$field['id']}_field"
1329
					: trim( "give-field-wrap {$field['id']}_field {$field['wrapper_attributes']['class']}" );
1330
1331
				// if( 'group' === $field['type'] && ! empty( $field['fields'] ) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1332
				// 	foreach ( $field['fields'] as $key => $single_field ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1333
				// 		$single_field['id']    = ! empty( $single_field['id'] )
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1334
				// 			? $single_field['id']
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1335
				// 			: $key;
1336
				// 		$single_field['repeat'] = true;
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1337
				// 		$field['fields'][ $key ] = self::$instance->set_default_values( $single_field, $form, false );
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1338
				// 	}
1339
				// }
1340
1341
				/**
1342
				 * Filter the field values.
1343
				 *
1344
				 * @since 2.0
1345
				 *
1346
				 * @param array $field
1347
				 * @param array $form
1348
				 * @param array $args
1349
				 */
1350
				$field = apply_filters( 'give_field_api_set_values', $field, $form, $args );
1351
		}
1352
1353
		/**
1354
		 * Filter the field after set default values.
1355
		 *
1356
		 * @since 2.0
1357
		 *
1358
		 * @param array $field
1359
		 * @param array $form
1360
		 */
1361
		$field = ! empty( $args['fire_filter'] )
1362
			? apply_filters( 'give_field_api_post_set_default_values', $field, $form )
1363
			: $field;
1364
1365
		return $field;
1366
	}
1367
1368
1369
	/**
1370
	 * Set responsive fields.
1371
	 *
1372
	 * @since  2.0
1373
	 * @access private
1374
	 *
1375
	 * @param $form
1376
	 *
1377
	 * @return mixed
1378
	 */
1379
	private function set_responsive_field( &$form ) {
1380
1381
		foreach ( $form['fields'] as $key => $field ) {
1382
			switch ( true ) {
1383
				case array_key_exists( 'fields', $field ):
1384
					foreach ( $field['fields'] as $section_field_index => $section_field ) {
1385
						if ( ! self::$instance->is_sub_section( $section_field ) ) {
1386
							continue;
1387
						}
1388
1389
						$form['fields'][ $key ]['fields'][ $section_field_index ]['wrapper_attributes']['class'] = 'give-form-col';
1390
1391
						if ( array_key_exists( 'sub_section_end', $section_field ) ) {
1392
							$form['fields'][ $key ]['fields'][ $section_field_index ]['wrapper_attributes']['class'] = 'give-form-col give-form-col-end';
1393
1394
							// Clear float left for next field.
1395
							$fields_keys = array_keys( $form['fields'][ $key ]['fields'] );
1396
1397
							if ( $next_field_key = array_search( $section_field_index, $fields_keys ) ) {
1398
								if (
1399
									! isset( $fields_keys[ $next_field_key + 1 ] )
1400
									|| ! isset( $form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ] )
1401
								) {
1402
									continue;
1403
								}
1404
1405
								$next_field = $form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ];
1406
1407
								$next_field['wrapper_attributes']['class'] = isset( $next_field['wrapper_attributes']['class'] )
1408
									? $next_field['wrapper_attributes']['class'] . ' give-clearfix'
1409
									: 'give-clearfix';
1410
1411
								$form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ] = $next_field;
1412
							}
1413
						}
1414
					}
1415
1416
					break;
1417
1418
				default:
1419
					if ( ! self::$instance->is_sub_section( $field ) ) {
1420
						continue;
1421
					}
1422
1423
					$form['fields'][ $key ]['wrapper_attributes']['class'] = 'give-form-col';
1424
1425
					if ( array_key_exists( 'sub_section_end', $field ) ) {
1426
						$form['fields'][ $key ]['wrapper_attributes']['class'] = 'give-form-col give-form-col-end';
1427
1428
						// Clear float left for next field.
1429
						$fields_keys = array_keys( $form['fields'] );
1430
1431
						if ( $next_field_key = array_search( $key, $fields_keys ) ) {
1432
							$form['fields'][ $fields_keys[ $next_field_key + 1 ] ]['wrapper_attributes']['class'] = 'give-clearfix';
1433
						}
1434
					}
1435
			}
1436
		}
1437
	}
1438
1439
1440
	/**
1441
	 * Check if current field is part of sub section or not.
1442
	 *
1443
	 * @since  2.0
1444
	 * @access private
1445
	 *
1446
	 * @param $field
1447
	 *
1448
	 * @return bool
1449
	 */
1450
	private function is_sub_section( $field ) {
1451
		$is_sub_section = false;
1452
		if ( array_key_exists( 'sub_section_start', $field ) || array_key_exists( 'sub_section_end', $field ) ) {
1453
			$is_sub_section = true;
1454
		}
1455
1456
		return $is_sub_section;
1457
	}
1458
1459
1460
	/**
1461
	 * Get field type.
1462
	 *
1463
	 * @since  2.0
1464
	 * @access private
1465
	 *
1466
	 * @param  array $field
1467
	 * @param  array $form
1468
	 * @param  array $args
1469
	 *
1470
	 * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1471
	 */
1472
	public static function get_field_type( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1473
		$field_type = 'field';
1474
1475
		if (
1476
			isset( $field['type'] )
1477
			&& 'block' === $field['type']
1478
		) {
1479
			$field_type = 'block';
1480
1481
		} elseif (
1482
			array_key_exists( 'fields', $field )
1483
			&& 'section' === $field['type']
1484
		) {
1485
			$field_type = 'section';
1486
1487
		}
1488
1489
		return $field_type;
1490
	}
1491
1492
	/**
1493
	 * Get field name.
1494
	 *
1495
	 * @since  2.0
1496
	 *
1497
	 * @param  array $field
1498
	 * @param  array $form
1499
	 * @param  array $args
1500
	 *
1501
	 * @return string
1502
	 */
1503
	public static function get_field_name( $field, $form = null, $args = array() ) {
0 ignored issues
show
Unused Code introduced by
The parameter $form is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1504
		$field_name = esc_attr( empty( $field['repeat'] ) ? $field['id'] : $field['repeater_field_name'] );
1505
1506
		/**
1507
		 * Filter the field name.
1508
		 *
1509
		 * @since 1.8
1510
		 *
1511
		 * @param string $field_name
1512
		 */
1513
		$field_name = apply_filters( 'give_get_field_name', $field_name, $field );
1514
1515
		return $field_name;
1516
	}
1517
1518
	/**
1519
	 * Get repeater field id.
1520
	 *
1521
	 * @since  2.0
1522
	 *
1523
	 * @param array    $field
1524
	 * @param array    $fields
1525
	 * @param int|bool $default
1526
	 *
1527
	 * @return string
1528
	 */
1529
	public static function get_repeater_field_name( $field, $fields, $default = false ) {
1530
		$row_placeholder = false !== $default ? $default : '{{row-count-placeholder}}';
1531
1532
		// Get field id.
1533
		$field_id = "{$fields['id']}[{$row_placeholder}][{$field['id']}]";
1534
1535
		/**
1536
		 * Filter the specific repeater field id
1537
		 *
1538
		 * @since 1.8
1539
		 *
1540
		 * @param string $field_id
1541
		 */
1542
		$field_id = apply_filters( "give_get_repeater_field_{$field['id']}_name", $field_id, $field, $fields, $default );
1543
1544
		/**
1545
		 * Filter the repeater field id
1546
		 *
1547
		 * @since 1.8
1548
		 *
1549
		 * @param string $field_id
1550
		 */
1551
		$field_id = apply_filters( 'give_get_repeater_field_name', $field_id, $field, $fields, $default );
1552
1553
		return $field_id;
1554
	}
1555
1556
1557
	/**
1558
	 * Get repeater field value.
1559
	 *
1560
	 * @since  2.0
1561
	 * @access public
1562
	 *
1563
	 * @param array $field
1564
	 * @param array $field_value_group
1565
	 * @param array $fields
1566
	 *
1567
	 * @return mixed
1568
	 */
1569
	public static function get_repeater_field_value( $field, $field_value_group, $fields ) {
1570
		$field_value = ( isset( $field_value_group[ $field['id'] ] ) ? $field_value_group[ $field['id'] ] : '' );
1571
1572
		/**
1573
		 * Filter the specific repeater field value
1574
		 *
1575
		 * @since 1.8
1576
		 *
1577
		 * @param string $field_id
1578
		 */
1579
		$field_value = apply_filters( "give_get_repeater_field_{$field['id']}_value", $field_value, $field, $field_value_group, $fields );
1580
1581
		/**
1582
		 * Filter the repeater field value
1583
		 *
1584
		 * @since 1.8
1585
		 *
1586
		 * @param string $field_id
1587
		 */
1588
		$field_value = apply_filters( 'give_get_repeater_field_value', $field_value, $field, $field_value_group, $fields );
1589
1590
		return $field_value;
1591
	}
1592
1593
1594
	/**
1595
	 * Check if string or array is callback or not.
1596
	 *
1597
	 * @since  2.0
1598
	 * @access public
1599
	 *
1600
	 * @param $callback
1601
	 *
1602
	 * @return bool
1603
	 */
1604
	public static function is_callback( $callback ) {
1605
		$is_callback = false;
1606
1607
		// Process callback to get field html.
1608
		if ( is_string( $callback ) && function_exists( "$callback" ) ) {
1609
			$is_callback = true;
1610
		} elseif ( is_array( $callback ) && method_exists( $callback[0], "$callback[1]" ) ) {
1611
			$is_callback = true;
1612
		}
1613
1614
		return $is_callback;
1615
	}
1616
1617
1618
	/**
1619
	 * Sort field list.
1620
	 *
1621
	 * @since  2.0
1622
	 * @access private
1623
	 *
1624
	 * @param array $fields
1625
	 * @param array $form
1626
	 *
1627
	 * @return array
1628
	 */
1629
	private function sort_fields( $fields, $form ) {
1630
		// Set if sort by priority is enable or not.
1631
		if( empty( $form['sort_by_priority'] ) ) {
1632
			return $form;
1633
		}
1634
1635
		if ( ! empty( $fields ) ) {
1636
1637
			foreach ( $fields as $index => $field ) {
1638
				if ( 'field' === self::$instance->get_field_type( $field ) && 'group' !== $field['type'] ) {
1639
					continue;
1640
				}
1641
1642
				// Sort fields list inside section or block.
1643
				$fields[ $index ]['fields'] = self::$instance->sort_fields( $field['fields'], $form );
1644
			}
1645
1646
			uasort( $fields, array( $this, 'sort_by_priority' ) );
1647
		}
1648
		
1649
		return $fields;
1650
	}
1651
1652
	/**
1653
	 * Sort array by priority value
1654
	 *
1655
	 * @param array $a
1656
	 * @param array $b
1657
	 *
1658
	 * @return int
1659
	 */
1660
	private function sort_by_priority( $a, $b ) {
1661
		// Priority must be set for each field
1662
		// @see class-give-form-api.php:43
1663
		// $a['priority'] = ! isset( $a['priority'] )
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1664
		// 	? ( 'submit' === $a['type'] ? 9999 : 0 )
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1665
		// 	: $a['priority'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1666
		//
1667
		// $b['priority'] = ! isset( $b['priority'] )
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1668
		// 	? ( 'submit' === $b['type'] ? 9999 : 0 )
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1669
		// 	: $b['priority'];
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1670
1671
		if ( $a['priority'] == $b['priority'] ) {
1672
			return 0;
1673
		}
1674
1675
		return ( $a['priority'] < $b['priority'] ) ? - 1 : 1;
1676
	}
1677
}
1678
1679
// @todo implement required and aria-required for all form fields. required should be custom tag because we want custom validation for form instead html5.
1680
// @todo develop field validation feature