Moving remaining classes to refactor
This commit is contained in:
parent
9934ec8420
commit
35dfc10dc7
|
@ -0,0 +1,467 @@
|
|||
<?php
|
||||
/**
|
||||
* REST Controller
|
||||
*
|
||||
* This class extend `WP_REST_Controller` in order to include /batch endpoint
|
||||
* for almost all endpoints in WooCommerce REST API.
|
||||
*
|
||||
* It's required to follow "Controller Classes" guide before extending this class:
|
||||
* <https://developer.wordpress.org/rest-api/extending-the-rest-api/controller-classes/>
|
||||
*
|
||||
* NOTE THAT ONLY CODE RELEVANT FOR MOST ENDPOINTS SHOULD BE INCLUDED INTO THIS CLASS.
|
||||
* If necessary extend this class and create new abstract classes like `WC_REST_CRUD_Controller` or `WC_REST_Terms_Controller`.
|
||||
*
|
||||
* @class WC_REST_Controller
|
||||
* @package WooCommerce/RestApi
|
||||
* @see https://developer.wordpress.org/rest-api/extending-the-rest-api/controller-classes/
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract Rest Controller Class
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WP_REST_Controller
|
||||
* @version 2.6.0
|
||||
*/
|
||||
abstract class WC_REST_Controller extends WP_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v1';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = '';
|
||||
|
||||
/**
|
||||
* Add the schema from additional fields to an schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function add_additional_fields_schema( $schema ) {
|
||||
if ( empty( $schema['title'] ) ) {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can't use $this->get_object_type otherwise we cause an inf loop.
|
||||
*/
|
||||
$object_type = $schema['title'];
|
||||
|
||||
$additional_fields = $this->get_additional_fields( $object_type );
|
||||
|
||||
foreach ( $additional_fields as $field_name => $field_options ) {
|
||||
if ( ! $field_options['schema'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$schema['properties'][ $field_name ] = $field_options['schema'];
|
||||
}
|
||||
|
||||
$schema['properties'] = apply_filters( 'woocommerce_rest_' . $object_type . '_schema', $schema['properties'] );
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalized rest base.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_normalized_rest_base() {
|
||||
return preg_replace( '/\(.*\)\//i', '', $this->rest_base );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check batch limit.
|
||||
*
|
||||
* @param array $items Request items.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
protected function check_batch_limit( $items ) {
|
||||
$limit = apply_filters( 'woocommerce_rest_batch_items_limit', 100, $this->get_normalized_rest_base() );
|
||||
$total = 0;
|
||||
|
||||
if ( ! empty( $items['create'] ) ) {
|
||||
$total += count( $items['create'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $items['update'] ) ) {
|
||||
$total += count( $items['update'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $items['delete'] ) ) {
|
||||
$total += count( $items['delete'] );
|
||||
}
|
||||
|
||||
if ( $total > $limit ) {
|
||||
/* translators: %s: items limit */
|
||||
return new WP_Error( 'woocommerce_rest_request_entity_too_large', sprintf( __( 'Unable to accept more than %s items for this request.', 'woocommerce' ), $limit ), array( 'status' => 413 ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk create, update and delete items.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Of WP_Error or WP_REST_Response.
|
||||
*/
|
||||
public function batch_items( $request ) {
|
||||
/**
|
||||
* REST Server
|
||||
*
|
||||
* @var WP_REST_Server $wp_rest_server
|
||||
*/
|
||||
global $wp_rest_server;
|
||||
|
||||
// Get the request params.
|
||||
$items = array_filter( $request->get_params() );
|
||||
$response = array();
|
||||
|
||||
// Check batch limit.
|
||||
$limit = $this->check_batch_limit( $items );
|
||||
if ( is_wp_error( $limit ) ) {
|
||||
return $limit;
|
||||
}
|
||||
|
||||
if ( ! empty( $items['create'] ) ) {
|
||||
foreach ( $items['create'] as $item ) {
|
||||
$_item = new WP_REST_Request( 'POST' );
|
||||
|
||||
// Default parameters.
|
||||
$defaults = array();
|
||||
$schema = $this->get_public_item_schema();
|
||||
foreach ( $schema['properties'] as $arg => $options ) {
|
||||
if ( isset( $options['default'] ) ) {
|
||||
$defaults[ $arg ] = $options['default'];
|
||||
}
|
||||
}
|
||||
$_item->set_default_params( $defaults );
|
||||
|
||||
// Set request parameters.
|
||||
$_item->set_body_params( $item );
|
||||
$_response = $this->create_item( $_item );
|
||||
|
||||
if ( is_wp_error( $_response ) ) {
|
||||
$response['create'][] = array(
|
||||
'id' => 0,
|
||||
'error' => array(
|
||||
'code' => $_response->get_error_code(),
|
||||
'message' => $_response->get_error_message(),
|
||||
'data' => $_response->get_error_data(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
$response['create'][] = $wp_rest_server->response_to_data( $_response, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $items['update'] ) ) {
|
||||
foreach ( $items['update'] as $item ) {
|
||||
$_item = new WP_REST_Request( 'PUT' );
|
||||
$_item->set_body_params( $item );
|
||||
$_response = $this->update_item( $_item );
|
||||
|
||||
if ( is_wp_error( $_response ) ) {
|
||||
$response['update'][] = array(
|
||||
'id' => $item['id'],
|
||||
'error' => array(
|
||||
'code' => $_response->get_error_code(),
|
||||
'message' => $_response->get_error_message(),
|
||||
'data' => $_response->get_error_data(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
$response['update'][] = $wp_rest_server->response_to_data( $_response, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $items['delete'] ) ) {
|
||||
foreach ( $items['delete'] as $id ) {
|
||||
$id = (int) $id;
|
||||
|
||||
if ( 0 === $id ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$_item = new WP_REST_Request( 'DELETE' );
|
||||
$_item->set_query_params(
|
||||
array(
|
||||
'id' => $id,
|
||||
'force' => true,
|
||||
)
|
||||
);
|
||||
$_response = $this->delete_item( $_item );
|
||||
|
||||
if ( is_wp_error( $_response ) ) {
|
||||
$response['delete'][] = array(
|
||||
'id' => $id,
|
||||
'error' => array(
|
||||
'code' => $_response->get_error_code(),
|
||||
'message' => $_response->get_error_message(),
|
||||
'data' => $_response->get_error_data(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
$response['delete'][] = $wp_rest_server->response_to_data( $_response, '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a text value for a text based setting.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $value Value.
|
||||
* @param array $setting Setting.
|
||||
* @return string
|
||||
*/
|
||||
public function validate_setting_text_field( $value, $setting ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wp_kses_post( trim( stripslashes( $value ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate select based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $value Value.
|
||||
* @param array $setting Setting.
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
public function validate_setting_select_field( $value, $setting ) {
|
||||
if ( array_key_exists( $value, $setting['options'] ) ) {
|
||||
return $value;
|
||||
} else {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate multiselect based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $values Values.
|
||||
* @param array $setting Setting.
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function validate_setting_multiselect_field( $values, $setting ) {
|
||||
if ( empty( $values ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if ( ! is_array( $values ) ) {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$final_values = array();
|
||||
foreach ( $values as $value ) {
|
||||
if ( array_key_exists( $value, $setting['options'] ) ) {
|
||||
$final_values[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $final_values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate image_width based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $values Values.
|
||||
* @param array $setting Setting.
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
public function validate_setting_image_width_field( $values, $setting ) {
|
||||
if ( ! is_array( $values ) ) {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$current = $setting['value'];
|
||||
if ( isset( $values['width'] ) ) {
|
||||
$current['width'] = intval( $values['width'] );
|
||||
}
|
||||
if ( isset( $values['height'] ) ) {
|
||||
$current['height'] = intval( $values['height'] );
|
||||
}
|
||||
if ( isset( $values['crop'] ) ) {
|
||||
$current['crop'] = (bool) $values['crop'];
|
||||
}
|
||||
return $current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate radio based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $value Value.
|
||||
* @param array $setting Setting.
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
public function validate_setting_radio_field( $value, $setting ) {
|
||||
return $this->validate_setting_select_field( $value, $setting );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate checkbox based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $value Value.
|
||||
* @param array $setting Setting.
|
||||
* @return string|WP_Error
|
||||
*/
|
||||
public function validate_setting_checkbox_field( $value, $setting ) {
|
||||
if ( in_array( $value, array( 'yes', 'no' ) ) ) {
|
||||
return $value;
|
||||
} elseif ( empty( $value ) ) {
|
||||
$value = isset( $setting['default'] ) ? $setting['default'] : 'no';
|
||||
return $value;
|
||||
} else {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate textarea based settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $value Value.
|
||||
* @param array $setting Setting.
|
||||
* @return string
|
||||
*/
|
||||
public function validate_setting_textarea_field( $value, $setting ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wp_kses(
|
||||
trim( stripslashes( $value ) ),
|
||||
array_merge(
|
||||
array(
|
||||
'iframe' => array(
|
||||
'src' => true,
|
||||
'style' => true,
|
||||
'id' => true,
|
||||
'class' => true,
|
||||
),
|
||||
),
|
||||
wp_kses_allowed_html( 'post' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add meta query.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $args Query args.
|
||||
* @param array $meta_query Meta query.
|
||||
* @return array
|
||||
*/
|
||||
protected function add_meta_query( $args, $meta_query ) {
|
||||
if ( empty( $args['meta_query'] ) ) {
|
||||
$args['meta_query'] = array();
|
||||
}
|
||||
|
||||
$args['meta_query'][] = $meta_query;
|
||||
|
||||
return $args['meta_query'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the batch schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_public_batch_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'batch',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'create' => array(
|
||||
'description' => __( 'List of created resources.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
),
|
||||
),
|
||||
'update' => array(
|
||||
'description' => __( 'List of updated resources.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
),
|
||||
),
|
||||
'delete' => array(
|
||||
'description' => __( 'List of delete resources.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of fields to be included on the response.
|
||||
* Included fields are based on item schema and `_fields=` request argument.
|
||||
* Introduced to support WordPress 4.9.6 changes.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Fields to be included in the response.
|
||||
*/
|
||||
public function get_fields_for_response( $request ) {
|
||||
$schema = $this->get_item_schema();
|
||||
$fields = isset( $schema['properties'] ) ? array_keys( $schema['properties'] ) : array();
|
||||
|
||||
$additional_fields = $this->get_additional_fields();
|
||||
foreach ( $additional_fields as $field_name => $field_options ) {
|
||||
// For back-compat, include any field with an empty schema
|
||||
// because it won't be present in $this->get_item_schema().
|
||||
if ( is_null( $field_options['schema'] ) ) {
|
||||
$fields[] = $field_name;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $request['_fields'] ) ) {
|
||||
return $fields;
|
||||
}
|
||||
$requested_fields = is_array( $request['_fields'] ) ? $request['_fields'] : preg_split( '/[\s,]+/', $request['_fields'] );
|
||||
if ( 0 === count( $requested_fields ) ) {
|
||||
return $fields;
|
||||
}
|
||||
// Trim off outside whitespace from the comma delimited list.
|
||||
$requested_fields = array_map( 'trim', $requested_fields );
|
||||
// Always persist 'id', because it can be needed for add_additional_fields_to_object().
|
||||
if ( in_array( 'id', $fields, true ) ) {
|
||||
$requested_fields[] = 'id';
|
||||
}
|
||||
return array_intersect( $fields, $requested_fields );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,627 @@
|
|||
<?php
|
||||
/**
|
||||
* Abstract Rest CRUD Controller Class
|
||||
*
|
||||
* @class WC_REST_CRUD_Controller
|
||||
* @package WooCommerce/RestApi
|
||||
* @version 3.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_REST_CRUD_Controller class.
|
||||
*
|
||||
* @extends WC_REST_Posts_Controller
|
||||
*/
|
||||
abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* If object is hierarchical.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $hierarchical = false;
|
||||
|
||||
/**
|
||||
* Get object.
|
||||
*
|
||||
* @param int $id Object ID.
|
||||
* @return object WC_Data object or WP_Error object.
|
||||
*/
|
||||
protected function get_object( $id ) {
|
||||
// translators: %s: Class method name.
|
||||
return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
|
||||
if ( $object && 0 !== $object->get_id() && ! wc_rest_check_post_permissions( $this->post_type, 'read', $object->get_id() ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to update an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
|
||||
if ( $object && 0 !== $object->get_id() && ! wc_rest_check_post_permissions( $this->post_type, 'edit', $object->get_id() ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to delete an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
public function delete_item_permissions_check( $request ) {
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
|
||||
if ( $object && 0 !== $object->get_id() && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $object->get_id() ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object permalink.
|
||||
*
|
||||
* @param object $object Object.
|
||||
* @return string
|
||||
*/
|
||||
protected function get_permalink( $object ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the object for the REST response.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WC_Data $object Object data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
protected function prepare_object_for_response( $object, $request ) {
|
||||
// translators: %s: Class method name.
|
||||
return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares one object for create or update operation.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param bool $creating If is creating a new object.
|
||||
* @return WP_Error|WC_Data The prepared item, or WP_Error object on failure.
|
||||
*/
|
||||
protected function prepare_object_for_database( $request, $creating = false ) {
|
||||
// translators: %s: Class method name.
|
||||
return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be overridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
|
||||
if ( ! $object || 0 === $object->get_id() ) {
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$data = $this->prepare_object_for_response( $object, $request );
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
if ( $this->public ) {
|
||||
$response->link_header( 'alternate', $this->get_permalink( $object ), array( 'type' => 'text/html' ) );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an object data.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @param bool $creating If is creating a new object.
|
||||
* @return WC_Data|WP_Error
|
||||
*/
|
||||
protected function save_object( $request, $creating = false ) {
|
||||
try {
|
||||
$object = $this->prepare_object_for_database( $request, $creating );
|
||||
|
||||
if ( is_wp_error( $object ) ) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
$object->save();
|
||||
|
||||
return $this->get_object( $object->get_id() );
|
||||
} catch ( WC_Data_Exception $e ) {
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() );
|
||||
} catch ( WC_REST_Exception $e ) {
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
if ( ! empty( $request['id'] ) ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$object = $this->save_object( $request, true );
|
||||
|
||||
if ( is_wp_error( $object ) ) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->update_additional_fields_for_object( $object, $request );
|
||||
} catch ( WC_Data_Exception $e ) {
|
||||
$object->delete();
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() );
|
||||
} catch ( WC_REST_Exception $e ) {
|
||||
$object->delete();
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single object is created or updated via the REST API.
|
||||
*
|
||||
* @param WC_Data $object Inserted object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating object, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$this->post_type}_object", $object, $request, true );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_object_for_response( $object, $request );
|
||||
$response = rest_ensure_response( $response );
|
||||
$response->set_status( 201 );
|
||||
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $object->get_id() ) ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
|
||||
if ( ! $object || 0 === $object->get_id() ) {
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$object = $this->save_object( $request, false );
|
||||
|
||||
if ( is_wp_error( $object ) ) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->update_additional_fields_for_object( $object, $request );
|
||||
} catch ( WC_Data_Exception $e ) {
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), $e->getErrorData() );
|
||||
} catch ( WC_REST_Exception $e ) {
|
||||
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single object is created or updated via the REST API.
|
||||
*
|
||||
* @param WC_Data $object Inserted object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating object, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$this->post_type}_object", $object, $request, false );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_object_for_response( $object, $request );
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare objects query.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
$args = array();
|
||||
$args['offset'] = $request['offset'];
|
||||
$args['order'] = $request['order'];
|
||||
$args['orderby'] = $request['orderby'];
|
||||
$args['paged'] = $request['page'];
|
||||
$args['post__in'] = $request['include'];
|
||||
$args['post__not_in'] = $request['exclude'];
|
||||
$args['posts_per_page'] = $request['per_page'];
|
||||
$args['name'] = $request['slug'];
|
||||
$args['post_parent__in'] = $request['parent'];
|
||||
$args['post_parent__not_in'] = $request['parent_exclude'];
|
||||
$args['s'] = $request['search'];
|
||||
|
||||
if ( 'date' === $args['orderby'] ) {
|
||||
$args['orderby'] = 'date ID';
|
||||
}
|
||||
|
||||
$args['date_query'] = array();
|
||||
// Set before into date query. Date query must be specified as an array of an array.
|
||||
if ( isset( $request['before'] ) ) {
|
||||
$args['date_query'][0]['before'] = $request['before'];
|
||||
}
|
||||
|
||||
// Set after into date query. Date query must be specified as an array of an array.
|
||||
if ( isset( $request['after'] ) ) {
|
||||
$args['date_query'][0]['after'] = $request['after'];
|
||||
}
|
||||
|
||||
// Force the post_type argument, since it's not a user input variable.
|
||||
$args['post_type'] = $this->post_type;
|
||||
|
||||
/**
|
||||
* Filter the query arguments for a request.
|
||||
*
|
||||
* Enables adding extra arguments or setting defaults for a post
|
||||
* collection request.
|
||||
*
|
||||
* @param array $args Key value array of query var to query value.
|
||||
* @param WP_REST_Request $request The request used.
|
||||
*/
|
||||
$args = apply_filters( "woocommerce_rest_{$this->post_type}_object_query", $args, $request );
|
||||
|
||||
return $this->prepare_items_query( $args, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get objects.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $query_args Query args.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_objects( $query_args ) {
|
||||
$query = new WP_Query();
|
||||
$result = $query->query( $query_args );
|
||||
|
||||
$total_posts = $query->found_posts;
|
||||
if ( $total_posts < 1 ) {
|
||||
// Out-of-bounds, run the query again without LIMIT for total count.
|
||||
unset( $query_args['paged'] );
|
||||
$count_query = new WP_Query();
|
||||
$count_query->query( $query_args );
|
||||
$total_posts = $count_query->found_posts;
|
||||
}
|
||||
|
||||
return array(
|
||||
'objects' => array_map( array( $this, 'get_object' ), $result ),
|
||||
'total' => (int) $total_posts,
|
||||
'pages' => (int) ceil( $total_posts / (int) $query->query_vars['posts_per_page'] ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of posts.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$query_args = $this->prepare_objects_query( $request );
|
||||
$query_results = $this->get_objects( $query_args );
|
||||
|
||||
$objects = array();
|
||||
foreach ( $query_results['objects'] as $object ) {
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'read', $object->get_id() ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $this->prepare_object_for_response( $object, $request );
|
||||
$objects[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
$page = (int) $query_args['paged'];
|
||||
$max_pages = $query_results['pages'];
|
||||
|
||||
$response = rest_ensure_response( $objects );
|
||||
$response->header( 'X-WP-Total', $query_results['total'] );
|
||||
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
||||
|
||||
$base = $this->rest_base;
|
||||
$attrib_prefix = '(?P<';
|
||||
if ( strpos( $base, $attrib_prefix ) !== false ) {
|
||||
$attrib_names = array();
|
||||
preg_match( '/\(\?P<[^>]+>.*\)/', $base, $attrib_names, PREG_OFFSET_CAPTURE );
|
||||
foreach ( $attrib_names as $attrib_name_match ) {
|
||||
$beginning_offset = strlen( $attrib_prefix );
|
||||
$attrib_name_end = strpos( $attrib_name_match[0], '>', $attrib_name_match[1] );
|
||||
$attrib_name = substr( $attrib_name_match[0], $beginning_offset, $attrib_name_end - $beginning_offset );
|
||||
if ( isset( $request[ $attrib_name ] ) ) {
|
||||
$base = str_replace( "(?P<$attrib_name>[\d]+)", $request[ $attrib_name ], $base );
|
||||
}
|
||||
}
|
||||
}
|
||||
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ) );
|
||||
|
||||
if ( $page > 1 ) {
|
||||
$prev_page = $page - 1;
|
||||
if ( $prev_page > $max_pages ) {
|
||||
$prev_page = $max_pages;
|
||||
}
|
||||
$prev_link = add_query_arg( 'page', $prev_page, $base );
|
||||
$response->link_header( 'prev', $prev_link );
|
||||
}
|
||||
if ( $max_pages > $page ) {
|
||||
$next_page = $page + 1;
|
||||
$next_link = add_query_arg( 'page', $next_page, $base );
|
||||
$response->link_header( 'next', $next_link );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$force = (bool) $request['force'];
|
||||
$object = $this->get_object( (int) $request['id'] );
|
||||
$result = false;
|
||||
|
||||
if ( ! $object || 0 === $object->get_id() ) {
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$supports_trash = EMPTY_TRASH_DAYS > 0 && is_callable( array( $object, 'get_status' ) );
|
||||
|
||||
/**
|
||||
* Filter whether an object is trashable.
|
||||
*
|
||||
* Return false to disable trash support for the object.
|
||||
*
|
||||
* @param boolean $supports_trash Whether the object type support trashing.
|
||||
* @param WC_Data $object The object being considered for trashing support.
|
||||
*/
|
||||
$supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_object_trashable", $supports_trash, $object );
|
||||
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $object->get_id() ) ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( "woocommerce_rest_user_cannot_delete_{$this->post_type}", sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_object_for_response( $object, $request );
|
||||
|
||||
// If we're forcing, then delete permanently.
|
||||
if ( $force ) {
|
||||
$object->delete( true );
|
||||
$result = 0 === $object->get_id();
|
||||
} else {
|
||||
// If we don't support trashing for this type, error out.
|
||||
if ( ! $supports_trash ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_trash_not_supported', sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ), array( 'status' => 501 ) );
|
||||
}
|
||||
|
||||
// Otherwise, only trash if we haven't already.
|
||||
if ( is_callable( array( $object, 'get_status' ) ) ) {
|
||||
if ( 'trash' === $object->get_status() ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_already_trashed', sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 410 ) );
|
||||
}
|
||||
|
||||
$object->delete();
|
||||
$result = 'trash' === $object->get_status();
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $result ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single object is deleted or trashed via the REST API.
|
||||
*
|
||||
* @param WC_Data $object The deleted or trashed object.
|
||||
* @param WP_REST_Response $response The response data.
|
||||
* @param WP_REST_Request $request The request sent to the API.
|
||||
*/
|
||||
do_action( "woocommerce_rest_delete_{$this->post_type}_object", $object, $response, $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param WC_Data $object Object data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return array Links for the given post.
|
||||
*/
|
||||
protected function prepare_links( $object, $request ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $object->get_id() ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections of attachments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = array();
|
||||
$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['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',
|
||||
);
|
||||
$params['search'] = array(
|
||||
'description' => __( 'Limit results to those matching a string.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['after'] = array(
|
||||
'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['before'] = array(
|
||||
'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['exclude'] = array(
|
||||
'description' => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
$params['include'] = array(
|
||||
'description' => __( 'Limit result set to specific ids.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
$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(
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'desc',
|
||||
'enum' => array( 'asc', 'desc' ),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['orderby'] = array(
|
||||
'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'date',
|
||||
'enum' => array(
|
||||
'date',
|
||||
'id',
|
||||
'include',
|
||||
'title',
|
||||
'slug',
|
||||
),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
if ( $this->hierarchical ) {
|
||||
$params['parent'] = array(
|
||||
'description' => __( 'Limit result set to those of particular parent IDs.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
'default' => array(),
|
||||
);
|
||||
$params['parent_exclude'] = array(
|
||||
'description' => __( 'Limit result set to all items except those of a particular parent ID.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
'default' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter collection parameters for the posts controller.
|
||||
*
|
||||
* The dynamic part of the filter `$this->post_type` refers to the post
|
||||
* type slug for the controller.
|
||||
*
|
||||
* This filter registers the collection parameter, but does not map the
|
||||
* collection parameter to an internal WP_Query parameter. Use the
|
||||
* `rest_{$this->post_type}_query` filter to set WP_Query parameters.
|
||||
*
|
||||
* @param array $query_params JSON Schema-formatted collection parameters.
|
||||
* @param WP_Post_Type $post_type Post type object.
|
||||
*/
|
||||
return apply_filters( "rest_{$this->post_type}_collection_params", $params, $this->post_type );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Data continents controller.
|
||||
*
|
||||
* Handles requests to the /data/continents endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Data continents controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Data_Continents_Controller extends WC_REST_Data_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'data/continents';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<location>[\w-]+)', array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
'args' => array(
|
||||
'continent' => array(
|
||||
'description' => __( '2 character continent code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of countries and states for a given continent.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param string $continent_code Continent code.
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return array|mixed Response data, ready for insertion into collection data.
|
||||
*/
|
||||
public function get_continent( $continent_code = false, $request ) {
|
||||
$continents = WC()->countries->get_continents();
|
||||
$countries = WC()->countries->get_countries();
|
||||
$states = WC()->countries->get_states();
|
||||
$locale_info = include WC()->plugin_path() . '/i18n/locale-info.php';
|
||||
$data = array();
|
||||
|
||||
if ( ! array_key_exists( $continent_code, $continents ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$continent_list = $continents[ $continent_code ];
|
||||
|
||||
$continent = array(
|
||||
'code' => $continent_code,
|
||||
'name' => $continent_list['name'],
|
||||
);
|
||||
|
||||
$local_countries = array();
|
||||
foreach ( $continent_list['countries'] as $country_code ) {
|
||||
if ( isset( $countries[ $country_code ] ) ) {
|
||||
$country = array(
|
||||
'code' => $country_code,
|
||||
'name' => $countries[ $country_code ],
|
||||
);
|
||||
|
||||
// If we have detailed locale information include that in the response.
|
||||
if ( array_key_exists( $country_code, $locale_info ) ) {
|
||||
// Defensive programming against unexpected changes in locale-info.php.
|
||||
$country_data = wp_parse_args(
|
||||
$locale_info[ $country_code ], array(
|
||||
'currency_code' => 'USD',
|
||||
'currency_pos' => 'left',
|
||||
'decimal_sep' => '.',
|
||||
'dimension_unit' => 'in',
|
||||
'num_decimals' => 2,
|
||||
'thousand_sep' => ',',
|
||||
'weight_unit' => 'lbs',
|
||||
)
|
||||
);
|
||||
|
||||
$country = array_merge( $country, $country_data );
|
||||
}
|
||||
|
||||
$local_states = array();
|
||||
if ( isset( $states[ $country_code ] ) ) {
|
||||
foreach ( $states[ $country_code ] as $state_code => $state_name ) {
|
||||
$local_states[] = array(
|
||||
'code' => $state_code,
|
||||
'name' => $state_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
$country['states'] = $local_states;
|
||||
|
||||
// Allow only desired keys (e.g. filter out tax rates).
|
||||
$allowed = array(
|
||||
'code',
|
||||
'currency_code',
|
||||
'currency_pos',
|
||||
'decimal_sep',
|
||||
'dimension_unit',
|
||||
'name',
|
||||
'num_decimals',
|
||||
'states',
|
||||
'thousand_sep',
|
||||
'weight_unit',
|
||||
);
|
||||
$country = array_intersect_key( $country, array_flip( $allowed ) );
|
||||
|
||||
$local_countries[] = $country;
|
||||
}
|
||||
}
|
||||
|
||||
$continent['countries'] = $local_countries;
|
||||
return $continent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of states for all continents.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$continents = WC()->countries->get_continents();
|
||||
$data = array();
|
||||
|
||||
foreach ( array_keys( $continents ) as $continent_code ) {
|
||||
$continent = $this->get_continent( $continent_code, $request );
|
||||
$response = $this->prepare_item_for_response( $continent, $request );
|
||||
$data[] = $this->prepare_response_for_collection( $response );
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of locations for a given continent.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$data = $this->get_continent( strtoupper( $request['location'] ), $request );
|
||||
if ( empty( $data ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_data_invalid_location', __( 'There are no locations matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
return $this->prepare_item_for_response( $data, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data object for response.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param object $item Data object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, 'view' );
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $item ) );
|
||||
|
||||
/**
|
||||
* Filter the location list returned from the API.
|
||||
*
|
||||
* Allows modification of the loction data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param array $item The original list of continent(s), countries, and states.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_data_continent', $response, $item, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param object $item Data object.
|
||||
* @return array Links for the given continent.
|
||||
*/
|
||||
protected function prepare_links( $item ) {
|
||||
$continent_code = strtolower( $item['code'] );
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $continent_code ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'data_continents',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( '2 character continent code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of continent.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'countries' => array(
|
||||
'type' => 'array',
|
||||
'description' => __( 'List of countries on this continent.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'currency_code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Default ISO4127 alpha-3 currency code for the country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'currency_pos' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Currency symbol position for this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'decimal_sep' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Decimal separator for displayed prices for this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'dimension_unit' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'The unit lengths are defined in for this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'num_decimals' => array(
|
||||
'type' => 'integer',
|
||||
'description' => __( 'Number of decimal points shown in displayed prices for this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'states' => array(
|
||||
'type' => 'array',
|
||||
'description' => __( 'List of states in this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'State code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of state.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'thousand_sep' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Thousands separator for displayed prices in this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'weight_unit' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'The unit weights are defined in for this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Data controller.
|
||||
*
|
||||
* Handles requests to the /data endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Data controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Data_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'data';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to read site data.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to read site settings.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of data resources.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$data = array();
|
||||
$resources = array(
|
||||
array(
|
||||
'slug' => 'continents',
|
||||
'description' => __( 'List of supported continents, countries, and states.', 'woocommerce' ),
|
||||
),
|
||||
array(
|
||||
'slug' => 'countries',
|
||||
'description' => __( 'List of supported states in a given country.', 'woocommerce' ),
|
||||
),
|
||||
array(
|
||||
'slug' => 'currencies',
|
||||
'description' => __( 'List of supported currencies.', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ( $resources as $resource ) {
|
||||
$item = $this->prepare_item_for_response( (object) $resource, $request );
|
||||
$data[] = $this->prepare_response_for_collection( $item );
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a data resource object for serialization.
|
||||
*
|
||||
* @param stdClass $resource Resource data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $resource, $request ) {
|
||||
$data = array(
|
||||
'slug' => $resource->slug,
|
||||
'description' => $resource->description,
|
||||
);
|
||||
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, 'view' );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links( $this->prepare_links( $resource ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param object $item Data object.
|
||||
* @return array Links for the given country.
|
||||
*/
|
||||
protected function prepare_links( $item ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $item->slug ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data index schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'data_index',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'Data resource ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Data resource description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Data countries controller.
|
||||
*
|
||||
* Handles requests to the /data/countries endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Data countries controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Data_Countries_Controller extends WC_REST_Data_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'data/countries';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<location>[\w-]+)', array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
'args' => array(
|
||||
'location' => array(
|
||||
'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of countries and states.
|
||||
*
|
||||
* @param string $country_code Country code.
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return array|mixed Response data, ready for insertion into collection data.
|
||||
*/
|
||||
public function get_country( $country_code = false, $request ) {
|
||||
$countries = WC()->countries->get_countries();
|
||||
$states = WC()->countries->get_states();
|
||||
$data = array();
|
||||
|
||||
if ( ! array_key_exists( $country_code, $countries ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$country = array(
|
||||
'code' => $country_code,
|
||||
'name' => $countries[ $country_code ],
|
||||
);
|
||||
|
||||
$local_states = array();
|
||||
if ( isset( $states[ $country_code ] ) ) {
|
||||
foreach ( $states[ $country_code ] as $state_code => $state_name ) {
|
||||
$local_states[] = array(
|
||||
'code' => $state_code,
|
||||
'name' => $state_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
$country['states'] = $local_states;
|
||||
return $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of states for all countries.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$countries = WC()->countries->get_countries();
|
||||
$data = array();
|
||||
|
||||
foreach ( array_keys( $countries ) as $country_code ) {
|
||||
$country = $this->get_country( $country_code, $request );
|
||||
$response = $this->prepare_item_for_response( $country, $request );
|
||||
$data[] = $this->prepare_response_for_collection( $response );
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of states for a given country.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$data = $this->get_country( strtoupper( $request['location'] ), $request );
|
||||
if ( empty( $data ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_data_invalid_location', __( 'There are no locations matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
return $this->prepare_item_for_response( $data, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data object for response.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @param object $item Data object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, 'view' );
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $item ) );
|
||||
|
||||
/**
|
||||
* Filter the states list for a country returned from the API.
|
||||
*
|
||||
* Allows modification of the loction data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param array $data The original country's states list.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_data_country', $response, $item, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param object $item Data object.
|
||||
* @return array Links for the given country.
|
||||
*/
|
||||
protected function prepare_links( $item ) {
|
||||
$country_code = strtolower( $item['code'] );
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $country_code ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the location schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'data_countries',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'ISO3166 alpha-2 country code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'states' => array(
|
||||
'type' => 'array',
|
||||
'description' => __( 'List of states in this country.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'State code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of state.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Data currencies controller.
|
||||
*
|
||||
* Handles requests to the /data/currencies endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Data Currencies controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
*/
|
||||
class WC_REST_Data_Currencies_Controller extends WC_REST_Data_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'data/currencies';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/current', array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_current_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<currency>[\w-]{3})', array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
'args' => array(
|
||||
'location' => array(
|
||||
'description' => __( 'ISO4217 currency code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get currency information.
|
||||
*
|
||||
* @param string $code Currency code.
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return array|mixed Response data, ready for insertion into collection data.
|
||||
*/
|
||||
public function get_currency( $code = false, $request ) {
|
||||
$currencies = get_woocommerce_currencies();
|
||||
$data = array();
|
||||
|
||||
if ( ! array_key_exists( $code, $currencies ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currency = array(
|
||||
'code' => $code,
|
||||
'name' => $currencies[ $code ],
|
||||
'symbol' => get_woocommerce_currency_symbol( $code ),
|
||||
);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of currencies.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$currencies = get_woocommerce_currencies();
|
||||
foreach ( array_keys( $currencies ) as $code ) {
|
||||
$currency = $this->get_currency( $code, $request );
|
||||
$response = $this->prepare_item_for_response( $currency, $request );
|
||||
$data[] = $this->prepare_response_for_collection( $response );
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information for a specific currency.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$data = $this->get_currency( strtoupper( $request['currency'] ), $request );
|
||||
if ( empty( $data ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_data_invalid_currency', __( 'There are no currencies matching these parameters.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
return $this->prepare_item_for_response( $data, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return information for the current site currency.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_current_item( $request ) {
|
||||
$currency = get_option( 'woocommerce_currency' );
|
||||
return $this->prepare_item_for_response( $this->get_currency( $currency, $request ), $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data object for response.
|
||||
*
|
||||
* @param object $item Data object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, 'view' );
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $item ) );
|
||||
|
||||
/**
|
||||
* Filter currency returned from the API.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param array $item Currency data.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_data_currency', $response, $item, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param object $item Data object.
|
||||
* @return array Links for the given currency.
|
||||
*/
|
||||
protected function prepare_links( $item ) {
|
||||
$code = strtoupper( $item['code'] );
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $code ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the currency schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'data_currencies',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'ISO4217 currency code.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Full name of currency.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'symbol' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Currency symbol.', 'woocommerce' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Network Orders controller
|
||||
*
|
||||
* Handles requests to the /orders/network endpoint
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.4.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Network Orders controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Network_Orders_V2_Controller
|
||||
*/
|
||||
class WC_REST_Network_Orders_Controller extends WC_REST_Network_Orders_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Network Orders controller
|
||||
*
|
||||
* Handles requests to the /orders/network endpoint
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.4.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Network Orders controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Orders_V2_Controller
|
||||
*/
|
||||
class WC_REST_Network_Orders_V2_Controller extends WC_REST_Orders_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Register the routes for network orders.
|
||||
*/
|
||||
public function register_routes() {
|
||||
if ( is_multisite() ) {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/network',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'network_orders' ),
|
||||
'permission_callback' => array( $this, 'network_orders_permissions_check' ),
|
||||
'args' => $this->get_collection_params(),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the item's schema for display / public consumption purposes.
|
||||
*
|
||||
* @return array Public item schema data.
|
||||
*/
|
||||
public function get_public_item_schema() {
|
||||
$schema = parent::get_public_item_schema();
|
||||
|
||||
$schema['properties']['blog'] = array(
|
||||
'description' => __( 'Blog id of the record on the multisite.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
);
|
||||
$schema['properties']['edit_url'] = array(
|
||||
'description' => __( 'URL to edit the order', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
);
|
||||
$schema['properties']['customer'][] = array(
|
||||
'description' => __( 'Name of the customer for the order', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
);
|
||||
$schema['properties']['status_name'][] = array(
|
||||
'description' => __( 'Order Status', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
);
|
||||
$schema['properties']['formatted_total'][] = array(
|
||||
'description' => __( 'Order total formatted for locale', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a permissions check for the proper requested blog
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return bool $permission
|
||||
*/
|
||||
public function network_orders_permissions_check( $request ) {
|
||||
$blog_id = $request->get_param( 'blog_id' );
|
||||
$blog_id = ! empty( $blog_id ) ? $blog_id : get_current_blog_id();
|
||||
|
||||
switch_to_blog( $blog_id );
|
||||
|
||||
$permission = $this->get_items_permissions_check( $request );
|
||||
|
||||
restore_current_blog();
|
||||
|
||||
return $permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of orders from the requested blog id
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function network_orders( $request ) {
|
||||
$blog_id = $request->get_param( 'blog_id' );
|
||||
$blog_id = ! empty( $blog_id ) ? $blog_id : get_current_blog_id();
|
||||
$active_plugins = get_blog_option( $blog_id, 'active_plugins', array() );
|
||||
$network_active_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
|
||||
|
||||
$plugins = array_merge( $active_plugins, $network_active_plugins );
|
||||
$wc_active = false;
|
||||
foreach ( $plugins as $plugin ) {
|
||||
if ( substr_compare( $plugin, '/woocommerce.php', strlen( $plugin ) - strlen( '/woocommerce.php' ), strlen( '/woocommerce.php' ) ) === 0 ) {
|
||||
$wc_active = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If WooCommerce not active for site, return an empty response.
|
||||
if ( ! $wc_active ) {
|
||||
$response = rest_ensure_response( array() );
|
||||
return $response;
|
||||
}
|
||||
|
||||
switch_to_blog( $blog_id );
|
||||
add_filter( 'woocommerce_rest_orders_prepare_object_query', array( $this, 'network_orders_filter_args' ) );
|
||||
$items = $this->get_items( $request );
|
||||
remove_filter( 'woocommerce_rest_orders_prepare_object_query', array( $this, 'network_orders_filter_args' ) );
|
||||
|
||||
foreach ( $items->data as &$current_order ) {
|
||||
$order = wc_get_order( $current_order['id'] );
|
||||
|
||||
$current_order['blog'] = get_blog_details( get_current_blog_id() );
|
||||
$current_order['edit_url'] = get_admin_url( $blog_id, 'post.php?post=' . absint( $order->get_id() ) . '&action=edit' );
|
||||
/* translators: 1: first name 2: last name */
|
||||
$current_order['customer'] = trim( sprintf( _x( '%1$s %2$s', 'full name', 'woocommerce' ), $order->get_billing_first_name(), $order->get_billing_last_name() ) );
|
||||
$current_order['status_name'] = wc_get_order_status_name( $order->get_status() );
|
||||
$current_order['formatted_total'] = $order->get_formatted_order_total();
|
||||
}
|
||||
|
||||
restore_current_blog();
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the post statuses to on hold and processing for the network order query.
|
||||
*
|
||||
* @param array $args Query args.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function network_orders_filter_args( $args ) {
|
||||
$args['post_status'] = array(
|
||||
'wc-on-hold',
|
||||
'wc-processing',
|
||||
);
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC Payment gateways controller
|
||||
*
|
||||
* Handles requests to the /payment_gateways endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Paymenga gateways controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Payment_Gateways_V2_Controller
|
||||
*/
|
||||
class WC_REST_Payment_Gateways_Controller extends WC_REST_Payment_Gateways_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Prepare a payment gateway for response.
|
||||
*
|
||||
* @param WC_Payment_Gateway $gateway Payment gateway object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $gateway, $request ) {
|
||||
$order = (array) get_option( 'woocommerce_gateway_order' );
|
||||
$item = array(
|
||||
'id' => $gateway->id,
|
||||
'title' => $gateway->title,
|
||||
'description' => $gateway->description,
|
||||
'order' => isset( $order[ $gateway->id ] ) ? $order[ $gateway->id ] : '',
|
||||
'enabled' => ( 'yes' === $gateway->enabled ),
|
||||
'method_title' => $gateway->get_method_title(),
|
||||
'method_description' => $gateway->get_method_description(),
|
||||
'method_supports' => $gateway->supports,
|
||||
'settings' => $this->get_settings( $gateway ),
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links( $this->prepare_links( $gateway, $request ) );
|
||||
|
||||
/**
|
||||
* Filter payment gateway objects returned from the REST API.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param WC_Payment_Gateway $gateway Payment gateway object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_payment_gateway', $response, $gateway, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return settings associated with this payment gateway.
|
||||
*
|
||||
* @param WC_Payment_Gateway $gateway Gateway instance.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings( $gateway ) {
|
||||
$settings = array();
|
||||
$gateway->init_form_fields();
|
||||
foreach ( $gateway->form_fields as $id => $field ) {
|
||||
// Make sure we at least have a title and type.
|
||||
if ( empty( $field['title'] ) || empty( $field['type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore 'enabled' and 'description' which get included elsewhere.
|
||||
if ( in_array( $id, array( 'enabled', 'description' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = array(
|
||||
'id' => $id,
|
||||
'label' => empty( $field['label'] ) ? $field['title'] : $field['label'],
|
||||
'description' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'type' => $field['type'],
|
||||
'value' => empty( $gateway->settings[ $id ] ) ? '' : $gateway->settings[ $id ],
|
||||
'default' => empty( $field['default'] ) ? '' : $field['default'],
|
||||
'tip' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
|
||||
);
|
||||
if ( ! empty( $field['options'] ) ) {
|
||||
$data['options'] = $field['options'];
|
||||
}
|
||||
$settings[ $id ] = $data;
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the payment gateway schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'payment_gateway',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Payment gateway ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => __( 'Payment gateway title on checkout.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Payment gateway description on checkout.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'order' => array(
|
||||
'description' => __( 'Payment gateway sort order.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'absint',
|
||||
),
|
||||
),
|
||||
'enabled' => array(
|
||||
'description' => __( 'Payment gateway enabled status.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'method_title' => array(
|
||||
'description' => __( 'Payment gateway method title.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'method_description' => array(
|
||||
'description' => __( 'Payment gateway method description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'method_supports' => array(
|
||||
'description' => __( 'Supported features for this payment gateway.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
'settings' => array(
|
||||
'description' => __( 'Payment gateway settings.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Type of setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Setting value.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'default' => array(
|
||||
'description' => __( 'Default value for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'tip' => array(
|
||||
'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'placeholder' => array(
|
||||
'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,466 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC Payment gateways controller
|
||||
*
|
||||
* Handles requests to the /payment_gateways endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Paymenga gateways controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Payment_Gateways_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'payment_gateways';
|
||||
|
||||
/**
|
||||
* Register the route for /payment_gateways and /payment_gateways/<id>
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
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' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<id>[\w-]+)', array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
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_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to view payment gateways.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read a payment gateway.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to edit payment gateways.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'payment_gateways', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payment gateways.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
$response = array();
|
||||
foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
|
||||
$payment_gateway->id = $payment_gateway_id;
|
||||
$gateway = $this->prepare_item_for_response( $payment_gateway, $request );
|
||||
$gateway = $this->prepare_response_for_collection( $gateway );
|
||||
$response[] = $gateway;
|
||||
}
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single payment gateway.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$gateway = $this->get_gateway( $request );
|
||||
|
||||
if ( is_null( $gateway ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$gateway = $this->prepare_item_for_response( $gateway, $request );
|
||||
return rest_ensure_response( $gateway );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update A Single Payment Method.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$gateway = $this->get_gateway( $request );
|
||||
|
||||
if ( is_null( $gateway ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_payment_gateway_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
// Get settings.
|
||||
$gateway->init_form_fields();
|
||||
$settings = $gateway->settings;
|
||||
|
||||
// Update settings.
|
||||
if ( isset( $request['settings'] ) ) {
|
||||
$errors_found = false;
|
||||
foreach ( $gateway->form_fields as $key => $field ) {
|
||||
if ( isset( $request['settings'][ $key ] ) ) {
|
||||
if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
|
||||
$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
|
||||
} else {
|
||||
$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
|
||||
}
|
||||
if ( is_wp_error( $value ) ) {
|
||||
$errors_found = true;
|
||||
break;
|
||||
}
|
||||
$settings[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $errors_found ) {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Update if this method is enabled or not.
|
||||
if ( isset( $request['enabled'] ) ) {
|
||||
$settings['enabled'] = wc_bool_to_string( $request['enabled'] );
|
||||
$gateway->enabled = $settings['enabled'];
|
||||
}
|
||||
|
||||
// Update title.
|
||||
if ( isset( $request['title'] ) ) {
|
||||
$settings['title'] = $request['title'];
|
||||
$gateway->title = $settings['title'];
|
||||
}
|
||||
|
||||
// Update description.
|
||||
if ( isset( $request['description'] ) ) {
|
||||
$settings['description'] = $request['description'];
|
||||
$gateway->description = $settings['description'];
|
||||
}
|
||||
|
||||
// Update options.
|
||||
$gateway->settings = $settings;
|
||||
update_option( $gateway->get_option_key(), apply_filters( 'woocommerce_gateway_' . $gateway->id . '_settings_values', $settings, $gateway ) );
|
||||
|
||||
// Update order.
|
||||
if ( isset( $request['order'] ) ) {
|
||||
$order = (array) get_option( 'woocommerce_gateway_order' );
|
||||
$order[ $gateway->id ] = $request['order'];
|
||||
update_option( 'woocommerce_gateway_order', $order );
|
||||
$gateway->order = absint( $request['order'] );
|
||||
}
|
||||
|
||||
$gateway = $this->prepare_item_for_response( $gateway, $request );
|
||||
return rest_ensure_response( $gateway );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a gateway based on the current request object.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|null
|
||||
*/
|
||||
public function get_gateway( $request ) {
|
||||
$gateway = null;
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
foreach ( $payment_gateways as $payment_gateway_id => $payment_gateway ) {
|
||||
if ( $request['id'] !== $payment_gateway_id ) {
|
||||
continue;
|
||||
}
|
||||
$payment_gateway->id = $payment_gateway_id;
|
||||
$gateway = $payment_gateway;
|
||||
}
|
||||
return $gateway;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a payment gateway for response.
|
||||
*
|
||||
* @param WC_Payment_Gateway $gateway Payment gateway object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $gateway, $request ) {
|
||||
$order = (array) get_option( 'woocommerce_gateway_order' );
|
||||
$item = array(
|
||||
'id' => $gateway->id,
|
||||
'title' => $gateway->title,
|
||||
'description' => $gateway->description,
|
||||
'order' => isset( $order[ $gateway->id ] ) ? $order[ $gateway->id ] : '',
|
||||
'enabled' => ( 'yes' === $gateway->enabled ),
|
||||
'method_title' => $gateway->get_method_title(),
|
||||
'method_description' => $gateway->get_method_description(),
|
||||
'settings' => $this->get_settings( $gateway ),
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links( $this->prepare_links( $gateway, $request ) );
|
||||
|
||||
/**
|
||||
* Filter payment gateway objects returned from the REST API.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param WC_Payment_Gateway $gateway Payment gateway object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_payment_gateway', $response, $gateway, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return settings associated with this payment gateway.
|
||||
*
|
||||
* @param WC_Payment_Gateway $gateway Gateway data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings( $gateway ) {
|
||||
$settings = array();
|
||||
$gateway->init_form_fields();
|
||||
foreach ( $gateway->form_fields as $id => $field ) {
|
||||
// Make sure we at least have a title and type.
|
||||
if ( empty( $field['title'] ) || empty( $field['type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
// Ignore 'title' settings/fields -- they are UI only.
|
||||
if ( 'title' === $field['type'] ) {
|
||||
continue;
|
||||
}
|
||||
// Ignore 'enabled' and 'description' which get included elsewhere.
|
||||
if ( in_array( $id, array( 'enabled', 'description' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
$data = array(
|
||||
'id' => $id,
|
||||
'label' => empty( $field['label'] ) ? $field['title'] : $field['label'],
|
||||
'description' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'type' => $field['type'],
|
||||
'value' => empty( $gateway->settings[ $id ] ) ? '' : $gateway->settings[ $id ],
|
||||
'default' => empty( $field['default'] ) ? '' : $field['default'],
|
||||
'tip' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
|
||||
);
|
||||
if ( ! empty( $field['options'] ) ) {
|
||||
$data['options'] = $field['options'];
|
||||
}
|
||||
$settings[ $id ] = $data;
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param WC_Payment_Gateway $gateway Payment gateway object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_links( $gateway, $request ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $gateway->id ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the payment gateway schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'payment_gateway',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Payment gateway ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => __( 'Payment gateway title on checkout.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Payment gateway description on checkout.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'order' => array(
|
||||
'description' => __( 'Payment gateway sort order.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'absint',
|
||||
),
|
||||
),
|
||||
'enabled' => array(
|
||||
'description' => __( 'Payment gateway enabled status.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'method_title' => array(
|
||||
'description' => __( 'Payment gateway method title.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'method_description' => array(
|
||||
'description' => __( 'Payment gateway method description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'settings' => array(
|
||||
'description' => __( 'Payment gateway settings.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Type of setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Setting value.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'default' => array(
|
||||
'description' => __( 'Default value for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'tip' => array(
|
||||
'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'placeholder' => array(
|
||||
'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any query params needed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
return array(
|
||||
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,723 @@
|
|||
<?php
|
||||
/**
|
||||
* Abstract Rest Posts Controller Class
|
||||
*
|
||||
* @class WC_REST_Posts_Controller
|
||||
* @package WooCommerce/RestApi
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_REST_Posts_Controller
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @version 2.6.0
|
||||
*/
|
||||
abstract class WC_REST_Posts_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v1';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = '';
|
||||
|
||||
/**
|
||||
* Post type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $post_type = '';
|
||||
|
||||
/**
|
||||
* Controls visibility on frontend.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $public = false;
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read items.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to create an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function create_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'create' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
$post = get_post( (int) $request['id'] );
|
||||
|
||||
if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to update an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
$post = get_post( (int) $request['id'] );
|
||||
|
||||
if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'edit', $post->ID ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to delete an item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
public function delete_item_permissions_check( $request ) {
|
||||
$post = get_post( (int) $request['id'] );
|
||||
|
||||
if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access batch create, update and delete items.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function batch_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'batch' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_batch', __( 'Sorry, you are not allowed to batch manipulate this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$id = (int) $request['id'];
|
||||
$post = get_post( $id );
|
||||
|
||||
if ( ! empty( $post->post_type ) && 'product_variation' === $post->post_type && 'product' === $this->post_type ) {
|
||||
return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/<product_id>/variations/<id> endpoint.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
} elseif ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
|
||||
return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'Invalid ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $post, $request );
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
if ( $this->public ) {
|
||||
$response->link_header( 'alternate', get_permalink( $id ), array( 'type' => 'text/html' ) );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
if ( ! empty( $request['id'] ) ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_exists", sprintf( __( 'Cannot create existing %s.', 'woocommerce' ), $this->post_type ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$post = $this->prepare_item_for_database( $request );
|
||||
if ( is_wp_error( $post ) ) {
|
||||
return $post;
|
||||
}
|
||||
|
||||
$post->post_type = $this->post_type;
|
||||
$post_id = wp_insert_post( $post, true );
|
||||
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
|
||||
if ( in_array( $post_id->get_error_code(), array( 'db_insert_error' ) ) ) {
|
||||
$post_id->add_data( array( 'status' => 500 ) );
|
||||
} else {
|
||||
$post_id->add_data( array( 'status' => 400 ) );
|
||||
}
|
||||
return $post_id;
|
||||
}
|
||||
$post->ID = $post_id;
|
||||
$post = get_post( $post_id );
|
||||
|
||||
$this->update_additional_fields_for_object( $post, $request );
|
||||
|
||||
// Add meta fields.
|
||||
$meta_fields = $this->add_post_meta_fields( $post, $request );
|
||||
if ( is_wp_error( $meta_fields ) ) {
|
||||
// Remove post.
|
||||
$this->delete_post( $post );
|
||||
|
||||
return $meta_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single item is created or updated via the REST API.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating item, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, true );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $post, $request );
|
||||
$response = rest_ensure_response( $response );
|
||||
$response->set_status( 201 );
|
||||
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add post meta fields.
|
||||
*
|
||||
* @param WP_Post $post Post Object.
|
||||
* @param WP_REST_Request $request WP_REST_Request Object.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
protected function add_post_meta_fields( $post, $request ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete post.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
protected function delete_post( $post ) {
|
||||
wp_delete_post( $post->ID, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$id = (int) $request['id'];
|
||||
$post = get_post( $id );
|
||||
|
||||
if ( ! empty( $post->post_type ) && 'product_variation' === $post->post_type && 'product' === $this->post_type ) {
|
||||
return new WP_Error( "woocommerce_rest_invalid_{$this->post_type}_id", __( 'To manipulate product variations you should use the /products/<product_id>/variations/<id> endpoint.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
} elseif ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
$post = $this->prepare_item_for_database( $request );
|
||||
if ( is_wp_error( $post ) ) {
|
||||
return $post;
|
||||
}
|
||||
// Convert the post object to an array, otherwise wp_update_post will expect non-escaped input.
|
||||
$post_id = wp_update_post( (array) $post, true );
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
if ( in_array( $post_id->get_error_code(), array( 'db_update_error' ) ) ) {
|
||||
$post_id->add_data( array( 'status' => 500 ) );
|
||||
} else {
|
||||
$post_id->add_data( array( 'status' => 400 ) );
|
||||
}
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
$this->update_additional_fields_for_object( $post, $request );
|
||||
|
||||
// Update meta fields.
|
||||
$meta_fields = $this->update_post_meta_fields( $post, $request );
|
||||
if ( is_wp_error( $meta_fields ) ) {
|
||||
return $meta_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single item is created or updated via the REST API.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating item, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$this->post_type}", $post, $request, false );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $post, $request );
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of posts.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$args = array();
|
||||
$args['offset'] = $request['offset'];
|
||||
$args['order'] = $request['order'];
|
||||
$args['orderby'] = $request['orderby'];
|
||||
$args['paged'] = $request['page'];
|
||||
$args['post__in'] = $request['include'];
|
||||
$args['post__not_in'] = $request['exclude'];
|
||||
$args['posts_per_page'] = $request['per_page'];
|
||||
$args['name'] = $request['slug'];
|
||||
$args['post_parent__in'] = $request['parent'];
|
||||
$args['post_parent__not_in'] = $request['parent_exclude'];
|
||||
$args['s'] = $request['search'];
|
||||
|
||||
$args['date_query'] = array();
|
||||
// Set before into date query. Date query must be specified as an array of an array.
|
||||
if ( isset( $request['before'] ) ) {
|
||||
$args['date_query'][0]['before'] = $request['before'];
|
||||
}
|
||||
|
||||
// Set after into date query. Date query must be specified as an array of an array.
|
||||
if ( isset( $request['after'] ) ) {
|
||||
$args['date_query'][0]['after'] = $request['after'];
|
||||
}
|
||||
|
||||
if ( 'wc/v1' === $this->namespace ) {
|
||||
if ( is_array( $request['filter'] ) ) {
|
||||
$args = array_merge( $args, $request['filter'] );
|
||||
unset( $args['filter'] );
|
||||
}
|
||||
}
|
||||
|
||||
// Force the post_type argument, since it's not a user input variable.
|
||||
$args['post_type'] = $this->post_type;
|
||||
|
||||
/**
|
||||
* Filter the query arguments for a request.
|
||||
*
|
||||
* Enables adding extra arguments or setting defaults for a post
|
||||
* collection request.
|
||||
*
|
||||
* @param array $args Key value array of query var to query value.
|
||||
* @param WP_REST_Request $request The request used.
|
||||
*/
|
||||
$args = apply_filters( "woocommerce_rest_{$this->post_type}_query", $args, $request );
|
||||
$query_args = $this->prepare_items_query( $args, $request );
|
||||
|
||||
$posts_query = new WP_Query();
|
||||
$query_result = $posts_query->query( $query_args );
|
||||
|
||||
$posts = array();
|
||||
foreach ( $query_result as $post ) {
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $post, $request );
|
||||
$posts[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
$page = (int) $query_args['paged'];
|
||||
$total_posts = $posts_query->found_posts;
|
||||
|
||||
if ( $total_posts < 1 ) {
|
||||
// Out-of-bounds, run the query again without LIMIT for total count.
|
||||
unset( $query_args['paged'] );
|
||||
$count_query = new WP_Query();
|
||||
$count_query->query( $query_args );
|
||||
$total_posts = $count_query->found_posts;
|
||||
}
|
||||
|
||||
$max_pages = ceil( $total_posts / (int) $query_args['posts_per_page'] );
|
||||
|
||||
$response = rest_ensure_response( $posts );
|
||||
$response->header( 'X-WP-Total', (int) $total_posts );
|
||||
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
||||
|
||||
$request_params = $request->get_query_params();
|
||||
if ( ! empty( $request_params['filter'] ) ) {
|
||||
// Normalize the pagination params.
|
||||
unset( $request_params['filter']['posts_per_page'] );
|
||||
unset( $request_params['filter']['paged'] );
|
||||
}
|
||||
$base = add_query_arg( $request_params, rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
||||
|
||||
if ( $page > 1 ) {
|
||||
$prev_page = $page - 1;
|
||||
if ( $prev_page > $max_pages ) {
|
||||
$prev_page = $max_pages;
|
||||
}
|
||||
$prev_link = add_query_arg( 'page', $prev_page, $base );
|
||||
$response->link_header( 'prev', $prev_link );
|
||||
}
|
||||
if ( $max_pages > $page ) {
|
||||
$next_page = $page + 1;
|
||||
$next_link = add_query_arg( 'page', $next_page, $base );
|
||||
$response->link_header( 'next', $next_link );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$id = (int) $request['id'];
|
||||
$force = (bool) $request['force'];
|
||||
$post = get_post( $id );
|
||||
|
||||
if ( empty( $id ) || empty( $post->ID ) || $post->post_type !== $this->post_type ) {
|
||||
return new WP_Error( "woocommerce_rest_{$this->post_type}_invalid_id", __( 'ID is invalid.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$supports_trash = EMPTY_TRASH_DAYS > 0;
|
||||
|
||||
/**
|
||||
* Filter whether an item is trashable.
|
||||
*
|
||||
* Return false to disable trash support for the item.
|
||||
*
|
||||
* @param boolean $supports_trash Whether the item type support trashing.
|
||||
* @param WP_Post $post The Post object being considered for trashing support.
|
||||
*/
|
||||
$supports_trash = apply_filters( "woocommerce_rest_{$this->post_type}_trashable", $supports_trash, $post );
|
||||
|
||||
if ( ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( "woocommerce_rest_user_cannot_delete_{$this->post_type}", sprintf( __( 'Sorry, you are not allowed to delete %s.', 'woocommerce' ), $this->post_type ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $post, $request );
|
||||
|
||||
// If we're forcing, then delete permanently.
|
||||
if ( $force ) {
|
||||
$result = wp_delete_post( $id, true );
|
||||
} else {
|
||||
// If we don't support trashing for this type, error out.
|
||||
if ( ! $supports_trash ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_trash_not_supported', sprintf( __( 'The %s does not support trashing.', 'woocommerce' ), $this->post_type ), array( 'status' => 501 ) );
|
||||
}
|
||||
|
||||
// Otherwise, only trash if we haven't already.
|
||||
if ( 'trash' === $post->post_status ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_already_trashed', sprintf( __( 'The %s has already been deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 410 ) );
|
||||
}
|
||||
|
||||
// (Note that internally this falls through to `wp_delete_post` if
|
||||
// the trash is disabled.)
|
||||
$result = wp_trash_post( $id );
|
||||
}
|
||||
|
||||
if ( ! $result ) {
|
||||
/* translators: %s: post type */
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', sprintf( __( 'The %s cannot be deleted.', 'woocommerce' ), $this->post_type ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single item is deleted or trashed via the REST API.
|
||||
*
|
||||
* @param object $post The deleted or trashed item.
|
||||
* @param WP_REST_Response $response The response data.
|
||||
* @param WP_REST_Request $request The request sent to the API.
|
||||
*/
|
||||
do_action( "woocommerce_rest_delete_{$this->post_type}", $post, $response, $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return array Links for the given post.
|
||||
*/
|
||||
protected function prepare_links( $post, $request ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post->ID ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the allowed query_vars for a get_items() response and
|
||||
* prepare for WP_Query.
|
||||
*
|
||||
* @param array $prepared_args Prepared arguments.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return array $query_args
|
||||
*/
|
||||
protected function prepare_items_query( $prepared_args = array(), $request = null ) {
|
||||
|
||||
$valid_vars = array_flip( $this->get_allowed_query_vars() );
|
||||
$query_args = array();
|
||||
foreach ( $valid_vars as $var => $index ) {
|
||||
if ( isset( $prepared_args[ $var ] ) ) {
|
||||
/**
|
||||
* Filter the query_vars used in `get_items` for the constructed query.
|
||||
*
|
||||
* The dynamic portion of the hook name, $var, refers to the query_var key.
|
||||
*
|
||||
* @param mixed $prepared_args[ $var ] The query_var value.
|
||||
*/
|
||||
$query_args[ $var ] = apply_filters( "woocommerce_rest_query_var-{$var}", $prepared_args[ $var ] );
|
||||
}
|
||||
}
|
||||
|
||||
$query_args['ignore_sticky_posts'] = true;
|
||||
|
||||
if ( 'include' === $query_args['orderby'] ) {
|
||||
$query_args['orderby'] = 'post__in';
|
||||
} elseif ( 'id' === $query_args['orderby'] ) {
|
||||
$query_args['orderby'] = 'ID'; // ID must be capitalized.
|
||||
} elseif ( 'slug' === $query_args['orderby'] ) {
|
||||
$query_args['orderby'] = 'name';
|
||||
}
|
||||
|
||||
return $query_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the WP Query vars that are allowed for the API request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_allowed_query_vars() {
|
||||
global $wp;
|
||||
|
||||
/**
|
||||
* Filter the publicly allowed query vars.
|
||||
*
|
||||
* Allows adjusting of the default query vars that are made public.
|
||||
*
|
||||
* @param array Array of allowed WP_Query query vars.
|
||||
*/
|
||||
$valid_vars = apply_filters( 'query_vars', $wp->public_query_vars );
|
||||
|
||||
$post_type_obj = get_post_type_object( $this->post_type );
|
||||
if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
|
||||
/**
|
||||
* Filter the allowed 'private' query vars for authorized users.
|
||||
*
|
||||
* If the user has the `edit_posts` capability, we also allow use of
|
||||
* private query parameters, which are only undesirable on the
|
||||
* frontend, but are safe for use in query strings.
|
||||
*
|
||||
* To disable anyway, use
|
||||
* `add_filter( 'woocommerce_rest_private_query_vars', '__return_empty_array' );`
|
||||
*
|
||||
* @param array $private_query_vars Array of allowed query vars for authorized users.
|
||||
* }
|
||||
*/
|
||||
$private = apply_filters( 'woocommerce_rest_private_query_vars', $wp->private_query_vars );
|
||||
$valid_vars = array_merge( $valid_vars, $private );
|
||||
}
|
||||
// Define our own in addition to WP's normal vars.
|
||||
$rest_valid = array(
|
||||
'date_query',
|
||||
'ignore_sticky_posts',
|
||||
'offset',
|
||||
'post__in',
|
||||
'post__not_in',
|
||||
'post_parent',
|
||||
'post_parent__in',
|
||||
'post_parent__not_in',
|
||||
'posts_per_page',
|
||||
'meta_query',
|
||||
'tax_query',
|
||||
'meta_key',
|
||||
'meta_value',
|
||||
'meta_compare',
|
||||
'meta_value_num',
|
||||
);
|
||||
$valid_vars = array_merge( $valid_vars, $rest_valid );
|
||||
|
||||
/**
|
||||
* Filter allowed query vars for the REST API.
|
||||
*
|
||||
* This filter allows you to add or remove query vars from the final allowed
|
||||
* list for all requests, including unauthenticated ones. To alter the
|
||||
* vars for editors only.
|
||||
*
|
||||
* @param array {
|
||||
* Array of allowed WP_Query query vars.
|
||||
*
|
||||
* @param string $allowed_query_var The query var to allow.
|
||||
* }
|
||||
*/
|
||||
$valid_vars = apply_filters( 'woocommerce_rest_query_vars', $valid_vars );
|
||||
|
||||
return $valid_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections of attachments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
|
||||
$params['context']['default'] = 'view';
|
||||
|
||||
$params['after'] = array(
|
||||
'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['before'] = array(
|
||||
'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'date-time',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['exclude'] = array(
|
||||
'description' => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
$params['include'] = array(
|
||||
'description' => __( 'Limit result set to specific ids.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
$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(
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'desc',
|
||||
'enum' => array( 'asc', 'desc' ),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['orderby'] = array(
|
||||
'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'date',
|
||||
'enum' => array(
|
||||
'date',
|
||||
'id',
|
||||
'include',
|
||||
'title',
|
||||
'slug',
|
||||
),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
$post_type_obj = get_post_type_object( $this->post_type );
|
||||
|
||||
if ( isset( $post_type_obj->hierarchical ) && $post_type_obj->hierarchical ) {
|
||||
$params['parent'] = array(
|
||||
'description' => __( 'Limit result set to those of particular parent IDs.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
'default' => array(),
|
||||
);
|
||||
$params['parent_exclude'] = array(
|
||||
'description' => __( 'Limit result set to all items except those of a particular parent ID.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
'default' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'wc/v1' === $this->namespace ) {
|
||||
$params['filter'] = array(
|
||||
'type' => 'object',
|
||||
'description' => __( 'Use WP Query arguments to modify the response; private query vars require appropriate authorization.', 'woocommerce' ),
|
||||
);
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update post meta fields.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
protected function update_post_meta_fields( $post, $request ) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,860 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API variations controller
|
||||
*
|
||||
* Handles requests to the /products/<product_id>/variations endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API variations controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Product_Variations_V2_Controller
|
||||
*/
|
||||
class WC_REST_Product_Variations_Controller extends WC_REST_Product_Variations_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Prepare a single variation output for response.
|
||||
*
|
||||
* @param WC_Data $object Object data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function prepare_object_for_response( $object, $request ) {
|
||||
$data = array(
|
||||
'id' => $object->get_id(),
|
||||
'date_created' => wc_rest_prepare_date_response( $object->get_date_created(), false ),
|
||||
'date_created_gmt' => wc_rest_prepare_date_response( $object->get_date_created() ),
|
||||
'date_modified' => wc_rest_prepare_date_response( $object->get_date_modified(), false ),
|
||||
'date_modified_gmt' => wc_rest_prepare_date_response( $object->get_date_modified() ),
|
||||
'description' => wc_format_content( $object->get_description() ),
|
||||
'permalink' => $object->get_permalink(),
|
||||
'sku' => $object->get_sku(),
|
||||
'price' => $object->get_price(),
|
||||
'regular_price' => $object->get_regular_price(),
|
||||
'sale_price' => $object->get_sale_price(),
|
||||
'date_on_sale_from' => wc_rest_prepare_date_response( $object->get_date_on_sale_from(), false ),
|
||||
'date_on_sale_from_gmt' => wc_rest_prepare_date_response( $object->get_date_on_sale_from() ),
|
||||
'date_on_sale_to' => wc_rest_prepare_date_response( $object->get_date_on_sale_to(), false ),
|
||||
'date_on_sale_to_gmt' => wc_rest_prepare_date_response( $object->get_date_on_sale_to() ),
|
||||
'on_sale' => $object->is_on_sale(),
|
||||
'status' => $object->get_status(),
|
||||
'purchasable' => $object->is_purchasable(),
|
||||
'virtual' => $object->is_virtual(),
|
||||
'downloadable' => $object->is_downloadable(),
|
||||
'downloads' => $this->get_downloads( $object ),
|
||||
'download_limit' => '' !== $object->get_download_limit() ? (int) $object->get_download_limit() : -1,
|
||||
'download_expiry' => '' !== $object->get_download_expiry() ? (int) $object->get_download_expiry() : -1,
|
||||
'tax_status' => $object->get_tax_status(),
|
||||
'tax_class' => $object->get_tax_class(),
|
||||
'manage_stock' => $object->managing_stock(),
|
||||
'stock_quantity' => $object->get_stock_quantity(),
|
||||
'stock_status' => $object->get_stock_status(),
|
||||
'backorders' => $object->get_backorders(),
|
||||
'backorders_allowed' => $object->backorders_allowed(),
|
||||
'backordered' => $object->is_on_backorder(),
|
||||
'weight' => $object->get_weight(),
|
||||
'dimensions' => array(
|
||||
'length' => $object->get_length(),
|
||||
'width' => $object->get_width(),
|
||||
'height' => $object->get_height(),
|
||||
),
|
||||
'shipping_class' => $object->get_shipping_class(),
|
||||
'shipping_class_id' => $object->get_shipping_class_id(),
|
||||
'image' => $this->get_image( $object ),
|
||||
'attributes' => $this->get_attributes( $object ),
|
||||
'menu_order' => $object->get_menu_order(),
|
||||
'meta_data' => $object->get_meta_data(),
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links( $this->prepare_links( $object, $request ) );
|
||||
|
||||
/**
|
||||
* Filter the data for a response.
|
||||
*
|
||||
* The dynamic portion of the hook name, $this->post_type,
|
||||
* refers to object type being prepared for the response.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param WC_Data $object Object data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
return apply_filters( "woocommerce_rest_prepare_{$this->post_type}_object", $response, $object, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a single variation for create or update.
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param bool $creating If is creating a new object.
|
||||
* @return WP_Error|WC_Data
|
||||
*/
|
||||
protected function prepare_object_for_database( $request, $creating = false ) {
|
||||
if ( isset( $request['id'] ) ) {
|
||||
$variation = wc_get_product( absint( $request['id'] ) );
|
||||
} else {
|
||||
$variation = new WC_Product_Variation();
|
||||
}
|
||||
|
||||
$variation->set_parent_id( absint( $request['product_id'] ) );
|
||||
|
||||
// Status.
|
||||
if ( isset( $request['status'] ) ) {
|
||||
$variation->set_status( get_post_status_object( $request['status'] ) ? $request['status'] : 'draft' );
|
||||
}
|
||||
|
||||
// SKU.
|
||||
if ( isset( $request['sku'] ) ) {
|
||||
$variation->set_sku( wc_clean( $request['sku'] ) );
|
||||
}
|
||||
|
||||
// Thumbnail.
|
||||
if ( isset( $request['image'] ) ) {
|
||||
if ( is_array( $request['image'] ) ) {
|
||||
$variation = $this->set_variation_image( $variation, $request['image'] );
|
||||
} else {
|
||||
$variation->set_image_id( '' );
|
||||
}
|
||||
}
|
||||
|
||||
// Virtual variation.
|
||||
if ( isset( $request['virtual'] ) ) {
|
||||
$variation->set_virtual( $request['virtual'] );
|
||||
}
|
||||
|
||||
// Downloadable variation.
|
||||
if ( isset( $request['downloadable'] ) ) {
|
||||
$variation->set_downloadable( $request['downloadable'] );
|
||||
}
|
||||
|
||||
// Downloads.
|
||||
if ( $variation->get_downloadable() ) {
|
||||
// Downloadable files.
|
||||
if ( isset( $request['downloads'] ) && is_array( $request['downloads'] ) ) {
|
||||
$variation = $this->save_downloadable_files( $variation, $request['downloads'] );
|
||||
}
|
||||
|
||||
// Download limit.
|
||||
if ( isset( $request['download_limit'] ) ) {
|
||||
$variation->set_download_limit( $request['download_limit'] );
|
||||
}
|
||||
|
||||
// Download expiry.
|
||||
if ( isset( $request['download_expiry'] ) ) {
|
||||
$variation->set_download_expiry( $request['download_expiry'] );
|
||||
}
|
||||
}
|
||||
|
||||
// Shipping data.
|
||||
$variation = $this->save_product_shipping_data( $variation, $request );
|
||||
|
||||
// Stock handling.
|
||||
if ( isset( $request['manage_stock'] ) ) {
|
||||
$variation->set_manage_stock( $request['manage_stock'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['stock_status'] ) ) {
|
||||
$variation->set_stock_status( $request['stock_status'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['backorders'] ) ) {
|
||||
$variation->set_backorders( $request['backorders'] );
|
||||
}
|
||||
|
||||
if ( $variation->get_manage_stock() ) {
|
||||
if ( isset( $request['stock_quantity'] ) ) {
|
||||
$variation->set_stock_quantity( $request['stock_quantity'] );
|
||||
} elseif ( isset( $request['inventory_delta'] ) ) {
|
||||
$stock_quantity = wc_stock_amount( $variation->get_stock_quantity() );
|
||||
$stock_quantity += wc_stock_amount( $request['inventory_delta'] );
|
||||
$variation->set_stock_quantity( $stock_quantity );
|
||||
}
|
||||
} else {
|
||||
$variation->set_backorders( 'no' );
|
||||
$variation->set_stock_quantity( '' );
|
||||
}
|
||||
|
||||
// Regular Price.
|
||||
if ( isset( $request['regular_price'] ) ) {
|
||||
$variation->set_regular_price( $request['regular_price'] );
|
||||
}
|
||||
|
||||
// Sale Price.
|
||||
if ( isset( $request['sale_price'] ) ) {
|
||||
$variation->set_sale_price( $request['sale_price'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['date_on_sale_from'] ) ) {
|
||||
$variation->set_date_on_sale_from( $request['date_on_sale_from'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['date_on_sale_from_gmt'] ) ) {
|
||||
$variation->set_date_on_sale_from( $request['date_on_sale_from_gmt'] ? strtotime( $request['date_on_sale_from_gmt'] ) : null );
|
||||
}
|
||||
|
||||
if ( isset( $request['date_on_sale_to'] ) ) {
|
||||
$variation->set_date_on_sale_to( $request['date_on_sale_to'] );
|
||||
}
|
||||
|
||||
if ( isset( $request['date_on_sale_to_gmt'] ) ) {
|
||||
$variation->set_date_on_sale_to( $request['date_on_sale_to_gmt'] ? strtotime( $request['date_on_sale_to_gmt'] ) : null );
|
||||
}
|
||||
|
||||
// Tax class.
|
||||
if ( isset( $request['tax_class'] ) ) {
|
||||
$variation->set_tax_class( $request['tax_class'] );
|
||||
}
|
||||
|
||||
// Description.
|
||||
if ( isset( $request['description'] ) ) {
|
||||
$variation->set_description( wp_kses_post( $request['description'] ) );
|
||||
}
|
||||
|
||||
// Update taxonomies.
|
||||
if ( isset( $request['attributes'] ) ) {
|
||||
$attributes = array();
|
||||
$parent = wc_get_product( $variation->get_parent_id() );
|
||||
|
||||
if ( ! $parent ) {
|
||||
return new WP_Error(
|
||||
// Translators: %d parent ID.
|
||||
"woocommerce_rest_{$this->post_type}_invalid_parent", sprintf( __( 'Cannot set attributes due to invalid parent product.', 'woocommerce' ), $variation->get_parent_id() ), array(
|
||||
'status' => 404,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$parent_attributes = $parent->get_attributes();
|
||||
|
||||
foreach ( $request['attributes'] as $attribute ) {
|
||||
$attribute_id = 0;
|
||||
$attribute_name = '';
|
||||
|
||||
// Check ID for global attributes or name for product attributes.
|
||||
if ( ! empty( $attribute['id'] ) ) {
|
||||
$attribute_id = absint( $attribute['id'] );
|
||||
$attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id );
|
||||
} elseif ( ! empty( $attribute['name'] ) ) {
|
||||
$attribute_name = sanitize_title( $attribute['name'] );
|
||||
}
|
||||
|
||||
if ( ! $attribute_id && ! $attribute_name ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! isset( $parent_attributes[ $attribute_name ] ) || ! $parent_attributes[ $attribute_name ]->get_variation() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attribute_key = sanitize_title( $parent_attributes[ $attribute_name ]->get_name() );
|
||||
$attribute_value = isset( $attribute['option'] ) ? wc_clean( stripslashes( $attribute['option'] ) ) : '';
|
||||
|
||||
if ( $parent_attributes[ $attribute_name ]->is_taxonomy() ) {
|
||||
// If dealing with a taxonomy, we need to get the slug from the name posted to the API.
|
||||
$term = get_term_by( 'name', $attribute_value, $attribute_name );
|
||||
|
||||
if ( $term && ! is_wp_error( $term ) ) {
|
||||
$attribute_value = $term->slug;
|
||||
} else {
|
||||
$attribute_value = sanitize_title( $attribute_value );
|
||||
}
|
||||
}
|
||||
|
||||
$attributes[ $attribute_key ] = $attribute_value;
|
||||
}
|
||||
|
||||
$variation->set_attributes( $attributes );
|
||||
}
|
||||
|
||||
// Menu order.
|
||||
if ( $request['menu_order'] ) {
|
||||
$variation->set_menu_order( $request['menu_order'] );
|
||||
}
|
||||
|
||||
// Meta data.
|
||||
if ( is_array( $request['meta_data'] ) ) {
|
||||
foreach ( $request['meta_data'] as $meta ) {
|
||||
$variation->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an object before it is inserted via the REST API.
|
||||
*
|
||||
* The dynamic portion of the hook name, `$this->post_type`,
|
||||
* refers to the object type slug.
|
||||
*
|
||||
* @param WC_Data $variation Object object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param bool $creating If is creating a new object.
|
||||
*/
|
||||
return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $variation, $request, $creating );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image for a product variation.
|
||||
*
|
||||
* @param WC_Product_Variation $variation Variation data.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_image( $variation ) {
|
||||
if ( ! $variation->get_image_id() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attachment_id = $variation->get_image_id();
|
||||
$attachment_post = get_post( $attachment_id );
|
||||
if ( is_null( $attachment_post ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attachment = wp_get_attachment_image_src( $attachment_id, 'full' );
|
||||
if ( ! is_array( $attachment ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isset( $image ) ) {
|
||||
return array(
|
||||
'id' => (int) $attachment_id,
|
||||
'date_created' => wc_rest_prepare_date_response( $attachment_post->post_date, false ),
|
||||
'date_created_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_date_gmt ) ),
|
||||
'date_modified' => wc_rest_prepare_date_response( $attachment_post->post_modified, false ),
|
||||
'date_modified_gmt' => wc_rest_prepare_date_response( strtotime( $attachment_post->post_modified_gmt ) ),
|
||||
'src' => current( $attachment ),
|
||||
'name' => get_the_title( $attachment_id ),
|
||||
'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variation image.
|
||||
*
|
||||
* @throws WC_REST_Exception REST API exceptions.
|
||||
* @param WC_Product_Variation $variation Variation instance.
|
||||
* @param array $image Image data.
|
||||
* @return WC_Product_Variation
|
||||
*/
|
||||
protected function set_variation_image( $variation, $image ) {
|
||||
$attachment_id = isset( $image['id'] ) ? absint( $image['id'] ) : 0;
|
||||
|
||||
if ( 0 === $attachment_id && isset( $image['src'] ) ) {
|
||||
$upload = wc_rest_upload_image_from_url( esc_url_raw( $image['src'] ) );
|
||||
|
||||
if ( is_wp_error( $upload ) ) {
|
||||
if ( ! apply_filters( 'woocommerce_rest_suppress_image_upload_error', false, $upload, $variation->get_id(), array( $image ) ) ) {
|
||||
throw new WC_REST_Exception( 'woocommerce_variation_image_upload_error', $upload->get_error_message(), 400 );
|
||||
}
|
||||
}
|
||||
|
||||
$attachment_id = wc_rest_set_uploaded_image_as_attachment( $upload, $variation->get_id() );
|
||||
}
|
||||
|
||||
if ( ! wp_attachment_is_image( $attachment_id ) ) {
|
||||
/* translators: %s: attachment ID */
|
||||
throw new WC_REST_Exception( 'woocommerce_variation_invalid_image_id', sprintf( __( '#%s is an invalid image ID.', 'woocommerce' ), $attachment_id ), 400 );
|
||||
}
|
||||
|
||||
$variation->set_image_id( $attachment_id );
|
||||
|
||||
// Set the image alt if present.
|
||||
if ( ! empty( $image['alt'] ) ) {
|
||||
update_post_meta( $attachment_id, '_wp_attachment_image_alt', wc_clean( $image['alt'] ) );
|
||||
}
|
||||
|
||||
// Set the image name if present.
|
||||
if ( ! empty( $image['name'] ) ) {
|
||||
wp_update_post(
|
||||
array(
|
||||
'ID' => $attachment_id,
|
||||
'post_title' => $image['name'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $variation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Variation's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$weight_unit = get_option( 'woocommerce_weight_unit' );
|
||||
$dimension_unit = get_option( 'woocommerce_dimension_unit' );
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => $this->post_type,
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_created' => array(
|
||||
'description' => __( "The date the variation was created, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_modified' => array(
|
||||
'description' => __( "The date the variation was last modified, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Variation description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'permalink' => array(
|
||||
'description' => __( 'Variation URL.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'uri',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'sku' => array(
|
||||
'description' => __( 'Unique identifier.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'price' => array(
|
||||
'description' => __( 'Current variation price.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'regular_price' => array(
|
||||
'description' => __( 'Variation regular price.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'sale_price' => array(
|
||||
'description' => __( 'Variation sale price.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'date_on_sale_from' => array(
|
||||
'description' => __( "Start date of sale price, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'date_on_sale_from_gmt' => array(
|
||||
'description' => __( 'Start date of sale price, as GMT.', 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'date_on_sale_to' => array(
|
||||
'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'date_on_sale_to_gmt' => array(
|
||||
'description' => __( "End date of sale price, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'on_sale' => array(
|
||||
'description' => __( 'Shows if the variation is on sale.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'status' => array(
|
||||
'description' => __( 'Variation status.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'publish',
|
||||
'enum' => array_keys( get_post_statuses() ),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'purchasable' => array(
|
||||
'description' => __( 'Shows if the variation can be bought.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'virtual' => array(
|
||||
'description' => __( 'If the variation is virtual.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'downloadable' => array(
|
||||
'description' => __( 'If the variation is downloadable.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'downloads' => array(
|
||||
'description' => __( 'List of downloadable files.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'File ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'File name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'file' => array(
|
||||
'description' => __( 'File URL.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'download_limit' => array(
|
||||
'description' => __( 'Number of times downloadable files can be downloaded after purchase.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => -1,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'download_expiry' => array(
|
||||
'description' => __( 'Number of days until access to downloadable files expires.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => -1,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'tax_status' => array(
|
||||
'description' => __( 'Tax status.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'taxable',
|
||||
'enum' => array( 'taxable', 'shipping', 'none' ),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'tax_class' => array(
|
||||
'description' => __( 'Tax class.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'manage_stock' => array(
|
||||
'description' => __( 'Stock management at variation level.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'stock_quantity' => array(
|
||||
'description' => __( 'Stock quantity.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'stock_status' => array(
|
||||
'description' => __( 'Controls the stock status of the product.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'instock',
|
||||
'enum' => array_keys( wc_get_product_stock_status_options() ),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'backorders' => array(
|
||||
'description' => __( 'If managing stock, this controls if backorders are allowed.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'no',
|
||||
'enum' => array( 'no', 'notify', 'yes' ),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'backorders_allowed' => array(
|
||||
'description' => __( 'Shows if backorders are allowed.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'backordered' => array(
|
||||
'description' => __( 'Shows if the variation is on backordered.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'weight' => array(
|
||||
/* translators: %s: weight unit */
|
||||
'description' => sprintf( __( 'Variation weight (%s).', 'woocommerce' ), $weight_unit ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'dimensions' => array(
|
||||
'description' => __( 'Variation dimensions.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'length' => array(
|
||||
/* translators: %s: dimension unit */
|
||||
'description' => sprintf( __( 'Variation length (%s).', 'woocommerce' ), $dimension_unit ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'width' => array(
|
||||
/* translators: %s: dimension unit */
|
||||
'description' => sprintf( __( 'Variation width (%s).', 'woocommerce' ), $dimension_unit ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'height' => array(
|
||||
/* translators: %s: dimension unit */
|
||||
'description' => sprintf( __( 'Variation height (%s).', 'woocommerce' ), $dimension_unit ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'shipping_class' => array(
|
||||
'description' => __( 'Shipping class slug.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'shipping_class_id' => array(
|
||||
'description' => __( 'Shipping class ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'image' => array(
|
||||
'description' => __( 'Variation image data.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Image ID.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'date_created' => array(
|
||||
'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_created_gmt' => array(
|
||||
'description' => __( 'The date the image was created, as GMT.', 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_modified' => array(
|
||||
'description' => __( "The date the image was last modified, in the site's timezone.", 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_modified_gmt' => array(
|
||||
'description' => __( 'The date the image was last modified, as GMT.', 'woocommerce' ),
|
||||
'type' => 'date-time',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'src' => array(
|
||||
'description' => __( 'Image URL.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'format' => 'uri',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Image name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'alt' => array(
|
||||
'description' => __( 'Image alternative text.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'description' => __( 'List of attributes.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Attribute ID.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Attribute name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'option' => array(
|
||||
'description' => __( 'Selected attribute term name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => array(
|
||||
'description' => __( 'Menu order, used to custom sort products.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'meta_data' => array(
|
||||
'description' => __( 'Meta data.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'items' => array(
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Meta ID.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'key' => array(
|
||||
'description' => __( 'Meta key.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Meta value.', 'woocommerce' ),
|
||||
'type' => 'mixed',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare objects query.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
$args = WC_REST_CRUD_Controller::prepare_objects_query( $request );
|
||||
|
||||
// Set post_status.
|
||||
$args['post_status'] = $request['status'];
|
||||
|
||||
// Filter by sku.
|
||||
if ( ! empty( $request['sku'] ) ) {
|
||||
$skus = explode( ',', $request['sku'] );
|
||||
// Include the current string as a SKU too.
|
||||
if ( 1 < count( $skus ) ) {
|
||||
$skus[] = $request['sku'];
|
||||
}
|
||||
|
||||
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
|
||||
$args,
|
||||
array(
|
||||
'key' => '_sku',
|
||||
'value' => $skus,
|
||||
'compare' => 'IN',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Filter by tax class.
|
||||
if ( ! empty( $request['tax_class'] ) ) {
|
||||
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
|
||||
$args,
|
||||
array(
|
||||
'key' => '_tax_class',
|
||||
'value' => 'standard' !== $request['tax_class'] ? $request['tax_class'] : '',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Price filter.
|
||||
if ( ! empty( $request['min_price'] ) || ! empty( $request['max_price'] ) ) {
|
||||
$args['meta_query'] = $this->add_meta_query( $args, wc_get_min_max_price_meta_query( $request ) ); // WPCS: slow query ok.
|
||||
}
|
||||
|
||||
// Filter product based on stock_status.
|
||||
if ( ! empty( $request['stock_status'] ) ) {
|
||||
$args['meta_query'] = $this->add_meta_query( // WPCS: slow query ok.
|
||||
$args,
|
||||
array(
|
||||
'key' => '_stock_status',
|
||||
'value' => $request['stock_status'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Filter by on sale products.
|
||||
if ( is_bool( $request['on_sale'] ) ) {
|
||||
$on_sale_key = $request['on_sale'] ? 'post__in' : 'post__not_in';
|
||||
$on_sale_ids = wc_get_product_ids_on_sale();
|
||||
|
||||
// Use 0 when there's no on sale products to avoid return all products.
|
||||
$on_sale_ids = empty( $on_sale_ids ) ? array( 0 ) : $on_sale_ids;
|
||||
|
||||
$args[ $on_sale_key ] += $on_sale_ids;
|
||||
}
|
||||
|
||||
// Force the post_type argument, since it's not a user input variable.
|
||||
if ( ! empty( $request['sku'] ) ) {
|
||||
$args['post_type'] = array( 'product', 'product_variation' );
|
||||
} else {
|
||||
$args['post_type'] = $this->post_type;
|
||||
}
|
||||
|
||||
$args['post_parent'] = $request['product_id'];
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections of attachments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
|
||||
unset(
|
||||
$params['in_stock'],
|
||||
$params['type'],
|
||||
$params['featured'],
|
||||
$params['category'],
|
||||
$params['tag'],
|
||||
$params['shipping_class'],
|
||||
$params['attribute'],
|
||||
$params['attribute_term']
|
||||
);
|
||||
|
||||
$params['stock_status'] = array(
|
||||
'description' => __( 'Limit result set to products with specified stock status.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'enum' => array_keys( wc_get_product_stock_status_options() ),
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Reports Coupons Totals controller
|
||||
*
|
||||
* Handles requests to the /reports/coupons/count endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Reports Coupons Totals controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Reports_Controller
|
||||
*/
|
||||
class WC_REST_Report_Coupons_Totals_Controller extends WC_REST_Reports_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'reports/coupons/totals';
|
||||
|
||||
/**
|
||||
* Get reports list.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
global $wpdb;
|
||||
|
||||
$data = get_transient( 'rest_api_coupons_type_count' );
|
||||
if ( false !== $data ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$types = wc_get_coupon_types();
|
||||
$data = array();
|
||||
|
||||
foreach ( $types as $slug => $name ) {
|
||||
$results = $wpdb->get_results(
|
||||
$wpdb->prepare( "
|
||||
SELECT count(meta_id) AS total
|
||||
FROM $wpdb->postmeta
|
||||
WHERE meta_key = 'discount_type'
|
||||
AND meta_value = %s
|
||||
", $slug )
|
||||
);
|
||||
|
||||
$total = isset( $results[0] ) ? (int) $results[0]->total : 0;
|
||||
|
||||
$data[] = array(
|
||||
'slug' => $slug,
|
||||
'name' => $name,
|
||||
'total' => $total,
|
||||
);
|
||||
}
|
||||
|
||||
set_transient( 'rest_api_coupons_type_count', $data, YEAR_IN_SECONDS );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report object for serialization.
|
||||
*
|
||||
* @param stdClass $report Report data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $report, $request ) {
|
||||
$data = array(
|
||||
'slug' => $report->slug,
|
||||
'name' => $report->name,
|
||||
'total' => $report->total,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
/**
|
||||
* Filter a report returned from the API.
|
||||
*
|
||||
* Allows modification of the report data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param object $report The original report object.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_report_coupons_count', $response, $report, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Report's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'report_coupon_total',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'An alphanumeric identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Coupon type name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'total' => array(
|
||||
'description' => __( 'Amount of coupons.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Reports Customers Totals controller
|
||||
*
|
||||
* Handles requests to the /reports/customers/count endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Reports Customers Totals controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Reports_Controller
|
||||
*/
|
||||
class WC_REST_Report_Customers_Totals_Controller extends WC_REST_Reports_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'reports/customers/totals';
|
||||
|
||||
/**
|
||||
* Get reports list.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
$users_count = count_users();
|
||||
$total_customers = 0;
|
||||
|
||||
foreach ( $users_count['avail_roles'] as $role => $total ) {
|
||||
if ( in_array( $role, array( 'administrator', 'shop_manager' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$total_customers += (int) $total;
|
||||
}
|
||||
|
||||
$customers_query = new WP_User_Query(
|
||||
array(
|
||||
'role__not_in' => array( 'administrator', 'shop_manager' ),
|
||||
'number' => 0,
|
||||
'fields' => 'ID',
|
||||
'count_total' => true,
|
||||
'meta_query' => array( // WPCS: slow query ok.
|
||||
array(
|
||||
'key' => 'paying_customer',
|
||||
'value' => 1,
|
||||
'compare' => '=',
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$total_paying = (int) $customers_query->get_total();
|
||||
|
||||
$data = array(
|
||||
array(
|
||||
'slug' => 'paying',
|
||||
'name' => __( 'Paying customer', 'woocommerce' ),
|
||||
'total' => $total_paying,
|
||||
),
|
||||
array(
|
||||
'slug' => 'non_paying',
|
||||
'name' => __( 'Non-paying customer', 'woocommerce' ),
|
||||
'total' => $total_customers - $total_paying,
|
||||
),
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report object for serialization.
|
||||
*
|
||||
* @param stdClass $report Report data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $report, $request ) {
|
||||
$data = array(
|
||||
'slug' => $report->slug,
|
||||
'name' => $report->name,
|
||||
'total' => $report->total,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
/**
|
||||
* Filter a report returned from the API.
|
||||
*
|
||||
* Allows modification of the report data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param object $report The original report object.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_report_customers_count', $response, $report, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Report's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'report_customer_total',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'An alphanumeric identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Customer type name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'total' => array(
|
||||
'description' => __( 'Amount of customers.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Reports Orders Totals controller
|
||||
*
|
||||
* Handles requests to the /reports/orders/count endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Reports Orders Totals controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Reports_Controller
|
||||
*/
|
||||
class WC_REST_Report_Orders_Totals_Controller extends WC_REST_Reports_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'reports/orders/totals';
|
||||
|
||||
/**
|
||||
* Get reports list.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
$totals = wp_count_posts( 'shop_order' );
|
||||
$data = array();
|
||||
|
||||
foreach ( wc_get_order_statuses() as $slug => $name ) {
|
||||
if ( ! isset( $totals->$slug ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = array(
|
||||
'slug' => str_replace( 'wc-', '', $slug ),
|
||||
'name' => $name,
|
||||
'total' => (int) $totals->$slug,
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report object for serialization.
|
||||
*
|
||||
* @param stdClass $report Report data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $report, $request ) {
|
||||
$data = array(
|
||||
'slug' => $report->slug,
|
||||
'name' => $report->name,
|
||||
'total' => $report->total,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
/**
|
||||
* Filter a report returned from the API.
|
||||
*
|
||||
* Allows modification of the report data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param object $report The original report object.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_report_orders_count', $response, $report, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Report's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'report_order_total',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'An alphanumeric identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Order status name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'total' => array(
|
||||
'description' => __( 'Amount of orders.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Reports Products Totals controller
|
||||
*
|
||||
* Handles requests to the /reports/products/count endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Reports Products Totals controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Reports_Controller
|
||||
*/
|
||||
class WC_REST_Report_Products_Totals_Controller extends WC_REST_Reports_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'reports/products/totals';
|
||||
|
||||
/**
|
||||
* Get reports list.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
$types = wc_get_product_types();
|
||||
$terms = get_terms(
|
||||
array(
|
||||
'taxonomy' => 'product_type',
|
||||
'hide_empty' => false,
|
||||
)
|
||||
);
|
||||
$data = array();
|
||||
|
||||
foreach ( $terms as $product_type ) {
|
||||
if ( ! isset( $types[ $product_type->name ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data[] = array(
|
||||
'slug' => $product_type->name,
|
||||
'name' => $types[ $product_type->name ],
|
||||
'total' => (int) $product_type->count,
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report object for serialization.
|
||||
*
|
||||
* @param stdClass $report Report data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $report, $request ) {
|
||||
$data = array(
|
||||
'slug' => $report->slug,
|
||||
'name' => $report->name,
|
||||
'total' => $report->total,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
/**
|
||||
* Filter a report returned from the API.
|
||||
*
|
||||
* Allows modification of the report data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param object $report The original report object.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_report_products_count', $response, $report, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Report's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'report_product_total',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'An alphanumeric identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Product type name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'total' => array(
|
||||
'description' => __( 'Amount of products.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Reports Reviews Totals controller
|
||||
*
|
||||
* Handles requests to the /reports/reviews/count endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Reports Reviews Totals controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Reports_Controller
|
||||
*/
|
||||
class WC_REST_Report_Reviews_Totals_Controller extends WC_REST_Reports_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'reports/reviews/totals';
|
||||
|
||||
/**
|
||||
* Get reports list.
|
||||
*
|
||||
* @since 3.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_reports() {
|
||||
$data = array();
|
||||
|
||||
$query_data = array(
|
||||
'count' => true,
|
||||
'post_type' => 'product',
|
||||
'meta_key' => 'rating', // WPCS: slow query ok.
|
||||
'meta_value' => '', // WPCS: slow query ok.
|
||||
);
|
||||
|
||||
for ( $i = 1; $i <= 5; $i++ ) {
|
||||
$query_data['meta_value'] = $i;
|
||||
|
||||
$data[] = array(
|
||||
'slug' => 'rated_' . $i . '_out_of_5',
|
||||
/* translators: %s: average rating */
|
||||
'name' => sprintf( __( 'Rated %s out of 5', 'woocommerce' ), $i ),
|
||||
'total' => (int) get_comments( $query_data ),
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report object for serialization.
|
||||
*
|
||||
* @param stdClass $report Report data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $report, $request ) {
|
||||
$data = array(
|
||||
'slug' => $report->slug,
|
||||
'name' => $report->name,
|
||||
'total' => $report->total,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
/**
|
||||
* Filter a report returned from the API.
|
||||
*
|
||||
* Allows modification of the report data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param object $report The original report object.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_report_reviews_count', $response, $report, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Report's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'report_review_total',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'slug' => array(
|
||||
'description' => __( 'An alphanumeric identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Review type name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'total' => array(
|
||||
'description' => __( 'Amount of reviews.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Setting Options controller
|
||||
*
|
||||
* Handles requests to the /settings/$group/$setting endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Setting Options controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Setting_Options_V2_Controller
|
||||
*/
|
||||
class WC_REST_Setting_Options_Controller extends WC_REST_Setting_Options_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Get setting data.
|
||||
*
|
||||
* @param string $group_id Group ID.
|
||||
* @param string $setting_id Setting ID.
|
||||
* @return stdClass|WP_Error
|
||||
*/
|
||||
public function get_setting( $group_id, $setting_id ) {
|
||||
$setting = parent::get_setting( $group_id, $setting_id );
|
||||
if ( is_wp_error( $setting ) ) {
|
||||
return $setting;
|
||||
}
|
||||
$setting['group_id'] = $group_id;
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for allowed keys for each setting response.
|
||||
*
|
||||
* @param string $key Key to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function allowed_setting_keys( $key ) {
|
||||
return in_array(
|
||||
$key, array(
|
||||
'id',
|
||||
'group_id',
|
||||
'label',
|
||||
'description',
|
||||
'default',
|
||||
'tip',
|
||||
'placeholder',
|
||||
'type',
|
||||
'options',
|
||||
'value',
|
||||
'option_key',
|
||||
), true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all settings in a group.
|
||||
*
|
||||
* @param string $group_id Group ID.
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function get_group_settings( $group_id ) {
|
||||
if ( empty( $group_id ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$settings = apply_filters( 'woocommerce_settings-' . $group_id, array() ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
|
||||
if ( empty( $settings ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$filtered_settings = array();
|
||||
foreach ( $settings as $setting ) {
|
||||
$option_key = $setting['option_key'];
|
||||
$setting = $this->filter_setting( $setting );
|
||||
$default = isset( $setting['default'] ) ? $setting['default'] : '';
|
||||
// Get the option value.
|
||||
if ( is_array( $option_key ) ) {
|
||||
$option = get_option( $option_key[0] );
|
||||
$setting['value'] = isset( $option[ $option_key[1] ] ) ? $option[ $option_key[1] ] : $default;
|
||||
} else {
|
||||
$admin_setting_value = WC_Admin_Settings::get_option( $option_key, $default );
|
||||
$setting['value'] = $admin_setting_value;
|
||||
}
|
||||
|
||||
if ( 'multi_select_countries' === $setting['type'] ) {
|
||||
$setting['options'] = WC()->countries->get_countries();
|
||||
$setting['type'] = 'multiselect';
|
||||
} elseif ( 'single_select_country' === $setting['type'] ) {
|
||||
$setting['type'] = 'select';
|
||||
$setting['options'] = $this->get_countries_and_states();
|
||||
} elseif ( 'single_select_page' === $setting['type'] ) {
|
||||
$pages = get_pages(
|
||||
array(
|
||||
'sort_column' => 'menu_order',
|
||||
'sort_order' => 'ASC',
|
||||
'hierarchical' => 0,
|
||||
)
|
||||
);
|
||||
$options = array();
|
||||
foreach ( $pages as $page ) {
|
||||
$options[ $page->ID ] = ! empty( $page->post_title ) ? $page->post_title : '#' . $page->ID;
|
||||
}
|
||||
$setting['type'] = 'select';
|
||||
$setting['options'] = $options;
|
||||
}
|
||||
|
||||
$filtered_settings[] = $setting;
|
||||
}
|
||||
|
||||
return $filtered_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of countries and states for use in the base location setting.
|
||||
*
|
||||
* @since 3.0.7
|
||||
* @return array Array of states and countries.
|
||||
*/
|
||||
private function get_countries_and_states() {
|
||||
$countries = WC()->countries->get_countries();
|
||||
if ( ! $countries ) {
|
||||
return array();
|
||||
}
|
||||
$output = array();
|
||||
foreach ( $countries as $key => $value ) {
|
||||
$states = WC()->countries->get_states( $key );
|
||||
|
||||
if ( $states ) {
|
||||
foreach ( $states as $state_key => $state_value ) {
|
||||
$output[ $key . ':' . $state_key ] = $value . ' - ' . $state_value;
|
||||
}
|
||||
} else {
|
||||
$output[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'setting',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'group_id' => array(
|
||||
'description' => __( 'An identifier for the group this setting belongs to.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Setting value.', 'woocommerce' ),
|
||||
'type' => 'mixed',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'default' => array(
|
||||
'description' => __( 'Default value for the setting.', 'woocommerce' ),
|
||||
'type' => 'mixed',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'tip' => array(
|
||||
'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'placeholder' => array(
|
||||
'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Type of setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'options' => array(
|
||||
'description' => __( 'Array of options (key value pairs) for inputs such as select, multiselect, and radio buttons.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,581 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Setting Options controller
|
||||
*
|
||||
* Handles requests to the /settings/$group/$setting endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Setting Options controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Setting_Options_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* WP REST API namespace/version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'settings/(?P<group_id>[\w-]+)';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
'args' => array(
|
||||
'group' => array(
|
||||
'description' => __( 'Settings group ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/batch', array(
|
||||
'args' => array(
|
||||
'group' => array(
|
||||
'description' => __( 'Settings group ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'batch_items' ),
|
||||
'permission_callback' => array( $this, 'update_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_batch_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<id>[\w-]+)', array(
|
||||
'args' => array(
|
||||
'group' => array(
|
||||
'description' => __( 'Settings group ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single setting.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$setting = $this->get_setting( $request['group_id'], $request['id'] );
|
||||
|
||||
if ( is_wp_error( $setting ) ) {
|
||||
return $setting;
|
||||
}
|
||||
|
||||
$response = $this->prepare_item_for_response( $setting, $request );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all settings in a group.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$settings = $this->get_group_settings( $request['group_id'] );
|
||||
|
||||
if ( is_wp_error( $settings ) ) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ( $settings as $setting_obj ) {
|
||||
$setting = $this->prepare_item_for_response( $setting_obj, $request );
|
||||
$setting = $this->prepare_response_for_collection( $setting );
|
||||
if ( $this->is_setting_type_valid( $setting['type'] ) ) {
|
||||
$data[] = $setting;
|
||||
}
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all settings in a group.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $group_id Group ID.
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
public function get_group_settings( $group_id ) {
|
||||
if ( empty( $group_id ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$settings = apply_filters( 'woocommerce_settings-' . $group_id, array() );
|
||||
|
||||
if ( empty( $settings ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_group_invalid', __( 'Invalid setting group.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$filtered_settings = array();
|
||||
foreach ( $settings as $setting ) {
|
||||
$option_key = $setting['option_key'];
|
||||
$setting = $this->filter_setting( $setting );
|
||||
$default = isset( $setting['default'] ) ? $setting['default'] : '';
|
||||
// Get the option value.
|
||||
if ( is_array( $option_key ) ) {
|
||||
$option = get_option( $option_key[0] );
|
||||
$setting['value'] = isset( $option[ $option_key[1] ] ) ? $option[ $option_key[1] ] : $default;
|
||||
} else {
|
||||
$admin_setting_value = WC_Admin_Settings::get_option( $option_key, $default );
|
||||
$setting['value'] = $admin_setting_value;
|
||||
}
|
||||
|
||||
if ( 'multi_select_countries' === $setting['type'] ) {
|
||||
$setting['options'] = WC()->countries->get_countries();
|
||||
$setting['type'] = 'multiselect';
|
||||
} elseif ( 'single_select_country' === $setting['type'] ) {
|
||||
$setting['type'] = 'select';
|
||||
$setting['options'] = $this->get_countries_and_states();
|
||||
}
|
||||
|
||||
$filtered_settings[] = $setting;
|
||||
}
|
||||
|
||||
return $filtered_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of countries and states for use in the base location setting.
|
||||
*
|
||||
* @since 3.0.7
|
||||
* @return array Array of states and countries.
|
||||
*/
|
||||
private function get_countries_and_states() {
|
||||
$countries = WC()->countries->get_countries();
|
||||
if ( ! $countries ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ( $countries as $key => $value ) {
|
||||
$states = WC()->countries->get_states( $key );
|
||||
if ( $states ) {
|
||||
foreach ( $states as $state_key => $state_value ) {
|
||||
$output[ $key . ':' . $state_key ] = $value . ' - ' . $state_value;
|
||||
}
|
||||
} else {
|
||||
$output[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setting data.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $group_id Group ID.
|
||||
* @param string $setting_id Setting ID.
|
||||
* @return stdClass|WP_Error
|
||||
*/
|
||||
public function get_setting( $group_id, $setting_id ) {
|
||||
if ( empty( $setting_id ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$settings = $this->get_group_settings( $group_id );
|
||||
|
||||
if ( is_wp_error( $settings ) ) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$array_key = array_keys( wp_list_pluck( $settings, 'id' ), $setting_id );
|
||||
|
||||
if ( empty( $array_key ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$setting = $settings[ $array_key[0] ];
|
||||
|
||||
if ( ! $this->is_setting_type_valid( $setting['type'] ) ) {
|
||||
return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk create, update and delete items.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Of WP_Error or WP_REST_Response.
|
||||
*/
|
||||
public function batch_items( $request ) {
|
||||
// Get the request params.
|
||||
$items = array_filter( $request->get_params() );
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
if ( ! empty( $items['update'] ) ) {
|
||||
$to_update = array();
|
||||
foreach ( $items['update'] as $item ) {
|
||||
$to_update[] = 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single setting in a group.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$setting = $this->get_setting( $request['group_id'], $request['id'] );
|
||||
|
||||
if ( is_wp_error( $setting ) ) {
|
||||
return $setting;
|
||||
}
|
||||
|
||||
if ( is_callable( array( $this, 'validate_setting_' . $setting['type'] . '_field' ) ) ) {
|
||||
$value = $this->{'validate_setting_' . $setting['type'] . '_field'}( $request['value'], $setting );
|
||||
} else {
|
||||
$value = $this->validate_setting_text_field( $request['value'], $setting );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $value ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( is_array( $setting['option_key'] ) ) {
|
||||
$setting['value'] = $value;
|
||||
$option_key = $setting['option_key'];
|
||||
$prev = get_option( $option_key[0] );
|
||||
$prev[ $option_key[1] ] = $request['value'];
|
||||
update_option( $option_key[0], $prev );
|
||||
} else {
|
||||
$update_data = array();
|
||||
$update_data[ $setting['option_key'] ] = $value;
|
||||
$setting['value'] = $value;
|
||||
WC_Admin_Settings::save_fields( array( $setting ), $update_data );
|
||||
}
|
||||
|
||||
$response = $this->prepare_item_for_response( $setting, $request );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a single setting object for response.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param object $item Setting object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
unset( $item['option_key'] );
|
||||
$data = $this->filter_setting( $item );
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, empty( $request['context'] ) ? 'view' : $request['context'] );
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links( $this->prepare_links( $data['id'], $request['group_id'] ) );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $setting_id Setting ID.
|
||||
* @param string $group_id Group ID.
|
||||
* @return array Links for the given setting.
|
||||
*/
|
||||
protected function prepare_links( $setting_id, $group_id ) {
|
||||
$base = str_replace( '(?P<group_id>[\w-]+)', $group_id, $this->rest_base );
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $base, $setting_id ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current user has access to READ the settings APIs.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current user has access to WRITE the settings APIs.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out bad values from the settings array/filter so we
|
||||
* only return known values via the API.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $setting Settings.
|
||||
* @return array
|
||||
*/
|
||||
public function filter_setting( $setting ) {
|
||||
$setting = array_intersect_key(
|
||||
$setting,
|
||||
array_flip( array_filter( array_keys( $setting ), array( $this, 'allowed_setting_keys' ) ) )
|
||||
);
|
||||
|
||||
if ( empty( $setting['options'] ) ) {
|
||||
unset( $setting['options'] );
|
||||
}
|
||||
|
||||
if ( 'image_width' === $setting['type'] ) {
|
||||
$setting = $this->cast_image_width( $setting );
|
||||
}
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* For image_width, Crop can return "0" instead of false -- so we want
|
||||
* to make sure we return these consistently the same we accept them.
|
||||
*
|
||||
* @todo remove in 4.0
|
||||
* @since 3.0.0
|
||||
* @param array $setting Settings.
|
||||
* @return array
|
||||
*/
|
||||
public function cast_image_width( $setting ) {
|
||||
foreach ( array( 'default', 'value' ) as $key ) {
|
||||
if ( isset( $setting[ $key ] ) ) {
|
||||
$setting[ $key ]['width'] = intval( $setting[ $key ]['width'] );
|
||||
$setting[ $key ]['height'] = intval( $setting[ $key ]['height'] );
|
||||
$setting[ $key ]['crop'] = (bool) $setting[ $key ]['crop'];
|
||||
}
|
||||
}
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for allowed keys for each setting response.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $key Key to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function allowed_setting_keys( $key ) {
|
||||
return in_array(
|
||||
$key, array(
|
||||
'id',
|
||||
'label',
|
||||
'description',
|
||||
'default',
|
||||
'tip',
|
||||
'placeholder',
|
||||
'type',
|
||||
'options',
|
||||
'value',
|
||||
'option_key',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean for if a setting type is a valid supported setting type.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $type Type.
|
||||
* @return bool
|
||||
*/
|
||||
public function is_setting_type_valid( $type ) {
|
||||
return in_array(
|
||||
$type, array(
|
||||
'text', // Validates with validate_setting_text_field.
|
||||
'email', // Validates with validate_setting_text_field.
|
||||
'number', // Validates with validate_setting_text_field.
|
||||
'color', // Validates with validate_setting_text_field.
|
||||
'password', // Validates with validate_setting_text_field.
|
||||
'textarea', // Validates with validate_setting_textarea_field.
|
||||
'select', // Validates with validate_setting_select_field.
|
||||
'multiselect', // Validates with validate_setting_multiselect_field.
|
||||
'radio', // Validates with validate_setting_radio_field (-> validate_setting_select_field).
|
||||
'checkbox', // Validates with validate_setting_checkbox_field.
|
||||
'image_width', // Validates with validate_setting_image_width_field.
|
||||
'thumbnail_cropping', // Validates with validate_setting_text_field.
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'setting',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Setting value.', 'woocommerce' ),
|
||||
'type' => 'mixed',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'default' => array(
|
||||
'description' => __( 'Default value for the setting.', 'woocommerce' ),
|
||||
'type' => 'mixed',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'tip' => array(
|
||||
'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'placeholder' => array(
|
||||
'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Type of setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox', 'thumbnail_cropping' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'options' => array(
|
||||
'description' => __( 'Array of options (key value pairs) for inputs such as select, multiselect, and radio buttons.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Settings controller
|
||||
*
|
||||
* Handles requests to the /settings endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Settings controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Settings_V2_Controller
|
||||
*/
|
||||
class WC_REST_Settings_Controller extends WC_REST_Settings_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
parent::register_routes();
|
||||
register_rest_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' ),
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current user has access to WRITE the settings APIs.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
* @return WP_Error|bool
|
||||
*/
|
||||
public function update_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a setting.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$options_controller = new WC_REST_Setting_Options_Controller();
|
||||
$response = $options_controller->update_item( $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'setting_group',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier that can be used to link settings together.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'parent_id' => array(
|
||||
'description' => __( 'ID of parent grouping.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'sub_groups' => array(
|
||||
'description' => __( 'IDs for settings sub groups.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Settings controller
|
||||
*
|
||||
* Handles requests to the /settings endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Settings controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Settings_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* WP REST API namespace/version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'settings';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all settings groups items.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$groups = apply_filters( 'woocommerce_settings_groups', array() );
|
||||
if ( empty( $groups ) ) {
|
||||
return new WP_Error( 'rest_setting_groups_empty', __( 'No setting groups have been registered.', 'woocommerce' ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
$defaults = $this->group_defaults();
|
||||
$filtered_groups = array();
|
||||
foreach ( $groups as $group ) {
|
||||
$sub_groups = array();
|
||||
foreach ( $groups as $_group ) {
|
||||
if ( ! empty( $_group['parent_id'] ) && $group['id'] === $_group['parent_id'] ) {
|
||||
$sub_groups[] = $_group['id'];
|
||||
}
|
||||
}
|
||||
$group['sub_groups'] = $sub_groups;
|
||||
|
||||
$group = wp_parse_args( $group, $defaults );
|
||||
if ( ! is_null( $group['id'] ) && ! is_null( $group['label'] ) ) {
|
||||
$group_obj = $this->filter_group( $group );
|
||||
$group_data = $this->prepare_item_for_response( $group_obj, $request );
|
||||
$group_data = $this->prepare_response_for_collection( $group_data );
|
||||
|
||||
$filtered_groups[] = $group_data;
|
||||
}
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $filtered_groups );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param string $group_id Group ID.
|
||||
* @return array Links for the given group.
|
||||
*/
|
||||
protected function prepare_links( $group_id ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
||||
$links = array(
|
||||
'options' => array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $group_id ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a report sales object for serialization.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $item Group object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$context = empty( $request['context'] ) ? 'view' : $request['context'];
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $item['id'] ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out bad values from the groups array/filter so we
|
||||
* only return known values via the API.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param array $group Group.
|
||||
* @return array
|
||||
*/
|
||||
public function filter_group( $group ) {
|
||||
return array_intersect_key(
|
||||
$group,
|
||||
array_flip( array_filter( array_keys( $group ), array( $this, 'allowed_group_keys' ) ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for allowed keys for each group response.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param string $key Key to check.
|
||||
* @return boolean
|
||||
*/
|
||||
public function allowed_group_keys( $key ) {
|
||||
return in_array( $key, array( 'id', 'label', 'description', 'parent_id', 'sub_groups' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns default settings for groups. null means the field is required.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return array
|
||||
*/
|
||||
protected function group_defaults() {
|
||||
return array(
|
||||
'id' => null,
|
||||
'label' => null,
|
||||
'description' => '',
|
||||
'parent_id' => '',
|
||||
'sub_groups' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current user has access to READ the settings APIs.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups schema, conforming to JSON Schema.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'setting_group',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier that can be used to link settings together.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'parent_id' => array(
|
||||
'description' => __( 'ID of parent grouping.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'sub_groups' => array(
|
||||
'description' => __( 'IDs for settings sub groups.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC Shipping Methods controller
|
||||
*
|
||||
* Handles requests to the /shipping_methods endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Shipping methods controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Methods_V2_Controller
|
||||
*/
|
||||
class WC_REST_Shipping_Methods_Controller extends WC_REST_Shipping_Methods_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC Shipping Methods controller
|
||||
*
|
||||
* Handles requests to the /shipping_methods endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Shipping methods controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_Shipping_Methods_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'shipping_methods';
|
||||
|
||||
/**
|
||||
* Register the route for /shipping_methods and /shipping_methods/<method>
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
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' ),
|
||||
)
|
||||
);
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<id>[\w-]+)', array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
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' ) ),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to view shipping methods.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'shipping_methods', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read a shipping method.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'shipping_methods', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shipping methods.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
$response = array();
|
||||
foreach ( $wc_shipping->get_shipping_methods() as $id => $shipping_method ) {
|
||||
$method = $this->prepare_item_for_response( $shipping_method, $request );
|
||||
$method = $this->prepare_response_for_collection( $method );
|
||||
$response[] = $method;
|
||||
}
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single Shipping Method.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
$methods = $wc_shipping->get_shipping_methods();
|
||||
if ( empty( $methods[ $request['id'] ] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$method = $methods[ $request['id'] ];
|
||||
$response = $this->prepare_item_for_response( $method, $request );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a shipping method for response.
|
||||
*
|
||||
* @param WC_Shipping_Method $method Shipping method object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $method, $request ) {
|
||||
$data = array(
|
||||
'id' => $method->id,
|
||||
'title' => $method->method_title,
|
||||
'description' => $method->method_description,
|
||||
);
|
||||
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $method, $request ) );
|
||||
|
||||
/**
|
||||
* Filter shipping methods object returned from the REST API.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param WC_Shipping_Method $method Shipping method object used to create response.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_shipping_method', $response, $method, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param WC_Shipping_Method $method Shipping method object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_links( $method, $request ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $method->id ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shipping method schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'shipping_method',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Method ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => __( 'Shipping method title.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Shipping method description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any query params needed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
return array(
|
||||
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zone Locations controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones/<id>/locations endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zone Locations class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zone_Locations_V2_Controller
|
||||
*/
|
||||
class WC_REST_Shipping_Zone_Locations_Controller extends WC_REST_Shipping_Zone_Locations_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zone Locations controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones/<id>/locations endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zone Locations class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zones_Controller_Base
|
||||
*/
|
||||
class WC_REST_Shipping_Zone_Locations_V2_Controller extends WC_REST_Shipping_Zones_Controller_Base {
|
||||
|
||||
/**
|
||||
* Register the routes for Shipping Zone Locations.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)/locations', array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique ID 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' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_items' ),
|
||||
'permission_callback' => array( $this, 'update_items_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Shipping Zone Locations.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$zone = $this->get_zone( (int) $request['id'] );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$locations = $zone->get_zone_locations();
|
||||
$data = array();
|
||||
|
||||
foreach ( $locations as $location_obj ) {
|
||||
$location = $this->prepare_item_for_response( $location_obj, $request );
|
||||
$location = $this->prepare_response_for_collection( $location );
|
||||
$data[] = $location;
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all Shipping Zone Locations.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function update_items( $request ) {
|
||||
$zone = $this->get_zone( (int) $request['id'] );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
if ( 0 === $zone->get_id() ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_locations_invalid_zone', __( 'The "locations not covered by your other zones" zone cannot be updated.', 'woocommerce' ), array( 'status' => 403 ) );
|
||||
}
|
||||
|
||||
$raw_locations = $request->get_json_params();
|
||||
$locations = array();
|
||||
|
||||
foreach ( (array) $raw_locations as $raw_location ) {
|
||||
if ( empty( $raw_location['code'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = ! empty( $raw_location['type'] ) ? sanitize_text_field( $raw_location['type'] ) : 'country';
|
||||
|
||||
if ( ! in_array( $type, array( 'postcode', 'state', 'country', 'continent' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$locations[] = array(
|
||||
'code' => sanitize_text_field( $raw_location['code'] ),
|
||||
'type' => sanitize_text_field( $type ),
|
||||
);
|
||||
}
|
||||
|
||||
$zone->set_locations( $locations );
|
||||
$zone->save();
|
||||
|
||||
return $this->get_items( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the Shipping Zone Location for the REST response.
|
||||
*
|
||||
* @param array $item Shipping Zone Location.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$context = empty( $request['context'] ) ? 'view' : $request['context'];
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( (int) $request['id'] ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param int $zone_id Given Shipping Zone ID.
|
||||
* @return array Links for the given Shipping Zone Location.
|
||||
*/
|
||||
protected function prepare_links( $zone_id ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base . '/' . $zone_id;
|
||||
$links = array(
|
||||
'collection' => array(
|
||||
'href' => rest_url( $base . '/locations' ),
|
||||
),
|
||||
'describes' => array(
|
||||
'href' => rest_url( $base ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Shipping Zone Locations schema, conforming to JSON Schema
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'shipping_zone_location',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'code' => array(
|
||||
'description' => __( 'Shipping zone location code.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Shipping zone location type.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'default' => 'country',
|
||||
'enum' => array(
|
||||
'postcode',
|
||||
'state',
|
||||
'country',
|
||||
'continent',
|
||||
),
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zone Methods controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones/<id>/methods endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zone Methods class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zone_Methods_V2_Controller
|
||||
*/
|
||||
class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zone_Methods_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,541 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zone Methods controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones/<id>/methods endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zone Methods class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zones_Controller_Base
|
||||
*/
|
||||
class WC_REST_Shipping_Zone_Methods_V2_Controller extends WC_REST_Shipping_Zones_Controller_Base {
|
||||
|
||||
/**
|
||||
* Register the routes for Shipping Zone Methods.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<zone_id>[\d]+)/methods', array(
|
||||
'args' => array(
|
||||
'zone_id' => array(
|
||||
'description' => __( 'Unique ID for the zone.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_item' ),
|
||||
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
||||
'args' => array_merge(
|
||||
$this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array(
|
||||
'method_id' => array(
|
||||
'required' => true,
|
||||
'readonly' => false,
|
||||
'description' => __( 'Shipping method ID.', 'woocommerce' ),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base . '/(?P<zone_id>[\d]+)/methods/(?P<instance_id>[\d]+)', array(
|
||||
'args' => array(
|
||||
'zone_id' => array(
|
||||
'description' => __( 'Unique ID for the zone.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
'instance_id' => array(
|
||||
'description' => __( 'Unique ID for the instance.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_items_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_items_permissions_check' ),
|
||||
'args' => array(
|
||||
'force' => array(
|
||||
'default' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'Whether to bypass trash and force deletion.', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single Shipping Zone Method.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$zone = $this->get_zone( $request['zone_id'] );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$instance_id = (int) $request['instance_id'];
|
||||
$methods = $zone->get_shipping_methods();
|
||||
$method = false;
|
||||
|
||||
foreach ( $methods as $method_obj ) {
|
||||
if ( $instance_id === $method_obj->instance_id ) {
|
||||
$method = $method_obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( false === $method ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $method, $request );
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Shipping Zone Methods.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$zone = $this->get_zone( $request['zone_id'] );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$methods = $zone->get_shipping_methods();
|
||||
$data = array();
|
||||
|
||||
foreach ( $methods as $method_obj ) {
|
||||
$method = $this->prepare_item_for_response( $method_obj, $request );
|
||||
$data[] = $method;
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new shipping zone method instance.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$method_id = $request['method_id'];
|
||||
$zone = $this->get_zone( $request['zone_id'] );
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$instance_id = $zone->add_shipping_method( $method_id );
|
||||
$methods = $zone->get_shipping_methods();
|
||||
$method = false;
|
||||
foreach ( $methods as $method_obj ) {
|
||||
if ( $instance_id === $method_obj->instance_id ) {
|
||||
$method = $method_obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( false === $method ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_not_created', __( 'Resource cannot be created.', 'woocommerce' ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
$method = $this->update_fields( $instance_id, $method, $request );
|
||||
if ( is_wp_error( $method ) ) {
|
||||
return $method;
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $method, $request );
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a shipping method instance.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$zone = $this->get_zone( $request['zone_id'] );
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$instance_id = (int) $request['instance_id'];
|
||||
$force = $request['force'];
|
||||
|
||||
$methods = $zone->get_shipping_methods();
|
||||
$method = false;
|
||||
|
||||
foreach ( $methods as $method_obj ) {
|
||||
if ( $instance_id === $method_obj->instance_id ) {
|
||||
$method = $method_obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( false === $method ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$method = $this->update_fields( $instance_id, $method, $request );
|
||||
if ( is_wp_error( $method ) ) {
|
||||
return $method;
|
||||
}
|
||||
|
||||
$request->set_param( 'context', 'view' );
|
||||
$response = $this->prepare_item_for_response( $method, $request );
|
||||
|
||||
// Actually delete.
|
||||
if ( $force ) {
|
||||
$zone->delete_shipping_method( $instance_id );
|
||||
} else {
|
||||
return new WP_Error( 'rest_trash_not_supported', __( 'Shipping methods do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a product review is deleted via the REST API.
|
||||
*
|
||||
* @param object $method
|
||||
* @param WP_REST_Response $response The response data.
|
||||
* @param WP_REST_Request $request The request sent to the API.
|
||||
*/
|
||||
do_action( 'rest_delete_product_review', $method, $response, $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update A Single Shipping Zone Method.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$zone = $this->get_zone( $request['zone_id'] );
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$instance_id = (int) $request['instance_id'];
|
||||
$methods = $zone->get_shipping_methods();
|
||||
$method = false;
|
||||
|
||||
foreach ( $methods as $method_obj ) {
|
||||
if ( $instance_id === $method_obj->instance_id ) {
|
||||
$method = $method_obj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( false === $method ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_method_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$method = $this->update_fields( $instance_id, $method, $request );
|
||||
if ( is_wp_error( $method ) ) {
|
||||
return $method;
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $method, $request );
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates settings, order, and enabled status on create.
|
||||
*
|
||||
* @param int $instance_id Instance ID.
|
||||
* @param WC_Shipping_Method $method Shipping method data.
|
||||
* @param WP_REST_Request $request Request data.
|
||||
*
|
||||
* @return WC_Shipping_Method
|
||||
*/
|
||||
public function update_fields( $instance_id, $method, $request ) {
|
||||
global $wpdb;
|
||||
|
||||
// Update settings if present.
|
||||
if ( isset( $request['settings'] ) ) {
|
||||
$method->init_instance_settings();
|
||||
$instance_settings = $method->instance_settings;
|
||||
$errors_found = false;
|
||||
foreach ( $method->get_instance_form_fields() as $key => $field ) {
|
||||
if ( isset( $request['settings'][ $key ] ) ) {
|
||||
if ( is_callable( array( $this, 'validate_setting_' . $field['type'] . '_field' ) ) ) {
|
||||
$value = $this->{'validate_setting_' . $field['type'] . '_field'}( $request['settings'][ $key ], $field );
|
||||
} else {
|
||||
$value = $this->validate_setting_text_field( $request['settings'][ $key ], $field );
|
||||
}
|
||||
if ( is_wp_error( $value ) ) {
|
||||
$errors_found = true;
|
||||
break;
|
||||
}
|
||||
$instance_settings[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $errors_found ) {
|
||||
return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
|
||||
update_option( $method->get_instance_option_key(), apply_filters( 'woocommerce_shipping_' . $method->id . '_instance_settings_values', $instance_settings, $method ) );
|
||||
}
|
||||
|
||||
// Update order.
|
||||
if ( isset( $request['order'] ) ) {
|
||||
$wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'method_order' => absint( $request['order'] ) ), array( 'instance_id' => absint( $instance_id ) ) );
|
||||
$method->method_order = absint( $request['order'] );
|
||||
}
|
||||
|
||||
// Update if this method is enabled or not.
|
||||
if ( isset( $request['enabled'] ) ) {
|
||||
if ( $wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'is_enabled' => $request['enabled'] ), array( 'instance_id' => absint( $instance_id ) ) ) ) {
|
||||
do_action( 'woocommerce_shipping_zone_method_status_toggled', $instance_id, $method->id, $request['zone_id'], $request['enabled'] );
|
||||
$method->enabled = ( true === $request['enabled'] ? 'yes' : 'no' );
|
||||
}
|
||||
}
|
||||
|
||||
return $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the Shipping Zone Method for the REST response.
|
||||
*
|
||||
* @param array $item Shipping Zone Method.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$method = array(
|
||||
'id' => $item->instance_id,
|
||||
'instance_id' => $item->instance_id,
|
||||
'title' => $item->instance_settings['title'],
|
||||
'order' => $item->method_order,
|
||||
'enabled' => ( 'yes' === $item->enabled ),
|
||||
'method_id' => $item->id,
|
||||
'method_title' => $item->method_title,
|
||||
'method_description' => $item->method_description,
|
||||
'settings' => $this->get_settings( $item ),
|
||||
);
|
||||
|
||||
$context = empty( $request['context'] ) ? 'view' : $request['context'];
|
||||
$data = $this->add_additional_fields_to_object( $method, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $request['zone_id'], $item->instance_id ) );
|
||||
|
||||
$response = $this->prepare_response_for_collection( $response );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return settings associated with this shipping zone method instance.
|
||||
*
|
||||
* @param WC_Shipping_Method $item Shipping method data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings( $item ) {
|
||||
$item->init_instance_settings();
|
||||
$settings = array();
|
||||
foreach ( $item->get_instance_form_fields() as $id => $field ) {
|
||||
$data = array(
|
||||
'id' => $id,
|
||||
'label' => $field['title'],
|
||||
'description' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'type' => $field['type'],
|
||||
'value' => $item->instance_settings[ $id ],
|
||||
'default' => empty( $field['default'] ) ? '' : $field['default'],
|
||||
'tip' => empty( $field['description'] ) ? '' : $field['description'],
|
||||
'placeholder' => empty( $field['placeholder'] ) ? '' : $field['placeholder'],
|
||||
);
|
||||
if ( ! empty( $field['options'] ) ) {
|
||||
$data['options'] = $field['options'];
|
||||
}
|
||||
$settings[ $id ] = $data;
|
||||
}
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param int $zone_id Given Shipping Zone ID.
|
||||
* @param int $instance_id Given Shipping Zone Method Instance ID.
|
||||
* @return array Links for the given Shipping Zone Method.
|
||||
*/
|
||||
protected function prepare_links( $zone_id, $instance_id ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base . '/' . $zone_id;
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( $base . '/methods/' . $instance_id ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( $base . '/methods' ),
|
||||
),
|
||||
'describes' => array(
|
||||
'href' => rest_url( $base ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Shipping Zone Methods schema, conforming to JSON Schema
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'shipping_zone_method',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Shipping method instance ID.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'instance_id' => array(
|
||||
'description' => __( 'Shipping method instance ID.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => __( 'Shipping method customer facing title.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'order' => array(
|
||||
'description' => __( 'Shipping method sort order.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'enabled' => array(
|
||||
'description' => __( 'Shipping method enabled status.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'method_id' => array(
|
||||
'description' => __( 'Shipping method ID.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'method_title' => array(
|
||||
'description' => __( 'Shipping method title.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'method_description' => array(
|
||||
'description' => __( 'Shipping method description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'settings' => array(
|
||||
'description' => __( 'Shipping method settings.', 'woocommerce' ),
|
||||
'type' => 'object',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => __( 'A human readable label for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'A human readable description for the setting used in interfaces.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'Type of setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'value' => array(
|
||||
'description' => __( 'Setting value.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'default' => array(
|
||||
'description' => __( 'Default value for the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'tip' => array(
|
||||
'description' => __( 'Additional help text shown to the user about the setting.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'placeholder' => array(
|
||||
'description' => __( 'Placeholder text to be displayed in text inputs.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zones Controller base
|
||||
*
|
||||
* Houses common functionality between Shipping Zones and Locations.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* REST API Shipping Zones base class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
abstract class WC_REST_Shipping_Zones_Controller_Base extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'shipping/zones';
|
||||
|
||||
/**
|
||||
* Retrieve a Shipping Zone by it's ID.
|
||||
*
|
||||
* @param int $zone_id Shipping Zone ID.
|
||||
* @return WC_Shipping_Zone|WP_Error
|
||||
*/
|
||||
protected function get_zone( $zone_id ) {
|
||||
$zone = WC_Shipping_Zones::get_zone_by( 'zone_id', $zone_id );
|
||||
|
||||
if ( false === $zone ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
return $zone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to read Shipping Zones.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return new WP_Error( 'rest_no_route', __( 'Shipping is disabled.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to create Shipping Zones.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function create_item_permissions_check( $request ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return new WP_Error( 'rest_no_route', __( 'Shipping is disabled.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to edit Shipping Zones.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_items_permissions_check( $request ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return new WP_Error( 'rest_no_route', __( 'Shipping is disabled.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to delete Shipping Zones.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function delete_items_permissions_check( $request ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return new WP_Error( 'rest_no_route', __( 'Shipping is disabled.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'delete' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zones controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zones class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zones_V2_Controller
|
||||
*/
|
||||
class WC_REST_Shipping_Zones_Controller extends WC_REST_Shipping_Zones_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,304 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Shipping Zones controller
|
||||
*
|
||||
* Handles requests to the /shipping/zones endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Shipping Zones class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Shipping_Zones_Controller_Base
|
||||
*/
|
||||
class WC_REST_Shipping_Zones_V2_Controller extends WC_REST_Shipping_Zones_Controller_Base {
|
||||
|
||||
/**
|
||||
* Register the routes for Shipping Zones.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace, '/' . $this->rest_base, array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_items' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_item' ),
|
||||
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
||||
'args' => array_merge(
|
||||
$this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), array(
|
||||
'name' => array(
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'description' => __( 'Shipping zone name.', 'woocommerce' ),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
'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 ID for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_items_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_items_permissions_check' ),
|
||||
'args' => array(
|
||||
'force' => array(
|
||||
'default' => false,
|
||||
'type' => 'boolean',
|
||||
'description' => __( 'Whether to bypass trash and force deletion.', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single Shipping Zone.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$zone = $this->get_zone( $request->get_param( 'id' ) );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$data = $zone->get_data();
|
||||
$data = $this->prepare_item_for_response( $data, $request );
|
||||
$data = $this->prepare_response_for_collection( $data );
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Shipping Zones.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$rest_of_the_world = WC_Shipping_Zones::get_zone_by( 'zone_id', 0 );
|
||||
|
||||
$zones = WC_Shipping_Zones::get_zones();
|
||||
array_unshift( $zones, $rest_of_the_world->get_data() );
|
||||
$data = array();
|
||||
|
||||
foreach ( $zones as $zone_obj ) {
|
||||
$zone = $this->prepare_item_for_response( $zone_obj, $request );
|
||||
$zone = $this->prepare_response_for_collection( $zone );
|
||||
$data[] = $zone;
|
||||
}
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single Shipping Zone.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$zone = new WC_Shipping_Zone( null );
|
||||
|
||||
if ( ! is_null( $request->get_param( 'name' ) ) ) {
|
||||
$zone->set_zone_name( $request->get_param( 'name' ) );
|
||||
}
|
||||
|
||||
if ( ! is_null( $request->get_param( 'order' ) ) ) {
|
||||
$zone->set_zone_order( $request->get_param( 'order' ) );
|
||||
}
|
||||
|
||||
$zone->save();
|
||||
|
||||
if ( $zone->get_id() !== 0 ) {
|
||||
$request->set_param( 'id', $zone->get_id() );
|
||||
$response = $this->get_item( $request );
|
||||
$response->set_status( 201 );
|
||||
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $zone->get_id() ) ) );
|
||||
return $response;
|
||||
} else {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_not_created', __( "Resource cannot be created. Check to make sure 'order' and 'name' are present.", 'woocommerce' ), array( 'status' => 500 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single Shipping Zone.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$zone = $this->get_zone( $request->get_param( 'id' ) );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
if ( 0 === $zone->get_id() ) {
|
||||
return new WP_Error( 'woocommerce_rest_shipping_zone_invalid_zone', __( 'The "locations not covered by your other zones" zone cannot be updated.', 'woocommerce' ), array( 'status' => 403 ) );
|
||||
}
|
||||
|
||||
$zone_changed = false;
|
||||
|
||||
if ( ! is_null( $request->get_param( 'name' ) ) ) {
|
||||
$zone->set_zone_name( $request->get_param( 'name' ) );
|
||||
$zone_changed = true;
|
||||
}
|
||||
|
||||
if ( ! is_null( $request->get_param( 'order' ) ) ) {
|
||||
$zone->set_zone_order( $request->get_param( 'order' ) );
|
||||
$zone_changed = true;
|
||||
}
|
||||
|
||||
if ( $zone_changed ) {
|
||||
$zone->save();
|
||||
}
|
||||
|
||||
return $this->get_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single Shipping Zone.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$zone = $this->get_zone( $request->get_param( 'id' ) );
|
||||
|
||||
if ( is_wp_error( $zone ) ) {
|
||||
return $zone;
|
||||
}
|
||||
|
||||
$force = $request['force'];
|
||||
|
||||
$response = $this->get_item( $request );
|
||||
|
||||
if ( $force ) {
|
||||
$zone->delete();
|
||||
} else {
|
||||
return new WP_Error( 'rest_trash_not_supported', __( 'Shipping zones do not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the Shipping Zone for the REST response.
|
||||
*
|
||||
* @param array $item Shipping Zone.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$data = array(
|
||||
'id' => (int) $item['id'],
|
||||
'name' => $item['zone_name'],
|
||||
'order' => (int) $item['zone_order'],
|
||||
);
|
||||
|
||||
$context = empty( $request['context'] ) ? 'view' : $request['context'];
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $data['id'] ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param int $zone_id Given Shipping Zone ID.
|
||||
* @return array Links for the given Shipping Zone.
|
||||
*/
|
||||
protected function prepare_links( $zone_id ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $zone_id ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( $base ),
|
||||
),
|
||||
'describedby' => array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $zone_id . '/locations' ),
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Shipping Zones schema, conforming to JSON Schema
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'shipping_zone',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Shipping zone name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
'order' => array(
|
||||
'description' => __( 'Shipping zone order.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC System Status controller
|
||||
*
|
||||
* Handles requests to the /system_status endpoint.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* System status controller class.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_System_Status_V2_Controller
|
||||
*/
|
||||
class WC_REST_System_Status_Controller extends WC_REST_System_Status_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC System Status Tools Controller
|
||||
*
|
||||
* Handles requests to the /system_status/tools/* endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* System status tools controller.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_System_Status_Tools_V2_Controller
|
||||
*/
|
||||
class WC_REST_System_Status_Tools_Controller extends WC_REST_System_Status_Tools_V2_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3';
|
||||
}
|
|
@ -0,0 +1,563 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API WC System Status Tools Controller
|
||||
*
|
||||
* Handles requests to the /system_status/tools/* endpoints.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* System status tools controller.
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @extends WC_REST_Controller
|
||||
*/
|
||||
class WC_REST_System_Status_Tools_V2_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v2';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'system_status/tools';
|
||||
|
||||
/**
|
||||
* Register the routes for /system_status/tools/*.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
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' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\w-]+)',
|
||||
array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the resource.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
),
|
||||
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 ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to view system status tools.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to view a specific system status tool.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to execute a specific system status tool.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'system_status', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_update', __( 'Sorry, you cannot update resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of available tools for use in the system status section.
|
||||
* 'button' becomes 'action' in the API.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_tools() {
|
||||
$tools = array(
|
||||
'clear_transients' => array(
|
||||
'name' => __( 'WooCommerce transients', 'woocommerce' ),
|
||||
'button' => __( 'Clear transients', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will clear the product/shop transients cache.', 'woocommerce' ),
|
||||
),
|
||||
'clear_expired_transients' => array(
|
||||
'name' => __( 'Expired transients', 'woocommerce' ),
|
||||
'button' => __( 'Clear transients', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will clear ALL expired transients from WordPress.', 'woocommerce' ),
|
||||
),
|
||||
'delete_orphaned_variations' => array(
|
||||
'name' => __( 'Orphaned variations', 'woocommerce' ),
|
||||
'button' => __( 'Delete orphaned variations', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will delete all variations which have no parent.', 'woocommerce' ),
|
||||
),
|
||||
'clear_expired_download_permissions' => array(
|
||||
'name' => __( 'Used-up download permissions', 'woocommerce' ),
|
||||
'button' => __( 'Clean up download permissions', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will delete expired download permissions and permissions with 0 remaining downloads.', 'woocommerce' ),
|
||||
),
|
||||
'regenerate_product_lookup_tables' => array(
|
||||
'name' => __( 'Product lookup tables', 'woocommerce' ),
|
||||
'button' => __( 'Regenerate', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will regenerate product lookup table data. This process may take a while.', 'woocommerce' ),
|
||||
),
|
||||
'recount_terms' => array(
|
||||
'name' => __( 'Term counts', 'woocommerce' ),
|
||||
'button' => __( 'Recount terms', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will recount product terms - useful when changing your settings in a way which hides products from the catalog.', 'woocommerce' ),
|
||||
),
|
||||
'reset_roles' => array(
|
||||
'name' => __( 'Capabilities', 'woocommerce' ),
|
||||
'button' => __( 'Reset capabilities', 'woocommerce' ),
|
||||
'desc' => __( 'This tool will reset the admin, customer and shop_manager roles to default. Use this if your users cannot access all of the WooCommerce admin pages.', 'woocommerce' ),
|
||||
),
|
||||
'clear_sessions' => array(
|
||||
'name' => __( 'Clear customer sessions', 'woocommerce' ),
|
||||
'button' => __( 'Clear', 'woocommerce' ),
|
||||
'desc' => sprintf(
|
||||
'<strong class="red">%1$s</strong> %2$s',
|
||||
__( 'Note:', 'woocommerce' ),
|
||||
__( 'This tool will delete all customer session data from the database, including current carts and saved carts in the database.', 'woocommerce' )
|
||||
),
|
||||
),
|
||||
'install_pages' => array(
|
||||
'name' => __( 'Create default WooCommerce pages', 'woocommerce' ),
|
||||
'button' => __( 'Create pages', 'woocommerce' ),
|
||||
'desc' => sprintf(
|
||||
'<strong class="red">%1$s</strong> %2$s',
|
||||
__( 'Note:', 'woocommerce' ),
|
||||
__( 'This tool will install all the missing WooCommerce pages. Pages already defined and set up will not be replaced.', 'woocommerce' )
|
||||
),
|
||||
),
|
||||
'delete_taxes' => array(
|
||||
'name' => __( 'Delete WooCommerce tax rates', 'woocommerce' ),
|
||||
'button' => __( 'Delete tax rates', 'woocommerce' ),
|
||||
'desc' => sprintf(
|
||||
'<strong class="red">%1$s</strong> %2$s',
|
||||
__( 'Note:', 'woocommerce' ),
|
||||
__( 'This option will delete ALL of your tax rates, use with caution. This action cannot be reversed.', 'woocommerce' )
|
||||
),
|
||||
),
|
||||
'regenerate_thumbnails' => array(
|
||||
'name' => __( 'Regenerate shop thumbnails', 'woocommerce' ),
|
||||
'button' => __( 'Regenerate', 'woocommerce' ),
|
||||
'desc' => __( 'This will regenerate all shop thumbnails to match your theme and/or image settings.', 'woocommerce' ),
|
||||
),
|
||||
'db_update_routine' => array(
|
||||
'name' => __( 'Update database', 'woocommerce' ),
|
||||
'button' => __( 'Update database', 'woocommerce' ),
|
||||
'desc' => sprintf(
|
||||
'<strong class="red">%1$s</strong> %2$s',
|
||||
__( 'Note:', 'woocommerce' ),
|
||||
__( 'This tool will update your WooCommerce database to the latest version. Please ensure you make sufficient backups before proceeding.', 'woocommerce' )
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Jetpack does the image resizing heavy lifting so you don't have to.
|
||||
if ( ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) ) || ! apply_filters( 'woocommerce_background_image_regeneration', true ) ) {
|
||||
unset( $tools['regenerate_thumbnails'] );
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_debug_tools', $tools );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of system status tools.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$tools = array();
|
||||
foreach ( $this->get_tools() as $id => $tool ) {
|
||||
$tools[] = $this->prepare_response_for_collection(
|
||||
$this->prepare_item_for_response(
|
||||
array(
|
||||
'id' => $id,
|
||||
'name' => $tool['name'],
|
||||
'action' => $tool['button'],
|
||||
'description' => $tool['desc'],
|
||||
),
|
||||
$request
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $tools );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a single tool.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$tools = $this->get_tools();
|
||||
if ( empty( $tools[ $request['id'] ] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_system_status_tool_invalid_id', __( 'Invalid tool ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
$tool = $tools[ $request['id'] ];
|
||||
return rest_ensure_response(
|
||||
$this->prepare_item_for_response(
|
||||
array(
|
||||
'id' => $request['id'],
|
||||
'name' => $tool['name'],
|
||||
'action' => $tool['button'],
|
||||
'description' => $tool['desc'],
|
||||
),
|
||||
$request
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (execute) a tool.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$tools = $this->get_tools();
|
||||
if ( empty( $tools[ $request['id'] ] ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_system_status_tool_invalid_id', __( 'Invalid tool ID.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
$tool = $tools[ $request['id'] ];
|
||||
$tool = array(
|
||||
'id' => $request['id'],
|
||||
'name' => $tool['name'],
|
||||
'action' => $tool['button'],
|
||||
'description' => $tool['desc'],
|
||||
);
|
||||
|
||||
$execute_return = $this->execute_tool( $request['id'] );
|
||||
$tool = array_merge( $tool, $execute_return );
|
||||
|
||||
/**
|
||||
* Fires after a WooCommerce REST system status tool has been executed.
|
||||
*
|
||||
* @param array $tool Details about the tool that has been executed.
|
||||
* @param WP_REST_Request $request The current WP_REST_Request object.
|
||||
*/
|
||||
do_action( 'woocommerce_rest_insert_system_status_tool', $tool, $request );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $tool, $request );
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a tool item for serialization.
|
||||
*
|
||||
* @param array $item Object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ) {
|
||||
$context = empty( $request['context'] ) ? 'view' : $request['context'];
|
||||
$data = $this->add_additional_fields_to_object( $item, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
$response->add_links( $this->prepare_links( $item['id'] ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the system status tools schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'system_status_tool',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'A unique identifier for the tool.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_title',
|
||||
),
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Tool name.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
'action' => array(
|
||||
'description' => __( 'What running the tool will do.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
'description' => array(
|
||||
'description' => __( 'Tool description.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
'success' => array(
|
||||
'description' => __( 'Did the tool run successfully?', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'edit' ),
|
||||
),
|
||||
'message' => array(
|
||||
'description' => __( 'Tool return message.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'edit' ),
|
||||
'arg_options' => array(
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param string $id ID.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_links( $id ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
||||
$links = array(
|
||||
'item' => array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $id ),
|
||||
'embeddable' => true,
|
||||
),
|
||||
);
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any query params needed.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
return array(
|
||||
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually executes a tool.
|
||||
*
|
||||
* @param string $tool Tool.
|
||||
* @return array
|
||||
*/
|
||||
public function execute_tool( $tool ) {
|
||||
global $wpdb;
|
||||
$ran = true;
|
||||
switch ( $tool ) {
|
||||
case 'clear_transients':
|
||||
wc_delete_product_transients();
|
||||
wc_delete_shop_order_transients();
|
||||
delete_transient( 'wc_count_comments' );
|
||||
|
||||
$attribute_taxonomies = wc_get_attribute_taxonomies();
|
||||
|
||||
if ( $attribute_taxonomies ) {
|
||||
foreach ( $attribute_taxonomies as $attribute ) {
|
||||
delete_transient( 'wc_layered_nav_counts_pa_' . $attribute->attribute_name );
|
||||
}
|
||||
}
|
||||
|
||||
WC_Cache_Helper::get_transient_version( 'shipping', true );
|
||||
$message = __( 'Product transients cleared', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'clear_expired_transients':
|
||||
/* translators: %d: amount of expired transients */
|
||||
$message = sprintf( __( '%d transients rows cleared', 'woocommerce' ), wc_delete_expired_transients() );
|
||||
break;
|
||||
|
||||
case 'delete_orphaned_variations':
|
||||
// Delete orphans.
|
||||
$result = absint(
|
||||
$wpdb->query(
|
||||
"DELETE products
|
||||
FROM {$wpdb->posts} products
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = products.post_parent
|
||||
WHERE wp.ID IS NULL AND products.post_type = 'product_variation';"
|
||||
)
|
||||
);
|
||||
/* translators: %d: amount of orphaned variations */
|
||||
$message = sprintf( __( '%d orphaned variations deleted', 'woocommerce' ), $result );
|
||||
break;
|
||||
|
||||
case 'clear_expired_download_permissions':
|
||||
// Delete expired download permissions and ones with 0 downloads remaining.
|
||||
$result = absint(
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
|
||||
WHERE ( downloads_remaining != '' AND downloads_remaining = 0 ) OR ( access_expires IS NOT NULL AND access_expires < %s )",
|
||||
date( 'Y-m-d', current_time( 'timestamp' ) )
|
||||
)
|
||||
)
|
||||
);
|
||||
/* translators: %d: amount of permissions */
|
||||
$message = sprintf( __( '%d permissions deleted', 'woocommerce' ), $result );
|
||||
break;
|
||||
|
||||
case 'regenerate_product_lookup_tables':
|
||||
if ( ! wc_update_product_lookup_tables_is_running() ) {
|
||||
wc_update_product_lookup_tables();
|
||||
}
|
||||
$message = __( 'Lookup tables are regenerating', 'woocommerce' );
|
||||
break;
|
||||
case 'reset_roles':
|
||||
// Remove then re-add caps and roles.
|
||||
WC_Install::remove_roles();
|
||||
WC_Install::create_roles();
|
||||
$message = __( 'Roles successfully reset', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'recount_terms':
|
||||
$product_cats = get_terms(
|
||||
'product_cat',
|
||||
array(
|
||||
'hide_empty' => false,
|
||||
'fields' => 'id=>parent',
|
||||
)
|
||||
);
|
||||
_wc_term_recount( $product_cats, get_taxonomy( 'product_cat' ), true, false );
|
||||
$product_tags = get_terms(
|
||||
'product_tag',
|
||||
array(
|
||||
'hide_empty' => false,
|
||||
'fields' => 'id=>parent',
|
||||
)
|
||||
);
|
||||
_wc_term_recount( $product_tags, get_taxonomy( 'product_tag' ), true, false );
|
||||
$message = __( 'Terms successfully recounted', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'clear_sessions':
|
||||
$wpdb->query( "TRUNCATE {$wpdb->prefix}woocommerce_sessions" );
|
||||
$result = absint( $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key='_woocommerce_persistent_cart_" . get_current_blog_id() . "';" ) ); // WPCS: unprepared SQL ok.
|
||||
wp_cache_flush();
|
||||
/* translators: %d: amount of sessions */
|
||||
$message = sprintf( __( 'Deleted all active sessions, and %d saved carts.', 'woocommerce' ), absint( $result ) );
|
||||
break;
|
||||
|
||||
case 'install_pages':
|
||||
WC_Install::create_pages();
|
||||
$message = __( 'All missing WooCommerce pages successfully installed', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'delete_taxes':
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rates;" );
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations;" );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
|
||||
$message = __( 'Tax rates successfully deleted', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'regenerate_thumbnails':
|
||||
WC_Regenerate_Images::queue_image_regeneration();
|
||||
$message = __( 'Thumbnail regeneration has been scheduled to run in the background.', 'woocommerce' );
|
||||
break;
|
||||
|
||||
case 'db_update_routine':
|
||||
$blog_id = get_current_blog_id();
|
||||
// Used to fire an action added in WP_Background_Process::_construct() that calls WP_Background_Process::handle_cron_healthcheck().
|
||||
// This method will make sure the database updates are executed even if cron is disabled. Nothing will happen if the updates are already running.
|
||||
do_action( 'wp_' . $blog_id . '_wc_updater_cron' );
|
||||
$message = __( 'Database upgrade routine has been scheduled to run in the background.', 'woocommerce' );
|
||||
break;
|
||||
|
||||
default:
|
||||
$tools = $this->get_tools();
|
||||
if ( isset( $tools[ $tool ]['callback'] ) ) {
|
||||
$callback = $tools[ $tool ]['callback'];
|
||||
$return = call_user_func( $callback );
|
||||
if ( is_string( $return ) ) {
|
||||
$message = $return;
|
||||
} elseif ( false === $return ) {
|
||||
$callback_string = is_array( $callback ) ? get_class( $callback[0] ) . '::' . $callback[1] : $callback;
|
||||
$ran = false;
|
||||
/* translators: %s: callback string */
|
||||
$message = sprintf( __( 'There was an error calling %s', 'woocommerce' ), $callback_string );
|
||||
} else {
|
||||
$message = __( 'Tool ran.', 'woocommerce' );
|
||||
}
|
||||
} else {
|
||||
$ran = false;
|
||||
$message = __( 'There was an error calling this tool. There is no callback present.', 'woocommerce' );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return array(
|
||||
'success' => $ran,
|
||||
'message' => $message,
|
||||
);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,806 @@
|
|||
<?php
|
||||
/**
|
||||
* Abstract Rest Terms Controller
|
||||
*
|
||||
* @package WooCommerce/RestApi
|
||||
* @version 3.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terms controller class.
|
||||
*/
|
||||
abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = '';
|
||||
|
||||
/**
|
||||
* Taxonomy.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $taxonomy = '';
|
||||
|
||||
/**
|
||||
* Register the routes for terms.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
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' => array_merge(
|
||||
$this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
||||
array(
|
||||
'name' => array(
|
||||
'type' => 'string',
|
||||
'description' => __( 'Name for the resource.', 'woocommerce' ),
|
||||
'required' => true,
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
'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',
|
||||
),
|
||||
),
|
||||
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(
|
||||
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' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read the terms.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'read' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to create a term.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function create_item_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'create' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to read a term.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'read' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to update a term.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'edit' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you are not allowed to edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to delete a term.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function delete_item_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'delete' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access batch create, update and delete items.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return boolean|WP_Error
|
||||
*/
|
||||
public function batch_items_permissions_check( $request ) {
|
||||
$permissions = $this->check_permissions( $request, 'batch' );
|
||||
if ( is_wp_error( $permissions ) ) {
|
||||
return $permissions;
|
||||
}
|
||||
|
||||
if ( ! $permissions ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_batch', __( 'Sorry, you are not allowed to batch manipulate this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check permissions.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @param string $context Request context.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
protected function check_permissions( $request, $context = 'read' ) {
|
||||
// Get taxonomy.
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
if ( ! $taxonomy || ! taxonomy_exists( $taxonomy ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_taxonomy_invalid', __( 'Taxonomy does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
// Check permissions for a single term.
|
||||
$id = intval( $request['id'] );
|
||||
if ( $id ) {
|
||||
$term = get_term( $id, $taxonomy );
|
||||
|
||||
if ( is_wp_error( $term ) || ! $term || $term->taxonomy !== $taxonomy ) {
|
||||
return new WP_Error( 'woocommerce_rest_term_invalid', __( 'Resource does not exist.', 'woocommerce' ), array( 'status' => 404 ) );
|
||||
}
|
||||
|
||||
return wc_rest_check_product_term_permissions( $taxonomy, $context, $term->term_id );
|
||||
}
|
||||
|
||||
return wc_rest_check_product_term_permissions( $taxonomy, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get terms associated with a taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
$prepared_args = array(
|
||||
'exclude' => $request['exclude'],
|
||||
'include' => $request['include'],
|
||||
'order' => $request['order'],
|
||||
'orderby' => $request['orderby'],
|
||||
'product' => $request['product'],
|
||||
'hide_empty' => $request['hide_empty'],
|
||||
'number' => $request['per_page'],
|
||||
'search' => $request['search'],
|
||||
'slug' => $request['slug'],
|
||||
);
|
||||
|
||||
if ( ! empty( $request['offset'] ) ) {
|
||||
$prepared_args['offset'] = $request['offset'];
|
||||
} else {
|
||||
$prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number'];
|
||||
}
|
||||
|
||||
$taxonomy_obj = get_taxonomy( $taxonomy );
|
||||
|
||||
if ( $taxonomy_obj->hierarchical && isset( $request['parent'] ) ) {
|
||||
if ( 0 === $request['parent'] ) {
|
||||
// Only query top-level terms.
|
||||
$prepared_args['parent'] = 0;
|
||||
} else {
|
||||
if ( $request['parent'] ) {
|
||||
$prepared_args['parent'] = $request['parent'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query arguments, before passing them to `get_terms()`.
|
||||
*
|
||||
* Enables adding extra arguments or setting defaults for a terms
|
||||
* collection request.
|
||||
*
|
||||
* @see https://developer.wordpress.org/reference/functions/get_terms/
|
||||
*
|
||||
* @param array $prepared_args Array of arguments to be
|
||||
* passed to get_terms.
|
||||
* @param WP_REST_Request $request The current request.
|
||||
*/
|
||||
$prepared_args = apply_filters( "woocommerce_rest_{$taxonomy}_query", $prepared_args, $request );
|
||||
|
||||
if ( ! empty( $prepared_args['product'] ) ) {
|
||||
$query_result = $this->get_terms_for_product( $prepared_args, $request );
|
||||
$total_terms = $this->total_terms;
|
||||
} else {
|
||||
$query_result = get_terms( $taxonomy, $prepared_args );
|
||||
|
||||
$count_args = $prepared_args;
|
||||
unset( $count_args['number'] );
|
||||
unset( $count_args['offset'] );
|
||||
$total_terms = wp_count_terms( $taxonomy, $count_args );
|
||||
|
||||
// Ensure we don't return results when offset is out of bounds.
|
||||
// See https://core.trac.wordpress.org/ticket/35935.
|
||||
if ( $prepared_args['offset'] && $prepared_args['offset'] >= $total_terms ) {
|
||||
$query_result = array();
|
||||
}
|
||||
|
||||
// wp_count_terms can return a falsy value when the term has no children.
|
||||
if ( ! $total_terms ) {
|
||||
$total_terms = 0;
|
||||
}
|
||||
}
|
||||
$response = array();
|
||||
foreach ( $query_result as $term ) {
|
||||
$data = $this->prepare_item_for_response( $term, $request );
|
||||
$response[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $response );
|
||||
|
||||
// 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 );
|
||||
|
||||
$response->header( 'X-WP-Total', (int) $total_terms );
|
||||
$max_pages = ceil( $total_terms / $per_page );
|
||||
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
||||
|
||||
$base = str_replace( '(?P<attribute_id>[\d]+)', $request['attribute_id'], $this->rest_base );
|
||||
$base = add_query_arg( $request->get_query_params(), rest_url( '/' . $this->namespace . '/' . $base ) );
|
||||
if ( $page > 1 ) {
|
||||
$prev_page = $page - 1;
|
||||
if ( $prev_page > $max_pages ) {
|
||||
$prev_page = $max_pages;
|
||||
}
|
||||
$prev_link = add_query_arg( 'page', $prev_page, $base );
|
||||
$response->link_header( 'prev', $prev_link );
|
||||
}
|
||||
if ( $max_pages > $page ) {
|
||||
$next_page = $page + 1;
|
||||
$next_link = add_query_arg( 'page', $next_page, $base );
|
||||
$response->link_header( 'next', $next_link );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single term for a taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
$name = $request['name'];
|
||||
$args = array();
|
||||
$schema = $this->get_item_schema();
|
||||
|
||||
if ( ! empty( $schema['properties']['description'] ) && isset( $request['description'] ) ) {
|
||||
$args['description'] = $request['description'];
|
||||
}
|
||||
if ( isset( $request['slug'] ) ) {
|
||||
$args['slug'] = $request['slug'];
|
||||
}
|
||||
if ( isset( $request['parent'] ) ) {
|
||||
if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_taxonomy_not_hierarchical', __( 'Can not set resource parent, taxonomy is not hierarchical.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
$args['parent'] = $request['parent'];
|
||||
}
|
||||
|
||||
$term = wp_insert_term( $name, $taxonomy, $args );
|
||||
if ( is_wp_error( $term ) ) {
|
||||
$error_data = array( 'status' => 400 );
|
||||
|
||||
// If we're going to inform the client that the term exists,
|
||||
// give them the identifier they can actually use.
|
||||
$term_id = $term->get_error_data( 'term_exists' );
|
||||
if ( $term_id ) {
|
||||
$error_data['resource_id'] = $term_id;
|
||||
}
|
||||
|
||||
return new WP_Error( $term->get_error_code(), $term->get_error_message(), $error_data );
|
||||
}
|
||||
|
||||
$term = get_term( $term['term_id'], $taxonomy );
|
||||
|
||||
$this->update_additional_fields_for_object( $term, $request );
|
||||
|
||||
// Add term data.
|
||||
$meta_fields = $this->update_term_meta_fields( $term, $request );
|
||||
if ( is_wp_error( $meta_fields ) ) {
|
||||
wp_delete_term( $term->term_id, $taxonomy );
|
||||
|
||||
return $meta_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single term is created or updated via the REST API.
|
||||
*
|
||||
* @param WP_Term $term Inserted Term object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating term, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$taxonomy}", $term, $request, true );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $term, $request );
|
||||
$response = rest_ensure_response( $response );
|
||||
$response->set_status( 201 );
|
||||
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
||||
if ( ! empty( $request['attribute_id'] ) ) {
|
||||
$base = str_replace( '(?P<attribute_id>[\d]+)', (int) $request['attribute_id'], $base );
|
||||
}
|
||||
|
||||
$response->header( 'Location', rest_url( $base . '/' . $term->term_id ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single term from a taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
$term = get_term( (int) $request['id'], $taxonomy );
|
||||
|
||||
if ( is_wp_error( $term ) ) {
|
||||
return $term;
|
||||
}
|
||||
|
||||
$response = $this->prepare_item_for_response( $term, $request );
|
||||
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single term from a taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
$term = get_term( (int) $request['id'], $taxonomy );
|
||||
$schema = $this->get_item_schema();
|
||||
$prepared_args = array();
|
||||
|
||||
if ( isset( $request['name'] ) ) {
|
||||
$prepared_args['name'] = $request['name'];
|
||||
}
|
||||
if ( ! empty( $schema['properties']['description'] ) && isset( $request['description'] ) ) {
|
||||
$prepared_args['description'] = $request['description'];
|
||||
}
|
||||
if ( isset( $request['slug'] ) ) {
|
||||
$prepared_args['slug'] = $request['slug'];
|
||||
}
|
||||
if ( isset( $request['parent'] ) ) {
|
||||
if ( ! is_taxonomy_hierarchical( $taxonomy ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_taxonomy_not_hierarchical', __( 'Can not set resource parent, taxonomy is not hierarchical.', 'woocommerce' ), array( 'status' => 400 ) );
|
||||
}
|
||||
$prepared_args['parent'] = $request['parent'];
|
||||
}
|
||||
|
||||
// Only update the term if we haz something to update.
|
||||
if ( ! empty( $prepared_args ) ) {
|
||||
$update = wp_update_term( $term->term_id, $term->taxonomy, $prepared_args );
|
||||
if ( is_wp_error( $update ) ) {
|
||||
return $update;
|
||||
}
|
||||
}
|
||||
|
||||
$term = get_term( (int) $request['id'], $taxonomy );
|
||||
|
||||
$this->update_additional_fields_for_object( $term, $request );
|
||||
|
||||
// Update term data.
|
||||
$meta_fields = $this->update_term_meta_fields( $term, $request );
|
||||
if ( is_wp_error( $meta_fields ) ) {
|
||||
return $meta_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single term is created or updated via the REST API.
|
||||
*
|
||||
* @param WP_Term $term Inserted Term object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @param boolean $creating True when creating term, false when updating.
|
||||
*/
|
||||
do_action( "woocommerce_rest_insert_{$taxonomy}", $term, $request, false );
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $term, $request );
|
||||
return rest_ensure_response( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a single term from a taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
|
||||
|
||||
// We don't support trashing for this type, error out.
|
||||
if ( ! $force ) {
|
||||
return new WP_Error( 'woocommerce_rest_trash_not_supported', __( 'Resource does not support trashing.', 'woocommerce' ), array( 'status' => 501 ) );
|
||||
}
|
||||
|
||||
$term = get_term( (int) $request['id'], $taxonomy );
|
||||
// Get default category id.
|
||||
$default_category_id = absint( get_option( 'default_product_cat', 0 ) );
|
||||
|
||||
// Prevent deleting the default product category.
|
||||
if ( $default_category_id === (int) $request['id'] ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Default product category cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
$request->set_param( 'context', 'edit' );
|
||||
$response = $this->prepare_item_for_response( $term, $request );
|
||||
|
||||
$retval = wp_delete_term( $term->term_id, $term->taxonomy );
|
||||
if ( ! $retval ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'The resource cannot be deleted.', 'woocommerce' ), array( 'status' => 500 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires after a single term is deleted via the REST API.
|
||||
*
|
||||
* @param WP_Term $term The deleted term.
|
||||
* @param WP_REST_Response $response The response data.
|
||||
* @param WP_REST_Request $request The request sent to the API.
|
||||
*/
|
||||
do_action( "woocommerce_rest_delete_{$taxonomy}", $term, $response, $request );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param object $term Term object.
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Links for the given term.
|
||||
*/
|
||||
protected function prepare_links( $term, $request ) {
|
||||
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
||||
|
||||
if ( ! empty( $request['attribute_id'] ) ) {
|
||||
$base = str_replace( '(?P<attribute_id>[\d]+)', (int) $request['attribute_id'], $base );
|
||||
}
|
||||
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $term->term_id ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( $base ),
|
||||
),
|
||||
);
|
||||
|
||||
if ( $term->parent ) {
|
||||
$parent_term = get_term( (int) $term->parent, $term->taxonomy );
|
||||
if ( $parent_term ) {
|
||||
$links['up'] = array(
|
||||
'href' => rest_url( trailingslashit( $base ) . $parent_term->term_id ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update term meta fields.
|
||||
*
|
||||
* @param WP_Term $term Term object.
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
protected function update_term_meta_fields( $term, $request ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the terms attached to a product.
|
||||
*
|
||||
* This is an alternative to `get_terms()` that uses `get_the_terms()`
|
||||
* instead, which hits the object cache. There are a few things not
|
||||
* supported, notably `include`, `exclude`. In `self::get_items()` these
|
||||
* are instead treated as a full query.
|
||||
*
|
||||
* @param array $prepared_args Arguments for `get_terms()`.
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array List of term objects. (Total count in `$this->total_terms`).
|
||||
*/
|
||||
protected function get_terms_for_product( $prepared_args, $request ) {
|
||||
$taxonomy = $this->get_taxonomy( $request );
|
||||
|
||||
$query_result = get_the_terms( $prepared_args['product'], $taxonomy );
|
||||
if ( empty( $query_result ) ) {
|
||||
$this->total_terms = 0;
|
||||
return array();
|
||||
}
|
||||
|
||||
// get_items() verifies that we don't have `include` set, and default.
|
||||
// ordering is by `name`.
|
||||
if ( ! in_array( $prepared_args['orderby'], array( 'name', 'none', 'include' ), true ) ) {
|
||||
switch ( $prepared_args['orderby'] ) {
|
||||
case 'id':
|
||||
$this->sort_column = 'term_id';
|
||||
break;
|
||||
case 'slug':
|
||||
case 'term_group':
|
||||
case 'description':
|
||||
case 'count':
|
||||
$this->sort_column = $prepared_args['orderby'];
|
||||
break;
|
||||
}
|
||||
usort( $query_result, array( $this, 'compare_terms' ) );
|
||||
}
|
||||
if ( strtolower( $prepared_args['order'] ) !== 'asc' ) {
|
||||
$query_result = array_reverse( $query_result );
|
||||
}
|
||||
|
||||
// Pagination.
|
||||
$this->total_terms = count( $query_result );
|
||||
$query_result = array_slice( $query_result, $prepared_args['offset'], $prepared_args['number'] );
|
||||
|
||||
return $query_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparison function for sorting terms by a column.
|
||||
*
|
||||
* Uses `$this->sort_column` to determine field to sort by.
|
||||
*
|
||||
* @param stdClass $left Term object.
|
||||
* @param stdClass $right Term object.
|
||||
* @return int <0 if left is higher "priority" than right, 0 if equal, >0 if right is higher "priority" than left.
|
||||
*/
|
||||
protected function compare_terms( $left, $right ) {
|
||||
$col = $this->sort_column;
|
||||
$left_val = $left->$col;
|
||||
$right_val = $right->$col;
|
||||
|
||||
if ( is_int( $left_val ) && is_int( $right_val ) ) {
|
||||
return $left_val - $right_val;
|
||||
}
|
||||
|
||||
return strcmp( $left_val, $right_val );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
|
||||
if ( '' !== $this->taxonomy && taxonomy_exists( $this->taxonomy ) ) {
|
||||
$taxonomy = get_taxonomy( $this->taxonomy );
|
||||
} else {
|
||||
$taxonomy = new stdClass();
|
||||
$taxonomy->hierarchical = true;
|
||||
}
|
||||
|
||||
$params['context']['default'] = 'view';
|
||||
|
||||
$params['exclude'] = array(
|
||||
'description' => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
$params['include'] = array(
|
||||
'description' => __( 'Limit result set to specific ids.', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'sanitize_callback' => 'wp_parse_id_list',
|
||||
);
|
||||
if ( ! $taxonomy->hierarchical ) {
|
||||
$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(
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'default' => 'asc',
|
||||
'enum' => array(
|
||||
'asc',
|
||||
'desc',
|
||||
),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['orderby'] = array(
|
||||
'description' => __( 'Sort collection by resource attribute.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
'default' => 'name',
|
||||
'enum' => array(
|
||||
'id',
|
||||
'include',
|
||||
'name',
|
||||
'slug',
|
||||
'term_group',
|
||||
'description',
|
||||
'count',
|
||||
),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['hide_empty'] = array(
|
||||
'description' => __( 'Whether to hide resources not assigned to any products.', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
if ( $taxonomy->hierarchical ) {
|
||||
$params['parent'] = array(
|
||||
'description' => __( 'Limit result set to resources assigned to a specific parent.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
}
|
||||
$params['product'] = array(
|
||||
'description' => __( 'Limit result set to resources assigned to a specific product.', 'woocommerce' ),
|
||||
'type' => 'integer',
|
||||
'default' => null,
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['slug'] = array(
|
||||
'description' => __( 'Limit result set to resources with a specific slug.', 'woocommerce' ),
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxonomy.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return int|WP_Error
|
||||
*/
|
||||
protected function get_taxonomy( $request ) {
|
||||
// Check if taxonomy is defined.
|
||||
// Prevents check for attribute taxonomy more than one time for each query.
|
||||
if ( '' !== $this->taxonomy ) {
|
||||
return $this->taxonomy;
|
||||
}
|
||||
|
||||
if ( ! empty( $request['attribute_id'] ) ) {
|
||||
$taxonomy = wc_attribute_taxonomy_name_by_id( (int) $request['attribute_id'] );
|
||||
|
||||
$this->taxonomy = $taxonomy;
|
||||
}
|
||||
|
||||
return $this->taxonomy;
|
||||
}
|
||||
}
|
|
@ -1,484 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Admin Notes controller
|
||||
*
|
||||
* Handles requests to the admin notes endpoint.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* REST API Admin Notes controller class.
|
||||
*
|
||||
* @package WooCommerce/API
|
||||
* @extends WC_REST_CRUD_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'admin/notes';
|
||||
|
||||
/**
|
||||
* Register the routes for admin notes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
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' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d-]+)',
|
||||
array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique ID for the resource.', 'woocommerce-admin' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
||||
),
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_items_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single note.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$note = WC_Admin_Notes::get_note( $request->get_param( 'id' ) );
|
||||
|
||||
if ( ! $note ) {
|
||||
return new WP_Error(
|
||||
'woocommerce_admin_notes_invalid_id',
|
||||
__( 'Sorry, there is no resouce with that ID.', 'woocommerce-admin' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
if ( is_wp_error( $note ) ) {
|
||||
return $note;
|
||||
}
|
||||
|
||||
$data = $note->get_data();
|
||||
$data = $this->prepare_item_for_response( $data, $request );
|
||||
$data = $this->prepare_response_for_collection( $data );
|
||||
|
||||
return rest_ensure_response( $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all notes.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
$query_args = $this->prepare_objects_query( $request );
|
||||
|
||||
$notes = WC_Admin_Notes::get_notes( 'edit', $query_args );
|
||||
|
||||
$data = array();
|
||||
foreach ( (array) $notes as $note_obj ) {
|
||||
$note = $this->prepare_item_for_response( $note_obj, $request );
|
||||
$note = $this->prepare_response_for_collection( $note );
|
||||
$data[] = $note;
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->header( 'X-WP-Total', WC_Admin_Notes::get_notes_count( $query_args['type'], $query_args['status'] ) );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare objects query.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
$args = array();
|
||||
$args['order'] = $request['order'];
|
||||
$args['orderby'] = $request['orderby'];
|
||||
$args['per_page'] = $request['per_page'];
|
||||
$args['page'] = $request['page'];
|
||||
$args['type'] = isset( $request['type'] ) ? $request['type'] : array();
|
||||
$args['status'] = isset( $request['status'] ) ? $request['status'] : array();
|
||||
|
||||
if ( 'date' === $args['orderby'] ) {
|
||||
$args['orderby'] = 'date_created';
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the query arguments for a request.
|
||||
*
|
||||
* Enables adding extra arguments or setting defaults for a post
|
||||
* collection request.
|
||||
*
|
||||
* @param array $args Key value array of query var to query value.
|
||||
* @param WP_REST_Request $request The request used.
|
||||
*/
|
||||
$args = apply_filters( 'woocommerce_rest_admin_notes_object_query', $args, $request );
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to read a single note.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_item_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a given request has permission to read notes.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single note.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Request|WP_Error
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$note = WC_Admin_Notes::get_note( $request->get_param( 'id' ) );
|
||||
|
||||
if ( ! $note ) {
|
||||
return new WP_Error(
|
||||
'woocommerce_admin_notes_invalid_id',
|
||||
__( 'Sorry, there is no resouce with that ID.', 'woocommerce-admin' ),
|
||||
array( 'status' => 404 )
|
||||
);
|
||||
}
|
||||
|
||||
// @todo Status is the only field that can be updated at the moment. We should also implement the "date reminder" setting.
|
||||
$note_changed = false;
|
||||
if ( ! is_null( $request->get_param( 'status' ) ) ) {
|
||||
$note->set_status( $request->get_param( 'status' ) );
|
||||
$note_changed = true;
|
||||
}
|
||||
|
||||
if ( ! is_null( $request->get_param( 'date_reminder' ) ) ) {
|
||||
$note->set_date_reminder( $request->get_param( 'date_reminder' ) );
|
||||
$note_changed = true;
|
||||
}
|
||||
|
||||
if ( $note_changed ) {
|
||||
$note->save();
|
||||
}
|
||||
return $this->get_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the current user has access to WRITE the settings APIs.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
* @return WP_Error|bool
|
||||
*/
|
||||
public function update_items_permissions_check( $request ) {
|
||||
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
|
||||
return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a path or query for serialization to the client.
|
||||
*
|
||||
* @param string $query The query, path, or URL to transform.
|
||||
* @return string A fully formed URL.
|
||||
*/
|
||||
public function prepare_query_for_response( $query ) {
|
||||
if ( 'https://' === substr( $query, 0, 8 ) ) {
|
||||
return $query;
|
||||
}
|
||||
if ( 'http://' === substr( $query, 0, 7 ) ) {
|
||||
return $query;
|
||||
}
|
||||
if ( '?' === substr( $query, 0, 1 ) ) {
|
||||
return admin_url( 'admin.php' . $query );
|
||||
}
|
||||
|
||||
return admin_url( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a note object for serialization.
|
||||
*
|
||||
* @param array $data Note data.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response $response Response data.
|
||||
*/
|
||||
public function prepare_item_for_response( $data, $request ) {
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data['date_created_gmt'] = wc_rest_prepare_date_response( $data['date_created'] );
|
||||
$data['date_created'] = wc_rest_prepare_date_response( $data['date_created'], false );
|
||||
$data['date_reminder_gmt'] = wc_rest_prepare_date_response( $data['date_reminder'] );
|
||||
$data['date_reminder'] = wc_rest_prepare_date_response( $data['date_reminder'], false );
|
||||
$data['title'] = stripslashes( $data['title'] );
|
||||
$data['content'] = stripslashes( $data['content'] );
|
||||
$data['is_snoozable'] = (bool) $data['is_snoozable'];
|
||||
foreach ( (array) $data['actions'] as $key => $value ) {
|
||||
$data['actions'][ $key ]->label = stripslashes( $data['actions'][ $key ]->label );
|
||||
$data['actions'][ $key ]->url = $this->prepare_query_for_response( $data['actions'][ $key ]->query );
|
||||
$data['actions'][ $key ]->status = stripslashes( $data['actions'][ $key ]->status );
|
||||
}
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
// Wrap the data in a response object.
|
||||
$response = rest_ensure_response( $data );
|
||||
$response->add_links(
|
||||
array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $data['id'] ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
)
|
||||
);
|
||||
/**
|
||||
* Filter a note returned from the API.
|
||||
*
|
||||
* Allows modification of the note data right before it is returned.
|
||||
*
|
||||
* @param WP_REST_Response $response The response object.
|
||||
* @param array $data The original note.
|
||||
* @param WP_REST_Request $request Request used to generate the response.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_rest_prepare_admin_note', $response, $data, $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = array();
|
||||
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
|
||||
$params['order'] = array(
|
||||
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'default' => 'desc',
|
||||
'enum' => array( 'asc', 'desc' ),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['orderby'] = array(
|
||||
'description' => __( 'Sort collection by object attribute.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'default' => 'date',
|
||||
'enum' => array(
|
||||
'note_id',
|
||||
'date',
|
||||
'type',
|
||||
'title',
|
||||
'status',
|
||||
),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['page'] = array(
|
||||
'description' => __( 'Current page of the collection.', 'woocommerce-admin' ),
|
||||
'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-admin' ),
|
||||
'type' => 'integer',
|
||||
'default' => 10,
|
||||
'minimum' => 1,
|
||||
'maximum' => 100,
|
||||
'sanitize_callback' => 'absint',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['type'] = array(
|
||||
'description' => __( 'Type of note.', 'woocommerce-admin' ),
|
||||
'type' => 'array',
|
||||
'sanitize_callback' => 'wp_parse_slug_list',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'items' => array(
|
||||
'enum' => WC_Admin_Note::get_allowed_types(),
|
||||
'type' => 'string',
|
||||
),
|
||||
);
|
||||
$params['status'] = array(
|
||||
'description' => __( 'Status of note.', 'woocommerce-admin' ),
|
||||
'type' => 'array',
|
||||
'sanitize_callback' => 'wp_parse_slug_list',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
'items' => array(
|
||||
'enum' => WC_Admin_Note::get_allowed_statuses(),
|
||||
'type' => 'string',
|
||||
),
|
||||
);
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the note's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'note',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'ID of the note record.', 'woocommerce-admin' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => __( 'Name of the note.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'type' => array(
|
||||
'description' => __( 'The type of the note (e.g. error, warning, etc.).', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'locale' => array(
|
||||
'description' => __( 'Locale used for the note title and content.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'title' => array(
|
||||
'description' => __( 'Title of the note.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'content' => array(
|
||||
'description' => __( 'Content of the note.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'icon' => array(
|
||||
'description' => __( 'Icon (gridicon) for the note.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'content_data' => array(
|
||||
'description' => __( 'Content data for the note. JSON string. Available for re-localization.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'status' => array(
|
||||
'description' => __( 'The status of the note (e.g. unactioned, actioned).', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'source' => array(
|
||||
'description' => __( 'Source of the note.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_created' => array(
|
||||
'description' => __( 'Date the note was created.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_created_gmt' => array(
|
||||
'description' => __( 'Date the note was created (GMT).', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'date_reminder' => array(
|
||||
'description' => __( 'Date after which the user should be reminded of the note, if any.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true, // @todo Allow date_reminder to be updated.
|
||||
),
|
||||
'date_reminder_gmt' => array(
|
||||
'description' => __( 'Date after which the user should be reminded of the note, if any (GMT).', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'is_snoozable' => array(
|
||||
'description' => __( 'Whether or a user can request to be reminded about the note.', 'woocommerce-admin' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'actions' => array(
|
||||
'description' => __( 'An array of actions, if any, for the note.', 'woocommerce-admin' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Coupons Controller
|
||||
*
|
||||
* Handles requests to /coupons/*
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Coupons controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Coupons_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Coupons_Controller extends WC_REST_Coupons_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
$params['search'] = array(
|
||||
'description' => __( 'Limit results to coupons with codes matching a given string.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
return $params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add coupon code searching to the WC API.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
$args = parent::prepare_objects_query( $request );
|
||||
|
||||
if ( ! empty( $request['search'] ) ) {
|
||||
$args['search'] = $request['search'];
|
||||
$args['s'] = false;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of posts and add the code search option to WP_Query.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
add_filter( 'posts_where', array( __CLASS__, 'add_wp_query_search_code_filter' ), 10, 2 );
|
||||
$response = parent::get_items( $request );
|
||||
remove_filter( 'posts_where', array( __CLASS__, 'add_wp_query_search_code_filter' ), 10 );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add code searching to the WP Query
|
||||
*
|
||||
* @param string $where Where clause used to search posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_wp_query_search_code_filter( $where, $wp_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$search = $wp_query->get( 'search' );
|
||||
if ( $search ) {
|
||||
$search = $wpdb->esc_like( $search );
|
||||
$search = "'%" . $search . "%'";
|
||||
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE ' . $search;
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Customers Controller
|
||||
*
|
||||
* Handles requests to /customers/*
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Customers controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_Admin_REST_Reports_Customers_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Customers_Controller extends WC_Admin_REST_Reports_Customers_Controller {
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'customers';
|
||||
|
||||
/**
|
||||
* Maps query arguments from the REST request.
|
||||
*
|
||||
* @param array $request Request array.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_reports_query( $request ) {
|
||||
$args = parent::prepare_reports_query( $request );
|
||||
$args['customers'] = $request['include'];
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
$params['include'] = $params['customers'];
|
||||
unset( $params['customers'] );
|
||||
return $params;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Orders Controller
|
||||
*
|
||||
* Handles requests to /orders/*
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Orders controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Orders_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Orders_Controller extends WC_REST_Orders_Controller {
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
// This needs to remain a string to support extensions that filter Order Number.
|
||||
$params['number'] = array(
|
||||
'description' => __( 'Limit result set to orders matching part of an order number.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare objects query.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
global $wpdb;
|
||||
$args = parent::prepare_objects_query( $request );
|
||||
|
||||
// Search by partial order number.
|
||||
if ( ! empty( $request['number'] ) ) {
|
||||
$partial_number = trim( $request['number'] );
|
||||
$limit = intval( $args['posts_per_page'] );
|
||||
$order_ids = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID
|
||||
FROM {$wpdb->prefix}posts
|
||||
WHERE post_type = 'shop_order'
|
||||
AND ID LIKE %s
|
||||
LIMIT %d",
|
||||
$wpdb->esc_like( absint( $partial_number ) ) . '%',
|
||||
$limit
|
||||
)
|
||||
);
|
||||
|
||||
// Force WP_Query return empty if don't found any order.
|
||||
$order_ids = empty( $order_ids ) ? array( 0 ) : $order_ids;
|
||||
$args['post__in'] = $order_ids;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Product Categories Controller
|
||||
*
|
||||
* Handles requests to /products/categories.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Product categories controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Product_Categories_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Product_Categories_Controller extends WC_REST_Product_Categories_Controller {
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Product Reviews Controller
|
||||
*
|
||||
* Handles requests to /products/reviews.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Product reviews controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Product_Reviews_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Product_Reviews_Controller extends WC_REST_Product_Reviews_Controller {
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Prepare links for the request.
|
||||
*
|
||||
* @param WP_Comment $review Product review object.
|
||||
* @return array Links for the given product review.
|
||||
*/
|
||||
protected function prepare_links( $review ) {
|
||||
$links = array(
|
||||
'self' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $review->comment_ID ) ),
|
||||
),
|
||||
'collection' => array(
|
||||
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
||||
),
|
||||
);
|
||||
if ( 0 !== (int) $review->comment_post_ID ) {
|
||||
$links['up'] = array(
|
||||
'href' => rest_url( sprintf( '/%s/products/%d', $this->namespace, $review->comment_post_ID ) ),
|
||||
'embeddable' => true,
|
||||
);
|
||||
}
|
||||
if ( 0 !== (int) $review->user_id ) {
|
||||
$links['reviewer'] = array(
|
||||
'href' => rest_url( 'wp/v2/users/' . $review->user_id ),
|
||||
'embeddable' => true,
|
||||
);
|
||||
}
|
||||
return $links;
|
||||
}
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Products Controller
|
||||
*
|
||||
* Handles requests to /products/*
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Products controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Products_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Products_Controller extends WC_REST_Products_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Adds properties that can be embed via ?_embed=1.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = parent::get_item_schema();
|
||||
|
||||
$properties_to_embed = array(
|
||||
'id',
|
||||
'name',
|
||||
'slug',
|
||||
'permalink',
|
||||
'images',
|
||||
'description',
|
||||
'short_description',
|
||||
);
|
||||
|
||||
foreach ( $properties_to_embed as $property ) {
|
||||
$schema['properties'][ $property ]['context'][] = 'embed';
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
$params['low_in_stock'] = array(
|
||||
'description' => __( 'Limit result set to products that are low or out of stock.', 'woocommerce-admin' ),
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'sanitize_callback' => 'wc_string_to_bool',
|
||||
);
|
||||
$params['search'] = array(
|
||||
'description' => __( 'Search by similar product name or sku.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
return $params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add product name and sku filtering to the WC API.
|
||||
*
|
||||
* @param WP_REST_Request $request Request data.
|
||||
* @return array
|
||||
*/
|
||||
protected function prepare_objects_query( $request ) {
|
||||
$args = parent::prepare_objects_query( $request );
|
||||
|
||||
if ( ! empty( $request['search'] ) ) {
|
||||
$args['search'] = trim( $request['search'] );
|
||||
unset( $args['s'] );
|
||||
}
|
||||
if ( ! empty( $request['low_in_stock'] ) ) {
|
||||
$args['low_in_stock'] = $request['low_in_stock'];
|
||||
$args['post_type'] = array( 'product', 'product_variation' );
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of posts and add the post title filter option to WP_Query.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
add_filter( 'posts_where', array( __CLASS__, 'add_wp_query_filter' ), 10, 2 );
|
||||
add_filter( 'posts_join', array( __CLASS__, 'add_wp_query_join' ), 10, 2 );
|
||||
add_filter( 'posts_groupby', array( __CLASS__, 'add_wp_query_group_by' ), 10, 2 );
|
||||
$response = parent::get_items( $request );
|
||||
remove_filter( 'posts_where', array( __CLASS__, 'add_wp_query_filter' ), 10 );
|
||||
remove_filter( 'posts_join', array( __CLASS__, 'add_wp_query_join' ), 10 );
|
||||
remove_filter( 'posts_groupby', array( __CLASS__, 'add_wp_query_group_by' ), 10 );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add in conditional search filters for products.
|
||||
*
|
||||
* @param string $where Where clause used to search posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_wp_query_filter( $where, $wp_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$search = $wp_query->get( 'search' );
|
||||
if ( $search ) {
|
||||
$search = $wpdb->esc_like( $search );
|
||||
$search = "'%" . $search . "%'";
|
||||
$where .= " AND ({$wpdb->posts}.post_title LIKE {$search}";
|
||||
$where .= wc_product_sku_enabled() ? ' OR ps_post_meta.meta_key = "_sku" AND ps_post_meta.meta_value LIKE ' . $search . ')' : ')';
|
||||
}
|
||||
|
||||
if ( $wp_query->get( 'low_in_stock' ) ) {
|
||||
$low_stock_amount = absint( max( get_option( 'woocommerce_notify_low_stock_amount' ), 1 ) );
|
||||
$where .= " AND lis_postmeta2.meta_key = '_manage_stock'
|
||||
AND lis_postmeta2.meta_value = 'yes'
|
||||
AND lis_postmeta.meta_key = '_stock'
|
||||
AND lis_postmeta.meta_value IS NOT NULL
|
||||
AND lis_postmeta3.meta_key = '_low_stock_amount'
|
||||
AND (
|
||||
lis_postmeta3.meta_value > ''
|
||||
AND CAST(lis_postmeta.meta_value AS SIGNED) <= CAST(lis_postmeta3.meta_value AS SIGNED)
|
||||
OR lis_postmeta3.meta_value <= ''
|
||||
AND CAST(lis_postmeta.meta_value AS SIGNED) <= {$low_stock_amount}
|
||||
)";
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join posts meta tables when product search or low stock query is present.
|
||||
*
|
||||
* @param string $join Join clause used to search posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_wp_query_join( $join, $wp_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$search = $wp_query->get( 'search' );
|
||||
if ( $search && wc_product_sku_enabled() ) {
|
||||
$join .= " INNER JOIN {$wpdb->postmeta} AS ps_post_meta ON ps_post_meta.post_id = {$wpdb->posts}.ID";
|
||||
}
|
||||
|
||||
if ( $wp_query->get( 'low_in_stock' ) ) {
|
||||
$join .= " INNER JOIN {$wpdb->postmeta} AS lis_postmeta ON {$wpdb->posts}.ID = lis_postmeta.post_id
|
||||
INNER JOIN {$wpdb->postmeta} AS lis_postmeta2 ON {$wpdb->posts}.ID = lis_postmeta2.post_id
|
||||
INNER JOIN {$wpdb->postmeta} AS lis_postmeta3 ON {$wpdb->posts}.ID = lis_postmeta3.post_id";
|
||||
}
|
||||
|
||||
return $join;
|
||||
}
|
||||
|
||||
/**
|
||||
* Group by post ID to prevent duplicates.
|
||||
*
|
||||
* @param string $groupby Group by clause used to organize posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_wp_query_group_by( $groupby, $wp_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$search = $wp_query->get( 'search' );
|
||||
$low_in_stock = $wp_query->get( 'low_in_stock' );
|
||||
if ( empty( $groupby ) && ( $search || $low_in_stock ) ) {
|
||||
$groupby = $wpdb->posts . '.ID';
|
||||
}
|
||||
return $groupby;
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Taxes Controller
|
||||
*
|
||||
* Handles requests to /taxes/*
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Taxes controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Taxes_Controller
|
||||
*/
|
||||
class WC_Admin_REST_Taxes_Controller extends WC_REST_Taxes_Controller {
|
||||
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v4';
|
||||
|
||||
/**
|
||||
* Get the query params for collections.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_collection_params() {
|
||||
$params = parent::get_collection_params();
|
||||
$params['code'] = array(
|
||||
'description' => __( 'Search by similar tax code.', 'woocommerce-admin' ),
|
||||
'type' => 'string',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
$params['include'] = array(
|
||||
'description' => __( 'Limit result set to items that have the specified rate ID(s) assigned.', 'woocommerce-admin' ),
|
||||
'type' => 'array',
|
||||
'items' => array(
|
||||
'type' => 'integer',
|
||||
),
|
||||
'default' => array(),
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
);
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all taxes and allow filtering by tax code.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|WP_REST_Response
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
global $wpdb;
|
||||
|
||||
$prepared_args = array();
|
||||
$prepared_args['order'] = $request['order'];
|
||||
$prepared_args['number'] = $request['per_page'];
|
||||
if ( ! empty( $request['offset'] ) ) {
|
||||
$prepared_args['offset'] = $request['offset'];
|
||||
} else {
|
||||
$prepared_args['offset'] = ( $request['page'] - 1 ) * $prepared_args['number'];
|
||||
}
|
||||
$orderby_possibles = array(
|
||||
'id' => 'tax_rate_id',
|
||||
'order' => 'tax_rate_order',
|
||||
);
|
||||
$prepared_args['orderby'] = $orderby_possibles[ $request['orderby'] ];
|
||||
$prepared_args['class'] = $request['class'];
|
||||
$prepared_args['code'] = $request['code'];
|
||||
$prepared_args['include'] = $request['include'];
|
||||
|
||||
/**
|
||||
* Filter arguments, before passing to $wpdb->get_results(), when querying taxes via the REST API.
|
||||
*
|
||||
* @param array $prepared_args Array of arguments for $wpdb->get_results().
|
||||
* @param WP_REST_Request $request The current request.
|
||||
*/
|
||||
$prepared_args = apply_filters( 'woocommerce_rest_tax_query', $prepared_args, $request );
|
||||
|
||||
$query = "
|
||||
SELECT *
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
WHERE 1 = 1
|
||||
";
|
||||
|
||||
// Filter by tax class.
|
||||
if ( ! empty( $prepared_args['class'] ) ) {
|
||||
$class = 'standard' !== $prepared_args['class'] ? sanitize_title( $prepared_args['class'] ) : '';
|
||||
$query .= " AND tax_rate_class = '$class'";
|
||||
}
|
||||
|
||||
// Filter by tax code.
|
||||
$tax_code_search = $prepared_args['code'];
|
||||
if ( $tax_code_search ) {
|
||||
$tax_code_search = $wpdb->esc_like( $tax_code_search );
|
||||
$tax_code_search = ' \'%' . $tax_code_search . '%\'';
|
||||
$query .= ' AND CONCAT_WS( "-", NULLIF(tax_rate_country, ""), NULLIF(tax_rate_state, ""), NULLIF(tax_rate_name, ""), NULLIF(tax_rate_priority, "") ) LIKE ' . $tax_code_search;
|
||||
}
|
||||
|
||||
// Filter by included tax rate IDs.
|
||||
$included_taxes = $prepared_args['include'];
|
||||
if ( ! empty( $included_taxes ) ) {
|
||||
$included_taxes = implode( ',', $prepared_args['include'] );
|
||||
$query .= " AND tax_rate_id IN ({$included_taxes})";
|
||||
}
|
||||
|
||||
// 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 ); // @codingStandardsIgnoreLine.
|
||||
|
||||
$taxes = array();
|
||||
foreach ( $results as $tax ) {
|
||||
$data = $this->prepare_item_for_response( $tax, $request );
|
||||
$taxes[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
$response = rest_ensure_response( $taxes );
|
||||
|
||||
// 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 );
|
||||
|
||||
// Query only for ids.
|
||||
$wpdb->get_results( str_replace( 'SELECT *', 'SELECT tax_rate_id', $query ) ); // @codingStandardsIgnoreLine.
|
||||
|
||||
// Calculate totals.
|
||||
$total_taxes = (int) $wpdb->num_rows;
|
||||
$response->header( 'X-WP-Total', (int) $total_taxes );
|
||||
$max_pages = ceil( $total_taxes / $per_page );
|
||||
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
||||
|
||||
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
||||
if ( $page > 1 ) {
|
||||
$prev_page = $page - 1;
|
||||
if ( $prev_page > $max_pages ) {
|
||||
$prev_page = $max_pages;
|
||||
}
|
||||
$prev_link = add_query_arg( 'page', $prev_page, $base );
|
||||
$response->link_header( 'prev', $prev_link );
|
||||
}
|
||||
if ( $max_pages > $page ) {
|
||||
$next_page = $page + 1;
|
||||
$next_link = add_query_arg( 'page', $next_page, $base );
|
||||
$response->link_header( 'next', $next_link );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue