--- a/wp/wp-includes/rest-api/class-wp-rest-request.php Tue Dec 15 15:52:01 2020 +0100
+++ b/wp/wp-includes/rest-api/class-wp-rest-request.php Wed Sep 21 18:19:35 2022 +0200
@@ -324,9 +324,22 @@
}
/**
+ * Checks if the request has specified a JSON content-type.
+ *
+ * @since 5.6.0
+ *
+ * @return bool True if the content-type header is JSON.
+ */
+ public function is_json_content_type() {
+ $content_type = $this->get_content_type();
+
+ return isset( $content_type['value'] ) && wp_is_json_media_type( $content_type['value'] );
+ }
+
+ /**
* Retrieves the parameter priority order.
*
- * Used when checking parameters in get_param().
+ * Used when checking parameters in WP_REST_Request::get_param().
*
* @since 4.4.0
*
@@ -335,8 +348,7 @@
protected function get_parameter_order() {
$order = array();
- $content_type = $this->get_content_type();
- if ( isset( $content_type['value'] ) && 'application/json' === $content_type['value'] ) {
+ if ( $this->is_json_content_type() ) {
$order[] = 'JSON';
}
@@ -359,10 +371,10 @@
$order[] = 'defaults';
/**
- * Filters the parameter order.
+ * Filters the parameter priority order for a REST API request.
*
- * The order affects which parameters are checked when using get_param() and family.
- * This acts similarly to PHP's `request_order` setting.
+ * The order affects which parameters are checked when using WP_REST_Request::get_param()
+ * and family. This acts similarly to PHP's `request_order` setting.
*
* @since 4.4.0
*
@@ -658,9 +670,7 @@
$this->parsed_json = true;
// Check that we actually got JSON.
- $content_type = $this->get_content_type();
-
- if ( empty( $content_type ) || 'application/json' !== $content_type['value'] ) {
+ if ( ! $this->is_json_content_type() ) {
return true;
}
@@ -792,7 +802,8 @@
$order = $this->get_parameter_order();
- $invalid_params = array();
+ $invalid_params = array();
+ $invalid_details = array();
foreach ( $order as $type ) {
if ( empty( $this->params[ $type ] ) ) {
@@ -815,10 +826,12 @@
continue;
}
+ /** @var mixed|WP_Error $sanitized_value */
$sanitized_value = call_user_func( $param_args['sanitize_callback'], $value, $this, $key );
if ( is_wp_error( $sanitized_value ) ) {
- $invalid_params[ $key ] = $sanitized_value->get_error_message();
+ $invalid_params[ $key ] = implode( ' ', $sanitized_value->get_error_messages() );
+ $invalid_details[ $key ] = rest_convert_error_to_response( $sanitized_value )->get_data();
} else {
$this->params[ $type ][ $key ] = $sanitized_value;
}
@@ -831,8 +844,9 @@
/* translators: %s: List of invalid parameters. */
sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ),
array(
- 'status' => 400,
- 'params' => $invalid_params,
+ 'status' => 400,
+ 'params' => $invalid_params,
+ 'details' => $invalid_details,
)
);
}
@@ -845,7 +859,7 @@
*
* @since 4.4.0
*
- * @return bool|WP_Error True if there are no parameters to validate or if all pass validation,
+ * @return true|WP_Error True if there are no parameters to validate or if all pass validation,
* WP_Error if required parameters are missing.
*/
public function has_valid_params() {
@@ -858,13 +872,9 @@
$attributes = $this->get_attributes();
$required = array();
- // No arguments set, skip validation.
- if ( empty( $attributes['args'] ) ) {
- return true;
- }
+ $args = empty( $attributes['args'] ) ? array() : $attributes['args'];
- foreach ( $attributes['args'] as $key => $arg ) {
-
+ foreach ( $args as $key => $arg ) {
$param = $this->get_param( $key );
if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) {
$required[] = $key;
@@ -888,13 +898,15 @@
*
* This is done after required checking as required checking is cheaper.
*/
- $invalid_params = array();
+ $invalid_params = array();
+ $invalid_details = array();
- foreach ( $attributes['args'] as $key => $arg ) {
+ foreach ( $args as $key => $arg ) {
$param = $this->get_param( $key );
if ( null !== $param && ! empty( $arg['validate_callback'] ) ) {
+ /** @var bool|\WP_Error $valid_check */
$valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key );
if ( false === $valid_check ) {
@@ -902,7 +914,8 @@
}
if ( is_wp_error( $valid_check ) ) {
- $invalid_params[ $key ] = $valid_check->get_error_message();
+ $invalid_params[ $key ] = implode( ' ', $valid_check->get_error_messages() );
+ $invalid_details[ $key ] = rest_convert_error_to_response( $valid_check )->get_data();
}
}
}
@@ -913,14 +926,27 @@
/* translators: %s: List of invalid parameters. */
sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ),
array(
- 'status' => 400,
- 'params' => $invalid_params,
+ 'status' => 400,
+ 'params' => $invalid_params,
+ 'details' => $invalid_details,
)
);
}
+ if ( isset( $attributes['validate_callback'] ) ) {
+ $valid_check = call_user_func( $attributes['validate_callback'], $this );
+
+ if ( is_wp_error( $valid_check ) ) {
+ return $valid_check;
+ }
+
+ if ( false === $valid_check ) {
+ // A WP_Error instance is preferred, but false is supported for parity with the per-arg validate_callback.
+ return new WP_Error( 'rest_invalid_params', __( 'Invalid parameters.' ), array( 'status' => 400 ) );
+ }
+ }
+
return true;
-
}
/**
@@ -1017,7 +1043,7 @@
}
/**
- * Filters the request generated from a URL.
+ * Filters the REST API request generated from a URL.
*
* @since 4.5.0
*