Completed
Push — issues/1038 ( d48073...5f951d )
by Ravinder
19:26
created

Give_Fields_API::render_group_field()   F

Complexity

Conditions 21
Paths 1153

Size

Total Lines 167
Code Lines 105

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 105
nc 1153
nop 1
dl 0
loc 167
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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       1.9
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  1.9
17
	 * @access private
18
	 * @var Give_Fields_API
19
	 */
20
	static private $instance;
21
22
	/**
23
	 * The defaults for all elements
24
	 *
25
	 * @since  1.9
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
		'name'                 => '',
31
		'data_type'            => '',
32
		'value'                => '',
33
		'required'             => false,
34
		'options'              => array(),
35
36
		// Set default value to field.
37
		'default'              => '',
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
		'label_position'       => 'before',
49
50
		// Add description to field as tooltip.
51
		'tooltip'              => '',
52
53
		// Show multiple fields in same row with in sub section.
54
		'sub_section_start'    => false,
55
		'sub_section_end'      => false,
56
57
		// Add custom attributes.
58
		'field_attributes'     => array(),
59
		'wrapper_attributes'   => array(),
60
61
		// Show/Hide field in before/after modal view.
62
		'show_without_modal'   => false,
63
		'show_within_modal'    => true,
64
65
		// Params to edit field html.
66
		'before_field'         => '',
67
		'after_field'          => '',
68
		'before_field_wrapper' => '',
69
		'after_field_wrapper'  => '',
70
		'before_label'         => '',
71
		'after_label'          => '',
72
73
		// Manually render field.
74
		'callback'             => '',
75
76
	);
77
78
	/**
79
	 * The defaults for all sections.
80
	 *
81
	 * @since  1.9
82
	 * @access static
83
	 */
84
	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...
85
		'type'               => 'section',
86
		'label'              => '',
87
		'name'               => '',
88
		'section_attributes' => array(),
89
90
		// Manually render section.
91
		'callback'           => '',
92
	);
93
94
	/**
95
	 * The defaults for all blocks.
96
	 *
97
	 * @since  1.9
98
	 * @access static
99
	 */
100
	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...
101
		'type'             => 'block',
102
		'label'            => '',
103
		'name'             => '',
104
		'block_attributes' => array(),
105
106
		// Manually render section.
107
		'callback'         => '',
108
	);
109
110
111
	private function __construct() {
112
	}
113
114
115
	/**
116
	 * Get instance.
117
	 *
118
	 * @return static
119
	 */
120
	public static function get_instance() {
121
		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...
122
			self::$instance = new static();
123
		}
124
125
		return self::$instance;
126
	}
127
128
	/**
129
	 * Initialize this module
130
	 *
131
	 * @since  1.9
132
	 * @access static
133
	 */
134
	public function init() {
135
		add_filter( 'give_form_api_render_form_tags', array( $this, 'render_tags' ), 10, 2 );
136
	}
137
138
139
	/**
140
	 * Render custom field.
141
	 *
142
	 * @since  1.0
143
	 * @access private
144
	 *
145
	 * @param array $field
146
	 * @param array $form
147
	 *
148
	 * @return bool
149
	 */
150
	private function render_custom_field( $field, $form = null ) {
151
		$field = self::$instance->set_default_values( $field, $form );
152
153
		$field_html = '';
154
155
		if ( empty( $field['callback'] ) ) {
156
			$callback = $field['callback'];
157
158
			// Process callback to get field html.
159
			if ( is_string( $callback ) && function_exists( "$callback" ) ) {
160
				$field_html = $callback( $field );
161
			} elseif ( is_array( $callback ) && method_exists( $callback[0], "$callback[1]" ) ) {
162
				$field_html = $callback[0]->$callback[1]( $field );
163
			}
164
		}
165
166
		return $field_html;
167
	}
168
169
170
	/**
171
	 * Render `{{form_fields}}` tag.
172
	 *
173
	 * @since  1.9
174
	 * @access private
175
	 *
176
	 * @param  string $form_html
177
	 * @param  array  $form
178
	 *
179
	 * @return string
180
	 */
181
	public function render_tags( $form_html, $form ) {
182
		// Bailout: If form does not contain any field.
183
		if ( empty( $form['fields'] ) ) {
184
			str_replace( '{{form_fields}}', '', $form_html );
185
186
			return $form_html;
187
		}
188
189
		$fields_html = '';
190
191
		// Set responsive fields.
192
		self::$instance->set_responsive_field( $form );
193
194
		// Render fields.
195
		foreach ( $form['fields'] as $key => $field ) {
196
			// Set default value.
197
			$field['name'] = empty( $field['name'] ) ? $key : $field['name'];
198
199
			// Render custom form with callback.
200
			if ( $field_html = self::$instance->render_custom_field( $field, $form ) ) {
201
				$fields_html .= $field_html;
202
			}
203
204
			switch ( true ) {
205
				// Block.
206
				case ( 'block' === self::get_field_type( $field ) ):
207
					$fields_html .= self::$instance->render_block( $field, $form );
208
					break;
209
210
				// Section.
211
				case ( 'section' === self::get_field_type( $field ) ):
212
					$fields_html .= self::$instance->render_section( $field, $form );
213
					break;
214
215
				// Field
216
				default:
217
					$fields_html .= self::render_tag( $field, $form );
218
			}
219
		}
220
221
		$form_html = str_replace( '{{form_fields}}', $fields_html, $form_html );
222
223
		return $form_html;
224
	}
225
226
227
	/**
228
	 * Render section.
229
	 *
230
	 * @since  1.9
231
	 * @access public
232
	 *
233
	 * @param array $section
234
	 * @param array $form
235
	 * @param array $args Helper argument to render section.
236
	 *
237
	 * @return string
238
	 */
239
	public static function render_section( $section, $form = null, $args = array() ) {
240
		// Set default values if necessary.
241
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
242
			$section = self::$instance->set_default_values( $section, $form );
243
		}
244
245
		ob_start();
246
		?>
247
		<fieldset <?php echo self::$instance->get_attributes( $section['section_attributes'] ); ?>>
248
			<?php
249
			// Legend.
250
			if ( ! empty( $section['label'] ) ) {
251
				echo "<legend>{$section['label']}</legend>";
252
			};
253
254
			// Fields.
255
			foreach ( $section['fields'] as $key => $field ) {
256
				echo self::render_tag( $field, $form, array( 'set_default' => false ) );
257
			}
258
			?>
259
		</fieldset>
260
		<?php
261
		return ob_get_clean();
262
	}
263
264
265
	/**
266
	 * Render block.
267
	 *
268
	 * @since  1.9
269
	 * @access public
270
	 *
271
	 * @param array $block
272
	 * @param array $form
273
	 * @param array $args Helper argument to render section.
274
	 *
275
	 * @return string
276
	 */
277
	public static function render_block( $block, $form = null, $args = array() ) {
278
		// Set default values if necessary.
279
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
280
			$block = self::$instance->set_default_values( $block, $form );
281
		}
282
283
		ob_start();
284
		?>
285
		<div <?php echo self::$instance->get_attributes( $block['block_attributes'] ); ?>>
286
			<?php
287
			// Fields.
288
			foreach ( $block['fields'] as $key => $field ) {
289
				echo array_key_exists( 'fields', $field )
290
					? self::render_section( $field, $form, array( 'set_default' => false ) )
291
					: self::render_tag( $field, $form, array( 'set_default' => false ) );
292
			}
293
			?>
294
		</div>
295
		<?php
296
		return ob_get_clean();
297
	}
298
299
	/**
300
	 * Render tag
301
	 *
302
	 * @since   1.9
303
	 * @access  public
304
	 *
305
	 * @param array $field
306
	 * @param array $form
307
	 * @param array $args Helper argument to render section.
308
	 *
309
	 * @return string
310
	 */
311
	public static function render_tag( $field, $form = null, $args = array() ) {
312
		// Enqueue scripts.
313
		Give_Form_API::enqueue_scripts();
314
315
		// Set default values if necessary.
316
		if ( ! isset( $args['set_default'] ) || (bool) $args['set_default'] ) {
317
			$field = self::$instance->set_default_values( $field, $form );
318
		}
319
320
		$field_html     = '';
321
		$functions_name = "render_{$field['type']}_field";
322
323
		if ( 'section' === self::$instance->get_field_type( $field ) ) {
324
			echo self::$instance->render_section( $field, $form, array( 'set_default' => false ) );
325
326
		} elseif ( method_exists( self::$instance, $functions_name ) ) {
327
			$field_html .= self::$instance->{$functions_name}( $field );
328
329
		} else {
330
			/**
331
			 * Filter the custom field type html.
332
			 * Developer can use this hook to render custom field type.
333
			 *
334
			 * @since 1.9
335
			 *
336
			 * @param string $field_html
337
			 * @param array  $field
338
			 * @param array  $form
339
			 */
340
			$field_html .= apply_filters(
341
				"give_field_api_render_{$field['type']}_field",
342
				$field_html,
343
				$field,
344
				$form
345
			);
346
		}
347
348
		return $field_html;
349
	}
350
351
352
	/**
353
	 * Render text field.
354
	 *
355
	 * @since  1.9
356
	 * @access public
357
	 *
358
	 * @param  array $field
359
	 *
360
	 * @return string
361
	 */
362
	public static function render_text_field( $field ) {
363
		$field_wrapper = self::$instance->render_field_wrapper( $field );
364
		ob_start();
365
		?>
366
		<input
367
				type="<?php echo $field['type']; ?>"
368
				name="<?php echo $field['name']; ?>"
369
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
370
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
371
		>
372
		<?php
373
374
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
375
	}
376
377
	/**
378
	 * Render submit field.
379
	 *
380
	 * @since  1.9
381
	 * @access public
382
	 *
383
	 * @param  array $field
384
	 *
385
	 * @return string
386
	 */
387
	public static function render_submit_field( $field ) {
388
		return self::$instance->render_text_field( $field );
389
	}
390
391
	/**
392
	 * Render checkbox field.
393
	 *
394
	 * @since  1.9
395
	 * @access public
396
	 *
397
	 * @param  array $field
398
	 *
399
	 * @return string
400
	 */
401
	public static function render_checkbox_field( $field ) {
402
		$field_wrapper = self::$instance->render_field_wrapper( $field );
403
		ob_start();
404
		?>
405
		<input
406
				type="checkbox"
407
				name="<?php echo $field['name']; ?>"
408
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
409
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
410
		>
411
		<?php
412
413
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
414
	}
415
416
	/**
417
	 * Render email field.
418
	 *
419
	 * @since  1.9
420
	 * @access public
421
	 *
422
	 * @param  array $field
423
	 *
424
	 * @return string
425
	 */
426
	public static function render_email_field( $field ) {
427
		return self::$instance->render_text_field( $field );
428
	}
429
430
	/**
431
	 * Render number field.
432
	 *
433
	 * @since  1.9
434
	 * @access public
435
	 *
436
	 * @param  array $field
437
	 *
438
	 * @return string
439
	 */
440
	public static function render_number_field( $field ) {
441
		return self::$instance->render_text_field( $field );
442
	}
443
444
	/**
445
	 * Render password field.
446
	 *
447
	 * @since  1.9
448
	 * @access public
449
	 *
450
	 * @param  array $field
451
	 *
452
	 * @return string
453
	 */
454
	public static function render_password_field( $field ) {
455
		return self::$instance->render_text_field( $field );
456
	}
457
458
	/**
459
	 * Render button field.
460
	 *
461
	 * @since  1.9
462
	 * @access public
463
	 *
464
	 * @param  array $field
465
	 *
466
	 * @return string
467
	 */
468
	public static function render_button_field( $field ) {
469
		return self::$instance->render_text_field( $field );
470
	}
471
472
	/**
473
	 * Render hidden field.
474
	 *
475
	 * @since  1.9
476
	 * @access public
477
	 *
478
	 * @param  array $field
479
	 *
480
	 * @return string
481
	 */
482
	public static function render_hidden_field( $field ) {
483
		$field['wrapper'] = false;
484
485
		return self::$instance->render_text_field( $field );
486
	}
487
488
	/**
489
	 * Render textarea field.
490
	 *
491
	 * @since  1.9
492
	 * @access public
493
	 *
494
	 * @param  array $field
495
	 *
496
	 * @return string
497
	 */
498
	public static function render_textarea_field( $field ) {
499
		$field_wrapper = self::$instance->render_field_wrapper( $field );
500
		ob_start();
501
		?>
502
		<textarea
503
				name="<?php echo $field['name']; ?>"
504
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
505
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
506
		><?php echo $field ['value']; ?></textarea>
507
508
509
		<?php
510
511
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
512
	}
513
514
	/**
515
	 * Render select field.
516
	 *
517
	 * @since  1.9
518
	 * @access public
519
	 *
520
	 * @param  array $field
521
	 *
522
	 * @return string
523
	 */
524
	public static function render_select_field( $field ) {
525
		$field_wrapper = self::$instance->render_field_wrapper( $field );
526
		ob_start();
527
528
		$options_html = '';
529
		foreach ( $field['options'] as $key => $option ) {
530
			$selected = '';
531
532
			if ( is_array( $field['value'] ) ) {
533
				$selected = in_array( $key, $field['value'] )
534
					? 'selected="selected"'
535
					: '';
536
537
			} else {
538
				$selected = selected( $key, $field['value'], false );
539
			}
540
541
			$options_html .= '<option value="' . $key . '" ' . $selected . '>' . $option . '</option>';
542
		}
543
		?>
544
545
		<select
546
				name="<?php echo $field['name']; ?>"
547
			<?php echo( $field['required'] ? 'required=""' : '' ); ?>
548
			<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
549
		><?php echo $options_html; ?></select>
550
		<?php
551
552
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
553
	}
554
555
	/**
556
	 * Render multi select field.
557
	 *
558
	 * @since  1.9
559
	 * @access public
560
	 *
561
	 * @param  array $field
562
	 *
563
	 * @return string
564
	 */
565
	public static function render_multi_select_field( $field ) {
566
		$field['field_attributes'] = array_merge( $field['field_attributes'], array( 'multiple' => 'multiple' ) );
567
		$field['name']             = "{$field['name']}[]";
568
569
		return self::$instance->render_select_field( $field );
570
	}
571
572
	/**
573
	 * Render radio field.
574
	 *
575
	 * @since  1.9
576
	 * @access public
577
	 *
578
	 * @param  array $field
579
	 *
580
	 * @return string
581
	 */
582
	public static function render_radio_field( $field ) {
583
		$field['wrapper_type'] = 'p' === $field['wrapper_type']
584
			? 'fieldset'
585
			: $field['wrapper_type'];
586
587
588
		$field_wrapper = self::$instance->render_field_wrapper( $field );
589
		ob_start();
590
591
		$id_base = $field['field_attributes']['id'];
592
		unset( $field['field_attributes']['id'] );
593
594
		echo '<ul>';
595
		foreach ( $field['options'] as $key => $option ) :
596
			?>
597
			<li>
598
				<label class="give-label" for="<?php echo "{$id_base}-{$key}" ?>">
599
					<input
600
							type="<?php echo $field['type']; ?>"
601
							name="<?php echo $field['name']; ?>"
602
							value="<?php echo $key; ?>"
603
							id="<?php echo "{$id_base}-{$key}"; ?>"
604
						<?php checked( $key, $field['value'] ) ?>
605
						<?php echo( $field['required'] ? 'required=""' : '' ); ?>
606
						<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
607
					><?php echo $option; ?>
608
				</label>
609
			</li>
610
			<?php
611
		endforeach;
612
		echo '</ul>';
613
614
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
615
	}
616
617
	/**
618
	 * Render multi checkbox field.
619
	 *
620
	 * @since  1.9
621
	 * @access public
622
	 *
623
	 * @param  array $field
624
	 *
625
	 * @return string
626
	 */
627
	public static function render_multi_checkbox_field( $field ) {
628
		$field['wrapper_type'] = 'p' === $field['wrapper_type']
629
			? 'fieldset'
630
			: $field['wrapper_type'];
631
632
		$field_wrapper = self::$instance->render_field_wrapper( $field );
633
		ob_start();
634
635
		$id_base = $field['field_attributes']['id'];
636
		unset( $field['field_attributes']['id'] );
637
638
		echo '<ul>';
639
		foreach ( $field['options'] as $key => $option ) :
640
			$checked = ! empty( $field['value'] ) && in_array( $key, $field['value'] )
641
				? 'checked="checked"'
642
				: '';
643
			?>
644
			<li>
645
				<label class="give-label" for="<?php echo "{$id_base}-{$key}" ?>">
646
					<input
647
							type="checkbox"
648
							name="<?php echo $field['name']; ?>[]"
649
							value="<?php echo $key; ?>"
650
							id="<?php echo "{$id_base}-{$key}"; ?>"
651
						<?php echo $checked ?>
652
						<?php echo( $field['required'] ? 'required=""' : '' ); ?>
653
						<?php echo self::$instance->get_attributes( $field['field_attributes'] ); ?>
654
					><?php echo $option; ?>
655
				</label>
656
			</li>
657
			<?php
658
		endforeach;
659
		echo '</ul>';
660
661
662
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
663
	}
664
665
666
	/**
667
	 * Render group field
668
	 *
669
	 * @since 1.9
670
	 * @access public
671
	 *
672
	 * @param array $fields
673
	 *
674
	 * @return string
675
	 */
676
	public static function render_group_field( $fields ) {
677
		global $thepostid, $post;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
678
679
		// Bailout.
680
		if ( ! isset( $fields['fields'] ) || empty( $fields['fields'] ) ) {
681
			return '';
682
		}
683
684
		$group_numbering       = isset( $fields['options']['group_numbering'] ) ? (int) $fields['options']['group_numbering'] : 0;
685
		$close_tabs            = isset( $fields['options']['close_tabs'] ) ? (int) $fields['options']['close_tabs'] : 0;
686
		$close_tabs = 0;
687
		$repeater_field_values = $fields['value'];
688
		$header_title          = isset( $fields['options']['header_title'] )
689
			? $fields['options']['header_title']
690
			: esc_attr__( 'Group', 'give' );
691
692
		$add_default_donation_field = false;
693
694
		// Check if level is not created or we have to add default level.
695
		if ( is_array( $repeater_field_values ) && ( $fields_count = count( $repeater_field_values ) ) ) {
696
			$repeater_field_values = array_values( $repeater_field_values );
697
		} else {
698
			$fields_count               = 1;
699
			$add_default_donation_field = true;
700
		}
701
702
		$field_wrapper = self::$instance->render_field_wrapper( $fields );
703
704
		ob_start();
705
		?>
706
		<div class="give-repeatable-field-section" id="<?php echo "{$fields['id']}_field"; ?>"
707
			 data-group-numbering="<?php echo $group_numbering; ?>" data-close-tabs="<?php echo $close_tabs; ?>">
708
			<?php if ( ! empty( $fields['name'] ) ) : ?>
709
				<p class="give-repeater-field-name"><?php echo $fields['name']; ?></p>
710
			<?php endif; ?>
711
712
			<?php if ( ! empty( $fields['description'] ) ) : ?>
713
				<p class="give-repeater-field-description"><?php echo $fields['description']; ?></p>
714
			<?php endif; ?>
715
716
			<table class="give-repeatable-fields-section-wrapper" cellspacing="0">
717
				<?php
718
719
				?>
720
				<tbody class="container"<?php echo " data-rf-row-count=\"{$fields_count}\""; ?>>
721
					<!--Repeater field group template-->
722
					<tr class="give-template give-row">
723
						<td class="give-repeater-field-wrap give-column" colspan="2">
724
							<div class="give-row-head give-move">
725
								<button type="button" class="give-toggle-btn">
726
									<span class="give-toggle-indicator"></span>
727
								</button>
728
								<span class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">-</span>
729
								<h2>
730
									<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
731
								</h2>
732
							</div>
733
							<div class="give-row-body">
734
								<?php foreach ( $fields['fields'] as $field ) : ?>
735
									<?php if ( ! give_is_field_callback_exist( $field ) ) {
736
										continue;
737
									} ?>
738
									<?php
739
									$field['repeat']              = true;
740
									$field['repeatable_field_id'] = give_get_repeater_field_id( $field, $fields );
741
									$field['id']                  = str_replace( array( '[', ']' ), array(
742
										'_',
743
										'',
744
									), $field['repeatable_field_id'] );
745
									?>
746
									<?php give_render_field( $field ); ?>
747
								<?php endforeach; ?>
748
							</div>
749
						</td>
750
					</tr>
751
752
					<?php if ( ! empty( $repeater_field_values ) ) : ?>
753
						<!--Stored repeater field group-->
754
						<?php foreach ( $repeater_field_values as $index => $field_group ) : ?>
755
							<tr class="give-row">
756
								<td class="give-repeater-field-wrap give-column" colspan="2">
757
									<div class="give-row-head give-move">
758
										<button type="button" class="give-toggle-btn">
759
											<span class="give-toggle-indicator"></span>
760
										</button>
761
										<sapn class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">-
762
										</sapn>
763
										<h2>
764
											<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
765
										</h2>
766
									</div>
767
									<div class="give-row-body">
768
										<?php foreach ( $fields['fields'] as $field ) : ?>
769
											<?php if ( ! give_is_field_callback_exist( $field ) ) {
770
												continue;
771
											} ?>
772
											<?php
773
											$field['repeat']              = true;
774
											$field['repeatable_field_id'] = give_get_repeater_field_id( $field, $fields, $index );
775
											$field['attributes']['value'] = give_get_repeater_field_value( $field, $field_group, $fields );
776
											$field['id']                  = str_replace( array( '[', ']' ), array(
777
												'_',
778
												'',
779
											), $field['repeatable_field_id'] );
780
											?>
781
											<?php give_render_field( $field ); ?>
782
										<?php endforeach; ?>
783
									</div>
784
								</td>
785
							</tr>
786
						<?php endforeach;
787
						; ?>
788
789
					<?php elseif ( $add_default_donation_field ) : ?>
790
						<!--Default repeater field group-->
791
						<tr class="give-row">
792
							<td class="give-repeater-field-wrap give-column" colspan="2">
793
								<div class="give-row-head give-move">
794
									<button type="button" class="give-toggle-btn">
795
										<span class="give-toggle-indicator"></span>
796
									</button>
797
									<sapn class="give-remove" title="<?php esc_html_e( 'Remove Group', 'give' ); ?>">-
798
									</sapn>
799
									<h2>
800
										<span data-header-title="<?php echo $header_title; ?>"><?php echo $header_title; ?></span>
801
									</h2>
802
								</div>
803
								<div class="give-row-body">
804
									<?php
805
									foreach ( $fields['fields'] as $field ) :
806
										if ( ! give_is_field_callback_exist( $field ) ) {
807
											continue;
808
										}
809
810
										$field['repeat']              = true;
811
										$field['repeatable_field_id'] = give_get_repeater_field_id( $field, $fields, 0 );
812
										$field['attributes']['value'] = apply_filters( "give_default_field_group_field_{$field['id']}_value", ( ! empty( $field['default'] ) ? $field['default'] : '' ), $field );
813
										$field['id']                  = str_replace( array( '[', ']' ), array(
814
											'_',
815
											'',
816
										), $field['repeatable_field_id'] );
817
										give_render_field( $field );
818
									endforeach;
819
									?>
820
								</div>
821
							</td>
822
						</tr>
823
					<?php endif; ?>
824
				</tbody>
825
				<tfoot>
826
					<tr>
827
						<?php
828
						$add_row_btn_title = isset( $fields['options']['add_button'] )
829
							? $add_row_btn_title = $fields['options']['add_button']
830
							: esc_html__( 'Add Row', 'give' );
831
						?>
832
						<td colspan="2" class="give-add-repeater-field-section-row-wrap">
833
							<span class="button button-primary give-add-repeater-field-section-row"><?php echo $add_row_btn_title; ?></span>
834
						</td>
835
					</tr>
836
				</tfoot>
837
			</table>
838
		</div>
839
		<?php
840
841
		return str_replace( '{{form_field}}', ob_get_clean(), $field_wrapper );
842
	}
843
844
845
	/**
846
	 * Render wrapper
847
	 *
848
	 * @since  1.9
849
	 * @access private
850
	 *
851
	 * @param $field
852
	 *
853
	 * @return string
854
	 */
855
	public static function render_field_wrapper( $field ) {
856
		ob_start();
857
858
		if ( $field['wrapper'] ) :
859
860
			echo $field['before_field_wrapper'];
861
			?>
862
			<<?php echo $field['wrapper_type']; ?> <?php echo self::$instance->get_attributes( $field['wrapper_attributes'] ); ?>>
863
			<?php
864
			// Label: before field.
865
			if ( 'before' === $field['label_position'] ) {
866
				echo self::$instance->render_label( $field );
867
			}
868
869
			echo "{$field['before_field']}{{form_field}}{$field['after_field']}";
870
871
			// Label: before field.
872
			if ( 'after' === $field['label_position'] ) {
873
				echo self::$instance->render_label( $field );
874
			}
875
			?>
876
			</<?php echo $field['wrapper_type']; ?>>
877
			<?php
878
			echo $field['after_field_wrapper'];
879
		else :
880
			echo "{$field['before_field']}{{form_field}}{$field['after_field']}";
881
		endif;
882
883
		return ob_get_clean();
884
	}
885
886
887
	/**
888
	 * Render label
889
	 *
890
	 * @since  1.9
891
	 * @access private
892
	 *
893
	 * @param $field
894
	 *
895
	 * @return string
896
	 */
897
	private function render_label( $field ) {
898
		ob_start();
899
		?>
900
		<?php if ( ! empty( $field['label'] ) ) : ?>
901
			<?php echo $field['before_label']; ?>
902
			<label class="give-label" for="<?php echo $field['field_attributes']['id']; ?>">
903
904
				<?php echo $field['label']; ?>
905
906
				<?php if ( $field['required'] ) : ?>
907
					<span class="give-required-indicator">*</span>
908
				<?php endif; ?>
909
910
				<?php if ( $field['tooltip'] ) : ?>
911
					<span class="give-tooltip give-icon give-icon-question" data-tooltip="<?php echo $field['tooltip'] ?>"></span>
912
				<?php endif; ?>
913
			</label>
914
			<?php echo $field['after_label']; ?>
915
		<?php endif; ?>
916
		<?php
917
		return ob_get_clean();
918
	}
919
920
	/**
921
	 * Get field attribute string from field arguments.
922
	 *
923
	 * @since  1.9
924
	 * @access private
925
	 *
926
	 * @param array $attributes
927
	 *
928
	 * @return array|string
929
	 */
930
	private function get_attributes( $attributes ) {
931
		$field_attributes_val = '';
932
933
		if ( ! empty( $attributes ) ) {
934
			foreach ( $attributes as $attribute_name => $attribute_val ) {
935
				$field_attributes_val[] = "{$attribute_name}=\"{$attribute_val}\"";
936
			}
937
		}
938
939
		if ( ! empty( $field_attributes_val ) ) {
940
			$field_attributes_val = implode( ' ', $field_attributes_val );
941
		}
942
943
		return $field_attributes_val;
944
	}
945
946
	/**
947
	 * Set default values for fields
948
	 *
949
	 * @since  1.0
950
	 * @access private
951
	 *
952
	 * @param array $field
953
	 * @param array $form
954
	 * @param bool  $fire_filter
955
	 *
956
	 * @return array
957
	 */
958
	public static function set_default_values( $field, $form = null, $fire_filter = true ) {
959
		/**
960
		 * Filter the field before set default values.
961
		 *
962
		 * @since 1.9
963
		 *
964
		 * @param array $field
965
		 * @param array $form
966
		 */
967
		$field = $fire_filter
968
			? apply_filters( 'give_field_api_pre_set_default_values', $field, $form )
969
			: $field;
970
971
		switch ( self::$instance->get_field_type( $field ) ) {
972
			case 'block':
973
				// Set default values for block.
974
				$field = wp_parse_args( $field, self::$block_defaults );
975
976
				// Set wrapper class.
977
				$field['block_attributes']['class'] = empty( $field['block_attributes']['class'] )
978
					? "give-block-wrapper js-give-block-wrapper give-block-{$field['name']}"
979
					: "give-block-wrapper js-give-block-wrapper give-block-{$field['name']} {$field['block_attributes']['class']}";
980
981
				foreach ( $field['fields'] as $key => $single_field ) {
982
					$single_field['name']    = ! empty( $single_field['name'] )
983
						? $single_field['name']
984
						: $key;
985
					$field['fields'][ $key ] = self::$instance->set_default_values( $single_field, $form, false );
986
				}
987
988
				break;
989
990
			case 'section':
991
				// Set default values for block.
992
				$field = wp_parse_args( $field, self::$section_defaults );
993
994
				// Set wrapper class.
995
				$field['section_attributes']['class'] = empty( $field['section_attributes']['class'] )
996
					? 'give-section-wrapper'
997
					: "give-section-wrapper {$field['section_attributes']['class']}";
998
999
				foreach ( $field['fields'] as $key => $single_field ) {
1000
					$single_field['name']    = ! empty( $single_field['name'] )
1001
						? $single_field['name']
1002
						: $key;
1003
					$field['fields'][ $key ] = self::$instance->set_default_values( $single_field, $form, false );
1004
				}
1005
1006
				break;
1007
1008
			default:
1009
				// Set default values for field or section.
1010
				$field = wp_parse_args( $field, self::$field_defaults );
1011
1012
				// Set ID.
1013
				$field['field_attributes']['id'] = empty( $field['field_attributes']['id'] )
1014
					? "give-{$field['name']}-field"
1015
					: $field['field_attributes']['id'];
1016
1017
				// Set class.
1018
				$field['field_attributes']['class'] = empty( $field['field_attributes']['class'] )
1019
					? "give-field js-give-field give-field-type-{$field['type']}"
1020
					: "give-field js-give-field give-field-type-{$field['type']} {$field['field_attributes']['class']}";
1021
1022
				// Set wrapper class.
1023
				$field['wrapper_attributes']['class'] = empty( $field['wrapper_attributes']['class'] )
1024
					? 'give-field-wrapper'
1025
					: "give-field-wrapper {$field['wrapper_attributes']['class']}";
1026
1027
				/**
1028
				 * Filter the field values.
1029
				 *
1030
				 * @since 1.9
1031
				 *
1032
				 * @param array $field
1033
				 * @param array $form
1034
				 */
1035
				$field = apply_filters( 'give_field_api_set_values', $field, $form );
1036
		}
1037
1038
		/**
1039
		 * Filter the field after set default values.
1040
		 *
1041
		 * @since 1.9
1042
		 *
1043
		 * @param array $field
1044
		 * @param array $form
1045
		 */
1046
		$field = $fire_filter
1047
			? apply_filters( 'give_field_api_post_set_default_values', $field, $form )
1048
			: $field;
1049
1050
		return $field;
1051
	}
1052
1053
1054
	/**
1055
	 * Set responsive fields.
1056
	 *
1057
	 * @since  1.9
1058
	 * @access private
1059
	 *
1060
	 * @param $form
1061
	 *
1062
	 * @return mixed
1063
	 */
1064
	private function set_responsive_field( &$form ) {
1065
1066
		foreach ( $form['fields'] as $key => $field ) {
1067
			switch ( true ) {
1068
				case array_key_exists( 'fields', $field ):
1069
					foreach ( $field['fields'] as $section_field_index => $section_field ) {
1070
						if ( ! self::$instance->is_sub_section( $section_field ) ) {
1071
							continue;
1072
						}
1073
1074
						$form['fields'][ $key ]['fields'][ $section_field_index ]['wrapper_attributes']['class'] = 'give-form-col';
1075
1076
						if ( array_key_exists( 'sub_section_end', $section_field ) ) {
1077
							$form['fields'][ $key ]['fields'][ $section_field_index ]['wrapper_attributes']['class'] = 'give-form-col give-form-col-end';
1078
1079
							// Clear float left for next field.
1080
							$fields_keys = array_keys( $form['fields'][ $key ]['fields'] );
1081
1082
							if ( $next_field_key = array_search( $section_field_index, $fields_keys ) ) {
1083
								if (
1084
									! isset( $fields_keys[ $next_field_key + 1 ] )
1085
									|| ! isset( $form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ] )
1086
								) {
1087
									continue;
1088
								}
1089
1090
								$next_field = $form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ];
1091
1092
								$next_field['wrapper_attributes']['class'] = isset( $next_field['wrapper_attributes']['class'] )
1093
									? $next_field['wrapper_attributes']['class'] . ' give-clearfix'
1094
									: 'give-clearfix';
1095
1096
								$form['fields'][ $key ]['fields'][ $fields_keys[ $next_field_key + 1 ] ] = $next_field;
1097
							}
1098
						}
1099
					}
1100
1101
					break;
1102
1103
				default:
1104
					if ( ! self::$instance->is_sub_section( $field ) ) {
1105
						continue;
1106
					}
1107
1108
					$form['fields'][ $key ]['wrapper_attributes']['class'] = 'give-form-col';
1109
1110
					if ( array_key_exists( 'sub_section_end', $field ) ) {
1111
						$form['fields'][ $key ]['wrapper_attributes']['class'] = 'give-form-col give-form-col-end';
1112
1113
						// Clear float left for next field.
1114
						$fields_keys = array_keys( $form['fields'] );
1115
1116
						if ( $next_field_key = array_search( $key, $fields_keys ) ) {
1117
							$form['fields'][ $fields_keys[ $next_field_key + 1 ] ]['wrapper_attributes']['class'] = 'give-clearfix';
1118
						}
1119
					}
1120
			}
1121
		}
1122
	}
1123
1124
1125
	/**
1126
	 * Check if current field is part of sub section or not.
1127
	 *
1128
	 * @since  1.9
1129
	 * @access private
1130
	 *
1131
	 * @param $field
1132
	 *
1133
	 * @return bool
1134
	 */
1135
	private function is_sub_section( $field ) {
1136
		$is_sub_section = false;
1137
		if ( array_key_exists( 'sub_section_start', $field ) || array_key_exists( 'sub_section_end', $field ) ) {
1138
			$is_sub_section = true;
1139
		}
1140
1141
		return $is_sub_section;
1142
	}
1143
1144
1145
	/**
1146
	 * Get field type.
1147
	 *
1148
	 * @since  1.9
1149
	 * @access private
1150
	 *
1151
	 * @param $field
1152
	 *
1153
	 * @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...
1154
	 */
1155
	public static function get_field_type( $field ) {
1156
		$field_type = 'field';
1157
1158
		if (
1159
			isset( $field['type'] )
1160
			&& 'block' === $field['type']
1161
		) {
1162
			$field_type = 'block';
1163
1164
		} elseif (
1165
			array_key_exists( 'fields', $field )
1166
			&& 'section' === $field['type']
1167
		) {
1168
			$field_type = 'section';
1169
1170
		}
1171
1172
		return $field_type;
1173
	}
1174
1175
	/**
1176
	 * Is the element a button?
1177
	 *
1178
	 * @since  1.9
1179
	 * @access static
1180
	 *
1181
	 * @param array $element
1182
	 *
1183
	 * @return bool
0 ignored issues
show
Documentation introduced by
Should the return type not be integer?

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...
1184
	 */
1185
	static function is_button( $element ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1186
		return preg_match( '/^button|submit$/', $element['#type'] );
1187
	}
1188
}
1189