Automattic\WooCommerce\StoreApi\Schemas\V1
AbstractSchema{} │ WC 1.0
AbstractSchema class.
For REST Route Schemas
No Hooks.
Usage
$AbstractSchema = new AbstractSchema(); // use class methods
Methods
- public __construct( ExtendSchema $extend, SchemaController $controller )
- protected force_schema_readonly( $properties )
- public get_endpoint_args_for_item_schema( $method = \WP_REST_Server::CREATABLE )
- protected get_extended_data( $endpoint, ...$passed_args )
- protected get_extended_schema( $endpoint, ...$passed_args )
- public get_item_response( $item )
- protected get_item_responses_from_schema( AbstractSchema $schema, $items )
- public get_item_schema()
- public get_properties()
- public get_public_item_schema()
- protected get_recursive_sanitize_callback( $properties )
- protected get_recursive_schema_property_defaults( $properties )
- protected get_recursive_validate_callback( $properties )
- protected get_store_currency_properties()
- protected prepare_currency_response( $values )
- protected prepare_html_response( $response )
- protected prepare_money_response( $amount, $decimals = 2, $rounding_mode = PHP_ROUND_HALF_UP )
- protected remove_arg_options( $properties )
AbstractSchema{} AbstractSchema{} code WC 9.4.2
abstract class AbstractSchema { /** * The schema item name. * * @var string */ protected $title = 'Schema'; /** * Rest extend instance. * * @var ExtendSchema */ protected $extend; /** * Schema Controller instance. * * @var SchemaController */ protected $controller; /** * Extending key that gets added to endpoint. * * @var string */ const EXTENDING_KEY = 'extensions'; /** * Constructor. * * @param ExtendSchema $extend Rest Extending instance. * @param SchemaController $controller Schema Controller instance. */ public function __construct( ExtendSchema $extend, SchemaController $controller ) { $this->extend = $extend; $this->controller = $controller; } /** * Returns the full item schema. * * @return array */ public function get_item_schema() { return array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => $this->title, 'type' => 'object', 'properties' => $this->get_properties(), ); } /** * Returns the full item response. * * @param mixed $item Item to get response for. * @return array|stdClass */ public function get_item_response( $item ) { return []; } /** * Return schema properties. * * @return array */ abstract public function get_properties(); /** * Recursive removal of arg_options. * * @param array $properties Schema properties. */ protected function remove_arg_options( $properties ) { return array_map( function( $property ) { if ( isset( $property['properties'] ) ) { $property['properties'] = $this->remove_arg_options( $property['properties'] ); } elseif ( isset( $property['items']['properties'] ) ) { $property['items']['properties'] = $this->remove_arg_options( $property['items']['properties'] ); } unset( $property['arg_options'] ); return $property; }, (array) $properties ); } /** * Returns the public schema. * * @return array */ public function get_public_item_schema() { $schema = $this->get_item_schema(); if ( isset( $schema['properties'] ) ) { $schema['properties'] = $this->remove_arg_options( $schema['properties'] ); } return $schema; } /** * Returns extended data for a specific endpoint. * * @param string $endpoint The endpoint identifier. * @param array ...$passed_args An array of arguments to be passed to callbacks. * @return object the data that will get added. */ protected function get_extended_data( $endpoint, ...$passed_args ) { return $this->extend->get_endpoint_data( $endpoint, $passed_args ); } /** * Gets an array of schema defaults recursively. * * @param array $properties Schema property data. * @return array Array of defaults, pulled from arg_options */ protected function get_recursive_schema_property_defaults( $properties ) { $defaults = []; foreach ( $properties as $property_key => $property_value ) { if ( isset( $property_value['arg_options']['default'] ) ) { $defaults[ $property_key ] = $property_value['arg_options']['default']; } elseif ( isset( $property_value['properties'] ) ) { $defaults[ $property_key ] = $this->get_recursive_schema_property_defaults( $property_value['properties'] ); } } return $defaults; } /** * Gets a function that validates recursively. * * @param array $properties Schema property data. * @return function Anonymous validation callback. */ protected function get_recursive_validate_callback( $properties ) { /** * Validate a request argument based on details registered to the route. * * @param mixed $values * @param \WP_REST_Request $request * @param string $param * @return true|\WP_Error */ return function ( $values, $request, $param ) use ( $properties ) { foreach ( $properties as $property_key => $property_value ) { $current_value = isset( $values[ $property_key ] ) ? $values[ $property_key ] : null; $property_type = is_array( $property_value['type'] ) ? $property_value['type'] : [ $property_value['type'] ]; if ( empty( $current_value ) && in_array( 'null', $property_type, true ) ) { // If the value is null and the schema allows null, we can skip validation for children. continue; } if ( isset( $property_value['arg_options']['validate_callback'] ) ) { $callback = $property_value['arg_options']['validate_callback']; $result = is_callable( $callback ) ? $callback( $current_value, $request, $param ) : false; } else { $result = rest_validate_value_from_schema( $current_value, $property_value, $param . ' > ' . $property_key ); } if ( ! $result || is_wp_error( $result ) ) { // If schema validation fails, we return here as we don't need to validate any deeper. return $result; } if ( isset( $property_value['properties'] ) ) { $validate_callback = $this->get_recursive_validate_callback( $property_value['properties'] ); $result = $validate_callback( $current_value, $request, $param . ' > ' . $property_key ); if ( ! $result || is_wp_error( $result ) ) { // If schema validation fails, we return here as we don't need to validate any deeper. return $result; } } } return true; }; } /** * Gets a function that sanitizes recursively. * * @param array $properties Schema property data. * @return function Anonymous validation callback. */ protected function get_recursive_sanitize_callback( $properties ) { /** * Validate a request argument based on details registered to the route. * * @param mixed $values * @param \WP_REST_Request $request * @param string $param * @return true|\WP_Error */ return function ( $values, $request, $param ) use ( $properties ) { $sanitized_values = []; foreach ( $properties as $property_key => $property_value ) { $current_value = isset( $values[ $property_key ] ) ? $values[ $property_key ] : null; if ( isset( $property_value['arg_options']['sanitize_callback'] ) ) { $callback = $property_value['arg_options']['sanitize_callback']; $current_value = is_callable( $callback ) ? $callback( $current_value, $request, $param ) : $current_value; } else { $current_value = rest_sanitize_value_from_schema( $current_value, $property_value, $param . ' > ' . $property_key ); } // If sanitization failed, return the WP_Error object straight away. if ( is_wp_error( $current_value ) ) { return $current_value; } if ( isset( $property_value['properties'] ) ) { $sanitize_callback = $this->get_recursive_sanitize_callback( $property_value['properties'] ); $sanitized_values[ $property_key ] = $sanitize_callback( $current_value, $request, $param . ' > ' . $property_key ); } else { $sanitized_values[ $property_key ] = $current_value; } } return $sanitized_values; }; } /** * Returns extended schema for a specific endpoint. * * @param string $endpoint The endpoint identifer. * @param array ...$passed_args An array of arguments to be passed to callbacks. * @return array the data that will get added. */ protected function get_extended_schema( $endpoint, ...$passed_args ) { $extended_schema = $this->extend->get_endpoint_schema( $endpoint, $passed_args ); $defaults = $this->get_recursive_schema_property_defaults( $extended_schema ); return [ 'type' => 'object', 'context' => [ 'view', 'edit' ], 'arg_options' => [ 'default' => $defaults, 'validate_callback' => $this->get_recursive_validate_callback( $extended_schema ), 'sanitize_callback' => $this->get_recursive_sanitize_callback( $extended_schema ), ], 'properties' => $extended_schema, ]; } /** * Apply a schema get_item_response callback to an array of items and return the result. * * @param AbstractSchema $schema Schema class instance. * @param array $items Array of items. * @return array Array of values from the callback function. */ protected function get_item_responses_from_schema( AbstractSchema $schema, $items ) { $items = array_filter( $items ); if ( empty( $items ) ) { return []; } return array_values( array_map( [ $schema, 'get_item_response' ], $items ) ); } /** * Retrieves an array of endpoint arguments from the item schema for the controller. * * @uses rest_get_endpoint_args_for_schema() * @param string $method Optional. HTTP method of the request. * @return array Endpoint arguments. */ public function get_endpoint_args_for_item_schema( $method = \WP_REST_Server::CREATABLE ) { $schema = $this->get_item_schema(); $endpoint_args = rest_get_endpoint_args_for_schema( $schema, $method ); $endpoint_args = $this->remove_arg_options( $endpoint_args ); return $endpoint_args; } /** * Force all schema properties to be readonly. * * @param array $properties Schema. * @return array Updated schema. */ protected function force_schema_readonly( $properties ) { return array_map( function( $property ) { $property['readonly'] = true; if ( isset( $property['items']['properties'] ) ) { $property['items']['properties'] = $this->force_schema_readonly( $property['items']['properties'] ); } return $property; }, (array) $properties ); } /** * Returns consistent currency schema used across endpoints for prices. * * @return array */ protected function get_store_currency_properties() { return [ 'currency_code' => [ 'description' => __( 'Currency code (in ISO format) for returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], 'readonly' => true, ], 'currency_symbol' => [ 'description' => __( 'Currency symbol for the currency which can be used to format returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], 'readonly' => true, ], 'currency_minor_unit' => [ 'description' => __( 'Currency minor unit (number of digits after the decimal separator) for returned prices.', 'woocommerce' ), 'type' => 'integer', 'context' => [ 'view', 'edit' ], 'readonly' => true, ], 'currency_decimal_separator' => array( 'description' => __( 'Decimal separator for the currency which can be used to format returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'currency_thousand_separator' => array( 'description' => __( 'Thousand separator for the currency which can be used to format returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'currency_prefix' => array( 'description' => __( 'Price prefix for the currency which can be used to format returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), 'currency_suffix' => array( 'description' => __( 'Price prefix for the currency which can be used to format returned prices.', 'woocommerce' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ]; } /** * Adds currency data to an array of monetary values. * * @param array $values Monetary amounts. * @return array Monetary amounts with currency data appended. */ protected function prepare_currency_response( $values ) { return $this->extend->get_formatter( 'currency' )->format( $values ); } /** * Convert monetary values from WooCommerce to string based integers, using * the smallest unit of a currency. * * @param string|float $amount Monetary amount with decimals. * @param int $decimals Number of decimals the amount is formatted with. * @param int $rounding_mode Defaults to the PHP_ROUND_HALF_UP constant. * @return string The new amount. */ protected function prepare_money_response( $amount, $decimals = 2, $rounding_mode = PHP_ROUND_HALF_UP ) { return $this->extend->get_formatter( 'money' )->format( $amount, [ 'decimals' => $decimals, 'rounding_mode' => $rounding_mode, ] ); } /** * Prepares HTML based content, such as post titles and content, for the API response. * * @param string|array $response Data to format. * @return string|array Formatted data. */ protected function prepare_html_response( $response ) { return $this->extend->get_formatter( 'html' )->format( $response ); } }