diff --git a/includes/class-wc-api.php b/includes/class-wc-api.php index 6b3a5b133f7..22b62f69e54 100644 --- a/includes/class-wc-api.php +++ b/includes/class-wc-api.php @@ -14,10 +14,14 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } +/** + * API class. + */ class WC_API extends WC_Legacy_API { /** * Setup class. + * * @since 2.0 */ public function __construct() { @@ -43,7 +47,7 @@ class WC_API extends WC_Legacy_API { * Add new query vars. * * @since 2.0 - * @param array $vars + * @param array $vars Query vars. * @return string[] */ public function add_query_vars( $vars ) { @@ -54,6 +58,7 @@ class WC_API extends WC_Legacy_API { /** * WC API for payment gateway IPNs, etc. + * * @since 2.0 */ public static function add_endpoint() { @@ -70,8 +75,8 @@ class WC_API extends WC_Legacy_API { public function handle_api_requests() { global $wp; - if ( ! empty( $_GET['wc-api'] ) ) { - $wp->query_vars['wc-api'] = $_GET['wc-api']; + if ( ! empty( $_GET['wc-api'] ) ) { // WPCS: input var okay, CSRF ok. + $wp->query_vars['wc-api'] = sanitize_key( wp_unslash( $_GET['wc-api'] ) ); // WPCS: input var okay, CSRF ok. } // wc-api endpoint requests. @@ -84,7 +89,7 @@ class WC_API extends WC_Legacy_API { nocache_headers(); // Clean the API request. - $api_request = strtolower( wc_clean( $wp->query_vars['wc-api'] ) ); + $api_request = $wp->query_vars['wc-api']; // Trigger generic action before request hook. do_action( 'woocommerce_api_request', $api_request ); @@ -103,6 +108,7 @@ class WC_API extends WC_Legacy_API { /** * Init WP REST API. + * * @since 2.6.0 */ private function rest_api_init() { @@ -129,12 +135,6 @@ class WC_API extends WC_Legacy_API { // Authentication. include_once( dirname( __FILE__ ) . '/api/class-wc-rest-authentication.php' ); - // WP-API classes and functions. - include_once( dirname( __FILE__ ) . '/vendor/wp-rest-functions.php' ); - if ( ! class_exists( 'WP_REST_Controller' ) ) { - include_once( dirname( __FILE__ ) . '/vendor/abstract-wp-rest-controller.php' ); - } - // Abstract controllers. include_once( dirname( __FILE__ ) . '/abstracts/abstract-wc-rest-controller.php' ); include_once( dirname( __FILE__ ) . '/abstracts/abstract-wc-rest-posts-controller.php' ); @@ -205,6 +205,7 @@ class WC_API extends WC_Legacy_API { /** * Register REST API routes. + * * @since 2.6.0 */ public function register_rest_routes() { @@ -275,6 +276,7 @@ class WC_API extends WC_Legacy_API { /** * Register WC settings from WP-API to the REST API. + * * @since 3.0.0 */ public function register_wp_admin_settings() { diff --git a/includes/vendor/abstract-wp-rest-controller.php b/includes/vendor/abstract-wp-rest-controller.php deleted file mode 100644 index fa483b20812..00000000000 --- a/includes/vendor/abstract-wp-rest-controller.php +++ /dev/null @@ -1,492 +0,0 @@ - 405 ) ); - } - - /** - * Get a collection of items. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|WP_REST_Response - */ - public function get_items( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Check if a given request has access to get a specific item. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|boolean - */ - public function get_item_permissions_check( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Get one item from the collection. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|WP_REST_Response - */ - public function get_item( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Check if a given request has access to create items. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|boolean - */ - public function create_item_permissions_check( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Create one item from the collection. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|WP_REST_Response - */ - public function create_item( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Check if a given request has access to update a specific item. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|boolean - */ - public function update_item_permissions_check( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Update one item from the collection. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|WP_REST_Response - */ - public function update_item( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Check if a given request has access to delete a specific item. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|boolean - */ - public function delete_item_permissions_check( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Delete one item from the collection. - * - * @param WP_REST_Request $request Full data about the request. - * @return WP_Error|WP_REST_Response - */ - public function delete_item( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Prepare the item for create or update operation. - * - * @param WP_REST_Request $request Request object. - * @return WP_Error|object $prepared_item - */ - protected function prepare_item_for_database( $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Prepare the item for the REST response. - * - * @param mixed $item WordPress representation of the item. - * @param WP_REST_Request $request Request object. - * - * @return WP_Error|WP_REST_Response - */ - public function prepare_item_for_response( $item, $request ) { - return new WP_Error( 'invalid-method', sprintf( __( "Method '%s' not implemented. Must be over-ridden in subclass.", 'woocommerce' ), __METHOD__ ), array( 'status' => 405 ) ); - } - - /** - * Prepare a response for inserting into a collection. - * - * @param WP_REST_Response $response Response object. - * - * @return array|WP_REST_Response - */ - public function prepare_response_for_collection( $response ) { - if ( ! ( $response instanceof WP_REST_Response ) ) { - return $response; - } - - $data = (array) $response->get_data(); - $server = rest_get_server(); - - if ( method_exists( $server, 'get_compact_response_links' ) ) { - $links = call_user_func( array( $server, 'get_compact_response_links' ), $response ); - } else { - $links = call_user_func( array( $server, 'get_response_links' ), $response ); - } - - if ( ! empty( $links ) ) { - $data['_links'] = $links; - } - - return $data; - } - - /** - * Filter a response based on the context defined in the schema. - * - * @param array $data - * @param string $context - * @return array - */ - public function filter_response_by_context( $data, $context ) { - - $schema = $this->get_item_schema(); - foreach ( $data as $key => $value ) { - if ( empty( $schema['properties'][ $key ] ) || empty( $schema['properties'][ $key ]['context'] ) ) { - continue; - } - - if ( ! in_array( $context, $schema['properties'][ $key ]['context'] ) ) { - unset( $data[ $key ] ); - } - - if ( 'object' === $schema['properties'][ $key ]['type'] && ! empty( $schema['properties'][ $key ]['properties'] ) ) { - foreach ( $schema['properties'][ $key ]['properties'] as $attribute => $details ) { - if ( empty( $details['context'] ) ) { - continue; - } - if ( ! in_array( $context, $details['context'] ) ) { - if ( isset( $data[ $key ][ $attribute ] ) ) { - unset( $data[ $key ][ $attribute ] ); - } - } - } - } - } - - return $data; - } - - /** - * Get the item's schema, conforming to JSON Schema. - * - * @return array - */ - public function get_item_schema() { - return $this->add_additional_fields_schema( array() ); - } - - /** - * Get the item's schema for display / public consumption purposes. - * - * @return array - */ - public function get_public_item_schema() { - - $schema = $this->get_item_schema(); - - foreach ( $schema['properties'] as &$property ) { - if ( isset( $property['arg_options'] ) ) { - unset( $property['arg_options'] ); - } - } - - return $schema; - } - - /** - * Get the query params for collections. - * - * @return array - */ - public function get_collection_params() { - return array( - 'context' => $this->get_context_param(), - 'page' => array( - 'description' => __( 'Current page of the collection.', 'woocommerce' ), - 'type' => 'integer', - 'default' => 1, - 'sanitize_callback' => 'absint', - 'validate_callback' => 'rest_validate_request_arg', - 'minimum' => 1, - ), - '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', - ), - 'search' => array( - 'description' => __( 'Limit results to those matching a string.', 'woocommerce' ), - 'type' => 'string', - 'sanitize_callback' => 'sanitize_text_field', - 'validate_callback' => 'rest_validate_request_arg', - ), - ); - } - - /** - * Get the magical context param. - * - * Ensures consistent description between endpoints, and populates enum from schema. - * - * @param array $args - * @return array - */ - public function get_context_param( $args = array() ) { - $param_details = array( - 'description' => __( 'Scope under which the request is made; determines fields present in response.', 'woocommerce' ), - 'type' => 'string', - 'sanitize_callback' => 'sanitize_key', - 'validate_callback' => 'rest_validate_request_arg', - ); - $schema = $this->get_item_schema(); - if ( empty( $schema['properties'] ) ) { - return array_merge( $param_details, $args ); - } - $contexts = array(); - foreach ( $schema['properties'] as $key => $attributes ) { - if ( ! empty( $attributes['context'] ) ) { - $contexts = array_merge( $contexts, $attributes['context'] ); - } - } - if ( ! empty( $contexts ) ) { - $param_details['enum'] = array_unique( $contexts ); - rsort( $param_details['enum'] ); - } - return array_merge( $param_details, $args ); - } - - /** - * Add the values from additional fields to a data object. - * - * @param array $object - * @param WP_REST_Request $request - * @return array modified object with additional fields. - */ - protected function add_additional_fields_to_object( $object, $request ) { - - $additional_fields = $this->get_additional_fields(); - - foreach ( $additional_fields as $field_name => $field_options ) { - - if ( ! $field_options['get_callback'] ) { - continue; - } - - $object[ $field_name ] = call_user_func( $field_options['get_callback'], $object, $field_name, $request, $this->get_object_type() ); - } - - return $object; - } - - /** - * Update the values of additional fields added to a data object. - * - * @param array $object - * @param WP_REST_Request $request - */ - protected function update_additional_fields_for_object( $object, $request ) { - - $additional_fields = $this->get_additional_fields(); - - foreach ( $additional_fields as $field_name => $field_options ) { - - if ( ! $field_options['update_callback'] ) { - continue; - } - - // Don't run the update callbacks if the data wasn't passed in the request. - if ( ! isset( $request[ $field_name ] ) ) { - continue; - } - - call_user_func( $field_options['update_callback'], $request[ $field_name ], $object, $field_name, $request, $this->get_object_type() ); - } - } - - /** - * 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 $schema Schema 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']; - } - - return $schema; - } - - /** - * Get all the registered additional fields for a given object-type. - * - * @param string $object_type - * @return array - */ - protected function get_additional_fields( $object_type = null ) { - - if ( ! $object_type ) { - $object_type = $this->get_object_type(); - } - - if ( ! $object_type ) { - return array(); - } - - global $wp_rest_additional_fields; - - if ( ! $wp_rest_additional_fields || ! isset( $wp_rest_additional_fields[ $object_type ] ) ) { - return array(); - } - - return $wp_rest_additional_fields[ $object_type ]; - } - - /** - * Get the object type this controller is responsible for managing. - * - * @return string - */ - protected function get_object_type() { - $schema = $this->get_item_schema(); - - if ( ! $schema || ! isset( $schema['title'] ) ) { - return null; - } - - return $schema['title']; - } - - /** - * Get an array of endpoint arguments from the item schema for the controller. - * - * @param string $method HTTP method of the request. The arguments - * for `CREATABLE` requests are checked for required - * values and may fall-back to a given default, this - * is not done on `EDITABLE` requests. Default is - * WP_REST_Server::CREATABLE. - * @return array $endpoint_args - */ - public function get_endpoint_args_for_item_schema( $method = WP_REST_Server::CREATABLE ) { - - $schema = $this->get_item_schema(); - $schema_properties = ! empty( $schema['properties'] ) ? $schema['properties'] : array(); - $endpoint_args = array(); - - foreach ( $schema_properties as $field_id => $params ) { - - // Arguments specified as `readonly` are not allowed to be set. - if ( ! empty( $params['readonly'] ) ) { - continue; - } - - $endpoint_args[ $field_id ] = array( - 'validate_callback' => 'rest_validate_request_arg', - 'sanitize_callback' => 'rest_sanitize_request_arg', - ); - - if ( isset( $params['description'] ) ) { - $endpoint_args[ $field_id ]['description'] = $params['description']; - } - - if ( WP_REST_Server::CREATABLE === $method && isset( $params['default'] ) ) { - $endpoint_args[ $field_id ]['default'] = $params['default']; - } - - if ( WP_REST_Server::CREATABLE === $method && ! empty( $params['required'] ) ) { - $endpoint_args[ $field_id ]['required'] = true; - } - - foreach ( array( 'type', 'format', 'enum' ) as $schema_prop ) { - if ( isset( $params[ $schema_prop ] ) ) { - $endpoint_args[ $field_id ][ $schema_prop ] = $params[ $schema_prop ]; - } - } - - // Merge in any options provided by the schema property. - if ( isset( $params['arg_options'] ) ) { - - // Only use required / default from arg_options on CREATABLE endpoints. - if ( WP_REST_Server::CREATABLE !== $method ) { - $params['arg_options'] = array_diff_key( $params['arg_options'], array( 'required' => '', 'default' => '' ) ); - } - - $endpoint_args[ $field_id ] = array_merge( $endpoint_args[ $field_id ], $params['arg_options'] ); - } - } - - return $endpoint_args; - } -} diff --git a/includes/vendor/wp-rest-functions.php b/includes/vendor/wp-rest-functions.php deleted file mode 100644 index a3262f58d3a..00000000000 --- a/includes/vendor/wp-rest-functions.php +++ /dev/null @@ -1,400 +0,0 @@ - $value ) { - $list[ $key ] = sanitize_title( $value ); - } - - return array_unique( $list ); - } -} - -if ( ! function_exists( 'rest_get_server' ) ) { - /** - * Retrieves the current REST server instance. - * - * Instantiates a new instance if none exists already. - * - * @since 4.5.0 - * - * @global WP_REST_Server $wp_rest_server REST server instance. - * - * @return WP_REST_Server REST server instance. - */ - function rest_get_server() { - /* @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; - - if ( empty( $wp_rest_server ) ) { - /** - * Filter the REST Server Class. - * - * This filter allows you to adjust the server class used by the API, using a - * different class to handle requests. - * - * @since 4.4.0 - * - * @param string $class_name The name of the server class. Default 'WP_REST_Server'. - */ - $wp_rest_server_class = apply_filters( 'wp_rest_server_class', 'WP_REST_Server' ); - $wp_rest_server = new $wp_rest_server_class; - - /** - * Fires when preparing to serve an API request. - * - * Endpoint objects should be created and register their hooks on this action rather - * than another action to ensure they're only loaded when needed. - * - * @since 4.4.0 - * - * @param WP_REST_Server $wp_rest_server Server object. - */ - do_action( 'rest_api_init', $wp_rest_server ); - } - - return $wp_rest_server; - } -} - -/** - * plugin.php - */ - -if ( ! function_exists( 'rest_authorization_required_code' ) ) { - /** - * Returns a contextual HTTP error code for authorization failure. - * - * @return integer - */ - function rest_authorization_required_code() { - return is_user_logged_in() ? 403 : 401; - } -} - -if ( ! function_exists( 'register_rest_field' ) ) { - /** - * Registers a new field on an existing WordPress object type. - * - * @global array $wp_rest_additional_fields Holds registered fields, organized - * by object type. - * - * @param string|array $object_type Object(s) the field is being registered - * to, "post"|"term"|"comment" etc. - * @param string $attribute The attribute name. - * @param array $args { - * Optional. An array of arguments used to handle the registered field. - * - * @type string|array|null $get_callback Optional. The callback function used to retrieve the field - * value. Default is 'null', the field will not be returned in - * the response. - * @type string|array|null $update_callback Optional. The callback function used to set and update the - * field value. Default is 'null', the value cannot be set or - * updated. - * @type string|array|null $schema Optional. The callback function used to create the schema for - * this field. Default is 'null', no schema entry will be returned. - * } - */ - function register_rest_field( $object_type, $attribute, $args = array() ) { - $defaults = array( - 'get_callback' => null, - 'update_callback' => null, - 'schema' => null, - ); - - $args = wp_parse_args( $args, $defaults ); - - global $wp_rest_additional_fields; - - $object_types = (array) $object_type; - - foreach ( $object_types as $object_type ) { - $wp_rest_additional_fields[ $object_type ][ $attribute ] = $args; - } - } -} - -if ( ! function_exists( 'register_api_field' ) ) { - /** - * Backwards compatibility shim - * - * @param array|string $object_type - * @param string $attributes - * @param array $args - */ - function register_api_field( $object_type, $attributes, $args = array() ) { - wc_deprecated_function( 'register_api_field', 'WPAPI-2.0', 'register_rest_field' ); - register_rest_field( $object_type, $attributes, $args ); - } -} - -if ( ! function_exists( 'rest_validate_request_arg' ) ) { - /** - * Validate a request argument based on details registered to the route. - * - * @param mixed $value - * @param WP_REST_Request $request - * @param string $param - * @return WP_Error|boolean - */ - function rest_validate_request_arg( $value, $request, $param ) { - - $attributes = $request->get_attributes(); - if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { - return true; - } - $args = $attributes['args'][ $param ]; - - if ( ! empty( $args['enum'] ) ) { - if ( ! in_array( $value, $args['enum'] ) ) { - /* translators: 1: parameter 2: arguments */ - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not one of %2$s', 'woocommerce' ), $param, implode( ', ', $args['enum'] ) ) ); - } - } - - if ( 'integer' === $args['type'] && ! is_numeric( $value ) ) { - /* translators: 1: parameter 2: integer type */ - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'woocommerce' ), $param, 'integer' ) ); - } - - if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) { - /* translators: 1: parameter 2: boolean type */ - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'woocommerce' ), $value, 'boolean' ) ); - } - - if ( 'string' === $args['type'] && ! is_string( $value ) ) { - /* translators: 1: parameter 2: string type */ - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'woocommerce' ), $param, 'string' ) ); - } - - if ( isset( $args['format'] ) ) { - switch ( $args['format'] ) { - case 'date-time' : - if ( ! rest_parse_date( $value ) ) { - return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.', 'woocommerce' ) ); - } - break; - - case 'email' : - if ( ! is_email( $value ) ) { - return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.', 'woocommerce' ) ); - } - break; - case 'ipv4' : - if ( ! rest_is_ip_address( $value ) ) { - /* translators: %s: IP address */ - return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.', 'woocommerce' ), $value ) ); - } - break; - } - } - - if ( in_array( $args['type'], array( 'numeric', 'integer' ) ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) { - if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) { - if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (exclusive)', 'woocommerce' ), $param, $args['minimum'] ) ); - } elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (inclusive)', 'woocommerce' ), $param, $args['minimum'] ) ); - } - } elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) { - if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (exclusive)', 'woocommerce' ), $param, $args['maximum'] ) ); - } elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (inclusive)', 'woocommerce' ), $param, $args['maximum'] ) ); - } - } elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) { - if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { - if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)', 'woocommerce' ), $param, $args['minimum'], $args['maximum'] ) ); - } - } elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { - if ( $value >= $args['maximum'] || $value < $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)', 'woocommerce' ), $param, $args['minimum'], $args['maximum'] ) ); - } - } elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { - if ( $value > $args['maximum'] || $value <= $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)', 'woocommerce' ), $param, $args['minimum'], $args['maximum'] ) ); - } - } elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { - if ( $value > $args['maximum'] || $value < $args['minimum'] ) { - return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)', 'woocommerce' ), $param, $args['minimum'], $args['maximum'] ) ); - } - } - } - } - - return true; - } -} - -if ( ! function_exists( 'rest_sanitize_request_arg' ) ) { - /** - * Sanitize a request argument based on details registered to the route. - * - * @param mixed $value - * @param WP_REST_Request $request - * @param string $param - * @return mixed - */ - function rest_sanitize_request_arg( $value, $request, $param ) { - - $attributes = $request->get_attributes(); - if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { - return $value; - } - $args = $attributes['args'][ $param ]; - - if ( 'integer' === $args['type'] ) { - return (int) $value; - } - - if ( 'boolean' === $args['type'] ) { - return rest_sanitize_boolean( $value ); - } - - if ( isset( $args['format'] ) ) { - switch ( $args['format'] ) { - case 'date-time' : - return sanitize_text_field( $value ); - - case 'email' : - /* - * sanitize_email() validates, which would be unexpected - */ - return sanitize_text_field( $value ); - - case 'uri' : - return esc_url_raw( $value ); - - case 'ipv4' : - return sanitize_text_field( $value ); - } - } - - return $value; - } -} - - -if ( ! function_exists( 'rest_parse_request_arg' ) ) { - /** - * Parse a request argument based on details registered to the route. - * - * Runs a validation check and sanitizes the value, primarily to be used via - * the `sanitize_callback` arguments in the endpoint args registration. - * - * @param mixed $value - * @param WP_REST_Request $request - * @param string $param - * @return mixed - */ - function rest_parse_request_arg( $value, $request, $param ) { - - $is_valid = rest_validate_request_arg( $value, $request, $param ); - - if ( is_wp_error( $is_valid ) ) { - return $is_valid; - } - - $value = rest_sanitize_request_arg( $value, $request, $param ); - - return $value; - } -} - -if ( ! function_exists( 'rest_is_ip_address' ) ) { - /** - * Determines if a IPv4 address is valid. - * - * Does not handle IPv6 addresses. - * - * @param string $ipv4 IP 32-bit address. - * @return string|false The valid IPv4 address, otherwise false. - */ - function rest_is_ip_address( $ipv4 ) { - $pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; - - if ( ! preg_match( $pattern, $ipv4 ) ) { - return false; - } - - return $ipv4; - } -} - -/** - * Changes a boolean-like value into the proper boolean value. - * - * @param bool|string|int $value The value being evaluated. - * @return boolean Returns the proper associated boolean value. - */ -if ( ! function_exists( 'rest_sanitize_boolean' ) ) { - function rest_sanitize_boolean( $value ) { - // String values are translated to `true`; make sure 'false' is false. - if ( is_string( $value ) ) { - $value = strtolower( $value ); - if ( in_array( $value, array( 'false', '0' ), true ) ) { - $value = false; - } - } - - // Everything else will map nicely to boolean. - return (boolean) $value; - } -} - -/** - * Determines if a given value is boolean-like. - * - * @param bool|string $maybe_bool The value being evaluated. - * @return boolean True if a boolean, otherwise false. - */ -if ( ! function_exists( 'rest_is_boolean' ) ) { - function rest_is_boolean( $maybe_bool ) { - if ( is_bool( $maybe_bool ) ) { - return true; - } - - if ( is_string( $maybe_bool ) ) { - $maybe_bool = strtolower( $maybe_bool ); - - $valid_boolean_values = array( - 'false', - 'true', - '0', - '1', - ); - - return in_array( $maybe_bool, $valid_boolean_values, true ); - } - - if ( is_int( $maybe_bool ) ) { - return in_array( $maybe_bool, array( 0, 1 ), true ); - } - - return false; - } -}