rest_validate_value_from_schema( mixed $value, array $args, string $param = '' )

Validate a value based on a schema.


Parameters Parameters

$value

(mixed) (Required) The value to validate.

$args

(array) (Required) Schema array to use for validation.

$param

(string) (Optional) The parameter name, used in error messages.

Default value: ''


Top ↑

Return Return

(true|WP_Error)


Top ↑

Source Source

File: wp-includes/rest-api.php

function rest_validate_value_from_schema( $value, $args, $param = '' ) {
	$allowed_types = array( 'array', 'object', 'string', 'number', 'integer', 'boolean', 'null' );

	if ( ! isset( $args['type'] ) ) {
		/* translators: 1. Parameter */
		_doing_it_wrong( __FUNCTION__, sprintf( __( 'The "type" schema keyword for %s is required.' ), $param ), '5.5.0' );
	}

	if ( is_array( $args['type'] ) ) {
		$best_type = rest_handle_multi_type_schema( $value, $args, $param );

		if ( ! $best_type ) {
			/* translators: 1: Parameter, 2: List of types. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, implode( ',', $args['type'] ) ) );
		}

		$args['type'] = $best_type;
	}

	if ( ! in_array( $args['type'], $allowed_types, true ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			/* translators: 1. Parameter 2. The list of allowed types. */
			wp_sprintf( __( 'The "type" schema keyword for %1$s can only be one of the built-in types: %2$l.' ), $param, $allowed_types ),
			'5.5.0'
		);
	}

	if ( 'array' === $args['type'] ) {
		if ( ! rest_is_array( $value ) ) {
			/* translators: 1: Parameter, 2: Type name. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'array' ) );
		}

		$value = rest_sanitize_array( $value );

		if ( isset( $args['items'] ) ) {
			foreach ( $value as $index => $v ) {
				$is_valid = rest_validate_value_from_schema( $v, $args['items'], $param . '[' . $index . ']' );
				if ( is_wp_error( $is_valid ) ) {
					return $is_valid;
				}
			}
		}

		if ( isset( $args['minItems'] ) && count( $value ) < $args['minItems'] ) {
			/* translators: 1: Parameter, 2: Number. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must contain at least %2$s items.' ), $param, number_format_i18n( $args['minItems'] ) ) );
		}

		if ( isset( $args['maxItems'] ) && count( $value ) > $args['maxItems'] ) {
			/* translators: 1: Parameter, 2: Number. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must contain at most %2$s items.' ), $param, number_format_i18n( $args['maxItems'] ) ) );
		}

		if ( ! empty( $args['uniqueItems'] ) && ! rest_validate_array_contains_unique_items( $value ) ) {
			/* translators: 1: Parameter */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s has duplicate items.' ), $param ) );
		}
	}

	if ( 'object' === $args['type'] ) {
		if ( ! rest_is_object( $value ) ) {
			/* translators: 1: Parameter, 2: Type name. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'object' ) );
		}

		$value = rest_sanitize_object( $value );

		if ( isset( $args['required'] ) && is_array( $args['required'] ) ) { // schema version 4
			foreach ( $args['required'] as $name ) {
				if ( ! array_key_exists( $name, $value ) ) {
					/* translators: 1: Property of an object, 2: Parameter. */
					return new WP_Error( 'rest_property_required', sprintf( __( '%1$s is a required property of %2$s.' ), $name, $param ) );
				}
			}
		} elseif ( isset( $args['properties'] ) ) { // schema version 3
			foreach ( $args['properties'] as $name => $property ) {
				if ( isset( $property['required'] ) && true === $property['required'] && ! array_key_exists( $name, $value ) ) {
					/* translators: 1: Property of an object, 2: Parameter. */
					return new WP_Error( 'rest_property_required', sprintf( __( '%1$s is a required property of %2$s.' ), $name, $param ) );
				}
			}
		}

		foreach ( $value as $property => $v ) {
			if ( isset( $args['properties'][ $property ] ) ) {
				$is_valid = rest_validate_value_from_schema( $v, $args['properties'][ $property ], $param . '[' . $property . ']' );
				if ( is_wp_error( $is_valid ) ) {
					return $is_valid;
				}
			} elseif ( isset( $args['additionalProperties'] ) ) {
				if ( false === $args['additionalProperties'] ) {
					/* translators: %s: Property of an object. */
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not a valid property of Object.' ), $property ) );
				}

				if ( is_array( $args['additionalProperties'] ) ) {
					$is_valid = rest_validate_value_from_schema( $v, $args['additionalProperties'], $param . '[' . $property . ']' );
					if ( is_wp_error( $is_valid ) ) {
						return $is_valid;
					}
				}
			}
		}
	}

	if ( 'null' === $args['type'] ) {
		if ( null !== $value ) {
			/* translators: 1: Parameter, 2: Type name. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ) );
		}

		return true;
	}

	if ( ! empty( $args['enum'] ) ) {
		if ( ! in_array( $value, $args['enum'], true ) ) {
			/* translators: 1: Parameter, 2: List of valid values. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) );
		}
	}

	if ( in_array( $args['type'], array( 'integer', 'number' ), true ) && ! is_numeric( $value ) ) {
		/* translators: 1: Parameter, 2: Type name. */
		return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) );
	}

	if ( 'integer' === $args['type'] && ! rest_is_integer( $value ) ) {
		/* translators: 1: Parameter, 2: Type name. */
		return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'integer' ) );
	}

	if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) {
		/* translators: 1: Parameter, 2: Type name. */
		return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'boolean' ) );
	}

	if ( 'string' === $args['type'] ) {
		if ( ! is_string( $value ) ) {
			/* translators: 1: Parameter, 2: Type name. */
			return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'string' ) );
		}

		if ( isset( $args['minLength'] ) && mb_strlen( $value ) < $args['minLength'] ) {
			return new WP_Error(
				'rest_invalid_param',
				sprintf(
					/* translators: 1: Parameter, 2: Number of characters. */
					_n( '%1$s must be at least %2$s character long.', '%1$s must be at least %2$s characters long.', $args['minLength'] ),
					$param,
					number_format_i18n( $args['minLength'] )
				)
			);
		}

		if ( isset( $args['maxLength'] ) && mb_strlen( $value ) > $args['maxLength'] ) {
			return new WP_Error(
				'rest_invalid_param',
				sprintf(
					/* translators: 1: Parameter, 2: Number of characters. */
					_n( '%1$s must be at most %2$s character long.', '%1$s must be at most %2$s characters long.', $args['maxLength'] ),
					$param,
					number_format_i18n( $args['maxLength'] )
				)
			);
		}

		if ( isset( $args['pattern'] ) ) {
			$pattern = str_replace( '#', '\\#', $args['pattern'] );
			if ( ! preg_match( '#' . $pattern . '#u', $value ) ) {
				/* translators: 1: Parameter, 2: Pattern. */
				return new WP_Error( 'rest_invalid_pattern', sprintf( __( '%1$s does not match pattern %2$s.' ), $param, $args['pattern'] ) );
			}
		}
	}

	// The "format" keyword should only be applied to strings. However, for backward compatibility,
	// we allow the "format" keyword if the type keyword was not specified, or was set to an invalid value.
	if ( isset( $args['format'] )
		&& ( ! isset( $args['type'] ) || 'string' === $args['type'] || ! in_array( $args['type'], $allowed_types, true ) )
	) {
		switch ( $args['format'] ) {
			case 'hex-color':
				if ( ! rest_parse_hex_color( $value ) ) {
					return new WP_Error( 'rest_invalid_hex_color', __( 'Invalid hex color.' ) );
				}
				break;

			case 'date-time':
				if ( ! rest_parse_date( $value ) ) {
					return new WP_Error( 'rest_invalid_date', __( 'Invalid date.' ) );
				}
				break;

			case 'email':
				if ( ! is_email( $value ) ) {
					return new WP_Error( 'rest_invalid_email', __( 'Invalid email address.' ) );
				}
				break;
			case 'ip':
				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.' ), $param ) );
				}
				break;
			case 'uuid':
				if ( ! wp_is_uuid( $value ) ) {
					/* translators: %s is the name of a JSON field expecting a valid uuid. */
					return new WP_Error( 'rest_invalid_uuid', sprintf( __( '%s is not a valid UUID.' ), $param ) );
				}
				break;
		}
	}

	if ( in_array( $args['type'], array( 'number', 'integer' ), true ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) {
		if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) {
			if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) {
				/* translators: 1: Parameter, 2: Minimum number. */
				return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d' ), $param, $args['minimum'] ) );
			} elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) {
				/* translators: 1: Parameter, 2: Minimum number. */
				return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than or equal to %2$d' ), $param, $args['minimum'] ) );
			}
		} elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) {
			if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) {
				/* translators: 1: Parameter, 2: Maximum number. */
				return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d' ), $param, $args['maximum'] ) );
			} elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) {
				/* translators: 1: Parameter, 2: Maximum number. */
				return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than or equal to %2$d' ), $param, $args['maximum'] ) );
			}
		} elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) {
			if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
				if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) {
					/* translators: 1: Parameter, 2: Minimum number, 3: Maximum number. */
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
				}
			} elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
				if ( $value >= $args['maximum'] || $value < $args['minimum'] ) {
					/* translators: 1: Parameter, 2: Minimum number, 3: Maximum number. */
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
				}
			} elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
				if ( $value > $args['maximum'] || $value <= $args['minimum'] ) {
					/* translators: 1: Parameter, 2: Minimum number, 3: Maximum number. */
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
				}
			} elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
				if ( $value > $args['maximum'] || $value < $args['minimum'] ) {
					/* translators: 1: Parameter, 2: Minimum number, 3: Maximum number. */
					return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
				}
			}
		}
	}

	return true;
}


Top ↑

Changelog Changelog

Changelog
Version Description
5.5.0 Add the "uuid" and "hex-color" formats. Support the "minLength", "maxLength" and "pattern" keywords for strings. Support the "minItems", "maxItems" and "uniqueItems" keywords for arrays. Validate required properties.
5.4.0 Convert an empty string to an empty object.
5.3.0 Support multiple types.
5.2.0 Support validating "additionalProperties" against a schema.
4.9.0 Support the "object" type.
4.7.0 Introduced.

Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.