函数文档

rest_sanitize_value_from_schema()

💡 云策文档标注

概述

rest_sanitize_value_from_schema() 是一个 WordPress REST API 函数,用于根据 JSON Schema 对值进行安全清理。它处理多种数据类型和模式关键字,确保输入符合预期格式。

关键要点

  • 函数接受三个参数:$value(待清理的值)、$args(模式数组)和 $param(参数名,用于错误消息)。
  • 支持 JSON Schema 关键字如 anyOf、oneOf、type、items、properties、additionalProperties 等,进行递归清理。
  • 返回清理后的值或 WP_Error 实例(如果无法安全清理)。
  • 处理的数据类型包括 array、object、string、number、integer、boolean 和 null,并支持特定格式如 hex-color、date-time、email 等。
  • 自 WordPress 4.7.0 引入,后续版本增加了对 anyOf、oneOf 关键字和 $param 参数的支持。

代码示例

function rest_sanitize_value_from_schema( $value, $args, $param = '' ) {
    // 处理 anyOf 和 oneOf 关键字
    if ( isset( $args['anyOf'] ) ) {
        $matching_schema = rest_find_any_matching_schema( $value, $args, $param );
        if ( is_wp_error( $matching_schema ) ) {
            return $matching_schema;
        }
        $value = rest_sanitize_value_from_schema( $value, $matching_schema, $param );
    }

    // 根据类型进行清理
    if ( 'array' === $args['type'] ) {
        $value = rest_sanitize_array( $value );
        if ( ! empty( $args['items'] ) ) {
            foreach ( $value as $index => $v ) {
                $value[ $index ] = rest_sanitize_value_from_schema( $v, $args['items'], $param . '[' . $index . ']' );
            }
        }
        return $value;
    }

    if ( 'string' === $args['type'] ) {
        return (string) $value;
    }

    // 其他类型处理...
    return $value;
}

注意事项

  • 模式中必须包含 type 关键字,否则会触发 _doing_it_wrong() 警告。
  • type 必须是允许的类型之一(如 array、string 等),否则会发出警告。
  • 对于 array 类型,如果设置了 uniqueItems,会检查重复项并返回 WP_Error。
  • object 类型支持 properties、patternProperties 和 additionalProperties 进行属性清理。
  • 使用递归处理嵌套结构,确保深层数据也得到清理。

📄 原文内容

Sanitize a value based on a schema.

Parameters

$valuemixedrequired
The value to sanitize.
$argsarrayrequired
Schema array to use for sanitization.
$paramstringrequired
The parameter name, used in error messages.

Return

mixed|WP_Error The sanitized value or a WP_Error instance if the value cannot be safely sanitized.

Source

function rest_sanitize_value_from_schema( $value, $args, $param = '' ) {
	if ( isset( $args['anyOf'] ) ) {
		$matching_schema = rest_find_any_matching_schema( $value, $args, $param );
		if ( is_wp_error( $matching_schema ) ) {
			return $matching_schema;
		}

		if ( ! isset( $args['type'] ) ) {
			$args['type'] = $matching_schema['type'];
		}

		$value = rest_sanitize_value_from_schema( $value, $matching_schema, $param );
	}

	if ( isset( $args['oneOf'] ) ) {
		$matching_schema = rest_find_one_matching_schema( $value, $args, $param );
		if ( is_wp_error( $matching_schema ) ) {
			return $matching_schema;
		}

		if ( ! isset( $args['type'] ) ) {
			$args['type'] = $matching_schema['type'];
		}

		$value = rest_sanitize_value_from_schema( $value, $matching_schema, $param );
	}

	$allowed_types = array( 'array', 'object', 'string', 'number', 'integer', 'boolean', 'null' );

	if ( ! isset( $args['type'] ) ) {
		/* translators: %s: 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 ) {
			return null;
		}

		$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'] ) {
		$value = rest_sanitize_array( $value );

		if ( ! empty( $args['items'] ) ) {
			foreach ( $value as $index => $v ) {
				$value[ $index ] = rest_sanitize_value_from_schema( $v, $args['items'], $param . '[' . $index . ']' );
			}
		}

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

		return $value;
	}

	if ( 'object' === $args['type'] ) {
		$value = rest_sanitize_object( $value );

		foreach ( $value as $property => $v ) {
			if ( isset( $args['properties'][ $property ] ) ) {
				$value[ $property ] = rest_sanitize_value_from_schema( $v, $args['properties'][ $property ], $param . '[' . $property . ']' );
				continue;
			}

			$pattern_property_schema = rest_find_matching_pattern_property_schema( $property, $args );
			if ( null !== $pattern_property_schema ) {
				$value[ $property ] = rest_sanitize_value_from_schema( $v, $pattern_property_schema, $param . '[' . $property . ']' );
				continue;
			}

			if ( isset( $args['additionalProperties'] ) ) {
				if ( false === $args['additionalProperties'] ) {
					unset( $value[ $property ] );
				} elseif ( is_array( $args['additionalProperties'] ) ) {
					$value[ $property ] = rest_sanitize_value_from_schema( $v, $args['additionalProperties'], $param . '[' . $property . ']' );
				}
			}
		}

		return $value;
	}

	if ( 'null' === $args['type'] ) {
		return null;
	}

	if ( 'integer' === $args['type'] ) {
		return (int) $value;
	}

	if ( 'number' === $args['type'] ) {
		return (float) $value;
	}

	if ( 'boolean' === $args['type'] ) {
		return rest_sanitize_boolean( $value );
	}

	// This behavior matches rest_validate_value_from_schema().
	if ( isset( $args['format'] )
		&& ( ! isset( $args['type'] ) || 'string' === $args['type'] || ! in_array( $args['type'], $allowed_types, true ) )
	) {
		switch ( $args['format'] ) {
			case 'hex-color':
				return (string) sanitize_hex_color( $value );

			case 'date-time':
				return sanitize_text_field( $value );

			case 'email':
				// sanitize_email() validates, which would be unexpected.
				return sanitize_text_field( $value );

			case 'uri':
				return sanitize_url( $value );

			case 'ip':
				return sanitize_text_field( $value );

			case 'uuid':
				return sanitize_text_field( $value );

			case 'text-field':
				return sanitize_text_field( $value );

			case 'textarea-field':
				return sanitize_textarea_field( $value );
		}
	}

	if ( 'string' === $args['type'] ) {
		return (string) $value;
	}

	return $value;
}

Changelog

Version Description
5.9.0 Added text-field and textarea-field formats.
5.6.0 Support the “anyOf” and “oneOf” keywords.
5.5.0 Added the $param parameter.
4.7.0 Introduced.