322 |
322 |
323 return $data; |
323 return $data; |
324 } |
324 } |
325 |
325 |
326 /** |
326 /** |
|
327 * Checks if the request has specified a JSON content-type. |
|
328 * |
|
329 * @since 5.6.0 |
|
330 * |
|
331 * @return bool True if the content-type header is JSON. |
|
332 */ |
|
333 public function is_json_content_type() { |
|
334 $content_type = $this->get_content_type(); |
|
335 |
|
336 return isset( $content_type['value'] ) && wp_is_json_media_type( $content_type['value'] ); |
|
337 } |
|
338 |
|
339 /** |
327 * Retrieves the parameter priority order. |
340 * Retrieves the parameter priority order. |
328 * |
341 * |
329 * Used when checking parameters in get_param(). |
342 * Used when checking parameters in WP_REST_Request::get_param(). |
330 * |
343 * |
331 * @since 4.4.0 |
344 * @since 4.4.0 |
332 * |
345 * |
333 * @return string[] Array of types to check, in order of priority. |
346 * @return string[] Array of types to check, in order of priority. |
334 */ |
347 */ |
335 protected function get_parameter_order() { |
348 protected function get_parameter_order() { |
336 $order = array(); |
349 $order = array(); |
337 |
350 |
338 $content_type = $this->get_content_type(); |
351 if ( $this->is_json_content_type() ) { |
339 if ( isset( $content_type['value'] ) && 'application/json' === $content_type['value'] ) { |
|
340 $order[] = 'JSON'; |
352 $order[] = 'JSON'; |
341 } |
353 } |
342 |
354 |
343 $this->parse_json_params(); |
355 $this->parse_json_params(); |
344 |
356 |
357 $order[] = 'GET'; |
369 $order[] = 'GET'; |
358 $order[] = 'URL'; |
370 $order[] = 'URL'; |
359 $order[] = 'defaults'; |
371 $order[] = 'defaults'; |
360 |
372 |
361 /** |
373 /** |
362 * Filters the parameter order. |
374 * Filters the parameter priority order for a REST API request. |
363 * |
375 * |
364 * The order affects which parameters are checked when using get_param() and family. |
376 * The order affects which parameters are checked when using WP_REST_Request::get_param() |
365 * This acts similarly to PHP's `request_order` setting. |
377 * and family. This acts similarly to PHP's `request_order` setting. |
366 * |
378 * |
367 * @since 4.4.0 |
379 * @since 4.4.0 |
368 * |
380 * |
369 * @param string[] $order Array of types to check, in order of priority. |
381 * @param string[] $order Array of types to check, in order of priority. |
370 * @param WP_REST_Request $this The request object. |
382 * @param WP_REST_Request $this The request object. |
813 // If there's still no sanitize_callback, nothing to do here. |
824 // If there's still no sanitize_callback, nothing to do here. |
814 if ( empty( $param_args['sanitize_callback'] ) ) { |
825 if ( empty( $param_args['sanitize_callback'] ) ) { |
815 continue; |
826 continue; |
816 } |
827 } |
817 |
828 |
|
829 /** @var mixed|WP_Error $sanitized_value */ |
818 $sanitized_value = call_user_func( $param_args['sanitize_callback'], $value, $this, $key ); |
830 $sanitized_value = call_user_func( $param_args['sanitize_callback'], $value, $this, $key ); |
819 |
831 |
820 if ( is_wp_error( $sanitized_value ) ) { |
832 if ( is_wp_error( $sanitized_value ) ) { |
821 $invalid_params[ $key ] = $sanitized_value->get_error_message(); |
833 $invalid_params[ $key ] = implode( ' ', $sanitized_value->get_error_messages() ); |
|
834 $invalid_details[ $key ] = rest_convert_error_to_response( $sanitized_value )->get_data(); |
822 } else { |
835 } else { |
823 $this->params[ $type ][ $key ] = $sanitized_value; |
836 $this->params[ $type ][ $key ] = $sanitized_value; |
824 } |
837 } |
825 } |
838 } |
826 } |
839 } |
829 return new WP_Error( |
842 return new WP_Error( |
830 'rest_invalid_param', |
843 'rest_invalid_param', |
831 /* translators: %s: List of invalid parameters. */ |
844 /* translators: %s: List of invalid parameters. */ |
832 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), |
845 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), |
833 array( |
846 array( |
834 'status' => 400, |
847 'status' => 400, |
835 'params' => $invalid_params, |
848 'params' => $invalid_params, |
|
849 'details' => $invalid_details, |
836 ) |
850 ) |
837 ); |
851 ); |
838 } |
852 } |
839 |
853 |
840 return true; |
854 return true; |
843 /** |
857 /** |
844 * Checks whether this request is valid according to its attributes. |
858 * Checks whether this request is valid according to its attributes. |
845 * |
859 * |
846 * @since 4.4.0 |
860 * @since 4.4.0 |
847 * |
861 * |
848 * @return bool|WP_Error True if there are no parameters to validate or if all pass validation, |
862 * @return true|WP_Error True if there are no parameters to validate or if all pass validation, |
849 * WP_Error if required parameters are missing. |
863 * WP_Error if required parameters are missing. |
850 */ |
864 */ |
851 public function has_valid_params() { |
865 public function has_valid_params() { |
852 // If JSON data was passed, check for errors. |
866 // If JSON data was passed, check for errors. |
853 $json_error = $this->parse_json_params(); |
867 $json_error = $this->parse_json_params(); |
856 } |
870 } |
857 |
871 |
858 $attributes = $this->get_attributes(); |
872 $attributes = $this->get_attributes(); |
859 $required = array(); |
873 $required = array(); |
860 |
874 |
861 // No arguments set, skip validation. |
875 $args = empty( $attributes['args'] ) ? array() : $attributes['args']; |
862 if ( empty( $attributes['args'] ) ) { |
876 |
863 return true; |
877 foreach ( $args as $key => $arg ) { |
864 } |
|
865 |
|
866 foreach ( $attributes['args'] as $key => $arg ) { |
|
867 |
|
868 $param = $this->get_param( $key ); |
878 $param = $this->get_param( $key ); |
869 if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) { |
879 if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) { |
870 $required[] = $key; |
880 $required[] = $key; |
871 } |
881 } |
872 } |
882 } |
886 /* |
896 /* |
887 * Check the validation callbacks for each registered arg. |
897 * Check the validation callbacks for each registered arg. |
888 * |
898 * |
889 * This is done after required checking as required checking is cheaper. |
899 * This is done after required checking as required checking is cheaper. |
890 */ |
900 */ |
891 $invalid_params = array(); |
901 $invalid_params = array(); |
892 |
902 $invalid_details = array(); |
893 foreach ( $attributes['args'] as $key => $arg ) { |
903 |
|
904 foreach ( $args as $key => $arg ) { |
894 |
905 |
895 $param = $this->get_param( $key ); |
906 $param = $this->get_param( $key ); |
896 |
907 |
897 if ( null !== $param && ! empty( $arg['validate_callback'] ) ) { |
908 if ( null !== $param && ! empty( $arg['validate_callback'] ) ) { |
|
909 /** @var bool|\WP_Error $valid_check */ |
898 $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key ); |
910 $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key ); |
899 |
911 |
900 if ( false === $valid_check ) { |
912 if ( false === $valid_check ) { |
901 $invalid_params[ $key ] = __( 'Invalid parameter.' ); |
913 $invalid_params[ $key ] = __( 'Invalid parameter.' ); |
902 } |
914 } |
903 |
915 |
904 if ( is_wp_error( $valid_check ) ) { |
916 if ( is_wp_error( $valid_check ) ) { |
905 $invalid_params[ $key ] = $valid_check->get_error_message(); |
917 $invalid_params[ $key ] = implode( ' ', $valid_check->get_error_messages() ); |
|
918 $invalid_details[ $key ] = rest_convert_error_to_response( $valid_check )->get_data(); |
906 } |
919 } |
907 } |
920 } |
908 } |
921 } |
909 |
922 |
910 if ( $invalid_params ) { |
923 if ( $invalid_params ) { |
911 return new WP_Error( |
924 return new WP_Error( |
912 'rest_invalid_param', |
925 'rest_invalid_param', |
913 /* translators: %s: List of invalid parameters. */ |
926 /* translators: %s: List of invalid parameters. */ |
914 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), |
927 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), |
915 array( |
928 array( |
916 'status' => 400, |
929 'status' => 400, |
917 'params' => $invalid_params, |
930 'params' => $invalid_params, |
|
931 'details' => $invalid_details, |
918 ) |
932 ) |
919 ); |
933 ); |
920 } |
934 } |
921 |
935 |
|
936 if ( isset( $attributes['validate_callback'] ) ) { |
|
937 $valid_check = call_user_func( $attributes['validate_callback'], $this ); |
|
938 |
|
939 if ( is_wp_error( $valid_check ) ) { |
|
940 return $valid_check; |
|
941 } |
|
942 |
|
943 if ( false === $valid_check ) { |
|
944 // A WP_Error instance is preferred, but false is supported for parity with the per-arg validate_callback. |
|
945 return new WP_Error( 'rest_invalid_params', __( 'Invalid parameters.' ), array( 'status' => 400 ) ); |
|
946 } |
|
947 } |
|
948 |
922 return true; |
949 return true; |
923 |
|
924 } |
950 } |
925 |
951 |
926 /** |
952 /** |
927 * Checks if a parameter is set. |
953 * Checks if a parameter is set. |
928 * |
954 * |
1015 $request = new WP_REST_Request( 'GET', $route ); |
1041 $request = new WP_REST_Request( 'GET', $route ); |
1016 $request->set_query_params( $query_params ); |
1042 $request->set_query_params( $query_params ); |
1017 } |
1043 } |
1018 |
1044 |
1019 /** |
1045 /** |
1020 * Filters the request generated from a URL. |
1046 * Filters the REST API request generated from a URL. |
1021 * |
1047 * |
1022 * @since 4.5.0 |
1048 * @since 4.5.0 |
1023 * |
1049 * |
1024 * @param WP_REST_Request|false $request Generated request object, or false if URL |
1050 * @param WP_REST_Request|false $request Generated request object, or false if URL |
1025 * could not be parsed. |
1051 * could not be parsed. |