Completed
Push — issues/611 ( 661115...758b1c )
by Ravinder
21:11
created

Give_Admin_Settings::output_fields()   F

Complexity

Conditions 81
Paths 1346

Size

Total Lines 508
Code Lines 319

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 81
eloc 319
nc 1346
nop 2
dl 0
loc 508
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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 23 and the first side effect is on line 13.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

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

Loading history...
2
/**
3
 * Give Admin Settings Class
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Give_Admin_Settings
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
9
 * @since       1.8
10
 */
11
12
if ( ! defined( 'ABSPATH' ) ) {
13
	exit;
14
}
15
16
if ( ! class_exists( 'Give_Admin_Settings' ) ) :
17
18
	/**
19
	 * Give_Admin_Settings Class.
20
	 *
21
	 * @since 1.8
22
	 */
23
	class Give_Admin_Settings {
24
25
		/**
26
		 * Setting pages.
27
		 *
28
		 * @since 1.8
29
		 * @var   array List of settings.
30
		 */
31
		private static $settings = array();
32
33
		/**
34
		 * Setting filter and action prefix.
35
		 *
36
		 * @since 1.8
37
		 * @var   string setting fileter and action anme prefix.
38
		 */
39
		private static $setting_filter_prefix = '';
40
41
		/**
42
		 * Error messages.
43
		 *
44
		 * @since 1.8
45
		 * @var   array List of errors.
46
		 */
47
		private static $errors = array();
48
49
		/**
50
		 * Update messages.
51
		 *
52
		 * @since 1.8
53
		 * @var   array List of messages.
54
		 */
55
		private static $messages = array();
56
57
		/**
58
		 * Include the settings page classes.
59
		 *
60
		 * @since  1.8
61
		 * @return array
62
		 */
63
		public static function get_settings_pages() {
64
			/**
65
			 * Filter the setting page.
66
			 *
67
			 * Note: filter dynamically fire on basis of setting page slug.
68
			 * For example: if you register a setting page with give-settings menu slug
69
			 *              then filter will be give-settings_get_settings_pages
70
			 *
71
			 * @since 1.8
72
			 *
73
			 * @param array $settings Array of settings class object.
74
			 */
75
			self::$settings = apply_filters( self::$setting_filter_prefix . '_get_settings_pages', array() );
76
77
			return self::$settings;
78
		}
79
80
		/**
81
		 * Save the settings.
82
		 *
83
		 * @since  1.8
84
		 * @return void
85
		 */
86
		public static function save() {
87
			$current_tab = give_get_current_setting_tab();
88
89
			if ( empty( $_REQUEST['_give-save-settings'] ) || ! wp_verify_nonce( $_REQUEST['_give-save-settings'], 'give-save-settings' ) ) {
90
				echo '<div class="notice error"><p>' . __( 'Action failed. Please refresh the page and retry.', 'give' ) . '</p></div>';
91
				die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method save() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
92
			}
93
94
			/**
95
			 * Trigger Action.
96
			 *
97
			 * Note: action dynamically fire on basis of setting page slug and current tab.
98
			 * For example: if you register a setting page with give-settings menu slug and general current tab name
99
			 *              then action will be give-settings_save_general
100
			 *
101
			 * @since 1.8
102
			 */
103
			do_action( self::$setting_filter_prefix . '_save_' . $current_tab );
104
105
			self::add_message( 'give-setting-updated', __( 'Your settings have been saved.', 'give' ) );
106
107
			/**
108
			 * Trigger Action.
109
			 *
110
			 * Note: action dynamically fire on basis of setting page slug.
111
			 * For example: if you register a setting page with give-settings menu slug
112
			 *              then action will be give-settings_saved
113
			 *
114
			 * @since 1.8
115
			 */
116
			do_action( self::$setting_filter_prefix . '_saved' );
117
		}
118
119
		/**
120
		 * Add a message.
121
		 *
122
		 * @since  1.8
123
		 *
124
		 * @param  string $code    Message code (Note: This should be unique).
125
		 * @param  string $message Message text.
126
		 *
127
		 * @return void
128
		 */
129
		public static function add_message( $code, $message ) {
130
			self::$messages[ $code ] = $message;
131
		}
132
133
		/**
134
		 * Add an error.
135
		 *
136
		 * @since  1.8
137
		 *
138
		 * @param  string $code    Message code (Note: This should be unique).
139
		 * @param  string $message Message text.
140
		 *
141
		 * @return void
142
		 */
143
		public static function add_error( $code, $message ) {
144
			self::$errors[ $code ] = $message;
145
		}
146
147
		/**
148
		 * Output messages + errors.
149
		 *
150
		 * @since  1.8
151
		 * @return void
152
		 */
153
		public static function show_messages() {
154
			$notice_html = '';
155
			$classes     = 'give-notice settings-error notice is-dismissible';
156
157
			self::$errors   = apply_filters( self::$setting_filter_prefix . '_error_notices', self::$errors );
158
			self::$messages = apply_filters( self::$setting_filter_prefix . '_update_notices', self::$messages );
159
160
			if ( 0 < count( self::$errors ) ) {
161
				foreach ( self::$errors as $code => $message ) {
162
					$notice_html .= '<div id="setting-error-' . $code . '" class="' . $classes . ' error"><p><strong>' . $message . '</strong></p></div>';
163
				}
164
			}
165
166
			if ( 0 < count( self::$messages ) ) {
167
				foreach ( self::$messages as $code => $message ) {
168
					$notice_html .= '<div id="setting-error-' . $code . '" class="' . $classes . ' updated"><p><strong>' . $message . '</strong></p></div>';
169
				}
170
			}
171
172
			echo $notice_html;
173
		}
174
175
		/**
176
		 * Settings page.
177
		 *
178
		 * Handles the display of the main give settings page in admin.
179
		 *
180
		 * @since  1.8
181
		 * @return void|bool
182
		 */
183
		public static function output() {
184
			// Get current setting page.
185
			self::$setting_filter_prefix = give_get_current_setting_page();
186
187
			// Bailout: Exit if setting page is not defined.
188
			if ( empty( self::$setting_filter_prefix ) ) {
189
				return false;
190
			}
191
192
			/**
193
			 * Trigger Action.
194
			 *
195
			 * Note: action dynamically fire on basis of setting page slug
196
			 * For example: if you register a setting page with give-settings menu slug
197
			 *              then action will be give-settings_start
198
			 *
199
			 * @since 1.8
200
			 */
201
			do_action( self::$setting_filter_prefix . '_start' );
202
203
			$current_tab = give_get_current_setting_tab();
204
205
			// Include settings pages.
206
			self::get_settings_pages();
207
208
			// Save settings if data has been posted.
209
			if ( ! empty( $_POST ) ) {
210
				self::save();
211
			}
212
213
			/**
214
			 * Filter the tabs for current setting page.
215
			 *
216
			 * Note: filter dynamically fire on basis of setting page slug.
217
			 * For example: if you register a setting page with give-settings menu slug and general current tab name
218
			 *              then action will be give-settings_tabs_array
219
			 *
220
			 * @since 1.8
221
			 */
222
			$tabs = apply_filters( self::$setting_filter_prefix . '_tabs_array', array() );
223
224
			include 'views/html-admin-settings.php';
225
226
			return true;
227
		}
228
229
		/**
230
		 * Get a setting from the settings API.
231
		 *
232
		 * @since  1.8
233
		 *
234
		 * @param  string $option_name
235
		 * @param  string $field_id
236
		 * @param  mixed  $default
237
		 *
238
		 * @return string|bool
239
		 */
240
		public static function get_option( $option_name = '', $field_id = '', $default = false ) {
241
			// Bailout.
242
			if ( empty( $option_name ) && empty( $field_id ) ) {
243
				return false;
244
			}
245
246
			if ( ! empty( $field_id ) && ! empty( $option_name ) ) {
247
				// Get field value if any.
248
				$option_value = get_option( $option_name );
249
250
				$option_value = ( is_array( $option_value ) && array_key_exists( $field_id, $option_value ) )
251
					? $option_value[ $field_id ]
252
					: $default;
253
			} else {
254
				// If option name is empty but not field name then this means, setting is direct store to option table under there field name.
255
				$option_name = ! $option_name ? $field_id : $option_name;
256
257
				// Get option value if any.
258
				$option_value = get_option( $option_name, $default );
259
			}
260
261
			return $option_value;
262
		}
263
264
		/**
265
		 * Output admin fields.
266
		 *
267
		 * Loops though the give options array and outputs each field.
268
		 *
269
		 * @todo: Refactor this function
270
		 * @since  1.8
271
		 *
272
		 * @param  array  $options     Opens array to output
273
		 * @param  string $option_name Opens array to output
274
		 *
275
		 * @return void
276
		 */
277
		public static function output_fields( $options, $option_name = '' ) {
278
			$current_tab = give_get_current_setting_tab();
279
280
			// Field Default values.
281
			$defaults = array(
282
				'id'               => '',
283
				'class'            => '',
284
				'css'              => '',
285
				'default'          => '',
286
				'desc'             => '',
287
				'table_html'       => true,
288
				'repeat'           => false,
289
				'repeat_btn_title' => __( 'Add Field', 'give' ),
290
			);
291
292
			foreach ( $options as $value ) {
293
				if ( ! isset( $value['type'] ) ) {
294
					continue;
295
				}
296
297
				// Set title.
298
				$defaults['title'] = isset( $value['name'] ) ? $value['name'] : '';
299
300
				// Set default setting.
301
				$value = wp_parse_args( $value, $defaults );
302
303
				// Colorpicker field.
304
				$value['class'] = ( 'colorpicker' === $value['type'] ? trim( $value['class'] ) . ' give-colorpicker' : $value['class'] );
305
				$value['type']  = ( 'colorpicker' === $value['type'] ? 'text' : $value['type'] );
306
307
308
				// Custom attribute handling.
309
				$custom_attributes = array();
310
311
				if ( ! empty( $value['attributes'] ) && is_array( $value['attributes'] ) ) {
312
					foreach ( $value['attributes'] as $attribute => $attribute_value ) {
313
						$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
314
					}
315
				}
316
317
				// Description handling.
318
				$description          = self::get_field_description( $value );
319
320
				// Switch based on type.
321
				switch ( $value['type'] ) {
322
323
					// Section Titles
324
					case 'title':
325
						if ( ! empty( $value['title'] ) || ! empty( $value['desc'] ) ) {
326
							?>
327
							<div class="give-setting-tab-header give-setting-tab-header-<?php echo $current_tab; ?>">
328
								<?php if ( ! empty( $value['title'] ) ) : ?>
329
									<h2><?php echo self::get_field_title( $value ); ?></h2><hr>
330
								<?php endif; ?>
331
332
								<?php if ( ! empty( $value['desc'] ) ) : ?>
333
									<?php echo wpautop( wptexturize( wp_kses_post( $value['desc'] ) ) ); ?>
334
								<?php endif; ?>
335
							</div>
336
							<?php
337
						}
338
339
						if ( $value['table_html'] ) {
340
							echo '<table class="form-table give-setting-tab-body give-setting-tab-body-' . $current_tab . '">' . "\n\n";
341
						}
342
343
						if ( ! empty( $value['id'] ) ) {
344
345
							/**
346
							 * Trigger Action.
347
							 *
348
							 * Note: action dynamically fire on basis of field id.
349
							 *
350
							 * @since 1.8
351
							 */
352
							do_action( 'give_settings_' . sanitize_title( $value['id'] ) );
353
						}
354
355
						break;
356
357
					// Section Ends.
358
					case 'sectionend':
359
						if ( ! empty( $value['id'] ) ) {
360
361
							/**
362
							 * Trigger Action.
363
							 *
364
							 * Note: action dynamically fire on basis of field id.
365
							 *
366
							 * @since 1.8
367
							 */
368
							do_action( 'give_settings_' . sanitize_title( $value['id'] ) . '_end' );
369
						}
370
371
						if ( $value['table_html'] ) {
372
							echo '</table>';
373
						}
374
375
						if ( ! empty( $value['id'] ) ) {
376
377
							/**
378
							 * Trigger Action.
379
							 *
380
							 * Note: action dynamically fire on basis of field id.
381
							 *
382
							 * @since 1.8
383
							 */
384
							do_action( 'give_settings_' . sanitize_title( $value['id'] ) . '_after' );
385
						}
386
387
						break;
388
389
					// Standard text inputs and subtypes like 'number'.
390
					case 'colorpicker':
391
					case 'text':
392
					case 'email':
393
					case 'number':
394
					case 'password' :
395
396
						$type = $value['type'];
397
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
398
399
						// Set default value for repeater field if not any value set yet.
400
						if( $value['repeat'] && is_string( $option_value ) ) {
401
							$option_value = array( $value['default'] );
402
						}
403
						?>
404
						<tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
405
							<th scope="row" class="titledesc">
406
								<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
407
							</th>
408
							<td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?>">
409
								<?php if ( $value['repeat'] ) : ?>
410
									<?php foreach ( $option_value as $index => $field_value ) : ?>
0 ignored issues
show
Bug introduced by
The expression $option_value of type string|boolean|array<integer,?,{"0":"?"}> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
411
										<p>
412
											<input
413
													name="<?php echo esc_attr( $value['id'] ); ?>[]"
414
													type="<?php echo esc_attr( $type ); ?>"
415
													style="<?php echo esc_attr( $value['css'] ); ?>"
416
													value="<?php echo esc_attr( $field_value ); ?>"
417
													class="give-input-field<?php echo( empty( $value['class'] ) ? '' : ' ' . esc_attr( $value['class'] ) ); ?> <?php echo esc_attr( $value['id'] ); ?>"
418
												<?php echo implode( ' ', $custom_attributes ); ?>
419
											/>
420
											<span class="give-remove-setting-field" title="<?php esc_html_e( 'Remove setting field', 'give' ); ?>">-</span>
421
										</p>
422
									<?php endforeach; ?>
423
									<a href="#" data-id="<?php echo $value['id']; ?>" class="give-repeat-setting-field button-secondary"><?php echo $value['repeat_btn_title']; ?></a>
424
								<?php else : ?>
425
									<input
426
											name="<?php echo esc_attr( $value['id'] ); ?>"
427
											id="<?php echo esc_attr( $value['id'] ); ?>"
428
											type="<?php echo esc_attr( $type ); ?>"
429
											style="<?php echo esc_attr( $value['css'] ); ?>"
430
											value="<?php echo esc_attr( $option_value ); ?>"
431
											class="give-input-field<?php echo( empty( $value['class'] ) ? '' : ' ' . esc_attr( $value['class'] ) ); ?>"
432
										<?php echo implode( ' ', $custom_attributes ); ?>
433
									/>
434
								<?php endif; ?>
435
								<?php echo $description; ?>
436
							</td>
437
							</tr><?php
438
							break;
439
440
					// Textarea.
441
					case 'textarea':
442
443
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
444
445
						?>
446
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
447
                        <th scope="row" class="titledesc">
448
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
449
                        </th>
450
                        <td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?>">
451
								<textarea
452
                                        name="<?php echo esc_attr( $value['id'] ); ?>"
453
                                        id="<?php echo esc_attr( $value['id'] ); ?>"
454
                                        style="<?php echo esc_attr( $value['css'] ); ?>"
455
                                        class="<?php echo esc_attr( $value['class'] ); ?>"
456
                                        rows="10"
457
                                        cols="60"
458
									<?php echo implode( ' ', $custom_attributes ); ?>
459
                                ><?php echo esc_textarea( $option_value ); ?></textarea>
460
							<?php echo $description; ?>
461
                        </td>
462
                        </tr><?php
463
						break;
464
465
					// Select boxes.
466
					case 'select' :
467
					case 'multiselect' :
468
469
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
470
471
						?>
472
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
473
                        <th scope="row" class="titledesc">
474
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
475
                        </th>
476
                        <td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?>">
477
                            <select
478
                                    name="<?php echo esc_attr( $value['id'] ); ?><?php if ( $value['type'] == 'multiselect' ) {
479
										echo '[]';
480
									} ?>"
481
                                    id="<?php echo esc_attr( $value['id'] ); ?>"
482
                                    style="<?php echo esc_attr( $value['css'] ); ?>"
483
                                    class="<?php echo esc_attr( $value['class'] ); ?>"
484
								<?php echo implode( ' ', $custom_attributes ); ?>
485
								<?php echo ( 'multiselect' == $value['type'] ) ? 'multiple="multiple"' : ''; ?>
486
                            >
487
488
								<?php
489
								if ( ! empty( $value['options'] ) ) {
490
									foreach ( $value['options'] as $key => $val ) {
491
										?>
492
                                        <option value="<?php echo esc_attr( $key ); ?>" <?php
493
494
										if ( is_array( $option_value ) ) {
495
											selected( in_array( $key, $option_value ), true );
496
										} else {
497
											selected( $option_value, $key );
498
										}
499
500
										?>><?php echo $val ?></option>
501
										<?php
502
									}
503
								}
504
								?>
505
506
                            </select> <?php echo $description; ?>
507
                        </td>
508
                        </tr><?php
509
						break;
510
511
					// Radio inputs.
512
					case 'radio_inline' :
513
						$value['class'] = empty( $value['class'] ) ? 'give-radio-inline' : $value['class'] . ' give-radio-inline';
514
					case 'radio' :
515
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
516
						?>
517
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
518
                        <th scope="row" class="titledesc">
519
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
520
                        </th>
521
                        <td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?> <?php echo( ! empty( $value['class'] ) ? $value['class'] : '' ); ?>">
522
                            <fieldset>
523
                                <ul>
524
									<?php
525
									foreach ( $value['options'] as $key => $val ) {
526
										?>
527
                                        <li>
528
                                            <label><input
529
                                                        name="<?php echo esc_attr( $value['id'] ); ?>"
530
                                                        value="<?php echo $key; ?>"
531
                                                        type="radio"
532
                                                        style="<?php echo esc_attr( $value['css'] ); ?>"
533
													<?php echo implode( ' ', $custom_attributes ); ?>
534
													<?php checked( $key, $option_value ); ?>
535
                                                /> <?php echo $val ?></label>
536
                                        </li>
537
										<?php
538
									}
539
									?>
540
									<?php echo $description; ?>
541
                            </fieldset>
542
                        </td>
543
                        </tr><?php
544
						break;
545
546
					// Checkbox input.
547
					case 'checkbox' :
548
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
549
						?>
550
                        <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
551
                            <th scope="row" class="titledesc">
552
                                <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
553
                            </th>
554
                            <td class="give-forminp">
555
                                <input
556
                                        name="<?php echo esc_attr( $value['id'] ); ?>"
557
                                        id="<?php echo esc_attr( $value['id'] ); ?>"
558
                                        type="checkbox"
559
                                        class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
560
                                        value="1"
561
									<?php checked( $option_value, 'on' ); ?>
562
									<?php echo implode( ' ', $custom_attributes ); ?>
563
                                />
564
								<?php echo $description; ?>
565
                            </td>
566
                        </tr>
567
						<?php
568
						break;
569
570
					// Multi Checkbox input.
571
					case 'multicheck' :
572
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
573
						$option_value = is_array( $option_value ) ? $option_value : array();
574
						?>
575
                        <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
576
                            <th scope="row" class="titledesc">
577
                                <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
578
                            </th>
579
                            <td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?> <?php echo( ! empty( $value['class'] ) ? $value['class'] : '' ); ?>">
580
                                <fieldset>
581
                                    <ul>
582
										<?php
583
										foreach ( $value['options'] as $key => $val ) {
584
											?>
585
                                            <li>
586
                                                <label>
587
                                                    <input
588
                                                            name="<?php echo esc_attr( $value['id'] ); ?>[]"
589
                                                            value="<?php echo $key; ?>"
590
                                                            type="checkbox"
591
                                                            style="<?php echo esc_attr( $value['css'] ); ?>"
592
														<?php echo implode( ' ', $custom_attributes ); ?>
593
														<?php if ( in_array( $key, $option_value ) ) {
594
															echo 'checked="checked"';
595
														} ?>
596
                                                    /> <?php echo $val ?>
597
                                                </label>
598
                                            </li>
599
											<?php
600
										}
601
										?>
602
										<?php echo $description; ?>
603
                                </fieldset>
604
                            </td>
605
                        </tr>
606
						<?php
607
						break;
608
609
					// File input field.
610
					case 'file' :
611
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
612
						?>
613
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
614
                        <th scope="row" class="titledesc">
615
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
616
                        </th>
617
                        <td class="give-forminp">
618
                            <div class="give-field-wrap">
619
                                <label for="<?php echo $value['id'] ?>">
620
                                    <input
621
                                            name="<?php echo esc_attr( $value['id'] ); ?>"
622
                                            id="<?php echo esc_attr( $value['id'] ); ?>"
623
                                            type="text"
624
                                            class="give-input-field<?php echo esc_attr( isset( $value['class'] ) ? ' ' . $value['class'] : '' ); ?>"
625
                                            value="<?php echo $option_value; ?>"
626
                                            style="<?php echo esc_attr( $value['css'] ); ?>"
627
										<?php echo implode( ' ', $custom_attributes ); ?>
628
                                    />&nbsp;&nbsp;&nbsp;&nbsp;<input class="give-upload-button button" type="button"
629
                                                                     value="<?php echo esc_html__( 'Add or Upload File', 'give' ); ?>">
630
									<?php echo $description ?>
631
                                    <div class="give-image-thumb<?php echo ! $option_value ? ' give-hidden' : ''; ?>">
632
                                        <span class="give-delete-image-thumb dashicons dashicons-no-alt"></span>
633
                                        <img src="<?php echo $option_value; ?>" alt="">
634
                                    </div>
635
                                </label>
636
                            </div>
637
                        </td>
638
                        </tr><?php
639
						break;
640
641
					// WordPress Editor.
642
					case 'wysiwyg' :
643
						// Get option value.
644
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
645
646
						// Get editor settings.
647
						$editor_settings = ! empty( $value['options'] ) ? $value['options'] : array();
648
						?>
649
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
650
                        <th scope="row" class="titledesc">
651
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
652
                        </th>
653
                        <td class="give-forminp">
654
							<?php wp_editor( $option_value, $value['id'], $editor_settings ); ?>
655
							<?php echo $description; ?>
656
                        </td>
657
                        </tr><?php
658
						break;
659
660
					// Custom: System setting field.
661
					case 'system_info' :
662
						?>
663
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
664
                        <th scope="row" class="titledesc">
665
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
666
                        </th>
667
                        <td class="give-forminp">
668
							<?php give_system_info_callback(); ?>
669
							<?php echo $description; ?>
670
                        </td>
671
                        </tr><?php
672
						break;
673
674
					// Custom: Default gateways setting field.
675
					case 'default_gateway' :
676
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
677
						?>
678
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
679
                        <th scope="row" class="titledesc">
680
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
681
                        </th>
682
                        <td class="give-forminp">
683
							<?php give_default_gateway_callback( $value, $option_value ); ?>
684
							<?php echo $description; ?>
685
                        </td>
686
                        </tr><?php
687
						break;
688
689
					// Custom: Enable gateways setting field.
690
					case 'enabled_gateways' :
691
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
692
						?>
693
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
694
                        <th scope="row" class="titledesc">
695
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
696
                        </th>
697
                        <td class="give-forminp">
698
							<?php give_enabled_gateways_callback( $value, $option_value ); ?>
699
							<?php echo $description; ?>
700
                        </td>
701
                        </tr><?php
702
						break;
703
704
					// Custom: Email preview buttons field.
705
					case 'email_preview_buttons' :
706
						?>
707
						<tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
708
						<th scope="row" class="titledesc">
709
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
710
						</th>
711
						<td class="give-forminp">
712
							<?php give_email_preview_buttons_callback( $value ); ?>
713
							<?php echo $description; ?>
714
                        </td>
715
                        </tr><?php
716
						break;
717
718
					// Custom: API field.
719
					case 'api' :
720
						give_api_callback();
721
						echo $description;
722
						break;
723
724
					// Custom: Gateway API key.
725
					case 'api_key' :
726
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
727
						$type         = ! empty( $option_value ) ? 'password' : 'text';
728
						?>
729
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
730
                        <th scope="row" class="titledesc">
731
                            <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo self::get_field_title( $value ); ?></label>
732
                        </th>
733
                        <td class="give-forminp give-forminp-<?php echo sanitize_title( $value['type'] ) ?>">
734
                            <input
735
                                    name="<?php echo esc_attr( $value['id'] ); ?>"
736
                                    id="<?php echo esc_attr( $value['id'] ); ?>"
737
                                    type="<?php echo esc_attr( $type ); ?>"
738
                                    style="<?php echo esc_attr( $value['css'] ); ?>"
739
                                    value="<?php echo esc_attr( trim( $option_value ) ); ?>"
740
                                    class="give-input-field<?php echo( empty( $value['class'] ) ? '' : ' ' . esc_attr( $value['class'] ) ); ?>"
741
								<?php echo implode( ' ', $custom_attributes ); ?>
742
                            /> <?php echo $description; ?>
743
                        </td>
744
                        </tr><?php
745
						break;
746
747
					// Custom: Log field.
748
					case 'logs' :
749
						// Note: there are no need to check for html field param because we want custom html to this field.
750
						give_reports_tab_logs();
751
						echo $description;
752
						break;
753
754
					// Custom: API field.
755
					case 'data' :
756
						give_tools_recount_stats_display();
757
						echo $description;
758
						break;
759
760
					// Custom: Give Docs Link field type.
761
					case 'give_docs_link' :
762
						?>
763
                    <tr valign="top" <?php echo ! empty( $value['wrapper_class'] ) ? 'class="' . $value['wrapper_class'] . '"' : '' ?>>
764
                        <td class="give-docs-link" colspan="2">
765
							<?php
766
							echo '<p class="give-docs-link"><a href="' . esc_url( $value['url'] )
767
							     . '" target="_blank">'
768
							     . sprintf( esc_html__( 'Need Help? See docs on "%s"' ), $value['title'] )
769
							     . '<span class="dashicons dashicons-editor-help"></span></a></p>';
770
							?>
771
                        </td>
772
                        </tr><?php
773
						break;
774
775
					// Default: run an action
776
					// You can add or handle your custom field action.
777
					default:
778
						// Get option value.
779
						$option_value = self::get_option( $option_name, $value['id'], $value['default'] );
780
						do_action( 'give_admin_field_' . $value['type'], $value, $option_value );
781
						break;
782
				}
783
			}
784
		}
785
786
		/**
787
		 * Helper function to get the formatted description for a given form field.
788
		 * Plugins can call this when implementing their own custom settings types.
789
		 *
790
		 * @since  1.8
791
		 *
792
		 * @param  array $value The form field value array
793
		 *
794
		 * @return string The HTML description of the field.
795
		 */
796
		public static function get_field_description( $value ) {
797
			$description = '';
798
799
			// Support for both 'description' and 'desc' args.
800
			$description_key = isset( $value['description'] ) ? 'description' : 'desc';
801
			$value           = ( isset( $value[ $description_key ] ) && ! empty( $value[ $description_key ] ) ) ? $value[ $description_key ] : '';
802
803
			if ( ! empty( $value ) ) {
804
				$description = '<p class="give-field-description">' . wp_kses_post( $value ) . '</p>';
805
			}
806
807
			return $description;
808
		}
809
810
811
		/**
812
		 * Helper function to get the formated title.
813
		 * Plugins can call this when implementing their own custom settings types.
814
		 *
815
		 * @since  1.8
816
		 *
817
		 * @param  array $value The form field value array
818
		 *
819
		 * @return array The description and tip as a 2 element array
820
		 */
821
		public static function get_field_title( $value ) {
822
			$title = esc_html( $value['title'] );
823
824
			// If html tag detected then allow them to print.
825
			if ( strip_tags( $title ) ) {
826
				$title = $value['title'];
827
			}
828
829
			return $title;
830
		}
831
832
		/**
833
		 * Save admin fields.
834
		 *
835
		 * Loops though the give options array and outputs each field.
836
		 *
837
		 * @since  1.8
838
		 *
839
		 * @param  array  $options     Options array to output
840
		 * @param  string $option_name Option name to save output. If empty then option will be store in there own option name i.e option id.
841
		 *
842
		 * @return bool
843
		 */
844
		public static function save_fields( $options, $option_name = '' ) {
845
			if ( empty( $_POST ) ) {
846
				return false;
847
			}
848
849
			// Options to update will be stored here and saved later.
850
			$update_options = array();
851
852
			// Loop options and get values to save.
853
			foreach ( $options as $option ) {
854
				if ( ! isset( $option['id'] ) || ! isset( $option['type'] ) ) {
855
					continue;
856
				}
857
858
				// Get posted value.
859
				if ( strstr( $option['id'], '[' ) ) {
860
					parse_str( $option['id'], $option_name_array );
861
					$field_option_name = current( array_keys( $option_name_array ) );
862
					$setting_name      = key( $option_name_array[ $field_option_name ] );
863
					$raw_value         = isset( $_POST[ $field_option_name ][ $setting_name ] ) ? wp_unslash( $_POST[ $field_option_name ][ $setting_name ] ) : null;
864
				} else {
865
					$field_option_name = $option['id'];
866
					$setting_name      = '';
867
					$raw_value         = isset( $_POST[ $option['id'] ] ) ? wp_unslash( $_POST[ $option['id'] ] ) : null;
868
				}
869
870
				// Format the value based on option type.
871
				switch ( $option['type'] ) {
872
					case 'checkbox' :
873
						$value = is_null( $raw_value ) ? '' : 'on';
874
						break;
875
					case 'wysiwyg'  :
876
					case 'textarea' :
877
						$value = wp_kses_post( trim( $raw_value ) );
878
						break;
879
					case 'multiselect' :
880
						$value = array_filter( array_map( 'give_clean', (array) $raw_value ) );
881
						break;
882
					default :
883
						$value = give_clean( $raw_value );
884
						break;
885
				}
886
887
				/**
888
				 * Sanitize the value of an option.
889
				 *
890
				 * @since 1.8
891
				 */
892
				$value = apply_filters( 'give_admin_settings_sanitize_option', $value, $option, $raw_value );
893
894
				/**
895
				 * Sanitize the value of an option by option name.
896
				 *
897
				 * @since 1.8
898
				 */
899
				$value = apply_filters( "give_admin_settings_sanitize_option_{$field_option_name}", $value, $option, $raw_value );
900
901
				if ( is_null( $value ) ) {
902
					continue;
903
				}
904
905
				// Check if option is an array and handle that differently to single values.
906
				if ( $field_option_name && $setting_name ) {
907
					if ( ! isset( $update_options[ $field_option_name ] ) ) {
908
						$update_options[ $field_option_name ] = get_option( $field_option_name, array() );
909
					}
910
					if ( ! is_array( $update_options[ $field_option_name ] ) ) {
911
						$update_options[ $field_option_name ] = array();
912
					}
913
					$update_options[ $field_option_name ][ $setting_name ] = $value;
914
				} else {
915
					$update_options[ $field_option_name ] = $value;
916
				}
917
			}
918
919
			// Save all options in our array or there own option name i.e. option id.
920
			if ( empty( $option_name ) ) {
921
				foreach ( $update_options as $name => $value ) {
922
					update_option( $name, $value );
923
924
					/**
925
					 * Trigger action.
926
					 *
927
					 * Note: This is dynamically fire on basis of option name.
928
					 *
929
					 * @since 1.8
930
					 */
931
					do_action( "give_save_option_{$name}", $value, $name );
932
				}
933
			} else {
934
				$old_options    = ( $old_options = get_option( $option_name ) ) ? $old_options : array();
935
				$update_options = array_merge( $old_options, $update_options );
936
937
				update_option( $option_name, $update_options );
938
939
				/**
940
				 * Trigger action.
941
				 *
942
				 * Note: This is dynamically fire on basis of setting name.
943
				 *
944
				 * @since 1.8
945
				 */
946
				do_action( "give_save_settings_{$option_name}", $update_options, $option_name );
947
			}
948
949
			return true;
950
		}
951
	}
952
953
endif;
954