wp/wp-includes/rest-api/class-wp-rest-request.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 19 3d72ae0968f4
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
   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.
   656 		}
   668 		}
   657 
   669 
   658 		$this->parsed_json = true;
   670 		$this->parsed_json = true;
   659 
   671 
   660 		// Check that we actually got JSON.
   672 		// Check that we actually got JSON.
   661 		$content_type = $this->get_content_type();
   673 		if ( ! $this->is_json_content_type() ) {
   662 
       
   663 		if ( empty( $content_type ) || 'application/json' !== $content_type['value'] ) {
       
   664 			return true;
   674 			return true;
   665 		}
   675 		}
   666 
   676 
   667 		$body = $this->get_body();
   677 		$body = $this->get_body();
   668 		if ( empty( $body ) ) {
   678 		if ( empty( $body ) ) {
   790 			return true;
   800 			return true;
   791 		}
   801 		}
   792 
   802 
   793 		$order = $this->get_parameter_order();
   803 		$order = $this->get_parameter_order();
   794 
   804 
   795 		$invalid_params = array();
   805 		$invalid_params  = array();
       
   806 		$invalid_details = array();
   796 
   807 
   797 		foreach ( $order as $type ) {
   808 		foreach ( $order as $type ) {
   798 			if ( empty( $this->params[ $type ] ) ) {
   809 			if ( empty( $this->params[ $type ] ) ) {
   799 				continue;
   810 				continue;
   800 			}
   811 			}
   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.