Completed
Push — master ( 15aa29...17da96 )
by Claudio
18:39 queued 11s
created

includes/abstracts/abstract-wc-settings-api.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Abstract Settings API Class
4
 *
5
 * Admin Settings API used by Integrations, Shipping Methods, and Payment Gateways.
6
 *
7
 * @package  WooCommerce/Abstracts
8
 */
9
10
defined( 'ABSPATH' ) || exit;
11
12
/**
13
 * WC_Settings_API class.
14
 */
15
abstract class WC_Settings_API {
16
17
	/**
18
	 * The plugin ID. Used for option names.
19
	 *
20
	 * @var string
21
	 */
22
	public $plugin_id = 'woocommerce_';
23
24
	/**
25
	 * ID of the class extending the settings API. Used in option names.
26
	 *
27
	 * @var string
28
	 */
29
	public $id = '';
30
31
	/**
32
	 * Validation errors.
33
	 *
34
	 * @var array of strings
35
	 */
36
	public $errors = array();
37
38
	/**
39
	 * Setting values.
40
	 *
41
	 * @var array
42
	 */
43
	public $settings = array();
44
45
	/**
46
	 * Form option fields.
47
	 *
48
	 * @var array
49
	 */
50
	public $form_fields = array();
51
52
	/**
53
	 * The posted settings data. When empty, $_POST data will be used.
54
	 *
55
	 * @var array
56
	 */
57
	protected $data = array();
58
59
	/**
60
	 * Get the form fields after they are initialized.
61
	 *
62
	 * @return array of options
63
	 */
64 506
	public function get_form_fields() {
65 506
		return apply_filters( 'woocommerce_settings_api_form_fields_' . $this->id, array_map( array( $this, 'set_defaults' ), $this->form_fields ) );
66
	}
67
68
	/**
69
	 * Set default required properties for each field.
70
	 *
71
	 * @param array $field Setting field array.
72
	 * @return array
73
	 */
74 498
	protected function set_defaults( $field ) {
75 498
		if ( ! isset( $field['default'] ) ) {
76 428
			$field['default'] = '';
77
		}
78 498
		return $field;
79
	}
80
81
	/**
82
	 * Output the admin options table.
83
	 */
84
	public function admin_options() {
85
		echo '<table class="form-table">' . $this->generate_settings_html( $this->get_form_fields(), false ) . '</table>'; // WPCS: XSS ok.
86
	}
87
88
	/**
89
	 * Initialise settings form fields.
90
	 *
91
	 * Add an array of fields to be displayed on the gateway's settings screen.
92
	 *
93
	 * @since  1.0.0
94
	 */
95
	public function init_form_fields() {}
96
97
	/**
98
	 * Return the name of the option in the WP DB.
99
	 *
100
	 * @since 2.6.0
101
	 * @return string
102
	 */
103 506
	public function get_option_key() {
104 506
		return $this->plugin_id . $this->id . '_settings';
105
	}
106
107
	/**
108
	 * Get a fields type. Defaults to "text" if not set.
109
	 *
110
	 * @param  array $field Field key.
111
	 * @return string
112
	 */
113 10
	public function get_field_type( $field ) {
114 10
		return empty( $field['type'] ) ? 'text' : $field['type'];
115
	}
116
117
	/**
118
	 * Get a fields default value. Defaults to "" if not set.
119
	 *
120
	 * @param  array $field Field key.
121
	 * @return string
122
	 */
123 1
	public function get_field_default( $field ) {
124 1
		return empty( $field['default'] ) ? '' : $field['default'];
125
	}
126
127
	/**
128
	 * Get a field's posted and validated value.
129
	 *
130
	 * @param string $key Field key.
131
	 * @param array  $field Field array.
132
	 * @param array  $post_data Posted data.
133
	 * @return string
134
	 */
135
	public function get_field_value( $key, $field, $post_data = array() ) {
136
		$type      = $this->get_field_type( $field );
137
		$field_key = $this->get_field_key( $key );
138
		$post_data = empty( $post_data ) ? $_POST : $post_data; // WPCS: CSRF ok, input var ok.
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_POST
Loading history...
139
		$value     = isset( $post_data[ $field_key ] ) ? $post_data[ $field_key ] : null;
140
141
		if ( isset( $field['sanitize_callback'] ) && is_callable( $field['sanitize_callback'] ) ) {
142
			return call_user_func( $field['sanitize_callback'], $value );
143
		}
144
145
		// Look for a validate_FIELDID_field method for special handling.
146 View Code Duplication
		if ( is_callable( array( $this, 'validate_' . $key . '_field' ) ) ) {
147
			return $this->{'validate_' . $key . '_field'}( $key, $value );
148
		}
149
150
		// Look for a validate_FIELDTYPE_field method.
151 View Code Duplication
		if ( is_callable( array( $this, 'validate_' . $type . '_field' ) ) ) {
152
			return $this->{'validate_' . $type . '_field'}( $key, $value );
153
		}
154
155
		// Fallback to text.
156
		return $this->validate_text_field( $key, $value );
157
	}
158
159
	/**
160
	 * Sets the POSTed data. This method can be used to set specific data, instead of taking it from the $_POST array.
161
	 *
162
	 * @param array $data Posted data.
163
	 */
164
	public function set_post_data( $data = array() ) {
165
		$this->data = $data;
166
	}
167
168
	/**
169
	 * Returns the POSTed data, to be used to save the settings.
170
	 *
171
	 * @return array
172
	 */
173
	public function get_post_data() {
174
		if ( ! empty( $this->data ) && is_array( $this->data ) ) {
175
			return $this->data;
176
		}
177
		return $_POST; // WPCS: CSRF ok, input var ok.
0 ignored issues
show
Detected usage of a non-sanitized input variable: $_POST
Loading history...
178
	}
179
180
	/**
181
	 * Update a single option.
182
	 *
183
	 * @since 3.4.0
184
	 * @param string $key Option key.
185
	 * @param mixed  $value Value to set.
186
	 * @return bool was anything saved?
187
	 */
188
	public function update_option( $key, $value = '' ) {
189
		if ( empty( $this->settings ) ) {
190
			$this->init_settings();
191
		}
192
193
		$this->settings[ $key ] = $value;
194
195
		return update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ), 'yes' );
196
	}
197
198
	/**
199
	 * Processes and saves options.
200
	 * If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
201
	 *
202
	 * @return bool was anything saved?
203
	 */
204
	public function process_admin_options() {
205
		$this->init_settings();
206
207
		$post_data = $this->get_post_data();
208
209 View Code Duplication
		foreach ( $this->get_form_fields() as $key => $field ) {
210
			if ( 'title' !== $this->get_field_type( $field ) ) {
211
				try {
212
					$this->settings[ $key ] = $this->get_field_value( $key, $field, $post_data );
213
				} catch ( Exception $e ) {
214
					$this->add_error( $e->getMessage() );
215
				}
216
			}
217
		}
218
219
		return update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ), 'yes' );
220
	}
221
222
	/**
223
	 * Add an error message for display in admin on save.
224
	 *
225
	 * @param string $error Error message.
226
	 */
227
	public function add_error( $error ) {
228
		$this->errors[] = $error;
229
	}
230
231
	/**
232
	 * Get admin error messages.
233
	 */
234
	public function get_errors() {
235
		return $this->errors;
236
	}
237
238
	/**
239
	 * Display admin error messages.
240
	 */
241
	public function display_errors() {
242
		if ( $this->get_errors() ) {
243
			echo '<div id="woocommerce_errors" class="error notice is-dismissible">';
244
			foreach ( $this->get_errors() as $error ) {
245
				echo '<p>' . wp_kses_post( $error ) . '</p>';
246
			}
247
			echo '</div>';
248
		}
249
	}
250
251
	/**
252
	 * Initialise Settings.
253
	 *
254
	 * Store all settings in a single database entry
255
	 * and make sure the $settings array is either the default
256
	 * or the settings stored in the database.
257
	 *
258
	 * @since 1.0.0
259
	 * @uses get_option(), add_option()
260
	 */
261 506 View Code Duplication
	public function init_settings() {
262 506
		$this->settings = get_option( $this->get_option_key(), null );
263
264
		// If there are no settings defined, use defaults.
265 506
		if ( ! is_array( $this->settings ) ) {
266 506
			$form_fields    = $this->get_form_fields();
267 506
			$this->settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) );
268
		}
269
	}
270
271
	/**
272
	 * Get option from DB.
273
	 *
274
	 * Gets an option from the settings API, using defaults if necessary to prevent undefined notices.
275
	 *
276
	 * @param  string $key Option key.
277
	 * @param  mixed  $empty_value Value when empty.
278
	 * @return string The value specified for the option or a default value for the option.
279
	 */
280 505
	public function get_option( $key, $empty_value = null ) {
281 505
		if ( empty( $this->settings ) ) {
282 504
			$this->init_settings();
283
		}
284
285
		// Get option default if unset.
286 505
		if ( ! isset( $this->settings[ $key ] ) ) {
287 505
			$form_fields            = $this->get_form_fields();
288 505
			$this->settings[ $key ] = isset( $form_fields[ $key ] ) ? $this->get_field_default( $form_fields[ $key ] ) : '';
289
		}
290
291 505
		if ( ! is_null( $empty_value ) && '' === $this->settings[ $key ] ) {
292 505
			$this->settings[ $key ] = $empty_value;
293
		}
294
295 505
		return $this->settings[ $key ];
296
	}
297
298
	/**
299
	 * Prefix key for settings.
300
	 *
301
	 * @param  string $key Field key.
302
	 * @return string
303
	 */
304 10
	public function get_field_key( $key ) {
305 10
		return $this->plugin_id . $this->id . '_' . $key;
306
	}
307
308
	/**
309
	 * Generate Settings HTML.
310
	 *
311
	 * Generate the HTML for the fields on the "settings" screen.
312
	 *
313
	 * @param array $form_fields (default: array()) Array of form fields.
314
	 * @param bool  $echo Echo or return.
315
	 * @return string the html for the settings
316
	 * @since  1.0.0
317
	 * @uses   method_exists()
318
	 */
319 10
	public function generate_settings_html( $form_fields = array(), $echo = true ) {
320 10
		if ( empty( $form_fields ) ) {
321
			$form_fields = $this->get_form_fields();
322
		}
323
324 10
		$html = '';
325 10
		foreach ( $form_fields as $k => $v ) {
326 10
			$type = $this->get_field_type( $v );
327
328 10
			if ( method_exists( $this, 'generate_' . $type . '_html' ) ) {
329 10
				$html .= $this->{'generate_' . $type . '_html'}( $k, $v );
330
			} else {
331
				$html .= $this->generate_text_html( $k, $v );
332
			}
333
		}
334
335 10
		if ( $echo ) {
336
			echo $html; // WPCS: XSS ok.
337
		} else {
338 10
			return $html;
339
		}
340
	}
341
342
	/**
343
	 * Get HTML for tooltips.
344
	 *
345
	 * @param  array $data Data for the tooltip.
346
	 * @return string
347
	 */
348 10
	public function get_tooltip_html( $data ) {
349 10
		if ( true === $data['desc_tip'] ) {
350 10
			$tip = $data['description'];
351 10
		} elseif ( ! empty( $data['desc_tip'] ) ) {
352
			$tip = $data['desc_tip'];
353
		} else {
354 10
			$tip = '';
355
		}
356
357 10
		return $tip ? wc_help_tip( $tip, true ) : '';
358
	}
359
360
	/**
361
	 * Get HTML for descriptions.
362
	 *
363
	 * @param  array $data Data for the description.
364
	 * @return string
365
	 */
366 10
	public function get_description_html( $data ) {
367 10 View Code Duplication
		if ( true === $data['desc_tip'] ) {
368 10
			$description = '';
369 10
		} elseif ( ! empty( $data['desc_tip'] ) ) {
370
			$description = $data['description'];
371 10
		} elseif ( ! empty( $data['description'] ) ) {
372
			$description = $data['description'];
373
		} else {
374 10
			$description = '';
375
		}
376
377 10
		return $description ? '<p class="description">' . wp_kses_post( $description ) . '</p>' . "\n" : '';
378
	}
379
380
	/**
381
	 * Get custom attributes.
382
	 *
383
	 * @param  array $data Field data.
384
	 * @return string
385
	 */
386 10
	public function get_custom_attribute_html( $data ) {
387 10
		$custom_attributes = array();
388
389 10 View Code Duplication
		if ( ! empty( $data['custom_attributes'] ) && is_array( $data['custom_attributes'] ) ) {
390
			foreach ( $data['custom_attributes'] as $attribute => $attribute_value ) {
391
				$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
392
			}
393
		}
394
395 10
		return implode( ' ', $custom_attributes );
396
	}
397
398
	/**
399
	 * Generate Text Input HTML.
400
	 *
401
	 * @param string $key Field key.
402
	 * @param array  $data Field data.
403
	 * @since  1.0.0
404
	 * @return string
405
	 */
406 10 View Code Duplication
	public function generate_text_html( $key, $data ) {
407 10
		$field_key = $this->get_field_key( $key );
408
		$defaults  = array(
409 10
			'title'             => '',
410
			'disabled'          => false,
411
			'class'             => '',
412
			'css'               => '',
413
			'placeholder'       => '',
414
			'type'              => 'text',
415
			'desc_tip'          => false,
416
			'description'       => '',
417
			'custom_attributes' => array(),
418
		);
419
420 10
		$data = wp_parse_args( $data, $defaults );
421
422 10
		ob_start();
423
		?>
424 10
		<tr valign="top">
425
			<th scope="row" class="titledesc">
426
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
427
			</th>
428
			<td class="forminp">
429
				<fieldset>
430
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
431
					<input class="input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> />
432
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
433 10
				</fieldset>
434
			</td>
435
		</tr>
436
		<?php
437
438 10
		return ob_get_clean();
439
	}
440
441
	/**
442
	 * Generate Price Input HTML.
443
	 *
444
	 * @param string $key Field key.
445
	 * @param array  $data Field data.
446
	 * @since  1.0.0
447
	 * @return string
448
	 */
449 1 View Code Duplication
	public function generate_price_html( $key, $data ) {
450 1
		$field_key = $this->get_field_key( $key );
451
		$defaults  = array(
452 1
			'title'             => '',
453
			'disabled'          => false,
454
			'class'             => '',
455
			'css'               => '',
456
			'placeholder'       => '',
457
			'type'              => 'text',
458
			'desc_tip'          => false,
459
			'description'       => '',
460
			'custom_attributes' => array(),
461
		);
462
463 1
		$data = wp_parse_args( $data, $defaults );
464
465 1
		ob_start();
466
		?>
467 1
		<tr valign="top">
468
			<th scope="row" class="titledesc">
469
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
470
			</th>
471
			<td class="forminp">
472
				<fieldset>
473
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
474
					<input class="wc_input_price input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> />
475
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
476 1
				</fieldset>
477
			</td>
478
		</tr>
479
		<?php
480
481 1
		return ob_get_clean();
482
	}
483
484
	/**
485
	 * Generate Decimal Input HTML.
486
	 *
487
	 * @param string $key Field key.
488
	 * @param array  $data Field data.
489
	 * @since  1.0.0
490
	 * @return string
491
	 */
492 View Code Duplication
	public function generate_decimal_html( $key, $data ) {
493
		$field_key = $this->get_field_key( $key );
494
		$defaults  = array(
495
			'title'             => '',
496
			'disabled'          => false,
497
			'class'             => '',
498
			'css'               => '',
499
			'placeholder'       => '',
500
			'type'              => 'text',
501
			'desc_tip'          => false,
502
			'description'       => '',
503
			'custom_attributes' => array(),
504
		);
505
506
		$data = wp_parse_args( $data, $defaults );
507
508
		ob_start();
509
		?>
510
		<tr valign="top">
511
			<th scope="row" class="titledesc">
512
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
513
			</th>
514
			<td class="forminp">
515
				<fieldset>
516
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
517
					<input class="wc_input_decimal input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_decimal( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> />
518
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
519
				</fieldset>
520
			</td>
521
		</tr>
522
		<?php
523
524
		return ob_get_clean();
525
	}
526
527
	/**
528
	 * Generate Password Input HTML.
529
	 *
530
	 * @param string $key Field key.
531
	 * @param array  $data Field data.
532
	 * @since  1.0.0
533
	 * @return string
534
	 */
535
	public function generate_password_html( $key, $data ) {
536
		$data['type'] = 'password';
537
		return $this->generate_text_html( $key, $data );
538
	}
539
540
	/**
541
	 * Generate Color Picker Input HTML.
542
	 *
543
	 * @param string $key Field key.
544
	 * @param array  $data Field data.
545
	 * @since  1.0.0
546
	 * @return string
547
	 */
548
	public function generate_color_html( $key, $data ) {
549
		$field_key = $this->get_field_key( $key );
550
		$defaults  = array(
551
			'title'             => '',
552
			'disabled'          => false,
553
			'class'             => '',
554
			'css'               => '',
555
			'placeholder'       => '',
556
			'desc_tip'          => false,
557
			'description'       => '',
558
			'custom_attributes' => array(),
559
		);
560
561
		$data = wp_parse_args( $data, $defaults );
562
563
		ob_start();
564
		?>
565
		<tr valign="top">
566
			<th scope="row" class="titledesc">
567
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
568
			</th>
569
			<td class="forminp">
570
				<fieldset>
571
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
572
					<span class="colorpickpreview" style="background:<?php echo esc_attr( $this->get_option( $key ) ); ?>;">&nbsp;</span>
573
					<input class="colorpick <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> />
574
					<div id="colorPickerDiv_<?php echo esc_attr( $field_key ); ?>" class="colorpickdiv" style="z-index: 100; background: #eee; border: 1px solid #ccc; position: absolute; display: none;"></div>
575
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
576
				</fieldset>
577
			</td>
578
		</tr>
579
		<?php
580
581
		return ob_get_clean();
582
	}
583
584
	/**
585
	 * Generate Textarea HTML.
586
	 *
587
	 * @param string $key Field key.
588
	 * @param array  $data Field data.
589
	 * @since  1.0.0
590
	 * @return string
591
	 */
592 View Code Duplication
	public function generate_textarea_html( $key, $data ) {
593
		$field_key = $this->get_field_key( $key );
594
		$defaults  = array(
595
			'title'             => '',
596
			'disabled'          => false,
597
			'class'             => '',
598
			'css'               => '',
599
			'placeholder'       => '',
600
			'type'              => 'text',
601
			'desc_tip'          => false,
602
			'description'       => '',
603
			'custom_attributes' => array(),
604
		);
605
606
		$data = wp_parse_args( $data, $defaults );
607
608
		ob_start();
609
		?>
610
		<tr valign="top">
611
			<th scope="row" class="titledesc">
612
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
613
			</th>
614
			<td class="forminp">
615
				<fieldset>
616
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
617
					<textarea rows="3" cols="20" class="input-text wide-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?>><?php echo esc_textarea( $this->get_option( $key ) ); ?></textarea>
618
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
619
				</fieldset>
620
			</td>
621
		</tr>
622
		<?php
623
624
		return ob_get_clean();
625
	}
626
627
	/**
628
	 * Generate Checkbox HTML.
629
	 *
630
	 * @param string $key Field key.
631
	 * @param array  $data Field data.
632
	 * @since  1.0.0
633
	 * @return string
634
	 */
635
	public function generate_checkbox_html( $key, $data ) {
636
		$field_key = $this->get_field_key( $key );
637
		$defaults  = array(
638
			'title'             => '',
639
			'label'             => '',
640
			'disabled'          => false,
641
			'class'             => '',
642
			'css'               => '',
643
			'type'              => 'text',
644
			'desc_tip'          => false,
645
			'description'       => '',
646
			'custom_attributes' => array(),
647
		);
648
649
		$data = wp_parse_args( $data, $defaults );
650
651
		if ( ! $data['label'] ) {
652
			$data['label'] = $data['title'];
653
		}
654
655
		ob_start();
656
		?>
657
		<tr valign="top">
658
			<th scope="row" class="titledesc">
659
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
660
			</th>
661
			<td class="forminp">
662
				<fieldset>
663
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
664
					<label for="<?php echo esc_attr( $field_key ); ?>">
665
					<input <?php disabled( $data['disabled'], true ); ?> class="<?php echo esc_attr( $data['class'] ); ?>" type="checkbox" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="1" <?php checked( $this->get_option( $key ), 'yes' ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> /> <?php echo wp_kses_post( $data['label'] ); ?></label><br/>
666
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
667
				</fieldset>
668
			</td>
669
		</tr>
670
		<?php
671
672
		return ob_get_clean();
673
	}
674
675
	/**
676
	 * Generate Select HTML.
677
	 *
678
	 * @param string $key Field key.
679
	 * @param array  $data Field data.
680
	 * @since  1.0.0
681
	 * @return string
682
	 */
683 10
	public function generate_select_html( $key, $data ) {
684 10
		$field_key = $this->get_field_key( $key );
685
		$defaults  = array(
686 10
			'title'             => '',
687
			'disabled'          => false,
688
			'class'             => '',
689
			'css'               => '',
690
			'placeholder'       => '',
691
			'type'              => 'text',
692
			'desc_tip'          => false,
693
			'description'       => '',
694
			'custom_attributes' => array(),
695
			'options'           => array(),
696
		);
697
698 10
		$data = wp_parse_args( $data, $defaults );
699
700 10
		ob_start();
701
		?>
702 10
		<tr valign="top">
703
			<th scope="row" class="titledesc">
704
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
705
			</th>
706
			<td class="forminp">
707
				<fieldset>
708
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
709
					<select class="select <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?>>
710
						<?php foreach ( (array) $data['options'] as $option_key => $option_value ) : ?>
711
							<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( (string) $option_key, esc_attr( $this->get_option( $key ) ) ); ?>><?php echo esc_attr( $option_value ); ?></option>
712
						<?php endforeach; ?>
713 10
					</select>
714
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
715 10
				</fieldset>
716
			</td>
717
		</tr>
718
		<?php
719
720 10
		return ob_get_clean();
721
	}
722
723
	/**
724
	 * Generate Multiselect HTML.
725
	 *
726
	 * @param string $key Field key.
727
	 * @param array  $data Field data.
728
	 * @since  1.0.0
729
	 * @return string
730
	 */
731
	public function generate_multiselect_html( $key, $data ) {
732
		$field_key = $this->get_field_key( $key );
733
		$defaults  = array(
734
			'title'             => '',
735
			'disabled'          => false,
736
			'class'             => '',
737
			'css'               => '',
738
			'placeholder'       => '',
739
			'type'              => 'text',
740
			'desc_tip'          => false,
741
			'description'       => '',
742
			'custom_attributes' => array(),
743
			'select_buttons'    => false,
744
			'options'           => array(),
745
		);
746
747
		$data  = wp_parse_args( $data, $defaults );
748
		$value = (array) $this->get_option( $key, array() );
749
750
		ob_start();
751
		?>
752
		<tr valign="top">
753
			<th scope="row" class="titledesc">
754
				<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?> <?php echo $this->get_tooltip_html( $data ); // WPCS: XSS ok. ?></label>
755
			</th>
756
			<td class="forminp">
757
				<fieldset>
758
					<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
759
					<select multiple="multiple" class="multiselect <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>[]" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); // WPCS: XSS ok. ?>>
760
						<?php foreach ( (array) $data['options'] as $option_key => $option_value ) : ?>
761
							<?php if ( is_array( $option_value ) ) : ?>
762
								<optgroup label="<?php echo esc_attr( $option_key ); ?>">
763
									<?php foreach ( $option_value as $option_key_inner => $option_value_inner ) : ?>
764
										<option value="<?php echo esc_attr( $option_key_inner ); ?>" <?php selected( in_array( (string) $option_key_inner, $value, true ), true ); ?>><?php echo esc_attr( $option_value_inner ); ?></option>
765
									<?php endforeach; ?>
766
								</optgroup>
767
							<?php else : ?>
768
								<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( in_array( (string) $option_key, $value, true ), true ); ?>><?php echo esc_attr( $option_value ); ?></option>
769
							<?php endif; ?>
770
						<?php endforeach; ?>
771
					</select>
772
					<?php echo $this->get_description_html( $data ); // WPCS: XSS ok. ?>
773
					<?php if ( $data['select_buttons'] ) : ?>
774
						<br/><a class="select_all button" href="#"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></a> <a class="select_none button" href="#"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></a>
775
					<?php endif; ?>
776
				</fieldset>
777
			</td>
778
		</tr>
779
		<?php
780
781
		return ob_get_clean();
782
	}
783
784
	/**
785
	 * Generate Title HTML.
786
	 *
787
	 * @param string $key Field key.
788
	 * @param array  $data Field data.
789
	 * @since  1.0.0
790
	 * @return string
791
	 */
792
	public function generate_title_html( $key, $data ) {
793
		$field_key = $this->get_field_key( $key );
794
		$defaults  = array(
795
			'title' => '',
796
			'class' => '',
797
		);
798
799
		$data = wp_parse_args( $data, $defaults );
800
801
		ob_start();
802
		?>
803
			</table>
804
			<h3 class="wc-settings-sub-title <?php echo esc_attr( $data['class'] ); ?>" id="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></h3>
805
			<?php if ( ! empty( $data['description'] ) ) : ?>
806
				<p><?php echo wp_kses_post( $data['description'] ); ?></p>
807
			<?php endif; ?>
808
			<table class="form-table">
809
		<?php
810
811
		return ob_get_clean();
812
	}
813
814
	/**
815
	 * Validate Text Field.
816
	 *
817
	 * Make sure the data is escaped correctly, etc.
818
	 *
819
	 * @param  string $key Field key.
820
	 * @param  string $value Posted Value.
821
	 * @return string
822
	 */
823
	public function validate_text_field( $key, $value ) {
824
		$value = is_null( $value ) ? '' : $value;
825
		return wp_kses_post( trim( stripslashes( $value ) ) );
826
	}
827
828
	/**
829
	 * Validate Price Field.
830
	 *
831
	 * Make sure the data is escaped correctly, etc.
832
	 *
833
	 * @param  string $key Field key.
834
	 * @param  string $value Posted Value.
835
	 * @return string
836
	 */
837
	public function validate_price_field( $key, $value ) {
838
		$value = is_null( $value ) ? '' : $value;
839
		return ( '' === $value ) ? '' : wc_format_decimal( trim( stripslashes( $value ) ) );
840
	}
841
842
	/**
843
	 * Validate Decimal Field.
844
	 *
845
	 * Make sure the data is escaped correctly, etc.
846
	 *
847
	 * @param  string $key Field key.
848
	 * @param  string $value Posted Value.
849
	 * @return string
850
	 */
851
	public function validate_decimal_field( $key, $value ) {
852
		$value = is_null( $value ) ? '' : $value;
853
		return ( '' === $value ) ? '' : wc_format_decimal( trim( stripslashes( $value ) ) );
854
	}
855
856
	/**
857
	 * Validate Password Field. No input sanitization is used to avoid corrupting passwords.
858
	 *
859
	 * @param  string $key Field key.
860
	 * @param  string $value Posted Value.
861
	 * @return string
862
	 */
863
	public function validate_password_field( $key, $value ) {
864
		$value = is_null( $value ) ? '' : $value;
865
		return trim( stripslashes( $value ) );
866
	}
867
868
	/**
869
	 * Validate Textarea Field.
870
	 *
871
	 * @param  string $key Field key.
872
	 * @param  string $value Posted Value.
873
	 * @return string
874
	 */
875 View Code Duplication
	public function validate_textarea_field( $key, $value ) {
876
		$value = is_null( $value ) ? '' : $value;
877
		return wp_kses( trim( stripslashes( $value ) ),
878
			array_merge(
879
				array(
880
					'iframe' => array(
881
						'src'   => true,
882
						'style' => true,
883
						'id'    => true,
884
						'class' => true,
885
					),
886
				),
887
				wp_kses_allowed_html( 'post' )
888
			)
889
		);
890
	}
891
892
	/**
893
	 * Validate Checkbox Field.
894
	 *
895
	 * If not set, return "no", otherwise return "yes".
896
	 *
897
	 * @param  string $key Field key.
898
	 * @param  string $value Posted Value.
899
	 * @return string
900
	 */
901
	public function validate_checkbox_field( $key, $value ) {
902
		return ! is_null( $value ) ? 'yes' : 'no';
903
	}
904
905
	/**
906
	 * Validate Select Field.
907
	 *
908
	 * @param  string $key Field key.
909
	 * @param  string $value Posted Value.
910
	 * @return string
911
	 */
912
	public function validate_select_field( $key, $value ) {
913
		$value = is_null( $value ) ? '' : $value;
914
		return wc_clean( stripslashes( $value ) );
915
	}
916
917
	/**
918
	 * Validate Multiselect Field.
919
	 *
920
	 * @param  string $key Field key.
921
	 * @param  string $value Posted Value.
922
	 * @return string|array
923
	 */
924
	public function validate_multiselect_field( $key, $value ) {
925
		return is_array( $value ) ? array_map( 'wc_clean', array_map( 'stripslashes', $value ) ) : '';
926
	}
927
928
	/**
929
	 * Validate the data on the "Settings" form.
930
	 *
931
	 * @deprecated 2.6.0 No longer used.
932
	 * @param array $form_fields Array of fields.
933
	 */
934
	public function validate_settings_fields( $form_fields = array() ) {
935
		wc_deprecated_function( 'validate_settings_fields', '2.6' );
936
	}
937
938
	/**
939
	 * Format settings if needed.
940
	 *
941
	 * @deprecated 2.6.0 Unused.
942
	 * @param  array $value Value to format.
943
	 * @return array
944
	 */
945
	public function format_settings( $value ) {
946
		wc_deprecated_function( 'format_settings', '2.6' );
947
		return $value;
948
	}
949
}
950