WordPress Version: 6.1
/**
* Sanitize a value based on a schema.
*
* @since 4.7.0
* @since 5.5.0 Added the `$param` parameter.
* @since 5.6.0 Support the "anyOf" and "oneOf" keywords.
* @since 5.9.0 Added `text-field` and `textarea-field` formats.
*
* @param mixed $value The value to sanitize.
* @param array $args Schema array to use for sanitization.
* @param string $param 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.
*/
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;
}