server = $server;
// automatically register routes for sub-classes
add_filter( 'kkart_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
foreach ( array( 'order', 'coupon', 'customer', 'product', 'report' ) as $resource ) {
add_filter( "kkart_api_{$resource}_response", array( $this, 'maybe_add_meta' ), 15, 2 );
add_filter( "kkart_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( "kkart_api_invalid_{$resource_name}_id", sprintf( __( 'Invalid %s ID', 'kkart' ), $type ), array( 'status' => 404 ) );
}
// only custom post types have per-post type/permission checks
if ( 'customer' !== $type ) {
$post = get_post( $id );
// for checking permissions, product variations are the same as the product post type
$post_type = ( 'product_variation' === $post->post_type ) ? 'product' : $post->post_type;
// validate post type
if ( $type !== $post_type ) {
return new WP_Error( "kkart_api_invalid_{$resource_name}", sprintf( __( 'Invalid %s', 'kkart' ), $resource_name ), array( 'status' => 404 ) );
}
// validate permissions
switch ( $context ) {
case 'read':
if ( ! $this->is_readable( $post ) ) {
return new WP_Error( "kkart_api_user_cannot_read_{$resource_name}", sprintf( __( 'You do not have permission to read this %s', 'kkart' ), $resource_name ), array( 'status' => 401 ) );
}
break;
case 'edit':
if ( ! $this->is_editable( $post ) ) {
return new WP_Error( "kkart_api_user_cannot_edit_{$resource_name}", sprintf( __( 'You do not have permission to edit this %s', 'kkart' ), $resource_name ), array( 'status' => 401 ) );
}
break;
case 'delete':
if ( ! $this->is_deletable( $post ) ) {
return new WP_Error( "kkart_api_user_cannot_delete_{$resource_name}", sprintf( __( 'You do not have permission to delete this %s', 'kkart' ), $resource_name ), array( 'status' => 401 ) );
}
break;
}
}
return $id;
}
/**
* Add common request arguments to argument list before WP_Query is run
*
* @since 2.1
* @param array $base_args required arguments for the query (e.g. `post_type`, etc)
* @param array $request_args arguments provided in the request
* @return array
*/
protected function merge_query_args( $base_args, $request_args ) {
$args = array();
// 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();
// resources created after specified date
if ( ! empty( $request_args['created_at_min'] ) ) {
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $this->server->parse_datetime( $request_args['created_at_min'] ), 'inclusive' => true );
}
// resources created before specified date
if ( ! empty( $request_args['created_at_max'] ) ) {
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $this->server->parse_datetime( $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' => $this->server->parse_datetime( $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' => $this->server->parse_datetime( $request_args['updated_at_max'] ), 'inclusive' => true );
}
}
// search
if ( ! empty( $request_args['q'] ) ) {
$args['s'] = $request_args['q'];
}
// resources per response
if ( ! empty( $request_args['limit'] ) ) {
$args['posts_per_page'] = $request_args['limit'];
}
// resource offset
if ( ! empty( $request_args['offset'] ) ) {
$args['offset'] = $request_args['offset'];
}
// resource page
$args['paged'] = ( isset( $request_args['page'] ) ) ? absint( $request_args['page'] ) : 1;
return array_merge( $base_args, $args );
}
/**
* Add meta to resources when requested by the client. Meta is added as a top-level
* `