abstract-wc-settings-api.php 29 KB

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