WC_Admin_Settings::save()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 23
Code Lines 14

Duplication

Lines 3
Ratio 13.04 %

Importance

Changes 0
Metric Value
cc 3
dl 3
loc 23
rs 9.0856
c 0
b 0
f 0
eloc 14
nc 2
nop 0
1
<?php
2
/**
3
 * WooCommerce Admin Settings Class
4
 *
5
 * @author   WooThemes
6
 * @category Admin
7
 * @package  WooCommerce/Admin
8
 * @version  2.5.0
9
 */
10
11
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
if ( ! class_exists( 'WC_Admin_Settings' ) ) :
16
17
/**
18
 * WC_Admin_Settings Class.
19
 */
20
class WC_Admin_Settings {
21
22
	/**
23
	 * Setting pages.
24
	 *
25
	 * @var array
26
	 */
27
	private static $settings = array();
28
29
	/**
30
	 * Error messages.
31
	 *
32
	 * @var array
33
	 */
34
	private static $errors   = array();
35
36
	/**
37
	 * Update messages.
38
	 *
39
	 * @var array
40
	 */
41
	private static $messages = array();
42
43
	/**
44
	 * Include the settings page classes.
45
	 */
46
	public static function get_settings_pages() {
47
		if ( empty( self::$settings ) ) {
48
			$settings = array();
49
50
			include_once( 'settings/class-wc-settings-page.php' );
51
52
			$settings[] = include( 'settings/class-wc-settings-general.php' );
53
			$settings[] = include( 'settings/class-wc-settings-products.php' );
54
			$settings[] = include( 'settings/class-wc-settings-tax.php' );
55
			$settings[] = include( 'settings/class-wc-settings-shipping.php' );
56
			$settings[] = include( 'settings/class-wc-settings-checkout.php' );
57
			$settings[] = include( 'settings/class-wc-settings-accounts.php' );
58
			$settings[] = include( 'settings/class-wc-settings-emails.php' );
59
			$settings[] = include( 'settings/class-wc-settings-integrations.php' );
60
			$settings[] = include( 'settings/class-wc-settings-api.php' );
61
62
			self::$settings = apply_filters( 'woocommerce_get_settings_pages', $settings );
63
		}
64
65
		return self::$settings;
66
	}
67
68
	/**
69
	 * Save the settings.
70
	 */
71
	public static function save() {
72
		global $current_tab;
73
74 View Code Duplication
		if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
75
			die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
76
		}
77
78
		// Trigger actions
79
		do_action( 'woocommerce_settings_save_' . $current_tab );
80
		do_action( 'woocommerce_update_options_' . $current_tab );
81
		do_action( 'woocommerce_update_options' );
82
83
		self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) );
84
		self::check_download_folder_protection();
85
86
		// Clear any unwanted data and flush rules
87
		delete_transient( 'woocommerce_cache_excluded_uris' );
88
		WC()->query->init_query_vars();
89
		WC()->query->add_endpoints();
90
		flush_rewrite_rules();
91
92
		do_action( 'woocommerce_settings_saved' );
93
	}
94
95
	/**
96
	 * Add a message.
97
	 * @param string $text
98
	 */
99
	public static function add_message( $text ) {
100
		self::$messages[] = $text;
101
	}
102
103
	/**
104
	 * Add an error.
105
	 * @param string $text
106
	 */
107
	public static function add_error( $text ) {
108
		self::$errors[] = $text;
109
	}
110
111
	/**
112
	 * Output messages + errors.
113
	 * @return string
114
	 */
115
	public static function show_messages() {
116
		if ( sizeof( self::$errors ) > 0 ) {
117
			foreach ( self::$errors as $error ) {
118
				echo '<div id="message" class="error inline"><p><strong>' . esc_html( $error ) . '</strong></p></div>';
119
			}
120
		} elseif ( sizeof( self::$messages ) > 0 ) {
121
			foreach ( self::$messages as $message ) {
122
				echo '<div id="message" class="updated inline"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
123
			}
124
		}
125
	}
126
127
	/**
128
	 * Settings page.
129
	 *
130
	 * Handles the display of the main woocommerce settings page in admin.
131
	 */
132
	public static function output() {
133
		global $current_section, $current_tab;
134
135
		$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
136
137
		do_action( 'woocommerce_settings_start' );
138
139
		wp_enqueue_script( 'woocommerce_settings', WC()->plugin_url() . '/assets/js/admin/settings' . $suffix . '.js', array( 'jquery', 'jquery-ui-datepicker', 'jquery-ui-sortable', 'iris', 'select2' ), WC()->version, true );
140
141
		wp_localize_script( 'woocommerce_settings', 'woocommerce_settings_params', array(
142
			'i18n_nav_warning' => __( 'The changes you made will be lost if you navigate away from this page.', 'woocommerce' )
143
		) );
144
145
		// Include settings pages
146
		self::get_settings_pages();
147
148
		// Get current tab/section
149
		$current_tab     = empty( $_GET['tab'] ) ? 'general' : sanitize_title( $_GET['tab'] );
150
		$current_section = empty( $_REQUEST['section'] ) ? '' : sanitize_title( $_REQUEST['section'] );
151
152
		// Save settings if data has been posted
153
		if ( ! empty( $_POST ) ) {
154
			self::save();
155
		}
156
157
		// Add any posted messages
158
		if ( ! empty( $_GET['wc_error'] ) ) {
159
			self::add_error( stripslashes( $_GET['wc_error'] ) );
160
		}
161
162
		if ( ! empty( $_GET['wc_message'] ) ) {
163
			self::add_message( stripslashes( $_GET['wc_message'] ) );
164
		}
165
166
		// Get tabs for the settings page
167
		$tabs = apply_filters( 'woocommerce_settings_tabs_array', array() );
168
169
		include 'views/html-admin-settings.php';
170
	}
171
172
	/**
173
	 * Get a setting from the settings API.
174
	 *
175
	 * @param mixed $option_name
176
	 * @return string
177
	 */
178
	public static function get_option( $option_name, $default = '' ) {
179
		// Array value
180
		if ( strstr( $option_name, '[' ) ) {
181
182
			parse_str( $option_name, $option_array );
183
184
			// Option name is first key
185
			$option_name = current( array_keys( $option_array ) );
186
187
			// Get value
188
			$option_values = get_option( $option_name, '' );
189
190
			$key = key( $option_array[ $option_name ] );
191
192
			if ( isset( $option_values[ $key ] ) ) {
193
				$option_value = $option_values[ $key ];
194
			} else {
195
				$option_value = null;
196
			}
197
198
		// Single value
199
		} else {
200
			$option_value = get_option( $option_name, null );
201
		}
202
203
		if ( is_array( $option_value ) ) {
204
			$option_value = array_map( 'stripslashes', $option_value );
205
		} elseif ( ! is_null( $option_value ) ) {
206
			$option_value = stripslashes( $option_value );
207
		}
208
209
		return $option_value === null ? $default : $option_value;
210
	}
211
212
	/**
213
	 * Output admin fields.
214
	 *
215
	 * Loops though the woocommerce options array and outputs each field.
216
	 *
217
	 * @param array $options Opens array to output
218
	 */
219
	public static function output_fields( $options ) {
220
		foreach ( $options as $value ) {
221
			if ( ! isset( $value['type'] ) ) {
222
				continue;
223
			}
224
			if ( ! isset( $value['id'] ) ) {
225
				$value['id'] = '';
226
			}
227
			if ( ! isset( $value['title'] ) ) {
228
				$value['title'] = isset( $value['name'] ) ? $value['name'] : '';
229
			}
230
			if ( ! isset( $value['class'] ) ) {
231
				$value['class'] = '';
232
			}
233
			if ( ! isset( $value['css'] ) ) {
234
				$value['css'] = '';
235
			}
236
			if ( ! isset( $value['default'] ) ) {
237
				$value['default'] = '';
238
			}
239
			if ( ! isset( $value['desc'] ) ) {
240
				$value['desc'] = '';
241
			}
242
			if ( ! isset( $value['desc_tip'] ) ) {
243
				$value['desc_tip'] = false;
244
			}
245
			if ( ! isset( $value['placeholder'] ) ) {
246
				$value['placeholder'] = '';
247
			}
248
249
			// Custom attribute handling
250
			$custom_attributes = array();
251
252 View Code Duplication
			if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
253
				foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
254
					$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
255
				}
256
			}
257
258
			// Description handling
259
			$field_description = self::get_field_description( $value );
260
			extract( $field_description );
261
262
			// Switch based on type
263
			switch ( $value['type'] ) {
264
265
				// Section Titles
266
				case 'title':
267
					if ( ! empty( $value['title'] ) ) {
268
						echo '<h2>' . esc_html( $value['title'] ) . '</h2>';
269
					}
270
					if ( ! empty( $value['desc'] ) ) {
271
						echo wpautop( wptexturize( wp_kses_post( $value['desc'] ) ) );
272
					}
273
					echo '<table class="form-table">'. "\n\n";
274
					if ( ! empty( $value['id'] ) ) {
275
						do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) );
276
					}
277
					break;
278
279
				// Section Ends
280
				case 'sectionend':
281 View Code Duplication
					if ( ! empty( $value['id'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
282
						do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) . '_end' );
283
					}
284
					echo '</table>';
285 View Code Duplication
					if ( ! empty( $value['id'] ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
286
						do_action( 'woocommerce_settings_' . sanitize_title( $value['id'] ) . '_after' );
287
					}
288
					break;
289
290
				// Standard text inputs and subtypes like 'number'
291
				case 'text':
292
				case 'email':
293
				case 'number':
294
				case 'color' :
295
				case 'password' :
296
297
					$type         = $value['type'];
298
					$option_value = self::get_option( $value['id'], $value['default'] );
299
300
					if ( $value['type'] == 'color' ) {
301
						$type = 'text';
302
						$value['class'] .= 'colorpick';
303
						$description .= '<div id="colorPickerDiv_' . esc_attr( $value['id'] ) . '" class="colorpickdiv" style="z-index: 100;background:#eee;border:1px solid #ccc;position:absolute;display:none;"></div>';
304
					}
305
306
					?><tr valign="top">
307
						<th scope="row" class="titledesc">
308
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
309
							<?php echo $tooltip_html; ?>
310
						</th>
311
						<td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
312
							<?php
313
							if ( 'color' == $value['type'] ) {
314
								echo '<span class="colorpickpreview" style="background: ' . esc_attr( $option_value ) . ';"></span>';
315
							}
316
							?>
317
							<input
318
								name="<?php echo esc_attr( $value['id'] ); ?>"
319
								id="<?php echo esc_attr( $value['id'] ); ?>"
320
								type="<?php echo esc_attr( $type ); ?>"
321
								style="<?php echo esc_attr( $value['css'] ); ?>"
322
								value="<?php echo esc_attr( $option_value ); ?>"
323
								class="<?php echo esc_attr( $value['class'] ); ?>"
324
								placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
325
								<?php echo implode( ' ', $custom_attributes ); ?>
326
								/> <?php echo $description; ?>
327
						</td>
328
					</tr><?php
329
					break;
330
331
				// Textarea
332
				case 'textarea':
333
334
					$option_value = self::get_option( $value['id'], $value['default'] );
335
336
					?><tr valign="top">
337
						<th scope="row" class="titledesc">
338
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
339
							<?php echo $tooltip_html; ?>
340
						</th>
341
						<td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
342
							<?php echo $description; ?>
343
344
							<textarea
345
								name="<?php echo esc_attr( $value['id'] ); ?>"
346
								id="<?php echo esc_attr( $value['id'] ); ?>"
347
								style="<?php echo esc_attr( $value['css'] ); ?>"
348
								class="<?php echo esc_attr( $value['class'] ); ?>"
349
								placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
350
								<?php echo implode( ' ', $custom_attributes ); ?>
351
								><?php echo esc_textarea( $option_value );  ?></textarea>
352
						</td>
353
					</tr><?php
354
					break;
355
356
				// Select boxes
357
				case 'select' :
358
				case 'multiselect' :
359
360
					$option_value = self::get_option( $value['id'], $value['default'] );
361
362
					?><tr valign="top">
363
						<th scope="row" class="titledesc">
364
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
365
							<?php echo $tooltip_html; ?>
366
						</th>
367
						<td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
368
							<select
369
								name="<?php echo esc_attr( $value['id'] ); ?><?php if ( $value['type'] == 'multiselect' ) echo '[]'; ?>"
370
								id="<?php echo esc_attr( $value['id'] ); ?>"
371
								style="<?php echo esc_attr( $value['css'] ); ?>"
372
								class="<?php echo esc_attr( $value['class'] ); ?>"
373
								<?php echo implode( ' ', $custom_attributes ); ?>
374
								<?php echo ( 'multiselect' == $value['type'] ) ? 'multiple="multiple"' : ''; ?>
375
								>
376
								<?php
377
									foreach ( $value['options'] as $key => $val ) {
378
										?>
379
										<option value="<?php echo esc_attr( $key ); ?>" <?php
380
381
											if ( is_array( $option_value ) ) {
382
												selected( in_array( $key, $option_value ), true );
383
											} else {
384
												selected( $option_value, $key );
385
											}
386
387
										?>><?php echo $val ?></option>
388
										<?php
389
									}
390
								?>
391
							</select> <?php echo $description; ?>
392
						</td>
393
					</tr><?php
394
					break;
395
396
				// Radio inputs
397
				case 'radio' :
398
399
					$option_value = self::get_option( $value['id'], $value['default'] );
400
401
					?><tr valign="top">
402
						<th scope="row" class="titledesc">
403
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
404
							<?php echo $tooltip_html; ?>
405
						</th>
406
						<td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
407
							<fieldset>
408
								<?php echo $description; ?>
409
								<ul>
410
								<?php
411
									foreach ( $value['options'] as $key => $val ) {
412
										?>
413
										<li>
414
											<label><input
415
												name="<?php echo esc_attr( $value['id'] ); ?>"
416
												value="<?php echo $key; ?>"
417
												type="radio"
418
												style="<?php echo esc_attr( $value['css'] ); ?>"
419
												class="<?php echo esc_attr( $value['class'] ); ?>"
420
												<?php echo implode( ' ', $custom_attributes ); ?>
421
												<?php checked( $key, $option_value ); ?>
422
												/> <?php echo $val ?></label>
423
										</li>
424
										<?php
425
									}
426
								?>
427
								</ul>
428
							</fieldset>
429
						</td>
430
					</tr><?php
431
					break;
432
433
				// Checkbox input
434
				case 'checkbox' :
435
436
					$option_value    = self::get_option( $value['id'], $value['default'] );
437
					$visbility_class = array();
438
439
					if ( ! isset( $value['hide_if_checked'] ) ) {
440
						$value['hide_if_checked'] = false;
441
					}
442
					if ( ! isset( $value['show_if_checked'] ) ) {
443
						$value['show_if_checked'] = false;
444
					}
445
					if ( 'yes' == $value['hide_if_checked'] || 'yes' == $value['show_if_checked'] ) {
446
						$visbility_class[] = 'hidden_option';
447
					}
448
					if ( 'option' == $value['hide_if_checked'] ) {
449
						$visbility_class[] = 'hide_options_if_checked';
450
					}
451
					if ( 'option' == $value['show_if_checked'] ) {
452
						$visbility_class[] = 'show_options_if_checked';
453
					}
454
455
					if ( ! isset( $value['checkboxgroup'] ) || 'start' == $value['checkboxgroup'] ) {
456
						?>
457
							<tr valign="top" class="<?php echo esc_attr( implode( ' ', $visbility_class ) ); ?>">
458
								<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ) ?></th>
459
								<td class="forminp forminp-checkbox">
460
									<fieldset>
461
						<?php
462
					} else {
463
						?>
464
							<fieldset class="<?php echo esc_attr( implode( ' ', $visbility_class ) ); ?>">
465
						<?php
466
					}
467
468
					if ( ! empty( $value['title'] ) ) {
469
						?>
470
							<legend class="screen-reader-text"><span><?php echo esc_html( $value['title'] ) ?></span></legend>
471
						<?php
472
					}
473
474
					?>
475
						<label for="<?php echo $value['id'] ?>">
476
							<input
477
								name="<?php echo esc_attr( $value['id'] ); ?>"
478
								id="<?php echo esc_attr( $value['id'] ); ?>"
479
								type="checkbox"
480
								class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
481
								value="1"
482
								<?php checked( $option_value, 'yes'); ?>
483
								<?php echo implode( ' ', $custom_attributes ); ?>
484
							/> <?php echo $description ?>
485
						</label> <?php echo $tooltip_html; ?>
486
					<?php
487
488
					if ( ! isset( $value['checkboxgroup'] ) || 'end' == $value['checkboxgroup'] ) {
489
									?>
490
									</fieldset>
491
								</td>
492
							</tr>
493
						<?php
494
					} else {
495
						?>
496
							</fieldset>
497
						<?php
498
					}
499
					break;
500
501
				// Image width settings
502
				case 'image_width' :
503
504
					$image_size       = str_replace( '_image_size', '', $value[ 'id' ] );
505
					$size             = wc_get_image_size( $image_size );
506
					$width            = isset( $size[ 'width' ] ) ? $size[ 'width' ] : $value[ 'default' ][ 'width' ];
507
					$height           = isset( $size[ 'height' ] ) ? $size[ 'height' ] : $value[ 'default' ][ 'height' ];
508
					$crop             = isset( $size[ 'crop' ] ) ? $size[ 'crop' ] : $value[ 'default' ][ 'crop' ];
509
					$disabled_attr    = '';
510
					$disabled_message = '';
511
512
					if ( has_filter( 'woocommerce_get_image_size_' . $image_size ) ) {
513
						$disabled_attr = 'disabled="disabled"';
514
						$disabled_message = "<p><small>" . __( 'The settings of this image size have been disabled because its values are being overwritten by a filter.', 'woocommerce' ) . "</small></p>";
515
					}
516
517
					?><tr valign="top">
518
						<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ) ?> <?php echo $tooltip_html; echo $disabled_message; ?></th>
519
						<td class="forminp image_width_settings">
520
521
							<input name="<?php echo esc_attr( $value['id'] ); ?>[width]" <?php echo $disabled_attr; ?> id="<?php echo esc_attr( $value['id'] ); ?>-width" type="text" size="3" value="<?php echo $width; ?>" /> &times; <input name="<?php echo esc_attr( $value['id'] ); ?>[height]" <?php echo $disabled_attr; ?> id="<?php echo esc_attr( $value['id'] ); ?>-height" type="text" size="3" value="<?php echo $height; ?>" />px
522
523
							<label><input name="<?php echo esc_attr( $value['id'] ); ?>[crop]" <?php echo $disabled_attr; ?> id="<?php echo esc_attr( $value['id'] ); ?>-crop" type="checkbox" value="1" <?php checked( 1, $crop ); ?> /> <?php _e( 'Hard Crop?', 'woocommerce' ); ?></label>
524
525
							</td>
526
					</tr><?php
527
					break;
528
529
				// Single page selects
530
				case 'single_select_page' :
531
532
					$args = array(
533
						'name'             => $value['id'],
534
						'id'               => $value['id'],
535
						'sort_column'      => 'menu_order',
536
						'sort_order'       => 'ASC',
537
						'show_option_none' => ' ',
538
						'class'            => $value['class'],
539
						'echo'             => false,
540
						'selected'         => absint( self::get_option( $value['id'] ) )
541
					);
542
543
					if ( isset( $value['args'] ) ) {
544
						$args = wp_parse_args( $value['args'], $args );
545
					}
546
547
					?><tr valign="top" class="single_select_page">
548
						<th scope="row" class="titledesc"><?php echo esc_html( $value['title'] ) ?> <?php echo $tooltip_html; ?></th>
549
						<td class="forminp">
550
							<?php echo str_replace(' id=', " data-placeholder='" . esc_attr__( 'Select a page&hellip;', 'woocommerce' ) .  "' style='" . $value['css'] . "' class='" . $value['class'] . "' id=", wp_dropdown_pages( $args ) ); ?> <?php echo $description; ?>
551
						</td>
552
					</tr><?php
553
					break;
554
555
				// Single country selects
556
				case 'single_select_country' :
557
					$country_setting = (string) self::get_option( $value['id'] );
558
559
					if ( strstr( $country_setting, ':' ) ) {
560
						$country_setting = explode( ':', $country_setting );
561
						$country         = current( $country_setting );
562
						$state           = end( $country_setting );
563
					} else {
564
						$country = $country_setting;
565
						$state   = '*';
566
					}
567
					?><tr valign="top">
568
						<th scope="row" class="titledesc">
569
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
570
							<?php echo $tooltip_html; ?>
571
						</th>
572
						<td class="forminp"><select name="<?php echo esc_attr( $value['id'] ); ?>" style="<?php echo esc_attr( $value['css'] ); ?>" data-placeholder="<?php esc_attr_e( 'Choose a country&hellip;', 'woocommerce' ); ?>" title="<?php esc_attr_e( 'Country', 'woocommerce' ) ?>" class="wc-enhanced-select">
573
							<?php WC()->countries->country_dropdown_options( $country, $state ); ?>
574
						</select> <?php echo $description; ?>
575
						</td>
576
					</tr><?php
577
					break;
578
579
				// Country multiselects
580
				case 'multi_select_countries' :
581
582
					$selections = (array) self::get_option( $value['id'] );
583
584
					if ( ! empty( $value['options'] ) ) {
585
						$countries = $value['options'];
586
					} else {
587
						$countries = WC()->countries->countries;
588
					}
589
590
					asort( $countries );
591
					?><tr valign="top">
592
						<th scope="row" class="titledesc">
593
							<label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
594
							<?php echo $tooltip_html; ?>
595
						</th>
596
						<td class="forminp">
597
							<select multiple="multiple" name="<?php echo esc_attr( $value['id'] ); ?>[]" style="width:350px" data-placeholder="<?php esc_attr_e( 'Choose countries&hellip;', 'woocommerce' ); ?>" title="<?php esc_attr_e( 'Country', 'woocommerce' ) ?>" class="wc-enhanced-select">
598
								<?php
599
									if ( ! empty( $countries ) ) {
600
										foreach ( $countries as $key => $val ) {
601
											echo '<option value="' . esc_attr( $key ) . '" ' . selected( in_array( $key, $selections ), true, false ).'>' . $val . '</option>';
602
										}
603
									}
604
								?>
605
							</select> <?php echo ( $description ) ? $description : ''; ?> <br /><a class="select_all button" href="#"><?php _e( 'Select all', 'woocommerce' ); ?></a> <a class="select_none button" href="#"><?php _e( 'Select none', 'woocommerce' ); ?></a>
606
						</td>
607
					</tr><?php
608
					break;
609
610
				// Default: run an action
611
				default:
612
					do_action( 'woocommerce_admin_field_' . $value['type'], $value );
613
					break;
614
			}
615
		}
616
	}
617
618
	/**
619
	 * Helper function to get the formated description and tip HTML for a
620
	 * given form field. Plugins can call this when implementing their own custom
621
	 * settings types.
622
	 *
623
	 * @param  array $value The form field value array
624
	 * @return array The description and tip as a 2 element array
625
	 */
626
	public static function get_field_description( $value ) {
627
		$description  = '';
628
		$tooltip_html = '';
629
630 View Code Duplication
		if ( true === $value['desc_tip'] ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
			$tooltip_html = $value['desc'];
632
		} elseif ( ! empty( $value['desc_tip'] ) ) {
633
			$description  = $value['desc'];
634
			$tooltip_html = $value['desc_tip'];
635
		} elseif ( ! empty( $value['desc'] ) ) {
636
			$description  = $value['desc'];
637
		}
638
639
		if ( $description && in_array( $value['type'], array( 'textarea', 'radio' ) ) ) {
640
			$description = '<p style="margin-top:0">' . wp_kses_post( $description ) . '</p>';
641
		} elseif ( $description && in_array( $value['type'], array( 'checkbox' ) ) ) {
642
			$description = wp_kses_post( $description );
643
		} elseif ( $description ) {
644
			$description = '<span class="description">' . wp_kses_post( $description ) . '</span>';
645
		}
646
647
		if ( $tooltip_html && in_array( $value['type'], array( 'checkbox' ) ) ) {
648
			$tooltip_html = '<p class="description">' . $tooltip_html . '</p>';
649
		} elseif ( $tooltip_html ) {
650
			$tooltip_html = wc_help_tip( $tooltip_html );
651
		}
652
653
		return array(
654
			'description'  => $description,
655
			'tooltip_html' => $tooltip_html
656
		);
657
	}
658
659
	/**
660
	 * Save admin fields.
661
	 *
662
	 * Loops though the woocommerce options array and outputs each field.
663
	 *
664
	 * @param array $options Options array to output
665
	 * @return bool
666
	 */
667
	public static function save_fields( $options ) {
668
		if ( empty( $_POST ) ) {
669
			return false;
670
		}
671
672
		// Options to update will be stored here and saved later.
673
		$update_options = array();
674
675
		// Loop options and get values to save.
676
		foreach ( $options as $option ) {
677
			if ( ! isset( $option['id'] ) || ! isset( $option['type'] ) ) {
678
				continue;
679
			}
680
681
			// Get posted value.
682
			if ( strstr( $option['id'], '[' ) ) {
683
				parse_str( $option['id'], $option_name_array );
684
				$option_name  = current( array_keys( $option_name_array ) );
685
				$setting_name = key( $option_name_array[ $option_name ] );
686
				$raw_value    = isset( $_POST[ $option_name ][ $setting_name ] ) ? wp_unslash( $_POST[ $option_name ][ $setting_name ] ) : null;
687
			} else {
688
				$option_name  = $option['id'];
689
				$setting_name = '';
690
				$raw_value    = isset( $_POST[ $option['id'] ] ) ? wp_unslash( $_POST[ $option['id'] ] ) : null;
691
			}
692
693
			// Format the value based on option type.
694
			switch ( $option['type'] ) {
695
				case 'checkbox' :
696
					$value = is_null( $raw_value ) ? 'no' : 'yes';
697
					break;
698
				case 'textarea' :
699
					$value = wp_kses_post( trim( $raw_value ) );
700
					break;
701
				case 'multiselect' :
702
				case 'multi_select_countries' :
703
					$value = array_filter( array_map( 'wc_clean', (array) $raw_value ) );
704
					break;
705
				case 'image_width' :
706
					$value = array();
707
					if ( isset( $raw_value['width'] ) ) {
708
						$value['width']  = wc_clean( $raw_value['width'] );
709
						$value['height'] = wc_clean( $raw_value['height'] );
710
						$value['crop']   = isset( $raw_value['crop'] ) ? 1 : 0;
711
					} else {
712
						$value['width']  = $option['default']['width'];
713
						$value['height'] = $option['default']['height'];
714
						$value['crop']   = $option['default']['crop'];
715
					}
716
					break;
717
				default :
718
					$value = wc_clean( $raw_value );
719
					break;
720
			}
721
722
			/**
723
			 * Fire an action when a certain 'type' of field is being saved.
724
			 * @deprecated 2.4.0 - doesn't allow manipulation of values!
725
			 */
726
			if ( has_action( 'woocommerce_update_option_' . sanitize_title( $option['type'] ) ) ) {
727
				_deprecated_function( 'The woocommerce_update_option_X action', '2.4.0', 'woocommerce_admin_settings_sanitize_option filter' );
728
				do_action( 'woocommerce_update_option_' . sanitize_title( $option['type'] ), $option );
729
				continue;
730
			}
731
732
			/**
733
			 * Sanitize the value of an option.
734
			 * @since 2.4.0
735
			 */
736
			$value = apply_filters( 'woocommerce_admin_settings_sanitize_option', $value, $option, $raw_value );
737
738
			/**
739
			 * Sanitize the value of an option by option name.
740
			 * @since 2.4.0
741
			 */
742
			$value = apply_filters( "woocommerce_admin_settings_sanitize_option_$option_name", $value, $option, $raw_value );
743
744
			if ( is_null( $value ) ) {
745
				continue;
746
			}
747
748
			// Check if option is an array and handle that differently to single values.
749
			if ( $option_name && $setting_name ) {
750
				if ( ! isset( $update_options[ $option_name ] ) ) {
751
					$update_options[ $option_name ] = get_option( $option_name, array() );
752
				}
753
				if ( ! is_array( $update_options[ $option_name ] ) ) {
754
					$update_options[ $option_name ] = array();
755
				}
756
				$update_options[ $option_name ][ $setting_name ] = $value;
757
			} else {
758
				$update_options[ $option_name ] = $value;
759
			}
760
761
			/**
762
			 * Fire an action before saved.
763
			 * @deprecated 2.4.0 - doesn't allow manipulation of values!
764
			 */
765
			do_action( 'woocommerce_update_option', $option );
766
		}
767
768
		// Save all options in our array.
769
		foreach ( $update_options as $name => $value ) {
770
			update_option( $name, $value );
771
		}
772
773
		return true;
774
	}
775
776
	/**
777
	 * Checks which method we're using to serve downloads.
778
	 *
779
	 * If using force or x-sendfile, this ensures the .htaccess is in place.
780
	 */
781
	public static function check_download_folder_protection() {
782
		$upload_dir      = wp_upload_dir();
783
		$downloads_url   = $upload_dir['basedir'] . '/woocommerce_uploads';
784
		$download_method = get_option( 'woocommerce_file_download_method' );
785
786
		if ( 'redirect' == $download_method ) {
787
788
			// Redirect method - don't protect
789
			if ( file_exists( $downloads_url . '/.htaccess' ) ) {
790
				unlink( $downloads_url . '/.htaccess' );
791
			}
792
793
		} else {
794
795
			// Force method - protect, add rules to the htaccess file
796
			if ( ! file_exists( $downloads_url . '/.htaccess' ) ) {
797
				if ( $file_handle = @fopen( $downloads_url . '/.htaccess', 'w' ) ) {
798
					fwrite( $file_handle, 'deny from all' );
799
					fclose( $file_handle );
800
				}
801
			}
802
		}
803
	}
804
}
805
806
endif;
807