Completed
Push — issues/1038 ( d4c9fc...318ff5 )
by Ravinder
17:23
created

Give_Fields_API::render_custom_field()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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