Update API resource classes
Change method naming to snake_case and implement initial `current_user_can()` permission checks
This commit is contained in:
parent
9c7791e3d8
commit
a13a95e452
|
@ -29,24 +29,29 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public function registerRoutes( $routes ) {
|
||||
public function register_routes( $routes ) {
|
||||
|
||||
# GET|POST /coupons
|
||||
$routes[ $this->base ] = array(
|
||||
array( array( $this, 'getCoupons' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'createCoupon' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'get_coupons' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'create_coupon' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
);
|
||||
|
||||
# GET /coupons/count
|
||||
$routes[ $this->base . '/count'] = array(
|
||||
array( array( $this, 'getCouponsCount' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_coupons_count' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET|PUT|DELETE /coupons/<id>
|
||||
$routes[ $this->base . '/(?P<id>\d+)' ] = array(
|
||||
array( array( $this, 'getCoupon' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'editCoupon' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'deleteCoupon' ), WC_API_Server::DELETABLE ),
|
||||
array( array( $this, 'get_coupon' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'edit_coupon' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'delete_coupon' ), WC_API_Server::DELETABLE ),
|
||||
);
|
||||
|
||||
# GET /coupons/<code> TODO: should looking up coupon codes containing spaces or dashes be supported? OR all-digit coupon codes
|
||||
$routes[ $this->base . '/(?P<code>\w+)' ] = array(
|
||||
array( array( $this, 'get_coupon_by_code' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
return $routes;
|
||||
|
@ -55,36 +60,27 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
/**
|
||||
* Get all coupons
|
||||
*
|
||||
* @TODO should we support an extra "code" param for lookup instead of "q" which searches both title & description?
|
||||
*
|
||||
* @since 2.1
|
||||
* @param string $fields
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param string $q search terms
|
||||
* @param int $limit coupons per response
|
||||
* @param int $offset
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getCoupons( $fields = null, $created_at_min = null, $created_at_max = null, $q = null, $limit = null, $offset = null ) {
|
||||
public function get_coupons( $fields = null, $filter = array() ) {
|
||||
|
||||
$request_args = array(
|
||||
'created_at_min' => $created_at_min,
|
||||
'created_at_max' => $created_at_max,
|
||||
'q' => $q,
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
);
|
||||
|
||||
$query = $this->queryCoupons( $request_args );
|
||||
$query = $this->query_coupons( $filter );
|
||||
|
||||
$coupons = array();
|
||||
|
||||
foreach( $query->posts as $coupon_id ) {
|
||||
|
||||
$coupons[] = $this->getCoupon( $coupon_id, $fields );
|
||||
if ( ! $this->is_readable( $coupon_id ) )
|
||||
continue;
|
||||
|
||||
$coupons[] = $this->get_coupon( $coupon_id, $fields );
|
||||
}
|
||||
|
||||
$this->server->query_navigation_headers( $query );
|
||||
|
||||
return array( 'coupons' => $coupons );
|
||||
}
|
||||
|
||||
|
@ -94,25 +90,29 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* @since 2.1
|
||||
* @param int $id the coupon ID
|
||||
* @param string $fields fields to include in response
|
||||
* @return array
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function getCoupon( $id, $fields = null ) {
|
||||
public function get_coupon( $id, $fields = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$id = $this->validate_request( $id, 'shop_coupon', 'read' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// get the coupon code
|
||||
$code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE id = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $id ) );
|
||||
|
||||
if ( ! $code )
|
||||
return new WP_Error( 'wc_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_null( $code ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_coupon_id', __( 'Invalid coupon ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
$coupon = new WC_Coupon( $code );
|
||||
|
||||
// TODO: how to implement coupon meta?
|
||||
$coupon_data = array(
|
||||
'id' => $coupon->id,
|
||||
'code' => $coupon->code,
|
||||
'type' => $coupon->type,
|
||||
'amount' => $coupon->amount, // TODO: should this be formatted?
|
||||
'amount' => (string) number_format( $coupon->amount, 2 ),
|
||||
'individual_use' => $coupon->individual_use,
|
||||
'product_ids' => $coupon->product_ids,
|
||||
'exclude_product_ids' => $coupon->exclude_product_ids,
|
||||
|
@ -137,17 +137,36 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* Get the total number of coupons
|
||||
*
|
||||
* @since 2.1
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getCouponsCount( $created_at_min = null, $created_at_max = null ) {
|
||||
public function get_coupons_count( $filter = array() ) {
|
||||
|
||||
$query = $this->queryCoupons( array( 'created_at_min' => $created_at_min, 'created_at_max' => $created_at_max ) );
|
||||
$query = $this->query_coupons( $filter );
|
||||
|
||||
// TODO: permissions?
|
||||
|
||||
return array( 'count' => $query->found_posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the coupon for the given code
|
||||
*
|
||||
* @param string $code the coupon code
|
||||
* @param string $fields fields to include in response
|
||||
* @return int|WP_Error
|
||||
*/
|
||||
public function get_coupon_by_code( $code, $fields = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish'", $code ) );
|
||||
|
||||
if ( is_null( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_coupon_code', __( 'Invalid coupon code', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
return $this->get_coupon( $id, $fields );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a coupon
|
||||
*
|
||||
|
@ -155,7 +174,9 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function createCoupon( $data ) {
|
||||
public function create_coupon( $data ) {
|
||||
|
||||
// TODO: permissions check
|
||||
|
||||
// TODO: implement - what's the minimum set of data required?
|
||||
|
||||
|
@ -170,10 +191,15 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function editCoupon( $id, $data ) {
|
||||
public function edit_coupon( $id, $data ) {
|
||||
|
||||
$id = $this->validate_request( $id, 'shop_coupon', 'edit' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// TODO: implement
|
||||
return $this->getCoupon( $id );
|
||||
return $this->get_coupon( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -184,9 +210,14 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
* @param bool $force true to permanently delete coupon, false to move to trash
|
||||
* @return array
|
||||
*/
|
||||
public function deleteCoupon( $id, $force = false ) {
|
||||
public function delete_coupon( $id, $force = false ) {
|
||||
|
||||
return $this->deleteResource( $id, 'coupon', ( 'true' === $force ) );
|
||||
$id = $this->validate_request( $id, 'shop_coupon', 'delete' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
return $this->delete( $id, 'shop_coupon', ( 'true' === $force ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -194,21 +225,18 @@ class WC_API_Coupons extends WC_API_Resource {
|
|||
*
|
||||
* @since 2.1
|
||||
* @param array $args request arguments for filtering query
|
||||
* @return array
|
||||
* @return WP_Query
|
||||
*/
|
||||
private function queryCoupons( $args ) {
|
||||
private function query_coupons( $args ) {
|
||||
|
||||
// set base query arguments
|
||||
$query_args = array(
|
||||
'fields' => 'ids',
|
||||
'post_type' => 'shop_coupon',
|
||||
'post_status' => 'publish',
|
||||
'orderby' => 'title',
|
||||
);
|
||||
|
||||
$query_args = $this->mergeQueryArgs( $query_args, $args );
|
||||
|
||||
// TODO: navigation/total count headers for pagination
|
||||
$query_args = $this->merge_query_args( $query_args, $args );
|
||||
|
||||
return new WP_Query( $query_args );
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
parent::__construct( $server );
|
||||
|
||||
// add customer data to order responses
|
||||
add_filter( 'woocommerce_api_order_response', array( $this, 'addCustomerData' ), 10, 2 );
|
||||
add_filter( 'woocommerce_api_order_response', array( $this, 'add_customer_data' ), 10, 2 );
|
||||
|
||||
// modify WP_User_Query to support created_at date filtering
|
||||
add_action( 'pre_user_query', array( $this, 'modify_user_query' ) );
|
||||
}
|
||||
|
@ -52,29 +53,29 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public function registerRoutes( $routes ) {
|
||||
public function register_routes( $routes ) {
|
||||
|
||||
# GET|POST /customers
|
||||
$routes[ $this->base ] = array(
|
||||
array( array( $this, 'getCustomers' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'createCustomer' ), WC_API_SERVER::CREATABLE | WC_API_SERVER::ACCEPT_DATA ),
|
||||
array( array( $this, 'get_customers' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'create_customer' ), WC_API_SERVER::CREATABLE | WC_API_SERVER::ACCEPT_DATA ),
|
||||
);
|
||||
|
||||
# GET /customers/count
|
||||
$routes[ $this->base . '/count'] = array(
|
||||
array( array( $this, 'getCustomersCount' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'get_customers_count' ), WC_API_SERVER::READABLE ),
|
||||
);
|
||||
|
||||
# GET|PUT|DELETE /customers/<id>
|
||||
$routes[ $this->base . '/(?P<id>\d+)' ] = array(
|
||||
array( array( $this, 'getCustomer' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'editCustomer' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),
|
||||
array( array( $this, 'deleteCustomer' ), WC_API_SERVER::DELETABLE ),
|
||||
array( array( $this, 'get_customer' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'edit_customer' ), WC_API_SERVER::EDITABLE | WC_API_SERVER::ACCEPT_DATA ),
|
||||
array( array( $this, 'delete_customer' ), WC_API_SERVER::DELETABLE ),
|
||||
);
|
||||
|
||||
# GET /customers/<id>/orders
|
||||
$routes[ $this->base . '/(?P<id>\d+)/orders' ] = array(
|
||||
array( array( $this, 'getCustomerOrders' ), WC_API_SERVER::READABLE ),
|
||||
array( array( $this, 'get_customer_orders' ), WC_API_SERVER::READABLE ),
|
||||
);
|
||||
|
||||
return $routes;
|
||||
|
@ -83,60 +84,48 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
/**
|
||||
* Get all customers
|
||||
*
|
||||
* @TODO support created_at_min/created_at_max with pre_user_query filter
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $fields
|
||||
* @param string $q search terms
|
||||
* @param int $limit coupons per response
|
||||
* @param int $offset
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getCustomers( $fields = null, $q = null, $limit = null, $offset = null ) {
|
||||
public function get_customers( $fields = null, $filter = array() ) {
|
||||
|
||||
$request_args = array(
|
||||
'q' => $q,
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
);
|
||||
|
||||
$query = $this->queryCustomers( $request_args );
|
||||
$query = $this->query_customers( $filter );
|
||||
|
||||
$customers = array();
|
||||
|
||||
foreach( $query->results as $user_id ) {
|
||||
|
||||
$customers[] = $this->getCustomer( $user_id, $fields );
|
||||
if ( ! $this->is_readable( $user_id ) )
|
||||
continue;
|
||||
|
||||
$customers[] = $this->get_customer( $user_id, $fields );
|
||||
}
|
||||
|
||||
// TODO: add navigation/total count headers for pagination
|
||||
|
||||
return array( 'customers' => $customers );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the customer for the given ID
|
||||
*
|
||||
* @TODO: implement customer meta
|
||||
*
|
||||
* @since 2.1
|
||||
* @param int $id the customer ID
|
||||
* @param string $fields
|
||||
* @return array
|
||||
*/
|
||||
public function getCustomer( $id, $fields = null ) {
|
||||
public function get_customer( $id, $fields = null ) {
|
||||
global $wpdb;
|
||||
|
||||
$id = absint( $id );
|
||||
$id = $this->validate_request( $id, 'customer', 'read' );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', __( 'Invalid customer ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// non-existent IDs return a valid WP_User object with the user ID = 0
|
||||
$customer = new WP_User( $id );
|
||||
|
||||
if ( 0 === $customer->ID )
|
||||
return new WP_Error( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
// get info about user's last order
|
||||
$last_order = $wpdb->get_row( "SELECT id, post_date
|
||||
FROM $wpdb->posts AS posts
|
||||
|
@ -157,7 +146,7 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
'last_order_id' => is_object( $last_order ) ? $last_order->id : null,
|
||||
'last_order_date' => is_object( $last_order ) ? $last_order->post_date : null,
|
||||
'orders_count' => $customer->_order_count,
|
||||
'total_spent' => $customer->_money_spent,
|
||||
'total_spent' => (string) number_format( $customer->_money_spent, 2 ),
|
||||
'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
|
||||
'billing_address' => array(
|
||||
'first_name' => $customer->billing_first_name,
|
||||
|
@ -191,14 +180,15 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
/**
|
||||
* Get the total number of customers
|
||||
*
|
||||
* @TODO support created_at_min/created_at_max with pre_user_query filter
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getCustomersCount() {
|
||||
public function get_customers_count( $filter = array() ) {
|
||||
|
||||
$query = $this->queryCustomers();
|
||||
$query = $this->query_customers( $filter );
|
||||
|
||||
// TODO: permissions?
|
||||
|
||||
return array( 'count' => $query->get_total() );
|
||||
}
|
||||
|
@ -211,10 +201,12 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function createCustomer( $data ) {
|
||||
public function create_customer( $data ) {
|
||||
|
||||
// TODO: implement - what's the minimum set of data required?
|
||||
// woocommerce_create_new_customer()
|
||||
if ( ! current_user_can( 'create_users' ) )
|
||||
return new WP_Error( 'woocommerce_api_user_cannot_create_customer', __( 'You do not have permission to create this customer', 'woocommerce' ), array( 'status' => 401 ) );
|
||||
|
||||
// TODO: implement - woocommerce_create_new_customer()
|
||||
|
||||
return array();
|
||||
}
|
||||
|
@ -227,10 +219,16 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function editCustomer( $id, $data ) {
|
||||
public function edit_customer( $id, $data ) {
|
||||
|
||||
$id = $this->validate_request( $id, 'customer', 'edit' );
|
||||
|
||||
if ( ! is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// TODO: implement
|
||||
return $this->getCustomer( $id );
|
||||
|
||||
return $this->get_customer( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -240,43 +238,40 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* @param int $id the customer ID
|
||||
* @return array
|
||||
*/
|
||||
public function deleteCustomer( $id ) {
|
||||
public function delete_customer( $id ) {
|
||||
|
||||
return $this->deleteResource( $id, 'customer' );
|
||||
$id = $this->validate_request( $id, 'customer', 'delete' );
|
||||
|
||||
if ( ! is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
return $this->delete( $id, 'customer' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the orders for a customer
|
||||
*
|
||||
* @TODO should this support the same parameters as getOrders call? e.g. fields, created_at, pagination, etc
|
||||
*
|
||||
* @since 2.1
|
||||
* @param int $id the customer ID
|
||||
* @param string $fields fields to include in response
|
||||
* @return array
|
||||
*/
|
||||
public function getCustomerOrders( $id ) {
|
||||
public function get_customer_orders( $id, $fields = null ) {
|
||||
global $wpdb;
|
||||
|
||||
// TODO: DRY this along with duplicate code in getCustomer()
|
||||
$id = absint( $id );
|
||||
$id = $this->validate_request( $id, 'customer', 'read' );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', __( 'Invalid customer ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// non-existent IDs return a valid WP_User object with the user ID = 0
|
||||
$customer = new WP_User( $id );
|
||||
|
||||
if ( 0 === $customer->ID )
|
||||
return new WP_Error( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
$order_ids = $wpdb->get_col( "SELECT id
|
||||
$order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id
|
||||
FROM $wpdb->posts AS posts
|
||||
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
|
||||
WHERE meta.meta_key = '_customer_user'
|
||||
AND meta.meta_value = {$id}
|
||||
AND meta.meta_value = '%s'
|
||||
AND posts.post_type = 'shop_order'
|
||||
AND posts.post_status = 'publish'
|
||||
" );
|
||||
", $id ) );
|
||||
|
||||
if ( empty( $order_ids ) )
|
||||
return array( 'orders' => array() );
|
||||
|
@ -284,7 +279,7 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
$orders = array();
|
||||
|
||||
foreach ( $order_ids as $order_id ) {
|
||||
$orders[] = WC()->api->WC_API_Orders->getOrder( $order_id );
|
||||
$orders[] = WC()->api->WC_API_Orders->get_order( $order_id, $fields );
|
||||
}
|
||||
|
||||
return array( 'orders' => $orders );
|
||||
|
@ -297,18 +292,15 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* @param array $args request arguments for filtering query
|
||||
* @return array
|
||||
*/
|
||||
private function queryCustomers( $args = array() ) {
|
||||
private function query_customers( $args = array() ) {
|
||||
|
||||
// set base query arguments
|
||||
$query_args = array(
|
||||
'fields' => 'ID',
|
||||
'role' => 'customer',
|
||||
'orderby' => 'registered',
|
||||
'order' => 'DESC',
|
||||
);
|
||||
|
||||
// TODO: refactor WP_API_Base::mergeQueryVars to support user query args
|
||||
|
||||
if ( ! empty( $args['q'] ) )
|
||||
$query_args['search'] = $args['q'];
|
||||
|
||||
|
@ -318,7 +310,6 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
if ( ! empty( $args['offset'] ) )
|
||||
$query_args['offset'] = $args['offset'];
|
||||
|
||||
// TODO: navigation/total count headers for pagination
|
||||
if ( ! empty( $args['created_at_min'] ) )
|
||||
$this->created_at_min = $args['created_at_min'];
|
||||
|
||||
|
@ -333,14 +324,12 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
/**
|
||||
* Add customer data to orders
|
||||
*
|
||||
* @TODO should guest orders return more than 'guest'?
|
||||
*
|
||||
* @since 2.1
|
||||
* @param $order_data
|
||||
* @param $order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function addCustomerData( $order_data, $order ) {
|
||||
public function add_customer_data( $order_data, $order ) {
|
||||
|
||||
if ( 0 == $order->customer_user ) {
|
||||
|
||||
|
@ -348,7 +337,7 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
|
||||
} else {
|
||||
|
||||
$order_data['customer'] = $this->getCustomer( $order->customer_user );
|
||||
$order_data['customer'] = $this->get_customer( $order->customer_user );
|
||||
}
|
||||
|
||||
return $order_data;
|
||||
|
@ -373,6 +362,7 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
* Wrapper for @see get_avatar() which doesn't simply return
|
||||
* the URL so we need to pluck it from the HTML img tag
|
||||
*
|
||||
* @since 2.1
|
||||
* @param string $email the customer's email
|
||||
* @return string the URL to the customer's avatar
|
||||
*/
|
||||
|
@ -382,9 +372,72 @@ class WC_API_Customers extends WC_API_Resource {
|
|||
|
||||
$dom->loadHTML( get_avatar( $email ) );
|
||||
|
||||
$url = $dom->getElementsByTagName('img')->item(0)->getAttribute('src');
|
||||
$url = $dom->getElementsByTagName( 'img' )->item( 0 )->getAttribute( 'src' );
|
||||
|
||||
return ( ! empty( $url ) ) ? $url : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the request by checking:
|
||||
*
|
||||
* 1) the ID is a valid integer
|
||||
* 2) the ID returns a valid WP_User
|
||||
* 3) the current user has the proper permissions
|
||||
*
|
||||
* @since 2.1
|
||||
* @see WC_API_Resource::validate_request()
|
||||
* @param string|int $id the customer ID
|
||||
* @param string $type the request type, unused because this method overrides the parent class
|
||||
* @param string $context the context of the request, either `read`, `edit` or `delete`
|
||||
* @return int|WP_Error valid user ID or WP_Error if any of the checks fails
|
||||
*/
|
||||
protected function validate_request( $id, $type, $context ) {
|
||||
|
||||
$id = absint( $id );
|
||||
|
||||
// validate ID
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_customer_id', __( 'Invalid customer ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
// non-existent IDs return a valid WP_User object with the user ID = 0
|
||||
$customer = new WP_User( $id );
|
||||
|
||||
if ( 0 === $customer->ID )
|
||||
return new WP_Error( 'woocommerce_api_invalid_customer', __( 'Invalid customer', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
// validate permissions
|
||||
switch ( $context ) {
|
||||
|
||||
case 'read':
|
||||
if ( ! current_user_can( 'list_users' ) )
|
||||
return new WP_Error( 'woocommerce_api_user_cannot_read_customer', __( 'You do not have permission to read this customer', 'woocommerce' ), array( 'status' => 401 ) );
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
if ( ! current_user_can( 'edit_users' ) )
|
||||
return new WP_Error( 'woocommerce_api_user_cannot_edit_customer', __( 'You do not have permission to edit this customer', 'woocommerce' ), array( 'status' => 401 ) );
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ( ! current_user_can( 'delete_users' ) )
|
||||
return new WP_Error( 'woocommerce_api_user_cannot_delete_customer', __( 'You do not have permission to delete this customer', 'woocommerce' ), array( 'status' => 401 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user can read users
|
||||
*
|
||||
* @since 2.1
|
||||
* @see WC_API_Resource::is_readable()
|
||||
* @param int|WP_Post $post unused
|
||||
* @return bool true if the current user can read users, false otherwise
|
||||
*/
|
||||
protected function is_readable( $post ) {
|
||||
|
||||
return current_user_can( 'list_users' );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
/**
|
||||
* Register the routes for this class
|
||||
*
|
||||
* GET|POST /orders
|
||||
* GET /orders
|
||||
* GET /orders/count
|
||||
* GET|PUT|DELETE /orders/<id>
|
||||
* GET /orders/<id>/notes
|
||||
|
@ -29,29 +29,28 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public function registerRoutes( $routes ) {
|
||||
public function register_routes( $routes ) {
|
||||
|
||||
# GET|POST /orders
|
||||
# GET /orders
|
||||
$routes[ $this->base ] = array(
|
||||
array( array( $this, 'getOrders' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'createOrder' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'get_orders' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET /orders/count
|
||||
$routes[ $this->base . '/count'] = array(
|
||||
array( array( $this, 'getOrdersCount' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_orders_count' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET|PUT|DELETE /orders/<id>
|
||||
$routes[ $this->base . '/(?P<id>\d+)' ] = array(
|
||||
array( array( $this, 'getOrder' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'editOrder' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'deleteOrder' ), WC_API_Server::DELETABLE ),
|
||||
array( array( $this, 'get_order' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'edit_order' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'delete_order' ), WC_API_Server::DELETABLE ),
|
||||
);
|
||||
|
||||
# GET /orders/<id>/notes
|
||||
$routes[ $this->base . '/(?P<id>\d+)/notes' ] = array(
|
||||
array( array( $this, 'getOrderNotes' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_order_notes' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
return $routes;
|
||||
|
@ -61,39 +60,27 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* Get all orders
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $fields
|
||||
* @param string $fields
|
||||
* @param array $filter
|
||||
* @param string $status
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param string $updated_at_min
|
||||
* @param string $updated_at_max
|
||||
* @param string $q search terms
|
||||
* @param int $limit coupons per response
|
||||
* @param int $offset
|
||||
* @return array
|
||||
*/
|
||||
public function getOrders( $fields = array(), $status = null, $created_at_min = null, $created_at_max = null, $updated_at_min = null, $updated_at_max = null, $q = null, $limit = null, $offset = null ) {
|
||||
public function get_orders( $fields = null, $filter = array(), $status = null ) {
|
||||
|
||||
$request_args = array(
|
||||
'status' => $status,
|
||||
'created_at_min' => $created_at_min,
|
||||
'created_at_max' => $created_at_max,
|
||||
'updated_at_min' => $updated_at_min,
|
||||
'updated_at_max' => $updated_at_max,
|
||||
'q' => $q,
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
);
|
||||
if ( ! empty( $status ) )
|
||||
$filter['status'] = $status;
|
||||
|
||||
$query = $this->queryOrders( $request_args );
|
||||
$query = $this->query_orders( $filter );
|
||||
|
||||
$orders = array();
|
||||
|
||||
foreach( $query->posts as $order_id ) {
|
||||
|
||||
$orders[] = $this->getOrder( $order_id, $fields );
|
||||
$orders[] = $this->get_order( $order_id, $fields );
|
||||
}
|
||||
|
||||
$this->server->query_navigation_headers( $query );
|
||||
|
||||
return array( 'orders' => $orders );
|
||||
}
|
||||
|
||||
|
@ -106,20 +93,16 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* @param array $fields
|
||||
* @return array
|
||||
*/
|
||||
public function getOrder( $id, $fields = null ) {
|
||||
public function get_order( $id, $fields = null ) {
|
||||
|
||||
$id = absint( $id );
|
||||
// ensure order ID is valid & user has permission to read
|
||||
$id = $this->validate_request( $id, 'shop_order', 'read' );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', __( 'Invalid order ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// invalid IDs return a valid WC_Order object with customer_user equal to a blank string
|
||||
$order = new WC_Order( $id );
|
||||
|
||||
// TODO: check post type instead or abstract into generic object/permissions check in base class @see self::getOrderNotes()
|
||||
if ( '' === $order->customer_user )
|
||||
return new WP_Error( 'woocommerce_api_invalid_order', __( 'Invalid order', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
$order_data = array(
|
||||
'id' => $order->id,
|
||||
'order_number' => $order->get_order_number(),
|
||||
|
@ -128,15 +111,15 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
'completed_at' => $order->completed_date,
|
||||
'status' => $order->status,
|
||||
'currency' => $order->order_currency,
|
||||
'total' => $order->get_total(),
|
||||
'total_line_items_quantity' => $order->get_item_count(),
|
||||
'total_tax' => $order->get_total_tax(),
|
||||
'total_shipping' => $order->get_total_shipping(),
|
||||
'cart_tax' => $order->get_cart_tax(),
|
||||
'shipping_tax' => $order->get_shipping_tax(),
|
||||
'total_discount' => $order->get_total_discount(),
|
||||
'cart_discount' => $order->get_cart_discount(),
|
||||
'order_discount' => $order->get_order_discount(),
|
||||
'total' => (string) $order->get_total(),
|
||||
'total_line_items_quantity' => (string) $order->get_item_count(),
|
||||
'total_tax' => (string) $order->get_total_tax(),
|
||||
'total_shipping' => (string) $order->get_total_shipping(),
|
||||
'cart_tax' => (string) $order->get_cart_tax(),
|
||||
'shipping_tax' => (string) $order->get_shipping_tax(),
|
||||
'total_discount' => (string) $order->get_total_discount(),
|
||||
'cart_discount' => (string) $order->get_cart_discount(),
|
||||
'order_discount' => (string) $order->get_order_discount(),
|
||||
'shipping_methods' => $order->get_shipping_method(),
|
||||
'payment_details' => array(
|
||||
'method_id' => $order->payment_method,
|
||||
|
@ -181,10 +164,10 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
|
||||
$order_data['line_items'][] = array(
|
||||
'id' => $item_id,
|
||||
'subtotal' => $order->get_line_subtotal( $item ),
|
||||
'total' => $order->get_line_total( $item ),
|
||||
'total_tax' => $order->get_line_tax( $item ),
|
||||
'quantity' => $item['qty'],
|
||||
'subtotal' => (string) $order->get_line_subtotal( $item ),
|
||||
'total' => (string) $order->get_line_total( $item ),
|
||||
'total_tax' => (string) $order->get_line_tax( $item ),
|
||||
'quantity' => (string) $item['qty'],
|
||||
'tax_class' => ( ! empty( $item['tax_class'] ) ) ? $item['tax_class'] : null,
|
||||
'name' => $item['name'],
|
||||
'product_id' => ( isset( $product->variation_id ) ) ? $product->variation_id : $product->id,
|
||||
|
@ -199,7 +182,7 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
'id' => $shipping_item_id,
|
||||
'method_id' => $shipping_item['method_id'],
|
||||
'method_title' => $shipping_item['name'],
|
||||
'total' => $shipping_item['cost'],
|
||||
'total' => (string) number_format( $shipping_item['cost'], 2 )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -209,7 +192,7 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
$order_data['tax_lines'][] = array(
|
||||
'code' => $tax_code,
|
||||
'title' => $tax->label,
|
||||
'total' => $tax->amount,
|
||||
'total' => (string) $tax->amount,
|
||||
'compound' => (bool) $tax->is_compound,
|
||||
);
|
||||
}
|
||||
|
@ -221,8 +204,8 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
'id' => $fee_item_id,
|
||||
'title' => $fee_item['name'],
|
||||
'tax_class' => ( ! empty( $fee_item['tax_class'] ) ) ? $fee_item['tax_class'] : null,
|
||||
'total' => $order->get_line_total( $fee_item ),
|
||||
'total_tax' => $order->get_line_tax( $fee_item ),
|
||||
'total' => (string) $order->get_line_total( $fee_item ),
|
||||
'total_tax' => (string) $order->get_line_tax( $fee_item ),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -232,7 +215,7 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
$order_data['coupon_lines'] = array(
|
||||
'id' => $coupon_item_id,
|
||||
'code' => $coupon_item['name'],
|
||||
'amount' => $coupon_item['discount_amount'],
|
||||
'amount' => (string) number_format( $coupon_item['discount_amount'], 2),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -251,40 +234,21 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
*
|
||||
* @since 2.1
|
||||
* @param string $status
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param string $updated_at_min
|
||||
* @param string $updated_at_max
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getOrdersCount( $status = null, $created_at_min = null, $created_at_max = null, $updated_at_min = null, $updated_at_max = null ) {
|
||||
public function get_orders_count( $status = null, $filter = array() ) {
|
||||
|
||||
$request_args = array(
|
||||
'status' => $status,
|
||||
'created_at_min' => $created_at_min,
|
||||
'created_at_max' => $created_at_max,
|
||||
'updated_at_min' => $updated_at_min,
|
||||
'updated_at_max' => $updated_at_max,
|
||||
);
|
||||
if ( ! empty( $status ) )
|
||||
$filter['status'] = $status;
|
||||
|
||||
$query = $this->queryOrders( $request_args );
|
||||
$query = $this->query_orders( $filter );
|
||||
|
||||
// TODO: permissions?
|
||||
|
||||
return array( 'count' => $query->found_posts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an order
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function createOrder( $data ) {
|
||||
|
||||
// TODO: implement - a woocommerce_create_new_order() function would be great
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit an order
|
||||
|
@ -294,11 +258,16 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function editOrder( $id, $data ) {
|
||||
public function edit_order( $id, $data ) {
|
||||
|
||||
$id = $this->validate_request( $id, 'shop_order', 'write' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// TODO: implement
|
||||
|
||||
return $this->getOrder( $id );
|
||||
return $this->get_order( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -309,9 +278,11 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* @param bool $force true to permanently delete order, false to move to trash
|
||||
* @return array
|
||||
*/
|
||||
public function deleteOrder( $id, $force = false ) {
|
||||
public function delete_order( $id, $force = false ) {
|
||||
|
||||
return $this->deleteResource( $id, 'order', ( 'true' === $force ) );
|
||||
$id = $this->validate_request( $id, 'shop_order', 'delete' );
|
||||
|
||||
return $this->delete( $id, 'order', ( 'true' === $force ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,17 +290,13 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOrderNotes( $id ) {
|
||||
public function get_order_notes( $id ) {
|
||||
|
||||
$id = absint( $id );
|
||||
// ensure ID is valid order ID
|
||||
$id = $this->validate_request( $id, 'order', 'read' );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', __( 'Invalid order ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
$post = get_post( $id, ARRAY_A );
|
||||
|
||||
if ( 'shop_order' !== $post['post_type'] )
|
||||
return new WP_Error( 'woocommerce_api_invalid_order', __( 'Invalid order', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
$args = array(
|
||||
'post_id' => $id,
|
||||
|
@ -337,7 +304,6 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
'type' => 'order_note'
|
||||
);
|
||||
|
||||
|
||||
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments', 10, 1 ) );
|
||||
|
||||
$notes = get_comments( $args );
|
||||
|
@ -349,7 +315,7 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
foreach ( $notes as $note ) {
|
||||
|
||||
$order_notes[] = array(
|
||||
'created_at' => $note->comment_date,
|
||||
'created_at' => $note->comment_date_gmt, // TODO: date formatting
|
||||
'note' => $note->comment_content,
|
||||
'customer_note' => get_comment_meta( $note->comment_ID, 'is_customer_note', true ) ? true : false,
|
||||
);
|
||||
|
@ -363,9 +329,9 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
*
|
||||
* @since 2.1
|
||||
* @param array $args request arguments for filtering query
|
||||
* @return array
|
||||
* @return WP_Query
|
||||
*/
|
||||
private function queryOrders( $args ) {
|
||||
private function query_orders( $args ) {
|
||||
|
||||
// set base query arguments
|
||||
$query_args = array(
|
||||
|
@ -382,15 +348,15 @@ class WC_API_Orders extends WC_API_Resource {
|
|||
$query_args['tax_query'] = array(
|
||||
array(
|
||||
'taxonomy' => 'shop_order_status',
|
||||
'field' => 'slug',
|
||||
'terms' => $statuses,
|
||||
'field' => 'slug',
|
||||
'terms' => $statuses,
|
||||
),
|
||||
);
|
||||
|
||||
unset( $args['status'] );
|
||||
}
|
||||
|
||||
$query_args = $this->mergeQueryArgs( $query_args, $args );
|
||||
|
||||
// TODO: navigation/total count headers for pagination
|
||||
$query_args = $this->merge_query_args( $query_args, $args );
|
||||
|
||||
return new WP_Query( $query_args );
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ class WC_API_Products extends WC_API_Resource {
|
|||
/**
|
||||
* Register the routes for this class
|
||||
*
|
||||
* GET|POST /products
|
||||
* GET /products
|
||||
* GET /products/count
|
||||
* GET|PUT|DELETE /products/<id>
|
||||
* GET /products/<id>/reviews
|
||||
|
@ -29,29 +29,28 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public function registerRoutes( $routes ) {
|
||||
public function register_routes( $routes ) {
|
||||
|
||||
# GET|POST /products
|
||||
# GET /products
|
||||
$routes[ $this->base ] = array(
|
||||
array( array( $this, 'getProducts' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'createProduct' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'get_products' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET /products/count
|
||||
$routes[ $this->base . '/count'] = array(
|
||||
array( array( $this, 'getProductsCount' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_products_count' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET|PUT|DELETE /products/<id>
|
||||
$routes[ $this->base . '/(?P<id>\d+)' ] = array(
|
||||
array( array( $this, 'getProduct' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'editProduct' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'deleteProduct' ), WC_API_Server::DELETABLE ),
|
||||
array( array( $this, 'get_product' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'edit_product' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),
|
||||
array( array( $this, 'delete_product' ), WC_API_Server::DELETABLE ),
|
||||
);
|
||||
|
||||
# GET /products/<id>/reviews
|
||||
$routes[ $this->base . '/(?P<id>\d+)/reviews' ] = array(
|
||||
array( array( $this, 'getProductReviews' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_product_reviews' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
return $routes;
|
||||
|
@ -61,35 +60,30 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* Get all products
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $fields
|
||||
* @param string $fields
|
||||
* @param string $type
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param string $q search terms
|
||||
* @param int $limit coupons per response
|
||||
* @param int $offset
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getProducts( $fields = null, $type = null, $created_at_min = null, $created_at_max = null, $q = null, $limit = null, $offset = null ) {
|
||||
public function get_products( $fields = null, $type = null, $filter = array() ) {
|
||||
|
||||
$request_args = array(
|
||||
'type' => $type,
|
||||
'created_at_min' => $created_at_min,
|
||||
'created_at_max' => $created_at_max,
|
||||
'q' => $q,
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
);
|
||||
if ( ! empty( $type ) )
|
||||
$filter['type'] = $type;
|
||||
|
||||
$query = $this->queryProducts( $request_args );
|
||||
$query = $this->query_products( $filter );
|
||||
|
||||
$products = array();
|
||||
|
||||
foreach( $query->posts as $product_id ) {
|
||||
|
||||
$products[] = $this->getProduct( $product_id, $fields );
|
||||
if ( ! $this->is_readable( $product_id ) )
|
||||
continue;
|
||||
|
||||
$products[] = $this->get_product( $product_id, $fields );
|
||||
}
|
||||
|
||||
$this->server->query_navigation_headers( $query );
|
||||
|
||||
return array( 'products' => $products );
|
||||
}
|
||||
|
||||
|
@ -101,18 +95,15 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* @param string $fields
|
||||
* @return array
|
||||
*/
|
||||
public function getProduct( $id, $fields = null ) {
|
||||
public function get_product( $id, $fields = null ) {
|
||||
|
||||
$id = absint( $id );
|
||||
$id = $this->validate_request( $id, 'product', 'read' );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', __( 'Invalid product ID', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
$product = get_product( $id );
|
||||
|
||||
if ( 'product' !== $product->get_post_data()->post_type )
|
||||
return new WP_Error( 'woocommerce_api_invalid_product', __( 'Invalid product', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
|
||||
$product_data = array(
|
||||
'id' => $product->id
|
||||
);
|
||||
|
@ -125,38 +116,21 @@ class WC_API_Products extends WC_API_Resource {
|
|||
*
|
||||
* @since 2.1
|
||||
* @param string $type
|
||||
* @param string $created_at_min
|
||||
* @param string $created_at_max
|
||||
* @param array $filter
|
||||
* @return array
|
||||
*/
|
||||
public function getProductsCount( $type = null, $created_at_min = null, $created_at_max = null ) {
|
||||
public function get_products_count( $type = null, $filter = array() ) {
|
||||
|
||||
$request_args = array(
|
||||
'type' => $type,
|
||||
'created_at_min' => $created_at_min,
|
||||
'created_at_max' => $created_at_max,
|
||||
);
|
||||
if ( ! empty( $type ) )
|
||||
$filter['type'] = $type;
|
||||
|
||||
$query = $this->queryProducts( $request_args );
|
||||
// TODO: permissions?
|
||||
|
||||
$query = $this->query_products( $filter );
|
||||
|
||||
return array( 'count' => $query->found_posts );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a product
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function createProduct( $data ) {
|
||||
|
||||
// TODO: implement - what's the minimum set of data required? woocommerce_create_product() would be nice
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a product
|
||||
*
|
||||
|
@ -165,11 +139,16 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
public function editProduct( $id, $data ) {
|
||||
public function edit_product( $id, $data ) {
|
||||
|
||||
$id = $this->validate_request( $id, 'product', 'edit' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// TODO: implement
|
||||
|
||||
return $this->getProduct( $id );
|
||||
return $this->get_product( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,9 +159,14 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* @param bool $force true to permanently delete order, false to move to trash
|
||||
* @return array
|
||||
*/
|
||||
public function deleteProduct( $id, $force = false ) {
|
||||
public function delete_product( $id, $force = false ) {
|
||||
|
||||
return $this->deleteResource( $id, 'product', ( 'true' === $force ) );
|
||||
$id = $this->validate_request( $id, 'product', 'delete' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
return $this->delete( $id, 'product', ( 'true' === $force ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,7 +174,14 @@ class WC_API_Products extends WC_API_Resource {
|
|||
* @param $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProductReviews( $id ) {
|
||||
public function get_product_reviews( $id ) {
|
||||
|
||||
$id = $this->validate_request( $id, 'product', 'read' );
|
||||
|
||||
if ( is_wp_error( $id ) )
|
||||
return $id;
|
||||
|
||||
// TODO: implement
|
||||
|
||||
return array();
|
||||
}
|
||||
|
@ -200,9 +191,9 @@ class WC_API_Products extends WC_API_Resource {
|
|||
*
|
||||
* @since 2.1
|
||||
* @param array $args request arguments for filtering query
|
||||
* @return array
|
||||
* @return WP_Query
|
||||
*/
|
||||
private function queryProducts( $args ) {
|
||||
private function query_products( $args ) {
|
||||
|
||||
// set base query arguments
|
||||
$query_args = array(
|
||||
|
@ -213,12 +204,23 @@ class WC_API_Products extends WC_API_Resource {
|
|||
'meta_query' => array(),
|
||||
);
|
||||
|
||||
if ( ! empty( $args['type'] ) ) {
|
||||
|
||||
$query_args['tax_query'] = array(
|
||||
array(
|
||||
'taxonomy' => 'product_type',
|
||||
'field' => 'slug',
|
||||
'terms' => $args['type'],
|
||||
),
|
||||
);
|
||||
|
||||
unset( $args['type'] );
|
||||
}
|
||||
|
||||
// TODO: some param to show hidden products, but hide by default
|
||||
$query_args['meta_query'][] = WC()->query->visibility_meta_query();
|
||||
|
||||
$query_args = $this->mergeQueryArgs( $query_args, $args );
|
||||
|
||||
// TODO: navigation/total count headers for pagination
|
||||
$query_args = $this->merge_query_args( $query_args, $args );
|
||||
|
||||
return new WP_Query( $query_args );
|
||||
}
|
||||
|
|
|
@ -28,16 +28,16 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
* @param array $routes
|
||||
* @return array
|
||||
*/
|
||||
public function registerRoutes( $routes ) {
|
||||
public function register_routes( $routes ) {
|
||||
|
||||
# GET /reports
|
||||
$routes[ $this->base ] = array(
|
||||
array( array( $this, 'getReports' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_reports' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
# GET /reports/sales
|
||||
$routes[ $this->base . '/sales'] = array(
|
||||
array( array( $this, 'getSalesReport' ), WC_API_Server::READABLE ),
|
||||
array( array( $this, 'get_sales_report' ), WC_API_Server::READABLE ),
|
||||
);
|
||||
|
||||
return $routes;
|
||||
|
@ -50,7 +50,7 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
* @since 2.1
|
||||
* @return array
|
||||
*/
|
||||
public function getReports() {
|
||||
public function get_reports() {
|
||||
|
||||
return array( 'reports' => array( 'sales' ) );
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class WC_API_Reports extends WC_API_Resource {
|
|||
* @since 2.1
|
||||
* @return array
|
||||
*/
|
||||
public function getSalesReport() {
|
||||
public function get_sales_report() {
|
||||
|
||||
// TODO: implement - DRY by abstracting the report classes?
|
||||
|
||||
|
|
|
@ -32,17 +32,75 @@ class WC_API_Resource {
|
|||
$this->server = $server;
|
||||
|
||||
// automatically register routes for sub-classes
|
||||
add_filter( 'woocommerce_api_endpoints', array( $this, 'registerRoutes' ) );
|
||||
add_filter( 'woocommerce_api_endpoints', array( $this, 'register_routes' ) );
|
||||
|
||||
// remove fields from responses when requests specify certain fields
|
||||
// note these are hooked at a later priority so data added via filters (e.g. customer data to the order response)
|
||||
// still has the fields filtered properly
|
||||
add_filter( 'woocommerce_api_order_response', array( $this, 'filterFields' ), 20, 3 );
|
||||
add_filter( 'woocommerce_api_coupon_response', array( $this, 'filterFields' ), 20, 3 );
|
||||
add_filter( 'woocommerce_api_customer_response', array( $this, 'filterFields' ), 20, 3 );
|
||||
add_filter( 'woocommerce_api_product_response', array( $this, 'filterFields' ), 20, 3 );
|
||||
foreach ( array( 'order', 'coupon', 'customer', 'product', 'report' ) as $resource ) {
|
||||
|
||||
add_filter( "woocommerce_api_{$resource}_response", array( $this, 'maybe_add_meta' ), 15, 2 );
|
||||
add_filter( "woocommerce_api_{$resource}_response", array( $this, 'filter_response_fields' ), 20, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the request by checking:
|
||||
*
|
||||
* 1) the ID is a valid integer
|
||||
* 2) the ID returns a valid post object and matches the provided post type
|
||||
* 3) the current user has the proper permissions to read/edit/delete the post
|
||||
*
|
||||
* @since 2.1
|
||||
* @param string|int $id the post ID
|
||||
* @param string $type the post type, either `shop_order`, `shop_coupon`, or `product`
|
||||
* @param string $context the context of the request, either `read`, `edit` or `delete`
|
||||
* @return int|WP_Error valid post ID or WP_Error if any of the checks fails
|
||||
*/
|
||||
protected function validate_request( $id, $type, $context ) {
|
||||
|
||||
if ( 'shop_order' === $type || 'shop_coupon' === $type )
|
||||
$resource_name = str_replace( 'shop_', '', $type );
|
||||
else
|
||||
$resource_name = $type;
|
||||
|
||||
$id = absint( $id );
|
||||
|
||||
// validate ID
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( "woocommerce_api_invalid_{$resource_name}_id", sprintf( __( 'Invalid %s ID', 'woocommerce' ), $type ), array( 'status' => 404 ) );
|
||||
|
||||
// only custom post types have per-post type/permission checks
|
||||
if ( 'customer' !== $type ) {
|
||||
|
||||
$post = get_post( $id, ARRAY_A );
|
||||
|
||||
// validate post type
|
||||
if ( $type !== $post['post_type'] )
|
||||
return new WP_Error( "woocommerce_api_invalid_{$resource_name}", sprintf( __( 'Invalid %s', 'woocommerce' ), $resource_name ), array( 'status' => 404 ) );
|
||||
|
||||
// validate permissions
|
||||
switch ( $context ) {
|
||||
|
||||
case 'read':
|
||||
if ( ! $this->is_readable( $post ) )
|
||||
return new WP_Error( "woocommerce_api_user_cannot_read_{$resource_name}", sprintf( __( 'You do not have permission to read this %s', 'woocommerce' ), $resource_name ), array( 'status' => 401 ) );
|
||||
break;
|
||||
|
||||
case 'edit':
|
||||
if ( ! $this->is_editable( $post ) )
|
||||
return new WP_Error( "woocommerce_api_user_cannot_edit_{$resource_name}", sprintf( __( 'You do not have permission to edit this %s', 'woocommerce' ), $resource_name ), array( 'status' => 401 ) );
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ( ! $this->is_deletable( $post ) )
|
||||
return new WP_Error( "woocommerce_api_user_cannot_delete_{$resource_name}", sprintf( __( 'You do not have permission to delete this %s', 'woocommerce' ), $resource_name ), array( 'status' => 401 ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add common request arguments to argument list before WP_Query is run
|
||||
|
@ -52,25 +110,32 @@ class WC_API_Resource {
|
|||
* @param array $request_args arguments provided in the request
|
||||
* @return array
|
||||
*/
|
||||
protected function mergeQueryArgs( $base_args, $request_args ) {
|
||||
protected function merge_query_args( $base_args, $request_args ) {
|
||||
|
||||
$args = array();
|
||||
|
||||
// TODO: updated_at_min, updated_at_max,s date formatting
|
||||
// TODO: WP 3.7 is required to support date args
|
||||
if ( ! empty( $request_args['created_at_min'] ) || ! empty( $request_args['created_at_max'] ) ) {
|
||||
// TODO: convert all dates from provided timezone into UTC
|
||||
// TODO: return all dates in provided timezone, else UTC
|
||||
// date
|
||||
if ( ! empty( $request_args['created_at_min'] ) || ! empty( $request_args['created_at_max'] ) || ! empty( $request_args['updated_at_min'] ) || ! empty( $request_args['updated_at_max'] ) ) {
|
||||
|
||||
$args['date_query'] = array(
|
||||
array(
|
||||
'inclusive' => true,
|
||||
)
|
||||
);
|
||||
$args['date_query'] = array();
|
||||
|
||||
// resources created after specified date
|
||||
if ( ! empty( $request_args['created_at_min'] ) )
|
||||
$args['date_query'] = array_merge( $args['date_query'], array( 'after' => $request_args['created_at_min'] ) );
|
||||
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $request_args['created_at_min'], 'inclusive' => true );
|
||||
|
||||
// resources created before specified date
|
||||
if ( ! empty( $request_args['created_at_max'] ) )
|
||||
$args['date_query'] = array_merge( $args['date_query'], array( 'before' => $request_args['created_at_min'] ) );
|
||||
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $request_args['created_at_max'], 'inclusive' => true );
|
||||
|
||||
// resources updated after specified date
|
||||
if ( ! empty( $request_args['updated_at_min'] ) )
|
||||
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'after' => $request_args['updated_at_min'], 'inclusive' => true );
|
||||
|
||||
// resources updated before specified date
|
||||
if ( ! empty( $request_args['updated_at_max'] ) )
|
||||
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'before' => $request_args['updated_at_max'], 'inclusive' => true );
|
||||
}
|
||||
|
||||
// search
|
||||
|
@ -85,9 +150,35 @@ class WC_API_Resource {
|
|||
if ( ! empty( $request_args['offset'] ) )
|
||||
$args['offset'] = $request_args['offset'];
|
||||
|
||||
// resource page
|
||||
if ( empty( $request_args['page'] ) )
|
||||
$args['paged'] = 1;
|
||||
else
|
||||
$args['paged'] = absint( $request_args['page'] );
|
||||
|
||||
return array_merge( $base_args, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add meta to resources when requested by the client. Meta is added as a top-level
|
||||
* `<resource_name>_meta` attribute (e.g. `order_meta`) as a list of key/value pairs.
|
||||
*
|
||||
* @since 2.1
|
||||
* @param array $data the resource data
|
||||
* @param object $resource the resource object (e.g WC_Order)
|
||||
* @return mixed
|
||||
*/
|
||||
public function maybe_add_meta( $data, $resource ) {
|
||||
|
||||
if ( isset( $this->server->params['GET']['filter']['meta'] ) && 'true' === $this->server->params['GET']['filter']['meta'] ) {
|
||||
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restrict the fields included in the response if the request specified certain only certain fields should be returned
|
||||
*
|
||||
|
@ -99,7 +190,7 @@ class WC_API_Resource {
|
|||
* @param array|string the requested list of fields to include in the response
|
||||
* @return mixed
|
||||
*/
|
||||
public function filterFields( $data, $resource, $fields ) {
|
||||
public function filter_response_fields( $data, $resource, $fields ) {
|
||||
|
||||
if ( empty( $fields ) )
|
||||
return $data;
|
||||
|
@ -118,20 +209,18 @@ class WC_API_Resource {
|
|||
/**
|
||||
* Delete a given resource
|
||||
*
|
||||
* @see WP_JSON_Posts::deletePost
|
||||
*
|
||||
* @since 2.1
|
||||
* @param int $id the resource ID
|
||||
* @param string $type the type of resource, either `order`,`coupon`, `product`, or `customer`
|
||||
* @param string $type the resource post type, or `customer`
|
||||
* @param bool $force true to permanently delete resource, false to move to trash (not supported for `customer`)
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
protected function deleteResource( $id, $type, $force = false ) {
|
||||
protected function delete( $id, $type, $force = false ) {
|
||||
|
||||
$id = absint( $id );
|
||||
|
||||
if ( empty( $id ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', sprintf( __( 'Invalid %s ID', 'woocommerce' ), $type ), array( 'status' => 404 ) );
|
||||
if ( 'shop_order' === $type || 'shop_coupon' === $type )
|
||||
$resource_name = str_replace( 'shop_', '', $type );
|
||||
else
|
||||
$resource_name = $type;
|
||||
|
||||
if ( 'customer' === $type ) {
|
||||
|
||||
|
@ -146,33 +235,93 @@ class WC_API_Resource {
|
|||
|
||||
// delete order/coupon/product
|
||||
|
||||
$post = get_post( $id, ARRAY_A );
|
||||
|
||||
// TODO: check if provided $type is the same as $post['post_type']
|
||||
|
||||
if ( empty( $post['ID'] ) )
|
||||
return new WP_Error( 'woocommerce_api_invalid_id', sprintf( __( 'Invalid % ID', 'woocommerce' ), $type ), array( 'status' => 404 ) );
|
||||
|
||||
$post_type = get_post_type_object( $post['post_type'] );
|
||||
|
||||
if ( ! current_user_can( $post_type->cap->delete_post, $id ) )
|
||||
return new WP_Error( "woocommerce_api_user_cannot_delete_{$type}", sprintf( __( 'You do not have permission to delete this %s', 'woocommerce' ), $type ), array( 'status' => 401 ) );
|
||||
|
||||
$result = ( $force ) ? wp_delete_post( $id, true ) : wp_trash_post( $id );
|
||||
|
||||
if ( ! $result )
|
||||
return new WP_Error( "woocommerce_api_cannot_delete_{$type}", sprintf( __( 'The %s cannot be deleted', 'woocommerce' ), $type ), array( 'status' => 500 ) );
|
||||
return new WP_Error( "woocommerce_api_cannot_delete_{$resource_name}", sprintf( __( 'This %s cannot be deleted', 'woocommerce' ), $resource_name ), array( 'status' => 500 ) );
|
||||
|
||||
if ( $force ) {
|
||||
return array( 'message' => sprintf( __( 'Permanently deleted %s', 'woocommerce' ), $type ) );
|
||||
return array( 'message' => sprintf( __( 'Permanently deleted %s', 'woocommerce' ), $resource_name ) );
|
||||
|
||||
} else {
|
||||
|
||||
$this->server->send_status( '202' );
|
||||
|
||||
return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), $type ) );
|
||||
return array( 'message' => sprintf( __( 'Deleted %s', 'woocommerce' ), $resource_name ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the given post is readable by the current user
|
||||
*
|
||||
* @since 2.1
|
||||
* @see WC_API_Resource::check_permission()
|
||||
* @param WP_Post|int $post
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_readable( $post ) {
|
||||
|
||||
return $this->check_permission( $post, 'read' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given post is editable by the current user
|
||||
*
|
||||
* @since 2.1
|
||||
* @see WC_API_Resource::check_permission()
|
||||
* @param WP_Post|int $post
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_editable( $post ) {
|
||||
|
||||
return $this->check_permission( $post, 'edit' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given post is deletable by the current user
|
||||
*
|
||||
* @since 2.1
|
||||
* @see WC_API_Resource::check_permission()
|
||||
* @param WP_Post|int $post
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_deletable( $post ) {
|
||||
|
||||
return $this->check_permission( $post, 'delete' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the permissions for the current user given a post and context
|
||||
*
|
||||
* @since 2.1
|
||||
* @param WP_Post|int $post
|
||||
* @param string $context the type of permission to check, either `read`, `write`, or `delete`
|
||||
* @return bool true if the current user has the permissions to perform the context on the post
|
||||
*/
|
||||
private function check_permission( $post, $context ) {
|
||||
|
||||
if ( ! is_a( $post, 'WP_Post' ) )
|
||||
$post = get_post( $post, ARRAY_A );
|
||||
|
||||
if ( is_null( $post ) )
|
||||
return false;
|
||||
|
||||
$post_type = get_post_type_object( $post['post_type'] );
|
||||
|
||||
if ( 'read' === $context )
|
||||
return current_user_can( $post_type->cap->read_post, $post['ID'] );
|
||||
|
||||
elseif ( 'edit' === $context )
|
||||
return current_user_can( $post_type->cap->edit_post, $post['ID'] );
|
||||
|
||||
elseif ( 'delete' === $context )
|
||||
return current_user_can( $post_type->cap->delete_post, $post['ID'] );
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue