Merge pull request #11882 from woothemes/settings-and-api-fixes

Settings & API Fixes
This commit is contained in:
Justin Shreve 2016-09-09 05:52:23 -07:00 committed by GitHub
commit c8ddca0635
17 changed files with 686 additions and 110 deletions

View File

@ -185,6 +185,140 @@ abstract class WC_REST_Controller extends WP_REST_Controller {
return $response;
}
/**
* Validate a text value for a text based setting.
*
* @since 2.7.0
* @param string $value
* @param array $setting
* @return string
*/
public function validate_setting_text_field( $value, $setting ) {
$value = is_null( $value ) ? '' : $value;
return wp_kses_post( trim( stripslashes( $value ) ) );
return $value;
}
/**
* Validate select based settings.
*
* @since 2.7.0
* @param string $value
* @param array $setting
* @return string|WP_Error
*/
public function validate_setting_select_field( $value, $setting ) {
if ( array_key_exists( $value, $setting['options'] ) ) {
return $value;
} else {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
}
/**
* Validate multiselect based settings.
*
* @since 2.7.0
* @param array $values
* @param array $setting
* @return string|WP_Error
*/
public function validate_setting_multiselect_field( $values, $setting ) {
if ( empty( $values ) ) {
return array();
}
if ( ! is_array( $values ) ) {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
$final_values = array();
foreach ( $values as $value ) {
if ( array_key_exists( $value, $setting['options'] ) ) {
$final_values[] = $value;
}
}
return $final_values;
}
/**
* Validate image_width based settings.
*
* @since 2.7.0
* @param array $value
* @param array $setting
* @return string|WP_Error
*/
public function validate_setting_image_width_field( $values, $setting ) {
if ( ! is_array( $values ) ) {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
$current = $setting['value'];
if ( isset( $values['width'] ) ) {
$current['width'] = intval( $values['width'] );
}
if ( isset( $values['height'] ) ) {
$current['height'] = intval( $values['height'] );
}
if ( isset( $values['crop'] ) ) {
$current['crop'] = (bool) $values['crop'];
}
return $current;
}
/**
* Validate radio based settings.
*
* @since 2.7.0
* @param string $value
* @param array $setting
* @return string|WP_Error
*/
public function validate_setting_radio_field( $value, $setting ) {
return $this->validate_setting_select_field( $value, $setting );
}
/**
* Validate checkbox based settings.
*
* @since 2.7.0
* @param string $value
* @param array $setting
* @return string|WP_Error
*/
public function validate_setting_checkbox_field( $value, $setting ) {
if ( in_array( $value, array( 'yes', 'no' ) ) ) {
return $value;
} elseif ( empty( $value ) ) {
$value = isset( $setting['default'] ) ? $setting['default'] : 'no';
return $value;
} else {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
}
/**
* Validate textarea based settings.
*
* @since 2.7.0
* @param string $value
* @param array $setting
* @return string
*/
public function validate_setting_textarea_field( $value, $setting ) {
$value = is_null( $value ) ? '' : $value;
return wp_kses( trim( stripslashes( $value ) ),
array_merge(
array(
'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true ),
),
wp_kses_allowed_html( 'post' )
)
);
}
/**
* Get the batch schema, conforming to JSON Schema.
*

View File

@ -46,7 +46,7 @@ abstract class WC_REST_Shipping_Zones_Controller_Base extends WC_REST_Controller
$zone = WC_Shipping_Zones::get_zone_by( 'zone_id', $zone_id );
if ( false === $zone ) {
return new WP_Error( 'woocommerce_rest_shipping_zone_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_shipping_zone_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
return $zone;

View File

@ -217,7 +217,7 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
// Get taxonomy.
$taxonomy = $this->get_taxonomy( $request );
if ( ! $taxonomy ) {
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( "Taxonomy doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Taxonomy does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
// Check permissions for a single term.
@ -225,7 +225,7 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
$term = get_term( $id, $taxonomy );
if ( ! $term || $term->taxonomy !== $taxonomy ) {
return new WP_Error( 'woocommerce_rest_term_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_term_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
return wc_rest_check_product_term_permissions( $taxonomy, $context, $term->term_id );
@ -370,7 +370,7 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
$parent = get_term( (int) $request['parent'], $taxonomy );
if ( ! $parent ) {
return new WP_Error( 'woocommerce_rest_term_invalid', __( "Parent resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_term_invalid', __( 'Parent resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$args['parent'] = $parent->term_id;
@ -474,7 +474,7 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
$parent = get_term( (int) $request['parent'], $taxonomy );
if ( ! $parent ) {
return new WP_Error( 'woocommerce_rest_term_invalid', __( "Parent resource doesn't exist.", 'woocommerce' ), array( 'status' => 400 ) );
return new WP_Error( 'woocommerce_rest_term_invalid', __( 'Parent resource does not exist.', 'woocommerce' ), array( 'status' => 400 ) );
}
$prepared_args['parent'] = $parent->term_id;

View File

@ -61,7 +61,7 @@ class WC_REST_Customer_Downloads_Controller extends WC_REST_Controller {
$customer = get_user_by( 'id', (int) $request['customer_id'] );
if ( ! $customer ) {
return new WP_Error( "woocommerce_rest_customer_invalid", __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_customer_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
if ( ! wc_rest_check_user_permissions( 'read', $customer->id ) ) {

View File

@ -133,7 +133,7 @@ class WC_REST_Payment_Gateways_Controller extends WC_REST_Controller {
$gateway = $this->get_gateway( $request );
if ( is_null( $gateway ) ) {
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( "Resource does not exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$gateway = $this->prepare_item_for_response( $gateway, $request );
@ -150,18 +150,33 @@ class WC_REST_Payment_Gateways_Controller extends WC_REST_Controller {
$gateway = $this->get_gateway( $request );
if ( is_null( $gateway ) ) {
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( "Resource does not exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
// Update settings if present
if ( isset( $request['settings'] ) ) {
$gateway->init_form_fields();
$settings = $gateway->settings;
$settings = $gateway->settings;
$errors_found = false;
foreach ( $gateway->form_fields as $key => $field ) {
if ( isset( $request['settings'][ $key ] ) ) {
$settings[ $key ] = $request['settings'][ $key ];
if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
} else {
$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
}
if ( is_wp_error( $value ) ) {
$errors_found = true;
break;
}
$settings[ $key ] = $value;
}
}
if ( $errors_found ) {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
$gateway->settings = $settings;
update_option( $gateway->get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );
}

View File

@ -143,7 +143,7 @@ class WC_REST_Product_Attributes_Controller extends WC_REST_Controller {
*/
public function get_item_permissions_check( $request ) {
if ( ! $this->get_taxonomy( $request ) ) {
return new WP_Error( "woocommerce_rest_taxonomy_invalid", __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
if ( ! wc_rest_check_manager_permissions( 'attributes', 'read' ) ) {
@ -161,7 +161,7 @@ class WC_REST_Product_Attributes_Controller extends WC_REST_Controller {
*/
public function update_item_permissions_check( $request ) {
if ( ! $this->get_taxonomy( $request ) ) {
return new WP_Error( "woocommerce_rest_taxonomy_invalid", __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
if ( ! wc_rest_check_manager_permissions( 'attributes', 'edit' ) ) {
@ -179,7 +179,7 @@ class WC_REST_Product_Attributes_Controller extends WC_REST_Controller {
*/
public function delete_item_permissions_check( $request ) {
if ( ! $this->get_taxonomy( $request ) ) {
return new WP_Error( "woocommerce_rest_taxonomy_invalid", __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
if ( ! wc_rest_check_manager_permissions( 'attributes', 'delete' ) ) {
@ -617,7 +617,7 @@ class WC_REST_Product_Attributes_Controller extends WC_REST_Controller {
", $id ) );
if ( is_wp_error( $attribute ) || is_null( $attribute ) ) {
return new WP_Error( 'woocommerce_rest_attribute_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_attribute_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
return $attribute;

View File

@ -185,7 +185,7 @@ class WC_REST_Settings_Controller extends WC_REST_Controller {
public function get_item_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'settings-group',
'title' => 'setting_group',
'type' => 'object',
'properties' => array(
'id' => array(

View File

@ -106,7 +106,9 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
foreach ( $settings as $setting_obj ) {
$setting = $this->prepare_item_for_response( $setting_obj, $request );
$setting = $this->prepare_response_for_collection( $setting );
$data[] = $setting;
if ( $this->is_setting_type_valid( $setting['type'] ) ) {
$data[] = $setting;
}
}
return rest_ensure_response( $data );
@ -131,13 +133,25 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
}
$filtered_settings = array();
foreach ( $settings as $setting ) {
$setting = $this->filter_setting( $setting );
if ( $this->is_setting_type_valid( $setting['type'] ) ) {
$setting['value'] = WC_Admin_Settings::get_option( $setting['id'] );
$filtered_settings[] = $setting;
$option_key = $setting['option_key'];
$setting = $this->filter_setting( $setting );
$default = isset( $setting['default'] ) ? $setting['default'] : '';
// Get the option value
if ( is_array( $option_key ) ) {
$option = get_option( $option_key[0] );
$setting['value'] = isset( $option[ $option_key[1] ] ) ? $option[ $option_key[1] ] : $default;
} else {
$admin_setting_value = WC_Admin_Settings::get_option( $option_key );
$setting['value'] = empty( $admin_setting_value ) ? $default : $admin_setting_value;
}
if ( 'multi_select_countries' === $setting['type'] ) {
$setting['options'] = WC()->countries->get_countries();
$setting['type'] = 'multiselect';
}
$filtered_settings[] = $setting;
}
return $filtered_settings;
@ -218,10 +232,28 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
return $setting;
}
$update_data = array();
$update_data[ $setting['id'] ] = $request['value'];
if ( is_callable( array( $this, 'validate_setting_' . $setting['type'] . '_field' ) ) ) {
$value = $this->{'validate_setting_' . $setting['type'] . '_field'}( $request['value'], $setting );
} else {
$value = $this->validate_setting_text_field( $request['value'], $setting );
}
WC_Admin_Settings::save_fields( array( $setting ), $update_data );
if ( is_wp_error( $value ) ) {
return $value;
}
if ( is_array( $setting['option_key'] ) ) {
$setting['value'] = $value;
$option_key = $setting['option_key'];
$prev = get_option( $option_key[0] );
$prev[ $option_key[1] ] = $request['value'];
update_option( $option_key[0], $prev );
} else {
$update_data = array();
$update_data[ $setting['option_key'] ] = $value;
$setting['value'] = $value;
WC_Admin_Settings::save_fields( array( $setting ), $update_data );
}
$response = $this->prepare_item_for_response( $setting, $request );
@ -237,17 +269,12 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
* @return WP_REST_Response $response Response data.
*/
public function prepare_item_for_response( $item, $request ) {
$data = $this->filter_setting( $item );
$data['value'] = WC_Admin_Settings::get_option( $data['id'] );
$context = empty( $request['context'] ) ? 'view' : $request['context'];
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );
unset( $item['option_key'] );
$data = $this->filter_setting( $item );
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, empty( $request['context'] ) ? 'view' : $request['context'] );
$response = rest_ensure_response( $data );
$response->add_links( $this->prepare_links( $data['id'], $request['group'] ) );
return $response;
}
@ -321,6 +348,29 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
unset( $setting['options'] );
}
if ( 'image_width' === $setting['type'] ) {
$setting = $this->cast_image_width( $setting );
}
return $setting;
}
/**
* For image_width, Crop can return "0" instead of false -- so we want
* to make sure we return these consistently the same we accept them.
*
* @since 2.7.0
* @param array $setting
* @return array
*/
public function cast_image_width( $setting ) {
foreach ( array( 'default', 'value' ) as $key ) {
if ( isset( $setting[ $key ] ) ) {
$setting[ $key ]['width'] = intval( $setting[ $key ]['width'] );
$setting[ $key ]['height'] = intval( $setting[ $key ]['height'] );
$setting[ $key ]['crop'] = (bool) $setting[ $key ]['crop'];
}
}
return $setting;
}
@ -342,6 +392,7 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
'type',
'options',
'value',
'option_key',
) );
}
@ -354,18 +405,17 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
*/
public function is_setting_type_valid( $type ) {
return in_array( $type, array(
'text',
'email',
'number',
'color',
'password',
'textarea',
'select',
'multiselect',
'radio',
'checkbox',
'multi_select_countries',
'image_width',
'text', // validates with validate_setting_text_field
'email', // validates with validate_setting_text_field
'number', // validates with validate_setting_text_field
'color', // validates with validate_setting_text_field
'password', // validates with validate_setting_text_field
'textarea', // validates with validate_setting_textarea_field
'select', // validates with validate_setting_select_field
'multiselect', // validates with validate_setting_multiselect_field
'radio', // validates with validate_setting_radio_field (-> validate_setting_select_field)
'checkbox', // validates with validate_setting_checkbox_field
'image_width', // validates with validate_setting_image_width_field
) );
}
@ -378,7 +428,7 @@ class WC_REST_Settings_Options_Controller extends WC_REST_Controller {
public function get_item_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'settings',
'title' => 'setting',
'type' => 'object',
'properties' => array(
'id' => array(

View File

@ -113,7 +113,7 @@ class WC_REST_Shipping_Methods_Controller extends WC_REST_Controller {
$wc_shipping = WC_Shipping::instance();
$methods = $wc_shipping->get_shipping_methods();
if ( empty( $methods[ $request['id'] ] ) ) {
return new WP_Error( 'woocommerce_rest_shipping_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_shipping_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$method = $methods[ $request['id'] ];

View File

@ -93,7 +93,7 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
}
if ( false === $method ) {
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$data = $this->prepare_item_for_response( $method, $request );
@ -155,6 +155,9 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
}
$method = $this->update_fields( $instance_id, $method, $request );
if ( is_wp_error( $method ) ) {
return $method;
}
$data = $this->prepare_item_for_response( $method, $request );
return rest_ensure_response( $data );
@ -188,10 +191,14 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
}
if ( false === $method ) {
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$method = $this->update_fields( $instance_id, $method, $request );
if ( is_wp_error( $method ) ) {
return $method;
}
$request->set_param( 'context', 'view' );
$response = $this->prepare_item_for_response( $method, $request );
@ -240,10 +247,13 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
}
if ( false === $method ) {
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( "Resource doesn't exist.", 'woocommerce' ), array( 'status' => 404 ) );
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
}
$method = $this->update_fields( $instance_id, $method, $request );
if ( is_wp_error( $method ) ) {
return $method;
}
$data = $this->prepare_item_for_response( $method, $request );
return rest_ensure_response( $data );
@ -264,11 +274,26 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
if ( isset( $request['settings'] ) ) {
$method->init_instance_settings();
$instance_settings = $method->instance_settings;
$errors_found = false;
foreach ( $method->get_instance_form_fields() as $key => $field ) {
if ( isset( $request['settings'][ $key ] ) ) {
$instance_settings[ $key ] = $request['settings'][ $key ];
if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
} else {
$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
}
if ( is_wp_error( $value ) ) {
$errors_found = true;
break;
}
$instance_settings[ $key ] = $value;
}
}
if ( $errors_found ) {
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
}
update_option( $method->get_instance_option_key(), apply_filters( 'woocommerce_shipping_' . $method->id . '_instance_settings_values', $instance_settings, $method ) );
}

View File

@ -230,7 +230,13 @@ class WC_API extends WC_Legacy_API {
public function register_wp_admin_settings() {
$pages = WC_Admin_Settings::get_settings_pages();
foreach ( $pages as $page ) {
new WC_Register_WP_Admin_Settings( $page );
new WC_Register_WP_Admin_Settings( $page, 'page' );
}
$emails = WC_Emails::instance();
foreach ( $emails->get_emails() as $email ) {
new WC_Register_WP_Admin_Settings( $email, 'email' );
}
}
}

View File

@ -13,18 +13,62 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class WC_Register_WP_Admin_Settings {
/** @var class Current settings class. Used to pull settings. */
protected $page;
/** @var class Contains the current class to pull settings from. Either a admin page object or WC_Email object. */
protected $object;
/**
* Hooks into the settings API and starts registering our settings.
*
* @since 2.7.0
* @param WC_Email|WC_Settings_Page $object The object that contains the settings to register.
* @param string $type Type of settings to register (email or page).
*/
public function __construct( $page ) {
$this->page = $page;
add_filter( 'woocommerce_settings_groups', array( $this, 'register_group' ) );
add_filter( 'woocommerce_settings-' . $this->page->get_id(), array( $this, 'register_settings' ) );
public function __construct( $object, $type ) {
$this->object = $object;
if ( 'page' === $type ) {
add_filter( 'woocommerce_settings_groups', array( $this, 'register_page_group' ) );
add_filter( 'woocommerce_settings-' . $this->object->get_id(), array( $this, 'register_page_settings' ) );
} else if ( 'email' === $type ) {
add_filter( 'woocommerce_settings_groups', array( $this, 'register_email_group' ) );
add_filter( 'woocommerce_settings-email_' . $this->object->id, array( $this, 'register_email_settings' ) );
}
}
/**
* Register's all of our different notification emails as sub groups
* of email settings.
*
* @since 2.7.0
* @param array $groups Existing registered groups.
* @return array
*/
public function register_email_group( $groups ) {
$groups[] = array(
'id' => 'email_' . $this->object->id,
'label' => $this->object->title,
'description' => $this->object->description,
'parent_id' => 'email',
);
return $groups;
}
/**
* Registers all of the setting form fields for emails to each email type's group.
*
* @since 2.7.0
* @param array $settings Existing registered settings.
* @return array
*/
public function register_email_settings( $settings ) {
foreach ( $this->object->form_fields as $id => $setting ) {
$setting['id'] = $id;
$setting['option_key'] = array( $this->object->get_option_key(), $id );
$new_setting = $this->register_setting( $setting );
if ( $new_setting ) {
$settings[] = $new_setting;
}
}
return $settings;
}
/**
@ -34,10 +78,10 @@ class WC_Register_WP_Admin_Settings {
* @param array $groups Array of previously registered groups.
* @return array
*/
public function register_group( $groups ) {
public function register_page_group( $groups ) {
$groups[] = array(
'id' => $this->page->get_id(),
'label' => $this->page->get_label(),
'id' => $this->object->get_id(),
'label' => $this->object->get_label(),
);
return $groups;
}
@ -49,23 +93,27 @@ class WC_Register_WP_Admin_Settings {
* @param array $settings Existing registered settings
* @return array
*/
public function register_settings( $settings ) {
public function register_page_settings( $settings ) {
/**
* wp-admin settings can be broken down into separate sections from
* a UI standpoint. This will grab all the sections associated with
* a particular setting group (like 'products') and register them
* to the REST API.
*/
$sections = $this->page->get_sections();
$sections = $this->object->get_sections();
if ( empty( $sections ) ) {
// Default section is just an empty string, per admin page classes
$sections = array( '' );
}
foreach ( $sections as $section => $section_label ) {
$settings_from_section = $this->page->get_settings( $section );
$settings_from_section = $this->object->get_settings( $section );
foreach ( $settings_from_section as $setting ) {
$new_setting = $this->register_setting( $setting );
if ( ! isset( $setting['id'] ) ) {
continue;
}
$setting['option_key'] = $setting['id'];
$new_setting = $this->register_setting( $setting );
if ( $new_setting ) {
$settings[] = $new_setting;
}
@ -75,23 +123,32 @@ class WC_Register_WP_Admin_Settings {
}
/**
* Register's a specific setting (from WC_Settings_Page::get_settings() )
* into the format expected for the REST API Settings Controller.
* Register a setting into the format expected for the Settings REST API.
*
* @since 2.7.0
* @param array $setting Settings array, as produced by a subclass of WC_Settings_Page.
* @return array|bool boolean False if setting has no ID or converted array.
* @param array $setting
* @return array|bool
*/
public function register_setting( $setting ) {
if ( ! isset( $setting['id'] ) ) {
return false;
}
$description = '';
if ( ! empty ( $setting['desc'] ) ) {
$description = $setting['desc'];
} else if ( ! empty( $setting['description'] ) ) {
$description = $setting['description'];
}
$new_setting = array(
'id' => $setting['id'],
'label' => ( ! empty( $setting['title'] ) ? $setting['title'] : '' ),
'description' => ( ! empty( $setting['desc'] ) ? $setting['desc'] : '' ),
'description' => $description,
'type' => $setting['type'],
'option_key' => $setting['option_key'],
);
if ( isset( $setting['default'] ) ) {
$new_setting['default'] = $setting['default'];
}
@ -100,12 +157,13 @@ class WC_Register_WP_Admin_Settings {
}
if ( isset( $setting['desc_tip'] ) ) {
if ( true === $setting['desc_tip'] ) {
$new_setting['tip'] = $setting['desc'];
} elseif ( ! empty( $setting['desc_tip'] ) ) {
$new_setting['tip'] = $description;
} else if ( ! empty( $setting['desc_tip'] ) ) {
$new_setting['tip'] = $setting['desc_tip'];
}
}
return $new_setting;
}
}

View File

@ -30,19 +30,23 @@ class WC_Helper_Settings {
'bad' => 'value',
'label' => __( 'Test Extension', 'woocommerce' ),
'description' => __( 'My awesome test settings.', 'woocommerce' ),
'option_key' => '',
);
$groups[] = array(
'id' => 'sub-test',
'parent_id' => 'test',
'label' => __( 'Sub test', 'woocommerce' ),
'description' => '',
'option_key' => '',
);
$groups[] = array(
'id' => 'coupon-data',
'label' => __( 'Coupon Data', 'woocommerce' ),
'option_key' => '',
);
$groups[] = array(
'id' => 'invalid',
'option_key' => '',
);
return $groups;
}
@ -66,6 +70,7 @@ class WC_Helper_Settings {
'subcategories' => __( 'Show categories & subcategories', 'woocommerce' ),
'both' => __( 'Show both', 'woocommerce' ),
),
'option_key' => 'woocommerce_shop_page_display',
);
$settings[] = array(
'id' => 'woocommerce_enable_lightbox',
@ -74,6 +79,7 @@ class WC_Helper_Settings {
'default' => 'yes',
'tip' => __( 'Product gallery images will open in a lightbox.', 'woocommerce' ),
'type' => 'checkbox',
'option_key' => 'woocommerce_enable_lightbox',
);
return $settings;
}

View File

@ -184,6 +184,26 @@ class Payment_Gateways extends WC_REST_Unit_Test_Case {
$this->assertEquals( 'PayPal - New Title', $paypal['settings']['title']['value'] );
$this->assertEquals( 'woo@woo.local', $paypal['settings']['email']['value'] );
$this->assertEquals( 'yes', $paypal['settings']['testmode']['value'] );
// test bogus
$request = new WP_REST_Request( 'POST', '/wc/v1/payment_gateways/paypal' );
$request->set_body_params( array(
'settings' => array(
'paymentaction' => 'afasfasf',
)
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
$request = new WP_REST_Request( 'POST', '/wc/v1/payment_gateways/paypal' );
$request->set_body_params( array(
'settings' => array(
'paymentaction' => 'authorization',
)
) );
$response = $this->server->dispatch( $request );
$paypal = $response->get_data();
$this->assertEquals( 'authorization', $paypal['settings']['paymentaction']['value'] );
}
/**

View File

@ -8,14 +8,12 @@
class Settings extends WC_REST_Unit_Test_Case {
protected $server;
/**
* Setup our test server, endpoints, and user info.
*/
public function setUp() {
parent::setUp();
$this->endpoint = new WC_Rest_Settings_Options_Controller();
$this->endpoint = new WC_REST_Settings_Options_Controller();
WC_Helper_Settings::register();
$this->user = $this->factory->user->create( array(
'role' => 'administrator',
@ -519,7 +517,7 @@ class Settings extends WC_REST_Unit_Test_Case {
),
),
),
), $data );
), $data );
// test get single
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/settings/products/woocommerce_dimension_unit' ) );
@ -538,4 +536,243 @@ class Settings extends WC_REST_Unit_Test_Case {
$this->assertEquals( 'yd', $data['value'] );
$this->assertEquals( 'yd', get_option( 'woocommerce_dimension_unit' ) );
}
/**
* Tests our email etting registration to make sure settings added for WP-Admin are available over the API.
*
* @since 2.7.0
*/
public function test_email_settings() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/settings/email_new_order' ) );
$settings = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertContains( array(
'id' => 'recipient',
'label' => 'Recipient(s)',
'description' => 'Enter recipients (comma separated) for this email. Defaults to <code>admin@example.org</code>.',
'type' => 'text',
'default' => '',
'tip' => 'Enter recipients (comma separated) for this email. Defaults to <code>admin@example.org</code>.',
'value' => '',
'_links' => array(
'self' => array(
array(
'href' => rest_url( '/wc/v1/settings/email_new_order/recipient' ),
),
),
'collection' => array(
array(
'href' => rest_url( '/wc/v1/settings/email_new_order' ),
),
),
),
), $settings );
// test get single
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/settings/email_new_order/subject' ) );
$setting = $response->get_data();
$this->assertEquals( array(
'id' => 'subject',
'label' => 'Subject',
'description' => 'This controls the email subject line. Leave blank to use the default subject: <code>[{site_title}] New customer order ({order_number}) - {order_date}</code>.',
'type' => 'text',
'default' => '',
'tip' => 'This controls the email subject line. Leave blank to use the default subject: <code>[{site_title}] New customer order ({order_number}) - {order_date}</code>.',
'value' => '',
), $setting );
// test update
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'email_new_order', 'subject' ) );
$request->set_body_params( array(
'value' => 'This is my subject',
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array(
'id' => 'subject',
'label' => 'Subject',
'description' => 'This controls the email subject line. Leave blank to use the default subject: <code>[{site_title}] New customer order ({order_number}) - {order_date}</code>.',
'type' => 'text',
'default' => '',
'tip' => 'This controls the email subject line. Leave blank to use the default subject: <code>[{site_title}] New customer order ({order_number}) - {order_date}</code>.',
'value' => 'This is my subject',
), $setting );
// test updating another subject and making sure it works with a "similar" id
$request = new WP_REST_Request( 'GET', sprintf( '/wc/v1/settings/%s/%s', 'email_customer_new_account', 'subject' ) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEmpty( $setting['value'] );
// test update
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'email_customer_new_account', 'subject' ) );
$request->set_body_params( array(
'value' => 'This is my new subject',
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( 'This is my new subject', $setting['value'] );
// make sure the other is what we left it
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/settings/email_new_order/subject' ) );
$setting = $response->get_data();
$this->assertEquals( 'This is my subject', $setting['value'] );
}
/**
* Test validation of checkbox settings.
*
* @since 2.7.0
*/
public function test_validation_checkbox() {
wp_set_current_user( $this->user );
// test bogus value
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'email_cancelled_order', 'enabled' ) );
$request->set_body_params( array(
'value' => 'not_yes_or_no',
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
// test yes
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'email_cancelled_order', 'enabled' ) );
$request->set_body_params( array(
'value' => 'yes',
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
// test no
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'email_cancelled_order', 'enabled' ) );
$request->set_body_params( array(
'value' => 'no',
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
}
/**
* Test validation of radio settings.
*
* @since 2.7.0
*/
public function test_validation_radio() {
wp_set_current_user( $this->user );
// not a valid option
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'shipping', 'woocommerce_ship_to_destination' ) );
$request->set_body_params( array(
'value' => 'billing2',
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
// valid
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'shipping', 'woocommerce_ship_to_destination' ) );
$request->set_body_params( array(
'value' => 'billing',
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
}
/**
* Test validation of multiselect.
*
* @since 2.7.0
*/
public function test_validation_multiselect() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', sprintf( '/wc/v1/settings/%s/%s', 'general', 'woocommerce_specific_allowed_countries' ) ) );
$setting = $response->get_data();
$this->assertEmpty( $setting['value'] );
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'general', 'woocommerce_specific_allowed_countries' ) );
$request->set_body_params( array(
'value' => array( 'AX', 'DZ', 'MMM' ),
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array( 'AX', 'DZ' ), $setting['value'] );
}
/**
* Test validation of select.
*
* @since 2.7.0
*/
public function test_validation_select() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', sprintf( '/wc/v1/settings/%s/%s', 'products', 'woocommerce_weight_unit' ) ) );
$setting = $response->get_data();
$this->assertEquals( 'kg', $setting['value'] );
// invalid
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'products', 'woocommerce_weight_unit' ) );
$request->set_body_params( array(
'value' => 'pounds', // invalid, should be lbs
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
// valid
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'products', 'woocommerce_weight_unit' ) );
$request->set_body_params( array(
'value' => 'lbs', // invalid, should be lbs
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( 'lbs', $setting['value'] );
}
/**
* Test validation of image_width.
*
* @since 2.7.0
*/
public function test_validation_image_width() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', sprintf( '/wc/v1/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) ) );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 180, 'height' => 180, 'crop' => true ), $setting['value'] );
// test bogus
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) );
$request->set_body_params( array(
'value' => array(
'width' => 400,
'height' => 200,
'crop' => 'asdasdasd',
),
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 400, 'height' => 200, 'crop' => true ), $setting['value'] );
$request = new WP_REST_Request( 'PUT', sprintf( '/wc/v1/settings/%s/%s', 'products', 'shop_thumbnail_image_size' ) );
$request->set_body_params( array(
'value' => array(
'width' => 200,
'height' => 100,
'crop' => false,
),
) );
$response = $this->server->dispatch( $request );
$setting = $response->get_data();
$this->assertEquals( array( 'width' => 200, 'height' => 100, 'crop' => false ), $setting['value'] );
}
}

View File

@ -677,6 +677,17 @@ class WC_Tests_API_Shipping_Zones extends WC_REST_Unit_Test_Case {
$this->assertArrayHasKey( 'cost', $data['settings'] );
$this->assertEquals( '10', $data['settings']['cost']['value'] );
// Test bogus
$request = new WP_REST_Request( 'POST', '/wc/v1/shipping/zones/' . $zone->get_id() . '/methods/' . $instance_id );
$request->set_body_params( array(
'settings' => array(
'cost' => 10,
'tax_status' => 'this_is_not_a_valid_option',
),
) );
$response = $this->server->dispatch( $request );
$this->assertEquals( 400, $response->get_status() );
// Test other parameters
$this->assertTrue( $data['enabled'] );
$this->assertEquals( 1, $data['order'] );

View File

@ -41,10 +41,10 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
* @covers WC_Register_WP_Admin_Settings::__construct
*/
public function test_constructor() {
$settings = new WC_Register_WP_Admin_Settings( $this->page );
$settings = new WC_Register_WP_Admin_Settings( $this->page, 'page' );
$this->assertEquals( has_filter( 'woocommerce_settings_groups', array( $settings, 'register_group' ) ), 10 );
$this->assertEquals( has_filter( 'woocommerce_settings-' . $this->page->get_id(), array( $settings, 'register_settings' ) ), 10 );
$this->assertEquals( has_filter( 'woocommerce_settings_groups', array( $settings, 'register_page_group' ) ), 10 );
$this->assertEquals( has_filter( 'woocommerce_settings-' . $this->page->get_id(), array( $settings, 'register_page_settings' ) ), 10 );
}
/**
@ -52,7 +52,7 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
* @covers WC_Register_WP_Admin_Settings::register_group
*/
public function test_register_group() {
$settings = new WC_Register_WP_Admin_Settings( $this->page );
$settings = new WC_Register_WP_Admin_Settings( $this->page, 'page' );
$existing = array(
'id' => 'existing-id',
@ -66,7 +66,7 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
'label' => $this->page->get_label(),
),
);
$actual = $settings->register_group( $initial );
$actual = $settings->register_page_group( $initial );
$this->assertEquals( $expected, $actual );
}
@ -79,19 +79,21 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
// No "id" case
array(
array(
'type' => 'some-type-with-no-id',
'type' => 'some-type-with-no-id',
'option_key' => '',
),
false,
),
// All optional properties except 'desc_tip'
array(
array(
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'default' => 'one',
'options' => array( 'one', 'two' ),
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'default' => 'one',
'options' => array( 'one', 'two' ),
'option_key' => '',
),
array(
'id' => 'setting-id',
@ -100,16 +102,18 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
'description' => 'Setting Description',
'default' => 'one',
'options' => array( 'one', 'two' ),
'option_key' => '',
),
),
// Boolean 'desc_tip' defaulting to 'desc' value
array(
array(
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'desc_tip' => true,
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'desc_tip' => true,
'option_key' => '',
),
array(
'id' => 'setting-id',
@ -117,16 +121,18 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
'label' => 'Setting Name',
'description' => 'Setting Description',
'tip' => 'Setting Description',
'option_key' => '',
),
),
// String 'desc_tip'
array(
array(
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'desc_tip' => 'Setting Tip',
'id' => 'setting-id',
'type' => 'select',
'title' => 'Setting Name',
'desc' => 'Setting Description',
'desc_tip' => 'Setting Tip',
'option_key' => '',
),
array(
'id' => 'setting-id',
@ -134,19 +140,22 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
'label' => 'Setting Name',
'description' => 'Setting Description',
'tip' => 'Setting Tip',
'option_key' => '',
),
),
// Empty 'title' and 'desc'
array(
array(
'id' => 'setting-id',
'type' => 'select',
'id' => 'setting-id',
'type' => 'select',
'option_key' => '',
),
array(
'id' => 'setting-id',
'type' => 'select',
'label' => '',
'description' => '',
'option_key' => '',
),
),
);
@ -158,7 +167,7 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
* @covers WC_Register_WP_Admin_Settings::register_setting
*/
public function test_register_setting( $input, $expected ) {
$settings = new WC_Register_WP_Admin_Settings( $this->page );
$settings = new WC_Register_WP_Admin_Settings( $this->page, 'page' );
$actual = $settings->register_setting( $input );
@ -181,10 +190,10 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
->with( $this->equalTo( 0 ) )
->will( $this->returnValue( array() ) );
$settings = new WC_Register_WP_Admin_Settings( $this->page );
$settings = new WC_Register_WP_Admin_Settings( $this->page, 'page' );
$expected = array();
$actual = $settings->register_settings( array() );
$actual = $settings->register_page_settings( array() );
$this->assertEquals( $expected, $actual );
}
@ -201,15 +210,18 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
$settings = array(
array(
'id' => 'setting-1',
'type' => 'text',
'id' => 'setting-1',
'type' => 'text',
'option_key' => '',
),
array(
'type' => 'no-id',
'type' => 'no-id',
'option_key' => '',
),
array(
'id' => 'setting-2',
'type' => 'textarea',
'id' => 'setting-2',
'type' => 'textarea',
'option_key' => '',
),
);
@ -218,7 +230,7 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
->method( 'get_settings' )
->will( $this->returnValue( $settings ) );
$settings = new WC_Register_WP_Admin_Settings( $this->page );
$settings = new WC_Register_WP_Admin_Settings( $this->page, 'page' );
$expected = array(
array(
@ -226,15 +238,17 @@ class WC_Tests_Register_WP_Admin_Settings extends WC_Unit_Test_Case {
'type' => 'text',
'label' => '',
'description' => '',
'option_key' => 'setting-1',
),
array(
'id' => 'setting-2',
'type' => 'textarea',
'label' => '',
'description' => '',
'option_key' => 'setting-2',
),
);
$actual = $settings->register_settings( array() );
$actual = $settings->register_page_settings( array() );
$this->assertEquals( $expected, $actual );
}