Merge pull request #29495 from woocommerce/fix/29472
Add "postcodes" and "cities" support for the REST API tax rate creation/update endpoint
This commit is contained in:
commit
e4502fe314
|
@ -4,8 +4,6 @@
|
|||
*
|
||||
* Handles requests to the /taxes endpoint.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category API
|
||||
* @package WooCommerce\RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
@ -40,67 +38,79 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
* Register the routes for taxes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
'args' => $this->get_collection_params(),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_item' ),
|
||||
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
) );
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
'args' => $this->get_collection_params(),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_item' ),
|
||||
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d]+)',
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
'args' => array(
|
||||
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'callback' => array( $this, 'delete_item' ),
|
||||
'permission_callback' => array( $this, 'delete_item_permissions_check' ),
|
||||
'args' => array(
|
||||
'force' => array(
|
||||
'default' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
) );
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
'args' => array(
|
||||
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'callback' => array( $this, 'delete_item' ),
|
||||
'permission_callback' => array( $this, 'delete_item_permissions_check' ),
|
||||
'args' => array(
|
||||
'force' => array(
|
||||
'default' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'Required to be true, as resource does not support trashing.', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route( $this->namespace, '/' . $this->rest_base . '/batch', array(
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/batch',
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'batch_items' ),
|
||||
'permission_callback' => array( $this, 'batch_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_batch_schema' ),
|
||||
) );
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'batch_items' ),
|
||||
'permission_callback' => array( $this, 'batch_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_batch_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -200,7 +210,7 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
public function get_items( $request ) {
|
||||
global $wpdb;
|
||||
|
||||
$prepared_args = array();
|
||||
$prepared_args = array();
|
||||
$prepared_args['order'] = $request['order'];
|
||||
$prepared_args['number'] = $request['per_page'];
|
||||
if ( ! empty( $request['offset'] ) ) {
|
||||
|
@ -208,9 +218,10 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
} else {
|
||||
$prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number'];
|
||||
}
|
||||
$orderby_possibles = array(
|
||||
'id' => 'tax_rate_id',
|
||||
'order' => 'tax_rate_order',
|
||||
$orderby_possibles = array(
|
||||
'id' => 'tax_rate_id',
|
||||
'order' => 'tax_rate_order',
|
||||
'priority' => 'tax_rate_priority',
|
||||
);
|
||||
$prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
|
||||
$prepared_args['class'] = $request['class'];
|
||||
|
@ -223,30 +234,42 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
*/
|
||||
$prepared_args = apply_filters( 'woocommerce_rest_tax_query', $prepared_args, $request );
|
||||
|
||||
$query = "
|
||||
$orderby = sanitize_key( $prepared_args['orderby'] ) . ' ' . sanitize_key( $prepared_args['order'] );
|
||||
$query = "
|
||||
SELECT *
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
WHERE 1 = 1
|
||||
%s
|
||||
ORDER BY {$orderby}
|
||||
LIMIT %%d, %%d
|
||||
";
|
||||
|
||||
$wpdb_prepare_args = array(
|
||||
$prepared_args['offset'],
|
||||
$prepared_args['number'],
|
||||
);
|
||||
|
||||
// Filter by tax class.
|
||||
if ( ! empty( $prepared_args['class'] ) ) {
|
||||
if ( empty( $prepared_args['class'] ) ) {
|
||||
$query = sprintf( $query, '' );
|
||||
} else {
|
||||
$class = 'standard' !== $prepared_args['class'] ? sanitize_title( $prepared_args['class'] ) : '';
|
||||
$query .= " AND tax_rate_class = '$class'";
|
||||
array_unshift( $wpdb_prepare_args, $class );
|
||||
$query = sprintf( $query, 'WHERE tax_rate_class = %s' );
|
||||
}
|
||||
|
||||
// Order tax rates.
|
||||
$order_by = sprintf( ' ORDER BY %s', sanitize_key( $prepared_args['orderby'] ) );
|
||||
|
||||
// Pagination.
|
||||
$pagination = sprintf( ' LIMIT %d, %d', $prepared_args['offset'], $prepared_args['number'] );
|
||||
|
||||
// Query taxes.
|
||||
$results = $wpdb->get_results( $query . $order_by . $pagination );
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
$query,
|
||||
$wpdb_prepare_args
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
$taxes = array();
|
||||
foreach ( $results as $tax ) {
|
||||
$data = $this->prepare_item_for_response( $tax, $request );
|
||||
$data = $this->prepare_item_for_response( $tax, $request );
|
||||
$taxes[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
|
@ -254,10 +277,18 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
|
||||
// Store pagination values for headers then unset for count query.
|
||||
$per_page = (int) $prepared_args['number'];
|
||||
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
|
||||
$page = ceil( ( ( (int) $prepared_args['offset'] ) / $per_page ) + 1 );
|
||||
|
||||
// Query only for ids.
|
||||
$wpdb->get_results( str_replace( 'SELECT *', 'SELECT tax_rate_id', $query ) );
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
|
||||
$query = str_replace( 'SELECT *', 'SELECT tax_rate_id', $query );
|
||||
$wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
$query,
|
||||
$wpdb_prepare_args
|
||||
)
|
||||
);
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
// Calculate totals.
|
||||
$total_taxes = (int) $wpdb->num_rows;
|
||||
|
@ -287,13 +318,13 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
* Take tax data from the request and return the updated or newly created rate.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @param stdClass|null $current Existing tax object.
|
||||
* @param stdClass|null $current Existing tax object.
|
||||
* @return object
|
||||
*/
|
||||
protected function create_or_update_tax( $request, $current = null ) {
|
||||
$id = absint( isset( $request['id'] ) ? $request['id'] : 0 );
|
||||
$data = array();
|
||||
$fields = array(
|
||||
$id = absint( isset( $request['id'] ) ? $request['id'] : 0 );
|
||||
$data = array();
|
||||
$fields = array(
|
||||
'tax_rate_country',
|
||||
'tax_rate_state',
|
||||
'tax_rate',
|
||||
|
@ -321,25 +352,25 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
|
||||
// Add to data array.
|
||||
switch ( $key ) {
|
||||
case 'tax_rate_priority' :
|
||||
case 'tax_rate_compound' :
|
||||
case 'tax_rate_shipping' :
|
||||
case 'tax_rate_order' :
|
||||
case 'tax_rate_priority':
|
||||
case 'tax_rate_compound':
|
||||
case 'tax_rate_shipping':
|
||||
case 'tax_rate_order':
|
||||
$data[ $field ] = absint( $request[ $key ] );
|
||||
break;
|
||||
case 'tax_rate_class' :
|
||||
case 'tax_rate_class':
|
||||
$data[ $field ] = 'standard' !== $request['tax_rate_class'] ? $request['tax_rate_class'] : '';
|
||||
break;
|
||||
default :
|
||||
default:
|
||||
$data[ $field ] = wc_clean( $request[ $key ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $id ) {
|
||||
WC_Tax::_update_tax_rate( $id, $data );
|
||||
} else {
|
||||
if ( ! $id ) {
|
||||
$id = WC_Tax::_insert_tax_rate( $data );
|
||||
} elseif ( $data ) {
|
||||
WC_Tax::_update_tax_rate( $id, $data );
|
||||
}
|
||||
|
||||
// Add locales.
|
||||
|
@ -538,7 +569,7 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
*/
|
||||
protected function prepare_links( $tax ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $tax->tax_rate_id ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
|
@ -592,18 +623,18 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
'title' => 'tax',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'country' => array(
|
||||
'country' => array(
|
||||
'description' => __( 'Country ISO 3166 code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'state' => array(
|
||||
'state' => array(
|
||||
'description' => __( 'State code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
|
@ -613,17 +644,17 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'city' => array(
|
||||
'city' => array(
|
||||
'description' => __( 'City name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'rate' => array(
|
||||
'rate' => array(
|
||||
'description' => __( 'Tax rate.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'name' => array(
|
||||
'name' => array(
|
||||
'description' => __( 'Tax rate name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
|
@ -646,12 +677,12 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
'default' => true,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'order' => array(
|
||||
'order' => array(
|
||||
'description' => __( 'Indicates the order that will appear in queries.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'class' => array(
|
||||
'class' => array(
|
||||
'description' => __( 'Tax class.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'standard',
|
||||
|
@ -674,54 +705,55 @@ class WC_REST_Taxes_V1_Controller extends WC_REST_Controller {
|
|||
$params['context'] = $this->get_context_param();
|
||||
$params['context']['default'] = 'view';
|
||||
|
||||
$params['page'] = array(
|
||||
'description' => __( 'Current page of the collection.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => 1,
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'minimum' => 1,
|
||||
$params['page'] = array(
|
||||
'description' => __( 'Current page of the collection.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => 1,
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'minimum' => 1,
|
||||
);
|
||||
$params['per_page'] = array(
|
||||
'description' => __( 'Maximum number of items to be returned in result set.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => 10,
|
||||
'minimum' => 1,
|
||||
'maximum' => 100,
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'description' => __( 'Maximum number of items to be returned in result set.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => 10,
|
||||
'minimum' => 1,
|
||||
'maximum' => 100,
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['offset'] = array(
|
||||
'description' => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
$params['offset'] = array(
|
||||
'description' => __( 'Offset the result set by a specific number of items.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['order'] = array(
|
||||
'default' => 'asc',
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
|
||||
'enum' => array( 'asc', 'desc' ),
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
$params['order'] = array(
|
||||
'default' => 'asc',
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
|
||||
'enum' => array( 'asc', 'desc' ),
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['orderby'] = array(
|
||||
'default' => 'order',
|
||||
'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
|
||||
'enum' => array(
|
||||
$params['orderby'] = array(
|
||||
'default' => 'order',
|
||||
'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
|
||||
'enum' => array(
|
||||
'id',
|
||||
'order',
|
||||
'priority',
|
||||
),
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['class'] = array(
|
||||
'description' => __( 'Sort by tax class.', 'woocommerce' ),
|
||||
'enum' => array_merge( array( 'standard' ), WC_Tax::get_tax_class_slugs() ),
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
$params['class'] = array(
|
||||
'description' => __( 'Sort by tax class.', 'woocommerce' ),
|
||||
'enum' => array_merge( array( 'standard' ), WC_Tax::get_tax_class_slugs() ),
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
return $params;
|
||||
|
|
|
@ -74,7 +74,7 @@ class WC_REST_Taxes_Controller extends WC_REST_Taxes_V2_Controller {
|
|||
$schema = parent::get_item_schema();
|
||||
|
||||
$schema['properties']['postcodes'] = array(
|
||||
'description' => __( 'List of postcodes / ZIPs.', 'woocommerce' ),
|
||||
'description' => __( 'List of postcodes / ZIPs. Introduced in WooCommerce 5.3.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
|
@ -83,7 +83,7 @@ class WC_REST_Taxes_Controller extends WC_REST_Taxes_V2_Controller {
|
|||
);
|
||||
|
||||
$schema['properties']['cities'] = array(
|
||||
'description' => __( 'List of city names.', 'woocommerce' ),
|
||||
'description' => __( 'List of city names. Introduced in WooCommerce 5.3.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
|
@ -91,6 +91,51 @@ class WC_REST_Taxes_Controller extends WC_REST_Taxes_V2_Controller {
|
|||
'context' => array( 'view', 'edit' ),
|
||||
);
|
||||
|
||||
$schema['properties']['postcode']['description'] =
|
||||
__( "Postcode/ZIP, it doesn't support multiple values. Deprecated as of WooCommerce 5.3, 'postcodes' should be used instead.", 'woocommerce' );
|
||||
|
||||
$schema['properties']['city']['description'] =
|
||||
__( "City name, it doesn't support multiple values. Deprecated as of WooCommerce 5.3, 'cities' should be used instead.", 'woocommerce' );
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single tax.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response The response, or an error.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$this->adjust_cities_and_postcodes( $request );
|
||||
|
||||
return parent::create_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single tax.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response The response, or an error.
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$this->adjust_cities_and_postcodes( $request );
|
||||
|
||||
return parent::update_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert array "cities" and "postcodes" parameters
|
||||
* into semicolon-separated strings "city" and "postcode".
|
||||
*
|
||||
* @param WP_REST_Request $request The request to adjust.
|
||||
*/
|
||||
private function adjust_cities_and_postcodes( &$request ) {
|
||||
if ( isset( $request['cities'] ) ) {
|
||||
$request['city'] = join( ';', $request['cities'] );
|
||||
}
|
||||
if ( isset( $request['postcodes'] ) ) {
|
||||
$request['postcode'] = join( ';', $request['postcodes'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,18 @@
|
|||
*
|
||||
* Provides REST API specific methods and setup/teardown.
|
||||
*
|
||||
* @package WooCommerce\Tests
|
||||
* @since 3.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for REST related unit test classes.
|
||||
*/
|
||||
class WC_REST_Unit_Test_Case extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* @var WP_REST_Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
|
@ -36,4 +43,64 @@ class WC_REST_Unit_Test_Case extends WC_Unit_Test_Case {
|
|||
unset( $this->server );
|
||||
$wp_rest_server = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a REST request.
|
||||
*
|
||||
* @param string $url The endpopint url, if it doesn't start with '/' it'll be prepended with '/wc/v3/'.
|
||||
* @param string $verb HTTP verb for the request, default is GET.
|
||||
* @param array|null $body_params Body parameters for the request, null if none are required.
|
||||
* @param array|null $query_params Query string parameters for the request, null if none are required.
|
||||
* @return array Result from the request.
|
||||
*/
|
||||
public function do_rest_request( $url, $verb = 'GET', $body_params = null, $query_params = null ) {
|
||||
if ( '/' !== $url[0] ) {
|
||||
$url = '/wc/v3/' . $url;
|
||||
}
|
||||
|
||||
$request = new WP_REST_Request( $verb, $url );
|
||||
if ( ! is_null( $query_params ) ) {
|
||||
$request->set_query_params( $query_params );
|
||||
}
|
||||
if ( ! is_null( $body_params ) ) {
|
||||
$request->set_body_params( $body_params );
|
||||
}
|
||||
|
||||
return $this->server->dispatch( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a GET REST request.
|
||||
*
|
||||
* @param string $url The endpopint url, if it doesn't start with '/' it'll be prepended with '/wc/v3/'.
|
||||
* @param array|null $query_params Query string parameters for the request, null if none are required.
|
||||
* @return WP_REST_Response The response for the request.
|
||||
*/
|
||||
public function do_rest_get_request( $url, $query_params = null ) {
|
||||
return $this->do_rest_request( $url, 'GET', null, $query_params );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a POST REST request.
|
||||
*
|
||||
* @param string $url The endpopint url, if it doesn't start with '/' it'll be prepended with '/wc/v3/'.
|
||||
* @param array|null $body_params Body parameters for the request, null if none are required.
|
||||
* @param array|null $query_params Query string parameters for the request, null if none are required.
|
||||
* @return array Result from the request.
|
||||
*/
|
||||
public function do_rest_post_request( $url, $body_params = null, $query_params = null ) {
|
||||
return $this->do_rest_request( $url, 'POST', $body_params, $query_params );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a PUT REST request.
|
||||
*
|
||||
* @param string $url The endpopint url, if it doesn't start with '/' it'll be prepended with '/wc/v3/'.
|
||||
* @param array|null $body_params Body parameters for the request, null if none are required.
|
||||
* @param array|null $query_params Query string parameters for the request, null if none are required.
|
||||
* @return array Result from the request.
|
||||
*/
|
||||
public function do_rest_put_request( $url, $body_params = null, $query_params = null ) {
|
||||
return $this->do_rest_request( $url, 'PUT', $body_params, $query_params );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* class WC_REST_Taxes_Controller_Tests.
|
||||
* Taxes Controller tests for V3 REST API.
|
||||
*/
|
||||
class WC_REST_Taxes_Controller_Tests extends WC_REST_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Runs before any test.
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->user = $this->factory->user->create(
|
||||
array(
|
||||
'role' => 'administrator',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_can_create_and_update_tax_rates_with_multiple_cities_and_postcodes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function data_provider_for_test_can_create_and_update_tax_rates_with_multiple_cities_and_postcodes() {
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'city' => 'Osaka;Kyoto;Kobe',
|
||||
'postcode' => '5555;7777;8888',
|
||||
),
|
||||
'create',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'cities' => array(
|
||||
'Osaka',
|
||||
'Kyoto',
|
||||
'Kobe',
|
||||
),
|
||||
'postcodes' => array(
|
||||
'5555',
|
||||
'7777',
|
||||
'8888',
|
||||
),
|
||||
),
|
||||
'create',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'city' => 'Osaka;Kyoto;Kobe',
|
||||
'postcode' => '5555;7777;8888',
|
||||
),
|
||||
'update',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'cities' => array(
|
||||
'Osaka',
|
||||
'Kyoto',
|
||||
'Kobe',
|
||||
),
|
||||
'postcodes' => array(
|
||||
'5555',
|
||||
'7777',
|
||||
'8888',
|
||||
),
|
||||
),
|
||||
'update',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox It is possible to create or update a tax rate passing either "city"/"postcode" (strings) or "cities"/"postcodes" (arrays) fields.
|
||||
*
|
||||
* @dataProvider data_provider_for_test_can_create_and_update_tax_rates_with_multiple_cities_and_postcodes
|
||||
*
|
||||
* @param array $request_body The body for the REST request.
|
||||
* @param string $action The action to perform, 'create' or 'update'.
|
||||
*/
|
||||
public function test_can_create_and_update_tax_rates_with_multiple_cities_and_postcodes( $request_body, $action ) {
|
||||
global $wpdb;
|
||||
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
if ( 'create' === $action ) {
|
||||
$tax_rate_id = null;
|
||||
|
||||
$request_body = array_merge(
|
||||
$request_body,
|
||||
array(
|
||||
'country' => 'JP',
|
||||
'rate' => '1',
|
||||
'name' => 'Fake Tax',
|
||||
)
|
||||
);
|
||||
|
||||
$verb = 'POST';
|
||||
$url = 'taxes';
|
||||
$success_status = 201;
|
||||
} else {
|
||||
$tax_rate_id = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_name' => 'Fake Tax',
|
||||
)
|
||||
);
|
||||
|
||||
WC_Tax::_update_tax_rate_cities( $tax_rate_id, 'Tokyo' );
|
||||
WC_Tax::_update_tax_rate_postcodes( $tax_rate_id, '0000' );
|
||||
|
||||
$verb = 'PUT';
|
||||
$url = 'taxes/' . $tax_rate_id;
|
||||
$success_status = 200;
|
||||
}
|
||||
|
||||
$response = $this->do_rest_request( $url, $verb, $request_body );
|
||||
$this->assertEquals( $success_status, $response->get_status() );
|
||||
if ( ! $tax_rate_id ) {
|
||||
$tax_rate_id = $response->get_data()['id'];
|
||||
}
|
||||
|
||||
$data = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT location_type, GROUP_CONCAT(location_code SEPARATOR ';') as items
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rate_locations
|
||||
WHERE tax_rate_id=%d
|
||||
GROUP BY location_type",
|
||||
$tax_rate_id
|
||||
),
|
||||
OBJECT_K
|
||||
);
|
||||
|
||||
$this->assertEquals( 'OSAKA;KYOTO;KOBE', $data['city']->items );
|
||||
$this->assertEquals( '5555;7777;8888', $data['postcode']->items );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox The response for tax rate(s) includes the "city"/"postcode" (strings) and "cities"/"postcodes" (arrays) fields.
|
||||
*
|
||||
* @testWith [true]
|
||||
* [false]
|
||||
*
|
||||
* @param bool $request_one True to request only one tax, false to request all the taxes.
|
||||
*/
|
||||
public function test_get_tax_response_includes_cities_and_postcodes_as_arrays( $request_one ) {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
$tax_id = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_name' => 'Fake Tax',
|
||||
)
|
||||
);
|
||||
|
||||
WC_Tax::_update_tax_rate_cities( $tax_id, 'Osaka;Kyoto;Kobe' );
|
||||
WC_Tax::_update_tax_rate_postcodes( $tax_id, '5555;7777;8888' );
|
||||
|
||||
if ( $request_one ) {
|
||||
$response = $this->do_rest_get_request( 'taxes/' . $tax_id );
|
||||
} else {
|
||||
$response = $this->do_rest_get_request( 'taxes' );
|
||||
}
|
||||
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$data = $response->get_data();
|
||||
if ( ! $request_one ) {
|
||||
$data = current( $data );
|
||||
}
|
||||
|
||||
$this->assertEquals( 'KOBE', $data['city'] );
|
||||
$this->assertEquals( '8888', $data['postcode'] );
|
||||
$this->assertEquals( array( 'OSAKA', 'KYOTO', 'KOBE' ), $data['cities'] );
|
||||
$this->assertEquals( array( '5555', '7777', '8888' ), $data['postcodes'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox The response of a REST API request for taxes can be sorted by priority.
|
||||
*
|
||||
* @testWith ["asc"]
|
||||
* ["desc"]
|
||||
*
|
||||
* @param string $order_type Sort type, 'asc' or 'desc'.
|
||||
*/
|
||||
public function test_get_tax_response_can_be_sorted_by_priority( $order_type ) {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
$tax_id_1 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_priority' => 1,
|
||||
'tax_rate_name' => 'Fake Tax 1',
|
||||
)
|
||||
);
|
||||
$tax_id_3 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_priority' => 3,
|
||||
'tax_rate_name' => 'Fake Tax 3',
|
||||
)
|
||||
);
|
||||
$tax_id_2 = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_priority' => 2,
|
||||
'tax_rate_name' => 'Fake Tax 2',
|
||||
)
|
||||
);
|
||||
|
||||
$response = $this->do_rest_get_request(
|
||||
'taxes',
|
||||
array(
|
||||
'orderby' => 'priority',
|
||||
'order' => $order_type,
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$data = array_values( $response->get_data() );
|
||||
$ids = array_map(
|
||||
function( $item ) {
|
||||
return $item['id'];
|
||||
},
|
||||
$data
|
||||
);
|
||||
|
||||
if ( 'asc' === $order_type ) {
|
||||
$expected = array( $tax_id_1, $tax_id_2, $tax_id_3 );
|
||||
} else {
|
||||
$expected = array( $tax_id_3, $tax_id_2, $tax_id_1 );
|
||||
}
|
||||
$this->assertEquals( $expected, $ids );
|
||||
}
|
||||
|
||||
/**
|
||||
* @testdox Tax rates can be queries filtering by tax class.
|
||||
*
|
||||
* @testWith ["standard"]
|
||||
* ["reduced-rate"]
|
||||
* ["zero-rate"]
|
||||
*
|
||||
* @param string $class The tax class name to try getting the taxes for.
|
||||
*/
|
||||
public function test_can_get_taxes_filtering_by_class( $class ) {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
$classes = array( 'standard', 'reduced-rate', 'zero-rate' );
|
||||
|
||||
$tax_ids_by_class = array();
|
||||
foreach ( $classes as $class ) {
|
||||
$tax_id = WC_Tax::_insert_tax_rate(
|
||||
array(
|
||||
'tax_rate_country' => 'JP',
|
||||
'tax_rate' => '1',
|
||||
'tax_rate_priority' => 1,
|
||||
'tax_rate_name' => 'Fake Tax',
|
||||
'tax_rate_class' => $class,
|
||||
)
|
||||
);
|
||||
$tax_ids_by_class[ $class ] = $tax_id;
|
||||
}
|
||||
|
||||
$response = $this->do_rest_get_request(
|
||||
'taxes',
|
||||
array(
|
||||
'class' => $class,
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$data = array_values( $response->get_data() );
|
||||
$ids = array_map(
|
||||
function( $item ) {
|
||||
return $item['id'];
|
||||
},
|
||||
$data
|
||||
);
|
||||
|
||||
$this->assertEquals( array( $tax_ids_by_class[ $class ] ), $ids );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue