Fix tests for batches

This commit is contained in:
Mike Jolley 2019-06-14 13:43:29 +01:00
parent d88ab33dda
commit 7f2ea5cc2f
15 changed files with 215 additions and 256 deletions

View File

@ -13,5 +13,8 @@
<testsuite name="WooCommerce REST API Test Suite"> <testsuite name="WooCommerce REST API Test Suite">
<directory suffix=".php">./unit-tests/Tests</directory> <directory suffix=".php">./unit-tests/Tests</directory>
</testsuite> </testsuite>
<testsuite name="v4">
<directory suffix=".php">./unit-tests/Tests/Version4</directory>
</testsuite>
</testsuites> </testsuites>
</phpunit> </phpunit>

View File

@ -24,6 +24,7 @@ use \WP_REST_Controller;
* @version 2.6.0 * @version 2.6.0
*/ */
abstract class AbstractController extends WP_REST_Controller { abstract class AbstractController extends WP_REST_Controller {
use BatchTrait;
/** /**
* Endpoint namespace. * Endpoint namespace.
@ -41,45 +42,56 @@ abstract class AbstractController extends WP_REST_Controller {
/** /**
* Register route for items requests. * Register route for items requests.
*
* @param array $methods Supported methods. read, create.
*/ */
protected function register_items_route() { protected function register_items_route( $methods = [ 'read', 'create' ] ) {
register_rest_route( $routes = [];
$this->namespace, $routes['schema'] = [ $this, 'get_public_item_schema' ];
'/' . $this->rest_base,
array( if ( in_array( 'read', $methods, true ) ) {
array( $routes[] = array(
'methods' => \WP_REST_Server::READABLE, 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ), 'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ), 'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(), 'args' => $this->get_collection_params(),
), );
array( }
if ( in_array( 'create', $methods, true ) ) {
$routes[] = array(
'methods' => \WP_REST_Server::CREATABLE, 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_item' ), 'callback' => array( $this, 'create_item' ),
'permission_callback' => array( $this, 'create_item_permissions_check' ), 'permission_callback' => array( $this, 'create_item_permissions_check' ),
'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ), '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,
$routes,
true true
); );
} }
/** /**
* Register route for item create/get/delete/update requests. * Register route for item create/get/delete/update requests.
*
* @param array $methods Supported methods. read, create.
*/ */
protected function register_item_route() { protected function register_item_route( $methods = [ 'read', 'edit', 'delete' ] ) {
register_rest_route( $routes = [];
$this->namespace, $routes['schema'] = [ $this, 'get_public_item_schema' ];
'/' . $this->rest_base . '/(?P<id>[\d]+)', $routes['args'] = [
array( 'id' => [
'args' => array(
'id' => array(
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ), 'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
'type' => 'integer', 'type' => 'integer',
), ],
), ];
array(
if ( in_array( 'read', $methods, true ) ) {
$routes[] = array(
'methods' => \WP_REST_Server::READABLE, 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ), 'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ), 'permission_callback' => array( $this, 'get_item_permissions_check' ),
@ -90,14 +102,20 @@ abstract class AbstractController extends WP_REST_Controller {
) )
), ),
), ),
), );
array( }
if ( in_array( 'edit', $methods, true ) ) {
$routes[] = array(
'methods' => \WP_REST_Server::EDITABLE, 'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'update_item' ), 'callback' => array( $this, 'update_item' ),
'permission_callback' => array( $this, 'update_item_permissions_check' ), 'permission_callback' => array( $this, 'update_item_permissions_check' ),
'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ), 'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
), );
array( }
if ( in_array( 'delete', $methods, true ) ) {
$routes[] = array(
'methods' => \WP_REST_Server::DELETABLE, 'methods' => \WP_REST_Server::DELETABLE,
'callback' => array( $this, 'delete_item' ), 'callback' => array( $this, 'delete_item' ),
'permission_callback' => array( $this, 'delete_item_permissions_check' ), 'permission_callback' => array( $this, 'delete_item_permissions_check' ),
@ -108,9 +126,13 @@ abstract class AbstractController extends WP_REST_Controller {
'type' => 'boolean', 'type' => 'boolean',
), ),
), ),
), );
'schema' => array( $this, 'get_public_item_schema' ), }
),
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/(?P<id>[\d]+)',
$routes,
true true
); );
} }

View File

@ -13,7 +13,6 @@ defined( 'ABSPATH' ) || exit;
* CRUD Object Controller. * CRUD Object Controller.
*/ */
abstract class AbstractObjectsController extends AbstractController { abstract class AbstractObjectsController extends AbstractController {
use BatchTrait;
/** /**
* If object is hierarchical. * If object is hierarchical.

View File

@ -117,20 +117,7 @@ abstract class AbstractTermsContoller extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -19,23 +19,37 @@ trait BatchTrait {
* @return array Of \WP_Error or \WP_REST_Response. * @return array Of \WP_Error or \WP_REST_Response.
*/ */
public function batch_items( $request ) { public function batch_items( $request ) {
$items = array_filter( $request->get_params() ); $items = $request->get_params();
$limit = $this->check_batch_limit( $items ); $limit = $this->check_batch_limit( $items );
if ( is_wp_error( $limit ) ) { if ( is_wp_error( $limit ) ) {
return $limit; return $limit;
} }
$response = [];
$batches = [ 'create', 'update', 'delete' ]; $batches = [ 'create', 'update', 'delete' ];
$response = [];
foreach ( $batches as $batch ) { foreach ( $batches as $batch ) {
if ( ! isset( $items[ $batch ] ) ) { $response[ $batch ] = $this->{"batch_$batch"}( $this->get_batch_of_items_from_request( $request, $batch ) );
continue;
}
$items[ $batch ] = wp_parse_id_list( $items[ $batch ] );
$response[ $batch ] = $this->{"batch_$batch"}( $items[ $batch ] );
} }
return $response; return array_filter( $response );
}
/**
* Get batch of items from requst.
*
* @param \WP_REST_Request $request Full details about the request.
* @param string $batch_type Batch type; one of create, update, delete.
* @return array
*/
protected function get_batch_of_items_from_request( $request, $batch_type ) {
$params = $request->get_params();
if ( ! isset( $params[ $batch_type ] ) ) {
return array();
}
return array_filter( $params[ $batch_type ] );
} }
/** /**
@ -44,7 +58,9 @@ trait BatchTrait {
* @param \WP_REST_Request $request Full details about the request. * @param \WP_REST_Request $request Full details about the request.
* @return boolean|\WP_Error * @return boolean|\WP_Error
*/ */
abstract public function batch_items_permissions_check( $request ); public function batch_items_permissions_check( $request ) {
return update_items_permissions_check( $request );
}
/** /**
* Register route for batch requests. * Register route for batch requests.
@ -125,13 +141,12 @@ trait BatchTrait {
protected function check_batch_limit( $items ) { protected function check_batch_limit( $items ) {
$limit = apply_filters( 'woocommerce_rest_batch_items_limit', 100, $this->get_normalized_rest_base() ); $limit = apply_filters( 'woocommerce_rest_batch_items_limit', 100, $this->get_normalized_rest_base() );
$total = 0; $total = 0;
$batches = [ 'create', 'update', 'delete' ]; $batches = [ 'create', 'update', 'delete' ];
foreach ( $batches as $batch ) { foreach ( $batches as $batch ) {
if ( ! isset( $items[ $batch ] ) ) { if ( ! isset( $items[ $batch ] ) ) {
continue; continue;
} }
$items[ $batch ] = wp_parse_id_list( $items[ $batch ] );
$total = $total + count( $items[ $batch ] ); $total = $total + count( $items[ $batch ] );
} }
@ -162,40 +177,42 @@ trait BatchTrait {
/** /**
* Batch create items. * Batch create items.
* *
* @param array $items Array of item ids. * @param array $items Array of items.
* @return array Response data. * @return array Response data.
*/ */
protected function batch_create( $items ) { protected function batch_create( $items ) {
$response = []; $batch_response = [];
foreach ( $items as $id ) { foreach ( $items as $item ) {
$item = new \WP_REST_Request( 'POST' ); $request = new \WP_REST_Request( 'POST' );
$item->set_default_params( $this->get_default_params() ); $request->set_default_params( $this->get_default_params() );
$item->set_body_params( $item ); $request->set_body_params( $item );
$item_response = $this->create_item( $item );
$response[] = $this->format_response( $id, $item_response ); $response = $this->create_item( $request );
$batch_response[] = $this->format_response( 0, $response );
} }
return $response; return $batch_response;
} }
/** /**
* Batch update items. * Batch update items.
* *
* @param array $items Array of item ids. * @param array $items Array of items.
* @return array Response data. * @return array Response data.
*/ */
protected function batch_update( $items ) { protected function batch_update( $items ) {
$response = []; $batch_response = [];
foreach ( $items as $id ) { foreach ( $items as $item ) {
$item = new \WP_REST_Request( 'PUT' ); $request = new \WP_REST_Request( 'PUT' );
$item->set_body_params( $item ); $request->set_body_params( $item );
$item_response = $this->update_item( $item );
$response[] = $this->format_response( $id, $item_response ); $response = $this->update_item( $request );
$batch_response[] = $this->format_response( $item['id'], $response );
} }
return $response; return $batch_response;
} }
/** /**
@ -205,21 +222,22 @@ trait BatchTrait {
* @return array Response data. * @return array Response data.
*/ */
protected function batch_delete( $items ) { protected function batch_delete( $items ) {
$response = []; $batch_response = [];
$items = wp_parse_id_list( $items );
foreach ( $items as $id ) { foreach ( $items as $id ) {
$item = new \WP_REST_Request( 'DELETE' ); $request = new \WP_REST_Request( 'DELETE' );
$item->set_query_params( $request->set_query_params(
[ [
'id' => $id, 'id' => $id,
'force' => true, 'force' => true,
] ]
); );
$item_response = $this->delete_item( $item ); $response = $this->delete_item( $request );
$response[] = $this->format_response( $id, $item_response ); $batch_response[] = $this->format_response( $id, $response );
} }
return $response; return $batch_response;
} }
/** /**
@ -237,12 +255,12 @@ trait BatchTrait {
*/ */
global $wp_rest_server; global $wp_rest_server;
if ( is_wp_error( $response ) ) { if ( ! is_wp_error( $response ) ) {
return $this->format_error_response( $response ); return $wp_rest_server->response_to_data( $response, '' );
} else { } else {
return array( return array(
'id' => $id, 'id' => $id,
'error' => $wp_rest_server->response_to_data( $response, '' ), 'error' => $this->format_error_response( $response ),
); );
} }
} }

View File

@ -27,26 +27,7 @@ class CustomerDownloads extends AbstractController {
* Register the routes for customers. * Register the routes for customers.
*/ */
public function register_routes() { public function register_routes() {
register_rest_route( $this->register_items_route( [ 'read' ] );
$this->namespace,
'/' . $this->rest_base,
array(
'args' => array(
'customer_id' => array(
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
'type' => 'integer',
),
),
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
),
true
);
} }
/** /**

View File

@ -115,20 +115,7 @@ class Customers extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -105,20 +105,7 @@ class ProductAttributes extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -113,20 +113,7 @@ class ProductReviews extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -725,37 +725,35 @@ class ProductVariations extends Products {
} }
/** /**
* Bulk create, update and delete items. * Get batch of items from requst.
* *
* @since 3.0.0
* @param \WP_REST_Request $request Full details about the request. * @param \WP_REST_Request $request Full details about the request.
* @return array Of \WP_Error or \WP_REST_Response. * @param string $batch_type Batch type; one of create, update, delete.
* @return array
*/ */
public function batch_items( $request ) { protected function get_batch_of_items_from_request( $request, $batch_type ) {
$items = array_filter( $request->get_params() ); $params = $request->get_params();
$params = $request->get_url_params(); $url_params = $request->get_url_params();
$product_id = $params['product_id']; $product_id = $url_params['product_id'];
$body_params = array();
foreach ( array( 'update', 'create', 'delete' ) as $batch_type ) { if ( ! isset( $params[ $batch_type ] ) ) {
if ( ! empty( $items[ $batch_type ] ) ) { return array();
$injected_items = array(); }
foreach ( $items[ $batch_type ] as $item ) {
$injected_items[] = is_array( $item ) ? array_merge( $items = array_filter( $params[ $batch_type ] );
if ( 'update' === $batch_type || 'create' === $batch_type ) {
foreach ( $items as $key => $item ) {
$items[ $key ] = array_merge(
array( array(
'product_id' => $product_id, 'product_id' => $product_id,
), ),
$item $item
) : $item; );
}
$body_params[ $batch_type ] = $injected_items;
} }
} }
$request = new \WP_REST_Request( $request->get_method() ); return array_filter( $items );
$request->set_body_params( $body_params );
return parent::batch_items( $request );
} }
/** /**

View File

@ -42,19 +42,7 @@ class Settings extends AbstractController {
), ),
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
array(
'methods' => \WP_REST_Server::EDITABLE,
'callback' => array( $this, 'batch_items' ),
'permission_callback' => array( $this, 'update_items_permissions_check' ),
),
'schema' => array( $this, 'get_public_batch_schema' ),
),
true
);
} }
/** /**

View File

@ -274,30 +274,32 @@ class SettingsOptions extends AbstractController {
} }
/** /**
* Bulk create, update and delete items. * Get batch of items from requst.
* *
* @since 3.0.0
* @param \WP_REST_Request $request Full details about the request. * @param \WP_REST_Request $request Full details about the request.
* @return array Of \WP_Error or \WP_REST_Response. * @param string $batch_type Batch type; one of create, update, delete.
* @return array
*/ */
public function batch_items( $request ) { protected function get_batch_of_items_from_request( $request, $batch_type ) {
// Get the request params. $params = $request->get_params();
$items = array_filter( $request->get_params() );
/* if ( ! isset( $params[ $batch_type ] ) ) {
return array();
}
/**
* Since our batch settings update is group-specific and matches based on the route, * Since our batch settings update is group-specific and matches based on the route,
* we inject the URL parameters (containing group) into the batch items * we inject the URL parameters (containing group) into the batch items
*/ */
if ( ! empty( $items['update'] ) ) { $items = array_filter( $params[ $batch_type ] );
$to_update = array();
foreach ( $items['update'] as $item ) { if ( 'update' === $batch_type ) {
$to_update[] = array_merge( $request->get_url_params(), $item ); foreach ( $items as $key => $item ) {
$items[ $key ] = array_merge( $request->get_url_params(), $item );
} }
$request = new \WP_REST_Request( $request->get_method() );
$request->set_body_params( array( 'update' => $to_update ) );
} }
return parent::batch_items( $request ); return array_filter( $items );
} }
/** /**
@ -345,7 +347,6 @@ class SettingsOptions extends AbstractController {
/** /**
* Prepare a single setting object for response. * Prepare a single setting object for response.
* *
* @since 3.0.0
* @param object $item Setting object. * @param object $item Setting object.
* @param \WP_REST_Request $request Request object. * @param \WP_REST_Request $request Request object.
* @return \WP_REST_Response $response Response data. * @return \WP_REST_Response $response Response data.
@ -363,7 +364,6 @@ class SettingsOptions extends AbstractController {
/** /**
* Prepare links for the request. * Prepare links for the request.
* *
* @since 3.0.0
* @param string $setting_id Setting ID. * @param string $setting_id Setting ID.
* @param string $group_id Group ID. * @param string $group_id Group ID.
* @return array Links for the given setting. * @return array Links for the given setting.

View File

@ -89,20 +89,7 @@ class Taxes extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -110,20 +110,7 @@ class Webhooks extends AbstractController {
true true
); );
register_rest_route( $this->register_batch_route();
$this->namespace,
'/' . $this->rest_base . '/batch',
array(
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' ),
),
true
);
} }
/** /**

View File

@ -12,7 +12,7 @@ defined( 'ABSPATH' ) || exit;
/** /**
* WC Tests API Data * WC Tests API Data
*/ */
class Data { class Data extends \WC_REST_Unit_Test_Case {
/** /**
* Endpoints. * Endpoints.
@ -21,6 +21,34 @@ class Data {
*/ */
protected $endpoint = '/wc/v4/data'; protected $endpoint = '/wc/v4/data';
/**
* User variable.
*
* @var WP_User
*/
protected static $user;
/**
* Setup once before running tests.
*
* @param object $factory Factory object.
*/
public static function wpSetUpBeforeClass( $factory ) {
self::$user = $factory->user->create(
array(
'role' => 'administrator',
)
);
}
/**
* Setup test class.
*/
public function setUp() {
parent::setUp();
wp_set_current_user( self::$user );
}
/** /**
* Test that the list of data endpoints includes download-ips. * Test that the list of data endpoints includes download-ips.
*/ */